You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Re-exporting a default (`export { default as x } from`) routes through the interop helper to match bundler behavior for CJS sources.
15
17
- When the interop helper is emitted, `exports.__esModule = true` is also seeded for downstream consumers.
16
18
17
-
## Exports
19
+
## Exports and live bindings
18
20
19
-
- Local named exports emit to `exports.<name>` (or bracket access) with `Object.defineProperty` getters when `liveBindings: 'strict'`.
20
-
-`export default` writes to `module.exports = <expr>`; default functions/classes preserve their identifier before exporting.
21
+
- Local named exports emit to `exports.<name>` (or bracket access) with `Object.defineProperty` getters when `liveBindings: 'strict'`; snapshot assignment is used for `loose`/`off`.
22
+
-`export default` writes to `module.exports = <expr>` in the common case; when TLA is present and allowed (`wrap`/`preserve`), default exports write to `exports.default = <expr>` so the exports object stays stable for async wrapping.
21
23
-`export * from` lowers to a `for...in` over the required module, skipping `default`, guarding on `hasOwnProperty`, and defining getters to mirror live bindings.
22
-
- Named re-exports from another module (`export { foo as bar } from`) assign using either a direct property read or the interop helper for `default`.
24
+
- Named re-exports from another module (`export { foo as bar } from`) use getters when `liveBindings: 'strict'`, otherwise snapshot assignment; `default` re-exports still use the interop helper.
25
+
26
+
## Top-level await
27
+
28
+
-`topLevelAwait: 'error'` (default) throws during transform when a TLA is found while targeting CommonJS.
29
+
-`topLevelAwait: 'wrap'` wraps the entire CJS output in `const __tla = (async () => { ...; return module.exports; })();` and attaches `__tla` to both `module.exports` and the resolved value. Consumers can await `require('./file').__tla` for readiness.
30
+
-`topLevelAwait: 'preserve'` runs the lowered code inside an immediately-invoked async function but does not attach a promise; consumers must rely on the natural scheduling of async effects.
31
+
- In both allowed modes, default exports write to `exports.default` instead of replacing `module.exports` to keep the exports object consistent while async initialization completes.
32
+
- Fixture: `test/fixtures/topLevelAwait.mjs` plus tests in `test/module.ts` cover both `wrap` and `preserve` behaviors.
-`import.meta.main` → configurable: default shim to `process.argv[1] === __filename`; with `importMetaMain: 'warn'` a warning is embedded for Node <22.18/24.2; with `importMetaMain: 'error'` the transform throws on those runtimes.
31
41
- Bare `import.meta` becomes `module` so property accesses stay valid in CJS output.
32
42
33
43
## Fixtures for this phase
@@ -36,4 +46,5 @@
36
46
-`test/fixtures/esmNamed.mjs`: named import and aliasing from the CJS provider, re-exported for assertions.
37
47
-`test/fixtures/esmNamespace.mjs`: namespace import shape from the CJS provider, re-exported as `ns`.
38
48
-`test/fixtures/esmReexport.mjs`: named + star re-exports from the CJS provider (includes live binding passthrough).
49
+
-`test/fixtures/liveReexport.mjs`: re-export from a mutating CJS source; exercised when `liveBindings: 'strict'` to verify getter-based live bindings.
39
50
-`test/fixtures/esmProvider.cjs`: CJS source exposing default/named exports plus a mutating `live` counter for binding checks (interval is `unref()`ed; tests wait ≥30ms to observe changes).
return`(${importMetaMainSupport} ? ${importMetaMainShim} : (console.warn("import.meta.main is not supported before Node 22.18/24.2; falling back to shim."), ${importMetaMainShim}))`
14
+
case'error':
15
+
return`(${importMetaMainSupport} ? ${importMetaMainShim} : (() => { throw new Error("import.meta.main is not supported before Node 22.18/24.2"); })())`
16
+
case'shim':
17
+
default:
18
+
returnimportMetaMainShim
19
+
}
20
+
}
21
+
6
22
exportconstmetaProperty=(
7
23
node: MetaProperty,
8
24
parent: Node|null,
@@ -34,12 +50,14 @@ export const metaProperty = (
34
50
break
35
51
case'resolve':
36
52
/**
37
-
* Should this be `require('node:url').pathToFileURL(require.resolve(<parsed specifier>)).href`?
53
+
* Map to require.resolve intentionally: matches CJS resolution semantics.
54
+
* Wrapping in pathToFileURL(...) would change the return shape (URL string)
55
+
* without truly emulating ESM import.meta.resolve rules.
0 commit comments