-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Add support for -sEXPORT_ES6
/*.mjs
on Node.js
#17915
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -37,10 +37,12 @@ function processMacros(text) { | |||||||||||||||||||||||||||||||||||||||||
function preprocess(text, filenameHint) { | ||||||||||||||||||||||||||||||||||||||||||
if (EXPORT_ES6 && USE_ES6_IMPORT_META) { | ||||||||||||||||||||||||||||||||||||||||||
// `eval`, Terser and Closure don't support module syntax; to allow it, | ||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we try to fix Terser and Closure ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, eventually it would be nice to fix Terser and Closure, but it's a relatively large change. For Terser we need to cherry-pick terser/terser@24ce297 on top of https://github.com/emscripten-core/terser/tree/emscripten_patches_v4.8.0 and Closure needs to run with some additional flags. Lines 603 to 610 in 234940f
Though, I think(?), Lines 215 to 222 in 234940f
Lines 207 to 210 in 234940f
The above changes are not included in this PR, see comment #17915 (comment). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Pretty sure this was the reason I used this hack in the first place btw - it was just easier to support the variety of tooling + There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
👍, I realised that too late, after doing all those Terser and Closure changes. 😅 Anyway, the Closure change, that optimizes the wrapper function when linking with |
||||||||||||||||||||||||||||||||||||||||||
// we need to temporarily replace `import.meta` usages with placeholders | ||||||||||||||||||||||||||||||||||||||||||
// during preprocess phase, and back after all the other ops. | ||||||||||||||||||||||||||||||||||||||||||
// we need to temporarily replace `import.meta` and `await import` usages | ||||||||||||||||||||||||||||||||||||||||||
// with placeholders during preprocess phase, and back after all the other ops. | ||||||||||||||||||||||||||||||||||||||||||
// See also: `phase_final_emitting` in emcc.py. | ||||||||||||||||||||||||||||||||||||||||||
text = text.replace(/\bimport\.meta\b/g, 'EMSCRIPTEN$IMPORT$META'); | ||||||||||||||||||||||||||||||||||||||||||
text = text | ||||||||||||||||||||||||||||||||||||||||||
.replace(/\bimport\.meta\b/g, 'EMSCRIPTEN$IMPORT$META') | ||||||||||||||||||||||||||||||||||||||||||
.replace(/\bawait import\b/g, 'EMSCRIPTEN$AWAIT$IMPORT'); | ||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
const IGNORE = 0; | ||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -238,41 +238,68 @@ def test_emcc_generate_config(self): | |
self.assertContained('LLVM_ROOT', config_contents) | ||
os.remove(config_path) | ||
|
||
def test_emcc_output_mjs(self): | ||
self.run_process([EMCC, '-o', 'hello_world.mjs', test_file('hello_world.c')]) | ||
output = read_file('hello_world.mjs') | ||
self.assertContained('export default Module;', output) | ||
# TODO(sbc): Test that this is actually runnable. We currently don't have | ||
# any tests for EXPORT_ES6 but once we do this should be enabled. | ||
# self.assertContained('hello, world!', self.run_js('hello_world.mjs')) | ||
@parameterized({ | ||
'': ([],), | ||
'node': (['-sENVIRONMENT=node'],), | ||
RReverser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}) | ||
def test_emcc_output_mjs(self, args): | ||
create_file('extern-post.js', 'await Module();') | ||
self.run_process([EMCC, '-o', 'hello_world.mjs', | ||
'--extern-post-js', 'extern-post.js', | ||
test_file('hello_world.c')] + args) | ||
src = read_file('hello_world.mjs') | ||
self.assertContained('export default Module;', src) | ||
self.assertContained('hello, world!', self.run_js('hello_world.mjs')) | ||
|
||
@parameterized({ | ||
'': (True, [],), | ||
'no_import_meta': (False, ['-sUSE_ES6_IMPORT_META=0'],), | ||
'': ([],), | ||
'node': (['-sENVIRONMENT=node'],), | ||
}) | ||
def test_emcc_output_worker_mjs(self, has_import_meta, args): | ||
@node_pthreads | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why pthreads here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test links with |
||
def test_emcc_output_worker_mjs(self, args): | ||
create_file('extern-post.js', 'await Module();') | ||
os.mkdir('subdir') | ||
self.run_process([EMCC, '-o', 'subdir/hello_world.mjs', '-pthread', '-O1', | ||
self.run_process([EMCC, '-o', 'subdir/hello_world.mjs', | ||
'-sEXIT_RUNTIME', '-sPROXY_TO_PTHREAD', '-pthread', '-O1', | ||
'--extern-post-js', 'extern-post.js', | ||
test_file('hello_world.c')] + args) | ||
src = read_file('subdir/hello_world.mjs') | ||
self.assertContainedIf("new URL('hello_world.wasm', import.meta.url)", src, condition=has_import_meta) | ||
self.assertContainedIf("new Worker(new URL('hello_world.worker.js', import.meta.url))", src, condition=has_import_meta) | ||
self.assertContained("new URL('hello_world.wasm', import.meta.url)", src) | ||
self.assertContained("new Worker(new URL('hello_world.worker.js', import.meta.url))", src) | ||
self.assertContained('export default Module;', src) | ||
src = read_file('subdir/hello_world.worker.js') | ||
self.assertContained('import("./hello_world.mjs")', src) | ||
self.assertContained('hello, world!', self.run_js('subdir/hello_world.mjs')) | ||
|
||
@node_pthreads | ||
def test_emcc_output_worker_mjs_single_file(self): | ||
create_file('extern-post.js', 'await Module();') | ||
self.run_process([EMCC, '-o', 'hello_world.mjs', '-pthread', | ||
'--extern-post-js', 'extern-post.js', | ||
test_file('hello_world.c'), '-sSINGLE_FILE']) | ||
src = read_file('hello_world.mjs') | ||
self.assertNotContained("new URL('data:", src) | ||
self.assertContained("new Worker(new URL('hello_world.worker.js', import.meta.url))", src) | ||
self.assertContained('hello, world!', self.run_js('hello_world.mjs')) | ||
|
||
def test_emcc_output_mjs_closure(self): | ||
create_file('extern-post.js', 'await Module();') | ||
self.run_process([EMCC, '-o', 'hello_world.mjs', | ||
'--extern-post-js', 'extern-post.js', | ||
test_file('hello_world.c'), '--closure=1']) | ||
src = read_file('hello_world.mjs') | ||
self.assertContained('new URL("hello_world.wasm", import.meta.url)', src) | ||
self.assertContained('hello, world!', self.run_js('hello_world.mjs')) | ||
|
||
def test_emcc_output_mjs_web_no_import_meta(self): | ||
# Ensure we don't emit import.meta.url at all for: | ||
# ENVIRONMENT=web + EXPORT_ES6 + USE_ES6_IMPORT_META=0 | ||
self.run_process([EMCC, '-o', 'hello_world.mjs', | ||
test_file('hello_world.c'), | ||
'-sENVIRONMENT=web', '-sUSE_ES6_IMPORT_META=0']) | ||
src = read_file('hello_world.mjs') | ||
self.assertNotContained('import.meta.url', src) | ||
self.assertContained('export default Module;', src) | ||
|
||
def test_export_es6_implies_modularize(self): | ||
self.run_process([EMCC, test_file('hello_world.c'), '-sEXPORT_ES6']) | ||
|
@@ -283,6 +310,11 @@ def test_export_es6_requires_modularize(self): | |
err = self.expect_fail([EMCC, test_file('hello_world.c'), '-sEXPORT_ES6', '-sMODULARIZE=0']) | ||
self.assertContained('EXPORT_ES6 requires MODULARIZE to be set', err) | ||
|
||
def test_export_es6_node_requires_import_meta(self): | ||
err = self.expect_fail([EMCC, test_file('hello_world.c'), | ||
'-sENVIRONMENT=node', '-sEXPORT_ES6', '-sUSE_ES6_IMPORT_META=0']) | ||
self.assertContained('EXPORT_ES6 and ENVIRONMENT=*node* requires USE_ES6_IMPORT_META to be set', err) | ||
|
||
def test_export_es6_allows_export_in_post_js(self): | ||
self.run_process([EMCC, test_file('hello_world.c'), '-O3', '-sEXPORT_ES6', '--post-js', test_file('export_module.js')]) | ||
src = read_file('a.out.js') | ||
|
Uh oh!
There was an error while loading. Please reload this page.