# Module namespace objects: why are properties writable but not mutable in practice?

**URL:** <https://es.discourse.group/t/module-namespace-objects-why-are-properties-writable-but-not-mutable-in-practice/1584>\
**Category:** I have questions\
**Created:** [January 10, 2023, 10:08pm UTC](https://es.discourse.group/t/module-namespace-objects-why-are-properties-writable-but-not-mutable-in-practice/1584 "2023-01-10T22:08:14Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Josh-Cena](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/josh-cena/32/1408_2.png) [@Josh-Cena](https://es.discourse.group/u/Josh-Cena)\
**Post date:** [January 10, 2023, 10:08pm UTC](https://es.discourse.group/t/module-namespace-objects-why-are-properties-writable-but-not-mutable-in-practice/1584/1 "2023-01-10T22:08:14Z")

</div>

A module namespace object has all string properties writable and non-configurable. However, due to the `[[DefineOwnProperty]]` and `[[Set]]` exotic behaviors, the properties are in fact not mutable. In what case is the writability useful?

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [January 10, 2023, 10:32pm UTC](https://es.discourse.group/t/module-namespace-objects-why-are-properties-writable-but-not-mutable-in-practice/1584/2 "2023-01-10T22:32:15Z")

</div>

If it wasn't writable, you could write code that depends on the value not changing.

However, since exports are "live", the value can change at any time, which means it _must_ be marked as writable.

---

<div class="post-metadata">

**Author:** ![bakkot](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bakkot/32/22_2.png) [@bakkot](https://es.discourse.group/u/bakkot)\
**Post date:** [January 10, 2023, 11:58pm UTC](https://es.discourse.group/t/module-namespace-objects-why-are-properties-writable-but-not-mutable-in-practice/1584/3 "2023-01-10T23:58:49Z")

</div>

And indeed one of the [essential invariants](https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-invariants-of-the-essential-internal-methods) states if the value of a non-configurable data property can change then that property must be marked writable. (The invariant is written as the contrapositive of that - "If P is described as a non-configurable, non-writable own data property, all future calls to [[GetOwnProperty]] ( P ) must return Property Descriptor whose [[Value]] is SameValue as P's [[Value]] attribute." - but it's equivalent.)

---

<div class="post-metadata">

**Author:** ![Josh-Cena](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/josh-cena/32/1408_2.png) [@Josh-Cena](https://es.discourse.group/u/Josh-Cena)\
**Post date:** [January 11, 2023, 5:35am UTC](https://es.discourse.group/t/module-namespace-objects-why-are-properties-writable-but-not-mutable-in-practice/1584/4 "2023-01-11T05:35:19Z")

</div>

That makes so much sense—thanks @ljharb and @bakkot

---

<div class="post-metadata">

**Author:** ![mhofman](https://avatars.discourse-cdn.com/v4/letter/m/f14d63/32.png) [@mhofman](https://es.discourse.group/u/mhofman)\
**Post date:** [January 13, 2023, 4:43pm UTC](https://es.discourse.group/t/module-namespace-objects-why-are-properties-writable-but-not-mutable-in-practice/1584/5 "2023-01-13T16:43:46Z")

</div>

In theory `const` exports when out of TDZ could be shown as non writable, as they'd be guaranteed not to change. This is actually something the Moddable implementation of modules in XS does, which is not technically spec compliant. Been wondering if it's a behavior we should specify.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [January 13, 2023, 4:56pm UTC](https://es.discourse.group/t/module-namespace-objects-why-are-properties-writable-but-not-mutable-in-practice/1584/6 "2023-01-13T16:56:15Z")

</div>

Doing so would expose whether an export used const, or let/var, and would thus become an observable part of a module’s API - making it a breaking change to switch between them - so i don’t think it would be a good thing to specify and expose.

---

<div class="post-metadata">

**Author:** ![Josh-Cena](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/josh-cena/32/1408_2.png) [@Josh-Cena](https://es.discourse.group/u/Josh-Cena)\
**Post date:** [January 13, 2023, 6:33pm UTC](https://es.discourse.group/t/module-namespace-objects-why-are-properties-writable-but-not-mutable-in-practice/1584/7 "2023-01-13T18:33:56Z")

</div>

I thought about what @mhofman said as well, but self-rejected it as a backward-incompatible change of ES itself. However, I don't feel like it's any more of an API stability risk than, say, changing the `name` or `length` of an exported function, or whether you are freezing an object, provided that was never part of the API contract.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [January 13, 2023, 6:44pm UTC](https://es.discourse.group/t/module-namespace-objects-why-are-properties-writable-but-not-mutable-in-practice/1584/8 "2023-01-13T18:44:31Z")

</div>

My view is that anything observable, including the things you mentioned, are part of the API contract (except for function toString because that’d be absurd)

---

<div class="post-metadata">

**Author:** ![mhofman](https://avatars.discourse-cdn.com/v4/letter/m/f14d63/32.png) [@mhofman](https://es.discourse.group/u/mhofman)\
**Post date:** [January 14, 2023, 3:08am UTC](https://es.discourse.group/t/module-namespace-objects-why-are-properties-writable-but-not-mutable-in-practice/1584/9 "2023-01-14T03:08:28Z")

</div>

Maybe an alternative would be to implement define property in the module namespace exotic such that setting the property to non-writable would succeed if the binding is a const out of TDZ. That's a slightly less observable change and would allow "freezing" the module namespace.

---

<div class="post-metadata">

**Author:** ![bergus](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bergus/32/152_2.png) [@bergus](https://es.discourse.group/u/bergus)\
**Post date:** [January 14, 2023, 10:35am UTC](https://es.discourse.group/t/module-namespace-objects-why-are-properties-writable-but-not-mutable-in-practice/1584/10 "2023-01-14T10:35:36Z")

</div>

I wonder if there is a reason why properties of module namespace objects were not made to be non-configurable getters without a setter?

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [January 14, 2023, 12:37pm UTC](https://es.discourse.group/t/module-namespace-objects-why-are-properties-writable-but-not-mutable-in-practice/1584/11 "2023-01-14T12:37:40Z")

</div>

Possibly to avoid allocation the extra getter function, it would also create a hidden communications presuming the function isn't frozen.

---

<div class="post-metadata">

**Author:** ![senocular](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/senocular/32/642_2.png) [@senocular](https://es.discourse.group/u/senocular)\
**Post date:** [January 14, 2023, 9:42pm UTC](https://es.discourse.group/t/module-namespace-objects-why-are-properties-writable-but-not-mutable-in-practice/1584/12 "2023-01-14T21:42:58Z")

</div>

Oddly enough the Chrome console shows exports in a module object as accessor properties even though this is not observable in code (getOwnPropertyDescriptor shows exports as data properties)

 ![image](https://global.discourse-cdn.com/free1/uploads/es/original/2X/4/496f79769d1ec4ae8b3569636fc1aa812861bb7f.png)
