Skip to content

Commit d05dbc8

Browse files
authored
[esm-integration] Allow JS library symbols to be exported (#24061)
See #24060
1 parent a392cbb commit d05dbc8

File tree

7 files changed

+39
-6
lines changed

7 files changed

+39
-6
lines changed

src/jsifier.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,13 @@ function(${args}) {
735735
}
736736
contentText = `var ${mangled} = ${snippet};`;
737737
}
738+
739+
if (WASM_ESM_INTEGRATION && (EXPORT_ALL || EXPORTED_FUNCTIONS.has(mangled)) && !isStub) {
740+
// It ESM integration mode we mark JS library symbols are exported at
741+
// the point of declaration.
742+
contentText = 'export ' + contentText;
743+
}
744+
738745
// Relocatable code needs signatures to create proper wrappers.
739746
if (sig && RELOCATABLE) {
740747
if (!WASM_BIGINT) {

src/modules.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,9 @@ function exportLibrarySymbols() {
561561
}
562562

563563
function exportJSSymbols() {
564+
// In WASM_ESM_INTEGRATION mode JS library symbols are marked with `export`
565+
// at the point of declaration.
566+
if (WASM_ESM_INTEGRATION) return '';
564567
return exportRuntimeSymbols() + ' ' + exportLibrarySymbols();
565568
}
566569

test/js_optimizer/JSDCE-output.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ export default function l(a) {
4747
return a + 1;
4848
}
4949

50+
export var m = a => a + 1;
51+
5052
(function() {
5153
var z = fleefl();
5254
var zz = fleefl();

test/js_optimizer/JSDCE.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ export default function l(a) {
4848
return a+1;
4949
}
5050

51+
// ES6 exported var
52+
export var m = (a) => {
53+
return a+1;
54+
}
55+
5156
// inner workings
5257
(function() {
5358
var x;

test/test_core.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9568,10 +9568,11 @@ def test_esm_integration(self):
95689568
# TODO(sbc): WASM_ESM_INTEGRATION doesn't currently work with closure.
95699569
# self.maybe_closure()
95709570
self.node_args += ['--experimental-wasm-modules', '--no-warnings']
9571-
self.run_process([EMCC, '-o', 'hello_world.mjs', '-sWASM_ESM_INTEGRATION', '-Wno-experimental', test_file('hello_world_argv.c')] + self.get_emcc_args())
9571+
self.run_process([EMCC, '-o', 'hello_world.mjs', '-sEXPORTED_FUNCTIONS=_main,stringToNewUTF8', '-sWASM_ESM_INTEGRATION', '-Wno-experimental', test_file('hello_world_argv.c')] + self.get_emcc_args())
95729572
create_file('runner.mjs', '''
9573-
import init from "./hello_world.mjs";
9573+
import init, { stringToNewUTF8, main } from "./hello_world.mjs";
95749574
await init({arguments: ['foo', 'bar']});
9575+
console.log('this is a pointer:', stringToNewUTF8('hello'));
95759576
''')
95769577
self.assertContained('hello, world! (3)', self.run_js('runner.mjs'))
95779578

tools/acorn-optimizer.mjs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,8 +447,16 @@ function JSDCE(ast, aggressive) {
447447
},
448448
ExportNamedDeclaration(node, c) {
449449
if (node.declaration) {
450-
const name = node.declaration.id.name;
451-
ensureData(scopes[scopes.length - 1], name).use = 1;
450+
if (node.declaration.type == 'FunctionDeclaration') {
451+
const name = node.declaration.id.name;
452+
ensureData(scopes[scopes.length - 1], name).use = 1;
453+
} else {
454+
assert(node.declaration.type == 'VariableDeclaration');
455+
for (const decl of node.declaration.declarations) {
456+
const name = decl.id.name;
457+
ensureData(scopes[scopes.length - 1], name).use = 1;
458+
}
459+
}
452460
c(node.declaration);
453461
} else {
454462
for (const specifier of node.specifiers) {

tools/link.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2114,12 +2114,16 @@ def create_worker_file(input_file, target_dir, output_file, options):
21142114

21152115
def create_esm_wrapper(wrapper_file, support_target, wasm_target):
21162116
wasm_exports = []
2117+
js_exports = []
21172118
for f in settings.USER_EXPORTS:
21182119
if f == '_main' and '__main_argc_argv' in settings.WASM_EXPORTS:
21192120
wasm_exports.append('__main_argc_argv as main')
2120-
else:
2121+
elif f in settings.WASM_EXPORTS:
21212122
wasm_exports.append(shared.demangle_c_symbol_name(f))
2123+
else:
2124+
js_exports.append(f)
21222125
wasm_exports = ', '.join(wasm_exports)
2126+
js_exports = ', '.join(js_exports)
21232127

21242128
wrapper = []
21252129
if wasm_exports:
@@ -2132,7 +2136,10 @@ def create_esm_wrapper(wrapper_file, support_target, wasm_target):
21322136
wrapper.append('// in order to avoid issues with circullr dependencies.')
21332137
wrapper.append(f"import * as unused from './{settings.WASM_BINARY_FILE}';")
21342138
support_url = f'./{os.path.basename(support_target)}'
2135-
wrapper.append(f"export {{ default }} from '{support_url}';")
2139+
if js_exports:
2140+
wrapper.append(f"export {{ default, {js_exports} }} from '{support_url}';")
2141+
else:
2142+
wrapper.append(f"export {{ default }} from '{support_url}';")
21362143
write_file(wrapper_file, '\n'.join(wrapper) + '\n')
21372144

21382145
# FIXME(sbc): This is a huge hack to rename the imports in the

0 commit comments

Comments
 (0)