Skip to content
Open
Show file tree
Hide file tree
Changes from all 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: 4 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ See docs/process.md for more on how version tagging works.
in the next release. (#27261)
- The default value for `GROWABLE_ARRAYBUFFERS` was reverted to `0` since we
found issues with Web API compatibility. (#27260)
- Fixed `-sWASM_ESM_INTEGRATION` builds at `-O2` and above, which previously
failed in the JS optimizer's metadce (dead code elimination) pass. metadce now
understands the native ES import/export wasm boundary that this mode emits.
(#27217)

6.0.2 - 07/01/26
----------------
Expand Down
29 changes: 29 additions & 0 deletions test/codesize/test_codesize_hello_esm_integration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"a.out.mjs": 671,
"a.out.mjs.gz": 401,
"a.out.support.mjs": 6397,
"a.out.support.mjs.gz": 2473,
"a.out.nodebug.wasm": 1688,
"a.out.nodebug.wasm.gz": 973,
"total": 8756,
"total_gz": 3847,
"sent": [
"a (fd_write)"
],
"imports": [
"a (fd_write)"
],
"exports": [
"b (memory)",
"c (__wasm_call_ctors)",
"d (main)"
],
"funcs": [
"$__emscripten_stdout_close",
"$__emscripten_stdout_seek",
"$__stdio_write",
"$__towrite",
"$__wasm_call_ctors",
"$main"
]
}
22 changes: 22 additions & 0 deletions test/codesize/test_codesize_minimal_esm_integration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"a.out.mjs": 683,
"a.out.mjs.gz": 410,
"a.out.support.mjs": 3343,
"a.out.support.mjs.gz": 1350,
"a.out.nodebug.wasm": 75,
"a.out.nodebug.wasm.gz": 87,
"total": 4101,
"total_gz": 1847,
"sent": [],
"imports": [],
"exports": [
"a (memory)",
"b (__wasm_call_ctors)",
"c (add)",
"d (global_val)"
],
"funcs": [
"$__wasm_call_ctors",
"$add"
]
}
15 changes: 15 additions & 0 deletions test/js_optimizer/applyDCEGraphRemovals-esm-output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
function fd_write_impl() {}

function fd_close_impl() {}

function unused_import_impl() {}

import { memory, main as _main, used_export as _used_export, memory as wasmMemory } from "./a.out.wasm";

export { fd_write_impl as fd_write, fd_close_impl as fd_close };

export { _main };

var HEAP32;

export { HEAP32 };
34 changes: 34 additions & 0 deletions test/js_optimizer/applyDCEGraphRemovals-esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// WASM_ESM_INTEGRATION: unused wasm imports are dropped from the `export {..}`
// that sends JS functions to the wasm, and unused wasm exports (including
// internal ones like the indirect function table) from the `import {..}` that
// receives them, keeping the two ES module interfaces in sync.

function fd_write_impl() {
}
function fd_close_impl() {
}
function unused_import_impl() {
}

import {
memory,
__indirect_function_table,
main as _main,
used_export as _used_export,
unused_export as _unused_export,
memory as wasmMemory,
} from './a.out.wasm';

export {
fd_write_impl as fd_write,
fd_close_impl as fd_close,
unused_import_impl as unused_import,
};

export { _main };

// MODULARIZE=instance runtime exports (bare form) must be left untouched.
var HEAP32;
export { HEAP32 };

// EXTRA_INFO: { "unusedImports": ["unused_import"], "unusedExports": ["unused_export", "__indirect_function_table"] }
13 changes: 13 additions & 0 deletions test/js_optimizer/applyImportAndExportNameChanges-esm-output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function fd_write_impl() {}

function fd_close_impl() {}

import { memory, b as _main, c as _malloc, memory as wasmMemory } from "./a.out.wasm";

export { fd_write_impl as d, fd_close_impl as e };

export { _main };

var HEAP32;

export { HEAP32 };
30 changes: 30 additions & 0 deletions test/js_optimizer/applyImportAndExportNameChanges-esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// WASM_ESM_INTEGRATION: minified wasm import/export names are applied to the
// native ES import/export specifiers. Only the wasm-facing name of each
// specifier is renamed; the JS-local binding name is left intact (including the
// unaliased `memory`, whose local side must survive).

function fd_write_impl() {
}
function fd_close_impl() {
}

import {
memory,
main as _main,
malloc as _malloc,
memory as wasmMemory,
} from './a.out.wasm';

export {
fd_write_impl as fd_write,
fd_close_impl as fd_close,
};

// Re-export of a wasm export: the local name (_main) is never in the mapping.
export { _main };

// MODULARIZE=instance runtime export (bare form): never in the mapping.
var HEAP32;
export { HEAP32 };

// EXTRA_INFO: { "mapping": { "main": "b", "malloc": "c", "fd_write": "d", "fd_close": "e" } }
78 changes: 78 additions & 0 deletions test/js_optimizer/emitDCEGraph-esm-output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
[
{
"name": "emcc$defun$fd_close_impl",
"reaches": [
"emcc$defun$helper"
]
},
{
"name": "emcc$defun$fd_write_impl",
"reaches": []
},
{
"name": "emcc$defun$helper",
"reaches": []
},
{
"name": "emcc$defun$unused_import_impl",
"reaches": []
},
{
"name": "emcc$export$__indirect_function_table",
"export": "__indirect_function_table",
"reaches": []
},
{
"name": "emcc$export$_main",
"export": "main",
"reaches": [],
"root": true
},
{
"name": "emcc$export$_unused_export",
"export": "unused_export",
"reaches": []
},
{
"name": "emcc$export$_used_export",
"export": "used_export",
"reaches": [],
"root": true
},
{
"name": "emcc$export$memory",
"export": "memory",
"reaches": [],
"root": true
},
{
"name": "emcc$import$fd_close_impl",
"import": [
"env",
"fd_close"
],
"reaches": [
"emcc$defun$fd_close_impl"
]
},
{
"name": "emcc$import$fd_write_impl",
"import": [
"env",
"fd_write"
],
"reaches": [
"emcc$defun$fd_write_impl"
]
},
{
"name": "emcc$import$unused_import_impl",
"import": [
"env",
"unused_import"
],
"reaches": [
"emcc$defun$unused_import_impl"
]
}
]
49 changes: 49 additions & 0 deletions test/js_optimizer/emitDCEGraph-esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// WASM_ESM_INTEGRATION: the wasm<->JS boundary is expressed with native ES
// import/export syntax rather than the `wasmImports` object and
// `wasmExports['x']` member uses, and emitDCEGraph must build the same graph
// from it.

// JS functions implementing wasm imports.
function fd_write_impl() {
}
function unused_import_impl() {
}

// A JS function only reachable from a wasm import edge.
function helper() {
}
function fd_close_impl() {
helper();
}

// wasm exports received as ES imports. `memory` is imported twice (plain and
// aliased) and must map to a single export node.
import {
memory,
__indirect_function_table,
main as _main,
used_export as _used_export,
unused_export as _unused_export,
memory as wasmMemory,
} from './a.out.wasm';

// JS functions exported to the wasm module (the wasm imports).
export {
fd_write_impl as fd_write,
fd_close_impl as fd_close,
unused_import_impl as unused_import,
};

// Re-export of a wasm export to the JS entry point: a top-level use that should
// root the underlying `main` export, not be treated as a wasm import.
export { _main };

// MODULARIZE=instance runtime exports. These are plain JS bindings, not wasm
// import edges, and must be left untouched (bare `export {..}` form).
var HEAP32;
var baz = () => {};
export { HEAP32, baz };

// Top-level uses: root the memory export (via the alias) and one wasm export.
wasmMemory.buffer;
_used_export();
38 changes: 38 additions & 0 deletions test/js_optimizer/emitDCEGraph-sourcePhaseImports-output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[
{
"name": "emcc$defun$fd_write_impl",
"reaches": []
},
{
"name": "emcc$export$_main",
"export": "main",
"reaches": [],
"root": true
},
{
"name": "emcc$export$_unused_export",
"export": "unused_export",
"reaches": []
},
{
"name": "emcc$export$_used_export",
"export": "used_export",
"reaches": [],
"root": true
},
{
"name": "emcc$export$memory",
"export": "memory",
"reaches": []
},
{
"name": "emcc$import$fd_write_impl",
"import": [
"env",
"fd_write"
],
"reaches": [
"emcc$defun$fd_write_impl"
]
}
]
29 changes: 29 additions & 0 deletions test/js_optimizer/emitDCEGraph-sourcePhaseImports.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SOURCE_PHASE_IMPORTS combined with WASM_ESM_INTEGRATION: the glue emits a
// source-phase import for the wasm module alongside the value-phase import that
// binds the wasm exports. emitDCEGraph must skip the source-phase import
// (its specifier has no `imported`) and only treat the value-phase `.wasm`
// import as wasm export bindings.

// Source-phase import of the wasm module itself. This is NOT a wasm export
// binding and must be ignored by the DCE graph builder.
import source wasmModule from './a.out.wasm';

function fd_write_impl() {
}

// wasm exports received as ES imports (value-phase).
import {
memory,
main as _main,
used_export as _used_export,
unused_export as _unused_export,
} from './a.out.wasm';

export {
fd_write_impl as fd_write,
};

export { _main };

WebAssembly.instantiate(wasmModule);
_used_export();
Loading