diff --git a/test/language/expressions/compound-assignment/S11.13.2_A7.10_T4.js b/test/language/expressions/compound-assignment/S11.13.2_A7.10_T4.js deleted file mode 100644 index 4aadbb01a43..00000000000 --- a/test/language/expressions/compound-assignment/S11.13.2_A7.10_T4.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2015 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Compound Assignment Operator evaluates its operands from left to right. -description: > - The left-hand side expression is evaluated before the right-hand side. - Left-hand side expression is MemberExpression: base[prop]. ToPropertyKey(prop) - is only called once. - Check operator is "x ^= y". ----*/ - -var propKeyEvaluated = false; -var base = {}; -var prop = { - toString: function() { - assert(!propKeyEvaluated); - propKeyEvaluated = true; - return ""; - } -}; -var expr = function() { - return 0; -}; - -base[prop] ^= expr(); diff --git a/test/language/expressions/compound-assignment/S11.13.2_A7.11_T4.js b/test/language/expressions/compound-assignment/S11.13.2_A7.11_T4.js deleted file mode 100644 index 310f3ba9bdb..00000000000 --- a/test/language/expressions/compound-assignment/S11.13.2_A7.11_T4.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2015 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Compound Assignment Operator evaluates its operands from left to right. -description: > - The left-hand side expression is evaluated before the right-hand side. - Left-hand side expression is MemberExpression: base[prop]. ToPropertyKey(prop) - is only called once. - Check operator is "x |= y". ----*/ - -var propKeyEvaluated = false; -var base = {}; -var prop = { - toString: function() { - assert(!propKeyEvaluated); - propKeyEvaluated = true; - return ""; - } -}; -var expr = function() { - return 0; -}; - -base[prop] |= expr(); diff --git a/test/language/expressions/compound-assignment/S11.13.2_A7.1_T4.js b/test/language/expressions/compound-assignment/S11.13.2_A7.1_T4.js deleted file mode 100644 index 3f49ca96e0e..00000000000 --- a/test/language/expressions/compound-assignment/S11.13.2_A7.1_T4.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2015 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Compound Assignment Operator evaluates its operands from left to right. -description: > - The left-hand side expression is evaluated before the right-hand side. - Left-hand side expression is MemberExpression: base[prop]. ToPropertyKey(prop) - is only called once. - Check operator is "x *= y". ----*/ - -var propKeyEvaluated = false; -var base = {}; -var prop = { - toString: function() { - assert(!propKeyEvaluated); - propKeyEvaluated = true; - return ""; - } -}; -var expr = function() { - return 0; -}; - -base[prop] *= expr(); diff --git a/test/language/expressions/compound-assignment/S11.13.2_A7.2_T4.js b/test/language/expressions/compound-assignment/S11.13.2_A7.2_T4.js deleted file mode 100644 index c7963d97ea7..00000000000 --- a/test/language/expressions/compound-assignment/S11.13.2_A7.2_T4.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2015 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Compound Assignment Operator evaluates its operands from left to right. -description: > - The left-hand side expression is evaluated before the right-hand side. - Left-hand side expression is MemberExpression: base[prop]. ToPropertyKey(prop) - is only called once. - Check operator is "x /= y". ----*/ - -var propKeyEvaluated = false; -var base = {}; -var prop = { - toString: function() { - assert(!propKeyEvaluated); - propKeyEvaluated = true; - return ""; - } -}; -var expr = function() { - return 0; -}; - -base[prop] /= expr(); diff --git a/test/language/expressions/compound-assignment/S11.13.2_A7.3_T4.js b/test/language/expressions/compound-assignment/S11.13.2_A7.3_T4.js deleted file mode 100644 index c7f0f541714..00000000000 --- a/test/language/expressions/compound-assignment/S11.13.2_A7.3_T4.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2015 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Compound Assignment Operator evaluates its operands from left to right. -description: > - The left-hand side expression is evaluated before the right-hand side. - Left-hand side expression is MemberExpression: base[prop]. ToPropertyKey(prop) - is only called once. - Check operator is "x %= y". ----*/ - -var propKeyEvaluated = false; -var base = {}; -var prop = { - toString: function() { - assert(!propKeyEvaluated); - propKeyEvaluated = true; - return ""; - } -}; -var expr = function() { - return 0; -}; - -base[prop] %= expr(); diff --git a/test/language/expressions/compound-assignment/S11.13.2_A7.4_T4.js b/test/language/expressions/compound-assignment/S11.13.2_A7.4_T4.js deleted file mode 100644 index b149e25281d..00000000000 --- a/test/language/expressions/compound-assignment/S11.13.2_A7.4_T4.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2015 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Compound Assignment Operator evaluates its operands from left to right. -description: > - The left-hand side expression is evaluated before the right-hand side. - Left-hand side expression is MemberExpression: base[prop]. ToPropertyKey(prop) - is only called once. - Check operator is "x += y". ----*/ - -var propKeyEvaluated = false; -var base = {}; -var prop = { - toString: function() { - assert(!propKeyEvaluated); - propKeyEvaluated = true; - return ""; - } -}; -var expr = function() { - return 0; -}; - -base[prop] += expr(); diff --git a/test/language/expressions/compound-assignment/S11.13.2_A7.5_T4.js b/test/language/expressions/compound-assignment/S11.13.2_A7.5_T4.js deleted file mode 100644 index dd0515e5d2a..00000000000 --- a/test/language/expressions/compound-assignment/S11.13.2_A7.5_T4.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2015 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Compound Assignment Operator evaluates its operands from left to right. -description: > - The left-hand side expression is evaluated before the right-hand side. - Left-hand side expression is MemberExpression: base[prop]. ToPropertyKey(prop) - is only called once. - Check operator is "x -= y". ----*/ - -var propKeyEvaluated = false; -var base = {}; -var prop = { - toString: function() { - assert(!propKeyEvaluated); - propKeyEvaluated = true; - return ""; - } -}; -var expr = function() { - return 0; -}; - -base[prop] -= expr(); diff --git a/test/language/expressions/compound-assignment/S11.13.2_A7.6_T4.js b/test/language/expressions/compound-assignment/S11.13.2_A7.6_T4.js deleted file mode 100644 index df88da9e317..00000000000 --- a/test/language/expressions/compound-assignment/S11.13.2_A7.6_T4.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2015 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Compound Assignment Operator evaluates its operands from left to right. -description: > - The left-hand side expression is evaluated before the right-hand side. - Left-hand side expression is MemberExpression: base[prop]. ToPropertyKey(prop) - is only called once. - Check operator is "x <<= y". ----*/ - -var propKeyEvaluated = false; -var base = {}; -var prop = { - toString: function() { - assert(!propKeyEvaluated); - propKeyEvaluated = true; - return ""; - } -}; -var expr = function() { - return 0; -}; - -base[prop] <<= expr(); diff --git a/test/language/expressions/compound-assignment/S11.13.2_A7.7_T4.js b/test/language/expressions/compound-assignment/S11.13.2_A7.7_T4.js deleted file mode 100644 index 43d18298bdf..00000000000 --- a/test/language/expressions/compound-assignment/S11.13.2_A7.7_T4.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2015 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Compound Assignment Operator evaluates its operands from left to right. -description: > - The left-hand side expression is evaluated before the right-hand side. - Left-hand side expression is MemberExpression: base[prop]. ToPropertyKey(prop) - is only called once. - Check operator is "x >>= y". ----*/ - -var propKeyEvaluated = false; -var base = {}; -var prop = { - toString: function() { - assert(!propKeyEvaluated); - propKeyEvaluated = true; - return ""; - } -}; -var expr = function() { - return 0; -}; - -base[prop] >>= expr(); diff --git a/test/language/expressions/compound-assignment/S11.13.2_A7.8_T4.js b/test/language/expressions/compound-assignment/S11.13.2_A7.8_T4.js deleted file mode 100644 index 844282d17c3..00000000000 --- a/test/language/expressions/compound-assignment/S11.13.2_A7.8_T4.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2015 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Compound Assignment Operator evaluates its operands from left to right. -description: > - The left-hand side expression is evaluated before the right-hand side. - Left-hand side expression is MemberExpression: base[prop]. ToPropertyKey(prop) - is only called once. - Check operator is "x >>>= y". ----*/ - -var propKeyEvaluated = false; -var base = {}; -var prop = { - toString: function() { - assert(!propKeyEvaluated); - propKeyEvaluated = true; - return ""; - } -}; -var expr = function() { - return 0; -}; - -base[prop] >>>= expr(); diff --git a/test/language/expressions/compound-assignment/S11.13.2_A7.9_T4.js b/test/language/expressions/compound-assignment/S11.13.2_A7.9_T4.js deleted file mode 100644 index 709f65a5f61..00000000000 --- a/test/language/expressions/compound-assignment/S11.13.2_A7.9_T4.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2015 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -info: Compound Assignment Operator evaluates its operands from left to right. -description: > - The left-hand side expression is evaluated before the right-hand side. - Left-hand side expression is MemberExpression: base[prop]. ToPropertyKey(prop) - is only called once. - Check operator is "x &= y". ----*/ - -var propKeyEvaluated = false; -var base = {}; -var prop = { - toString: function() { - assert(!propKeyEvaluated); - propKeyEvaluated = true; - return ""; - } -}; -var expr = function() { - return 0; -}; - -base[prop] &= expr(); diff --git a/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-add.js b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-add.js new file mode 100644 index 00000000000..2dfa133e974 --- /dev/null +++ b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-add.js @@ -0,0 +1,46 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] += value. +info: | + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + ... + 3. Let leftValue be ? GetValue(leftRef). + ... + 9. Perform ? PutValue(leftRef, result). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = { p: 2 }; + +base[prop] += 3; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 5, "the result is assigned to the converted key"); diff --git a/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-bitand.js b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-bitand.js new file mode 100644 index 00000000000..4b923ef846c --- /dev/null +++ b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-bitand.js @@ -0,0 +1,46 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] &= value. +info: | + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + ... + 3. Let leftValue be ? GetValue(leftRef). + ... + 9. Perform ? PutValue(leftRef, result). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = { p: 6 }; + +base[prop] &= 3; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 2, "the result is assigned to the converted key"); diff --git a/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-bitor.js b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-bitor.js new file mode 100644 index 00000000000..806d2bfce3c --- /dev/null +++ b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-bitor.js @@ -0,0 +1,46 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] |= value. +info: | + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + ... + 3. Let leftValue be ? GetValue(leftRef). + ... + 9. Perform ? PutValue(leftRef, result). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = { p: 1 }; + +base[prop] |= 2; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 3, "the result is assigned to the converted key"); diff --git a/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-bitxor.js b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-bitxor.js new file mode 100644 index 00000000000..11f21cf3db7 --- /dev/null +++ b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-bitxor.js @@ -0,0 +1,46 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] ^= value. +info: | + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + ... + 3. Let leftValue be ? GetValue(leftRef). + ... + 9. Perform ? PutValue(leftRef, result). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = { p: 6 }; + +base[prop] ^= 3; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 5, "the result is assigned to the converted key"); diff --git a/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-div.js b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-div.js new file mode 100644 index 00000000000..8aecaeea514 --- /dev/null +++ b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-div.js @@ -0,0 +1,46 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] /= value. +info: | + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + ... + 3. Let leftValue be ? GetValue(leftRef). + ... + 9. Perform ? PutValue(leftRef, result). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = { p: 6 }; + +base[prop] /= 3; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 2, "the result is assigned to the converted key"); diff --git a/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-exp.js b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-exp.js new file mode 100644 index 00000000000..acbd69ea011 --- /dev/null +++ b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-exp.js @@ -0,0 +1,47 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] **= value. +info: | + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + ... + 3. Let leftValue be ? GetValue(leftRef). + ... + 9. Perform ? PutValue(leftRef, result). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +features: [exponentiation] +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = { p: 2 }; + +base[prop] **= 3; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 8, "the result is assigned to the converted key"); diff --git a/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-lshift.js b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-lshift.js new file mode 100644 index 00000000000..314ff1636ec --- /dev/null +++ b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-lshift.js @@ -0,0 +1,46 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] <<= value. +info: | + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + ... + 3. Let leftValue be ? GetValue(leftRef). + ... + 9. Perform ? PutValue(leftRef, result). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = { p: 1 }; + +base[prop] <<= 3; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 8, "the result is assigned to the converted key"); diff --git a/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-mod.js b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-mod.js new file mode 100644 index 00000000000..446290fa16c --- /dev/null +++ b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-mod.js @@ -0,0 +1,46 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] %= value. +info: | + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + ... + 3. Let leftValue be ? GetValue(leftRef). + ... + 9. Perform ? PutValue(leftRef, result). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = { p: 5 }; + +base[prop] %= 3; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 2, "the result is assigned to the converted key"); diff --git a/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-mult.js b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-mult.js new file mode 100644 index 00000000000..29069e28a3a --- /dev/null +++ b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-mult.js @@ -0,0 +1,46 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] *= value. +info: | + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + ... + 3. Let leftValue be ? GetValue(leftRef). + ... + 9. Perform ? PutValue(leftRef, result). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = { p: 2 }; + +base[prop] *= 3; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 6, "the result is assigned to the converted key"); diff --git a/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-rshift.js b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-rshift.js new file mode 100644 index 00000000000..2a66b064e75 --- /dev/null +++ b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-rshift.js @@ -0,0 +1,46 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] >>>= value. +info: | + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + ... + 3. Let leftValue be ? GetValue(leftRef). + ... + 9. Perform ? PutValue(leftRef, result). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = { p: 8 }; + +base[prop] >>>= 1; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 4, "the result is assigned to the converted key"); diff --git a/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-srshift.js b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-srshift.js new file mode 100644 index 00000000000..a6b2a4b834b --- /dev/null +++ b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-srshift.js @@ -0,0 +1,46 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] >>= value. +info: | + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + ... + 3. Let leftValue be ? GetValue(leftRef). + ... + 9. Perform ? PutValue(leftRef, result). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = { p: 8 }; + +base[prop] >>= 1; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 4, "the result is assigned to the converted key"); diff --git a/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-sub.js b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-sub.js new file mode 100644 index 00000000000..2b92f96df4a --- /dev/null +++ b/test/language/expressions/compound-assignment/left-hand-side-property-reference-topropertykey-once-sub.js @@ -0,0 +1,46 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] -= value. +info: | + AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + ... + 3. Let leftValue be ? GetValue(leftRef). + ... + 9. Perform ? PutValue(leftRef, result). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = { p: 5 }; + +base[prop] -= 3; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 2, "the result is assigned to the converted key"); diff --git a/test/language/expressions/logical-assignment/lgcl-and-assignment-operator-topropertykey-once.js b/test/language/expressions/logical-assignment/lgcl-and-assignment-operator-topropertykey-once.js new file mode 100644 index 00000000000..1ad846d0881 --- /dev/null +++ b/test/language/expressions/logical-assignment/lgcl-and-assignment-operator-topropertykey-once.js @@ -0,0 +1,47 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] &&= value when it assigns. +info: | + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + 2. Let leftValue be ? GetValue(leftRef). + 3. If ToBoolean(leftValue) is false, return leftValue. + ... + 6. Perform ? PutValue(leftRef, rightValue). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +features: [logical-assignment-operators] +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = { p: 1 }; + +base[prop] &&= 2; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 2, "the value is assigned to the converted key"); diff --git a/test/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-topropertykey-once.js b/test/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-topropertykey-once.js new file mode 100644 index 00000000000..3fe38339a57 --- /dev/null +++ b/test/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-topropertykey-once.js @@ -0,0 +1,47 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] ??= value when it assigns. +info: | + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + 2. Let leftValue be ? GetValue(leftRef). + 3. If leftValue is neither undefined nor null, return leftValue. + ... + 6. Perform ? PutValue(leftRef, rightValue). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +features: [logical-assignment-operators] +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = {}; + +base[prop] ??= 1; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 1, "the value is assigned to the converted key"); diff --git a/test/language/expressions/logical-assignment/lgcl-or-assignment-operator-topropertykey-once.js b/test/language/expressions/logical-assignment/lgcl-or-assignment-operator-topropertykey-once.js new file mode 100644 index 00000000000..4247e6a1abe --- /dev/null +++ b/test/language/expressions/logical-assignment/lgcl-or-assignment-operator-topropertykey-once.js @@ -0,0 +1,47 @@ +// Copyright (C) 2026 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ToPropertyKey is called only once on the key of base[prop] ||= value when it assigns. +info: | + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + + 1. Let leftRef be ? Evaluation of LeftHandSideExpression. + 2. Let leftValue be ? GetValue(leftRef). + 3. If ToBoolean(leftValue) is true, return leftValue. + ... + 6. Perform ? PutValue(leftRef, rightValue). + + GetValue ( refRecord ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). + + PutValue ( refRecord, value ) + + ... + 3. If IsPropertyReference(refRecord) is true, then + ... + c. If refRecord.[[ReferencedName]] is not a property key, then + i. Set refRecord.[[ReferencedName]] to ? ToPropertyKey(refRecord.[[ReferencedName]]). +features: [logical-assignment-operators] +---*/ + +var count = 0; +var prop = { + toString: function() { + count++; + return "p"; + } +}; +var base = { p: 0 }; + +base[prop] ||= 2; + +assert.sameValue(count, 1, "ToPropertyKey(prop) is performed once"); +assert.sameValue(base.p, 2, "the value is assigned to the converted key");