Fixing _serializeAbstractValue scoping

Summary:
Release notes: none

This fixes #1483.
Adding regression test case.
Closes https://github.com/facebook/prepack/pull/1484

Differential Revision: D7058713

Pulled By: NTillmann

fbshipit-source-id: ef8e417da4078109851242f23797b2480e135a04
This commit is contained in:
Nikolai Tillmann 2018-02-22 12:45:44 -08:00 committed by Facebook Github Bot
parent 80feb5e095
commit b24de956ea
3 changed files with 30 additions and 15 deletions

View File

@ -77,7 +77,7 @@ export class Emitter {
},
onAbstractValueWithIdentifier: val => {
// If the value hasn't been declared yet, then we should wait for it.
if (!this.ignoreDeclarations() && !this.hasBeenDeclared(val)) return val;
if (!this.cannotDeclare() && !this.hasBeenDeclared(val)) return val;
else return undefined;
},
};
@ -396,13 +396,13 @@ export class Emitter {
invariant(!this._activeValues.has(value));
invariant(value.hasIdentifier());
invariant(this._isEmittingActiveGenerator());
invariant(!this.ignoreDeclarations());
invariant(!this.cannotDeclare());
invariant(!this._body.done);
if (this._body.declaredAbstractValues === undefined) this._body.declaredAbstractValues = new Map();
this._body.declaredAbstractValues.set(value, this._body);
this._processValue(value);
}
ignoreDeclarations(): boolean {
cannotDeclare(): boolean {
// Bodies of the following types will never contain any (temporal) abstract value declarations.
return this._body.type === "DelayInitializations" || this._body.type === "LazyObjectInitializer";
}

View File

@ -733,6 +733,23 @@ export class ResidualHeapSerializer {
return ((residualBinding.serializedValue: any): BabelNodeIdentifier | BabelNodeMemberExpression);
}
_declare(
emittingToResidualFunction: boolean,
bindingType: BabelVariableKind,
id: BabelNodeLVal,
init: BabelNodeExpression
) {
if (emittingToResidualFunction) {
let declar = t.variableDeclaration(bindingType, [t.variableDeclarator(id)]);
this.mainBody.entries.push(declar);
let assignment = t.expressionStatement(t.assignmentExpression("=", id, init));
this.emitter.emit(assignment);
} else {
let declar = t.variableDeclaration(bindingType, [t.variableDeclarator(id, init)]);
this.emitter.emit(declar);
}
}
serializeValue(val: Value, referenceOnly?: boolean, bindingType?: BabelVariableKind): BabelNodeExpression {
invariant(!val.refuseSerialization);
if (val instanceof AbstractValue) {
@ -798,15 +815,7 @@ export class ResidualHeapSerializer {
this.emitter.emit(commentStatement(comment));
}
if (init !== id) {
if (target.usedOnlyByResidualFunctions) {
let declar = t.variableDeclaration(bindingType ? bindingType : "var", [t.variableDeclarator(id)]);
this.mainBody.entries.push(declar);
let assignment = t.expressionStatement(t.assignmentExpression("=", id, init));
this.emitter.emit(assignment);
} else {
let declar = t.variableDeclaration(bindingType ? bindingType : "var", [t.variableDeclarator(id, init)]);
this.emitter.emit(declar);
}
this._declare(!!target.usedOnlyByResidualFunctions, bindingType || "var", id, init);
}
this.statistics.valueIds++;
if (target.usedOnlyByResidualFunctions) this.statistics.delayedValues++;
@ -1516,7 +1525,7 @@ export class ResidualHeapSerializer {
let id = ((serializedValue: any): BabelNodeIdentifier);
invariant(
!this.preludeGenerator.derivedIds.has(id.name) ||
this.emitter.ignoreDeclarations() ||
this.emitter.cannotDeclare() ||
this.emitter.hasBeenDeclared(val)
);
}
@ -1536,8 +1545,7 @@ export class ResidualHeapSerializer {
this.emitter.emitNowOrAfterWaitingForDependencies(val.args, () => {
const serializedValue = this._serializeAbstractValueHelper(val);
let uid = this.getSerializeObjectIdentifier(val);
let declar = t.variableDeclaration("var", [t.variableDeclarator(uid, serializedValue)]);
this.emitter.emit(declar);
this._declare(this.emitter.cannotDeclare(), "var", uid, serializedValue);
});
}
}

View File

@ -0,0 +1,7 @@
(function () {
let a = global.__abstract ? __abstract(undefined, "(42)") : 42;
function f() {
return a++;
}
global.inspect = function() { f() + f(); }
})();