Ecma262: [[GetOwnProperty]] on module namespace exotic object returns writable: true, but [[Set]] is a noop

Created on 8 Dec 2016  路  8Comments  路  Source: tc39/ecma262

This means that it actually is _not_ possible to write to the property. It is not configurable or extensible too so [[DefineOwnProperty]] would fail, but it's defined to do nothing on module namespace exotic objects too so that's also out.

See https://tc39.github.io/ecma262/#sec-module-namespace-exotic-objects-getownproperty-p and https://tc39.github.io/ecma262/#sec-module-namespace-exotic-objects-set-p-v-receiver

question

All 8 comments

See definition of invariants of essential internal methods. If the value of a property can observably change then the writable attribute of the property must report as true.

While direct MOP operations on these objects can't change the property values, they are really just aliases for accessing (usually) mutable declative binds from some defining module. The values of such bindings can change. So, writable must be true.

Arguably, module name space properties that alias const declaration could report as writable:false. But importers do not have visibility of the declarative form used to define an export. Also initialization sequencing TDZ 聽enforcement means that accessing an imported const via a module name space object could observably change from reference error (TDZ) to some normal value.

Would another alternative be, making it a non-writable getter? Or would that create performance implications we wish to avoid?

If they were accessor properties then [[GetOwnProperty]] would have to reify a unique get accessor function for each property. And, those functions could be passed round arbitrarily.

The semantics of Module name space objects was designed to allow implementations to collapse chains of import/export indirections into a direct access to the base exported declarative binding. We don't want to screw that up by introducing accessors into the semantics.There is nothing buggy about an exotic object that is writable: true yet throws in a [[Set]]. That was explicitly anticipated because some DOM objects also work that way.

The problem is that the value of the property _cannot_ observably change, or at least its identity is fixed at creation time and cannot be changed, so the invariant is not violated for live bindings even with writable: false.

If a property P is described as a data property with Desc.[[Value]] equal to v and Desc.[[Writable]] and Desc.[[Configurable]] are both false, then the SameValue must be returned for the Desc.[[Value]] attribute of the property on all future calls to [[GetOwnProperty]] ( P ).

Even if the value is an object reference, while the object itself may be internally mutated, the result of SameValue will never change.

EDIT: ah, since [[Get]] fetches the value directly from the other module's environment record, the value might indeed change if it is not a const... 馃槙

This does also mean, though, that non-engine implementations (webpack, babel, etc) cannot implement the module record without actually using getters / chains of getters.

There is nothing buggy about an exotic object that is writable: false yet throws in a [[Set]].

The problem here is the inverse; it is writable: true yet throws in a [[Set]].

@Kovensky

The problem here is the inverse; it is writable: true yet throws in a [[Set]].

oops, typo. Meant writable: true. Corrected.

see https://tc39.github.io/ecma262/#sec-invariants-of-the-essential-internal-methods
In particular, NOTE 2 under [[GetOwnProperty]]

This seems answered; OK to close?

Was this page helpful?
0 / 5 - 0 ratings