-
Notifications
You must be signed in to change notification settings - Fork 422
Adds support for abstract length arrays in React reconcilation and serialization #2571
Changes from 3 commits
f296e3f
9769800
7e335e5
ff43d75
5adb04a
d43da2a
f46d018
2b3a071
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -224,6 +224,7 @@ export class ResidualHeapSerializer { | |
let environment = realm.$GlobalEnv.environmentRecord; | ||
invariant(environment instanceof GlobalEnvironmentRecord); | ||
this.globalEnvironmentRecord = environment; | ||
this.emptySerializesToEmptyString = false; | ||
} | ||
|
||
emitter: Emitter; | ||
|
@@ -269,6 +270,7 @@ export class ResidualHeapSerializer { | |
referentializer: Referentializer; | ||
additionalFunctionGenerators: Map<FunctionValue, Generator>; | ||
_residualOptimizedFunctions: ResidualOptimizedFunctions; | ||
emptySerializesToEmptyString: boolean; | ||
|
||
// function values nested in additional functions can't delay initializations | ||
// TODO: revisit this and fix additional functions to be capable of delaying initializations | ||
|
@@ -2047,6 +2049,10 @@ export class ResidualHeapSerializer { | |
} | ||
|
||
_serializeEmptyValue(): BabelNodeExpression { | ||
if (this.emptySerializesToEmptyString) { | ||
invariant(this.realm.react.enabled, "emptySerializesToEmptyString is a React optimization"); | ||
return t.stringLiteral(""); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than output the empty variable, instead we generate an empty string as the React serialization expects this for cases where the value is a string. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The special "empty value" is used as a marker value as part of comparisons. It should never leak through as the actual value of anything that's exposed. For that reason, I don't understand how this can fix anything? Also, the identity if that "empty value" matters. Replacing it in some contexts with something else (that isn't even unique), seems highly dubious to me. Why is this correct? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you remove the string literal optimization, you will see There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've removed this form the PR, but now the tests fail as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have a different approach that removes holes from the arrays in the reconciler so we shouldn't hit the same issue but the still overall problem with |
||
} | ||
this.needsEmptyVar = !this.realm.instantRender.enabled; | ||
return emptyExpression; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
var React = require("react"); | ||
|
||
function App(props) { | ||
var arr = [1, 2, 3]; | ||
|
||
if (props.cond) { | ||
arr.push(4); | ||
} else { | ||
arr.pop(); | ||
} | ||
return ( | ||
<div> | ||
<span x={arr} /> | ||
<span x={arr} /> | ||
</div> | ||
); | ||
} | ||
|
||
App.getTrials = function(renderer, Root) { | ||
let results = []; | ||
renderer.update(<Root cond={true} />); | ||
results.push(["abstract array length on prop (cond: true)", renderer.toJSON()]); | ||
renderer.update(<Root cond={false} />); | ||
results.push(["abstract array length on prop (cond: false)", renderer.toJSON()]); | ||
return results; | ||
}; | ||
|
||
if (this.__optimizeReactComponentTree) { | ||
__optimizeReactComponentTree(App); | ||
} | ||
|
||
module.exports = App; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comparing to what happens below for the concrete case, I don't understand how just using "length" once as the key here is supposed to work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should also add the
length
for the concrete case too.