From 784824895d34c3081bc4458ebf8aa23c34887a5d Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Tue, 5 Apr 2016 17:45:27 -0400 Subject: [PATCH] Extend coverage for eval code Closes #572 Introduce tests for new semantics for ES2015 features such as lexically-scoped bindings. Also add tests for semantics defined in prior editions of the specification but not yet covered in this test suite. --- .../eval-code/direct/lex-env-distinct-cls.js | 33 ++++++++++++++ .../direct/lex-env-distinct-const.js | 33 ++++++++++++++ .../eval-code/direct/lex-env-distinct-let.js | 33 ++++++++++++++ .../eval-code/direct/lex-env-heritage.js | 27 +++++++++++ .../eval-code/direct/lex-env-no-init-cls.js | 24 ++++++++++ .../eval-code/direct/lex-env-no-init-const.js | 24 ++++++++++ .../eval-code/direct/lex-env-no-init-let.js | 24 ++++++++++ .../eval-code/direct/strictness-override.js | 15 +++++++ ...ct.js => this-value-func-strict-caller.js} | 0 .../direct/this-value-func-strict-source.js | 17 +++++++ .../direct/var-env-func-init-global-new.js | 39 ++++++++++++++++ ...nv-func-init-global-update-configurable.js | 45 +++++++++++++++++++ ...unc-init-global-update-non-configurable.js | 45 +++++++++++++++++++ .../var-env-func-init-local-new-delete.js | 32 +++++++++++++ .../direct/var-env-func-init-local-new.js | 35 +++++++++++++++ .../direct/var-env-func-init-local-update.js | 35 +++++++++++++++ .../direct/var-env-func-init-multi.js | 30 +++++++++++++ .../var-env-gloabl-lex-strict-caller.js | 16 +++++++ .../direct/var-env-global-lex-non-strict.js | 28 ++++++++++++ .../var-env-global-lex-strict-source.js | 15 +++++++ .../direct/var-env-lower-lex-non-strict.js | 34 ++++++++++++++ .../direct/var-env-lower-lex-strict-caller.js | 19 ++++++++ .../direct/var-env-lower-lex-strict-source.js | 18 ++++++++ .../direct/var-env-var-init-global-exstng.js | 33 ++++++++++++++ .../direct/var-env-var-init-global-new.js | 33 ++++++++++++++ .../direct/var-env-var-init-local-exstng.js | 29 ++++++++++++ .../var-env-var-init-local-new-delete.js | 30 +++++++++++++ .../direct/var-env-var-init-local-new.js | 33 ++++++++++++++ .../eval-code/indirect/always-non-strict.js | 25 +++++++++++ .../indirect/lex-env-distinct-cls.js | 35 +++++++++++++++ .../indirect/lex-env-distinct-const.js | 35 +++++++++++++++ .../indirect/lex-env-distinct-let.js | 35 +++++++++++++++ .../eval-code/indirect/lex-env-heritage.js | 29 ++++++++++++ .../eval-code/indirect/lex-env-no-init-cls.js | 24 ++++++++++ .../indirect/lex-env-no-init-const.js | 24 ++++++++++ .../eval-code/indirect/lex-env-no-init-let.js | 24 ++++++++++ .../indirect/var-env-func-init-global-new.js | 38 ++++++++++++++++ ...nv-func-init-global-update-configurable.js | 44 ++++++++++++++++++ ...unc-init-global-update-non-configurable.js | 44 ++++++++++++++++++ .../indirect/var-env-func-init-multi.js | 29 ++++++++++++ .../indirect/var-env-global-lex-non-strict.js | 31 +++++++++++++ .../indirect/var-env-global-lex-strict.js | 15 +++++++ .../indirect/var-env-lower-lex-non-strict.js | 20 +++++++++ .../indirect/var-env-lower-lex-strict.js | 18 ++++++++ .../var-env-var-init-global-exstng.js | 32 +++++++++++++ .../indirect/var-env-var-init-global-new.js | 32 +++++++++++++ .../expressions/call/eval-err-args.js | 23 ++++++++++ .../language/expressions/call/eval-no-args.js | 15 +++++++ .../eval-strictness-inherit-non-strict.js | 30 +++++++++++++ .../call/eval-strictness-inherit-strict.js | 28 ++++++++++++ 50 files changed, 1409 insertions(+) create mode 100644 test/language/eval-code/direct/lex-env-distinct-cls.js create mode 100644 test/language/eval-code/direct/lex-env-distinct-const.js create mode 100644 test/language/eval-code/direct/lex-env-distinct-let.js create mode 100644 test/language/eval-code/direct/lex-env-heritage.js create mode 100644 test/language/eval-code/direct/lex-env-no-init-cls.js create mode 100644 test/language/eval-code/direct/lex-env-no-init-const.js create mode 100644 test/language/eval-code/direct/lex-env-no-init-let.js create mode 100644 test/language/eval-code/direct/strictness-override.js rename test/language/eval-code/direct/{this-value-func-strict.js => this-value-func-strict-caller.js} (100%) create mode 100644 test/language/eval-code/direct/this-value-func-strict-source.js create mode 100644 test/language/eval-code/direct/var-env-func-init-global-new.js create mode 100644 test/language/eval-code/direct/var-env-func-init-global-update-configurable.js create mode 100644 test/language/eval-code/direct/var-env-func-init-global-update-non-configurable.js create mode 100644 test/language/eval-code/direct/var-env-func-init-local-new-delete.js create mode 100644 test/language/eval-code/direct/var-env-func-init-local-new.js create mode 100644 test/language/eval-code/direct/var-env-func-init-local-update.js create mode 100644 test/language/eval-code/direct/var-env-func-init-multi.js create mode 100644 test/language/eval-code/direct/var-env-gloabl-lex-strict-caller.js create mode 100644 test/language/eval-code/direct/var-env-global-lex-non-strict.js create mode 100644 test/language/eval-code/direct/var-env-global-lex-strict-source.js create mode 100644 test/language/eval-code/direct/var-env-lower-lex-non-strict.js create mode 100644 test/language/eval-code/direct/var-env-lower-lex-strict-caller.js create mode 100644 test/language/eval-code/direct/var-env-lower-lex-strict-source.js create mode 100644 test/language/eval-code/direct/var-env-var-init-global-exstng.js create mode 100644 test/language/eval-code/direct/var-env-var-init-global-new.js create mode 100644 test/language/eval-code/direct/var-env-var-init-local-exstng.js create mode 100644 test/language/eval-code/direct/var-env-var-init-local-new-delete.js create mode 100644 test/language/eval-code/direct/var-env-var-init-local-new.js create mode 100644 test/language/eval-code/indirect/always-non-strict.js create mode 100644 test/language/eval-code/indirect/lex-env-distinct-cls.js create mode 100644 test/language/eval-code/indirect/lex-env-distinct-const.js create mode 100644 test/language/eval-code/indirect/lex-env-distinct-let.js create mode 100644 test/language/eval-code/indirect/lex-env-heritage.js create mode 100644 test/language/eval-code/indirect/lex-env-no-init-cls.js create mode 100644 test/language/eval-code/indirect/lex-env-no-init-const.js create mode 100644 test/language/eval-code/indirect/lex-env-no-init-let.js create mode 100644 test/language/eval-code/indirect/var-env-func-init-global-new.js create mode 100644 test/language/eval-code/indirect/var-env-func-init-global-update-configurable.js create mode 100644 test/language/eval-code/indirect/var-env-func-init-global-update-non-configurable.js create mode 100644 test/language/eval-code/indirect/var-env-func-init-multi.js create mode 100644 test/language/eval-code/indirect/var-env-global-lex-non-strict.js create mode 100644 test/language/eval-code/indirect/var-env-global-lex-strict.js create mode 100644 test/language/eval-code/indirect/var-env-lower-lex-non-strict.js create mode 100644 test/language/eval-code/indirect/var-env-lower-lex-strict.js create mode 100644 test/language/eval-code/indirect/var-env-var-init-global-exstng.js create mode 100644 test/language/eval-code/indirect/var-env-var-init-global-new.js create mode 100644 test/language/expressions/call/eval-err-args.js create mode 100644 test/language/expressions/call/eval-no-args.js create mode 100644 test/language/expressions/call/eval-strictness-inherit-non-strict.js create mode 100644 test/language/expressions/call/eval-strictness-inherit-strict.js diff --git a/test/language/eval-code/direct/lex-env-distinct-cls.js b/test/language/eval-code/direct/lex-env-distinct-cls.js new file mode 100644 index 0000000000..633018b682 --- /dev/null +++ b/test/language/eval-code/direct/lex-env-distinct-cls.js @@ -0,0 +1,33 @@ +// 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-performeval +description: > + Direct eval code creates a new declarative environment for lexically-scoped + declarations (class) +info: | + [...] + 9. If direct is true, then + a. Let lexEnv be NewDeclarativeEnvironment(ctx's LexicalEnvironment). + [...] +features: [class] +---*/ + +class outside {} + +eval('class outside {}'); +eval('"use strict"; class outside {}'); + +eval('class xNonStrict {}'); + +assert.sameValue(typeof xNonStrict, 'undefined'); +assert.throws(ReferenceError, function() { + xNonStrict; +}); + +eval('"use strict"; class xStrict {}'); + +assert.sameValue(typeof xStrict, 'undefined'); +assert.throws(ReferenceError, function() { + xStrict; +}); diff --git a/test/language/eval-code/direct/lex-env-distinct-const.js b/test/language/eval-code/direct/lex-env-distinct-const.js new file mode 100644 index 0000000000..8826b20d43 --- /dev/null +++ b/test/language/eval-code/direct/lex-env-distinct-const.js @@ -0,0 +1,33 @@ +// 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-performeval +description: > + Direct eval code creates a new declarative environment for lexically-scoped + declarations (const) +info: | + [...] + 9. If direct is true, then + a. Let lexEnv be NewDeclarativeEnvironment(ctx's LexicalEnvironment). + [...] +features: [const] +---*/ + +const outside = null; + +eval('const outside = null;'); +eval('"use strict"; const outside = null;'); + +eval('const xNonStrict = null;'); + +assert.sameValue(typeof xNonStrict, 'undefined'); +assert.throws(ReferenceError, function() { + xNonStrict; +}); + +eval('"use strict"; const xStrict = null;'); + +assert.sameValue(typeof xStrict, 'undefined'); +assert.throws(ReferenceError, function() { + xStrict; +}); diff --git a/test/language/eval-code/direct/lex-env-distinct-let.js b/test/language/eval-code/direct/lex-env-distinct-let.js new file mode 100644 index 0000000000..1166064e58 --- /dev/null +++ b/test/language/eval-code/direct/lex-env-distinct-let.js @@ -0,0 +1,33 @@ +// 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-performeval +description: > + Direct eval code creates a new declarative environment for lexically-scoped + declarations (let) +info: | + [...] + 9. If direct is true, then + a. Let lexEnv be NewDeclarativeEnvironment(ctx's LexicalEnvironment). + [...] +features: [let] +---*/ + +let outside = 23; + +eval('let outside;'); +eval('"use strict"; let outside;'); + +eval('let xNonStrict = 3;'); + +assert.sameValue(typeof xNonStrict, 'undefined'); +assert.throws(ReferenceError, function() { + xNonStrict; +}); + +eval('"use strict"; let xStrict = 3;'); + +assert.sameValue(typeof xStrict, 'undefined'); +assert.throws(ReferenceError, function() { + xStrict; +}); diff --git a/test/language/eval-code/direct/lex-env-heritage.js b/test/language/eval-code/direct/lex-env-heritage.js new file mode 100644 index 0000000000..4b399393d7 --- /dev/null +++ b/test/language/eval-code/direct/lex-env-heritage.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-performeval +description: > + Direct eval code sets the new declarative environment's outer environment + to that of the current context. +info: | + [...] + 9. If direct is true, then + a. Let lexEnv be NewDeclarativeEnvironment(ctx's LexicalEnvironment). + [...] +features: [let] +---*/ + +var actualStrict; +var actualNonStrict; + +let x = 'outside'; +{ + let x = 'inside'; + actualNonStrict = eval('x;'); + actualStrict = eval('"use strict"; x;'); +} + +assert.sameValue(actualNonStrict, 'inside', 'non strict mode'); +assert.sameValue(actualStrict, 'inside', 'strict mode'); diff --git a/test/language/eval-code/direct/lex-env-no-init-cls.js b/test/language/eval-code/direct/lex-env-no-init-cls.js new file mode 100644 index 0000000000..4fa56ba107 --- /dev/null +++ b/test/language/eval-code/direct/lex-env-no-init-cls.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-performeval +description: > + Direct eval code creates `class` bindings prior to evaluation, but does not + initialize them. +info: | + [...] + 14. For each element d in lexDeclarations do + a. NOTE Lexically declared names are only instantiated here but not + initialized. + b. For each element dn of the BoundNames of d do + i. If IsConstantDeclaration of d is true, then + 1. Perform ? lexEnvRec.CreateImmutableBinding(dn, true). + ii. Else, + 2. Perform ? lexEnvRec.CreateMutableBinding(dn, false). + [...] +features: [class] +---*/ + +assert.throws(ReferenceError, function() { + eval('typeof C; class C {}'); +}); diff --git a/test/language/eval-code/direct/lex-env-no-init-const.js b/test/language/eval-code/direct/lex-env-no-init-const.js new file mode 100644 index 0000000000..8fd8861dfa --- /dev/null +++ b/test/language/eval-code/direct/lex-env-no-init-const.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-performeval +description: > + Direct eval code creates `const` bindings prior to evaluation but does not + initialize them. +info: | + [...] + 14. For each element d in lexDeclarations do + a. NOTE Lexically declared names are only instantiated here but not + initialized. + b. For each element dn of the BoundNames of d do + i. If IsConstantDeclaration of d is true, then + 1. Perform ? lexEnvRec.CreateImmutableBinding(dn, true). + ii. Else, + 2. Perform ? lexEnvRec.CreateMutableBinding(dn, false). + [...] +features: [const] +---*/ + +assert.throws(ReferenceError, function() { + eval('typeof x; const x = null;'); +}); diff --git a/test/language/eval-code/direct/lex-env-no-init-let.js b/test/language/eval-code/direct/lex-env-no-init-let.js new file mode 100644 index 0000000000..c1cfa3d706 --- /dev/null +++ b/test/language/eval-code/direct/lex-env-no-init-let.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-performeval +description: > + Direct eval code creates `let` bindings prior to evaluation but does not + initialize them. +info: | + [...] + 14. For each element d in lexDeclarations do + a. NOTE Lexically declared names are only instantiated here but not + initialized. + b. For each element dn of the BoundNames of d do + i. If IsConstantDeclaration of d is true, then + 1. Perform ? lexEnvRec.CreateImmutableBinding(dn, true). + ii. Else, + 2. Perform ? lexEnvRec.CreateMutableBinding(dn, false). + [...] +features: [let] +---*/ + +assert.throws(ReferenceError, function() { + eval('typeof x; let x;'); +}); diff --git a/test/language/eval-code/direct/strictness-override.js b/test/language/eval-code/direct/strictness-override.js new file mode 100644 index 0000000000..cc4d0e1936 --- /dev/null +++ b/test/language/eval-code/direct/strictness-override.js @@ -0,0 +1,15 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Evaluated code honors a Use Strict Directive in the Directive Prologue +esid: sec-strict-mode-code +info: | + Eval code is strict mode code if it begins with a Directive Prologue that + contains a Use Strict Directive or if the call to eval is a direct eval + that is contained in strict mode code. +---*/ + +assert.throws(ReferenceError, function() { + eval('"use strict"; unresolvable = null;'); +}); diff --git a/test/language/eval-code/direct/this-value-func-strict.js b/test/language/eval-code/direct/this-value-func-strict-caller.js similarity index 100% rename from test/language/eval-code/direct/this-value-func-strict.js rename to test/language/eval-code/direct/this-value-func-strict-caller.js diff --git a/test/language/eval-code/direct/this-value-func-strict-source.js b/test/language/eval-code/direct/this-value-func-strict-source.js new file mode 100644 index 0000000000..c45025b1ea --- /dev/null +++ b/test/language/eval-code/direct/this-value-func-strict-source.js @@ -0,0 +1,17 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Direct eval code has the same `this` binding as the calling context (strict + function scope) +esid: sec-performeval +flags: [noStrict] +---*/ + +var thisValue; + +(function() { + thisValue = eval('"use strict"; this;'); +}()); + +assert.sameValue(thisValue, this); diff --git a/test/language/eval-code/direct/var-env-func-init-global-new.js b/test/language/eval-code/direct/var-env-func-init-global-new.js new file mode 100644 index 0000000000..ade372a2d9 --- /dev/null +++ b/test/language/eval-code/direct/var-env-func-init-global-new.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-evaldeclarationinstantiation +description: Initialization of new global property +info: | + [...] + 15. For each production f in functionsToInitialize, do + a. Let fn be the sole element of the BoundNames of f. + b. Let fo be the result of performing InstantiateFunctionObject for f + with argument lexEnv. + c. If varEnvRec is a global Environment Record, then + i. Perform ? varEnvRec.CreateGlobalFunctionBinding(fn, fo, true). + [...] + + 8.1.1.4.18 CreateGlobalFunctionBinding + + [...] + 5. If existingProp is undefined or existingProp.[[Configurable]] is true, + then + a. Let desc be the PropertyDescriptor{[[Value]]: V, [[Writable]]: true, + [[Enumerable]]: true, [[Configurable]]: D}. + 6. Else, + [...] + 7. Perform ? DefinePropertyOrThrow(globalObject, N, desc). + [...] +flags: [noStrict] +includes: [propertyHelper.js] +---*/ + +var initial; + +eval('initial = f; function f() { return 234; }'); + +verifyEnumerable(this, 'f'); +verifyWritable(this, 'f'); +verifyConfigurable(this, 'f'); +assert.sameValue(typeof initial, 'function'); +assert.sameValue(initial(), 234); diff --git a/test/language/eval-code/direct/var-env-func-init-global-update-configurable.js b/test/language/eval-code/direct/var-env-func-init-global-update-configurable.js new file mode 100644 index 0000000000..8d65f1c57b --- /dev/null +++ b/test/language/eval-code/direct/var-env-func-init-global-update-configurable.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-evaldeclarationinstantiation +description: Modification of previously-existing configurable global property +info: | + [...] + 15. For each production f in functionsToInitialize, do + a. Let fn be the sole element of the BoundNames of f. + b. Let fo be the result of performing InstantiateFunctionObject for f + with argument lexEnv. + c. If varEnvRec is a global Environment Record, then + i. Perform ? varEnvRec.CreateGlobalFunctionBinding(fn, fo, true). + [...] + + 8.1.1.4.18 CreateGlobalFunctionBinding + + [...] + 5. If existingProp is undefined or existingProp.[[Configurable]] is true, + then + a. Let desc be the PropertyDescriptor{[[Value]]: V, [[Writable]]: true, + [[Enumerable]]: true, [[Configurable]]: D}. + 6. Else, + [...] + 7. Perform ? DefinePropertyOrThrow(globalObject, N, desc). + [...] +flags: [noStrict] +includes: [propertyHelper.js] +---*/ + +var initial = null; + +Object.defineProperty(this, 'f', { + enumerable: false, + writable: false, + configurable: true +}); + +eval('initial = f; function f() { return 345; }'); + +verifyEnumerable(this, 'f'); +verifyWritable(this, 'f'); +verifyConfigurable(this, 'f'); +assert.sameValue(typeof initial, 'function'); +assert.sameValue(initial(), 345); diff --git a/test/language/eval-code/direct/var-env-func-init-global-update-non-configurable.js b/test/language/eval-code/direct/var-env-func-init-global-update-non-configurable.js new file mode 100644 index 0000000000..c423aeec15 --- /dev/null +++ b/test/language/eval-code/direct/var-env-func-init-global-update-non-configurable.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-evaldeclarationinstantiation +description: > + Modification of previously-existing non-configurable global property +info: | + [...] + 15. For each production f in functionsToInitialize, do + a. Let fn be the sole element of the BoundNames of f. + b. Let fo be the result of performing InstantiateFunctionObject for f + with argument lexEnv. + c. If varEnvRec is a global Environment Record, then + i. Perform ? varEnvRec.CreateGlobalFunctionBinding(fn, fo, true). + [...] + + 8.1.1.4.18 CreateGlobalFunctionBinding + + [...] + 5. If existingProp is undefined or existingProp.[[Configurable]] is true, + then + [...] + 6. Else, + b. Let desc be the PropertyDescriptor{[[Value]]: V }. + 7. Perform ? DefinePropertyOrThrow(globalObject, N, desc). + [...] +flags: [noStrict] +includes: [propertyHelper.js] +---*/ + +var initial; + +Object.defineProperty(this, 'f', { + enumerable: true, + writable: true, + configurable: false +}); + +eval('initial = f; function f() { return 2222; }'); + +verifyEnumerable(this, 'f'); +verifyWritable(this, 'f'); +verifyNotConfigurable(this, 'f'); +assert.sameValue(typeof initial, 'function'); +assert.sameValue(initial(), 2222); diff --git a/test/language/eval-code/direct/var-env-func-init-local-new-delete.js b/test/language/eval-code/direct/var-env-func-init-local-new-delete.js new file mode 100644 index 0000000000..243f5c16fd --- /dev/null +++ b/test/language/eval-code/direct/var-env-func-init-local-new-delete.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-evaldeclarationinstantiation +description: Newly-created local binding may be deleted +info: | + [...] + 15. For each production f in functionsToInitialize, do + a. Let fn be the sole element of the BoundNames of f. + b. Let fo be the result of performing InstantiateFunctionObject for f + with argument lexEnv. + c. If varEnvRec is a global Environment Record, then + [...] + d. Else, + i. Let bindingExists be varEnvRec.HasBinding(fn). + ii. If bindingExists is false, then + 1. Let status be ! varEnvRec.CreateMutableBinding(fn, true). + 2. Assert: status is not an abrupt completion because of + validation preceding step 12. + 3. Perform ! varEnvRec.InitializeBinding(fn, fo). + [...] +flags: [noStrict] +---*/ + +var initial, postDeletion; +(function() { + eval('initial = f; delete f; postDeletion = function() { f; }; function f() { return 33; }'); +}()); + +assert.sameValue(typeof initial, 'function'); +assert.sameValue(initial(), 33); +assert.throws(ReferenceError, postDeletion, 'binding may be deleted'); diff --git a/test/language/eval-code/direct/var-env-func-init-local-new.js b/test/language/eval-code/direct/var-env-func-init-local-new.js new file mode 100644 index 0000000000..2523e0afa3 --- /dev/null +++ b/test/language/eval-code/direct/var-env-func-init-local-new.js @@ -0,0 +1,35 @@ +// 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-evaldeclarationinstantiation +description: Initialization of new local binding +info: | + [...] + 15. For each production f in functionsToInitialize, do + a. Let fn be the sole element of the BoundNames of f. + b. Let fo be the result of performing InstantiateFunctionObject for f + with argument lexEnv. + c. If varEnvRec is a global Environment Record, then + [...] + d. Else, + i. Let bindingExists be varEnvRec.HasBinding(fn). + ii. If bindingExists is false, then + 1. Let status be ! varEnvRec.CreateMutableBinding(fn, true). + 2. Assert: status is not an abrupt completion because of + validation preceding step 12. + 3. Perform ! varEnvRec.InitializeBinding(fn, fo). + [...] +flags: [noStrict] +---*/ + +var initial, postAssignment; +(function() { + eval('initial = f; f = 5; postAssignment = f; function f() { return 33; }'); +}()); + +assert.sameValue(typeof initial, 'function'); +assert.sameValue(initial(), 33); +assert.sameValue(postAssignment, 5, 'binding is mutable'); +assert.throws(ReferenceError, function() { + f; +}); diff --git a/test/language/eval-code/direct/var-env-func-init-local-update.js b/test/language/eval-code/direct/var-env-func-init-local-update.js new file mode 100644 index 0000000000..21ffe67e41 --- /dev/null +++ b/test/language/eval-code/direct/var-env-func-init-local-update.js @@ -0,0 +1,35 @@ +// 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-evaldeclarationinstantiation +description: Re-declaration of an existing local variable binding +info: | + [...] + 15. For each production f in functionsToInitialize, do + a. Let fn be the sole element of the BoundNames of f. + b. Let fo be the result of performing InstantiateFunctionObject for f + with argument lexEnv. + c. If varEnvRec is a global Environment Record, then + [...] + d. Else, + i. Let bindingExists be varEnvRec.HasBinding(fn). + ii. If bindingExists is false, then + [...] + iii. Else, + 1. Perform ! varEnvRec.SetMutableBinding(fn, fo, false). + [...] +flags: [noStrict] +---*/ + +var initial; + +(function() { + var f = 88; + eval('initial = f; function f() { return 33; }'); +}()); + +assert.sameValue(typeof initial, 'function'); +assert.sameValue(initial(), 33); +assert.throws(ReferenceError, function() { + f; +}); diff --git a/test/language/eval-code/direct/var-env-func-init-multi.js b/test/language/eval-code/direct/var-env-func-init-multi.js new file mode 100644 index 0000000000..f0beefbf7f --- /dev/null +++ b/test/language/eval-code/direct/var-env-func-init-multi.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-evaldeclarationinstantiation +description: Precedence of final declaration when bindings are duplicated +info: | + [...] + 8. For each d in varDeclarations, in reverse list order do + a. If d is neither a VariableDeclaration or a ForBinding, then + i. Assert: d is either a FunctionDeclaration or a + GeneratorDeclaration. + [...] + iv. If fn is not an element of declaredFunctionNames, then + [...] + 3. Insert d as the first element of functionsToInitialize. + [...] + 15. For each production f in functionsToInitialize, do + a. Let fn be the sole element of the BoundNames of f. + b. Let fo be the result of performing InstantiateFunctionObject for f + with argument lexEnv. + [...] +flags: [noStrict] +---*/ + +var initial; + +eval('initial = f; function f() { return "first"; } function f() { return "second"; }'); + +assert.sameValue(initial(), 'second', 'initial value'); +assert.sameValue(f(), 'second', 'value following declaration evaluation'); diff --git a/test/language/eval-code/direct/var-env-gloabl-lex-strict-caller.js b/test/language/eval-code/direct/var-env-gloabl-lex-strict-caller.js new file mode 100644 index 0000000000..2ad3c8591a --- /dev/null +++ b/test/language/eval-code/direct/var-env-gloabl-lex-strict-caller.js @@ -0,0 +1,16 @@ +// 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-evaldeclarationinstantiation +description: No variable collision with global lexical binding +info: | + [...] + 5. If strict is false, then + [...] +flags: [onlyStrict] +features: [let] +---*/ + +let x; + +eval('var x;'); diff --git a/test/language/eval-code/direct/var-env-global-lex-non-strict.js b/test/language/eval-code/direct/var-env-global-lex-non-strict.js new file mode 100644 index 0000000000..364d4c5d59 --- /dev/null +++ b/test/language/eval-code/direct/var-env-global-lex-non-strict.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-evaldeclarationinstantiation +description: Variable collision with global lexical binding +info: | + [...] + 5. If strict is false, then + a. If varEnvRec is a global Environment Record, then + i. For each name in varNames, do + 1. If varEnvRec.HasLexicalDeclaration(name) is true, throw a + SyntaxError exception. + 2. NOTE: eval will not create a global var declaration that would + be shadowed by a global lexical declaration. + [...] +negative: SyntaxError +flags: [noStrict] +features: [let] +---*/ + +let x; + +// Although the `try` statement is a more precise mechanism for detecting +// runtime errors, the behavior under test is only observable for a direct eval +// call when the call is made from the global scope. This forces the use of +// the more coarse-grained `negative` frontmatter to assert the expected error. + +eval('var x;'); diff --git a/test/language/eval-code/direct/var-env-global-lex-strict-source.js b/test/language/eval-code/direct/var-env-global-lex-strict-source.js new file mode 100644 index 0000000000..1ab668d43b --- /dev/null +++ b/test/language/eval-code/direct/var-env-global-lex-strict-source.js @@ -0,0 +1,15 @@ +// 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-evaldeclarationinstantiation +description: No variable collision with global lexical binding +info: | + [...] + 5. If strict is false, then + [...] +features: [let] +---*/ + +let x; + +eval('"use strict"; var x;'); diff --git a/test/language/eval-code/direct/var-env-lower-lex-non-strict.js b/test/language/eval-code/direct/var-env-lower-lex-non-strict.js new file mode 100644 index 0000000000..ed4f09237a --- /dev/null +++ b/test/language/eval-code/direct/var-env-lower-lex-non-strict.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-evaldeclarationinstantiation +description: Variable collision with lexical binding in lower scope +info: | + [...] + 5. If strict is false, then + [...] + 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. + 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/eval-code/direct/var-env-lower-lex-strict-caller.js b/test/language/eval-code/direct/var-env-lower-lex-strict-caller.js new file mode 100644 index 0000000000..37c70814f8 --- /dev/null +++ b/test/language/eval-code/direct/var-env-lower-lex-strict-caller.js @@ -0,0 +1,19 @@ +// 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-evaldeclarationinstantiation +description: No variable collision with lexical binding in lower scope +info: | + [...] + 5. If strict is false, then + [...] +flags: [onlyStrict] +features: [let] +---*/ + +{ + let x; + { + eval('var x;'); + } +} diff --git a/test/language/eval-code/direct/var-env-lower-lex-strict-source.js b/test/language/eval-code/direct/var-env-lower-lex-strict-source.js new file mode 100644 index 0000000000..94a011684c --- /dev/null +++ b/test/language/eval-code/direct/var-env-lower-lex-strict-source.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-evaldeclarationinstantiation +description: No variable collision with lexical binding in lower scope +info: | + [...] + 5. If strict is false, then + [...] +features: [let] +---*/ + +{ + let x; + { + eval('"use strict"; var x;'); + } +} diff --git a/test/language/eval-code/direct/var-env-var-init-global-exstng.js b/test/language/eval-code/direct/var-env-var-init-global-exstng.js new file mode 100644 index 0000000000..f7fa64340a --- /dev/null +++ b/test/language/eval-code/direct/var-env-var-init-global-exstng.js @@ -0,0 +1,33 @@ +// 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-evaldeclarationinstantiation +description: Declaration does not modify existing global property +info: | + [...] + 16. For each String vn in declaredVarNames, in list order do + a. If varEnvRec is a global Environment Record, then + i. Perform ? varEnvRec.CreateGlobalVarBinding(vn, true). + [...] + + 8.1.1.4.17 CreateGlobalVarBinding + + [...] + 5. Let extensible be ? IsExtensible(globalObject). + 6. If hasProperty is false and extensible is true, then + [...] + [...] +flags: [noStrict] +includes: [propertyHelper.js] +---*/ + +var initial; +var x = 23; + +eval('initial = x; var x = 45;'); + +verifyEnumerable(this, 'x'); +verifyWritable(this, 'x'); +verifyNotConfigurable(this, 'x'); + +assert.sameValue(initial, 23); diff --git a/test/language/eval-code/direct/var-env-var-init-global-new.js b/test/language/eval-code/direct/var-env-var-init-global-new.js new file mode 100644 index 0000000000..38fb39113b --- /dev/null +++ b/test/language/eval-code/direct/var-env-var-init-global-new.js @@ -0,0 +1,33 @@ +// 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-evaldeclarationinstantiation +description: Initialization of new global property +info: | + [...] + 16. For each String vn in declaredVarNames, in list order do + a. If varEnvRec is a global Environment Record, then + i. Perform ? varEnvRec.CreateGlobalVarBinding(vn, true). + [...] + + 8.1.1.4.17 CreateGlobalVarBinding + + [...] + 5. Let extensible be ? IsExtensible(globalObject). + 6. If hasProperty is false and extensible is true, then + a. Perform ? ObjRec.CreateMutableBinding(N, D). + b. Perform ? ObjRec.InitializeBinding(N, undefined). + [...] +flags: [noStrict] +includes: [propertyHelper.js] +---*/ + +var initial = null; + +eval('initial = x; var x;'); + +verifyEnumerable(this, 'x'); +verifyWritable(this, 'x'); +verifyConfigurable(this, 'x'); + +assert.sameValue(initial, undefined); diff --git a/test/language/eval-code/direct/var-env-var-init-local-exstng.js b/test/language/eval-code/direct/var-env-var-init-local-exstng.js new file mode 100644 index 0000000000..74fe680950 --- /dev/null +++ b/test/language/eval-code/direct/var-env-var-init-local-exstng.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-evaldeclarationinstantiation +description: Re-declaration of an existing local variable binding has no effect +info: | + [...] + 16. For each String vn in declaredVarNames, in list order do + a. If varEnvRec is a global Environment Record, then + [...] + b. Else, + i. Let bindingExists be varEnvRec.HasBinding(vn). + ii. If bindingExists is false, then + [...] + [...] +flags: [noStrict] +---*/ + +var initial; + +(function() { + var x = 44443; + eval('initial = x; var x;'); +}()); + +assert.sameValue(initial, 44443); +assert.throws(ReferenceError, function() { + x; +}); diff --git a/test/language/eval-code/direct/var-env-var-init-local-new-delete.js b/test/language/eval-code/direct/var-env-var-init-local-new-delete.js new file mode 100644 index 0000000000..f751ae3368 --- /dev/null +++ b/test/language/eval-code/direct/var-env-var-init-local-new-delete.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-evaldeclarationinstantiation +description: Newly-created local binding may be deleted +info: | + [...] + 16. For each String vn in declaredVarNames, in list order do + a. If varEnvRec is a global Environment Record, then + [...] + b. Else, + i. Let bindingExists be varEnvRec.HasBinding(vn). + ii. If bindingExists is false, then + 1. Let status be ! varEnvRec.CreateMutableBinding(vn, true). + 2. Assert: status is not an abrupt completion because of + validation preceding step 12. + 3. Perform ! varEnvRec.InitializeBinding(vn, undefined). + [...] +flags: [noStrict] +---*/ + +var initial = null; +var postDeletion; + +(function() { + eval('initial = x; delete x; postDeletion = function() { x; }; var x;'); +}()); + +assert.sameValue(initial, undefined); +assert.throws(ReferenceError, postDeletion); diff --git a/test/language/eval-code/direct/var-env-var-init-local-new.js b/test/language/eval-code/direct/var-env-var-init-local-new.js new file mode 100644 index 0000000000..fe63f39ddb --- /dev/null +++ b/test/language/eval-code/direct/var-env-var-init-local-new.js @@ -0,0 +1,33 @@ +// 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-evaldeclarationinstantiation +description: Initialization of new variable binding +info: | + [...] + 16. For each String vn in declaredVarNames, in list order do + a. If varEnvRec is a global Environment Record, then + [...] + b. Else, + i. Let bindingExists be varEnvRec.HasBinding(vn). + ii. If bindingExists is false, then + 1. Let status be ! varEnvRec.CreateMutableBinding(vn, true). + 2. Assert: status is not an abrupt completion because of + validation preceding step 12. + 3. Perform ! varEnvRec.InitializeBinding(vn, undefined). + [...] +flags: [noStrict] +---*/ + +var initial = null; +var postAssignment; + +(function() { + eval('initial = x; x = 4; postAssignment = x; var x;'); +}()); + +assert.sameValue(initial, undefined); +assert.sameValue(postAssignment, 4, 'binding is mutable'); +assert.throws(ReferenceError, function() { + x; +}); diff --git a/test/language/eval-code/indirect/always-non-strict.js b/test/language/eval-code/indirect/always-non-strict.js new file mode 100644 index 0000000000..c58a74215b --- /dev/null +++ b/test/language/eval-code/indirect/always-non-strict.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. +/*--- +description: Strictness of direct eval is not dependent on strictness of caller +esid: sec-strict-mode-code +info: | + Eval code is strict mode code if it begins with a Directive Prologue that + contains a Use Strict Directive or if the call to eval is a direct eval + that is contained in strict mode code. +flags: [onlyStrict] +---*/ + +var count = 0; + +(0,eval)('var static; count += 1;'); + +assert.sameValue(count, 1); + +(0,eval)('with ({}) {} count += 1;'); + +assert.sameValue(count, 2); + +(0,eval)('unresolvable = null; count += 1;'); + +assert.sameValue(count, 3); diff --git a/test/language/eval-code/indirect/lex-env-distinct-cls.js b/test/language/eval-code/indirect/lex-env-distinct-cls.js new file mode 100644 index 0000000000..098fd61b6c --- /dev/null +++ b/test/language/eval-code/indirect/lex-env-distinct-cls.js @@ -0,0 +1,35 @@ +// 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-performeval +description: > + Indirect eval code creates a new declarative environment for + lexically-scoped declarations (class) +info: | + [...] + 9. If direct is true, then + [...] + 10. Else, + a. Let lexEnv be NewDeclarativeEnvironment(evalRealm.[[GlobalEnv]]). + [...] +features: [class] +---*/ + +class outside {} + +(0,eval)('class outside {}'); +(0,eval)('"use strict"; class outside {}'); + +(0,eval)('class xNonStrict {}'); + +assert.sameValue(typeof xNonStrict, 'undefined'); +assert.throws(ReferenceError, function() { + xNonStrict; +}); + +(0,eval)('"use strict"; class xStrict {}'); + +assert.sameValue(typeof xStrict, 'undefined'); +assert.throws(ReferenceError, function() { + xStrict; +}); diff --git a/test/language/eval-code/indirect/lex-env-distinct-const.js b/test/language/eval-code/indirect/lex-env-distinct-const.js new file mode 100644 index 0000000000..7a0cd95dfe --- /dev/null +++ b/test/language/eval-code/indirect/lex-env-distinct-const.js @@ -0,0 +1,35 @@ +// 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-performeval +description: > + Indirect eval code creates a new declarative environment for + lexically-scoped declarations (const) +info: | + [...] + 9. If direct is true, then + [...] + 10. Else, + a. Let lexEnv be NewDeclarativeEnvironment(evalRealm.[[GlobalEnv]]). + [...] +features: [const] +---*/ + +const outside = null; + +(0,eval)('const outside = null;'); +(0,eval)('"use strict"; const outside = null;'); + +(0,eval)('const xNonStrict = null;'); + +assert.sameValue(typeof xNonStrict, 'undefined'); +assert.throws(ReferenceError, function() { + xNonStrict; +}); + +(0,eval)('"use strict"; const xStrict = null;'); + +assert.sameValue(typeof xStrict, 'undefined'); +assert.throws(ReferenceError, function() { + xStrict; +}); diff --git a/test/language/eval-code/indirect/lex-env-distinct-let.js b/test/language/eval-code/indirect/lex-env-distinct-let.js new file mode 100644 index 0000000000..a354e19414 --- /dev/null +++ b/test/language/eval-code/indirect/lex-env-distinct-let.js @@ -0,0 +1,35 @@ +// 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-performeval +description: > + Indirect eval code creates a new declarative environment for + lexically-scoped declarations (let) +info: | + [...] + 9. If direct is true, then + [...] + 10. Else, + a. Let lexEnv be NewDeclarativeEnvironment(evalRealm.[[GlobalEnv]]). + [...] +features: [let] +---*/ + +let outside = 23; + +(0,eval)('let outside;'); +(0,eval)('"use strict"; let outside;'); + +(0,eval)('let xNonStrict = 3;'); + +assert.sameValue(typeof xNonStrict, 'undefined'); +assert.throws(ReferenceError, function() { + xNonStrict; +}); + +(0,eval)('"use strict"; let xStrict = 3;'); + +assert.sameValue(typeof xStrict, 'undefined'); +assert.throws(ReferenceError, function() { + xStrict; +}); diff --git a/test/language/eval-code/indirect/lex-env-heritage.js b/test/language/eval-code/indirect/lex-env-heritage.js new file mode 100644 index 0000000000..d349490295 --- /dev/null +++ b/test/language/eval-code/indirect/lex-env-heritage.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-performeval +description: > + Indirect eval code sets the new declarative environment's outer environment + to the global environment. +info: | + [...] + 9. If direct is true, then + [...] + 10. Else, + a. Let lexEnv be NewDeclarativeEnvironment(evalRealm.[[GlobalEnv]]). + [...] +features: [let] +---*/ + +var actualStrict; +var actualNonStrict; + +let x = 'outside'; +{ + let x = 'inside'; + actualNonStrict = (0,eval)('x;'); + actualStrict = (0,eval)('"use strict"; x;'); +} + +assert.sameValue(actualNonStrict, 'outside', 'non strict mode'); +assert.sameValue(actualStrict, 'outside', 'strict mode'); diff --git a/test/language/eval-code/indirect/lex-env-no-init-cls.js b/test/language/eval-code/indirect/lex-env-no-init-cls.js new file mode 100644 index 0000000000..c174b24f6a --- /dev/null +++ b/test/language/eval-code/indirect/lex-env-no-init-cls.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-performeval +description: > + Indirect eval code creates `class` bindings prior to evaluation, but does + not initialize them. +info: | + [...] + 14. For each element d in lexDeclarations do + a. NOTE Lexically declared names are only instantiated here but not + initialized. + b. For each element dn of the BoundNames of d do + i. If IsConstantDeclaration of d is true, then + 1. Perform ? lexEnvRec.CreateImmutableBinding(dn, true). + ii. Else, + 2. Perform ? lexEnvRec.CreateMutableBinding(dn, false). + [...] +features: [class] +---*/ + +assert.throws(ReferenceError, function() { + (0,eval)('typeof C; class C {}'); +}); diff --git a/test/language/eval-code/indirect/lex-env-no-init-const.js b/test/language/eval-code/indirect/lex-env-no-init-const.js new file mode 100644 index 0000000000..2b002f50b2 --- /dev/null +++ b/test/language/eval-code/indirect/lex-env-no-init-const.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-performeval +description: > + Indirect eval code creates `const` bindings prior to evaluation but does + not initialize them. +info: | + [...] + 14. For each element d in lexDeclarations do + a. NOTE Lexically declared names are only instantiated here but not + initialized. + b. For each element dn of the BoundNames of d do + i. If IsConstantDeclaration of d is true, then + 1. Perform ? lexEnvRec.CreateImmutableBinding(dn, true). + ii. Else, + 2. Perform ? lexEnvRec.CreateMutableBinding(dn, false). + [...] +features: [const] +---*/ + +assert.throws(ReferenceError, function() { + (0,eval)('typeof x; const x = null;'); +}); diff --git a/test/language/eval-code/indirect/lex-env-no-init-let.js b/test/language/eval-code/indirect/lex-env-no-init-let.js new file mode 100644 index 0000000000..6498d1d70c --- /dev/null +++ b/test/language/eval-code/indirect/lex-env-no-init-let.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-performeval +description: > + Indirect eval code creates `let` bindings prior to evaluation but does not + initialize them. +info: | + [...] + 14. For each element d in lexDeclarations do + a. NOTE Lexically declared names are only instantiated here but not + initialized. + b. For each element dn of the BoundNames of d do + i. If IsConstantDeclaration of d is true, then + 1. Perform ? lexEnvRec.CreateImmutableBinding(dn, true). + ii. Else, + 2. Perform ? lexEnvRec.CreateMutableBinding(dn, false). + [...] +features: [let] +---*/ + +assert.throws(ReferenceError, function() { + (0,eval)('typeof x; let x;'); +}); diff --git a/test/language/eval-code/indirect/var-env-func-init-global-new.js b/test/language/eval-code/indirect/var-env-func-init-global-new.js new file mode 100644 index 0000000000..4e87e8a7c6 --- /dev/null +++ b/test/language/eval-code/indirect/var-env-func-init-global-new.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-evaldeclarationinstantiation +description: Initialization of new global property +info: | + [...] + 15. For each production f in functionsToInitialize, do + a. Let fn be the sole element of the BoundNames of f. + b. Let fo be the result of performing InstantiateFunctionObject for f + with argument lexEnv. + c. If varEnvRec is a global Environment Record, then + i. Perform ? varEnvRec.CreateGlobalFunctionBinding(fn, fo, true). + [...] + + 8.1.1.4.18 CreateGlobalFunctionBinding + + [...] + 5. If existingProp is undefined or existingProp.[[Configurable]] is true, + then + a. Let desc be the PropertyDescriptor{[[Value]]: V, [[Writable]]: true, + [[Enumerable]]: true, [[Configurable]]: D}. + 6. Else, + [...] + 7. Perform ? DefinePropertyOrThrow(globalObject, N, desc). + [...] +includes: [propertyHelper.js] +---*/ + +var initial; + +(0, eval)('initial = f; function f() { return 234; }'); + +verifyEnumerable(this, 'f'); +verifyWritable(this, 'f'); +verifyConfigurable(this, 'f'); +assert.sameValue(typeof initial, 'function'); +assert.sameValue(initial(), 234); diff --git a/test/language/eval-code/indirect/var-env-func-init-global-update-configurable.js b/test/language/eval-code/indirect/var-env-func-init-global-update-configurable.js new file mode 100644 index 0000000000..f036e31826 --- /dev/null +++ b/test/language/eval-code/indirect/var-env-func-init-global-update-configurable.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-evaldeclarationinstantiation +description: Modification of previously-existing configurable global property +info: | + [...] + 15. For each production f in functionsToInitialize, do + a. Let fn be the sole element of the BoundNames of f. + b. Let fo be the result of performing InstantiateFunctionObject for f + with argument lexEnv. + c. If varEnvRec is a global Environment Record, then + i. Perform ? varEnvRec.CreateGlobalFunctionBinding(fn, fo, true). + [...] + + 8.1.1.4.18 CreateGlobalFunctionBinding + + [...] + 5. If existingProp is undefined or existingProp.[[Configurable]] is true, + then + a. Let desc be the PropertyDescriptor{[[Value]]: V, [[Writable]]: true, + [[Enumerable]]: true, [[Configurable]]: D}. + 6. Else, + [...] + 7. Perform ? DefinePropertyOrThrow(globalObject, N, desc). + [...] +includes: [propertyHelper.js] +---*/ + +var initial = null; + +Object.defineProperty(this, 'f', { + enumerable: false, + writable: false, + configurable: true +}); + +(0, eval)('initial = f; function f() { return 345; }'); + +verifyEnumerable(this, 'f'); +verifyWritable(this, 'f'); +verifyConfigurable(this, 'f'); +assert.sameValue(typeof initial, 'function'); +assert.sameValue(initial(), 345); diff --git a/test/language/eval-code/indirect/var-env-func-init-global-update-non-configurable.js b/test/language/eval-code/indirect/var-env-func-init-global-update-non-configurable.js new file mode 100644 index 0000000000..e20e5a6c86 --- /dev/null +++ b/test/language/eval-code/indirect/var-env-func-init-global-update-non-configurable.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-evaldeclarationinstantiation +description: > + Modification of previously-existing non-configurable global property +info: | + [...] + 15. For each production f in functionsToInitialize, do + a. Let fn be the sole element of the BoundNames of f. + b. Let fo be the result of performing InstantiateFunctionObject for f + with argument lexEnv. + c. If varEnvRec is a global Environment Record, then + i. Perform ? varEnvRec.CreateGlobalFunctionBinding(fn, fo, true). + [...] + + 8.1.1.4.18 CreateGlobalFunctionBinding + + [...] + 5. If existingProp is undefined or existingProp.[[Configurable]] is true, + then + [...] + 6. Else, + b. Let desc be the PropertyDescriptor{[[Value]]: V }. + 7. Perform ? DefinePropertyOrThrow(globalObject, N, desc). + [...] +includes: [propertyHelper.js] +---*/ + +var initial; + +Object.defineProperty(this, 'f', { + enumerable: true, + writable: true, + configurable: false +}); + +(0,eval)('initial = f; function f() { return 2222; }'); + +verifyEnumerable(this, 'f'); +verifyWritable(this, 'f'); +verifyNotConfigurable(this, 'f'); +assert.sameValue(typeof initial, 'function'); +assert.sameValue(initial(), 2222); diff --git a/test/language/eval-code/indirect/var-env-func-init-multi.js b/test/language/eval-code/indirect/var-env-func-init-multi.js new file mode 100644 index 0000000000..b0122ee8ea --- /dev/null +++ b/test/language/eval-code/indirect/var-env-func-init-multi.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-evaldeclarationinstantiation +description: Precedence of final declaration when bindings are duplicated +info: | + [...] + 8. For each d in varDeclarations, in reverse list order do + a. If d is neither a VariableDeclaration or a ForBinding, then + i. Assert: d is either a FunctionDeclaration or a + GeneratorDeclaration. + [...] + iv. If fn is not an element of declaredFunctionNames, then + [...] + 3. Insert d as the first element of functionsToInitialize. + [...] + 15. For each production f in functionsToInitialize, do + a. Let fn be the sole element of the BoundNames of f. + b. Let fo be the result of performing InstantiateFunctionObject for f + with argument lexEnv. + [...] +---*/ + +var initial; + +(0,eval)('initial = f; function f() { return "first"; } function f() { return "second"; }'); + +assert.sameValue(initial(), 'second', 'initial value'); +assert.sameValue(f(), 'second', 'value following declaration evaluation'); diff --git a/test/language/eval-code/indirect/var-env-global-lex-non-strict.js b/test/language/eval-code/indirect/var-env-global-lex-non-strict.js new file mode 100644 index 0000000000..b0a5c302f5 --- /dev/null +++ b/test/language/eval-code/indirect/var-env-global-lex-non-strict.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-evaldeclarationinstantiation +description: Variable collision with global lexical binding +info: | + [...] + 5. If strict is false, then + a. If varEnvRec is a global Environment Record, then + i. For each name in varNames, do + 1. If varEnvRec.HasLexicalDeclaration(name) is true, throw a + SyntaxError exception. + 2. NOTE: eval will not create a global var declaration that would + be shadowed by a global lexical declaration. + [...] +features: [let] +---*/ + +let x; +var caught; + +// The `assert.throws` helper function would interfere with the semantics under +// test. +try { + (0,eval)('var x;'); +} catch (err) { + caught = err; +} + +assert.notSameValue(caught, undefined); +assert.sameValue(caught.constructor, SyntaxError); diff --git a/test/language/eval-code/indirect/var-env-global-lex-strict.js b/test/language/eval-code/indirect/var-env-global-lex-strict.js new file mode 100644 index 0000000000..c2aa9f4da3 --- /dev/null +++ b/test/language/eval-code/indirect/var-env-global-lex-strict.js @@ -0,0 +1,15 @@ +// 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-evaldeclarationinstantiation +description: No variable collision with global lexical binding +info: | + [...] + 5. If strict is false, then + [...] +features: [let] +---*/ + +let x; + +(0,eval)('"use strict"; var x;'); diff --git a/test/language/eval-code/indirect/var-env-lower-lex-non-strict.js b/test/language/eval-code/indirect/var-env-lower-lex-non-strict.js new file mode 100644 index 0000000000..ccd06546ef --- /dev/null +++ b/test/language/eval-code/indirect/var-env-lower-lex-non-strict.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-evaldeclarationinstantiation +description: No variable collision with lexical binding in lower scope +info: | + [...] + 5. If strict is false, then + [...] + d. Repeat while thisLex is not the same as varEnv, + [...] +features: [let] +---*/ + +{ + let x; + { + (0,eval)('var x;'); + } +} diff --git a/test/language/eval-code/indirect/var-env-lower-lex-strict.js b/test/language/eval-code/indirect/var-env-lower-lex-strict.js new file mode 100644 index 0000000000..6f6e42581f --- /dev/null +++ b/test/language/eval-code/indirect/var-env-lower-lex-strict.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-evaldeclarationinstantiation +description: No variable collision with lexical binding in lower scope +info: | + [...] + 5. If strict is false, then + [...] +features: [let] +---*/ + +{ + let x; + { + (0,eval)('"use strict"; var x;'); + } +} diff --git a/test/language/eval-code/indirect/var-env-var-init-global-exstng.js b/test/language/eval-code/indirect/var-env-var-init-global-exstng.js new file mode 100644 index 0000000000..c08d4f55c7 --- /dev/null +++ b/test/language/eval-code/indirect/var-env-var-init-global-exstng.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-evaldeclarationinstantiation +description: Declaration does not modify existing global property +info: | + [...] + 16. For each String vn in declaredVarNames, in list order do + a. If varEnvRec is a global Environment Record, then + i. Perform ? varEnvRec.CreateGlobalVarBinding(vn, true). + [...] + + 8.1.1.4.17 CreateGlobalVarBinding + + [...] + 5. Let extensible be ? IsExtensible(globalObject). + 6. If hasProperty is false and extensible is true, then + [...] + [...] +includes: [propertyHelper.js] +---*/ + +var initial; +var x = 23; + +(0, eval)('initial = x; var x = 45;'); + +verifyEnumerable(this, 'x'); +verifyWritable(this, 'x'); +verifyNotConfigurable(this, 'x'); + +assert.sameValue(initial, 23); diff --git a/test/language/eval-code/indirect/var-env-var-init-global-new.js b/test/language/eval-code/indirect/var-env-var-init-global-new.js new file mode 100644 index 0000000000..daa9a1dbf6 --- /dev/null +++ b/test/language/eval-code/indirect/var-env-var-init-global-new.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-evaldeclarationinstantiation +description: Initialization of new global property +info: | + [...] + 16. For each String vn in declaredVarNames, in list order do + a. If varEnvRec is a global Environment Record, then + i. Perform ? varEnvRec.CreateGlobalVarBinding(vn, true). + [...] + + 8.1.1.4.17 CreateGlobalVarBinding + + [...] + 5. Let extensible be ? IsExtensible(globalObject). + 6. If hasProperty is false and extensible is true, then + a. Perform ? ObjRec.CreateMutableBinding(N, D). + b. Perform ? ObjRec.InitializeBinding(N, undefined). + [...] +includes: [propertyHelper.js] +---*/ + +var initial = null; + +(0, eval)('initial = x; var x = 9;'); + +verifyEnumerable(this, 'x'); +verifyWritable(this, 'x'); +verifyConfigurable(this, 'x'); + +assert.sameValue(initial, undefined); diff --git a/test/language/expressions/call/eval-err-args.js b/test/language/expressions/call/eval-err-args.js new file mode 100644 index 0000000000..a8fd5f4e69 --- /dev/null +++ b/test/language/expressions/call/eval-err-args.js @@ -0,0 +1,23 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Error evaluating arguments list for direct eval +esid: sec-function-calls-runtime-semantics-evaluation +info: | + [...] + 3. If Type(ref) is Reference and IsPropertyReference(ref) is false and + GetReferencedName(ref) is "eval", then + a. If SameValue(func, %eval%) is true, then + i. Let argList be ? ArgumentListEvaluation(Arguments). + + 12.3.6.1 Runtime Semantics: ArgumentListEvaluation + + ArgumentList : AssignmentExpression + + 1. Let ref be the result of evaluating AssignmentExpression. + 2. Let arg be ? GetValue(ref). +---*/ + +assert.throws(ReferenceError, function() { + eval(unresolvable); +}); diff --git a/test/language/expressions/call/eval-no-args.js b/test/language/expressions/call/eval-no-args.js new file mode 100644 index 0000000000..2cf827124f --- /dev/null +++ b/test/language/expressions/call/eval-no-args.js @@ -0,0 +1,15 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Error evaluating arguments list for direct eval +esid: sec-function-calls-runtime-semantics-evaluation +info: | + [...] + 3. If Type(ref) is Reference and IsPropertyReference(ref) is false and + GetReferencedName(ref) is "eval", then + a. If SameValue(func, %eval%) is true, then + i. Let argList be ? ArgumentListEvaluation(Arguments). + ii. If argList has no elements, return undefined. +---*/ + +assert.sameValue(eval(), undefined); diff --git a/test/language/expressions/call/eval-strictness-inherit-non-strict.js b/test/language/expressions/call/eval-strictness-inherit-non-strict.js new file mode 100644 index 0000000000..068e3b9559 --- /dev/null +++ b/test/language/expressions/call/eval-strictness-inherit-non-strict.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. +/*--- +description: Evaluated code honors the strictness of the calling context +esid: sec-function-calls-runtime-semantics-evaluation +info: | + [...] + 3. If Type(ref) is Reference and IsPropertyReference(ref) is false and + GetReferencedName(ref) is "eval", then + a. If SameValue(func, %eval%) is true, then + [...] + iv. If the source code matching this CallExpression is strict code, + let strictCaller be true. Otherwise let strictCaller be false. + [...] +flags: [noStrict] +---*/ + +var count = 0; + +eval('var static; count += 1;'); + +assert.sameValue(count, 1); + +eval('with ({}) {} count += 1;'); + +assert.sameValue(count, 2); + +eval('unresolvable = null; count += 1;'); + +assert.sameValue(count, 3); diff --git a/test/language/expressions/call/eval-strictness-inherit-strict.js b/test/language/expressions/call/eval-strictness-inherit-strict.js new file mode 100644 index 0000000000..0f7288b469 --- /dev/null +++ b/test/language/expressions/call/eval-strictness-inherit-strict.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. +/*--- +description: Evaluated code honors the strictness of the calling context +esid: sec-function-calls-runtime-semantics-evaluation +info: | + [...] + 3. If Type(ref) is Reference and IsPropertyReference(ref) is false and + GetReferencedName(ref) is "eval", then + a. If SameValue(func, %eval%) is true, then + [...] + iv. If the source code matching this CallExpression is strict code, + let strictCaller be true. Otherwise let strictCaller be false. + [...] +flags: [onlyStrict] +---*/ + +assert.throws(SyntaxError, function() { + eval('var static;'); +}); + +assert.throws(SyntaxError, function() { + eval('with ({}) {}'); +}); + +assert.throws(ReferenceError, function() { + eval('unresolvable = null;'); +});