fix(compartment-mapper): Support ESM imports defined property from CJ… #2330
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
…S from set property of CJS
Refs: Agoric/agoric-sdk#9408
Description
If a modern JavaScript module imports a named binding from a CommonJS module, we can hardly guarantee that it will always work. Outrageous heroics make it work under most circumstances using a heuristic lexical analysis of the CommonJS module to determine which names should exist on the module’s internal namespace. Then, the CommonJS runtime must account for all variety of shenanigans that might cause the binding for that name to change. These include assignment to property names on
exports
, reassignment tomodule.exports
, anddefineProperty
on the originalexports
object. These changes must be reflected both on the module namespace object and on thedefault
property thereof in in every case where this is in fact possible.Consider a CJS module (2.cjs) that exports a name:
Then, consider a TypeScript module (1.ts) that reexports this name:
Which gets compiled down to a CommonJS module (1.cjs):
Which gets imported by an ESM by name (0.mjs):
This has no right to work. We can trivially copy the getter from 1.cjs to the
default
export but the internal namespace object we use to emulate ESM in SES emits live binding notifications for every named property and doesn’t sufferdefineProperty
well. So, in the CommonJS emulation, we must attempt to propagate the current value from the getter to the module environment record after the module initializes.Security Considerations
None.
Scaling Considerations
None.
Documentation Considerations
None. Folks already assume this works. It works in Node.js. Code exists that relies on it.
Testing Considerations
We have an existing test that exercises the case that the getter under a defineProperty can’t be expected to succeed on the stack of defineProperty.
Compatibility Considerations
This increases ecosystem compatibility.
Upgrade Considerations
None.
PS
It didn’t have to be like this.