tc39 / proposal-defer-import-eval

A proposal for introducing a way to defer evaluate of a module
https://tc39.es/proposal-defer-import-eval
MIT License
208 stars 12 forks source link

Add support for "defer" re-exports #31

Open nicolo-ribaudo opened 5 months ago

nicolo-ribaudo commented 5 months ago

[!NOTE] See #30 for an alternative. Differences between the two PRs are marked with πŸ”Ž

export defer { foo, bar } from "./there.js"

This PR extends the πŸ”Ždefer keyword to named re-exports, with the following properties:

An optional re-export is considered to be used if the consumer of the module is:

πŸ”Ž If the consumer module is importing with import defer * as or import.defer(...), optional re-exports are preloaded but not evaluated until when the corresponding binding is accessed on the namespace object (async subgraphs are still pre-evaluated).

A bundler/transpiler can re-write deferred re-exports to these exact semantics by moving them to the consumer module:

OriginalRewritten
```js // main.js import { val, bar } from "./dep.js"; import "other"; // dep.js export let val = 2; export { foo } from "a"; export defer { bar } from "b"; export defer { baz } from "c"; ``` ```js // main.js import { val } from "./dep.js"; import { bar } from "b"; import "other"; // dep.js export let val = 2; export { foo } from "a"; ```
```js // main.js import * as ns from "./dep.js"; // dep.js export let val = 2; export { foo } from "a"; export defer { bar } from "b"; export defer { baz } from "c"; ``` ```js // main.js import * as _n1 from "./dep.js"; import * as _n2 from "b"; import * as _n2 from "c"; const ns = Object.freeze({ __proto__: null, get val() { return _n1.val; }, get foo() { return _n1.foo; }, get bar() { return _n2.bar; }, get baz() { return _n3.baz; }, }) // dep.js export let val = 2; export { foo } from "a"; ```
πŸ”Ž ```js // main.js import defer * as ns from "./dep.js"; // dep.js export let val = 2; export { foo } from "a"; export optional { bar } from "b"; export optional { baz } from "c"; ``` ```js // main.js import defer * as _n1 from "./dep.js"; import defer * as _n2 from "b"; import defer * as _n2 from "c"; const _run = () => { _n1.val; } const ns = Object.freeze({ __proto__: null, get val() { _run(); return _n1.val; }, get foo() { _run(); return _n1.foo; }, get bar() { _run(); return _n2.bar; }, get baz() { _run(); return _n3.baz; }, }) // dep.js export let val = 2; export { foo } from "a"; ```

Rendered preview: https://nicolo-ribaudo.github.io/proposal-defer-import-eval/branch/deferred-exports.html