mirror of
https://github.com/facebookarchive/prepack.git
synced 2024-09-11 14:46:37 +03:00
Support bound function values for ReactElement types (#2518)
Summary: Release notes: none Add support for bound function values for `ReactElement` `type`. Pull Request resolved: https://github.com/facebook/prepack/pull/2518 Differential Revision: D9612253 Pulled By: trueadm fbshipit-source-id: f6d0b937c5892cfa44297c12a48e73197b50756c
This commit is contained in:
parent
54be9b535c
commit
43d480cfad
@ -14,6 +14,7 @@ import {
|
||||
AbstractObjectValue,
|
||||
AbstractValue,
|
||||
BooleanValue,
|
||||
BoundFunctionValue,
|
||||
ConcreteValue,
|
||||
ECMAScriptSourceFunctionValue,
|
||||
FunctionValue,
|
||||
@ -217,7 +218,9 @@ export default function(realm: Realm): void {
|
||||
0,
|
||||
(context, [component, config]) => {
|
||||
let hasValidComponent =
|
||||
component instanceof ECMAScriptSourceFunctionValue || valueIsKnownReactAbstraction(realm, component);
|
||||
component instanceof ECMAScriptSourceFunctionValue ||
|
||||
component instanceof BoundFunctionValue ||
|
||||
valueIsKnownReactAbstraction(realm, component);
|
||||
let hasValidConfig =
|
||||
config instanceof ObjectValue || config === realm.intrinsics.undefined || config === undefined;
|
||||
|
||||
|
@ -11,8 +11,9 @@
|
||||
|
||||
import { Realm } from "../realm.js";
|
||||
import {
|
||||
ECMAScriptSourceFunctionValue,
|
||||
AbstractValue,
|
||||
BoundFunctionValue,
|
||||
ECMAScriptSourceFunctionValue,
|
||||
ObjectValue,
|
||||
AbstractObjectValue,
|
||||
SymbolValue,
|
||||
@ -54,7 +55,7 @@ const whitelistedProperties = new Set(["props", "context", "refs", "setState"]);
|
||||
|
||||
export function getInitialProps(
|
||||
realm: Realm,
|
||||
componentType: ECMAScriptSourceFunctionValue | null,
|
||||
componentType: ECMAScriptSourceFunctionValue | BoundFunctionValue | null,
|
||||
{ modelString }: ReactComponentTreeConfig
|
||||
): AbstractObjectValue {
|
||||
let componentModel = modelString !== undefined ? (JSON.parse(modelString): ComponentModel) : undefined;
|
||||
@ -64,9 +65,16 @@ export function getInitialProps(
|
||||
if (valueIsClassComponent(realm, componentType)) {
|
||||
propsName = "this.props";
|
||||
} else {
|
||||
let formalParameters;
|
||||
if (componentType instanceof BoundFunctionValue) {
|
||||
invariant(componentType.$BoundTargetFunction instanceof ECMAScriptSourceFunctionValue);
|
||||
formalParameters = componentType.$BoundTargetFunction.$FormalParameters;
|
||||
} else {
|
||||
formalParameters = componentType.$FormalParameters;
|
||||
}
|
||||
// otherwise it's a functional component, where the first paramater of the function is "props" (if it exists)
|
||||
if (componentType.$FormalParameters.length > 0) {
|
||||
let firstParam = componentType.$FormalParameters[0];
|
||||
if (formalParameters.length > 0) {
|
||||
let firstParam = formalParameters[0];
|
||||
if (t.isIdentifier(firstParam)) {
|
||||
propsName = ((firstParam: any): BabelNodeIdentifier).name;
|
||||
}
|
||||
@ -80,7 +88,10 @@ export function getInitialProps(
|
||||
return abstractPropsObject;
|
||||
}
|
||||
|
||||
export function getInitialContext(realm: Realm, componentType: ECMAScriptSourceFunctionValue): AbstractObjectValue {
|
||||
export function getInitialContext(
|
||||
realm: Realm,
|
||||
componentType: ECMAScriptSourceFunctionValue | BoundFunctionValue
|
||||
): AbstractObjectValue {
|
||||
let contextName = null;
|
||||
if (valueIsClassComponent(realm, componentType)) {
|
||||
// it's a class component, so we need to check the type on for context of the component prototype
|
||||
@ -91,9 +102,16 @@ export function getInitialContext(realm: Realm, componentType: ECMAScriptSourceF
|
||||
throw new ExpectedBailOut("context on class components not yet supported");
|
||||
}
|
||||
} else {
|
||||
let formalParameters;
|
||||
if (componentType instanceof BoundFunctionValue) {
|
||||
invariant(componentType.$BoundTargetFunction instanceof ECMAScriptSourceFunctionValue);
|
||||
formalParameters = componentType.$BoundTargetFunction.$FormalParameters;
|
||||
} else {
|
||||
formalParameters = componentType.$FormalParameters;
|
||||
}
|
||||
// otherwise it's a functional component, where the second paramater of the function is "context" (if it exists)
|
||||
if (componentType.$FormalParameters.length > 1) {
|
||||
let secondParam = componentType.$FormalParameters[1];
|
||||
if (formalParameters.length > 1) {
|
||||
let secondParam = formalParameters[1];
|
||||
if (t.isIdentifier(secondParam)) {
|
||||
contextName = ((secondParam: any): BabelNodeIdentifier).name;
|
||||
}
|
||||
@ -125,7 +143,7 @@ function visitClassMethodAstForThisUsage(realm: Realm, method: ECMAScriptSourceF
|
||||
|
||||
export function createSimpleClassInstance(
|
||||
realm: Realm,
|
||||
componentType: ECMAScriptSourceFunctionValue,
|
||||
componentType: ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
props: ObjectValue | AbstractValue,
|
||||
context: ObjectValue | AbstractValue
|
||||
): AbstractObjectValue {
|
||||
@ -196,7 +214,7 @@ function deeplyApplyInstancePrototypeProperties(
|
||||
|
||||
export function createClassInstanceForFirstRenderOnly(
|
||||
realm: Realm,
|
||||
componentType: ECMAScriptSourceFunctionValue,
|
||||
componentType: ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
props: ObjectValue | AbstractValue,
|
||||
context: ObjectValue | AbstractValue,
|
||||
evaluatedNode: ReactEvaluatedNode
|
||||
@ -257,7 +275,7 @@ export function createClassInstanceForFirstRenderOnly(
|
||||
|
||||
export function createClassInstance(
|
||||
realm: Realm,
|
||||
componentType: ECMAScriptSourceFunctionValue,
|
||||
componentType: ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
props: ObjectValue | AbstractValue,
|
||||
context: ObjectValue | AbstractValue,
|
||||
classMetadata: ClassComponentMetadata
|
||||
@ -284,7 +302,7 @@ export function createClassInstance(
|
||||
|
||||
export function evaluateClassConstructor(
|
||||
realm: Realm,
|
||||
constructorFunc: ECMAScriptSourceFunctionValue,
|
||||
constructorFunc: ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
props: ObjectValue | AbstractValue | AbstractObjectValue,
|
||||
context: ObjectValue | AbstractObjectValue
|
||||
): { instanceProperties: Set<string>, instanceSymbols: Set<SymbolValue> } {
|
||||
|
@ -10,7 +10,7 @@
|
||||
/* @flow strict-local */
|
||||
|
||||
import { type Effects, Realm } from "../realm.js";
|
||||
import { AbstractValue, ECMAScriptSourceFunctionValue, ObjectValue } from "../values/index.js";
|
||||
import { AbstractValue, ECMAScriptSourceFunctionValue, ObjectValue, BoundFunctionValue } from "../values/index.js";
|
||||
import { createAdditionalEffects } from "../serializer/utils.js";
|
||||
import {
|
||||
convertFunctionalComponentToComplexClassComponent,
|
||||
@ -33,7 +33,7 @@ import { Logger } from "../utils/logger.js";
|
||||
|
||||
function applyWriteEffectsForOptimizedComponent(
|
||||
realm: Realm,
|
||||
componentType: ECMAScriptSourceFunctionValue,
|
||||
componentType: ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
_effects: Effects,
|
||||
componentTreeState: ComponentTreeState,
|
||||
evaluatedNode: ReactEvaluatedNode,
|
||||
@ -66,9 +66,17 @@ function applyWriteEffectsForOptimizedComponent(
|
||||
if (componentTreeState.status === "SIMPLE") {
|
||||
// if the root component was a class and is now simple, we can convert it from a class
|
||||
// component to a functional component
|
||||
convertSimpleClassComponentToFunctionalComponent(realm, componentType, additionalFunctionEffects);
|
||||
normalizeFunctionalComponentParamaters(componentType);
|
||||
writeEffects.set(componentType, additionalFunctionEffects);
|
||||
if (componentType instanceof BoundFunctionValue) {
|
||||
let targetFunction = componentType.$BoundTargetFunction;
|
||||
invariant(targetFunction instanceof ECMAScriptSourceFunctionValue);
|
||||
convertSimpleClassComponentToFunctionalComponent(realm, targetFunction, additionalFunctionEffects);
|
||||
normalizeFunctionalComponentParamaters(targetFunction);
|
||||
writeEffects.set(targetFunction, additionalFunctionEffects);
|
||||
} else {
|
||||
convertSimpleClassComponentToFunctionalComponent(realm, componentType, additionalFunctionEffects);
|
||||
normalizeFunctionalComponentParamaters(componentType);
|
||||
writeEffects.set(componentType, additionalFunctionEffects);
|
||||
}
|
||||
} else {
|
||||
let prototype = Get(realm, componentType, "prototype");
|
||||
invariant(prototype instanceof ObjectValue);
|
||||
@ -90,8 +98,15 @@ function applyWriteEffectsForOptimizedComponent(
|
||||
invariant(renderMethod instanceof ECMAScriptSourceFunctionValue);
|
||||
writeEffects.set(renderMethod, additionalFunctionEffects);
|
||||
} else {
|
||||
normalizeFunctionalComponentParamaters(componentType);
|
||||
writeEffects.set(componentType, additionalFunctionEffects);
|
||||
if (componentType instanceof BoundFunctionValue) {
|
||||
let targetFunction = componentType.$BoundTargetFunction;
|
||||
invariant(targetFunction instanceof ECMAScriptSourceFunctionValue);
|
||||
normalizeFunctionalComponentParamaters(targetFunction);
|
||||
writeEffects.set(targetFunction, additionalFunctionEffects);
|
||||
} else {
|
||||
normalizeFunctionalComponentParamaters(componentType);
|
||||
writeEffects.set(componentType, additionalFunctionEffects);
|
||||
}
|
||||
}
|
||||
}
|
||||
// apply contextTypes for legacy context
|
||||
@ -111,7 +126,7 @@ function optimizeReactComponentTreeBranches(
|
||||
writeEffects: WriteEffects,
|
||||
environmentRecordIdAfterGlobalCode: number,
|
||||
logger: Logger,
|
||||
alreadyEvaluated: Map<ECMAScriptSourceFunctionValue, ReactEvaluatedNode>
|
||||
alreadyEvaluated: Map<ECMAScriptSourceFunctionValue | BoundFunctionValue, ReactEvaluatedNode>
|
||||
): void {
|
||||
if (realm.react.verbose && reconciler.branchedComponentTrees.length > 0) {
|
||||
logger.logInformation(` Evaluating React component tree branches...`);
|
||||
@ -151,13 +166,13 @@ function optimizeReactComponentTreeBranches(
|
||||
|
||||
export function optimizeReactComponentTreeRoot(
|
||||
realm: Realm,
|
||||
componentRoot: ECMAScriptSourceFunctionValue | AbstractValue,
|
||||
componentRoot: ECMAScriptSourceFunctionValue | BoundFunctionValue | AbstractValue,
|
||||
config: ReactComponentTreeConfig,
|
||||
writeEffects: WriteEffects,
|
||||
environmentRecordIdAfterGlobalCode: number,
|
||||
logger: Logger,
|
||||
statistics: ReactStatistics,
|
||||
alreadyEvaluated: Map<ECMAScriptSourceFunctionValue, ReactEvaluatedNode>
|
||||
alreadyEvaluated: Map<ECMAScriptSourceFunctionValue | BoundFunctionValue, ReactEvaluatedNode>
|
||||
): void {
|
||||
let reconciler = new Reconciler(realm, config, alreadyEvaluated, statistics, logger);
|
||||
let componentType = getComponentTypeFromRootValue(realm, componentRoot);
|
||||
|
@ -103,7 +103,7 @@ export type BranchReactComponentTree = {
|
||||
};
|
||||
|
||||
export type ComponentTreeState = {
|
||||
componentType: void | ECMAScriptSourceFunctionValue,
|
||||
componentType: void | ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
contextTypes: Set<string>,
|
||||
deadEnds: number,
|
||||
status: "SIMPLE" | "COMPLEX",
|
||||
@ -143,7 +143,7 @@ export class Reconciler {
|
||||
constructor(
|
||||
realm: Realm,
|
||||
componentTreeConfig: ReactComponentTreeConfig,
|
||||
alreadyEvaluated: Map<ECMAScriptSourceFunctionValue, ReactEvaluatedNode>,
|
||||
alreadyEvaluated: Map<ECMAScriptSourceFunctionValue | BoundFunctionValue, ReactEvaluatedNode>,
|
||||
statistics: ReactStatistics,
|
||||
logger?: Logger
|
||||
) {
|
||||
@ -160,13 +160,13 @@ export class Reconciler {
|
||||
statistics: ReactStatistics;
|
||||
logger: void | Logger;
|
||||
componentTreeState: ComponentTreeState;
|
||||
alreadyEvaluated: Map<ECMAScriptSourceFunctionValue, ReactEvaluatedNode>;
|
||||
alreadyEvaluated: Map<ECMAScriptSourceFunctionValue | BoundFunctionValue, ReactEvaluatedNode>;
|
||||
componentTreeConfig: ReactComponentTreeConfig;
|
||||
currentEffectsStack: Array<Effects>;
|
||||
branchedComponentTrees: Array<BranchReactComponentTree>;
|
||||
|
||||
resolveReactComponentTree(
|
||||
componentType: ECMAScriptSourceFunctionValue,
|
||||
componentType: ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
props: ObjectValue | AbstractObjectValue | null,
|
||||
context: ObjectValue | AbstractObjectValue | null,
|
||||
evaluatedRootNode: ReactEvaluatedNode
|
||||
@ -233,7 +233,7 @@ export class Reconciler {
|
||||
}
|
||||
|
||||
_resolveComplexClassComponent(
|
||||
componentType: ECMAScriptSourceFunctionValue,
|
||||
componentType: ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
props: ObjectValue | AbstractObjectValue,
|
||||
context: ObjectValue | AbstractObjectValue,
|
||||
classMetadata: ClassComponentMetadata,
|
||||
@ -268,7 +268,7 @@ export class Reconciler {
|
||||
}
|
||||
|
||||
_resolveSimpleClassComponent(
|
||||
componentType: ECMAScriptSourceFunctionValue,
|
||||
componentType: ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
props: ObjectValue | AbstractObjectValue,
|
||||
context: ObjectValue | AbstractObjectValue,
|
||||
branchStatus: BranchStatusEnum,
|
||||
@ -284,7 +284,7 @@ export class Reconciler {
|
||||
}
|
||||
|
||||
_resolveFunctionalComponent(
|
||||
componentType: ECMAScriptSourceFunctionValue,
|
||||
componentType: ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
props: ObjectValue | AbstractObjectValue,
|
||||
context: ObjectValue | AbstractObjectValue,
|
||||
evaluatedNode: ReactEvaluatedNode
|
||||
@ -293,7 +293,7 @@ export class Reconciler {
|
||||
}
|
||||
|
||||
_getClassComponentMetadata(
|
||||
componentType: ECMAScriptSourceFunctionValue,
|
||||
componentType: ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
props: ObjectValue | AbstractObjectValue,
|
||||
context: ObjectValue | AbstractObjectValue
|
||||
): ClassComponentMetadata {
|
||||
@ -487,7 +487,7 @@ export class Reconciler {
|
||||
let evaluatedChildNode = createReactEvaluatedNode("FORWARD_REF", getComponentName(this.realm, forwardedComponent));
|
||||
evaluatedNode.children.push(evaluatedChildNode);
|
||||
invariant(
|
||||
forwardedComponent instanceof ECMAScriptSourceFunctionValue,
|
||||
forwardedComponent instanceof ECMAScriptSourceFunctionValue || forwardedComponent instanceof BoundFunctionValue,
|
||||
"expect React.forwardRef() to be passed function value"
|
||||
);
|
||||
let value = getValueFromFunctionCall(this.realm, forwardedComponent, this.realm.intrinsics.undefined, [
|
||||
@ -551,7 +551,7 @@ export class Reconciler {
|
||||
}
|
||||
|
||||
_resolveClassComponent(
|
||||
componentType: ECMAScriptSourceFunctionValue,
|
||||
componentType: ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
props: ObjectValue | AbstractObjectValue,
|
||||
context: ObjectValue | AbstractObjectValue,
|
||||
branchStatus: BranchStatusEnum,
|
||||
@ -609,7 +609,7 @@ export class Reconciler {
|
||||
}
|
||||
|
||||
_resolveClassComponentForFirstRenderOnly(
|
||||
componentType: ECMAScriptSourceFunctionValue,
|
||||
componentType: ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
props: ObjectValue | AbstractObjectValue,
|
||||
context: ObjectValue | AbstractObjectValue,
|
||||
branchStatus: BranchStatusEnum,
|
||||
@ -703,7 +703,7 @@ export class Reconciler {
|
||||
evaluatedNode.message = "RelayContainer";
|
||||
throw new NewComponentTreeBranch(evaluatedNode);
|
||||
}
|
||||
invariant(componentType instanceof ECMAScriptSourceFunctionValue);
|
||||
invariant(componentType instanceof ECMAScriptSourceFunctionValue || componentType instanceof BoundFunctionValue);
|
||||
let value;
|
||||
let childContext = context;
|
||||
|
||||
@ -1140,7 +1140,11 @@ export class Reconciler {
|
||||
switch (componentResolutionStrategy) {
|
||||
case "NORMAL": {
|
||||
if (
|
||||
!(typeValue instanceof ECMAScriptSourceFunctionValue || valueIsKnownReactAbstraction(this.realm, typeValue))
|
||||
!(
|
||||
typeValue instanceof ECMAScriptSourceFunctionValue ||
|
||||
typeValue instanceof BoundFunctionValue ||
|
||||
valueIsKnownReactAbstraction(this.realm, typeValue)
|
||||
)
|
||||
) {
|
||||
return this._resolveUnknownComponentType(componentType, reactElement, context, branchStatus, evaluatedNode);
|
||||
}
|
||||
|
@ -438,11 +438,13 @@ const skipFunctionProperties = new Set(["length", "prototype", "arguments", "nam
|
||||
|
||||
export function convertFunctionalComponentToComplexClassComponent(
|
||||
realm: Realm,
|
||||
functionalComponentType: ECMAScriptSourceFunctionValue,
|
||||
complexComponentType: void | ECMAScriptSourceFunctionValue,
|
||||
functionalComponentType: ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
complexComponentType: void | ECMAScriptSourceFunctionValue | BoundFunctionValue,
|
||||
additionalFunctionEffects: AdditionalFunctionEffects
|
||||
): void {
|
||||
invariant(complexComponentType instanceof ECMAScriptSourceFunctionValue);
|
||||
invariant(
|
||||
complexComponentType instanceof ECMAScriptSourceFunctionValue || complexComponentType instanceof BoundFunctionValue
|
||||
);
|
||||
// get all properties on the functional component that were added in user-code
|
||||
// we add defaultProps as undefined, as merging a class component's defaultProps on to
|
||||
// a differnet component isn't right, we can discard defaultProps instead via folding
|
||||
@ -524,9 +526,18 @@ export function createReactHintObject(
|
||||
};
|
||||
}
|
||||
|
||||
export function getComponentTypeFromRootValue(realm: Realm, value: Value): ECMAScriptSourceFunctionValue | null {
|
||||
export function getComponentTypeFromRootValue(
|
||||
realm: Realm,
|
||||
value: Value
|
||||
): ECMAScriptSourceFunctionValue | BoundFunctionValue | null {
|
||||
let _valueIsKnownReactAbstraction = valueIsKnownReactAbstraction(realm, value);
|
||||
if (!(value instanceof ECMAScriptSourceFunctionValue || _valueIsKnownReactAbstraction)) {
|
||||
if (
|
||||
!(
|
||||
value instanceof ECMAScriptSourceFunctionValue ||
|
||||
value instanceof BoundFunctionValue ||
|
||||
_valueIsKnownReactAbstraction
|
||||
)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
if (_valueIsKnownReactAbstraction) {
|
||||
@ -542,7 +553,9 @@ export function getComponentTypeFromRootValue(realm: Realm, value: Value): ECMAS
|
||||
invariant(Array.isArray(reactHint.args));
|
||||
// componentType is the 1st argument of a ReactRelay container
|
||||
let componentType = reactHint.args[0];
|
||||
invariant(componentType instanceof ECMAScriptSourceFunctionValue);
|
||||
invariant(
|
||||
componentType instanceof ECMAScriptSourceFunctionValue || componentType instanceof BoundFunctionValue
|
||||
);
|
||||
return componentType;
|
||||
default:
|
||||
invariant(
|
||||
@ -553,7 +566,7 @@ export function getComponentTypeFromRootValue(realm: Realm, value: Value): ECMAS
|
||||
}
|
||||
invariant(false, "unsupported known React abstraction");
|
||||
} else {
|
||||
invariant(value instanceof ECMAScriptSourceFunctionValue);
|
||||
invariant(value instanceof ECMAScriptSourceFunctionValue || value instanceof BoundFunctionValue);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import {
|
||||
AbstractObjectValue,
|
||||
AbstractValue,
|
||||
ArrayValue,
|
||||
BoundFunctionValue,
|
||||
ConcreteValue,
|
||||
ECMAScriptSourceFunctionValue,
|
||||
FunctionValue,
|
||||
@ -396,7 +397,7 @@ export class Realm {
|
||||
// we need to know what React component was passed to this AbstractObjectValue so we can visit it next)
|
||||
abstractHints: WeakMap<AbstractValue | ObjectValue, ReactHint>,
|
||||
activeReconciler: any, // inentionally "any", importing the React reconciler class increases Flow's cylic count
|
||||
classComponentMetadata: Map<ECMAScriptSourceFunctionValue, ClassComponentMetadata>,
|
||||
classComponentMetadata: Map<ECMAScriptSourceFunctionValue | BoundFunctionValue, ClassComponentMetadata>,
|
||||
currentOwner?: ObjectValue,
|
||||
defaultPropsHelper?: ECMAScriptSourceFunctionValue,
|
||||
emptyArray: void | ArrayValue,
|
||||
|
@ -19,6 +19,7 @@ import { ignoreErrorsIn } from "../utils/errors.js";
|
||||
import {
|
||||
AbstractObjectValue,
|
||||
AbstractValue,
|
||||
BoundFunctionValue,
|
||||
ECMAScriptSourceFunctionValue,
|
||||
FunctionValue,
|
||||
ObjectValue,
|
||||
@ -87,6 +88,7 @@ export class Functions {
|
||||
let validConfig = config instanceof ObjectValue || config === realm.intrinsics.undefined;
|
||||
let validRootComponent =
|
||||
rootComponent instanceof ECMAScriptSourceFunctionValue ||
|
||||
rootComponent instanceof BoundFunctionValue ||
|
||||
(rootComponent instanceof AbstractValue && valueIsKnownReactAbstraction(this.realm, rootComponent));
|
||||
|
||||
if (validConfig && validRootComponent) {
|
||||
|
@ -128,6 +128,14 @@ it("Simple 24", () => {
|
||||
runTest(__dirname + "/FunctionalComponents/simple-24.js");
|
||||
});
|
||||
|
||||
it("Bound type", () => {
|
||||
runTest(__dirname + "/FunctionalComponents/bound-type.js");
|
||||
});
|
||||
|
||||
it("Bound type 2", () => {
|
||||
runTest(__dirname + "/FunctionalComponents/bound-type2.js");
|
||||
});
|
||||
|
||||
it("Two roots", () => {
|
||||
runTest(__dirname + "/FunctionalComponents/two-roots.js");
|
||||
});
|
||||
|
28
test/react/FunctionalComponents/bound-type.js
Normal file
28
test/react/FunctionalComponents/bound-type.js
Normal file
@ -0,0 +1,28 @@
|
||||
var React = require("react");
|
||||
|
||||
function Child(props) {
|
||||
return (
|
||||
<div>
|
||||
{props.x}
|
||||
{this.y}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
var foo = { y: " world" };
|
||||
const BoundChild = Child.bind(foo);
|
||||
|
||||
function App(props) {
|
||||
return <BoundChild x={props.x} />;
|
||||
}
|
||||
|
||||
App.getTrials = function(renderer, Root) {
|
||||
renderer.update(<Root />);
|
||||
return [["simple bound function", renderer.toJSON()]];
|
||||
};
|
||||
|
||||
if (this.__optimizeReactComponentTree) {
|
||||
__optimizeReactComponentTree(App);
|
||||
}
|
||||
|
||||
module.exports = App;
|
24
test/react/FunctionalComponents/bound-type2.js
Normal file
24
test/react/FunctionalComponents/bound-type2.js
Normal file
@ -0,0 +1,24 @@
|
||||
var React = require("react");
|
||||
|
||||
function App(props) {
|
||||
return (
|
||||
<div>
|
||||
{props.x}
|
||||
{this.y}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
var foo = { y: " world" };
|
||||
const BoundApp = App.bind(foo);
|
||||
|
||||
BoundApp.getTrials = function(renderer, Root) {
|
||||
renderer.update(<Root x={"Hello"} />);
|
||||
return [["simple bound function", renderer.toJSON()]];
|
||||
};
|
||||
|
||||
if (this.__optimizeReactComponentTree) {
|
||||
__optimizeReactComponentTree(BoundApp);
|
||||
}
|
||||
|
||||
module.exports = BoundApp;
|
@ -536,6 +536,170 @@ ReactStatistics {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Bound type 2: (JSX => JSX) 1`] = `
|
||||
ReactStatistics {
|
||||
"componentsEvaluated": 1,
|
||||
"evaluatedRootNodes": Array [
|
||||
Object {
|
||||
"children": Array [],
|
||||
"message": "",
|
||||
"name": "bound anonymous",
|
||||
"status": "ROOT",
|
||||
},
|
||||
],
|
||||
"inlinedComponents": 0,
|
||||
"optimizedNestedClosures": 0,
|
||||
"optimizedTrees": 1,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Bound type 2: (JSX => createElement) 1`] = `
|
||||
ReactStatistics {
|
||||
"componentsEvaluated": 1,
|
||||
"evaluatedRootNodes": Array [
|
||||
Object {
|
||||
"children": Array [],
|
||||
"message": "",
|
||||
"name": "bound anonymous",
|
||||
"status": "ROOT",
|
||||
},
|
||||
],
|
||||
"inlinedComponents": 0,
|
||||
"optimizedNestedClosures": 0,
|
||||
"optimizedTrees": 1,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Bound type 2: (createElement => JSX) 1`] = `
|
||||
ReactStatistics {
|
||||
"componentsEvaluated": 1,
|
||||
"evaluatedRootNodes": Array [
|
||||
Object {
|
||||
"children": Array [],
|
||||
"message": "",
|
||||
"name": "bound anonymous",
|
||||
"status": "ROOT",
|
||||
},
|
||||
],
|
||||
"inlinedComponents": 0,
|
||||
"optimizedNestedClosures": 0,
|
||||
"optimizedTrees": 1,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Bound type 2: (createElement => createElement) 1`] = `
|
||||
ReactStatistics {
|
||||
"componentsEvaluated": 1,
|
||||
"evaluatedRootNodes": Array [
|
||||
Object {
|
||||
"children": Array [],
|
||||
"message": "",
|
||||
"name": "bound anonymous",
|
||||
"status": "ROOT",
|
||||
},
|
||||
],
|
||||
"inlinedComponents": 0,
|
||||
"optimizedNestedClosures": 0,
|
||||
"optimizedTrees": 1,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Bound type: (JSX => JSX) 1`] = `
|
||||
ReactStatistics {
|
||||
"componentsEvaluated": 2,
|
||||
"evaluatedRootNodes": Array [
|
||||
Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
"children": Array [],
|
||||
"message": "",
|
||||
"name": "bound anonymous",
|
||||
"status": "INLINED",
|
||||
},
|
||||
],
|
||||
"message": "",
|
||||
"name": "App",
|
||||
"status": "ROOT",
|
||||
},
|
||||
],
|
||||
"inlinedComponents": 1,
|
||||
"optimizedNestedClosures": 0,
|
||||
"optimizedTrees": 1,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Bound type: (JSX => createElement) 1`] = `
|
||||
ReactStatistics {
|
||||
"componentsEvaluated": 2,
|
||||
"evaluatedRootNodes": Array [
|
||||
Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
"children": Array [],
|
||||
"message": "",
|
||||
"name": "bound anonymous",
|
||||
"status": "INLINED",
|
||||
},
|
||||
],
|
||||
"message": "",
|
||||
"name": "App",
|
||||
"status": "ROOT",
|
||||
},
|
||||
],
|
||||
"inlinedComponents": 1,
|
||||
"optimizedNestedClosures": 0,
|
||||
"optimizedTrees": 1,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Bound type: (createElement => JSX) 1`] = `
|
||||
ReactStatistics {
|
||||
"componentsEvaluated": 2,
|
||||
"evaluatedRootNodes": Array [
|
||||
Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
"children": Array [],
|
||||
"message": "",
|
||||
"name": "bound anonymous",
|
||||
"status": "INLINED",
|
||||
},
|
||||
],
|
||||
"message": "",
|
||||
"name": "App",
|
||||
"status": "ROOT",
|
||||
},
|
||||
],
|
||||
"inlinedComponents": 1,
|
||||
"optimizedNestedClosures": 0,
|
||||
"optimizedTrees": 1,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Bound type: (createElement => createElement) 1`] = `
|
||||
ReactStatistics {
|
||||
"componentsEvaluated": 2,
|
||||
"evaluatedRootNodes": Array [
|
||||
Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
"children": Array [],
|
||||
"message": "",
|
||||
"name": "bound anonymous",
|
||||
"status": "INLINED",
|
||||
},
|
||||
],
|
||||
"message": "",
|
||||
"name": "App",
|
||||
"status": "ROOT",
|
||||
},
|
||||
],
|
||||
"inlinedComponents": 1,
|
||||
"optimizedNestedClosures": 0,
|
||||
"optimizedTrees": 1,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Circular reference: (JSX => JSX) 1`] = `
|
||||
ReactStatistics {
|
||||
"componentsEvaluated": 1,
|
||||
|
Loading…
Reference in New Issue
Block a user