From 5ad625048a2941b593df0ca6a5816eef7b5d8dce Mon Sep 17 00:00:00 2001 From: Nikolai Tillmann Date: Tue, 19 Jun 2018 20:48:18 -0700 Subject: [PATCH] Don't purge bindings when execution leaves scope (#2136) Summary: Release notes: None For historical and apparently no longer needed reasons, we used to forget about modified bindings when execution leaves scopes. However, this means that the binding no longer properly participates in state tracking, which is conceptually dubious. While by itself, it didn't seem to cause much (or any?) harm, it turned out to be a blocker for #2125, where the initial state of a binding becomes important when joining partially leaked bindings. Closes https://github.com/facebook/prepack/pull/2136 Reviewed By: hermanventer Differential Revision: D8528939 Pulled By: NTillmann fbshipit-source-id: 0890c32d55f6b498cb4613171eee54ff9b445730 --- src/realm.js | 69 ---------------------------------------------------- 1 file changed, 69 deletions(-) diff --git a/src/realm.js b/src/realm.js index 30b74ea5a..7541495c8 100644 --- a/src/realm.js +++ b/src/realm.js @@ -495,46 +495,10 @@ export class Realm { return context; } - clearBlockBindings(modifiedBindings: void | Bindings, environmentRecord: DeclarativeEnvironmentRecord) { - if (modifiedBindings === undefined) return; - for (let b of modifiedBindings.keys()) - if (environmentRecord.bindings[b.name] && environmentRecord.bindings[b.name] === b) modifiedBindings.delete(b); - } - - clearBlockBindingsFromCompletion(completion: Completion, environmentRecord: DeclarativeEnvironmentRecord) { - if (completion instanceof PossiblyNormalCompletion) { - this.clearBlockBindings(completion.alternateEffects.modifiedBindings, environmentRecord); - this.clearBlockBindings(completion.consequentEffects.modifiedBindings, environmentRecord); - if (completion.savedEffects !== undefined) - this.clearBlockBindings(completion.savedEffects.modifiedBindings, environmentRecord); - if (completion.alternate instanceof Completion) - this.clearBlockBindingsFromCompletion(completion.alternate, environmentRecord); - if (completion.consequent instanceof Completion) - this.clearBlockBindingsFromCompletion(completion.consequent, environmentRecord); - } else if (completion instanceof ForkedAbruptCompletion) { - this.clearBlockBindings(completion.alternateEffects.modifiedBindings, environmentRecord); - this.clearBlockBindings(completion.consequentEffects.modifiedBindings, environmentRecord); - if (completion.alternate instanceof Completion) - this.clearBlockBindingsFromCompletion(completion.alternate, environmentRecord); - if (completion.consequent instanceof Completion) - this.clearBlockBindingsFromCompletion(completion.consequent, environmentRecord); - } - } - // Call when a scope falls out of scope and should be destroyed. // Clears the Bindings corresponding to the disappearing Scope from ModifiedBindings onDestroyScope(lexicalEnvironment: LexicalEnvironment) { invariant(this.activeLexicalEnvironments.has(lexicalEnvironment)); - let modifiedBindings = this.modifiedBindings; - if (modifiedBindings) { - // Don't undo things to global scope because it's needed past its destruction point (for serialization) - let environmentRecord = lexicalEnvironment.environmentRecord; - if (environmentRecord instanceof DeclarativeEnvironmentRecord) { - this.clearBlockBindings(modifiedBindings, environmentRecord); - if (this.savedCompletion !== undefined) - this.clearBlockBindingsFromCompletion(this.savedCompletion, environmentRecord); - } - } // Ensures if we call onDestroyScope too early, there will be a failure. this.activeLexicalEnvironments.delete(lexicalEnvironment); @@ -548,40 +512,7 @@ export class Realm { this.contextStack.push(context); } - clearFunctionBindings(modifiedBindings: void | Bindings, funcVal: FunctionValue) { - if (modifiedBindings === undefined) return; - for (let b of modifiedBindings.keys()) { - if (b.environment instanceof FunctionEnvironmentRecord && b.environment.$FunctionObject === funcVal) - modifiedBindings.delete(b); - } - } - - clearFunctionBindingsFromCompletion(completion: Completion, funcVal: FunctionValue) { - if (completion instanceof PossiblyNormalCompletion) { - this.clearFunctionBindings(completion.alternateEffects.modifiedBindings, funcVal); - this.clearFunctionBindings(completion.consequentEffects.modifiedBindings, funcVal); - if (completion.savedEffects !== undefined) - this.clearFunctionBindings(completion.savedEffects.modifiedBindings, funcVal); - if (completion.alternate instanceof Completion) - this.clearFunctionBindingsFromCompletion(completion.alternate, funcVal); - if (completion.consequent instanceof Completion) - this.clearFunctionBindingsFromCompletion(completion.consequent, funcVal); - } else if (completion instanceof ForkedAbruptCompletion) { - this.clearFunctionBindings(completion.alternateEffects.modifiedBindings, funcVal); - this.clearFunctionBindings(completion.consequentEffects.modifiedBindings, funcVal); - if (completion.alternate instanceof Completion) - this.clearFunctionBindingsFromCompletion(completion.alternate, funcVal); - if (completion.consequent instanceof Completion) - this.clearFunctionBindingsFromCompletion(completion.consequent, funcVal); - } - } - popContext(context: ExecutionContext): void { - let funcVal = context.function; - if (funcVal) { - this.clearFunctionBindings(this.modifiedBindings, funcVal); - if (this.savedCompletion !== undefined) this.clearFunctionBindingsFromCompletion(this.savedCompletion, funcVal); - } let c = this.contextStack.pop(); invariant(c === context); }