Skip to content

Support ES6 module syntax in Acorn, Babel and Closure#23730

Open
kleisauke wants to merge 32 commits intoemscripten-core:mainfrom
kleisauke:es6-acorn-closure
Open

Support ES6 module syntax in Acorn, Babel and Closure#23730
kleisauke wants to merge 32 commits intoemscripten-core:mainfrom
kleisauke:es6-acorn-closure

Conversation

@kleisauke
Copy link
Copy Markdown
Collaborator

@kleisauke kleisauke commented Feb 23, 2025

Acorn, Babel and Closure are now made aware of ES6 module syntax
when linking with -sEXPORT_ES6. The previous mangling of top-level
await, import.meta and dynamic import() is tightened to only
mangle top-level await when Closure is enabled, since this is the
only construct not supported there.

This file is not included when building with `-sMODULARIZE=instance`.
This is an automatic change generated by tools/maint/rebaseline_tests.py.

The following (6) test expectation files were updated by
running the tests with `--rebaseline`:

```
codesize/test_codesize_minimal_esm.json: 2504 => 2427 [-77 bytes / -3.08%]
codesize/test_minimal_runtime_code_size_hello_webgl2_wasm.json: 13199 => 13656 [+457 bytes / +3.46%]
codesize/test_minimal_runtime_code_size_hello_webgl2_wasm2js.json: 18537 => 19154 [+617 bytes / +3.33%]
codesize/test_minimal_runtime_code_size_hello_webgl2_wasm_singlefile.json: 15132 => 15604 [+472 bytes / +3.12%]
codesize/test_minimal_runtime_code_size_hello_webgl_wasm.json: 12737 => 13163 [+426 bytes / +3.34%]
codesize/test_minimal_runtime_code_size_hello_webgl_wasm2js.json: 18063 => 18652 [+589 bytes / +3.26%]

Average change: +2.24% (-3.08% - +3.46%)
```
This is an automatic change generated by tools/maint/rebaseline_tests.py.

The following (1) test expectation files were updated by
running the tests with `--rebaseline`:

```
codesize/test_codesize_minimal_esm.json: 2504 => 2474 [-30 bytes / -1.20%]

Average change: -1.20% (-1.20% - -1.20%)
```
This is an automatic change generated by tools/maint/rebaseline_tests.py.

The following (1) test expectation files were updated by
running the tests with `--rebaseline`:

```
codesize/test_codesize_minimal_esm.json: 2494 => 2525 [+31 bytes / +1.24%]

Average change: +1.24% (+1.24% - +1.24%)
```
This is an automatic change generated by tools/maint/rebaseline_tests.py.

The following (1) test expectation files were updated by
running the tests with `--rebaseline`:

```
codesize/test_codesize_minimal_esm.json: 2525 => 2521 [-4 bytes / -0.16%]

Average change: -0.16% (-0.16% - -0.16%)
```
@kleisauke kleisauke changed the title Support ES6 module syntax in Acorn and Closure Support ES6 module syntax in Acorn, Babel and Closure Jan 19, 2026
@kleisauke kleisauke marked this pull request as ready for review January 19, 2026 10:42
This is an automatic change generated by tools/maint/rebaseline_tests.py.

The following (1) test expectation files were updated by
running the tests with `--rebaseline`:

```
codesize/test_codesize_minimal_esm.json: 2523 => 2520 [-3 bytes / -0.12%]

Average change: -0.12% (-0.12% - -0.12%)
```
@kleisauke
Copy link
Copy Markdown
Collaborator Author

kleisauke commented Apr 4, 2026

PTAL, this would help PR #26384. Though, perhaps PR #26604 should land first, as it would make the changes to strip-node-prefix.mjs‎ and test_other.py unnecessary.

src/shell.js Outdated
const { createRequire } = await import('node:module');
/** @suppress{duplicate} */
var require = createRequire(import.meta.url);
global.require = createRequire(import.meta.url);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we prefer globalThis here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use global.Worker below, so aligning with that seemed reasonable (and it saves 4 bytes). Though, it appears to be legacy:
https://nodejs.org/api/globals.html#global

(there was a reason I originally did this, likely something related to Closure, but I can't recall the exact reason anymore)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... looking at commit ef36474, I think that I know the reason behind this. This was likely necessary for the now-removed strip-node-prefix.mjs Babel plugin, which required require() to remain unminified. Let me revert this.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted this with commit af43dd1, which further reduces the codesize expectations of codesize.test_codesize_minimal_esm.

which lives at: https://github.com/emscripten-core/terser/

The current patches are stored in the `emscripten_patches_v4.8.0` branch.
The current patches are stored in the `emscripten_patches_v5.18.2` branch.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a driveby fix? Was this just no updated at some point?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, a drive-by fix, since we're now using Terser 5.18.2.

# Unmangle previously mangled `import.meta` references in lib*.js.
# See also: `LibraryManager.load` in modules.mjs.
if settings.EXPORT_ES6:
glue = glue.replace('EMSCRIPTEN$IMPORT$META', 'import.meta')
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we cannot do the demangling in the JS compiler (i.e. the same place where we do the mangling?)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good idea. Let me try to move this to the JS compiler, I think that would work.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... that didn't work because the library contents (e.g. libpthread.js where import.meta is used) are streamed to stdout.

emscripten/src/jsifier.mjs

Lines 394 to 401 in 426fb2d

let outputHandle = process.stdout;
if (outputFile) {
outputHandle = await fs.open(outputFile, 'w');
}
async function writeOutput(str) {
await outputHandle.write(str + '\n');
}

So, this is probably the only place where the full file contents is available and where you can a single replace in one go. Added a comment with cf6417c instead.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could run this transform over all of the libraryItems before we call writeOutput?

src/modules.mjs Outdated
// we reverse this replacement.
// See also: `emscript` in emscripten.py.
contents = contents.replace(/\bimport\.meta\b/g, 'EMSCRIPTEN$IMPORT$META');
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need to move from preprocess to here?

Its a little confusing to have this mangling done in two different places.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved back to preprocess with commit 5c2f12b (and also updated to use replaceAll in commit 0b218f2 to avoid regex).

This is an automatic change generated by tools/maint/rebaseline_tests.py.

The following (1) test expectation files were updated by
running the tests with `--rebaseline`:

```
codesize/test_codesize_minimal_esm.json: 2520 => 2493 [-27 bytes / -1.07%]

Average change: -1.07% (-1.07% - -1.07%)
```
# Unmangle previously mangled `import.meta` references in lib*.js.
# See also: `preprocess` in parseTools.mjs.
# Note: this needs to be done here because this is the only stage
# where the complete file contents are available.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But why can't this be done in fix_js_mangling?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants