diff --git a/test/language/destructuring/binding/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js b/test/language/destructuring/binding/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js new file mode 100644 index 00000000000..bebf90a996a --- /dev/null +++ b/test/language/destructuring/binding/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js @@ -0,0 +1,100 @@ +// Copyright (C) 2024 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-destructuring-binding-patterns-runtime-semantics-propertybindinginitialization +description: > + Ensure correct evaluation order for binding lookups when destructuring target is var-binding. +info: | + 14.3.3.1 Runtime Semantics: PropertyBindingInitialization + + BindingProperty : PropertyName : BindingElement + + 1. Let P be ? Evaluation of PropertyName. + 2. Perform ? KeyedBindingInitialization of BindingElement with arguments value, environment, and P. + ... + + 14.3.3.3 Runtime Semantics: KeyedBindingInitialization + + SingleNameBinding : BindingIdentifier Initializer_opt + + 1. Let bindingId be the StringValue of BindingIdentifier. + 2. Let lhs be ? ResolveBinding(bindingId, environment). + 3. Let v be ? GetV(value, propertyName). + 4. If Initializer is present and v is undefined, then + ... + b. Else, + i. Let defaultValue be ? Evaluation of Initializer. + ii. Set v to ? GetValue(defaultValue). + ... + 6. Return ? InitializeReferencedBinding(lhs, v). + + 9.4.2 ResolveBinding ( name [ , env ] ) + + ... + 4. Return ? GetIdentifierReference(env, name, strict). + + 9.1.2.1 GetIdentifierReference ( env, name, strict ) + + ... + 2. Let exists be ? env.HasBinding(name). + ... + +includes: [compareArray.js] +features: [Proxy] +flags: [noStrict] +---*/ + +var log = []; + +var targetKey = { + toString: () => { + log.push("targetKey"); + return "q"; + } +}; + +var sourceKey = { + toString: () => { + log.push("sourceKey"); + return "p"; + } +}; + +var source = { + get p() { + log.push("get source"); + return undefined; + } +}; + +var target = { + set q(v) { + log.push("set target:"); + }, +}; + +var env = new Proxy({}, { + has(t, pk) { + log.push("binding::" + pk); + } +}); + +var defaultValue = 0; + +var varTarget; + +with (env) { + var { + [sourceKey]: varTarget = defaultValue + } = source; +} + +assert.compareArray(log, [ + "binding::source", + "binding::sourceKey", + "sourceKey", + "binding::varTarget", + "get source", + "binding::defaultValue", +]); diff --git a/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js b/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js new file mode 100644 index 00000000000..39549f1e794 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js @@ -0,0 +1,90 @@ +// Copyright (C) 2024 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-runtime-semantics-propertydestructuringassignmentevaluation +description: > + Ensure correct evaluation order for binding lookups when destructuring target is var-binding. +info: | + 13.15.5.3 Runtime Semantics: PropertyDestructuringAssignmentEvaluation + + AssignmentProperty : PropertyName : AssignmentElement + + 1. Let name be ? Evaluation of PropertyName. + 2. Perform ? KeyedDestructuringAssignmentEvaluation of AssignmentElement with arguments value and name. + ... + + 13.15.5.6 Runtime Semantics: KeyedDestructuringAssignmentEvaluation + + AssignmentElement : DestructuringAssignmentTarget Initializer_opt + + 1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then + a. Let lRef be ? Evaluation of DestructuringAssignmentTarget. + 2. Let v be ? GetV(value, propertyName). + 3. If Initializer is present and v is undefined, then + ... + b. Else, + i. Let defaultValue be ? Evaluation of Initializer. + ii. Let rhsValue be ? GetValue(defaultValue). + ... + 6. Return ? PutValue(lRef, rhsValue). + +includes: [compareArray.js] +features: [Proxy] +flags: [noStrict] +---*/ + +var log = []; + +var targetKey = { + toString: () => { + log.push("targetKey"); + return "q"; + } +}; + +var sourceKey = { + toString: () => { + log.push("sourceKey"); + return "p"; + } +}; + +var source = { + get p() { + log.push("get source"); + return undefined; + } +}; + +var target = { + set q(v) { + log.push("set target"); + }, +}; + +var env = new Proxy({}, { + has(t, pk) { + log.push("binding::" + pk); + } +}); + +var defaultValue = 0; + +with (env) { + ({ + [sourceKey]: target[targetKey] = defaultValue + } = source); +} + +assert.compareArray(log, [ + "binding::source", + "binding::sourceKey", + "sourceKey", + "binding::target", + "binding::targetKey", + "get source", + "binding::defaultValue", + "targetKey", + "set target", +]); diff --git a/test/language/expressions/delete/super-property-topropertykey.js b/test/language/expressions/delete/super-property-topropertykey.js new file mode 100644 index 00000000000..d8019b64450 --- /dev/null +++ b/test/language/expressions/delete/super-property-topropertykey.js @@ -0,0 +1,32 @@ +// Copyright (C) 2024 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-delete-operator-runtime-semantics-evaluation +description: > + ToPropertyKey not performed when deleting a super reference. +info: | + 13.5.1.2 Runtime Semantics: Evaluation + + UnaryExpression : delete UnaryExpression + + 1. Let ref be ? Evaluation of UnaryExpression. + ... + 4. If IsPropertyReference(ref) is true, then + ... + b. If IsSuperReference(ref) is true, throw a ReferenceError exception. +---*/ + +var key = { + toString() { + throw new Test262Error("ToPropertyKey performed"); + } +}; + +var obj = { + m() { + delete super[key]; + } +}; + +assert.throws(ReferenceError, () => obj.m()); diff --git a/test/language/expressions/delete/super-property-uninitialized-this.js b/test/language/expressions/delete/super-property-uninitialized-this.js new file mode 100644 index 00000000000..56c0a72c61d --- /dev/null +++ b/test/language/expressions/delete/super-property-uninitialized-this.js @@ -0,0 +1,43 @@ +// Copyright (C) 2024 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-delete-operator-runtime-semantics-evaluation +description: > + Element expression in delete super not evaluated when this is uninitialized. +info: | + 13.5.1.2 Runtime Semantics: Evaluation + + UnaryExpression : delete UnaryExpression + + 1. Let ref be ? Evaluation of UnaryExpression. + ... + + 13.3.7.1 Runtime Semantics: Evaluation + + SuperProperty : super [ Expression ] + + ... + 2. Let actualThis be ? env.GetThisBinding(). + 3. Let propertyNameReference be ? Evaluation of Expression. + ... + + 9.1.1.3.4 GetThisBinding ( ) + ... + 2. If envRec.[[ThisBindingStatus]] is uninitialized, throw a ReferenceError exception. + ... +---*/ + +class Base { + constructor() { + throw new Test262Error("base constructor called"); + } +} + +class Derived extends Base { + constructor() { + delete super[(super(), 0)]; + } +} + +assert.throws(ReferenceError, () => new Derived); diff --git a/test/language/expressions/object/computed-property-name-topropertykey-before-value-evaluation.js b/test/language/expressions/object/computed-property-name-topropertykey-before-value-evaluation.js new file mode 100644 index 00000000000..89844c85985 --- /dev/null +++ b/test/language/expressions/object/computed-property-name-topropertykey-before-value-evaluation.js @@ -0,0 +1,44 @@ +// Copyright (C) 2024 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-runtime-semantics-propertydefinitionevaluation +description: > + ToPropertyKey is performed before evaluating the value expression. +info: | + 13.2.5.5 Runtime Semantics: PropertyDefinitionEvaluation + + PropertyDefinition : PropertyName : AssignmentExpression + + 1. Let propKey be ? Evaluation of PropertyName. + ... + 6. Else, + a. Let exprValueRef be ? Evaluation of AssignmentExpression. + b. Let propValue be ? GetValue(exprValueRef). + ... + 9. Perform ! CreateDataPropertyOrThrow(object, propKey, propValue). + ... + + 13.2.5.4 Runtime Semantics: Evaluation + + ComputedPropertyName : [ AssignmentExpression ] + + 1. Let exprValue be ? Evaluation of AssignmentExpression. + 2. Let propName be ? GetValue(exprValue). + 3. Return ? ToPropertyKey(propName). +---*/ + +var value = "bad"; + +var key = { + toString() { + value = "ok"; + return "p"; + } +}; + +var obj = { + [key]: value +}; + +assert.sameValue(obj.p, "ok"); diff --git a/test/language/expressions/super/prop-expr-getsuperbase-before-topropertykey-getvalue.js b/test/language/expressions/super/prop-expr-getsuperbase-before-topropertykey-getvalue.js new file mode 100644 index 00000000000..a79f87c9122 --- /dev/null +++ b/test/language/expressions/super/prop-expr-getsuperbase-before-topropertykey-getvalue.js @@ -0,0 +1,60 @@ +// Copyright (C) 2024 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-super-keyword-runtime-semantics-evaluation +description: > + GetSuperBase is performed before ToPropertyKey in GetValue. +info: | + 13.3.7.1 Runtime Semantics: Evaluation + + SuperProperty : super [ Expression ] + + ... + 2. Let actualThis be ? env.GetThisBinding(). + 3. Let propertyNameReference be ? Evaluation of Expression. + 4. Let propertyNameValue be ? GetValue(propertyNameReference). + ... + 7. Return ? MakeSuperPropertyReference(actualThis, propertyNameValue, strict). + + 13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict ) + + 1. Let env be GetThisEnvironment(). + ... + 3. Let baseValue be ? env.GetSuperBase(). + ... + + 6.2.5.5 GetValue ( V ) + + ... + 3. If IsPropertyReference(V) is true, then + ... + c. If V.[[ReferencedName]] is not a property key, then + i. Set V.[[ReferencedName]] to ? ToPropertyKey(V.[[ReferencedName]]). + d. Return ? baseObj.[[Get]](V.[[ReferencedName]], GetThisValue(V)). + ... +---*/ + +var proto = { + p: "ok", +}; + +var proto2 = { + p: "bad", +}; + +var obj = { + __proto__: proto, + m() { + return super[key]; + } +}; + +var key = { + toString() { + Object.setPrototypeOf(obj, proto2); + return "p"; + } +}; + +assert.sameValue(obj.m(), "ok"); diff --git a/test/language/expressions/super/prop-expr-getsuperbase-before-topropertykey-putvalue-compound-assign.js b/test/language/expressions/super/prop-expr-getsuperbase-before-topropertykey-putvalue-compound-assign.js new file mode 100644 index 00000000000..7645e08adaf --- /dev/null +++ b/test/language/expressions/super/prop-expr-getsuperbase-before-topropertykey-putvalue-compound-assign.js @@ -0,0 +1,60 @@ +// Copyright (C) 2024 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-super-keyword-runtime-semantics-evaluation +description: > + GetSuperBase is performed before ToPropertyKey in PutValue with compound assignment. +info: | + 13.3.7.1 Runtime Semantics: Evaluation + + SuperProperty : super [ Expression ] + + ... + 2. Let actualThis be ? env.GetThisBinding(). + 3. Let propertyNameReference be ? Evaluation of Expression. + 4. Let propertyNameValue be ? GetValue(propertyNameReference). + ... + 7. Return ? MakeSuperPropertyReference(actualThis, propertyNameValue, strict). + + 13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict ) + + 1. Let env be GetThisEnvironment(). + ... + 3. Let baseValue be ? env.GetSuperBase(). + ... + + 6.2.5.6 PutValue ( V, W ) + + 3. If IsPropertyReference(V) is true, then + ... + c. If V.[[ReferencedName]] is not a property key, then + i. Set V.[[ReferencedName]] to ? ToPropertyKey(V.[[ReferencedName]]). + d. Let succeeded be ? baseObj.[[Set]](V.[[ReferencedName]], W, GetThisValue(V)). + ... + ... +---*/ + +var proto = { + p: 1, +}; + +var proto2 = { + p: -1, +}; + +var obj = { + __proto__: proto, + m() { + return super[key] += 1; + } +}; + +var key = { + toString() { + Object.setPrototypeOf(obj, proto2); + return "p"; + } +}; + +assert.sameValue(obj.m(), 2); diff --git a/test/language/expressions/super/prop-expr-getsuperbase-before-topropertykey-putvalue-increment.js b/test/language/expressions/super/prop-expr-getsuperbase-before-topropertykey-putvalue-increment.js new file mode 100644 index 00000000000..75e7b4d5401 --- /dev/null +++ b/test/language/expressions/super/prop-expr-getsuperbase-before-topropertykey-putvalue-increment.js @@ -0,0 +1,60 @@ +// Copyright (C) 2024 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-super-keyword-runtime-semantics-evaluation +description: > + GetSuperBase is performed before ToPropertyKey in PutValue with increment operator. +info: | + 13.3.7.1 Runtime Semantics: Evaluation + + SuperProperty : super [ Expression ] + + ... + 2. Let actualThis be ? env.GetThisBinding(). + 3. Let propertyNameReference be ? Evaluation of Expression. + 4. Let propertyNameValue be ? GetValue(propertyNameReference). + ... + 7. Return ? MakeSuperPropertyReference(actualThis, propertyNameValue, strict). + + 13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict ) + + 1. Let env be GetThisEnvironment(). + ... + 3. Let baseValue be ? env.GetSuperBase(). + ... + + 6.2.5.6 PutValue ( V, W ) + + 3. If IsPropertyReference(V) is true, then + ... + c. If V.[[ReferencedName]] is not a property key, then + i. Set V.[[ReferencedName]] to ? ToPropertyKey(V.[[ReferencedName]]). + d. Let succeeded be ? baseObj.[[Set]](V.[[ReferencedName]], W, GetThisValue(V)). + ... + ... +---*/ + +var proto = { + p: 1, +}; + +var proto2 = { + p: -1, +}; + +var obj = { + __proto__: proto, + m() { + return ++super[key]; + } +}; + +var key = { + toString() { + Object.setPrototypeOf(obj, proto2); + return "p"; + } +}; + +assert.sameValue(obj.m(), 2); diff --git a/test/language/expressions/super/prop-expr-getsuperbase-before-topropertykey-putvalue.js b/test/language/expressions/super/prop-expr-getsuperbase-before-topropertykey-putvalue.js new file mode 100644 index 00000000000..dc5d1126881 --- /dev/null +++ b/test/language/expressions/super/prop-expr-getsuperbase-before-topropertykey-putvalue.js @@ -0,0 +1,68 @@ +// Copyright (C) 2024 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-super-keyword-runtime-semantics-evaluation +description: > + GetSuperBase is performed before ToPropertyKey in PutValue. +info: | + 13.3.7.1 Runtime Semantics: Evaluation + + SuperProperty : super [ Expression ] + + ... + 2. Let actualThis be ? env.GetThisBinding(). + 3. Let propertyNameReference be ? Evaluation of Expression. + 4. Let propertyNameValue be ? GetValue(propertyNameReference). + ... + 7. Return ? MakeSuperPropertyReference(actualThis, propertyNameValue, strict). + + 13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict ) + + 1. Let env be GetThisEnvironment(). + ... + 3. Let baseValue be ? env.GetSuperBase(). + ... + + 6.2.5.6 PutValue ( V, W ) + + 3. If IsPropertyReference(V) is true, then + ... + c. If V.[[ReferencedName]] is not a property key, then + i. Set V.[[ReferencedName]] to ? ToPropertyKey(V.[[ReferencedName]]). + d. Let succeeded be ? baseObj.[[Set]](V.[[ReferencedName]], W, GetThisValue(V)). + ... + ... +---*/ + +var result; + +var proto = { + set p(v) { + result = "ok"; + }, +}; + +var proto2 = { + set p(v) { + result = "bad"; + }, +}; + +var obj = { + __proto__: proto, + m() { + super[key] = 10; + } +}; + +var key = { + toString() { + Object.setPrototypeOf(obj, proto2); + return "p"; + } +}; + +obj.m(); + +assert.sameValue(result, "ok"); diff --git a/test/language/expressions/super/prop-expr-uninitialized-this-getvalue.js b/test/language/expressions/super/prop-expr-uninitialized-this-getvalue.js new file mode 100644 index 00000000000..4ad32b3cfc3 --- /dev/null +++ b/test/language/expressions/super/prop-expr-uninitialized-this-getvalue.js @@ -0,0 +1,31 @@ +// Copyright (C) 2024 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-super-keyword-runtime-semantics-evaluation +description: > + Expression not evaluated when this binding is uninitialized in GetValue context. +info: | + 13.3.7.1 Runtime Semantics: Evaluation + + SuperProperty : super [ Expression ] + + ... + 2. Let actualThis be ? env.GetThisBinding(). + 3. Let propertyNameReference be ? Evaluation of Expression. + ... +---*/ + +class Base { + constructor() { + throw new Test262Error("base constructor"); + } +} + +class Derived extends Base { + constructor() { + return super[super()]; + } +} + +assert.throws(ReferenceError, () => new Derived); diff --git a/test/language/expressions/super/prop-expr-uninitialized-this-putvalue-compound-assign.js b/test/language/expressions/super/prop-expr-uninitialized-this-putvalue-compound-assign.js new file mode 100644 index 00000000000..1bb8e76148a --- /dev/null +++ b/test/language/expressions/super/prop-expr-uninitialized-this-putvalue-compound-assign.js @@ -0,0 +1,31 @@ +// Copyright (C) 2024 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-super-keyword-runtime-semantics-evaluation +description: > + Expression not evaluated when this binding is uninitialized in PutValue context with compound assignment. +info: | + 13.3.7.1 Runtime Semantics: Evaluation + + SuperProperty : super [ Expression ] + + ... + 2. Let actualThis be ? env.GetThisBinding(). + 3. Let propertyNameReference be ? Evaluation of Expression. + ... +---*/ + +class Base { + constructor() { + throw new Test262Error("base constructor"); + } +} + +class Derived extends Base { + constructor() { + super[super()] += 0; + } +} + +assert.throws(ReferenceError, () => new Derived); diff --git a/test/language/expressions/super/prop-expr-uninitialized-this-putvalue-increment.js b/test/language/expressions/super/prop-expr-uninitialized-this-putvalue-increment.js new file mode 100644 index 00000000000..b0821ab7f5e --- /dev/null +++ b/test/language/expressions/super/prop-expr-uninitialized-this-putvalue-increment.js @@ -0,0 +1,31 @@ +// Copyright (C) 2024 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-super-keyword-runtime-semantics-evaluation +description: > + Expression not evaluated when this binding is uninitialized in PutValue context with increment operator. +info: | + 13.3.7.1 Runtime Semantics: Evaluation + + SuperProperty : super [ Expression ] + + ... + 2. Let actualThis be ? env.GetThisBinding(). + 3. Let propertyNameReference be ? Evaluation of Expression. + ... +---*/ + +class Base { + constructor() { + throw new Test262Error("base constructor"); + } +} + +class Derived extends Base { + constructor() { + super[super()]++; + } +} + +assert.throws(ReferenceError, () => new Derived); diff --git a/test/language/expressions/super/prop-expr-uninitialized-this-putvalue.js b/test/language/expressions/super/prop-expr-uninitialized-this-putvalue.js new file mode 100644 index 00000000000..c6d10182ba0 --- /dev/null +++ b/test/language/expressions/super/prop-expr-uninitialized-this-putvalue.js @@ -0,0 +1,31 @@ +// Copyright (C) 2024 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-super-keyword-runtime-semantics-evaluation +description: > + Expression not evaluated when this binding is uninitialized in PutValue context. +info: | + 13.3.7.1 Runtime Semantics: Evaluation + + SuperProperty : super [ Expression ] + + ... + 2. Let actualThis be ? env.GetThisBinding(). + 3. Let propertyNameReference be ? Evaluation of Expression. + ... +---*/ + +class Base { + constructor() { + throw new Test262Error("base constructor"); + } +} + +class Derived extends Base { + constructor() { + super[super()] = 0; + } +} + +assert.throws(ReferenceError, () => new Derived);