Module Namespace Objects - "writable"

# T.J. Crowder (6 years ago)

I'm curious if I've inferred the rationale for something correctly.

The module namespace object properties for exports have writable: true in their property descriptors, but of course, they aren't writable (the module namespace object has its own [[Set]] implementation that returns false). I wondered why they weren't writable: false, so I went looking.

I found discussion in the March 24 2015 meeting notes about whether to even have getOwnPropertyDescriptor work. The consensus was yes, it should work (mixins!), and that it should report a basic data property that isn't configurable -- but is writable. Yahuda Katz points out that:

it is writable, but it's not writable by you

though that's not always true (it may be declared const; that information isn't leaked from the module, though).

In the May 25 2017 notes I found a comment from Mark S. Miller in relation to writable: true:

Non-writeable provides guarantee. Writable provides no guarantee.

And this exchange between Yahuda Katz, Allen Wirfs-Brock, and Adam Klein:

YK: There is a a new property that we define as writable that is not

writable.

AWB: Not new.

AK: Since... Proxys!

There was some discussion of considering some flag basically saying what YK said, e.g., it's writable, but not by you :-) -- but that was more a brief digression that didn't go anywhere.

So, then, what I infer is: They're marked writable because:

  1. They may be writable by the exporting module, so code can't assume the value won't change; writable: false would make that assumption valid
  2. Whether or not they're writable by the exporting module isn't information that should leak out of it
  3. Non-writable writable: true data properties were already a thing (Proxies)

So the most sensible thing was writable: true rather than writable: false.

How'd I do? :-)

-- T.J. Crowder

# Logan Smyth (6 years ago)

Here's one other post about this from Allen: tc39/ecma262#749

# Mark Miller (6 years ago)

Extremely good!

But it is more than just a "should" or "sensible". It is a requirement of the object invariants. If a property is described as a non-configurable non-writable data property, it must always have the same value.

One issue I think should be open to debate: If the exported variable is declared const, do we follow the principle you mention:

  1. Whether or not they're writable by the exporting module isn't

information that should leak out of it

or do we consider the exporting module to be exporting its const-ness as well? If the latter, then those properties probably should be described as non-writable non-configurable data properties with, therefore, a stable value.

However, I say "probably" above because of one issue that gives me pause: the temporal dead zone. It does not violate the invariants for a [[Get]] or [[GetOwnPropertyDescriptor]] on a non-writable non-configurable data property to intermittently fail with a thrown error. The stability guarantee is only regarding what the non-failure cases report. But it is weird to report that a property is a non-writable non-configurable data property with a stable value before that value is determined. Worse, given how the object invariants are enforced on proxies (with the shadow target bookkeeping), I don't see how a proxy could emulate this behavior. This is in some sense a flaw in the proxy design: This shows an exotic object behavior that is allowed by the object invariants but not emulatable by proxies.

# Mark Miller (6 years ago)

Ah. Crossed in the mail. Yes, Alan raises the same issues regarding the TDZ vs non-writable worry.

Thanks for the pointer.

# T.J. Crowder (6 years ago)

Oooh, I see.

Fantastic, thank you Mark and Logan!

-- T.J. Crowder