diff options
Diffstat (limited to 'js/src/tests/test262/language/expressions/logical-assignment')
80 files changed, 2844 insertions, 0 deletions
diff --git a/js/src/tests/test262/language/expressions/logical-assignment/browser.js b/js/src/tests/test262/language/expressions/logical-assignment/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/browser.js diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-and.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-and.js new file mode 100644 index 0000000000..600b575719 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-and.js @@ -0,0 +1,63 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/and.case +// - src/logical-assignment-private/default/getter-setter.template +/*--- +description: Logical-and assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *false*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +class C { + #setterCalledWith; + get #field() { + return true; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field &&= false; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), false, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), false, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-nullish.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-nullish.js new file mode 100644 index 0000000000..8bb644f294 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-nullish.js @@ -0,0 +1,62 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/nullish.case +// - src/logical-assignment-private/default/getter-setter.template +/*--- +description: Nullish-coalescing assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. If _lval_ is neither *undefined* nor *null*, return _lval_. + ... + 6. Perform ? PutValue(_lref_, _rval_). + 7. Return _rval_. +---*/ + + +class C { + #setterCalledWith; + get #field() { + return null; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field ??= 1; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), 1, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-or.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-or.js new file mode 100644 index 0000000000..769a1d4d16 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-or.js @@ -0,0 +1,63 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/or.case +// - src/logical-assignment-private/default/getter-setter.template +/*--- +description: Logical-or assignment with target being a private reference (to an accessor property with getter and setter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *true*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +class C { + #setterCalledWith; + get #field() { + return false; + } + set #field(value) { + this.#setterCalledWith = value; + } + compoundAssignment() { + return this.#field ||= true; + } + setterCalledWithValue() { + return this.#setterCalledWith; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), true, "The expression should evaluate to the result"); +assert.sameValue(o.setterCalledWithValue(), true, "PutValue should call the setter with the result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-and.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-and.js new file mode 100644 index 0000000000..3fbc6760d8 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-and.js @@ -0,0 +1,64 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/and.case +// - src/logical-assignment-private/default/getter-setter-short-circuit.template +/*--- +description: Logical-and assignment with target being a private reference (to an accessor property with getter and setter (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *false*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + setterWasCalled = false; + get #field() { + return false; + } + set #field(value) { + this.setterWasCalled = true; + } + compoundAssignment() { + return this.#field &&= doNotCall(); + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), false, "The expression should evaluate to the short-circuit value"); +assert(!o.setterWasCalled, "The setter should not be called"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-nullish.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-nullish.js new file mode 100644 index 0000000000..4933a5e99d --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-nullish.js @@ -0,0 +1,63 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/nullish.case +// - src/logical-assignment-private/default/getter-setter-short-circuit.template +/*--- +description: Nullish-coalescing assignment with target being a private reference (to an accessor property with getter and setter (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. If _lval_ is neither *undefined* nor *null*, return _lval_. + ... + 6. Perform ? PutValue(_lref_, _rval_). + 7. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + setterWasCalled = false; + get #field() { + return 1; + } + set #field(value) { + this.setterWasCalled = true; + } + compoundAssignment() { + return this.#field ??= doNotCall(); + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1, "The expression should evaluate to the short-circuit value"); +assert(!o.setterWasCalled, "The setter should not be called"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-or.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-or.js new file mode 100644 index 0000000000..ad8113b875 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-accessor-property-short-circuit-or.js @@ -0,0 +1,64 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/or.case +// - src/logical-assignment-private/default/getter-setter-short-circuit.template +/*--- +description: Logical-or assignment with target being a private reference (to an accessor property with getter and setter (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + ... + 5.c. Let _setter_ be _entry_.[[Set]]. + d. Perform ? Call(_setter_, _O_, « _value_ »). + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *true*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + setterWasCalled = false; + get #field() { + return true; + } + set #field(value) { + this.setterWasCalled = true; + } + compoundAssignment() { + return this.#field ||= doNotCall(); + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), true, "The expression should evaluate to the short-circuit value"); +assert(!o.setterWasCalled, "The setter should not be called"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-and.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-and.js new file mode 100644 index 0000000000..48f9da1452 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-and.js @@ -0,0 +1,55 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/and.case +// - src/logical-assignment-private/default/data-property.template +/*--- +description: Logical-and assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *false*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +class C { + #field = true; + compoundAssignment() { + return this.#field &&= false; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), false, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), false, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-nullish.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-nullish.js new file mode 100644 index 0000000000..895371b4ed --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-nullish.js @@ -0,0 +1,54 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/nullish.case +// - src/logical-assignment-private/default/data-property.template +/*--- +description: Nullish-coalescing assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. If _lval_ is neither *undefined* nor *null*, return _lval_. + ... + 6. Perform ? PutValue(_lref_, _rval_). + 7. Return _rval_. +---*/ + + +class C { + #field = null; + compoundAssignment() { + return this.#field ??= 1; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), 1, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-or.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-or.js new file mode 100644 index 0000000000..ecd05f0a85 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-or.js @@ -0,0 +1,55 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/or.case +// - src/logical-assignment-private/default/data-property.template +/*--- +description: Logical-or assignment with target being a private reference (to a field) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *true*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +class C { + #field = false; + compoundAssignment() { + return this.#field ||= true; + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), true, "The expression should evaluate to the result"); +assert.sameValue(o.fieldValue(), true, "PutValue should store the result in the private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-and.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-and.js new file mode 100644 index 0000000000..b97a76a866 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-and.js @@ -0,0 +1,58 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/and.case +// - src/logical-assignment-private/default/data-property-short-circuit.template +/*--- +description: Logical-and assignment with target being a private reference (to a field (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *false*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + #field = false; + compoundAssignment() { + return this.#field &&= doNotCall(); + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), false, "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-nullish.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-nullish.js new file mode 100644 index 0000000000..fa4568829b --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-nullish.js @@ -0,0 +1,57 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/nullish.case +// - src/logical-assignment-private/default/data-property-short-circuit.template +/*--- +description: Nullish-coalescing assignment with target being a private reference (to a field (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. If _lval_ is neither *undefined* nor *null*, return _lval_. + ... + 6. Perform ? PutValue(_lref_, _rval_). + 7. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + #field = 1; + compoundAssignment() { + return this.#field ??= doNotCall(); + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1, "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-or.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-or.js new file mode 100644 index 0000000000..c1e2e206ec --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-data-property-short-circuit-or.js @@ -0,0 +1,58 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/or.case +// - src/logical-assignment-private/default/data-property-short-circuit.template +/*--- +description: Logical-or assignment with target being a private reference (to a field (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 3. If _entry_.[[Kind]] is ~field~, then + a. Set _entry_.[[Value]] to _value_. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *true*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + #field = true; + compoundAssignment() { + return this.#field ||= doNotCall(); + } + fieldValue() { + return this.#field; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), true, "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-and.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-and.js new file mode 100644 index 0000000000..94168ea59d --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-and.js @@ -0,0 +1,51 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/and.case +// - src/logical-assignment-private/default/method.template +/*--- +description: Logical-and assignment with target being a private reference (to a private method) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *false*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod &&= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result in a method private reference"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-short-circuit-nullish.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-short-circuit-nullish.js new file mode 100644 index 0000000000..aa1b7225c7 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-short-circuit-nullish.js @@ -0,0 +1,57 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/nullish.case +// - src/logical-assignment-private/default/method-short-circuit.template +/*--- +description: Nullish-coalescing assignment with target being a private reference (to a private method (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. If _lval_ is neither *undefined* nor *null*, return _lval_. + ... + 6. Perform ? PutValue(_lref_, _rval_). + 7. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod ??= doNotCall(); + } + getPrivateMethodFunctionObject() { + return this.#privateMethod; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), o.getPrivateMethodFunctionObject(), "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-short-circuit-or.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-short-circuit-or.js new file mode 100644 index 0000000000..b19dd8efe0 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-method-short-circuit-or.js @@ -0,0 +1,58 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/or.case +// - src/logical-assignment-private/default/method-short-circuit.template +/*--- +description: Logical-or assignment with target being a private reference (to a private method (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 4. Else if _entry_.[[Kind]] is ~method~, then + a. Throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *true*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + #privateMethod() {} + compoundAssignment() { + return this.#privateMethod ||= doNotCall(); + } + getPrivateMethodFunctionObject() { + return this.#privateMethod; + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), o.getPrivateMethodFunctionObject(), "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-and.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-and.js new file mode 100644 index 0000000000..6e47415ac7 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-and.js @@ -0,0 +1,53 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/and.case +// - src/logical-assignment-private/default/getter.template +/*--- +description: Logical-and assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *false*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +class C { + get #field() { + return true; + } + compoundAssignment() { + return this.#field &&= false; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-nullish.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-nullish.js new file mode 100644 index 0000000000..45216d42a1 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-nullish.js @@ -0,0 +1,52 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/nullish.case +// - src/logical-assignment-private/default/getter.template +/*--- +description: Nullish-coalescing assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. If _lval_ is neither *undefined* nor *null*, return _lval_. + ... + 6. Perform ? PutValue(_lref_, _rval_). + 7. Return _rval_. +---*/ + + +class C { + get #field() { + return null; + } + compoundAssignment() { + return this.#field ??= 1; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-or.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-or.js new file mode 100644 index 0000000000..8c9695032e --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-or.js @@ -0,0 +1,53 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/or.case +// - src/logical-assignment-private/default/getter.template +/*--- +description: Logical-or assignment with target being a private reference (to an accessor property with getter) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *true*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +class C { + get #field() { + return false; + } + compoundAssignment() { + return this.#field ||= true; + } +} + +const o = new C(); +assert.throws(TypeError, () => o.compoundAssignment(), "PutValue throws when storing the result if no setter"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-and.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-and.js new file mode 100644 index 0000000000..f99b2c1a3b --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-and.js @@ -0,0 +1,57 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/and.case +// - src/logical-assignment-private/default/getter-short-circuit.template +/*--- +description: Logical-and assignment with target being a private reference (to an accessor property with getter (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *false*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + get #field() { + return false; + } + compoundAssignment() { + return this.#field &&= doNotCall(); + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), false, "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-nullish.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-nullish.js new file mode 100644 index 0000000000..00569dc546 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-nullish.js @@ -0,0 +1,56 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/nullish.case +// - src/logical-assignment-private/default/getter-short-circuit.template +/*--- +description: Nullish-coalescing assignment with target being a private reference (to an accessor property with getter (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. If _lval_ is neither *undefined* nor *null*, return _lval_. + ... + 6. Perform ? PutValue(_lref_, _rval_). + 7. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + get #field() { + return 1; + } + compoundAssignment() { + return this.#field ??= doNotCall(); + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), 1, "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-or.js b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-or.js new file mode 100644 index 0000000000..b776af7911 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/left-hand-side-private-reference-readonly-accessor-property-short-circuit-or.js @@ -0,0 +1,57 @@ +// This file was procedurally generated from the following sources: +// - src/logical-assignment-private/or.case +// - src/logical-assignment-private/default/getter-short-circuit.template +/*--- +description: Logical-or assignment with target being a private reference (to an accessor property with getter (short-circuit version)) +esid: sec-assignment-operators-runtime-semantics-evaluation +features: [class-fields-private, logical-assignment-operators] +flags: [generated] +info: | + sec-property-accessors-runtime-semantics-evaluation + MemberExpression : MemberExpression `.` PrivateIdentifier + + 1. Let _baseReference_ be the result of evaluating |MemberExpression|. + 2. Let _baseValue_ be ? GetValue(_baseReference_). + 3. Let _fieldNameString_ be the StringValue of |PrivateIdentifier|. + 4. Return ! MakePrivateReference(_baseValue_, _fieldNameString_). + + PutValue (V, W) + ... + 5.b. If IsPrivateReference(_V_) is *true*, then + i. Return ? PrivateSet(_baseObj_, _V_.[[ReferencedName]], _W_). + + PrivateSet (O, P, value) + ... + 5.a. Assert: _entry_.[[Kind]] is ~accessor~. + b. If _entry_.[[Set]] is *undefined*, throw a *TypeError* exception. + + + sec-assignment-operators-runtime-semantics-evaluation + AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression + 1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. + 2. Let _lval_ be ? GetValue(_lref_). + 3. Let _lbool_ be ! ToBoolean(_lval_). + 4. If _lbool_ is *true*, return _lval_. + ... + 7. Perform ? PutValue(_lref_, _rval_). + 8. Return _rval_. +---*/ + + +function doNotCall() { + throw new Test262Error("The right-hand side should not be evaluated"); +} + +class C { + get #field() { + return true; + } + compoundAssignment() { + return this.#field ||= doNotCall(); + } +} + +const o = new C(); +assert.sameValue(o.compoundAssignment(), true, "The expression should evaluate to the short-circuit value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-arguments-strict-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-arguments-strict-strict.js new file mode 100644 index 0000000000..dfb9c91e3b --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-arguments-strict-strict.js @@ -0,0 +1,20 @@ +// |reftest| error:SyntaxError +'use strict'; +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators +description: > + Strict Mode - SyntaxError is thrown if the identifier arguments + appear as the LeftHandSideExpression of a Logical Assignment + operator(&&=) +flags: [onlyStrict] +negative: + phase: parse + type: SyntaxError +features: [logical-assignment-operators] +---*/ +$DONOTEVALUATE(); + +arguments &&= 20; diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-bigint.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-bigint.js new file mode 100644 index 0000000000..ee443220f5 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-bigint.js @@ -0,0 +1,29 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: Logical And Assignment Operator +features: [BigInt, logical-assignment-operators] +info: | + AssignmentExpression: + LeftHandSideExpression &&= AssignmentExpression + + 1. Let lref be the result of evaluating LeftHandSideExpression. + 2. Let lval be ? GetValue(lref). + 3. Let lbool be ! ToBoolean(lval). + 4. If lbool is false, return lval. + 5. Let rref be the result of evaluating AssignmentExpression. + 6. Let rval be ? GetValue(rref). + 7. Perform ? PutValue(lref, rval). + 8. Return rval. + +---*/ + +var value = 0n; +assert.sameValue(value &&= 1n, 0n, "(value &&= 1n) === 0n; where value = 0n"); + +value = 2n; +assert.sameValue(value &&= 1n, 1n, "(value &&= 1n) === 1n; where value = 2n"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-lhs-before-rhs.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-lhs-before-rhs.js new file mode 100644 index 0000000000..bd11e7b6d1 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-lhs-before-rhs.js @@ -0,0 +1,55 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + The LeftHandSideExpression is evaluated before the AssignmentExpression. +features: [logical-assignment-operators] + +---*/ + +function DummyError() { } + +assert.throws(DummyError, function() { + var base = null; + var prop = function() { + throw new DummyError(); + }; + var expr = function() { + throw new Test262Error("right-hand side expression evaluated"); + }; + + base[prop()] &&= expr(); +}); + +assert.throws(TypeError, function() { + var base = null; + var prop = { + toString: function() { + throw new Test262Error("property key evaluated"); + } + }; + var expr = function() { + throw new Test262Error("right-hand side expression evaluated"); + }; + + base[prop] &&= expr(); +}); + +var count = 0; +var obj = {}; +function incr() { + return ++count; +} + +assert.sameValue(obj[incr()] &&= incr(), undefined, "obj[incr()] &&= incr()"); +assert.sameValue(obj[1], undefined, "obj[1]"); +assert.sameValue(count, 1, "count"); + +obj[2] = 1; +assert.sameValue(obj[incr()] &&= incr(), 3, "obj[incr()] &&= incr()"); +assert.sameValue(obj[2], 3, "obj[2]"); +assert.sameValue(count, 3, "count"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-arrow-function.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-arrow-function.js new file mode 100644 index 0000000000..3beba1cbae --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-arrow-function.js @@ -0,0 +1,22 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: NamedEvaluation of Logical And Assignment +info: | + AssignmentExpression: + LeftHandSideExpression &&= AssignmentExpression + + 5. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then + a. Let rval be NamedEvaluation of AssignmentExpression with argument GetReferencedName(lref). +features: [logical-assignment-operators] + +---*/ + +var value = 1; +value &&= () => {}; + +assert.sameValue(value.name, "value", "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-class-expression.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-class-expression.js new file mode 100644 index 0000000000..eb907f8dbd --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-class-expression.js @@ -0,0 +1,22 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: NamedEvaluation of Logical And Assignment +info: | + AssignmentExpression: + LeftHandSideExpression &&= AssignmentExpression + + 5. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then + a. Let rval be NamedEvaluation of AssignmentExpression with argument GetReferencedName(lref). +features: [logical-assignment-operators] + +---*/ + +var value = 1; +value &&= class {}; + +assert.sameValue(value.name, "value", "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-function.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-function.js new file mode 100644 index 0000000000..dd1dbe9ded --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-function.js @@ -0,0 +1,22 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: NamedEvaluation of Logical And Assignment +info: | + AssignmentExpression: + LeftHandSideExpression &&= AssignmentExpression + + 5. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then + a. Let rval be NamedEvaluation of AssignmentExpression with argument GetReferencedName(lref). +features: [logical-assignment-operators] + +---*/ + +var value = 1; +value &&= function() {}; + +assert.sameValue(value.name, "value", "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-no-set-put-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-no-set-put-strict.js new file mode 100644 index 0000000000..ac3fca3891 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-no-set-put-strict.js @@ -0,0 +1,31 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is thrown if the LeftHandSide of a Logical + Assignment operator(&&=) is a reference to a data property with the + attribute value {[[Set]]:undefined} and PutValue step is reached. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.defineProperty(obj, "prop", { + get: function() { + return 2; + }, + set: undefined, + enumerable: true, + configurable: true +}); + +assert.throws(TypeError, function() { + obj.prop &&= 1; +}); +assert.sameValue(obj.prop, 2, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-no-set-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-no-set-strict.js new file mode 100644 index 0000000000..9f730eead5 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-no-set-strict.js @@ -0,0 +1,28 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is not thrown if the LeftHandSide of a Logical + Assignment operator(&&=) is a reference to a data property with the + attribute value {[[Set]]:undefined} and PutValue step is not reached. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.defineProperty(obj, "prop", { + get: function() { + return 0; + }, + set: undefined, + enumerable: true, + configurable: true +}); + +assert.sameValue(obj.prop &&= 1, 0, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-non-extensible-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-non-extensible-strict.js new file mode 100644 index 0000000000..d5b614d9c5 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-non-extensible-strict.js @@ -0,0 +1,22 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is not thrown if The LeftHandSide of a Logical + Assignment operator(&&=) is a reference to a non-existent property of an + object whose [[Extensible]] internal property is false. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.preventExtensions(obj); + +obj.prop &&= 1; +assert.sameValue(obj.prop, undefined, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-non-simple-lhs.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-non-simple-lhs.js new file mode 100644 index 0000000000..41ef1dbc56 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-non-simple-lhs.js @@ -0,0 +1,20 @@ +// |reftest| error:SyntaxError +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-static-semantics-early-errors +description: > + It is a Syntax Error if AssignmentTargetType of LeftHandSideExpression is + not simple. +negative: + phase: parse + type: SyntaxError +features: [logical-assignment-operators] + +---*/ + +$DONOTEVALUATE(); + +function test() {} +test() &&= 1; diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-non-writeable-put-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-non-writeable-put-strict.js new file mode 100644 index 0000000000..074dfa9b75 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-non-writeable-put-strict.js @@ -0,0 +1,29 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is thrown if the LeftHandSide of a Logical + Assignment operator(&&=) is a reference to a data property with the + attribute value {[[Writable]]:false} and PutValue step is reached. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.defineProperty(obj, "prop", { + value: 2, + writable: false, + enumerable: true, + configurable: true +}); + +assert.throws(TypeError, function() { + obj.prop &&= 1; +}); +assert.sameValue(obj.prop, 2, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-non-writeable-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-non-writeable-strict.js new file mode 100644 index 0000000000..befc13c134 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-non-writeable-strict.js @@ -0,0 +1,26 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is not thrown if the LeftHandSide of a Logical + Assignment operator(&&=) is a reference to a data property with the + attribute value {[[Writable]]:false} and PutValue step is not reached. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.defineProperty(obj, "prop", { + value: 0, + writable: false, + enumerable: true, + configurable: true +}); + +assert.sameValue(obj.prop &&= 1, 0, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-unresolved-lhs-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-unresolved-lhs-strict.js new file mode 100644 index 0000000000..8eaa75089f --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-unresolved-lhs-strict.js @@ -0,0 +1,19 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ReferenceError is thrown if the LeftHandSideExpression of a Logical + Assignment operator(&&=) evaluates to an unresolvable reference +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +assert.throws(ReferenceError, function() { + unresolved &&= 1; +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-unresolved-rhs-put.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-unresolved-rhs-put.js new file mode 100644 index 0000000000..d298e9324a --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-unresolved-rhs-put.js @@ -0,0 +1,21 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ReferenceError is thrown if the AssignmentExpression of a Logical + Assignment operator(&&=) evaluates to an unresolvable reference and the + AssignmentExpression is evaluated. +features: [logical-assignment-operators] + +---*/ + +var value = 2; + +assert.throws(ReferenceError, function() { + value &&= unresolved; +}); +assert.sameValue(value, 2, "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-unresolved-rhs.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-unresolved-rhs.js new file mode 100644 index 0000000000..631b5e9e3d --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator-unresolved-rhs.js @@ -0,0 +1,18 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ReferenceError is not thrown if the AssignmentExpression of a Logical + Assignment operator(&&=) evaluates to an unresolvable reference and the + AssignmentExpression is not evaluated. +features: [logical-assignment-operators] + +---*/ + +var value = 0; + +assert.sameValue(value &&= unresolved, 0, "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator.js new file mode 100644 index 0000000000..68fcd7bbaa --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-assignment-operator.js @@ -0,0 +1,63 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: Logical And Assignment Operator +info: | + AssignmentExpression: + LeftHandSideExpression &&= AssignmentExpression + + 1. Let lref be the result of evaluating LeftHandSideExpression. + 2. Let lval be ? GetValue(lref). + 3. Let lbool be ! ToBoolean(lval). + 4. If lbool is false, return lval. + 5. Let rref be the result of evaluating AssignmentExpression. + 6. Let rval be ? GetValue(rref). + 7. Perform ? PutValue(lref, rval). + 8. Return rval. +features: [logical-assignment-operators] + +---*/ + +var value = undefined; +assert.sameValue(value &&= 1, undefined, "(value &&= 1) === undefined; where value = undefined"); + +value = null; +assert.sameValue(value &&= 1, null, "(value &&= 1) === null where value = null"); + +value = false; +assert.sameValue(value &&= 1, false, "(value &&= 1) === false; where value = false"); + +value = 0; +assert.sameValue(value &&= 1, 0, "(value &&= 1) === 0; where value = 0"); + +value = -0; +assert.sameValue(value &&= 1, -0, "(value &&= 1) === -0; where value = -0"); + +value = NaN; +assert.sameValue(value &&= 1, NaN, "(value &&= 1) === NaN; where value = NaN"); + +value = ""; +assert.sameValue(value &&= 1, "", '(value &&= 1) === "" where value = ""'); + + + +value = true; +assert.sameValue(value &&= 1, 1, "(value &&= 1) === 1; where value = true"); + +value = 2; +assert.sameValue(value &&= 1, 1, "(value &&= 1) === 1; where value = 2"); + +value = "test"; +assert.sameValue(value &&= 1, 1, '(value &&= 1) === 1; where value = "test"'); + +var sym = Symbol(""); +value = sym; +assert.sameValue(value &&= 1, 1, "(value &&= 1) === 1; where value = Symbol()"); + +var obj = {}; +value = obj; +assert.sameValue(value &&= 1, 1, "(value &&= 1) === 1; where value = {}"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-eval-strict-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-eval-strict-strict.js new file mode 100644 index 0000000000..acd470f5e4 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-eval-strict-strict.js @@ -0,0 +1,19 @@ +// |reftest| error:SyntaxError +'use strict'; +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators +description: > + Strict Mode - SyntaxError is thrown if the identifier eval appear + as the LeftHandSideExpression of a Logical Assignment operator(&&=) +flags: [onlyStrict] +negative: + phase: parse + type: SyntaxError +features: [logical-assignment-operators] +---*/ +$DONOTEVALUATE(); + +eval &&= 20; diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-non-simple.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-non-simple.js new file mode 100644 index 0000000000..d80e71c5b3 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-non-simple.js @@ -0,0 +1,18 @@ +// |reftest| error:SyntaxError +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-static-semantics-early-errors +info: | + It is an early Syntax Error if AssignmentTargetType of + LeftHandSideExpression is invalid or strict. +description: Logical "&&=" assignment with non-simple target +negative: + phase: parse + type: SyntaxError +features: [logical-assignment-operators] +---*/ +$DONOTEVALUATE(); + +1 &&= 1; diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-whitespace.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-whitespace.js new file mode 100644 index 0000000000..617b20e621 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-and-whitespace.js @@ -0,0 +1,60 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +info: | + White Space and Line Terminator between LeftHandSideExpression and "@=" + or between "@=" and AssignmentExpression are allowed +esid: sec-assignment-operators +description: Checking by evaluating expression "x[...]&&=[...]y" +features: [logical-assignment-operators] +---*/ +var x; + +x = 1; +assert.sameValue(x &&= 2, 2, 'U+0009 (expression)'); +assert.sameValue(x, 2, 'U+0009 (side effect)'); + +x = 1; +assert.sameValue(x&&=2, 2, 'U+000B (expression)'); +assert.sameValue(x, 2, 'U+000B (side effect)'); + +x = 1; +assert.sameValue(x&&=2, 2, 'U+000C (expression)'); +assert.sameValue(x, 2, 'U+000C (side effect)'); + +x = 1; +assert.sameValue(x &&= 2, 2, 'U+0020 (expression)'); +assert.sameValue(x, 2, 'U+0020 (side effect)'); + +x = 1; +assert.sameValue(x &&= 2, 2, 'U+00A0 (expression)'); +assert.sameValue(x, 2, 'U+00A0 (side effect)'); + +x = 1; +assert.sameValue(x +&&= +2, 2, 'U+000A (expression)'); +assert.sameValue(x, 2, 'U+000A (side effect)'); + +x = 1; +assert.sameValue(x +&&= +2, 2, 'U+000D (expression)'); +assert.sameValue(x, 2, 'U+000D (side effect)'); + +x = 1; +assert.sameValue(x
&&=
2, 2, 'U+2028 (expression)'); +assert.sameValue(x, 2, 'U+2028 (side effect)'); + +x = 1; +assert.sameValue(x
&&=
2, 2, 'U+2029 (expression)'); +assert.sameValue(x, 2, 'U+2029 (side effect)'); + +x = 1; +assert.sameValue(x +
&&= +
2, 2, 'U+0009U+000BU+000CU+0020U+00A0U+000AU+000DU+2028U+2029 (expression)'); +assert.sameValue(x, 2, 'U+0009U+000BU+000CU+0020U+00A0U+000AU+000DU+2028U+2029 (side effect)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-arguments-strict-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-arguments-strict-strict.js new file mode 100644 index 0000000000..24ca0cdcb6 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-arguments-strict-strict.js @@ -0,0 +1,20 @@ +// |reftest| error:SyntaxError +'use strict'; +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators +description: > + Strict Mode - SyntaxError is thrown if the identifier arguments + appear as the LeftHandSideExpression of a Logical Assignment + operator(??=) +flags: [onlyStrict] +negative: + phase: parse + type: SyntaxError +features: [logical-assignment-operators] +---*/ +$DONOTEVALUATE(); + +arguments ??= 20; diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-bigint.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-bigint.js new file mode 100644 index 0000000000..149099ab3f --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-bigint.js @@ -0,0 +1,28 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: Logical Nullish Assignment Operator +features: [BigInt, logical-assignment-operators] +info: | + AssignmentExpression: + LeftHandSideExpression ??= AssignmentExpression + + 1. Let lref be the result of evaluating LeftHandSideExpression. + 2. Let lval be ? GetValue(lref). + 3. If lval is neither undefined nor null, return lval. + 4. Let rref be the result of evaluating AssignmentExpression. + 5. Let rval be ? GetValue(rref). + 6. Perform ? PutValue(lref, rval). + 7. Return rval. + +---*/ + +var value = 0n; +assert.sameValue(value ??= 1n, 0n, "(value ??= 1n) === 0n; where value = 0n"); + +value = 2n; +assert.sameValue(value ??= 1n, 2n, "(value ??= 1n) === 2n; where value = 2n"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-lhs-before-rhs.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-lhs-before-rhs.js new file mode 100644 index 0000000000..1976fb4f91 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-lhs-before-rhs.js @@ -0,0 +1,55 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + The LeftHandSideExpression is evaluated before the AssignmentExpression. +features: [logical-assignment-operators] + +---*/ + +function DummyError() { } + +assert.throws(DummyError, function() { + var base = null; + var prop = function() { + throw new DummyError(); + }; + var expr = function() { + throw new Test262Error("right-hand side expression evaluated"); + }; + + base[prop()] ??= expr(); +}); + +assert.throws(TypeError, function() { + var base = null; + var prop = { + toString: function() { + throw new Test262Error("property key evaluated"); + } + }; + var expr = function() { + throw new Test262Error("right-hand side expression evaluated"); + }; + + base[prop] ??= expr(); +}); + +var count = 0; +var obj = {}; +function incr() { + return ++count; +} + +assert.sameValue(obj[incr()] ??= incr(), 2, "obj[incr()] ??= incr()"); +assert.sameValue(obj[1], 2, "obj[1]"); +assert.sameValue(count, 2, "count"); + +obj[3] = 1; +assert.sameValue(obj[incr()] ??= incr(), 1, "obj[incr()] ??= incr()"); +assert.sameValue(obj[3], 1, "obj[3]"); +assert.sameValue(count, 3, "count"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-namedevaluation-arrow-function.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-namedevaluation-arrow-function.js new file mode 100644 index 0000000000..424d5f70a5 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-namedevaluation-arrow-function.js @@ -0,0 +1,22 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: NamedEvaluation of Logical Nullish Assignment +info: | + AssignmentExpression: + LeftHandSideExpression ??= AssignmentExpression + + 4. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then + a. Let rval be NamedEvaluation of AssignmentExpression with argument GetReferencedName(lref). +features: [logical-assignment-operators] + +---*/ + +var value = undefined; +value ??= () => {}; + +assert.sameValue(value.name, "value", "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-namedevaluation-class-expression.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-namedevaluation-class-expression.js new file mode 100644 index 0000000000..389a8e896b --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-namedevaluation-class-expression.js @@ -0,0 +1,22 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: NamedEvaluation of Logical Nullish Assignment +info: | + AssignmentExpression: + LeftHandSideExpression ??= AssignmentExpression + + 4. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then + a. Let rval be NamedEvaluation of AssignmentExpression with argument GetReferencedName(lref). +features: [logical-assignment-operators] + +---*/ + +var value = undefined; +value ??= class {}; + +assert.sameValue(value.name, "value", "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-namedevaluation-function.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-namedevaluation-function.js new file mode 100644 index 0000000000..f293f4c4cf --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-namedevaluation-function.js @@ -0,0 +1,22 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: NamedEvaluation of Logical Nullish Assignment +info: | + AssignmentExpression: + LeftHandSideExpression ??= AssignmentExpression + + 4. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then + a. Let rval be NamedEvaluation of AssignmentExpression with argument GetReferencedName(lref). +features: [logical-assignment-operators] + +---*/ + +var value = undefined; +value ??= function() {}; + +assert.sameValue(value.name, "value", "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-no-set-put-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-no-set-put-strict.js new file mode 100644 index 0000000000..8c7854d7b8 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-no-set-put-strict.js @@ -0,0 +1,31 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is thrown if the LeftHandSide of a Logical + Assignment operator(??=) is a reference to a data property with the + attribute value {[[Set]]:undefined} and PutValue step is reached. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.defineProperty(obj, "prop", { + get: function() { + return undefined; + }, + set: undefined, + enumerable: true, + configurable: true +}); + +assert.throws(TypeError, function() { + obj.prop ??= 1; +}); +assert.sameValue(obj.prop, undefined, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-no-set-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-no-set-strict.js new file mode 100644 index 0000000000..f97739174b --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-no-set-strict.js @@ -0,0 +1,28 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is not thrown if the LeftHandSide of a Logical + Assignment operator(??=) is a reference to a data property with the + attribute value {[[Set]]:undefined} and PutValue step is not reached. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.defineProperty(obj, "prop", { + get: function() { + return 0; + }, + set: undefined, + enumerable: true, + configurable: true +}); + +assert.sameValue(obj.prop ??= 1, 0, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-extensible-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-extensible-strict.js new file mode 100644 index 0000000000..0c9b91f3fd --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-extensible-strict.js @@ -0,0 +1,24 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is thrown if The LeftHandSide of a Logical + Assignment operator(??=) is a reference to a non-existent property + of an object whose [[Extensible]] internal property is false. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.preventExtensions(obj); + +assert.throws(TypeError, function() { + obj.prop ??= 1; +}); +assert.sameValue(obj.prop, undefined, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-simple-lhs.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-simple-lhs.js new file mode 100644 index 0000000000..3e7a46afc3 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-simple-lhs.js @@ -0,0 +1,20 @@ +// |reftest| error:SyntaxError +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-static-semantics-early-errors +description: > + It is a Syntax Error if AssignmentTargetType of LeftHandSideExpression is + not simple. +negative: + phase: parse + type: SyntaxError +features: [logical-assignment-operators] + +---*/ + +$DONOTEVALUATE(); + +function test() {} +test() ??= 1; diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-writeable-put-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-writeable-put-strict.js new file mode 100644 index 0000000000..caef17b5d5 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-writeable-put-strict.js @@ -0,0 +1,29 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is thrown if the LeftHandSide of a Logical + Assignment operator(??=) is a reference to a data property with the + attribute value {[[Writable]]:false} and PutValue step is reached. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.defineProperty(obj, "prop", { + value: undefined, + writable: false, + enumerable: true, + configurable: true +}); + +assert.throws(TypeError, function() { + obj.prop ??= 1; +}); +assert.sameValue(obj.prop, undefined, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-writeable-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-writeable-strict.js new file mode 100644 index 0000000000..1340ca9390 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-writeable-strict.js @@ -0,0 +1,26 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is not thrown if the LeftHandSide of a Logical + Assignment operator(??=) is a reference to a data property with the + attribute value {[[Writable]]:false} and PutValue step is not reached. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.defineProperty(obj, "prop", { + value: 0, + writable: false, + enumerable: true, + configurable: true +}); + +assert.sameValue(obj.prop ??= 1, 0, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-unresolved-lhs-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-unresolved-lhs-strict.js new file mode 100644 index 0000000000..6473ffe917 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-unresolved-lhs-strict.js @@ -0,0 +1,19 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ReferenceError is thrown if the LeftHandSideExpression of a Logical + Assignment operator(??=) evaluates to an unresolvable reference +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +assert.throws(ReferenceError, function() { + unresolved ??= 1; +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-unresolved-rhs-put.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-unresolved-rhs-put.js new file mode 100644 index 0000000000..70c1b469d1 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-unresolved-rhs-put.js @@ -0,0 +1,21 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ReferenceError is thrown if the AssignmentExpression of a Logical + Assignment operator(??=) evaluates to an unresolvable reference and the + AssignmentExpression is evaluated. +features: [logical-assignment-operators] + +---*/ + +var value = undefined; + +assert.throws(ReferenceError, function() { + value ??= unresolved; +}); +assert.sameValue(value, undefined, "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-unresolved-rhs.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-unresolved-rhs.js new file mode 100644 index 0000000000..bc84537942 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator-unresolved-rhs.js @@ -0,0 +1,18 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ReferenceError is not thrown if the AssignmentExpression of a Logical + Assignment operator(??=) evaluates to an unresolvable reference and the + AssignmentExpression is not evaluated. +features: [logical-assignment-operators] + +---*/ + +var value = 0; + +assert.sameValue(value ??= unresolved, 0, "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator.js new file mode 100644 index 0000000000..f3cec88728 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-assignment-operator.js @@ -0,0 +1,62 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: Logical Nullish Assignment Operator +info: | + AssignmentExpression: + LeftHandSideExpression ??= AssignmentExpression + + 1. Let lref be the result of evaluating LeftHandSideExpression. + 2. Let lval be ? GetValue(lref). + 3. If lval is neither undefined nor null, return lval. + 4. Let rref be the result of evaluating AssignmentExpression. + 5. Let rval be ? GetValue(rref). + 6. Perform ? PutValue(lref, rval). + 7. Return rval. +features: [logical-assignment-operators] + +---*/ + +var value = undefined; +assert.sameValue(value ??= 1, 1, "(value ??= 1) === 1; where value = undefined"); + +value = null; +assert.sameValue(value ??= 1, 1, "(value ??= 1) === 1; where value = null"); + +value = false; +assert.sameValue(value ??= 1, false, "(value ??= 1) === false; where value = false"); + +value = 0; +assert.sameValue(value ??= 1, 0, "(value ??= 1) === 0; where value = 0"); + +value = -0; +assert.sameValue(value ??= 1, -0, "(value ??= 1) === -0; where value = -0"); + +value = NaN; +assert.sameValue(value ??= 1, NaN, "(value ??= 1) === NaN; where value = NaN"); + +value = ""; +assert.sameValue(value ??= 1, "", '(value ??= 1) === "" where value = ""'); + + + +value = true; +assert.sameValue(value ??= 1, true, "(value ??= 1) === true; where value = true"); + +value = 2; +assert.sameValue(value ??= 1, 2, "(value ??= 1) === 2; where value = 2"); + +value = "test"; +assert.sameValue(value ??= 1, "test", '(value ??= 1) === "test"; where value = "test"'); + +var sym = Symbol(""); +value = sym; +assert.sameValue(value ??= 1, sym, "(value ??= 1) === Symbol(); where value = Symbol()"); + +var obj = {}; +value = obj; +assert.sameValue(value ??= 1, obj, "(value ??= 1) === {}; where value = {}"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-eval-strict-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-eval-strict-strict.js new file mode 100644 index 0000000000..61ff3631bc --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-eval-strict-strict.js @@ -0,0 +1,19 @@ +// |reftest| error:SyntaxError +'use strict'; +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators +description: > + Strict Mode - SyntaxError is thrown if the identifier eval appear + as the LeftHandSideExpression of a Logical Assignment operator(??=) +flags: [onlyStrict] +negative: + phase: parse + type: SyntaxError +features: [logical-assignment-operators] +---*/ +$DONOTEVALUATE(); + +eval ??= 20; diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-non-simple.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-non-simple.js new file mode 100644 index 0000000000..7385dcf6e1 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-non-simple.js @@ -0,0 +1,18 @@ +// |reftest| error:SyntaxError +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-static-semantics-early-errors +info: | + It is an early Syntax Error if AssignmentTargetType of + LeftHandSideExpression is invalid or strict. +description: Logical "??=" assignment with non-simple target +negative: + phase: parse + type: SyntaxError +features: [logical-assignment-operators] +---*/ +$DONOTEVALUATE(); + +1 ??= 1; diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-whitespace.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-whitespace.js new file mode 100644 index 0000000000..7d92163dd6 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-nullish-whitespace.js @@ -0,0 +1,60 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +info: | + White Space and Line Terminator between LeftHandSideExpression and "@=" + or between "@=" and AssignmentExpression are allowed +esid: sec-assignment-operators +description: Checking by evaluating expression "x[...]??=[...]y" +features: [logical-assignment-operators] +---*/ +var x; + +x = null; +assert.sameValue(x ??= 1, 1, 'U+0009 (expression)'); +assert.sameValue(x, 1, 'U+0009 (side effect)'); + +x = null; +assert.sameValue(x??=1, 1, 'U+000B (expression)'); +assert.sameValue(x, 1, 'U+000B (side effect)'); + +x = null; +assert.sameValue(x??=1, 1, 'U+000C (expression)'); +assert.sameValue(x, 1, 'U+000C (side effect)'); + +x = null; +assert.sameValue(x ??= 1, 1, 'U+0020 (expression)'); +assert.sameValue(x, 1, 'U+0020 (side effect)'); + +x = null; +assert.sameValue(x ??= 1, 1, 'U+00A0 (expression)'); +assert.sameValue(x, 1, 'U+00A0 (side effect)'); + +x = null; +assert.sameValue(x +??= +1, 1, 'U+000A (expression)'); +assert.sameValue(x, 1, 'U+000A (side effect)'); + +x = null; +assert.sameValue(x +??= +1, 1, 'U+000D (expression)'); +assert.sameValue(x, 1, 'U+000D (side effect)'); + +x = null; +assert.sameValue(x
??=
1, 1, 'U+2028 (expression)'); +assert.sameValue(x, 1, 'U+2028 (side effect)'); + +x = null; +assert.sameValue(x
??=
1, 1, 'U+2029 (expression)'); +assert.sameValue(x, 1, 'U+2029 (side effect)'); + +x = null; +assert.sameValue(x +
??= +
1, 1, 'U+0009U+000BU+000CU+0020U+00A0U+000AU+000DU+2028U+2029 (expression)'); +assert.sameValue(x, 1, 'U+0009U+000BU+000CU+0020U+00A0U+000AU+000DU+2028U+2029 (side effect)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-arguments-strict-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-arguments-strict-strict.js new file mode 100644 index 0000000000..48f2c6847c --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-arguments-strict-strict.js @@ -0,0 +1,20 @@ +// |reftest| error:SyntaxError +'use strict'; +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators +description: > + Strict Mode - SyntaxError is thrown if the identifier arguments + appear as the LeftHandSideExpression of a Logical Assignment + operator(||=) +flags: [onlyStrict] +negative: + phase: parse + type: SyntaxError +features: [logical-assignment-operators] +---*/ +$DONOTEVALUATE(); + +arguments ||= 20; diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-bigint.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-bigint.js new file mode 100644 index 0000000000..bda9c537eb --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-bigint.js @@ -0,0 +1,29 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: Logical Or Assignment Operator +features: [BigInt, logical-assignment-operators] +info: | + AssignmentExpression: + LeftHandSideExpression ||= AssignmentExpression + + 1. Let lref be the result of evaluating LeftHandSideExpression. + 2. Let lval be ? GetValue(lref). + 3. Let lbool be ! ToBoolean(lval). + 4. If lbool is true, return lval. + 5. Let rref be the result of evaluating AssignmentExpression. + 6. Let rval be ? GetValue(rref). + 7. Perform ? PutValue(lref, rval). + 8. Return rval. + +---*/ + +var value = 0n; +assert.sameValue(value ||= 1n, 1n, "(value ||= 1n) === 1n; where value = 0n"); + +value = 2n; +assert.sameValue(value ||= 1n, 2n, "(value ||= 1n) === 2n; where value = 2n"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-lhs-before-rhs.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-lhs-before-rhs.js new file mode 100644 index 0000000000..f65d4acfff --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-lhs-before-rhs.js @@ -0,0 +1,55 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + The LeftHandSideExpression is evaluated before the AssignmentExpression. +features: [logical-assignment-operators] + +---*/ + +function DummyError() { } + +assert.throws(DummyError, function() { + var base = null; + var prop = function() { + throw new DummyError(); + }; + var expr = function() { + throw new Test262Error("right-hand side expression evaluated"); + }; + + base[prop()] ||= expr(); +}); + +assert.throws(TypeError, function() { + var base = null; + var prop = { + toString: function() { + throw new Test262Error("property key evaluated"); + } + }; + var expr = function() { + throw new Test262Error("right-hand side expression evaluated"); + }; + + base[prop] ||= expr(); +}); + +var count = 0; +var obj = {}; +function incr() { + return ++count; +} + +assert.sameValue(obj[incr()] ||= incr(), 2, "obj[incr()] ||= incr()"); +assert.sameValue(obj[1], 2, "obj[1]"); +assert.sameValue(count, 2, "count"); + +obj[3] = 1; +assert.sameValue(obj[incr()] ||= incr(), 1, "obj[incr()] ||= incr()"); +assert.sameValue(obj[3], 1, "obj[3]"); +assert.sameValue(count, 3, "count"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-arrow-function.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-arrow-function.js new file mode 100644 index 0000000000..19de1c8150 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-arrow-function.js @@ -0,0 +1,22 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: NamedEvaluation of Logical Or Assignment +info: | + AssignmentExpression: + LeftHandSideExpression ||= AssignmentExpression + + 5. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then + a. Let rval be NamedEvaluation of AssignmentExpression with argument GetReferencedName(lref). +features: [logical-assignment-operators] + +---*/ + +var value = 0; +value ||= () => {}; + +assert.sameValue(value.name, "value", "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-class-expression.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-class-expression.js new file mode 100644 index 0000000000..5c4aa91368 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-class-expression.js @@ -0,0 +1,22 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: NamedEvaluation of Logical Or Assignment +info: | + AssignmentExpression: + LeftHandSideExpression ||= AssignmentExpression + + 5. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then + a. Let rval be NamedEvaluation of AssignmentExpression with argument GetReferencedName(lref). +features: [logical-assignment-operators] + +---*/ + +var value = 0; +value ||= class {}; + +assert.sameValue(value.name, "value", "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-function.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-function.js new file mode 100644 index 0000000000..46c71f128b --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-function.js @@ -0,0 +1,22 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: NamedEvaluation of Logical Or Assignment +info: | + AssignmentExpression: + LeftHandSideExpression ||= AssignmentExpression + + 5. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then + a. Let rval be NamedEvaluation of AssignmentExpression with argument GetReferencedName(lref). +features: [logical-assignment-operators] + +---*/ + +var value = 0; +value ||= function() {}; + +assert.sameValue(value.name, "value", "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-no-set-put-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-no-set-put-strict.js new file mode 100644 index 0000000000..0d987baf23 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-no-set-put-strict.js @@ -0,0 +1,31 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is thrown if the LeftHandSide of a Logical + Assignment operator(||=) is a reference to a data property with the + attribute value {[[Set]]:undefined} and PutValue step is reached. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.defineProperty(obj, "prop", { + get: function() { + return 0; + }, + set: undefined, + enumerable: true, + configurable: true +}); + +assert.throws(TypeError, function() { + obj.prop ||= 1; +}); +assert.sameValue(obj.prop, 0, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-no-set-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-no-set-strict.js new file mode 100644 index 0000000000..3decdd426a --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-no-set-strict.js @@ -0,0 +1,28 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is not thrown if the LeftHandSide of a Logical + Assignment operator(||=) is a reference to a data property with the + attribute value {[[Set]]:undefined} and PutValue step is not reached. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.defineProperty(obj, "prop", { + get: function() { + return 2; + }, + set: undefined, + enumerable: true, + configurable: true +}); + +assert.sameValue(obj.prop ||= 1, 2, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-non-extensible-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-non-extensible-strict.js new file mode 100644 index 0000000000..6d3bd90e75 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-non-extensible-strict.js @@ -0,0 +1,24 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is thrown if The LeftHandSide of a Logical + Assignment operator(||=) is a reference to a non-existent property + of an object whose [[Extensible]] internal property is false. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.preventExtensions(obj); + +assert.throws(TypeError, function() { + obj.prop ||= 1; +}); +assert.sameValue(obj.prop, undefined, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-non-simple-lhs.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-non-simple-lhs.js new file mode 100644 index 0000000000..fe6f770428 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-non-simple-lhs.js @@ -0,0 +1,20 @@ +// |reftest| error:SyntaxError +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-static-semantics-early-errors +description: > + It is a Syntax Error if AssignmentTargetType of LeftHandSideExpression is + not simple. +negative: + phase: parse + type: SyntaxError +features: [logical-assignment-operators] + +---*/ + +$DONOTEVALUATE(); + +function test() {} +test() ||= 1; diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-non-writeable-put-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-non-writeable-put-strict.js new file mode 100644 index 0000000000..d534ad4358 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-non-writeable-put-strict.js @@ -0,0 +1,29 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is thrown if the LeftHandSide of a Logical + Assignment operator(||=) is a reference to a data property with the + attribute value {[[Writable]]:false} and PutValue step is reached. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.defineProperty(obj, "prop", { + value: 0, + writable: false, + enumerable: true, + configurable: true +}); + +assert.throws(TypeError, function() { + obj.prop ||= 1; +}); +assert.sameValue(obj.prop, 0, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-non-writeable-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-non-writeable-strict.js new file mode 100644 index 0000000000..58097a20ab --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-non-writeable-strict.js @@ -0,0 +1,26 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + Strict Mode - TypeError is not thrown if the LeftHandSide of a Logical + Assignment operator(||=) is a reference to a data property with the + attribute value {[[Writable]]:false} and PutValue step is not reached. +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +var obj = {}; +Object.defineProperty(obj, "prop", { + value: 2, + writable: false, + enumerable: true, + configurable: true +}); + +assert.sameValue(obj.prop ||= 1, 2, "obj.prop"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-unresolved-lhs-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-unresolved-lhs-strict.js new file mode 100644 index 0000000000..e783ff5ff4 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-unresolved-lhs-strict.js @@ -0,0 +1,19 @@ +'use strict'; +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ReferenceError is thrown if the LeftHandSideExpression of a Logical + Assignment operator(||=) evaluates to an unresolvable reference +flags: [onlyStrict] +features: [logical-assignment-operators] + +---*/ + +assert.throws(ReferenceError, function() { + unresolved ||= 1; +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-unresolved-rhs-put.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-unresolved-rhs-put.js new file mode 100644 index 0000000000..d482fe38d8 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-unresolved-rhs-put.js @@ -0,0 +1,21 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ReferenceError is thrown if the AssignmentExpression of a Logical + Assignment operator(||=) evaluates to an unresolvable reference and the + AssignmentExpression is evaluated. +features: [logical-assignment-operators] + +---*/ + +var value = 0; + +assert.throws(ReferenceError, function() { + value ||= unresolved; +}); +assert.sameValue(value, 0, "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-unresolved-rhs.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-unresolved-rhs.js new file mode 100644 index 0000000000..6a41c574e9 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator-unresolved-rhs.js @@ -0,0 +1,18 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: > + ReferenceError is not thrown if the AssignmentExpression of a Logical + Assignment operator(||=) evaluates to an unresolvable reference and the + AssignmentExpression is not evaluated. +features: [logical-assignment-operators] + +---*/ + +var value = 2; + +assert.sameValue(value ||= unresolved, 2, "value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator.js new file mode 100644 index 0000000000..6043caaf87 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-assignment-operator.js @@ -0,0 +1,63 @@ +// Copyright (c) 2020 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-runtime-semantics-evaluation +description: Logical Or Assignment Operator +info: | + AssignmentExpression: + LeftHandSideExpression ||= AssignmentExpression + + 1. Let lref be the result of evaluating LeftHandSideExpression. + 2. Let lval be ? GetValue(lref). + 3. Let lbool be ! ToBoolean(lval). + 4. If lbool is true, return lval. + 5. Let rref be the result of evaluating AssignmentExpression. + 6. Let rval be ? GetValue(rref). + 7. Perform ? PutValue(lref, rval). + 8. Return rval. +features: [logical-assignment-operators] + +---*/ + +var value = undefined; +assert.sameValue(value ||= 1, 1, "(value ||= 1) === 1; where value = undefined"); + +value = null; +assert.sameValue(value ||= 1, 1, "(value ||= 1) === 1; where value = null"); + +value = false; +assert.sameValue(value ||= 1, 1, "(value ||= 1) === 1; where value = false"); + +value = 0; +assert.sameValue(value ||= 1, 1, "(value ||= 1) === 1; where value = 0"); + +value = -0; +assert.sameValue(value ||= 1, 1, "(value ||= 1) === 1; where value = -0"); + +value = NaN; +assert.sameValue(value ||= 1, 1, "(value ||= 1) === 1; where value = NaN"); + +value = ""; +assert.sameValue(value ||= 1, 1, '(value ||= 1) === 1; where value = ""'); + + + +value = true; +assert.sameValue(value ||= 1, true, "(value ||= 1) === true; where value = true"); + +value = 2; +assert.sameValue(value ||= 1, 2, "(value ||= 1) === 2; where value = 2"); + +value = "test"; +assert.sameValue(value ||= 1, "test", '(value ||= 1) === "test"; where value = "test"'); + +var sym = Symbol(""); +value = sym; +assert.sameValue(value ||= 1, sym, "(value ||= 1) === Symbol(); where value = Symbol()"); + +var obj = {}; +value = obj; +assert.sameValue(value ||= 1, obj, "(value ||= 1) === {}; where value = {}"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-eval-strict-strict.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-eval-strict-strict.js new file mode 100644 index 0000000000..d64e44e0b0 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-eval-strict-strict.js @@ -0,0 +1,19 @@ +// |reftest| error:SyntaxError +'use strict'; +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators +description: > + Strict Mode - SyntaxError is thrown if the identifier eval appear + as the LeftHandSideExpression of a Logical Assignment operator(||=) +flags: [onlyStrict] +negative: + phase: parse + type: SyntaxError +features: [logical-assignment-operators] +---*/ +$DONOTEVALUATE(); + +eval ||= 20; diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-non-simple.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-non-simple.js new file mode 100644 index 0000000000..2c3195010b --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-non-simple.js @@ -0,0 +1,18 @@ +// |reftest| error:SyntaxError +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-assignment-operators-static-semantics-early-errors +info: | + It is an early Syntax Error if AssignmentTargetType of + LeftHandSideExpression is invalid or strict. +description: Logical "||=" assignment with non-simple target +negative: + phase: parse + type: SyntaxError +features: [logical-assignment-operators] +---*/ +$DONOTEVALUATE(); + +1 ||= 1; diff --git a/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-whitespace.js b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-whitespace.js new file mode 100644 index 0000000000..d4091dcb2d --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/lgcl-or-whitespace.js @@ -0,0 +1,60 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +info: | + White Space and Line Terminator between LeftHandSideExpression and "@=" + or between "@=" and AssignmentExpression are allowed +esid: sec-assignment-operators +description: Checking by evaluating expression "x[...]||=[...]y" +features: [logical-assignment-operators] +---*/ +var x; + +x = 0; +assert.sameValue(x ||= 1, 1, 'U+0009 (expression)'); +assert.sameValue(x, 1, 'U+0009 (side effect)'); + +x = 0; +assert.sameValue(x||=1, 1, 'U+000B (expression)'); +assert.sameValue(x, 1, 'U+000B (side effect)'); + +x = 0; +assert.sameValue(x||=1, 1, 'U+000C (expression)'); +assert.sameValue(x, 1, 'U+000C (side effect)'); + +x = 0; +assert.sameValue(x ||= 1, 1, 'U+0020 (expression)'); +assert.sameValue(x, 1, 'U+0020 (side effect)'); + +x = 0; +assert.sameValue(x ||= 1, 1, 'U+00A0 (expression)'); +assert.sameValue(x, 1, 'U+00A0 (side effect)'); + +x = 0; +assert.sameValue(x +||= +1, 1, 'U+000A (expression)'); +assert.sameValue(x, 1, 'U+000A (side effect)'); + +x = 0; +assert.sameValue(x +||= +1, 1, 'U+000D (expression)'); +assert.sameValue(x, 1, 'U+000D (side effect)'); + +x = 0; +assert.sameValue(x
||=
1, 1, 'U+2028 (expression)'); +assert.sameValue(x, 1, 'U+2028 (side effect)'); + +x = 0; +assert.sameValue(x
||=
1, 1, 'U+2029 (expression)'); +assert.sameValue(x, 1, 'U+2029 (side effect)'); + +x = 0; +assert.sameValue(x +
||= +
1, 1, 'U+0009U+000BU+000CU+0020U+00A0U+000AU+000DU+2028U+2029 (expression)'); +assert.sameValue(x, 1, 'U+0009U+000BU+000CU+0020U+00A0U+000AU+000DU+2028U+2029 (side effect)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/logical-assignment/shell.js b/js/src/tests/test262/language/expressions/logical-assignment/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/language/expressions/logical-assignment/shell.js |