Handle intrinsic values created by React that have the same name (#2126)

Summary:
Release notes: none

There was a bug, where React abstract object values with the same intrinsic name were incorrectly being de-duped and re-used. This is a normal expected Prepack optimization, but it actually breaks React components that expect to be able to create many values with the same intrinsic name. We now mark such objects and ensure they do not correctly return `true` from `equals()`. Fixes https://github.com/facebook/prepack/issues/2089
Closes https://github.com/facebook/prepack/pull/2126

Differential Revision: D8448171

Pulled By: trueadm

fbshipit-source-id: d21fddd70576e6e55c41070ac43ce2f58a059e7a
This commit is contained in:
Dominic Gannaway 2018-06-15 09:07:58 -07:00 committed by Facebook Github Bot
parent 0cc82dc875
commit f2219fd33c
4 changed files with 116 additions and 0 deletions

View File

@ -3654,6 +3654,29 @@ ReactStatistics {
}
`;
exports[`Test React with JSX input, JSX output Functional component folding Two roots 1`] = `
ReactStatistics {
"componentsEvaluated": 2,
"evaluatedRootNodes": Array [
Object {
"children": Array [],
"message": "",
"name": "A",
"status": "ROOT",
},
Object {
"children": Array [],
"message": "",
"name": "B",
"status": "ROOT",
},
],
"inlinedComponents": 0,
"optimizedNestedClosures": 0,
"optimizedTrees": 2,
}
`;
exports[`Test React with JSX input, JSX output Functional component folding Unsafe spread 1`] = `"Failed to optimize React component tree for \\"App\\" due to a fatal error during evaluation: A fatal error occurred while prepacking."`;
exports[`Test React with JSX input, JSX output Functional component folding defaultProps 1`] = `
@ -8638,6 +8661,29 @@ ReactStatistics {
}
`;
exports[`Test React with JSX input, create-element output Functional component folding Two roots 1`] = `
ReactStatistics {
"componentsEvaluated": 2,
"evaluatedRootNodes": Array [
Object {
"children": Array [],
"message": "",
"name": "A",
"status": "ROOT",
},
Object {
"children": Array [],
"message": "",
"name": "B",
"status": "ROOT",
},
],
"inlinedComponents": 0,
"optimizedNestedClosures": 0,
"optimizedTrees": 2,
}
`;
exports[`Test React with JSX input, create-element output Functional component folding Unsafe spread 1`] = `"Failed to optimize React component tree for \\"App\\" due to a fatal error during evaluation: A fatal error occurred while prepacking."`;
exports[`Test React with JSX input, create-element output Functional component folding defaultProps 1`] = `
@ -13622,6 +13668,29 @@ ReactStatistics {
}
`;
exports[`Test React with create-element input, JSX output Functional component folding Two roots 1`] = `
ReactStatistics {
"componentsEvaluated": 2,
"evaluatedRootNodes": Array [
Object {
"children": Array [],
"message": "",
"name": "A",
"status": "ROOT",
},
Object {
"children": Array [],
"message": "",
"name": "B",
"status": "ROOT",
},
],
"inlinedComponents": 0,
"optimizedNestedClosures": 0,
"optimizedTrees": 2,
}
`;
exports[`Test React with create-element input, JSX output Functional component folding Unsafe spread 1`] = `
ReactStatistics {
"componentsEvaluated": 1,
@ -18621,6 +18690,29 @@ ReactStatistics {
}
`;
exports[`Test React with create-element input, create-element output Functional component folding Two roots 1`] = `
ReactStatistics {
"componentsEvaluated": 2,
"evaluatedRootNodes": Array [
Object {
"children": Array [],
"message": "",
"name": "A",
"status": "ROOT",
},
Object {
"children": Array [],
"message": "",
"name": "B",
"status": "ROOT",
},
],
"inlinedComponents": 0,
"optimizedNestedClosures": 0,
"optimizedTrees": 2,
}
`;
exports[`Test React with create-element input, create-element output Functional component folding Unsafe spread 1`] = `
ReactStatistics {
"componentsEvaluated": 1,

View File

@ -385,6 +385,10 @@ function runTestSuite(outputJsx, shouldTranspileSource) {
await runTest(directory, "simple-21.js");
});
it("Two roots", async () => {
await runTest(directory, "two-roots.js");
});
it("Havocing of ReactElements should not result in property assignments", async () => {
await runTest(directory, "react-element-havoc.js");
});

View File

@ -946,6 +946,11 @@ export default class AbstractValue extends Value {
template.makePartial();
template.makeSimple();
value = AbstractValue.createFromTemplate(realm, buildExpressionTemplate(name), ObjectValue, [], name);
if (!realm.isNameStringUnique(name)) {
value.hashValue = ++realm.objectCount;
} else {
realm.saveNameString(name);
}
value.intrinsicName = name;
value.values = new ValuesDomain(new Set([template]));
realm.rebuildNestedProperties(value, name);

View File

@ -0,0 +1,15 @@
function A(props) {
return props.toString();
}
function B(props) {
return props.toString();
}
if (this.__optimizeReactComponentTree) {
__optimizeReactComponentTree(A);
__optimizeReactComponentTree(B);
}
this.A = A;
this.B = B;