From 3b3bd06819805338ddfe5f618e5ad1b554de9f43 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Tue, 12 Apr 2016 18:14:34 -0400 Subject: [PATCH] Add tests for Lexical Environment management Add tests that assert the management of the running execution context's LexicalEnvironment and VariableEnvironment components, as created by the following abstract operations: - NewDeclarativeEnvironment - NewObjectEnvironment - NewFunctionEnvironment Many tests require the use of non-strict direct eval, meaning they may not be run in strict mode. This does not effect coverage because the semantics in these cases are not observable from strict mode code. Some situations require the creation of a binding, but this binding has no relevance to the test itself. In these cases, use names consisting solely of the underscore character (`_`). Avoid the use of Block statements wherever possible, as these trigger the creation of additional environments which may interfere with the behavior under test. --- .../expressions/call/scope-lex-close.js | 30 +++++ .../expressions/call/scope-lex-open.js | 39 ++++++ .../expressions/call/scope-var-close.js | 29 +++++ .../expressions/call/scope-var-open.js | 41 +++++++ .../expressions/class/scope-name-lex-close.js | 21 ++++ .../class/scope-name-lex-open-heritage.js | 37 ++++++ .../class/scope-name-lex-open-no-heritage.js | 39 ++++++ .../function/scope-body-lex-distinct.js | 49 ++++++++ .../function/scope-name-var-close.js | 28 +++++ .../scope-name-var-open-non-strict.js | 50 ++++++++ .../function/scope-name-var-open-strict.js | 54 +++++++++ .../function/scope-param-elem-var-close.js | 32 +++++ .../function/scope-param-elem-var-open.js | 31 +++++ .../scope-param-rest-elem-var-close.js | 36 ++++++ .../scope-param-rest-elem-var-open.js | 36 ++++++ .../function/scope-paramsbody-var-close.js | 34 ++++++ .../function/scope-paramsbody-var-open.js | 32 +++++ .../generators/scope-name-var-close.js | 28 +++++ .../scope-name-var-open-non-strict.js | 50 ++++++++ .../generators/scope-name-var-open-strict.js | 54 +++++++++ .../statements/block/scope-lex-close.js | 27 +++++ .../statements/block/scope-lex-open.js | 26 ++++ .../statements/block/scope-var-none.js | 27 +++++ .../statements/class/scope-name-lex-close.js | 22 ++++ .../class/scope-name-lex-open-heritage.js | 46 ++++++++ .../class/scope-name-lex-open-no-heritage.js | 45 +++++++ .../for-in/scope-body-lex-boundary.js | 50 ++++++++ .../statements/for-in/scope-body-lex-close.js | 40 +++++++ .../statements/for-in/scope-body-lex-open.js | 48 ++++++++ .../statements/for-in/scope-body-var-none.js | 48 ++++++++ .../statements/for-in/scope-head-lex-close.js | 44 +++++++ .../statements/for-in/scope-head-lex-open.js | 38 ++++++ .../statements/for-in/scope-head-var-none.js | 45 +++++++ .../for-of/scope-body-lex-boundary.js | 38 ++++++ .../statements/for-of/scope-body-lex-close.js | 40 +++++++ .../statements/for-of/scope-body-lex-open.js | 48 ++++++++ .../statements/for-of/scope-body-var-none.js | 48 ++++++++ .../statements/for-of/scope-head-lex-close.js | 44 +++++++ .../statements/for-of/scope-head-lex-open.js | 38 ++++++ .../statements/for-of/scope-head-var-none.js | 45 +++++++ .../statements/for/scope-body-lex-boundary.js | 43 +++++++ .../statements/for/scope-body-lex-open.js | 46 ++++++++ .../statements/for/scope-body-var-none.js | 111 ++++++++++++++++++ .../statements/for/scope-head-lex-close.js | 39 ++++++ .../statements/for/scope-head-lex-open.js | 39 ++++++ .../statements/for/scope-head-var-none.js | 42 +++++++ .../statements/switch/scope-lex-close-case.js | 32 +++++ .../statements/switch/scope-lex-close-dflt.js | 46 ++++++++ .../statements/switch/scope-lex-open-case.js | 32 +++++ .../statements/switch/scope-lex-open-dflt.js | 29 +++++ .../statements/switch/scope-var-none-case.js | 32 +++++ .../statements/switch/scope-var-none-dflt.js | 31 +++++ .../try/scope-catch-block-lex-close.js | 24 ++++ .../try/scope-catch-block-lex-open.js | 24 ++++ .../try/scope-catch-block-var-none.js | 25 ++++ .../try/scope-catch-param-lex-close.js | 18 +++ .../try/scope-catch-param-lex-open.js | 20 ++++ .../try/scope-catch-param-var-none.js | 26 ++++ .../statements/with/scope-var-close.js | 25 ++++ .../statements/with/scope-var-open.js | 26 ++++ 60 files changed, 2267 insertions(+) create mode 100644 test/language/expressions/call/scope-lex-close.js create mode 100644 test/language/expressions/call/scope-lex-open.js create mode 100644 test/language/expressions/call/scope-var-close.js create mode 100644 test/language/expressions/call/scope-var-open.js create mode 100644 test/language/expressions/class/scope-name-lex-close.js create mode 100644 test/language/expressions/class/scope-name-lex-open-heritage.js create mode 100644 test/language/expressions/class/scope-name-lex-open-no-heritage.js create mode 100644 test/language/expressions/function/scope-body-lex-distinct.js create mode 100644 test/language/expressions/function/scope-name-var-close.js create mode 100644 test/language/expressions/function/scope-name-var-open-non-strict.js create mode 100644 test/language/expressions/function/scope-name-var-open-strict.js create mode 100644 test/language/expressions/function/scope-param-elem-var-close.js create mode 100644 test/language/expressions/function/scope-param-elem-var-open.js create mode 100644 test/language/expressions/function/scope-param-rest-elem-var-close.js create mode 100644 test/language/expressions/function/scope-param-rest-elem-var-open.js create mode 100644 test/language/expressions/function/scope-paramsbody-var-close.js create mode 100644 test/language/expressions/function/scope-paramsbody-var-open.js create mode 100644 test/language/expressions/generators/scope-name-var-close.js create mode 100644 test/language/expressions/generators/scope-name-var-open-non-strict.js create mode 100644 test/language/expressions/generators/scope-name-var-open-strict.js create mode 100644 test/language/statements/block/scope-lex-close.js create mode 100644 test/language/statements/block/scope-lex-open.js create mode 100644 test/language/statements/block/scope-var-none.js create mode 100644 test/language/statements/class/scope-name-lex-close.js create mode 100644 test/language/statements/class/scope-name-lex-open-heritage.js create mode 100644 test/language/statements/class/scope-name-lex-open-no-heritage.js create mode 100644 test/language/statements/for-in/scope-body-lex-boundary.js create mode 100644 test/language/statements/for-in/scope-body-lex-close.js create mode 100644 test/language/statements/for-in/scope-body-lex-open.js create mode 100644 test/language/statements/for-in/scope-body-var-none.js create mode 100644 test/language/statements/for-in/scope-head-lex-close.js create mode 100644 test/language/statements/for-in/scope-head-lex-open.js create mode 100644 test/language/statements/for-in/scope-head-var-none.js create mode 100644 test/language/statements/for-of/scope-body-lex-boundary.js create mode 100644 test/language/statements/for-of/scope-body-lex-close.js create mode 100644 test/language/statements/for-of/scope-body-lex-open.js create mode 100644 test/language/statements/for-of/scope-body-var-none.js create mode 100644 test/language/statements/for-of/scope-head-lex-close.js create mode 100644 test/language/statements/for-of/scope-head-lex-open.js create mode 100644 test/language/statements/for-of/scope-head-var-none.js create mode 100644 test/language/statements/for/scope-body-lex-boundary.js create mode 100644 test/language/statements/for/scope-body-lex-open.js create mode 100644 test/language/statements/for/scope-body-var-none.js create mode 100644 test/language/statements/for/scope-head-lex-close.js create mode 100644 test/language/statements/for/scope-head-lex-open.js create mode 100644 test/language/statements/for/scope-head-var-none.js create mode 100644 test/language/statements/switch/scope-lex-close-case.js create mode 100644 test/language/statements/switch/scope-lex-close-dflt.js create mode 100644 test/language/statements/switch/scope-lex-open-case.js create mode 100644 test/language/statements/switch/scope-lex-open-dflt.js create mode 100644 test/language/statements/switch/scope-var-none-case.js create mode 100644 test/language/statements/switch/scope-var-none-dflt.js create mode 100644 test/language/statements/try/scope-catch-block-lex-close.js create mode 100644 test/language/statements/try/scope-catch-block-lex-open.js create mode 100644 test/language/statements/try/scope-catch-block-var-none.js create mode 100644 test/language/statements/try/scope-catch-param-lex-close.js create mode 100644 test/language/statements/try/scope-catch-param-lex-open.js create mode 100644 test/language/statements/try/scope-catch-param-var-none.js create mode 100644 test/language/statements/with/scope-var-close.js create mode 100644 test/language/statements/with/scope-var-open.js diff --git a/test/language/expressions/call/scope-lex-close.js b/test/language/expressions/call/scope-lex-close.js new file mode 100644 index 0000000000..a9f048cbc7 --- /dev/null +++ b/test/language/expressions/call/scope-lex-close.js @@ -0,0 +1,30 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-ecmascript-function-objects-call-thisargument-argumentslist +description: > + Removal of lexical environment for the function parameters and body +info: | + [...] + 3. Let callerContext be the running execution context. + [...] + 8. Remove calleeContext from the execution context stack and restore + callerContext as the running execution context. + [...] +features: [let] +---*/ + +var probe; + +// This test intentionally elides parameter expressions because their presence +// triggers the creation of an additional LexicalEnvironment dedicated to the +// function body (see sec-functiondeclarationinstantiation) +(function() { + let x = 'inside'; + probe = function() { return x; }; +}()); + +var x = 'outside'; + +assert.sameValue(probe(), 'inside'); +assert.sameValue(x, 'outside'); diff --git a/test/language/expressions/call/scope-lex-open.js b/test/language/expressions/call/scope-lex-open.js new file mode 100644 index 0000000000..9f1e2cc1af --- /dev/null +++ b/test/language/expressions/call/scope-lex-open.js @@ -0,0 +1,39 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-ecmascript-function-objects-call-thisargument-argumentslist +description: > + Creation of new variable environment for the function parameters and body + (as disinct from that for the function's BindingIdentifier) +info: | + [...] + 3. Let callerContext be the running execution context. + 4. Let calleeContext be PrepareForOrdinaryCall(F, undefined). + [...] + + 9.2.1.1 PrepareForOrdinaryCall + + [...] + 8. Let localEnv be NewFunctionEnvironment(F, newTarget). + 9. Set the LexicalEnvironment of calleeContext to localEnv. + 10. Set the VariableEnvironment of calleeContext to localEnv. + [...] +features: [let] +---*/ + +var name = 'outside'; +var probeBefore = function() { return name; }; +var probeInside; + +// This test intentionally elides parameter expressions because their presence +// triggers the creation of an additional LexicalEnvironment dedicated to the +// function body (see sec-functiondeclarationinstantiation) +var func = function name() { + let name = 'inside'; + probeInside = function() { return name; }; +}; + +func(); + +assert.sameValue(probeBefore(), 'outside'); +assert.sameValue(probeInside(), 'inside'); diff --git a/test/language/expressions/call/scope-var-close.js b/test/language/expressions/call/scope-var-close.js new file mode 100644 index 0000000000..5a76a49ea5 --- /dev/null +++ b/test/language/expressions/call/scope-var-close.js @@ -0,0 +1,29 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-prepareforordinarycall +description: > + Removal of variable environment for the function parameters and body +info: | + [...] + 3. Let callerContext be the running execution context. + [...] + 8. Remove calleeContext from the execution context stack and restore + callerContext as the running execution context. + [...] +---*/ + +var probe; + +// This test intentionally elides parameter expressions because their presence +// triggers the creation of an additional LexicalEnvironment dedicated to the +// function body (see sec-functiondeclarationinstantiation) +(function() { + var x = 'inside'; + probe = function() { return x; }; +}()); + +var x = 'outside'; + +assert.sameValue(probe(), 'inside'); +assert.sameValue(x, 'outside'); diff --git a/test/language/expressions/call/scope-var-open.js b/test/language/expressions/call/scope-var-open.js new file mode 100644 index 0000000000..a50cc1e2c9 --- /dev/null +++ b/test/language/expressions/call/scope-var-open.js @@ -0,0 +1,41 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-prepareforordinarycall +description: > + Creation of new variable environment for the function parameters and body + (as disinct from that for the function's BindingIdentifier) +info: | + [...] + 3. Let callerContext be the running execution context. + 4. Let calleeContext be PrepareForOrdinaryCall(F, undefined). + [...] + + 9.2.1.1 PrepareForOrdinaryCall + + [...] + 8. Let localEnv be NewFunctionEnvironment(F, newTarget). + 9. Set the LexicalEnvironment of calleeContext to localEnv. + 10. Set the VariableEnvironment of calleeContext to localEnv. + [...] +---*/ + +var name = 'outside'; +var probeBefore = function() { return name; }; +var probeBody; + +// This test intentionally elides parameter expressions because their presence +// triggers the creation of an additional LexicalEnvironment dedicated to the +// function body (see sec-functiondeclarationinstantiation) +var func = function name() { + // The initializer is intentionally omitted from the following + // VariableStatement in order to demonstrate that a new binding is created + // (and not simply re-used from the FunctionExpression's BindingIdentifier). + var name; + probeBody = function() { return name; }; +}; + +func(); + +assert.sameValue(probeBefore(), 'outside'); +assert.sameValue(probeBody(), undefined); diff --git a/test/language/expressions/class/scope-name-lex-close.js b/test/language/expressions/class/scope-name-lex-close.js new file mode 100644 index 0000000000..4776a1e314 --- /dev/null +++ b/test/language/expressions/class/scope-name-lex-close.js @@ -0,0 +1,21 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-runtime-semantics-classdefinitionevaluation +description: Removal of lexical environment for class "name" +info: | + [...] + 22. Set the running execution context's LexicalEnvironment to lex. + [...] +---*/ + +var C = 'outside'; + +var cls = class C { + method() { + return C; + } +}; + +assert.sameValue(cls.prototype.method(), cls, 'from instance method'); +assert.sameValue(C, 'outside'); diff --git a/test/language/expressions/class/scope-name-lex-open-heritage.js b/test/language/expressions/class/scope-name-lex-open-heritage.js new file mode 100644 index 0000000000..e7d16fb498 --- /dev/null +++ b/test/language/expressions/class/scope-name-lex-open-heritage.js @@ -0,0 +1,37 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-runtime-semantics-classdefinitionevaluation +description: > + Creation of new lexical environment for the class "name" (with a heritage) +info: | + 1. Let lex be the LexicalEnvironment of the running execution context. + 2. Let classScope be NewDeclarativeEnvironment(lex). + 3. Let classScopeEnvRec be classScope's EnvironmentRecord. + 4. If className is not undefined, then + a. Perform classScopeEnvRec.CreateImmutableBinding(className, true). + 5. If ClassHeritageopt is not present, then + [...] + 6. Else, + a. Set the running execution context's LexicalEnvironment to classScope. + [...] +---*/ + +var probeBefore = function() { return C; }; +var probeHeritage, setHeritage; +var C = 'outside'; + +var cls = class C extends ( + probeHeritage = function() { return C; }, + setHeritage = function() { C = null; } + ) { + method() { + return C; + } +}; + +assert.sameValue(probeBefore(), 'outside'); +assert.sameValue(probeHeritage(), cls, 'from class heritage'); +assert.throws(TypeError, setHeritage, 'inner binding rejects modification'); +assert.sameValue(probeHeritage(), cls, 'inner binding is immutable'); +assert.sameValue(cls.prototype.method(), cls, 'from instance method'); diff --git a/test/language/expressions/class/scope-name-lex-open-no-heritage.js b/test/language/expressions/class/scope-name-lex-open-no-heritage.js new file mode 100644 index 0000000000..2717b51b58 --- /dev/null +++ b/test/language/expressions/class/scope-name-lex-open-no-heritage.js @@ -0,0 +1,39 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-runtime-semantics-classdefinitionevaluation +description: > + Creation of new lexical environment for the class "name" (without a + heritage) +info: | + 1. Let lex be the LexicalEnvironment of the running execution context. + 2. Let classScope be NewDeclarativeEnvironment(lex). + 3. Let classScopeEnvRec be classScope's EnvironmentRecord. + 4. If className is not undefined, then + a. Perform classScopeEnvRec.CreateImmutableBinding(className, true). + 5. If ClassHeritageopt is not present, then + [...] + 6. Else, + a. Set the running execution context's LexicalEnvironment to classScope. + [...] + 11. Set the running execution context's LexicalEnvironment to classScope. +---*/ + +var probeBefore = function() { return C; }; +var C = 'outside'; + +var cls = class C { + probe() { + return C; + } + modify() { + C = null; + } +}; + +assert.sameValue(probeBefore(), 'outside'); +assert.sameValue(cls.prototype.probe(), cls, 'inner binding value'); +assert.throws( + TypeError, cls.prototype.modify, 'inner binding rejects modification' +); +assert.sameValue(cls.prototype.probe(), cls, 'inner binding is immutable'); diff --git a/test/language/expressions/function/scope-body-lex-distinct.js b/test/language/expressions/function/scope-body-lex-distinct.js new file mode 100644 index 0000000000..3fbaa973c9 --- /dev/null +++ b/test/language/expressions/function/scope-body-lex-distinct.js @@ -0,0 +1,49 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-functiondeclarationinstantiation +description: > + Creation of new lexical environment (distinct from the variable + environment) for the function body outside of strict mode +info: | + [...] + 29. If strict is false, then + a. Let lexEnv be NewDeclarativeEnvironment(varEnv). + b. NOTE: Non-strict functions use a separate lexical Environment Record + for top-level lexical declarations so that a direct eval can + determine whether any var scoped declarations introduced by the eval + code conflict with pre-existing top-level lexically scoped + declarations. This is not needed for strict functions because a + strict direct eval always places all declarations into a new + Environment Record. + [...] + + 18.2.1.3 Runtime Semantics: EvalDeclarationInstantiation + + [...] + 5. If strict is false, then + [...] + b. Let thisLex be lexEnv. + c. Assert: The following loop will terminate. + d. Repeat while thisLex is not the same as varEnv, + i. Let thisEnvRec be thisLex's EnvironmentRecord. + ii. If thisEnvRec is not an object Environment Record, then + 1. NOTE: The environment of with statements cannot contain any + lexical declaration so it doesn't need to be checked for + var/let hoisting conflicts. + 2. For each name in varNames, do + a. If thisEnvRec.HasBinding(name) is true, then + i. Throw a SyntaxError exception. + ii. NOTE: Annex B.3.5 defines alternate semantics for the + above step. + b. NOTE: A direct eval will not hoist var declaration over a + like-named lexical declaration. + iii. Let thisLex be thisLex's outer environment reference. +flags: [noStrict] +features: [let] +---*/ + +assert.throws(SyntaxError, function() { + let x; + eval('var x;'); +}); diff --git a/test/language/expressions/function/scope-name-var-close.js b/test/language/expressions/function/scope-name-var-close.js new file mode 100644 index 0000000000..c119ca2771 --- /dev/null +++ b/test/language/expressions/function/scope-name-var-close.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function-definitions-runtime-semantics-evaluation +description: Removal of variable environment for the BindingIdentifier +info: | + [...] + 2. Let scope be the running execution context's LexicalEnvironment. + 3. Let funcEnv be NewDeclarativeEnvironment(scope). + 4. Let envRec be funcEnv's EnvironmentRecord. + 5. Let name be StringValue of BindingIdentifier. + 6. Perform envRec.CreateImmutableBinding(name, false). + 7. Let closure be FunctionCreate(Normal, FormalParameters, FunctionBody, + funcEnv, strict). + [...] +---*/ + +var probe; + +var func = function f() { + probe = function() { return f; }; +}; +var f = 'outside'; + +func(); + +assert.sameValue(f, 'outside'); +assert.sameValue(probe(), func); diff --git a/test/language/expressions/function/scope-name-var-open-non-strict.js b/test/language/expressions/function/scope-name-var-open-non-strict.js new file mode 100644 index 0000000000..4b85cf4ec8 --- /dev/null +++ b/test/language/expressions/function/scope-name-var-open-non-strict.js @@ -0,0 +1,50 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function-definitions-runtime-semantics-evaluation +description: > + Creation of new variable environment for the BindingIdentifier + parameter +info: | + [...] + 2. Let scope be the running execution context's LexicalEnvironment. + 3. Let funcEnv be NewDeclarativeEnvironment(scope). + 4. Let envRec be funcEnv's EnvironmentRecord. + 5. Let name be StringValue of BindingIdentifier. + 6. Perform envRec.CreateImmutableBinding(name, false). + 7. Let closure be FunctionCreate(Normal, FormalParameters, FunctionBody, + funcEnv, strict). + [...] +flags: [noStrict] +---*/ + +var f = 'outside'; +var probeBefore = function() { return f; }; +var setBefore = function() { f = null; }; +var probeParams, setParams, probeBody, setBody; + +var func = function f( + _ = ( + probeParams = function() { return f; }, + setParams = function() { f = null; } + ) + ) { + probeBody = function() { return f; }; + setBody = function() { f = null; }; +}; + +func(); + +assert.sameValue(probeBefore(), 'outside'); +setBefore(); +assert.sameValue(probeBefore(), null); + +assert.sameValue(probeParams(), func, 'inner binding value (from parameters)'); +setParams(); +assert.sameValue( + probeParams(), func, 'inner binding is immutable (from parameters)' +); + +assert.sameValue(probeBody(), func, 'inner binding value (from body)'); +setBody(); +assert.sameValue(probeBody(), func, 'inner binding is immutable (from body)'); diff --git a/test/language/expressions/function/scope-name-var-open-strict.js b/test/language/expressions/function/scope-name-var-open-strict.js new file mode 100644 index 0000000000..0eeb49d3c1 --- /dev/null +++ b/test/language/expressions/function/scope-name-var-open-strict.js @@ -0,0 +1,54 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function-definitions-runtime-semantics-evaluation +description: > + Creation of new variable environment for the BindingIdentifier + parameter +info: | + [...] + 2. Let scope be the running execution context's LexicalEnvironment. + 3. Let funcEnv be NewDeclarativeEnvironment(scope). + 4. Let envRec be funcEnv's EnvironmentRecord. + 5. Let name be StringValue of BindingIdentifier. + 6. Perform envRec.CreateImmutableBinding(name, false). + 7. Let closure be FunctionCreate(Normal, FormalParameters, FunctionBody, + funcEnv, strict). + [...] +flags: [onlyStrict] +---*/ + +var f = 'outside'; +var probeBefore = function() { return f; }; +var setBefore = function() { f = null; }; +var probeParams, setParams, probeBody, setBody; + +var func = function f( + _ = ( + probeParams = function() { return f; }, + setParams = function() { f = null; } + ) + ) { + probeBody = function() { return f; }; + setBody = function() { f = null; }; +}; + +func(); + +assert.sameValue(probeBefore(), 'outside'); +setBefore(); +assert.sameValue(probeBefore(), null); + +assert.sameValue(probeParams(), func, 'inner binding value (from parameters)'); +assert.throws( + TypeError, setParams, 'inner binding rejects modification (from parameters)' +); +assert.sameValue( + probeParams(), func, 'inner binding is immutable (from parameters)' +); + +assert.sameValue(probeBody(), func, 'inner binding value (from body)'); +assert.throws( + TypeError, setBody, 'inner binding rejects modification (from body)' +); +assert.sameValue(probeBody(), func, 'inner binding is immutable (from body)'); diff --git a/test/language/expressions/function/scope-param-elem-var-close.js b/test/language/expressions/function/scope-param-elem-var-close.js new file mode 100644 index 0000000000..4b7ffe8bc0 --- /dev/null +++ b/test/language/expressions/function/scope-param-elem-var-close.js @@ -0,0 +1,32 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function-definitions-runtime-semantics-iteratorbindinginitialization +description: > + Removal of variable environment for each BindingElement formal parameter +info: | + [...] + 6. Let paramVarEnv be NewDeclarativeEnvironment(originalEnv). + 7. Set the VariableEnvironment of currentContext to paramVarEnv. + 8. Set the LexicalEnvironment of currentContext to paramVarEnv. + 9. Let result be the result of performing IteratorBindingInitialization for + BindingElement using iteratorRecord and environment as the arguments. + 10. Set the VariableEnvironment of currentContext to originalEnv. + 11. Set the LexicalEnvironment of currentContext to originalEnv. + [...] +flags: [noStrict] +---*/ + +var x = 'outside'; +var probe1, probe2, probeBody; + +(function( + _ = (eval('var x = "inside";'), probe1 = function() { return x; }), + __ = probe2 = function() { return x; } + ) { + probeBody = function() { return x; }; +}()); + +assert.sameValue(probe1(), 'inside'); +assert.sameValue(probe2(), 'outside'); +assert.sameValue(probeBody(), 'outside'); diff --git a/test/language/expressions/function/scope-param-elem-var-open.js b/test/language/expressions/function/scope-param-elem-var-open.js new file mode 100644 index 0000000000..5306666a70 --- /dev/null +++ b/test/language/expressions/function/scope-param-elem-var-open.js @@ -0,0 +1,31 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function-definitions-runtime-semantics-iteratorbindinginitialization +description: > + Creation of new variable environment for each BindingElement formal + parameter +info: | + [...] + 6. Let paramVarEnv be NewDeclarativeEnvironment(originalEnv). + 7. Set the VariableEnvironment of currentContext to paramVarEnv. + 8. Set the LexicalEnvironment of currentContext to paramVarEnv. + 9. Let result be the result of performing IteratorBindingInitialization for + BindingElement using iteratorRecord and environment as the arguments. + 10. Set the VariableEnvironment of currentContext to originalEnv. + 11. Set the LexicalEnvironment of currentContext to originalEnv. + [...] +flags: [noStrict] +---*/ + +var x = 'outside'; +var probe1, probe2; + +(function( + _ = probe1 = function() { return x; }, + __ = (eval('var x = "inside";'), probe2 = function() { return x; }) + ) { +}()); + +assert.sameValue(probe1(), 'outside'); +assert.sameValue(probe2(), 'inside'); diff --git a/test/language/expressions/function/scope-param-rest-elem-var-close.js b/test/language/expressions/function/scope-param-rest-elem-var-close.js new file mode 100644 index 0000000000..413efdba4d --- /dev/null +++ b/test/language/expressions/function/scope-param-rest-elem-var-close.js @@ -0,0 +1,36 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function-definitions-runtime-semantics-iteratorbindinginitialization +description: > + Removal of variable environment for the BindingRestElement formal parameter +info: | + [...] + 2. Let currentContext be the running execution context. + 3. Let originalEnv be the VariableEnvironment of currentContext. + 4. Assert: The VariableEnvironment and LexicalEnvironment of currentContext + are the same. + 5. Assert: environment and originalEnv are the same. + 6. Let paramVarEnv be NewDeclarativeEnvironment(originalEnv). + 7. Set the VariableEnvironment of currentContext to paramVarEnv. + 8. Set the LexicalEnvironment of currentContext to paramVarEnv. + 9. Let result be the result of performing IteratorBindingInitialization for + BindingRestElement using iteratorRecord and environment as the + arguments. + 10. Set the VariableEnvironment of currentContext to originalEnv. + 11. Set the LexicalEnvironment of currentContext to originalEnv. + [...] +flags: [noStrict] +---*/ + +var x = 'outside'; +var probeParam, probeBody; + +(function( + ...[_ = (eval('var x = "inside";'), probeParam = function() { return x; })] + ) { + probeBody = function() { return x; } +}()); + +assert.sameValue(probeParam(), 'inside'); +assert.sameValue(probeBody(), 'outside'); diff --git a/test/language/expressions/function/scope-param-rest-elem-var-open.js b/test/language/expressions/function/scope-param-rest-elem-var-open.js new file mode 100644 index 0000000000..dcac19412c --- /dev/null +++ b/test/language/expressions/function/scope-param-rest-elem-var-open.js @@ -0,0 +1,36 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function-definitions-runtime-semantics-iteratorbindinginitialization +description: > + Creation of new variable environment for the BindingRestElement formal + parameter +info: | + [...] + 2. Let currentContext be the running execution context. + 3. Let originalEnv be the VariableEnvironment of currentContext. + 4. Assert: The VariableEnvironment and LexicalEnvironment of currentContext + are the same. + 5. Assert: environment and originalEnv are the same. + 6. Let paramVarEnv be NewDeclarativeEnvironment(originalEnv). + 7. Set the VariableEnvironment of currentContext to paramVarEnv. + 8. Set the LexicalEnvironment of currentContext to paramVarEnv. + 9. Let result be the result of performing IteratorBindingInitialization for + BindingRestElement using iteratorRecord and environment as the arguments. + 10. Set the VariableEnvironment of currentContext to originalEnv. + 11. Set the LexicalEnvironment of currentContext to originalEnv. + [...] +flags: [noStrict] +---*/ + +var x = 'outside'; +var probe1, probe2; + +(function( + _ = probe1 = function() { return x; }, + ...[__ = (eval('var x = "inside";'), probe2 = function() { return x; })] + ) { +}()); + +assert.sameValue(probe1(), 'outside'); +assert.sameValue(probe2(), 'inside'); diff --git a/test/language/expressions/function/scope-paramsbody-var-close.js b/test/language/expressions/function/scope-paramsbody-var-close.js new file mode 100644 index 0000000000..147c303a17 --- /dev/null +++ b/test/language/expressions/function/scope-paramsbody-var-close.js @@ -0,0 +1,34 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-functiondeclarationinstantiation +description: > + Removal of variable environment for the function body +info: | + [...] + 26. If hasParameterExpressions is false, then + [...] + 27. Else, + a. NOTE A separate Environment Record is needed to ensure that closures + created by expressions in the formal parameter list do not have + visibility of declarations in the function body. + b. Let varEnv be NewDeclarativeEnvironment(env). + c. Let varEnvRec be varEnv's EnvironmentRecord. + d. Set the VariableEnvironment of calleeContext to varEnv. + e. Let instantiatedVarNames be a new empty List. + [...] +---*/ + +var probe; + +// A parameter expression is necessary to trigger the creation of the scope +// under test. +(function(_ = null) { + var x = 'inside'; + probe = function() { return x; }; +}()); + +var x = 'outside'; + +assert.sameValue(probe(), 'inside'); +assert.sameValue(x, 'outside'); diff --git a/test/language/expressions/function/scope-paramsbody-var-open.js b/test/language/expressions/function/scope-paramsbody-var-open.js new file mode 100644 index 0000000000..dc01b5e921 --- /dev/null +++ b/test/language/expressions/function/scope-paramsbody-var-open.js @@ -0,0 +1,32 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-functiondeclarationinstantiation +description: > + Creation of new variable environment for the function body (as disinct from + that for the function's parameters) +info: | + [...] + 26. If hasParameterExpressions is false, then + [...] + 27. Else, + a. NOTE A separate Environment Record is needed to ensure that closures + created by expressions in the formal parameter list do not have + visibility of declarations in the function body. + b. Let varEnv be NewDeclarativeEnvironment(env). + c. Let varEnvRec be varEnv's EnvironmentRecord. + d. Set the VariableEnvironment of calleeContext to varEnv. + e. Let instantiatedVarNames be a new empty List. + [...] +---*/ + +var x = 'outside'; +var probeParams, probeBody; + +(function(_ = probeParams = function() { return x; }) { + var x = 'inside'; + probeBody = function() { return x; }; +}()); + +assert.sameValue(probeParams(), 'outside'); +assert.sameValue(probeBody(), 'inside'); diff --git a/test/language/expressions/generators/scope-name-var-close.js b/test/language/expressions/generators/scope-name-var-close.js new file mode 100644 index 0000000000..b163c1c013 --- /dev/null +++ b/test/language/expressions/generators/scope-name-var-close.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +description: Removal of variable environment for the BindingIdentifier +info: | + [...] + 2. Let scope be the running execution context's LexicalEnvironment. + 3. Let funcEnv be NewDeclarativeEnvironment(scope). + 4. Let envRec be funcEnv's EnvironmentRecord. + 5. Let name be StringValue of BindingIdentifier. + 6. Perform envRec.CreateImmutableBinding(name, false). + 7. Let closure be GeneratorFunctionCreate(Normal, FormalParameters, + GeneratorBody, funcEnv, strict). + [...] +---*/ + +var probe; + +var func = function* g() { + probe = function() { return g; }; +}; +var g = 'outside'; + +func().next(); + +assert.sameValue(g, 'outside'); +assert.sameValue(probe(), func); diff --git a/test/language/expressions/generators/scope-name-var-open-non-strict.js b/test/language/expressions/generators/scope-name-var-open-non-strict.js new file mode 100644 index 0000000000..f15ae6c498 --- /dev/null +++ b/test/language/expressions/generators/scope-name-var-open-non-strict.js @@ -0,0 +1,50 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +description: > + Creation of new variable environment for the BindingIdentifier + parameter +info: | + [...] + 2. Let scope be the running execution context's LexicalEnvironment. + 3. Let funcEnv be NewDeclarativeEnvironment(scope). + 4. Let envRec be funcEnv's EnvironmentRecord. + 5. Let name be StringValue of BindingIdentifier. + 6. Perform envRec.CreateImmutableBinding(name, false). + 7. Let closure be GeneratorFunctionCreate(Normal, FormalParameters, + GeneratorBody, funcEnv, strict). + [...] +flags: [noStrict] +---*/ + +var g = 'outside'; +var probeBefore = function() { return g; }; +var setBefore = function() { g = null; }; +var probeParams, setParams, probeBody, setBody; + +var func = function* g( + _ = ( + probeParams = function() { return g; }, + setParams = function() { g = null; } + ) + ) { + probeBody = function() { return g; }; + setBody = function() { g = null; }; +}; + +func().next(); + +assert.sameValue(probeBefore(), 'outside'); +setBefore(); +assert.sameValue(probeBefore(), null); + +assert.sameValue(probeParams(), func, 'inner binding value (from parameters)'); +setParams(); +assert.sameValue( + probeParams(), func, 'inner binding is immutable (from parameters)' +); + +assert.sameValue(probeBody(), func, 'inner binding value (from body)'); +setBody(); +assert.sameValue(probeBody(), func, 'inner binding is immutable (from body)'); diff --git a/test/language/expressions/generators/scope-name-var-open-strict.js b/test/language/expressions/generators/scope-name-var-open-strict.js new file mode 100644 index 0000000000..2ba37c432a --- /dev/null +++ b/test/language/expressions/generators/scope-name-var-open-strict.js @@ -0,0 +1,54 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +description: > + Creation of new variable environment for the BindingIdentifier + parameter +info: | + [...] + 2. Let scope be the running execution context's LexicalEnvironment. + 3. Let funcEnv be NewDeclarativeEnvironment(scope). + 4. Let envRec be funcEnv's EnvironmentRecord. + 5. Let name be StringValue of BindingIdentifier. + 6. Perform envRec.CreateImmutableBinding(name, false). + 7. Let closure be GeneratorFunctionCreate(Normal, FormalParameters, + GeneratorBody, funcEnv, strict). + [...] +flags: [onlyStrict] +---*/ + +var g = 'outside'; +var probeBefore = function() { return g; }; +var setBefore = function() { g = null; }; +var probeParams, setParams, probeBody, setBody; + +var func = function* g( + _ = ( + probeParams = function() { return g; }, + setParams = function() { g = null; } + ) + ) { + probeBody = function() { return g; }; + setBody = function() { g = null; }; +}; + +func().next(); + +assert.sameValue(probeBefore(), 'outside'); +setBefore(); +assert.sameValue(probeBefore(), null); + +assert.sameValue(probeParams(), func, 'inner binding value (from parameters)'); +assert.throws( + TypeError, setParams, 'inner binding rejects modification (from parameters)' +); +assert.sameValue( + probeParams(), func, 'inner binding is immutable (from parameters)' +); + +assert.sameValue(probeBody(), func, 'inner binding value (from body)'); +assert.throws( + TypeError, setBody, 'inner binding rejects modification (from body)' +); +assert.sameValue(probeBody(), func, 'inner binding is immutable (from body)'); diff --git a/test/language/statements/block/scope-lex-close.js b/test/language/statements/block/scope-lex-close.js new file mode 100644 index 0000000000..b4b304b54e --- /dev/null +++ b/test/language/statements/block/scope-lex-close.js @@ -0,0 +1,27 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-block-runtime-semantics-evaluation +description: Removal of lexical environment for BlockStatement +info: | + 1. Let oldEnv be the running execution context's LexicalEnvironment. + 2. Let blockEnv be NewDeclarativeEnvironment(oldEnv). + 3. Perform BlockDeclarationInstantiation(StatementList, blockEnv). + 4. Set the running execution context's LexicalEnvironment to blockEnv. + 5. Let blockValue be the result of evaluating StatementList. + 6. Set the running execution context's LexicalEnvironment to oldEnv. + 7. Return blockValue. +features: [let] +---*/ + +var probe; + +{ + let x = 'inside'; + probe = function() { return x; }; +} + +let x = 'outside'; + +assert.sameValue(x, 'outside'); +assert.sameValue(probe(), 'inside'); diff --git a/test/language/statements/block/scope-lex-open.js b/test/language/statements/block/scope-lex-open.js new file mode 100644 index 0000000000..5568c62729 --- /dev/null +++ b/test/language/statements/block/scope-lex-open.js @@ -0,0 +1,26 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-block-runtime-semantics-evaluation +description: Creation of new lexical environment for BlockStatement +info: | + 1. Let oldEnv be the running execution context's LexicalEnvironment. + 2. Let blockEnv be NewDeclarativeEnvironment(oldEnv). + 3. Perform BlockDeclarationInstantiation(StatementList, blockEnv). + 4. Set the running execution context's LexicalEnvironment to blockEnv. + 5. Let blockValue be the result of evaluating StatementList. + [...] +features: [let] +---*/ + +let x = 'outside'; +var probeBefore = function() { return x; }; +var probeInside; + +{ + let x = 'inside'; + probeInside = function() { return x; }; +} + +assert.sameValue(probeBefore(), 'outside'); +assert.sameValue(probeInside(), 'inside'); diff --git a/test/language/statements/block/scope-var-none.js b/test/language/statements/block/scope-var-none.js new file mode 100644 index 0000000000..5d1c0862fb --- /dev/null +++ b/test/language/statements/block/scope-var-none.js @@ -0,0 +1,27 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-block-runtime-semantics-evaluation +description: Retainment of existing variable environment for BlockStatement +info: | + 1. Let oldEnv be the running execution context's LexicalEnvironment. + 2. Let blockEnv be NewDeclarativeEnvironment(oldEnv). + 3. Perform BlockDeclarationInstantiation(StatementList, blockEnv). + 4. Set the running execution context's LexicalEnvironment to blockEnv. + 5. Let blockValue be the result of evaluating StatementList. + 6. Set the running execution context's LexicalEnvironment to oldEnv. + 7. Return blockValue. +---*/ + +var x = 'outside'; +var probeBefore = function() { return x; }; +var probeInside; + +{ + var x = 'inside'; + probeInside = function() { return x; }; +} + +assert.sameValue(probeBefore(), 'inside', 'reference preceeding statement'); +assert.sameValue(probeInside(), 'inside', 'reference within statement'); +assert.sameValue(x, 'inside', 'reference following statement'); diff --git a/test/language/statements/class/scope-name-lex-close.js b/test/language/statements/class/scope-name-lex-close.js new file mode 100644 index 0000000000..a6dedfd9ab --- /dev/null +++ b/test/language/statements/class/scope-name-lex-close.js @@ -0,0 +1,22 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-runtime-semantics-classdefinitionevaluation +description: Removal of lexical environment for class "name" +info: | + [...] + 22. Set the running execution context's LexicalEnvironment to lex. + [...] +---*/ + +class C { + method() { + return C; + } +} + +var cls = C; +assert.sameValue(typeof C, 'function'); +C = null; +assert.sameValue(C, null); +assert.sameValue(cls.prototype.method(), cls, 'from instance method'); diff --git a/test/language/statements/class/scope-name-lex-open-heritage.js b/test/language/statements/class/scope-name-lex-open-heritage.js new file mode 100644 index 0000000000..d844fd2c60 --- /dev/null +++ b/test/language/statements/class/scope-name-lex-open-heritage.js @@ -0,0 +1,46 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-runtime-semantics-classdefinitionevaluation +description: > + Creation of new lexical environment for the class "name" (with a heritage) +info: | + 1. Let lex be the LexicalEnvironment of the running execution context. + 2. Let classScope be NewDeclarativeEnvironment(lex). + 3. Let classScopeEnvRec be classScope's EnvironmentRecord. + 4. If className is not undefined, then + a. Perform classScopeEnvRec.CreateImmutableBinding(className, true). + 5. If ClassHeritageopt is not present, then + [...] + 6. Else, + a. Set the running execution context's LexicalEnvironment to classScope. + [...] +---*/ + +var setBefore = function() { C = null; }; +var probeBefore = function() { return C; }; +var probeHeritage, setHeritage; + +class C extends ( + probeHeritage = function() { return C; }, + setHeritage = function() { C = null; } + ) { + method() { + return C; + } +}; + +var cls = probeBefore(); +assert.sameValue(typeof cls, 'function'); +setBefore(); +assert.sameValue(probeBefore(), null); +assert.sameValue(probeHeritage(), cls, 'inner binding is independent'); +assert.throws( + TypeError, setHeritage, 'inner binding rejects modification' +); +assert.sameValue( + typeof probeHeritage(), 'function', 'inner binding is immutable' +); +assert.sameValue( + typeof cls.prototype.method(), 'function', 'from instance method' +); diff --git a/test/language/statements/class/scope-name-lex-open-no-heritage.js b/test/language/statements/class/scope-name-lex-open-no-heritage.js new file mode 100644 index 0000000000..87da14db01 --- /dev/null +++ b/test/language/statements/class/scope-name-lex-open-no-heritage.js @@ -0,0 +1,45 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-runtime-semantics-classdefinitionevaluation +description: > + Creation of new lexical environment for the class "name" (without a + heritage) +info: | + 1. Let lex be the LexicalEnvironment of the running execution context. + 2. Let classScope be NewDeclarativeEnvironment(lex). + 3. Let classScopeEnvRec be classScope's EnvironmentRecord. + 4. If className is not undefined, then + a. Perform classScopeEnvRec.CreateImmutableBinding(className, true). + 5. If ClassHeritageopt is not present, then + [...] + 6. Else, + a. Set the running execution context's LexicalEnvironment to classScope. + [...] + 11. Set the running execution context's LexicalEnvironment to classScope. +---*/ + +var probeBefore = function() { return C; }; +var setBefore = function() { C = null; }; + +class C { + probe() { + return C; + } + modify() { + C = null; + } +}; + +var cls = probeBefore(); +assert.sameValue(typeof cls, 'function'); +setBefore(); +assert.sameValue(probeBefore(), null); + +assert.sameValue(cls.prototype.probe(), cls, 'inner binding value'); +assert.throws( + TypeError, cls.prototype.modify, 'inner binding rejects modification' +); +assert.sameValue( + typeof cls.prototype.probe(), 'function', 'inner binding is immutable' +); diff --git a/test/language/statements/for-in/scope-body-lex-boundary.js b/test/language/statements/for-in/scope-body-lex-boundary.js new file mode 100644 index 0000000000..153442bd7d --- /dev/null +++ b/test/language/statements/for-in/scope-body-lex-boundary.js @@ -0,0 +1,50 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation +description: > + Creation of new lexical environment for each evaluation of the statement + body +info: | + IterationStatement : for ( ForDeclaration of AssignmentExpression ) Statement + + [...] + 2. Return ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, + lexicalBinding, labelSet). + + 13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation + + [...] + 5. Repeat + [...] + i. Let result be the result of evaluating stmt. + j. Set the running execution context's LexicalEnvironment to oldEnv. + k. If LoopContinues(result, labelSet) is false, return ? + IteratorClose(iterator, UpdateEmpty(result, V)). + l. If result.[[Value]] is not empty, let V be result.[[Value]]. +features: [let] +---*/ + +let x = 'outside'; +var probeFirst, probeSecond; + +for (let x in { a: 0, b: 0 }) + if (!probeFirst) + probeFirst = function() { return x; }; + else + probeSecond = function() { return x; }; + + +// 13.7.5.15 EnumerateObjectProperties +// +// > [...] The mechanics and order of enumerating the properties is not +// > specified [...] +assert.notSameValue(probeFirst(), probeSecond()); +assert( + probeFirst() === 'a' || probeFirst() === 'b', + 'First binding is either "a" or "b"' +); +assert( + probeSecond() === 'a' || probeSecond() === 'b', + 'Second binding is either "a" or "b"' +); diff --git a/test/language/statements/for-in/scope-body-lex-close.js b/test/language/statements/for-in/scope-body-lex-close.js new file mode 100644 index 0000000000..609369bbea --- /dev/null +++ b/test/language/statements/for-in/scope-body-lex-close.js @@ -0,0 +1,40 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation +description: > + Removal of lexical environment for the initial evaluation of the statement + body +info: | + IterationStatement : for ( ForDeclaration of AssignmentExpression ) Statement + + [...] + 2. Return ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, + lexicalBinding, labelSet). + + 13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation + + [...] + 5. Repeat + [...] + i. Let result be the result of evaluating stmt. + j. Set the running execution context's LexicalEnvironment to oldEnv. + k. If LoopContinues(result, labelSet) is false, return ? + IteratorClose(iterator, UpdateEmpty(result, V)). + l. If result.[[Value]] is not empty, let V be result.[[Value]]. +features: [let] +---*/ + +let x = 'outside'; +var probeDecl, probeBody; + +for ( + let [x, _ = probeDecl = function() { return x; }] + in + { i: 0 } + ) + probeBody = function() { return x; }; + +assert.sameValue(probeDecl(), 'i', 'reference from ForDeclaration'); +assert.sameValue(probeBody(), 'i', 'reference from statement body'); +assert.sameValue(x, 'outside'); diff --git a/test/language/statements/for-in/scope-body-lex-open.js b/test/language/statements/for-in/scope-body-lex-open.js new file mode 100644 index 0000000000..8dfda9f595 --- /dev/null +++ b/test/language/statements/for-in/scope-body-lex-open.js @@ -0,0 +1,48 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation +description: > + Creation of new lexical environment for the initial evaluation of the + statement body +info: | + IterationStatement : for ( ForDeclaration of AssignmentExpression ) Statement + + [...] + 2. Return ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, + lexicalBinding, labelSet). + + 13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation + + [...] + 5. Repeat + [...] + d. If lhsKind is either assignment or varBinding, then + [...] + e. Else, + i. Assert: lhsKind is lexicalBinding. + ii. Assert: lhs is a ForDeclaration. + iii. Let iterationEnv be NewDeclarativeEnvironment(oldEnv). + iv. Perform BindingInstantiation for lhs passing iterationEnv as the + argument. + v. Set the running execution context's LexicalEnvironment to + iterationEnv. + [...] +features: [let] +---*/ + +var probeBefore = function() { return x; }; +let x = 'outside'; +var probeExpr, probeDecl, probeBody; + +for ( + let [x, _ = probeDecl = function() { return x; }] + in + { i: probeExpr = function() { typeof x; }} + ) + probeBody = function() { return x; }; + +assert.sameValue(probeBefore(), 'outside'); +assert.throws(ReferenceError, probeExpr); +assert.sameValue(probeDecl(), 'i', 'reference from ForDeclaration'); +assert.sameValue(probeBody(), 'i', 'reference from statement body'); diff --git a/test/language/statements/for-in/scope-body-var-none.js b/test/language/statements/for-in/scope-body-var-none.js new file mode 100644 index 0000000000..23935da0b8 --- /dev/null +++ b/test/language/statements/for-in/scope-body-var-none.js @@ -0,0 +1,48 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation +description: No variable environment is created for the statement body +info: | + IterationStatement : for ( ForDeclaration of AssignmentExpression ) Statement + + [...] + 2. Return ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, + lexicalBinding, labelSet). + + 13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation + + [...] + 5. Repeat + [...] + d. If lhsKind is either assignment or varBinding, then + [...] + e. Else, + i. Assert: lhsKind is lexicalBinding. + ii. Assert: lhs is a ForDeclaration. + iii. Let iterationEnv be NewDeclarativeEnvironment(oldEnv). + iv. Perform BindingInstantiation for lhs passing iterationEnv as the + argument. + v. Set the running execution context's LexicalEnvironment to + iterationEnv. + [...] +features: [let] +---*/ + +var probeBefore = function() { return x; }; +var probeExpr, probeDecl, probeBody; +var x = 1; + +for ( + let [_ = probeDecl = function() { return x; }] + in + { '': probeExpr = function() { return x; }} + ) + var x = 2, __ = probeBody = function() { return x; }; + + +assert.sameValue(probeBefore(), 2, 'reference preceeding statement'); +assert.sameValue(probeExpr(), 2, 'reference from AssignmentExpression'); +assert.sameValue(probeDecl(), 2, 'reference from ForDeclaration'); +assert.sameValue(probeBody(), 2, 'reference from statement body'); +assert.sameValue(x, 2, 'reference following statement'); diff --git a/test/language/statements/for-in/scope-head-lex-close.js b/test/language/statements/for-in/scope-head-lex-close.js new file mode 100644 index 0000000000..a54e1a6f20 --- /dev/null +++ b/test/language/statements/for-in/scope-head-lex-close.js @@ -0,0 +1,44 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation +description: > + Removal of lexical environment to serve as a temporal dead zone for the + statement's AssignmentExpresson +info: | + IterationStatement : for ( ForDeclaration of AssignmentExpression ) Statement + + 1. Let keyResult be the result of performing ? + ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, + AssignmentExpression, iterate). + [...] + + 13.7.5.12 Runtime Semantics: ForIn/OfHeadEvaluation + + [...] + 2. If TDZnames is not an empty List, then + a. Assert: TDZnames has no duplicate entries. + b. Let TDZ be NewDeclarativeEnvironment(oldEnv). + c. Let TDZEnvRec be TDZ's EnvironmentRecord. + d. For each string name in TDZnames, do + i. Perform ! TDZEnvRec.CreateMutableBinding(name, false). + e. Set the running execution context's LexicalEnvironment to TDZ. + 3. Let exprRef be the result of evaluating expr. + 4. Set the running execution context's LexicalEnvironment to oldEnv. + [...] +features: [let] +---*/ + +let x = 'outside'; +var probeDecl, probeExpr, probeBody; + +for ( + let [x, _ = probeDecl = function() { return x; }] + in + { i: probeExpr = function() { typeof x; } } + ) + probeBody = function() { return x; }; + +assert.throws(ReferenceError, probeExpr); +assert.sameValue(probeDecl(), 'i', 'reference from ForDeclaration'); +assert.sameValue(probeBody(), 'i', 'reference from statement body'); diff --git a/test/language/statements/for-in/scope-head-lex-open.js b/test/language/statements/for-in/scope-head-lex-open.js new file mode 100644 index 0000000000..db1cabaac1 --- /dev/null +++ b/test/language/statements/for-in/scope-head-lex-open.js @@ -0,0 +1,38 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation +description: > + Creation of new lexical environment to serve as a temporal dead zone for + the statement's AssignmentExpresson +info: | + IterationStatement : for ( ForDeclaration of AssignmentExpression ) Statement + + 1. Let keyResult be the result of performing ? + ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, + AssignmentExpression, iterate). + [...] + + 13.7.5.12 Runtime Semantics: ForIn/OfHeadEvaluation + + [...] + 2. If TDZnames is not an empty List, then + a. Assert: TDZnames has no duplicate entries. + b. Let TDZ be NewDeclarativeEnvironment(oldEnv). + c. Let TDZEnvRec be TDZ's EnvironmentRecord. + d. For each string name in TDZnames, do + i. Perform ! TDZEnvRec.CreateMutableBinding(name, false). + e. Set the running execution context's LexicalEnvironment to TDZ. + 3. Let exprRef be the result of evaluating expr. + [...] +features: [let] +---*/ + +let x = 'outside'; +var probeBefore = function() { return x; }; +var probeExpr; + +for (let x in { i: probeExpr = function() { typeof x; }}) ; + +assert.sameValue(probeBefore(), 'outside'); +assert.throws(ReferenceError, probeExpr); diff --git a/test/language/statements/for-in/scope-head-var-none.js b/test/language/statements/for-in/scope-head-var-none.js new file mode 100644 index 0000000000..d70d05076e --- /dev/null +++ b/test/language/statements/for-in/scope-head-var-none.js @@ -0,0 +1,45 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation +description: > + No variable environment is created for the statement "head" +info: | + IterationStatement : for ( ForDeclaration of AssignmentExpression ) Statement + + 1. Let keyResult be the result of performing ? + ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, + AssignmentExpression, iterate). + [...] + + 13.7.5.12 Runtime Semantics: ForIn/OfHeadEvaluation + + [...] + 2. If TDZnames is not an empty List, then + a. Assert: TDZnames has no duplicate entries. + b. Let TDZ be NewDeclarativeEnvironment(oldEnv). + c. Let TDZEnvRec be TDZ's EnvironmentRecord. + d. For each string name in TDZnames, do + i. Perform ! TDZEnvRec.CreateMutableBinding(name, false). + e. Set the running execution context's LexicalEnvironment to TDZ. + 3. Let exprRef be the result of evaluating expr. + [...] +flags: [noStrict] +---*/ + +var probeBefore = function() { return x; }; +var x = 1; +var probeDecl, probeExpr, probeBody; + +for ( + let [_ = probeDecl = function() { return x; }] + in + { '': (eval('var x = 2;'), probeExpr = function() { return x; }) } + ) + probeBody = function() { return x; }; + +assert.sameValue(probeBefore(), 2, 'reference preceeding statement'); +assert.sameValue(probeDecl(), 2, 'reference from ForDeclaration'); +assert.sameValue(probeExpr(), 2, 'reference from AssignmentExpression'); +assert.sameValue(probeBody(), 2, 'reference from statement body'); +assert.sameValue(x, 2, 'reference following statement'); diff --git a/test/language/statements/for-of/scope-body-lex-boundary.js b/test/language/statements/for-of/scope-body-lex-boundary.js new file mode 100644 index 0000000000..445b812ca9 --- /dev/null +++ b/test/language/statements/for-of/scope-body-lex-boundary.js @@ -0,0 +1,38 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation +description: > + Creation of new lexical environment for each evaluation of the statement + body +info: | + IterationStatement : for ( ForDeclaration of AssignmentExpression ) Statement + + [...] + 2. Return ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, + lexicalBinding, labelSet). + + 13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation + + [...] + 5. Repeat + [...] + i. Let result be the result of evaluating stmt. + j. Set the running execution context's LexicalEnvironment to oldEnv. + k. If LoopContinues(result, labelSet) is false, return ? + IteratorClose(iterator, UpdateEmpty(result, V)). + l. If result.[[Value]] is not empty, let V be result.[[Value]]. +features: [let] +---*/ + +let x = 'outside'; +var probeFirst, probeSecond; + +for (let x of ['first', 'second']) + if (!probeFirst) + probeFirst = function() { return x; }; + else + probeSecond = function() { return x; }; + +assert.sameValue(probeFirst(), 'first'); +assert.sameValue(probeSecond(), 'second'); diff --git a/test/language/statements/for-of/scope-body-lex-close.js b/test/language/statements/for-of/scope-body-lex-close.js new file mode 100644 index 0000000000..7e36cc9657 --- /dev/null +++ b/test/language/statements/for-of/scope-body-lex-close.js @@ -0,0 +1,40 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation +description: > + Removal of lexical environment for the initial evaluation of the statement + body +info: | + IterationStatement : for ( ForDeclaration of AssignmentExpression ) Statement + + [...] + 2. Return ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, + lexicalBinding, labelSet). + + 13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation + + [...] + 5. Repeat + [...] + i. Let result be the result of evaluating stmt. + j. Set the running execution context's LexicalEnvironment to oldEnv. + k. If LoopContinues(result, labelSet) is false, return ? + IteratorClose(iterator, UpdateEmpty(result, V)). + l. If result.[[Value]] is not empty, let V be result.[[Value]]. +features: [let] +---*/ + +let x = 'outside'; +var probeDecl, probeBody; + +for ( + let [x, _ = probeDecl = function() { return x; }] + of + [['inside']] + ) + probeBody = function() { return x; }; + +assert.sameValue(probeDecl(), 'inside', 'reference from ForDeclaration'); +assert.sameValue(probeBody(), 'inside', 'reference from statement body'); +assert.sameValue(x, 'outside'); diff --git a/test/language/statements/for-of/scope-body-lex-open.js b/test/language/statements/for-of/scope-body-lex-open.js new file mode 100644 index 0000000000..bd0d0e938f --- /dev/null +++ b/test/language/statements/for-of/scope-body-lex-open.js @@ -0,0 +1,48 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation +description: > + Creation of new lexical environment for the initial evaluation of the + statement body +info: | + IterationStatement : for ( ForDeclaration of AssignmentExpression ) Statement + + [...] + 2. Return ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, + lexicalBinding, labelSet). + + 13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation + + [...] + 5. Repeat + [...] + d. If lhsKind is either assignment or varBinding, then + [...] + e. Else, + i. Assert: lhsKind is lexicalBinding. + ii. Assert: lhs is a ForDeclaration. + iii. Let iterationEnv be NewDeclarativeEnvironment(oldEnv). + iv. Perform BindingInstantiation for lhs passing iterationEnv as the + argument. + v. Set the running execution context's LexicalEnvironment to + iterationEnv. + [...] +features: [let] +---*/ + +var probeBefore = function() { return x; }; +let x = 'outside'; +var probeExpr, probeDecl, probeBody; + +for ( + let [x, _, __ = probeDecl = function() { return x; }] + of + [['inside', probeExpr = function() { typeof x; }]] + ) + probeBody = function() { return x; }; + +assert.sameValue(probeBefore(), 'outside'); +assert.throws(ReferenceError, probeExpr); +assert.sameValue(probeDecl(), 'inside', 'reference from ForDeclaration'); +assert.sameValue(probeBody(), 'inside', 'reference from statement body'); diff --git a/test/language/statements/for-of/scope-body-var-none.js b/test/language/statements/for-of/scope-body-var-none.js new file mode 100644 index 0000000000..fe7ad9bf1b --- /dev/null +++ b/test/language/statements/for-of/scope-body-var-none.js @@ -0,0 +1,48 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation +description: No variable environment is created for the statement body +info: | + IterationStatement : for ( ForDeclaration of AssignmentExpression ) Statement + + [...] + 2. Return ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, + lexicalBinding, labelSet). + + 13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation + + [...] + 5. Repeat + [...] + d. If lhsKind is either assignment or varBinding, then + [...] + e. Else, + i. Assert: lhsKind is lexicalBinding. + ii. Assert: lhs is a ForDeclaration. + iii. Let iterationEnv be NewDeclarativeEnvironment(oldEnv). + iv. Perform BindingInstantiation for lhs passing iterationEnv as the + argument. + v. Set the running execution context's LexicalEnvironment to + iterationEnv. + [...] +features: [let] +---*/ + +var probeBefore = function() { return x; }; +var probeExpr, probeDecl, probeBody; +var x = 1; + +for ( + let [_, __ = probeDecl = function() { return x; }] + of + [[probeExpr = function() { return x; }]] + ) + var x = 2, ___ = probeBody = function() { return x; }; + + +assert.sameValue(probeBefore(), 2, 'reference preceeding statement'); +assert.sameValue(probeExpr(), 2, 'reference from AssignmentExpression'); +assert.sameValue(probeDecl(), 2, 'reference from ForDelaration'); +assert.sameValue(probeBody(), 2, 'reference from statement body'); +assert.sameValue(x, 2, 'reference following statement'); diff --git a/test/language/statements/for-of/scope-head-lex-close.js b/test/language/statements/for-of/scope-head-lex-close.js new file mode 100644 index 0000000000..808fceb47a --- /dev/null +++ b/test/language/statements/for-of/scope-head-lex-close.js @@ -0,0 +1,44 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation +description: > + Removal of lexical environment to serve as a temporal dead zone for the + statement's AssignmentExpresson +info: | + IterationStatement : for ( ForDeclaration of AssignmentExpression ) Statement + + 1. Let keyResult be the result of performing ? + ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, + AssignmentExpression, iterate). + [...] + + 13.7.5.12 Runtime Semantics: ForIn/OfHeadEvaluation + + [...] + 2. If TDZnames is not an empty List, then + a. Assert: TDZnames has no duplicate entries. + b. Let TDZ be NewDeclarativeEnvironment(oldEnv). + c. Let TDZEnvRec be TDZ's EnvironmentRecord. + d. For each string name in TDZnames, do + i. Perform ! TDZEnvRec.CreateMutableBinding(name, false). + e. Set the running execution context's LexicalEnvironment to TDZ. + 3. Let exprRef be the result of evaluating expr. + 4. Set the running execution context's LexicalEnvironment to oldEnv. + [...] +features: [let] +---*/ + +let x = 'outside'; +var probeDecl, probeExpr, probeBody; + +for ( + let [x, _ = probeDecl = function() { return x; }] + of + (probeExpr = function() { typeof x; }, [['inside']]) + ) + probeBody = function() { return x; }; + +assert.throws(ReferenceError, probeExpr); +assert.sameValue(probeDecl(), 'inside', 'reference from ForDeclaration'); +assert.sameValue(probeBody(), 'inside', 'reference from statement body'); diff --git a/test/language/statements/for-of/scope-head-lex-open.js b/test/language/statements/for-of/scope-head-lex-open.js new file mode 100644 index 0000000000..4bcff42c1e --- /dev/null +++ b/test/language/statements/for-of/scope-head-lex-open.js @@ -0,0 +1,38 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation +description: > + Creation of new lexical environment to serve as a temporal dead zone for + the statement's AssignmentExpresson +info: | + IterationStatement : for ( ForDeclaration of AssignmentExpression ) Statement + + 1. Let keyResult be the result of performing ? + ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, + AssignmentExpression, iterate). + [...] + + 13.7.5.12 Runtime Semantics: ForIn/OfHeadEvaluation + + [...] + 2. If TDZnames is not an empty List, then + a. Assert: TDZnames has no duplicate entries. + b. Let TDZ be NewDeclarativeEnvironment(oldEnv). + c. Let TDZEnvRec be TDZ's EnvironmentRecord. + d. For each string name in TDZnames, do + i. Perform ! TDZEnvRec.CreateMutableBinding(name, false). + e. Set the running execution context's LexicalEnvironment to TDZ. + 3. Let exprRef be the result of evaluating expr. + [...] +features: [let] +---*/ + +let x = 'outside'; +var probeBefore = function() { return x; }; +var probeExpr; + +for (let x of (probeExpr = function() { typeof x; }, [])) ; + +assert.sameValue(probeBefore(), 'outside'); +assert.throws(ReferenceError, probeExpr); diff --git a/test/language/statements/for-of/scope-head-var-none.js b/test/language/statements/for-of/scope-head-var-none.js new file mode 100644 index 0000000000..d527736c74 --- /dev/null +++ b/test/language/statements/for-of/scope-head-var-none.js @@ -0,0 +1,45 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation +description: > + No variable environment is created for the statement "head" +info: | + IterationStatement : for ( ForDeclaration of AssignmentExpression ) Statement + + 1. Let keyResult be the result of performing ? + ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, + AssignmentExpression, iterate). + [...] + + 13.7.5.12 Runtime Semantics: ForIn/OfHeadEvaluation + + [...] + 2. If TDZnames is not an empty List, then + a. Assert: TDZnames has no duplicate entries. + b. Let TDZ be NewDeclarativeEnvironment(oldEnv). + c. Let TDZEnvRec be TDZ's EnvironmentRecord. + d. For each string name in TDZnames, do + i. Perform ! TDZEnvRec.CreateMutableBinding(name, false). + e. Set the running execution context's LexicalEnvironment to TDZ. + 3. Let exprRef be the result of evaluating expr. + [...] +flags: [noStrict] +---*/ + +var probeBefore = function() { return x; }; +var x = 1; +var probeDecl, probeExpr, probeBody; + +for ( + let [_ = probeDecl = function() { return x; }] + of + [[eval('var x = 2;'), probeExpr = function() { return x; }]] + ) + probeBody = function() { return x; }; + +assert.sameValue(probeBefore(), 2, 'reference preceeding statement'); +assert.sameValue(probeDecl(), 2, 'reference from ForDeclaration'); +assert.sameValue(probeExpr(), 2, 'reference from AssignmentExpression'); +assert.sameValue(probeBody(), 2, 'reference from statement body'); +assert.sameValue(x, 2, 'reference following statement'); diff --git a/test/language/statements/for/scope-body-lex-boundary.js b/test/language/statements/for/scope-body-lex-boundary.js new file mode 100644 index 0000000000..126d5f5973 --- /dev/null +++ b/test/language/statements/for/scope-body-lex-boundary.js @@ -0,0 +1,43 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-statement-runtime-semantics-labelledevaluation +description: > + Creation of new lexical environment for each evaluation of the statement + body +info: | + [...] + 11. Let bodyResult be ForBodyEvaluation(the first Expression, the second + Expression, Statement, perIterationLets, labelSet). + [...] + + 13.7.4.8 Runtime Semantics: ForBodyEvaluation + + [...] + 3. Repeat + [...] + b. Let result be the result of evaluating stmt. + [...] + e. Perform ? CreatePerIterationEnvironment(perIterationBindings). + [...] + + 13.7.4.9 Runtime Semantics: CreatePerIterationEnvironment + + 1. If perIterationBindings has any elements, then + [...] + e. Let thisIterationEnv be NewDeclarativeEnvironment(outer). + f. Let thisIterationEnvRec be thisIterationEnv's EnvironmentRecord. +features: [let] +---*/ + +var probeFirst; +var probeSecond = null; + +for (let x = 'first'; probeSecond === null; x = 'second') + if (!probeFirst) + probeFirst = function() { return x; }; + else + probeSecond = function() { return x; }; + +assert.sameValue(probeFirst(), 'first'); +assert.sameValue(probeSecond(), 'second'); diff --git a/test/language/statements/for/scope-body-lex-open.js b/test/language/statements/for/scope-body-lex-open.js new file mode 100644 index 0000000000..8efa583e88 --- /dev/null +++ b/test/language/statements/for/scope-body-lex-open.js @@ -0,0 +1,46 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-statement-runtime-semantics-labelledevaluation +description: > + Creation of new lexical environment for the initial evaluation of the + statement body +info: | + [...] + 11. Let bodyResult be ForBodyEvaluation(the first Expression, the second + Expression, Statement, perIterationLets, labelSet). + [...] + + 13.7.4.8 Runtime Semantics: ForBodyEvaluation + + [...] + 2. Perform ? CreatePerIterationEnvironment(perIterationBindings). + 3. Repeat + [...] + b. Let result be the result of evaluating stmt. + [...] + [...] + + 13.7.4.9 Runtime Semantics: CreatePerIterationEnvironment + + 1. If perIterationBindings has any elements, then + [...] + e. Let thisIterationEnv be NewDeclarativeEnvironment(outer). + f. Let thisIterationEnvRec be thisIterationEnv's EnvironmentRecord. +features: [let] +---*/ + +var probeBefore, probeTest, probeIncr, probeBody; +var run = true; + +for ( + let x = 'outside', _ = probeBefore = function() { return x; }; + run && (x = 'inside', probeTest = function() { return x; }); + probeIncr = function() { return x; } + ) + probeBody = function() { return x; }, run = false; + +assert.sameValue(probeBefore(), 'outside'); +assert.sameValue(probeTest(), 'inside', 'reference from "test" position'); +assert.sameValue(probeBody(), 'inside', 'reference from statement body'); +assert.sameValue(probeIncr(), 'inside', 'reference from "increment" position'); diff --git a/test/language/statements/for/scope-body-var-none.js b/test/language/statements/for/scope-body-var-none.js new file mode 100644 index 0000000000..230c2abcf8 --- /dev/null +++ b/test/language/statements/for/scope-body-var-none.js @@ -0,0 +1,111 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-statement-runtime-semantics-labelledevaluation +description: > + No variable environment is created for each evaluation of the statement + body +info: | + [...] + 11. Let bodyResult be ForBodyEvaluation(the first Expression, the second + Expression, Statement, perIterationLets, labelSet). + [...] + + 13.7.4.8 Runtime Semantics: ForBodyEvaluation + + [...] + 2. Perform ? CreatePerIterationEnvironment(perIterationBindings). + 3. Repeat + [...] + b. Let result be the result of evaluating stmt. + [...] + e. Perform ? CreatePerIterationEnvironment(perIterationBindings). + [...] + + 13.7.4.9 Runtime Semantics: CreatePerIterationEnvironment + + 1. If perIterationBindings has any elements, then + [...] + e. Let thisIterationEnv be NewDeclarativeEnvironment(outer). + f. Let thisIterationEnvRec be thisIterationEnv's EnvironmentRecord. +flags: [noStrict] +---*/ + +var probeBefore = function() { return [x, y, z]; }; +var probeTest, probeIncr, probeBody; +var run = true; + +for ( + ; + run && (eval('var x = 1;'), probeTest = function() { return [x, y, z]; }); + eval('var y = 1;'), probeIncr = function() { return [x, y, z]; } + ) + var z = 1, _ = (probeBody = function() { return [x, y, z]; }), run = false; + +var x = 2; +var y = 2; +var z = 2; + +assert.sameValue( + probeBefore()[0], + 2, + 'reference preceeding statement (redeclared in "test" position)' +); +assert.sameValue( + probeBefore()[1], + 2, + 'reference preceeding statement (redeclared in statement body)' +); +assert.sameValue( + probeBefore()[2], + 2, + 'reference preceeding statement (redeclared in "increment" position)' +); + +assert.sameValue( + probeTest()[0], + 2, + 'reference from "test" position (redeclared in "test" position)' +); +assert.sameValue( + probeTest()[1], + 2, + 'reference from "test" position (redeclared in statement body)' +); +assert.sameValue( + probeTest()[2], + 2, + 'reference from "test" position (redeclared in "increment" position)' +); + +assert.sameValue( + probeBody()[0], + 2, + 'reference from statement body (redeclared in "test" position)' +); +assert.sameValue( + probeBody()[1], + 2, + 'reference from statement body (redeclared in statement body)' +); +assert.sameValue( + probeBody()[2], + 2, + 'reference from statement body (redeclared in "increment" position)' +); + +assert.sameValue( + probeIncr()[0], + 2, + 'reference from "increment" position (redeclared in "test" position)' +); +assert.sameValue( + probeIncr()[1], + 2, + 'reference from "increment" position (redeclared in statement body)' +); +assert.sameValue( + probeIncr()[2], + 2, + 'reference from "increment" position (redeclared in "increment" position)' +); diff --git a/test/language/statements/for/scope-head-lex-close.js b/test/language/statements/for/scope-head-lex-close.js new file mode 100644 index 0000000000..ac7eba5ee8 --- /dev/null +++ b/test/language/statements/for/scope-head-lex-close.js @@ -0,0 +1,39 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-statement-runtime-semantics-labelledevaluation +description: Removal of lexical environment for the statement "head" +info: | + [...] + 2. Let loopEnv be NewDeclarativeEnvironment(oldEnv). + 3. Let loopEnvRec be loopEnv's EnvironmentRecord. + 4. Let isConst be the result of performing IsConstantDeclaration of + LexicalDeclaration. + 5. Let boundNames be the BoundNames of LexicalDeclaration. + 6. For each element dn of boundNames do + a. If isConst is true, then + i. Perform ! loopEnvRec.CreateImmutableBinding(dn, true). + b. Else, + i. Perform ! loopEnvRec.CreateMutableBinding(dn, false). + 7. Set the running execution context's LexicalEnvironment to loopEnv. + [...] + 12. Set the running execution context's LexicalEnvironment to oldEnv. + 13. Return Completion(bodyResult). +features: [let] +---*/ + +let x = 'outside'; +var run = true; +var probeTest, probeIncr, probeBody; + +for ( + let x = 'inside'; + (probeTest = function() { return x; }) && run; + probeIncr = function() { return x; } + ) + probeBody = function() { return x; }, run = false; + +assert.sameValue(probeBody(), 'inside', 'reference from statement body'); +assert.sameValue(probeIncr(), 'inside', 'reference from "increment" position'); +assert.sameValue(probeTest(), 'inside', 'reference from "test" position'); +assert.sameValue(x, 'outside'); diff --git a/test/language/statements/for/scope-head-lex-open.js b/test/language/statements/for/scope-head-lex-open.js new file mode 100644 index 0000000000..6c8a7d1cbc --- /dev/null +++ b/test/language/statements/for/scope-head-lex-open.js @@ -0,0 +1,39 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-statement-runtime-semantics-labelledevaluation +description: Creation of new lexical environment for the statement "head" +info: | + [...] + 2. Let loopEnv be NewDeclarativeEnvironment(oldEnv). + 3. Let loopEnvRec be loopEnv's EnvironmentRecord. + 4. Let isConst be the result of performing IsConstantDeclaration of + LexicalDeclaration. + 5. Let boundNames be the BoundNames of LexicalDeclaration. + 6. For each element dn of boundNames do + a. If isConst is true, then + i. Perform ! loopEnvRec.CreateImmutableBinding(dn, true). + b. Else, + i. Perform ! loopEnvRec.CreateMutableBinding(dn, false). + 7. Set the running execution context's LexicalEnvironment to loopEnv. + [...] +features: [let] +---*/ + +let x = 'outside'; +var probeBefore = function() { return x; }; +var probeDecl, probeTest, probeIncr, probeBody; +var run = true; + +for ( + let x = 'inside', _ = probeDecl = function() { return x; }; + run && (probeTest = function() { return x; }); + probeIncr = function() { return x; } + ) + probeBody = function() { return x; }, run = false; + +assert.sameValue(probeBefore(), 'outside'); +assert.sameValue(probeDecl(), 'inside', 'reference from LexicalDeclaration'); +assert.sameValue(probeTest(), 'inside', 'reference from "test" position'); +assert.sameValue(probeBody(), 'inside', 'reference from statement body'); +assert.sameValue(probeIncr(), 'inside', 'reference from "increment" position'); diff --git a/test/language/statements/for/scope-head-var-none.js b/test/language/statements/for/scope-head-var-none.js new file mode 100644 index 0000000000..301e5ee2f4 --- /dev/null +++ b/test/language/statements/for/scope-head-var-none.js @@ -0,0 +1,42 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-for-statement-runtime-semantics-labelledevaluation +description: No variable environment is created for the statement "head" +info: | + [...] + 2. Let loopEnv be NewDeclarativeEnvironment(oldEnv). + 3. Let loopEnvRec be loopEnv's EnvironmentRecord. + 4. Let isConst be the result of performing IsConstantDeclaration of + LexicalDeclaration. + 5. Let boundNames be the BoundNames of LexicalDeclaration. + 6. For each element dn of boundNames do + a. If isConst is true, then + i. Perform ! loopEnvRec.CreateImmutableBinding(dn, true). + b. Else, + i. Perform ! loopEnvRec.CreateMutableBinding(dn, false). + 7. Set the running execution context's LexicalEnvironment to loopEnv. + [...] + 12. Set the running execution context's LexicalEnvironment to oldEnv. + 13. Return Completion(bodyResult). +flags: [noStrict] +---*/ + +var probeBefore = function() { return x; }; +var probeTest, probeIncr, probeBody; +var run = true; + +for ( + var _ = eval('var x = 1;'); + run && (probeTest = function() { return x; }); + probeIncr = function() { return x; } + ) + probeBody = function() { return x; }, run = false; + +var x = 2; + +assert.sameValue(probeBefore(), 2, 'reference preceeding statement'); +assert.sameValue(probeTest(), 2, 'reference from "test" position'); +assert.sameValue(probeBody(), 2, 'reference from statement body'); +assert.sameValue(probeIncr(), 2, 'reference from "increment" position'); +assert.sameValue(x, 2, 'reference following statement'); diff --git a/test/language/statements/switch/scope-lex-close-case.js b/test/language/statements/switch/scope-lex-close-case.js new file mode 100644 index 0000000000..767f716035 --- /dev/null +++ b/test/language/statements/switch/scope-lex-close-case.js @@ -0,0 +1,32 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-switch-statement-runtime-semantics-evaluation +description: Removal of lexical environment (from `case` clause) +info: | + 1. Let exprRef be the result of evaluating Expression. + 2. Let switchValue be ? GetValue(exprRef). + 3. Let oldEnv be the running execution context's LexicalEnvironment. + 4. Let blockEnv be NewDeclarativeEnvironment(oldEnv). + 5. Perform BlockDeclarationInstantiation(CaseBlock, blockEnv). + 6. Set the running execution context's LexicalEnvironment to blockEnv. + 7. Let R be the result of performing CaseBlockEvaluation of CaseBlock with + argument switchValue. + [...] +features: [let] +---*/ + +let x = 'outside'; +var probe1, probe2; + +switch (null) { + case null: + let x = 'inside'; + probe1 = function() { return x; }; + case null: + probe2 = function() { return x; }; +} + +assert.sameValue(probe1(), 'inside', 'from first `case` clause'); +assert.sameValue(probe2(), 'inside', 'from second `case` clause'); +assert.sameValue(x, 'outside'); diff --git a/test/language/statements/switch/scope-lex-close-dflt.js b/test/language/statements/switch/scope-lex-close-dflt.js new file mode 100644 index 0000000000..fb6aa338bd --- /dev/null +++ b/test/language/statements/switch/scope-lex-close-dflt.js @@ -0,0 +1,46 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-switch-statement-runtime-semantics-evaluation +description: Removal of lexical environment (from `default` clause) +info: | + 1. Let exprRef be the result of evaluating Expression. + 2. Let switchValue be ? GetValue(exprRef). + 3. Let oldEnv be the running execution context's LexicalEnvironment. + 4. Let blockEnv be NewDeclarativeEnvironment(oldEnv). + 5. Perform BlockDeclarationInstantiation(CaseBlock, blockEnv). + 6. Set the running execution context's LexicalEnvironment to blockEnv. + 7. Let R be the result of performing CaseBlockEvaluation of CaseBlock with + argument switchValue. + [...] +features: [let] +---*/ + +let x = 'outside'; +var probeDefault, probeDefaultBeforeCase, probeCase; + +switch (null) { + default: + let x = 'inside'; + probeDefault = function() { return x; }; +} + +assert.sameValue(probeDefault(), 'inside', 'from lone `default` clause`'); +assert.sameValue(x, 'outside'); + +switch (null) { + default: + let x = 'inside'; + probeDefaultBeforeCase = function() { return x; }; + case 0: + probeCase = function() { return x; }; +} + +assert.sameValue( + probeDefaultBeforeCase(), + 'inside', + 'from `default` clause preceeding `case` clause' +); +assert.sameValue( + probeCase(), 'inside', 'from `case` clause following `default` clause' +); diff --git a/test/language/statements/switch/scope-lex-open-case.js b/test/language/statements/switch/scope-lex-open-case.js new file mode 100644 index 0000000000..bb0edd8889 --- /dev/null +++ b/test/language/statements/switch/scope-lex-open-case.js @@ -0,0 +1,32 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-switch-statement-runtime-semantics-evaluation +description: Creation of new lexical environment (into `case` clause) +info: | + 1. Let exprRef be the result of evaluating Expression. + 2. Let switchValue be ? GetValue(exprRef). + 3. Let oldEnv be the running execution context's LexicalEnvironment. + 4. Let blockEnv be NewDeclarativeEnvironment(oldEnv). + 5. Perform BlockDeclarationInstantiation(CaseBlock, blockEnv). + 6. Set the running execution context's LexicalEnvironment to blockEnv. + 7. Let R be the result of performing CaseBlockEvaluation of CaseBlock with + argument switchValue. + [...] +features: [let] +---*/ + +let x = 'outside'; +var probeExpr, probeSelector, probeStmt; + +switch (probeExpr = function() { return x; }, null) { + case probeSelector = function() { return x; }, null: + probeStmt = function() { return x; }; + let x = 'inside'; +} + +assert.sameValue(probeExpr(), 'outside'); +assert.sameValue( + probeSelector(), 'inside', 'reference from "selector" Expression' +); +assert.sameValue(probeStmt(), 'inside', 'reference from Statement position'); diff --git a/test/language/statements/switch/scope-lex-open-dflt.js b/test/language/statements/switch/scope-lex-open-dflt.js new file mode 100644 index 0000000000..7df609c6d2 --- /dev/null +++ b/test/language/statements/switch/scope-lex-open-dflt.js @@ -0,0 +1,29 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-switch-statement-runtime-semantics-evaluation +description: Creation of new lexical environment (into `default` clause) +info: | + 1. Let exprRef be the result of evaluating Expression. + 2. Let switchValue be ? GetValue(exprRef). + 3. Let oldEnv be the running execution context's LexicalEnvironment. + 4. Let blockEnv be NewDeclarativeEnvironment(oldEnv). + 5. Perform BlockDeclarationInstantiation(CaseBlock, blockEnv). + 6. Set the running execution context's LexicalEnvironment to blockEnv. + 7. Let R be the result of performing CaseBlockEvaluation of CaseBlock with + argument switchValue. + [...] +features: [let] +---*/ + +let x = 'outside'; +var probeExpr, probeStmt; + +switch (probeExpr = function() { return x; }) { + default: + probeStmt = function() { return x; }; + let x = 'inside'; +} + +assert.sameValue(probeExpr(), 'outside'); +assert.sameValue(probeStmt(), 'inside'); diff --git a/test/language/statements/switch/scope-var-none-case.js b/test/language/statements/switch/scope-var-none-case.js new file mode 100644 index 0000000000..0f6019faaa --- /dev/null +++ b/test/language/statements/switch/scope-var-none-case.js @@ -0,0 +1,32 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-switch-statement-runtime-semantics-evaluation +description: Retainment of existing variable environment (`case` clause) +info: | + 1. Let exprRef be the result of evaluating Expression. + 2. Let switchValue be ? GetValue(exprRef). + 3. Let oldEnv be the running execution context's LexicalEnvironment. + 4. Let blockEnv be NewDeclarativeEnvironment(oldEnv). + 5. Perform BlockDeclarationInstantiation(CaseBlock, blockEnv). + 6. Set the running execution context's LexicalEnvironment to blockEnv. + 7. Let R be the result of performing CaseBlockEvaluation of CaseBlock with + argument switchValue. + [...] +flags: [noStrict] +---*/ + +var probeExpr, probeSelector, probeStmt; +var probeBefore = function() { return x; }; + +switch (eval('var x = 1;'), probeExpr = function() { return x; }, null) { + case eval('var x = 2;'), probeSelector = function() { return x; }, null: + probeStmt = function() { return x; }; + var x = 3; +} + +assert.sameValue(probeBefore(), 3, 'reference preceeding statement'); +assert.sameValue(probeExpr(), 3, 'reference from first Expression'); +assert.sameValue(probeSelector(), 3, 'reference from "selector" Expression'); +assert.sameValue(probeStmt(), 3, 'reference from Statement position'); +assert.sameValue(x, 3, 'reference following statement'); diff --git a/test/language/statements/switch/scope-var-none-dflt.js b/test/language/statements/switch/scope-var-none-dflt.js new file mode 100644 index 0000000000..229084095c --- /dev/null +++ b/test/language/statements/switch/scope-var-none-dflt.js @@ -0,0 +1,31 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-switch-statement-runtime-semantics-evaluation +description: Retainment of existing variable environment (`default` clause) +info: | + 1. Let exprRef be the result of evaluating Expression. + 2. Let switchValue be ? GetValue(exprRef). + 3. Let oldEnv be the running execution context's LexicalEnvironment. + 4. Let blockEnv be NewDeclarativeEnvironment(oldEnv). + 5. Perform BlockDeclarationInstantiation(CaseBlock, blockEnv). + 6. Set the running execution context's LexicalEnvironment to blockEnv. + 7. Let R be the result of performing CaseBlockEvaluation of CaseBlock with + argument switchValue. + [...] +flags: [noStrict] +---*/ + +var probeExpr, probeStmt; +var probeBefore = function() { return x; }; + +switch (eval('var x = 1;'), probeExpr = function() { return x; }) { + default: + probeStmt = function() { return x; }; + var x = 2; +} + +assert.sameValue(probeBefore(), 2, 'reference preceeding statment'); +assert.sameValue(probeExpr(), 2, 'reference from Expression position'); +assert.sameValue(probeStmt(), 2, 'reference from Statement position'); +assert.sameValue(x, 2, 'reference following statement'); diff --git a/test/language/statements/try/scope-catch-block-lex-close.js b/test/language/statements/try/scope-catch-block-lex-close.js new file mode 100644 index 0000000000..458831d97f --- /dev/null +++ b/test/language/statements/try/scope-catch-block-lex-close.js @@ -0,0 +1,24 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-runtime-semantics-catchclauseevaluation +description: Removal of lexical environment for `catch` block +info: | + [...] + 8. Let B be the result of evaluating Block. + [...] +features: [let] +---*/ + +var probe, x; + +try { + throw null; +} catch (_) { + let x = 'inside'; + probe = function() { return x; }; +} +x = 'outside'; + +assert.sameValue(x, 'outside'); +assert.sameValue(probe(), 'inside'); diff --git a/test/language/statements/try/scope-catch-block-lex-open.js b/test/language/statements/try/scope-catch-block-lex-open.js new file mode 100644 index 0000000000..10b7ddf994 --- /dev/null +++ b/test/language/statements/try/scope-catch-block-lex-open.js @@ -0,0 +1,24 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-runtime-semantics-catchclauseevaluation +description: Creation of new lexical environment for `catch` block +info: | + [...] + 8. Let B be the result of evaluating Block. + [...] +features: [let] +---*/ + +var probeParam, probeBlock; +let x = 'outside'; + +try { + throw []; +} catch ([_ = probeParam = function() { return x; }]) { + probeBlock = function() { return x; }; + let x = 'inside'; +} + +assert.sameValue(probeParam(), 'outside'); +assert.sameValue(probeBlock(), 'inside'); diff --git a/test/language/statements/try/scope-catch-block-var-none.js b/test/language/statements/try/scope-catch-block-var-none.js new file mode 100644 index 0000000000..de10923b93 --- /dev/null +++ b/test/language/statements/try/scope-catch-block-var-none.js @@ -0,0 +1,25 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-runtime-semantics-catchclauseevaluation +description: Retainment of existing variable environment for `catch` block +info: | + [...] + 8. Let B be the result of evaluating Block. + [...] +---*/ + +var x = 1; +var probeBefore = function() { return x; }; +var probeInside; + +try { + throw null; +} catch (_) { + var x = 2; + probeInside = function() { return x; }; +} + +assert.sameValue(probeBefore(), 2, 'reference preceeding statement'); +assert.sameValue(probeInside(), 2, 'reference within statement'); +assert.sameValue(x, 2, 'reference following statement'); diff --git a/test/language/statements/try/scope-catch-param-lex-close.js b/test/language/statements/try/scope-catch-param-lex-close.js new file mode 100644 index 0000000000..682b5a8c10 --- /dev/null +++ b/test/language/statements/try/scope-catch-param-lex-close.js @@ -0,0 +1,18 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-runtime-semantics-catchclauseevaluation +description: Removal of lexical environment for `catch` parameter +---*/ + +var probe, x; + +try { + throw 'inside'; +} catch (x) { + probe = function() { return x; }; +} +x = 'outside'; + +assert.sameValue(x, 'outside'); +assert.sameValue(probe(), 'inside'); diff --git a/test/language/statements/try/scope-catch-param-lex-open.js b/test/language/statements/try/scope-catch-param-lex-open.js new file mode 100644 index 0000000000..5ade7b0210 --- /dev/null +++ b/test/language/statements/try/scope-catch-param-lex-open.js @@ -0,0 +1,20 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-runtime-semantics-catchclauseevaluation +description: Creation of new lexical environment for `catch` parameter +---*/ + +var probeBefore = function() { return x; }; +var probeTry, probeParam; +var x = 'outside'; + +try { + probeTry = function() { return x; }; + + throw ['inside']; +} catch ([x, _ = probeParam = function() { return x; }]) {} + +assert.sameValue(probeBefore(), 'outside'); +assert.sameValue(probeTry(), 'outside'); +assert.sameValue(probeParam(), 'inside'); diff --git a/test/language/statements/try/scope-catch-param-var-none.js b/test/language/statements/try/scope-catch-param-var-none.js new file mode 100644 index 0000000000..910eceea1a --- /dev/null +++ b/test/language/statements/try/scope-catch-param-var-none.js @@ -0,0 +1,26 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-runtime-semantics-catchclauseevaluation +description: Retainment of existing variable environment for `catch` parameter +flags: [noStrict] +---*/ + +var x = 1; +var probeBefore = function() { return x; }; +var probeTry, probeParam, probeBlock; + +try { + var x = 2; + probeTry = function() { return x; }; + throw []; +} catch ([_ = (eval('var x = 3;'), probeParam = function() { return x; })]) { + var x = 4; + probeBlock = function() { return x; }; +} + +assert.sameValue(probeBefore(), 4, 'reference preceeding statement'); +assert.sameValue(probeTry(), 4, 'reference from `try` block'); +assert.sameValue(probeParam(), 4, 'reference within CatchParameter'); +assert.sameValue(probeBlock(), 4, 'reference from `catch` block'); +assert.sameValue(x, 4, 'reference following statement'); diff --git a/test/language/statements/with/scope-var-close.js b/test/language/statements/with/scope-var-close.js new file mode 100644 index 0000000000..be804d7300 --- /dev/null +++ b/test/language/statements/with/scope-var-close.js @@ -0,0 +1,25 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-with-statement-runtime-semantics-evaluation +es6id: 13.11.7 +description: Removal of variable environment +info: | + 3. Let oldEnv be the running execution context's LexicalEnvironment. + 4. Let newEnv be NewObjectEnvironment(obj, oldEnv). + 5. Set the withEnvironment flag of newEnv's EnvironmentRecord to true. + 6. Set the running execution context's LexicalEnvironment to newEnv. + 7. Let C be the result of evaluating Statement. + 8. Set the running execution context's LexicalEnvironment to oldEnv. +flags: [noStrict] +---*/ + +var probeBody; + +with ({ x: 0 }) + var x = 1, _ = probeBody = function() { return x; }; + +var x = 2; + +assert.sameValue(probeBody(), 1, 'reference from statement body'); +assert.sameValue(x, 2, 'reference following statement'); diff --git a/test/language/statements/with/scope-var-open.js b/test/language/statements/with/scope-var-open.js new file mode 100644 index 0000000000..00dd5b4d55 --- /dev/null +++ b/test/language/statements/with/scope-var-open.js @@ -0,0 +1,26 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-with-statement-runtime-semantics-evaluation +es6id: 13.11.7 +description: Creation of new variable environment +info: | + 3. Let oldEnv be the running execution context's LexicalEnvironment. + 4. Let newEnv be NewObjectEnvironment(obj, oldEnv). + 5. Set the withEnvironment flag of newEnv's EnvironmentRecord to true. + 6. Set the running execution context's LexicalEnvironment to newEnv. + 7. Let C be the result of evaluating Statement. +flags: [noStrict] +---*/ + +var x = 0; +var objectRecord = { x: 2 }; +var probeBefore = function() { return x; }; +var probeExpr, probeBody; + +with (eval('var x = 1;'), probeExpr = function() { return x; }, objectRecord) + var x = 3, _ = probeBody = function() { return x; }; + +assert.sameValue(probeBefore(), 1, 'reference preceeding statement'); +assert.sameValue(probeExpr(), 1, 'reference from expression'); +assert.sameValue(probeBody(), 3, 'reference from statement body');