diff --git a/test/language/module-code/namespace/internals/super-access-to-tdz-binding.js b/test/language/module-code/namespace/internals/super-access-to-tdz-binding.js new file mode 100644 index 00000000000..5e1876eba3d --- /dev/null +++ b/test/language/module-code/namespace/internals/super-access-to-tdz-binding.js @@ -0,0 +1,46 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-module-namespace-exotic-objects-getownproperty-p +description: > + super.foo = V throws ReferenceError when Receiver is a module namespace + with an uninitialized binding +info: | + OrdinarySetWithOwnDescriptor ( _O_, _P_, _V_, _Receiver_, _ownDesc_ ) + ... + 1. If IsDataDescriptor(_ownDesc_) is *true*, then + 1. If _ownDesc_.[[Writable]] is *false*, return *false*. + 1. If _Receiver_ is not an Object, return *false*. + 1. Let _existingDescriptor_ be ? _Receiver_.[[GetOwnProperty]](_P_). + ... + + [[GetOwnProperty]] ( _P_ ) + ... + 1. Let _value_ be ? _O_.[[Get]](_P_, _O_). + ... + + [[Get]] ( _P_, _Receiver_ ) + ... + 1. Let _targetEnvRec_ be _targetEnv_'s EnvironmentRecord. + 1. Return ? _targetEnvRec_.GetBindingValue(_binding_.[[BindingName]], *true*). + + NOTE: If the binding is uninitialized, GetBindingValue throws a *ReferenceError*. +flags: [module] +features: [let] +---*/ + +import * as ns from './super-access-to-tdz-binding.js'; + +class A { constructor() { return ns; } }; +class B extends A { + constructor() { + super(); + super.foo = 14; + } +}; + +assert.throws(ReferenceError, function() { + new B(); +}); + +export let foo = 42; diff --git a/test/language/module-code/namespace/internals/super-set-to-tdz-binding-with-accessor.js b/test/language/module-code/namespace/internals/super-set-to-tdz-binding-with-accessor.js new file mode 100644 index 00000000000..7c546b36afd --- /dev/null +++ b/test/language/module-code/namespace/internals/super-set-to-tdz-binding-with-accessor.js @@ -0,0 +1,43 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-ordinarysetwithowndescriptor +description: > + super.foo = V calls the accessor on super class instead of throwing + ReferenceError for TDZ binding +info: | + OrdinarySetWithOwnDescriptor ( _O_, _P_, _V_, _Receiver_, _ownDesc_ ) + ... + 1. Assert: IsAccessorDescriptor(_ownDesc_) is *true*. + 1. Let _setter_ be _ownDesc_.[[Set]]. + 1. If _setter_ is *undefined*, return *false*. + 1. Perform ? Call(_setter_, _Receiver_, « _V_ »). + 1. Return *true*. + + NOTE: When the super class has an accessor property, the setter is called + directly and the Receiver's [[GetOwnProperty]] is never invoked, so the + module namespace TDZ binding is not accessed. +flags: [module] +features: [let] +---*/ + +import * as ns from './super-set-to-tdz-binding-with-accessor.js'; + +var setterValue; + +class A { + constructor() { return ns; } + set foo(v) { setterValue = v; } +}; +class B extends A { + constructor() { + super(); + super.foo = 14; + } +}; + +new B(); + +assert.sameValue(setterValue, 14, "setter on A.prototype should be called with the assigned value"); + +export let foo = 42;