diff --git a/test/language/statements/class/classelementname-abrupt-completion.js b/test/language/statements/class/classelementname-abrupt-completion.js new file mode 100644 index 0000000000..146df5e559 --- /dev/null +++ b/test/language/statements/class/classelementname-abrupt-completion.js @@ -0,0 +1,42 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Class definition should error if evaluation of ClassElementName errors +esid: runtime-semantics-class-definition-evaluation +info: | + Runtime Semantics: ClassDefinitionEvaluation + ... + 27. For each ClassElement e in order from elements + a. If IsStatic of e is false, then + i. Let fields be the result of performing ClassElementEvaluation for e with arguments proto and false. + b. Else, + i. Let fields be the result of performing ClassElementEvaluation for e with arguments F and false. + c. If fields is an abrupt completion, then + i. Set the running execution context's LexicalEnvironment to lex. + ii. Set the running execution context's PrivateNameEnvironment to outerPrivateEnvironment. + iii. Return Completion(status). + + Runtime Semantics: ClassElementEvaluation + ... + ClassElement : FieldDefinition ; + 1. Return ClassFieldDefinitionEvaluation of FieldDefinition with parameter false and object. + + Runtime Semantics: ClassFieldDefinitionEvaluation + With parameters isStatic and homeObject. + FieldDefinition : ClassElementNameInitializer + 1. Let fieldName be the result of evaluating ClassElementName. + 2. ReturnIfAbrupt(fieldName). + +features: [class-fields] +---*/ + +function f() { + throw new Test262Error(); +} + +assert.throws(Test262Error, function() { + class C { + [f()] + } +}); diff --git a/test/language/statements/class/fielddefinition-initializer-abrupt-completion.js b/test/language/statements/class/fielddefinition-initializer-abrupt-completion.js new file mode 100644 index 0000000000..090c8c9bc5 --- /dev/null +++ b/test/language/statements/class/fielddefinition-initializer-abrupt-completion.js @@ -0,0 +1,46 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Class construction should error if evaluation of field initializer errors +esid: sec-ecmascript-function-objects-construct-argumentslist-newtarget +info: | + [[Construct]] ( argumentsList, newTarget) + ... + 8. If kind is "base", then + a. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument). + b. Let result be InitializeInstanceFields(thisArgument, F). + c. If result is an abrupt completion, then + i. Remove calleeContext from execution context stack and restore callerContext as the running execution context. + ii. Return Completion(result). + + InitializeInstanceFields ( O, constructor ) + 1. Assert: Type ( O ) is Object. + 2. Assert: Assert constructor is an ECMAScript function object. + 3. Let fieldRecords be the value of constructor's [[Fields]] internal slot. + 4. For each item fieldRecord in order from fieldRecords, + a. If fieldRecord.[[static]] is false, then + i. Perform ? DefineField(O, fieldRecord). + + DefineField(receiver, fieldRecord) + 1. Assert: Type(receiver) is Object. + 2. Assert: fieldRecord is a Record as created by ClassFieldDefinitionEvaluation. + 3. Let fieldName be fieldRecord.[[Name]]. + 4. Let initializer be fieldRecord.[[Initializer]]. + 5. If initializer is not empty, then + a.Let initValue be ? Call(initializer, receiver). + +features: [class-fields] +---*/ + +function f() { + throw new Test262Error(); +} + +class C { + x = f(); +} + +assert.throws(Test262Error, function() { + new C(); +}) diff --git a/test/language/statements/class/privatefieldadd-typeerror.js b/test/language/statements/class/privatefieldadd-typeerror.js new file mode 100644 index 0000000000..bf51214567 --- /dev/null +++ b/test/language/statements/class/privatefieldadd-typeerror.js @@ -0,0 +1,60 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Class construction should error if attempting to add private field twice +esid: sec-ecmascript-function-objects-construct-argumentslist-newtarget +info: | + [[Construct]] ( argumentsList, newTarget) + ... + 8. If kind is "base", then + a. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument). + b. Let result be InitializeInstanceFields(thisArgument, F). + c. If result is an abrupt completion, then + i. Remove calleeContext from execution context stack and restore callerContext as the running execution context. + ii. Return Completion(result). + + InitializeInstanceFields ( O, constructor ) + 1. Assert: Type ( O ) is Object. + 2. Assert: Assert constructor is an ECMAScript function object. + 3. Let fieldRecords be the value of constructor's [[Fields]] internal slot. + 4. For each item fieldRecord in order from fieldRecords, + a. If fieldRecord.[[static]] is false, then + i. Perform ? DefineField(O, fieldRecord). + + DefineField(receiver, fieldRecord) + ... + 8. If fieldName is a Private Name, + a. Perform ? PrivateFieldAdd(fieldName, receiver, initValue). + + PrivateFieldAdd (P, O, value) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is not empty, throw a TypeError exception. + +features: [class-fields] +---*/ + + +class A { + constructor(arg) { + return arg; + } +} + +class C extends A { + #x; + + constructor(arg) { + super(arg); + } +} + +var containsprivatex = new C(); + +assert.throws(TypeError, function() { + // After the super call in C's constructor, the `this` value in C will + // already have "#x" in it's [[PrivateFieldValues]] + new C(containsprivatex); +}) diff --git a/test/language/statements/class/privatefieldget-success-1.js b/test/language/statements/class/privatefieldget-success-1.js new file mode 100644 index 0000000000..73836bd040 --- /dev/null +++ b/test/language/statements/class/privatefieldget-success-1.js @@ -0,0 +1,46 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Successfully access private field +esid: sec-getvalue +info: | + GetValue ( V ) + ... + 5. If IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Return ? PrivateFieldGet(field, base). + + PrivateFieldGet (P, O ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + 5. Return entry.[[PrivateFieldValue]]. + +features: [class-fields] +---*/ + +class Outer { + #x = 42; + + innerclass() { + var self = this; + + return class extends Outer { + f() { + return self.#x; + } + } + } +} + +var Inner = new Outer().innerclass(); +var i = new Inner(); +var value = i.f(); + +assert.sameValue(value, 42) diff --git a/test/language/statements/class/privatefieldget-success-2.js b/test/language/statements/class/privatefieldget-success-2.js new file mode 100644 index 0000000000..adc4e9a10f --- /dev/null +++ b/test/language/statements/class/privatefieldget-success-2.js @@ -0,0 +1,44 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Successfully access private field +esid: sec-getvalue +info: | + GetValue ( V ) + ... + 5. If IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Return ? PrivateFieldGet(field, base). + + PrivateFieldGet (P, O ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + 5. Return entry.[[PrivateFieldValue]]. + +features: [class-fields] +---*/ + + +class A { + #x = 'Avalue'; + x() { + return this.#x; + } +} +class B extends A { + #x = 'Bvalue'; + x() { + return this.#x; + } +} + +var b = new B(); + +assert.sameValue(b.x(), 'Bvalue') diff --git a/test/language/statements/class/privatefieldget-success-3.js b/test/language/statements/class/privatefieldget-success-3.js new file mode 100644 index 0000000000..d9722f5639 --- /dev/null +++ b/test/language/statements/class/privatefieldget-success-3.js @@ -0,0 +1,41 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Successfully access private field +esid: sec-getvalue +info: | + GetValue ( V ) + ... + 5. If IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Return ? PrivateFieldGet(field, base). + + PrivateFieldGet (P, O ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + 5. Return entry.[[PrivateFieldValue]]. + +features: [class-fields] +---*/ + + +class A { + #x = 'Avalue'; + x() { + return this.#x; + } +} +class B extends A { + #x = 'Bvalue'; +} + +var b = new B(); + +assert.sameValue(b.x(), 'Avalue') diff --git a/test/language/statements/class/privatefieldget-success-4.js b/test/language/statements/class/privatefieldget-success-4.js new file mode 100644 index 0000000000..7253d32f1c --- /dev/null +++ b/test/language/statements/class/privatefieldget-success-4.js @@ -0,0 +1,40 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Successfully access private field +esid: sec-getvalue +info: | + GetValue ( V ) + ... + 5. If IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Return ? PrivateFieldGet(field, base). + + PrivateFieldGet (P, O ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + 5. Return entry.[[PrivateFieldValue]]. + +features: [class-fields] +---*/ + + +class A { + #x = 'Avalue'; + x() { + return this.#x; + } +} +class B extends A { +} + +var b = new B(); + +assert.sameValue(b.x(), 'Avalue') diff --git a/test/language/statements/class/privatefieldget-success-5.js b/test/language/statements/class/privatefieldget-success-5.js new file mode 100644 index 0000000000..9bf09e9ea4 --- /dev/null +++ b/test/language/statements/class/privatefieldget-success-5.js @@ -0,0 +1,40 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Successfully access private field +esid: sec-getvalue +info: | + GetValue ( V ) + ... + 5. If IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Return ? PrivateFieldGet(field, base). + + PrivateFieldGet (P, O ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + 5. Return entry.[[PrivateFieldValue]]. + +features: [class-fields] +---*/ + + +class C { + #x = 42; + f() { + return this.#x; + } +} + +var c1 = new C(); +var c2 = new C(); +var value = c2.f.call(c1); + +assert.sameValue(value, 'Avalue'); diff --git a/test/language/statements/class/privatefieldget-typeerror-1.js b/test/language/statements/class/privatefieldget-typeerror-1.js new file mode 100644 index 0000000000..1f1f201449 --- /dev/null +++ b/test/language/statements/class/privatefieldget-typeerror-1.js @@ -0,0 +1,39 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Cannot access private field before the entry was added to [[PrivateFieldValues]] +esid: sec-getvalue +info: | + GetValue ( V ) + ... + 5. If IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Return ? PrivateFieldGet(field, base). + + PrivateFieldGet (P, O ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + + PrivateFieldFind (P, O) + 1. Assert: P is a Private Name value. + 2. Assert: O is an object with a [[PrivateFieldValues]] internal slot. + 3. For each element entry in O.[[PrivateFieldValues]], + a. If entry.[[PrivateName]] is P, return entry. + 4. Return empty. + +features: [class-fields] +---*/ + +class C { + y = this.#x; + #x; +} + +assert.throws(TypeError, function() { new C(); }) diff --git a/test/language/statements/class/privatefieldget-typeerror-2.js b/test/language/statements/class/privatefieldget-typeerror-2.js new file mode 100644 index 0000000000..4a5f6be656 --- /dev/null +++ b/test/language/statements/class/privatefieldget-typeerror-2.js @@ -0,0 +1,55 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: TypeError when referenced private field cannot be found in `this`'s [[PrivateFieldValues]] +esid: sec-getvalue +info: | + GetValue ( V ) + ... + 5. If IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Return ? PrivateFieldGet(field, base). + + PrivateFieldGet (P, O ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + + PrivateFieldFind (P, O) + 1. Assert: P is a Private Name value. + 2. Assert: O is an object with a [[PrivateFieldValues]] internal slot. + 3. For each element entry in O.[[PrivateFieldValues]], + a. If entry.[[PrivateName]] is P, return entry. + 4. Return empty. + +features: [class-fields] +---*/ + +class Outer { + #x = 42; + + innerclass() { + + // create class within in Outerclass -- the PrivateNameEnvironment binding for + // private field `#x` is resolvable. + return class { + f() { + return this.#x; + } + } + } +} + +var Inner = new Outer().innerclass(); +var i = new Inner(); + +assert.throws(TypeError, function() { + // when f() is called, the private field will not be found in Inner's `this` + i.f(); +}) diff --git a/test/language/statements/class/privatefieldget-typeerror-3.js b/test/language/statements/class/privatefieldget-typeerror-3.js new file mode 100644 index 0000000000..8c1ef2748b --- /dev/null +++ b/test/language/statements/class/privatefieldget-typeerror-3.js @@ -0,0 +1,55 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: TypeError when referenced private field cannot be found in `this`'s [[PrivateFieldValues]] +esid: sec-getvalue +info: | + GetValue ( V ) + ... + 5. If IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Return ? PrivateFieldGet(field, base). + + PrivateFieldGet (P, O ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + + PrivateFieldFind (P, O) + 1. Assert: P is a Private Name value. + 2. Assert: O is an object with a [[PrivateFieldValues]] internal slot. + 3. For each element entry in O.[[PrivateFieldValues]], + a. If entry.[[PrivateName]] is P, return entry. + 4. Return empty. + +features: [class-fields] +---*/ + +class Outer { + #x = 42; + + innerclass() { + + // create class within in Outerclass -- the PrivateNameEnvironment binding for + // private field `#x` is resolvable. + return class extends Outer { + f() { + return this.#x; + } + } + } +} + +var Inner = new Outer().innerclass(); +var i = new Inner(); + +assert.throws(TypeError, function() { + // when f() is called, the private field will not be found in Inner's `this` + i.f(); +}) diff --git a/test/language/statements/class/privatefieldget-typeerror-4.js b/test/language/statements/class/privatefieldget-typeerror-4.js new file mode 100644 index 0000000000..61f2d3a78d --- /dev/null +++ b/test/language/statements/class/privatefieldget-typeerror-4.js @@ -0,0 +1,53 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: TypeError when referenced private field cannot be found in `this`'s [[PrivateFieldValues]] +esid: sec-getvalue +info: | + GetValue ( V ) + ... + 5. If IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Return ? PrivateFieldGet(field, base). + + PrivateFieldGet (P, O ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + + PrivateFieldFind (P, O) + 1. Assert: P is a Private Name value. + 2. Assert: O is an object with a [[PrivateFieldValues]] internal slot. + 3. For each element entry in O.[[PrivateFieldValues]], + a. If entry.[[PrivateName]] is P, return entry. + 4. Return empty. + +features: [class-fields] +---*/ + +function classfactory() { + return class { + #x; + f() { + this.#x; + } + } +} + +var C1 = classfactory(); +var C2 = classfactory(); + +c1 = new C1(); +c2 = new C2(); + +assert.throws(TypeError, function() { + // when f() is called in class C1, the Private Name binding for #x in C1 will + // not found in C2's [[PrivateNameValues]] + c1.f.call(c2); +}) diff --git a/test/language/statements/class/privatefieldget-typeerror-5.js b/test/language/statements/class/privatefieldget-typeerror-5.js new file mode 100644 index 0000000000..ff1f3737c1 --- /dev/null +++ b/test/language/statements/class/privatefieldget-typeerror-5.js @@ -0,0 +1,58 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: TypeError when referenced private field cannot be found in `this`'s [[PrivateFieldValues]] +esid: sec-getvalue +info: | + GetValue ( V ) + ... + 5. If IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Return ? PrivateFieldGet(field, base). + + PrivateFieldGet (P, O ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + + PrivateFieldFind (P, O) + 1. Assert: P is a Private Name value. + 2. Assert: O is an object with a [[PrivateFieldValues]] internal slot. + 3. For each element entry in O.[[PrivateFieldValues]], + a. If entry.[[PrivateName]] is P, return entry. + 4. Return empty. + +features: [class-fields] +---*/ + +class Outer { + #x = 42; + + innerclass() { + var self = this; + + return class extends Outer { + #x = 'not42'; + f() { + return self.#x; + } + } + } +} + +var Inner = new Outer().innerclass(); +var i = new Inner(); + +assert.throws(TypeError, function() { + // when f() is called, the entry in the PrivateNameEnironment's environment + // record for '#x' will contain the Inner class's Private Name for '#x'. + // When this Private Name is used for lookup on the `self` object, it + // will not be found (as the `self` object has the Outer's Private Name for #x) + i.f(); +}) diff --git a/test/language/statements/class/privatefieldset-typeerror-1.js b/test/language/statements/class/privatefieldset-typeerror-1.js new file mode 100644 index 0000000000..ddd1a3f199 --- /dev/null +++ b/test/language/statements/class/privatefieldset-typeerror-1.js @@ -0,0 +1,39 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: TypeError when setting private field before the entry was added to [[PrivateFieldValues]] +esid: sec-putvalue +info: | + PutValue ( V, W ) + ... + 5. Else if IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Perform ? PrivateFieldSet(field, base, W). + + PrivateFieldSet (P, O, value ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + + PrivateFieldFind (P, O) + 1. Assert: P is a Private Name value. + 2. Assert: O is an object with a [[PrivateFieldValues]] internal slot. + 3. For each element entry in O.[[PrivateFieldValues]], + a. If entry.[[PrivateName]] is P, return entry. + 4. Return empty. + +features: [class-fields] +---*/ + +class C { + y = this.#x = 1; + #x; +} + +assert.throws(TypeError, function() { new C(); }) diff --git a/test/language/statements/class/privatefieldset-typeerror-2.js b/test/language/statements/class/privatefieldset-typeerror-2.js new file mode 100644 index 0000000000..8f83e513ea --- /dev/null +++ b/test/language/statements/class/privatefieldset-typeerror-2.js @@ -0,0 +1,55 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: TypeError when setting private field not in `this`'s [[PrivateFieldValues]] +esid: sec-putvalue +info: | + PutValue ( V, W ) + ... + 5. Else if IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Perform ? PrivateFieldSet(field, base, W). + + PrivateFieldSet (P, O, value ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + + PrivateFieldFind (P, O) + 1. Assert: P is a Private Name value. + 2. Assert: O is an object with a [[PrivateFieldValues]] internal slot. + 3. For each element entry in O.[[PrivateFieldValues]], + a. If entry.[[PrivateName]] is P, return entry. + 4. Return empty. + +features: [class-fields] +---*/ + +class Outer { + #x = 42; + + innerclass() { + + // create class within in Outerclass -- the PrivateNameEnvironment binding for + // private field `#x` is resolvable. + return class { + f() { + this.#x = 1; + } + } + } +} + +var Inner = new Outer().innerclass(); +var i = new Inner(); + +assert.throws(TypeError, function() { + // when f() is called, the private field will not be found in Inner's `this` + i.f(); +}) diff --git a/test/language/statements/class/privatefieldset-typeerror-3.js b/test/language/statements/class/privatefieldset-typeerror-3.js new file mode 100644 index 0000000000..4a0bfabd90 --- /dev/null +++ b/test/language/statements/class/privatefieldset-typeerror-3.js @@ -0,0 +1,55 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: TypeError when setting private field not in `this`'s [[PrivateFieldValues]] +esid: sec-putvalue +info: | + PutValue ( V, W ) + ... + 5. Else if IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Perform ? PrivateFieldSet(field, base, W). + + PrivateFieldSet (P, O, value ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + + PrivateFieldFind (P, O) + 1. Assert: P is a Private Name value. + 2. Assert: O is an object with a [[PrivateFieldValues]] internal slot. + 3. For each element entry in O.[[PrivateFieldValues]], + a. If entry.[[PrivateName]] is P, return entry. + 4. Return empty. + +features: [class-fields] +---*/ + +class Outer { + #x = 42; + + innerclass() { + + // create class within in Outerclass -- the PrivateNameEnvironment binding for + // private field `#x` is resolvable. + return class extends Outer { + f() { + this.#x = 1; + } + } + } +} + +var Inner = new Outer().innerclass(); +var i = new Inner(); + +assert.throws(TypeError, function() { + // when f() is called, the private field will not be found in Inner's `this` + i.f(); +}) diff --git a/test/language/statements/class/privatefieldset-typeerror-4.js b/test/language/statements/class/privatefieldset-typeerror-4.js new file mode 100644 index 0000000000..d3dc0ab966 --- /dev/null +++ b/test/language/statements/class/privatefieldset-typeerror-4.js @@ -0,0 +1,53 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: TypeError when setting private field not in `this`'s [[PrivateFieldValues]] +esid: sec-putvalue +info: | + PutValue ( V, W ) + ... + 5. Else if IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Perform ? PrivateFieldSet(field, base, W). + + PrivateFieldSet (P, O, value ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + + PrivateFieldFind (P, O) + 1. Assert: P is a Private Name value. + 2. Assert: O is an object with a [[PrivateFieldValues]] internal slot. + 3. For each element entry in O.[[PrivateFieldValues]], + a. If entry.[[PrivateName]] is P, return entry. + 4. Return empty. + +features: [class-fields] +---*/ + +function classfactory() { + return class { + #x; + f() { + this.#x = 1; + } + } +} + +var C1 = classfactory(); +var C2 = classfactory(); + +c1 = new C1(); +c2 = new C2(); + +assert.throws(TypeError, function() { + // when f() is called in class C1, the Private Name binding for #x in C1 will + // not found in C2's [[PrivateNameValues]] + c1.f.call(c2); +}) diff --git a/test/language/statements/class/privatefieldset-typeerror-5.js b/test/language/statements/class/privatefieldset-typeerror-5.js new file mode 100644 index 0000000000..7ccdc75e85 --- /dev/null +++ b/test/language/statements/class/privatefieldset-typeerror-5.js @@ -0,0 +1,59 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: TypeError when setting private field not in `this`'s [[PrivateFieldValues]] +esid: sec-putvalue +info: | + PutValue ( V, W ) + ... + 5. Else if IsPropertyReference(V), then + ... + b. If IsPrivateReference(V), then + i. Let env be the running execution context's PrivateNameEnvironment. + ii. Let field be ? ResolveBinding(GetReferencedName(V), env). + iii. Assert: field is a Private Name. + iv. Perform ? PrivateFieldSet(field, base, W). + + PrivateFieldSet (P, O, value ) + 1. Assert: P is a Private Name value. + 2. If O is not an object, throw a TypeError exception. + 3. Let entry be PrivateFieldFind(P, O). + 4. If entry is empty, throw a TypeError exception. + + PrivateFieldFind (P, O) + 1. Assert: P is a Private Name value. + 2. Assert: O is an object with a [[PrivateFieldValues]] internal slot. + 3. For each element entry in O.[[PrivateFieldValues]], + a. If entry.[[PrivateName]] is P, return entry. + 4. Return empty. + +features: [class-fields] +---*/ + + +class Outer { + #x = 42; + + innerclass() { + var self = this; + + return class extends Outer { + #x = 'not42'; + f() { + self.#x = 1; + } + } + } +} + +var Inner = new Outer().innerclass(); +var i = new Inner(); + +assert.throws(TypeError, function() { + // when f() is called, the entry in the PrivateNameEnironment's environment + // record for '#x' will contain the Inner class's Private Name for '#x'. + // When this Private Name is used for lookup on the `self` object, it + // will not be found (as the `self` object has the Outer's Private Name for #x) + i.f(); +}) diff --git a/test/language/statements/class/static-classelementname-abrupt-completion.js b/test/language/statements/class/static-classelementname-abrupt-completion.js new file mode 100644 index 0000000000..d86d1f30d8 --- /dev/null +++ b/test/language/statements/class/static-classelementname-abrupt-completion.js @@ -0,0 +1,42 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Class definition should error if evaluation of static ClassElementName errors +esid: runtime-semantics-class-definition-evaluation +info: | + Runtime Semantics: ClassDefinitionEvaluation + ... + 27. For each ClassElement e in order from elements + a. If IsStatic of e is false, then + i. Let fields be the result of performing ClassElementEvaluation for e with arguments proto and false. + b. Else, + i. Let fields be the result of performing ClassElementEvaluation for e with arguments F and false. + c. If fields is an abrupt completion, then + i. Set the running execution context's LexicalEnvironment to lex. + ii. Set the running execution context's PrivateNameEnvironment to outerPrivateEnvironment. + iii. Return Completion(status). + + Runtime Semantics: ClassElementEvaluation + ... + ClassElement : static FieldDefinition ; + 1. Return ClassFieldDefinitionEvaluation of FieldDefinition with parameter true and object. + + Runtime Semantics: ClassFieldDefinitionEvaluation + With parameters isStatic and homeObject. + FieldDefinition : ClassElementNameInitializer + 1. Let fieldName be the result of evaluating ClassElementName. + 2. ReturnIfAbrupt(fieldName). + +features: [class-fields] +---*/ + +function f() { + throw new Test262Error(); +} + +assert.throws(Test262Error, function() { + class C { + static [f()] + } +}); diff --git a/test/language/statements/class/static-fielddefinition-initializer-abrupt-completion.js b/test/language/statements/class/static-fielddefinition-initializer-abrupt-completion.js new file mode 100644 index 0000000000..226586d8b7 --- /dev/null +++ b/test/language/statements/class/static-fielddefinition-initializer-abrupt-completion.js @@ -0,0 +1,42 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Class construction should error if evaluation of static field initializer errors +esid: runtime-semantics-class-definition-evaluation +info: | + Runtime Semantics: ClassDefinitionEvaluation + ... + 33. Let result be InitializeStaticFields(F). + 34. If result is an abrupt completion, then + a. Set the running execution context's LexicalEnvironment to lex. + b. Return Completion(result). + + InitializeStaticFields(F) + 1. Assert: Type(F) is Object. + 2. Assert: F is an ECMAScript function object. + 3. Let fieldRecords be the value of F's [[Fields]] internal slot. + 4. For each item fieldRecord in order from fieldRecords, + a. If fieldRecord.[[static]] is true, then + i. Perform ? DefineField(F, fieldRecord). + + DefineField(receiver, fieldRecord) + 1. Assert: Type(receiver) is Object. + 2. Assert: fieldRecord is a Record as created by ClassFieldDefinitionEvaluation. + 3. Let fieldName be fieldRecord.[[Name]]. + 4. Let initializer be fieldRecord.[[Initializer]]. + 5. If initializer is not empty, then + a. Let initValue be ? Call(initializer, receiver). + +features: [class-fields] +---*/ + +function f() { + throw new Test262Error(); +} + +assert.throws(Test262Error, function() { + class C { + static x = f(); + } +}) diff --git a/test/language/statements/class/super-fielddefinition-initializer-abrupt-completion.js b/test/language/statements/class/super-fielddefinition-initializer-abrupt-completion.js new file mode 100644 index 0000000000..da97ab0215 --- /dev/null +++ b/test/language/statements/class/super-fielddefinition-initializer-abrupt-completion.js @@ -0,0 +1,56 @@ +// Copyright (C) 2017 Valerie Young. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Class construction should error if evaluation of field initializer in super errors +esid: sec-super-keyword-runtime-semantics-evaluation +info: | + Runtime Semantics: Evaluation + SuperCall : superArguments + 1. Let newTarget be GetNewTarget(). + 2. If newTarget is undefined, throw a ReferenceError exception. + 3. Let func be ? GetSuperConstructor(). + 4. Let argList be ArgumentListEvaluation of Arguments. + 5. ReturnIfAbrupt(argList). + 6. Let result be ? Construct(func, argList, newTarget). + 7. Let thisER be GetThisEnvironment( ). + 8. Let F be thisER.[[FunctionObject]]. + 9. Assert: F is an ECMAScript function object. + 10. Perform ? InitializeInstanceFields(result, F). + + InitializeInstanceFields ( O, constructor ) + 1. Assert: Type ( O ) is Object. + 2. Assert: Assert constructor is an ECMAScript function object. + 3. Let fieldRecords be the value of constructor's [[Fields]] internal slot. + 4. For each item fieldRecord in order from fieldRecords, + a. If fieldRecord.[[static]] is false, then + i. Perform ? DefineField(O, fieldRecord). + + DefineField(receiver, fieldRecord) + 1. Assert: Type(receiver) is Object. + 2. Assert: fieldRecord is a Record as created by ClassFieldDefinitionEvaluation. + 3. Let fieldName be fieldRecord.[[Name]]. + 4. Let initializer be fieldRecord.[[Initializer]]. + 5. If initializer is not empty, then + a.Let initValue be ? Call(initializer, receiver). + +features: [class-fields] +---*/ + +function f() { + throw new Test262Error(); +} + +class A { + x = f(); +} + +class C extends A { + constructor() { + super(); + } +} + +assert.throws(Test262Error, function() { + new C(); +})