Skip to content

Commit ec4927c

Browse files
committed
Support source-phase imports in the acorn/terser optimizer pipeline
When -sSOURCE_PHASE_IMPORTS=1, emcc emits ```js import source wasmModule from './foo.wasm'; ``` in its JS runtime. At -O2/-O3/-Os/-Oz the emitted JS is run through tools/acorn-optimizer.mjs which currently fails with a SyntaxError at parse time because acorn 8.x does not yet understand the source-phase imports proposal (https://github.com/tc39/proposal-source-phase-imports). Wire in the acorn-import-phases plugin so acorn can parse the syntax, and pull in the matching terser support (downstream of emscripten-core/terser#1) so the round-trip through from_mozilla_ast / to_mozilla_ast preserves the `phase` keyword on the way back out. Without the terser side, terser would silently drop the keyword and the host would return the module's exports namespace instead of a WebAssembly.Module, changing runtime semantics. * package.json: add acorn-import-phases dependency. * tools/acorn-optimizer.mjs: extend acorn with the plugin and use the extended parser at the parse site. * third_party/terser/terser.js: rebuilt from the emscripten-core/terser branch with source-phase imports support (PR emscripten-core/terser#1, the v5.18.2 downstream port of upstream terser PR terser/terser#1682). * test/js_optimizer/sourcePhaseImports{,-output}.js: new fixture that feeds two `import source` declarations through the JSDCE pass and checks the keyword survives. * test/test_other.py: register the fixture in test_js_optimizer, and parametrize test_esm_source_phase_imports across no-args and -O2 to exercise the optimizer pipeline.
1 parent 85ee810 commit ec4927c

8 files changed

Lines changed: 175 additions & 36 deletions

File tree

package-lock.json

Lines changed: 5 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
},
1919
"dependencies": {
2020
"acorn": "^8.15.0",
21+
"acorn-import-phases": "^1.0.4",
2122
"google-closure-compiler": "20260429.0.0",
2223
"html-minifier-terser": "7.2.0"
2324
},
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import source wasmModule from "./foo.wasm";
2+
3+
import source otherModule from "./bar.wasm";
4+
5+
function use() {
6+
return [ wasmModule, otherModule ];
7+
}
8+
9+
use();
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Source-phase imports (https://github.com/tc39/proposal-source-phase-imports).
2+
// The acorn optimizer must parse these via the acorn-import-phases plugin and
3+
// preserve the `source` phase keyword through the terser from_mozilla_ast ->
4+
// print round-trip used at -O2+.
5+
import source wasmModule from './foo.wasm';
6+
import source otherModule from './bar.wasm';
7+
8+
function use() {
9+
return [wasmModule, otherModule];
10+
}
11+
use();

test/test_other.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,11 +421,15 @@ def test_esm(self, args):
421421
self.assertContained('Hello, world!', self.run_js('hello_world.mjs'))
422422

423423
@requires_node_25
424-
def test_esm_source_phase_imports(self):
424+
@parameterized({
425+
'': ([],),
426+
'O3': (['-O3'],),
427+
})
428+
def test_esm_source_phase_imports(self, args):
425429
self.node_args += ['--experimental-wasm-modules', '--no-warnings']
426430
self.run_process([EMCC, '-o', 'hello_world.mjs', '-sSOURCE_PHASE_IMPORTS',
427431
'--extern-post-js', test_file('modularize_post_js.js'),
428-
test_file('hello_world.c')])
432+
test_file('hello_world.c')] + args)
429433
self.assertContained('import source wasmModule from', read_file('hello_world.mjs'))
430434
self.assertContained('Hello, world!', self.run_js('hello_world.mjs'))
431435

@@ -3012,6 +3016,7 @@ def test_extern_prepost(self):
30123016
'minifyGlobals': (['minifyGlobals'],),
30133017
'minifyLocals': (['minifyLocals'],),
30143018
'JSDCE': (['JSDCE', '--export-es6'],),
3019+
'sourcePhaseImports': (['JSDCE', '--export-es6'],),
30153020
'JSDCE-hasOwnProperty': (['JSDCE'],),
30163021
'JSDCE-defaultArg': (['JSDCE'],),
30173022
'JSDCE-fors': (['JSDCE'],),

third_party/terser/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ version published in npm.
77
This `terser.js` bundle in this directory was built from our fork of terser
88
which lives at: https://github.com/emscripten-core/terser/
99

10-
The current patches are stored in the `emscripten_patches_v4.8.0` branch.
10+
The current patches are stored in the `emscripten_patches_v5.18.2` branch.
1111

1212
To make changes to this code please submit patches to
1313
https://github.com/emscripten-core/terser/ and then re-create this bundle

0 commit comments

Comments
 (0)