Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions src/closure-externs/closure-externs.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@
* The closure_compiler() method in tools/shared.py refers to this file when calling closure.
*/

// Special placeholder for `await import` and `await`.
var EMSCRIPTEN$AWAIT$IMPORT;
var EMSCRIPTEN$AWAIT;

// Don't minify createRequire
var createRequire;

Expand Down
4 changes: 4 additions & 0 deletions src/closure-externs/modularize-externs.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ var moduleArg;
* @suppress {duplicate, undefinedVars}
*/
var Module;

// Special placeholder for `await import` and `await`.
var EMSCRIPTEN$AWAIT$IMPORT;
var EMSCRIPTEN$AWAIT;
7 changes: 6 additions & 1 deletion src/parseTools.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ function mangleUnsupportedSyntax(text) {
// See also: `fix_js_mangling` in link.py.
// FIXME: Remove after https://github.com/google/closure-compiler/issues/3835 is fixed.
if (EXPORT_ES6) {
text = text.replaceAll('await import', 'EMSCRIPTEN$AWAIT$IMPORT');
// We must use a low-priority pattern (`void 0 ||`) instead of a normal function name.
// Closure treats a normal name like a function call, so it thinks parentheses around it
// are useless and removes them (e.g. turning `(PLACEHOLDER).y` into `PLACEHOLDER.y`).
// When we swap `await` back in, `await x.y` runs in the wrong order. The `void 0 ||` trick
// forces Closure to keep the parentheses safely intact.
text = text.replaceAll('await import', 'void 0||EMSCRIPTEN$AWAIT$IMPORT');
}
text = text.replaceAll('await createWasm()', 'EMSCRIPTEN$AWAIT(createWasm())');
text = text.replaceAll('await run()', 'EMSCRIPTEN$AWAIT(run())');
Expand Down
10 changes: 10 additions & 0 deletions test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,16 @@ def test_esm_worker_single_file(self):
self.assertContained("new Worker(new URL('hello_world.mjs', import.meta.url), {", src)
self.assertContained('Hello, world!', self.run_js('hello_world.mjs'))

def test_esm_worker_closure(self):

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.

test_esm_pthread_closure?

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.

This is an extend of test_esm_worker, just like test_esm_worker_single_file.

self.run_process([EMCC, '-o', 'hello_world.mjs',
'-sEXIT_RUNTIME', '-sPROXY_TO_PTHREAD', '-pthread', '-O2',
test_file('hello_world.c'), '--closure=1'])
create_file('run.mjs', '''
import Module from './hello_world.mjs';
await Module();
''')
self.assertContained('Hello, world!', self.run_js('run.mjs'))

def test_esm_closure(self):
self.run_process([EMCC, '-o', 'hello_world.mjs',
'--extern-post-js', test_file('modularize_post_js.js'),
Expand Down
1 change: 1 addition & 0 deletions tools/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -2126,6 +2126,7 @@ def fix_js_mangling(js_file):
# https://github.com/google/closure-compiler/blob/v20260401/src/com/google/javascript/jscomp/ConvertChunksToESModules.java#L111-L113
src = src \
.replace('EMSCRIPTEN$AWAIT$IMPORT', 'await import') \
.replace('void 0||await import', 'await import') \

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 do this in two steps like 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.

Without this, it still emits:

isPthread=(void 0||await import("node:worker_threads")).workerData==="em-pthread";

The reason this is done in two steps is that Closure optimizes away the other void 0 || patterns.

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 wroth a comment here. I'm still a little confused by 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.

Added a comment with 8fb7c06.

.replace('export{};\n', '')

src = src.replace('EMSCRIPTEN$AWAIT(', 'await (')
Expand Down
Loading