Skip to content

Commit 694fd91

Browse files
committed
[esm-integration] Fix handling of EM_JS exports
This change also adds a new core test mode for ESM integration and uses this to run all the variants of test_fs_js_api. As part of this I also updated the octal constants in test_fs_js_api.c which are required to be of the new form in strict JS. All code in ES modules is implicitly in strict mode. Split out from emscripten-core#24288 See emscripten-core#24060
1 parent f3d9eb4 commit 694fd91

File tree

7 files changed

+47
-28
lines changed

7 files changed

+47
-28
lines changed

.circleci/config.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,9 @@ jobs:
800800
core0.test_esm_integration*
801801
core0.test_pthread_join_and_asyncify
802802
core0.test_async_ccall_promise_jspi*
803-
core0.test_cubescript_jspi"
803+
core0.test_cubescript_jspi
804+
esm_integration.test_fs_js_api*
805+
"
804806
# Run some basic tests with the minimum version of node that we currently
805807
# support in the generated code.
806808
# Keep this in sync with `OLDEST_SUPPORTED_NODE` in `feature_matrix.py`

src/shell.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
// can continue to use Module afterwards as well.
2323
#if MODULARIZE
2424
#if MODULARIZE == 'instance'
25-
var Module;
25+
var Module = {};
2626
#else
2727
var Module = moduleArg;
2828
#endif

test/fs/test_fs_js_api.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -240,19 +240,19 @@ EM_JS(void, test_fs_close, (), {
240240

241241
void test_fs_mknod() {
242242
EM_ASM(
243-
FS.mknod("mknodtest", 0100000 | 0777 /* S_IFREG | S_RWXU | S_RWXG | S_RWXO */);
243+
FS.mknod("mknodtest", 0o100000 | 0o777 /* S_IFREG | S_RWXU | S_RWXG | S_RWXO */);
244244

245-
FS.create("createtest", 0400 /* S_IRUSR */);
245+
FS.create("createtest", 0o400 /* S_IRUSR */);
246246
);
247247
struct stat s;
248248
stat("mknodtest", &s);
249249

250250
assert(S_ISREG(s.st_mode));
251-
assert(s.st_mode & 0777);
251+
assert(s.st_mode & 0o777);
252252

253253
stat("createtest", &s);
254254
assert(S_ISREG(s.st_mode));
255-
assert(s.st_mode & 0400);
255+
assert(s.st_mode & 0o400);
256256

257257
remove("mknodtest");
258258
remove("createtest");
@@ -382,7 +382,7 @@ void test_fs_mmap() {
382382
void test_fs_mkdirTree() {
383383
EM_ASM(
384384
FS.mkdirTree("/test1/test2/test3"); // Abs path
385-
FS.mkdirTree("/readable", 0400 /* S_IRUSR */);
385+
FS.mkdirTree("/readable", 0o400 /* S_IRUSR */);
386386
);
387387

388388
struct stat s;
@@ -394,7 +394,7 @@ void test_fs_mkdirTree() {
394394
assert(S_ISDIR(s.st_mode));
395395

396396
assert(stat("/readable", &s) == 0);
397-
assert(s.st_mode & 0400 /* S_IRUSR */);
397+
assert(s.st_mode & 0o400 /* S_IRUSR */);
398398

399399
EM_ASM(
400400
var ex;

test/runner.py

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
'wasm64',
7272
'wasm64_v8',
7373
'wasm64_4gb',
74+
'esm_integration',
7475
]
7576

7677
# The default core test mode, used when none is specified

test/test_core.py

+14-6
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,7 @@ def esm_integration(func):
4545

4646
@wraps(func)
4747
def decorated(self, *args, **kwargs):
48-
self.require_node_canary()
49-
self.node_args += ['--experimental-wasm-modules', '--no-warnings']
50-
self.emcc_args += ['-sWASM_ESM_INTEGRATION', '-Wno-experimental']
51-
if self.is_wasm64():
52-
self.skipTest('wasm64 requires wasm export wrappers')
48+
self.setup_esm_integration()
5349
func(self, *args, **kwargs)
5450

5551
return decorated
@@ -349,6 +345,14 @@ def should_use_closure(self):
349345
prohibited = ('-g', '--profiling')
350346
return all(f not in self.emcc_args for f in prohibited) and any(f in self.emcc_args for f in required)
351347

348+
def setup_esm_integration(self):
349+
self.require_node_canary()
350+
self.node_args += ['--experimental-wasm-modules', '--no-warnings']
351+
self.set_setting('WASM_ESM_INTEGRATION')
352+
self.emcc_args += ['-Wno-experimental']
353+
if self.is_wasm64():
354+
self.skipTest('wasm64 requires wasm export wrappers')
355+
352356
# Use closure in some tests for some additional coverage
353357
def maybe_closure(self):
354358
if '--closure=1' not in self.emcc_args and self.should_use_closure():
@@ -9644,11 +9648,13 @@ def test_modularize_instance_embind(self):
96449648

96459649

96469650
# Generate tests for everything
9647-
def make_run(name, emcc_args, settings=None, env=None,
9651+
def make_run(name, emcc_args=None, settings=None, env=None, # noqa
96489652
require_v8=False, v8_args=None,
96499653
require_node=False, node_args=None,
96509654
require_wasm64=False,
96519655
init=None):
9656+
if emcc_args is None:
9657+
emcc_args = {}
96529658
if env is None:
96539659
env = {}
96549660
if settings is None:
@@ -9777,6 +9783,8 @@ def setUp(self):
97779783
bigint = make_run('bigint', emcc_args=['--profiling-funcs'], settings={'WASM_BIGINT': 1},
97789784
init=lambda self: shared.node_bigint_flags(self.get_nodejs()))
97799785

9786+
esm_integration = make_run('esm_integration', init=lambda self: self.setup_esm_integration())
9787+
97809788
# Add DEFAULT_TO_CXX=0
97819789
strict = make_run('strict', emcc_args=[], settings={'STRICT': 1})
97829790
strict_js = make_run('strict_js', emcc_args=[], settings={'STRICT_JS': 1})

test/unistd/access.c

+7-7
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,17 @@ void test_fchmod() {
4242
chmod("fchmodtest", S_IRUGO | S_IWUGO);
4343
struct stat fileStats;
4444
stat("fchmodtest", &fileStats);
45-
int mode = fileStats.st_mode & 0777;
45+
int mode = fileStats.st_mode & 0o777;
4646
// Allow S_IXUGO in addtion to S_IWUGO because on windows
4747
// we always report the execute bit.
4848
assert(mode == (S_IRUGO | S_IWUGO) || mode == (S_IRUGO | S_IWUGO | S_IXUGO));
4949

5050
EM_ASM(
5151
var fchmodstream = FS.open("fchmodtest", "r");
52-
FS.fchmod(fchmodstream.fd, 0777);
52+
FS.fchmod(fchmodstream.fd, 0o777);
5353
);
5454
stat("fchmodtest", &fileStats);
55-
assert((fileStats.st_mode & 0777) == 0777);
55+
assert((fileStats.st_mode & 0o777) == 0o777);
5656
}
5757

5858
void test_lchmod() {
@@ -61,7 +61,7 @@ void test_lchmod() {
6161
// so skip this part of the test.
6262
EM_ASM(
6363
FS.symlink('writeable', 'symlinkfile');
64-
FS.lchmod('symlinkfile', 0777);
64+
FS.lchmod('symlinkfile', 0o777);
6565
);
6666

6767
struct stat symlinkStats;
@@ -80,21 +80,21 @@ void test_chmod_errors() {
8080
EM_ASM(
8181
var ex;
8282
try {
83-
FS.chmod("nonexistent", 0777);
83+
FS.chmod("nonexistent", 0o777);
8484
} catch (err) {
8585
ex = err;
8686
}
8787
assert(ex.name === "ErrnoError" && ex.errno === 44 /* ENOENT */);
8888

8989
try {
90-
FS.fchmod(99, 0777);
90+
FS.fchmod(99, 0o777);
9191
} catch (err) {
9292
ex = err;
9393
}
9494
assert(ex.name === "ErrnoError" && ex.errno === 8 /* EBADF */);
9595

9696
try {
97-
FS.lchmod("nonexistent", 0777);
97+
FS.lchmod("nonexistent", 0o777);
9898
} catch (err) {
9999
ex = err;
100100
}

tools/emscripten.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -755,10 +755,13 @@ def create_em_js(metadata):
755755
arg_names = [arg.split()[-1].replace('*', '') for arg in args if arg]
756756
args = ','.join(arg_names)
757757
func = f'function {name}({args}) {body}'
758+
if settings.WASM_ESM_INTEGRATION:
759+
func = 'export ' + func
760+
em_js_funcs.append(func)
758761
if (settings.MAIN_MODULE or settings.ASYNCIFY == 2) and name in metadata.em_js_func_types:
759762
sig = func_type_to_sig(metadata.em_js_func_types[name])
760-
func = func + f'\n{name}.sig = \'{sig}\';'
761-
em_js_funcs.append(func)
763+
sig = f'{name}.sig = \'{sig}\';'
764+
em_js_funcs.append(sig)
762765

763766
return em_js_funcs
764767

@@ -826,7 +829,10 @@ def create_sending(metadata, library_symbols):
826829

827830
for name in metadata.imports:
828831
if name in metadata.em_js_funcs:
829-
send_items_map[name] = name
832+
# EM_JS functions are exported directly at the declaration site in
833+
# WASM_ESM_INTEGRATION mode.
834+
if not settings.WASM_ESM_INTEGRATION:
835+
send_items_map[name] = name
830836
else:
831837
send_items_map[name] = asmjs_mangle(name)
832838

@@ -881,16 +887,18 @@ def create_sending(metadata, library_symbols):
881887
return '{\n ' + ',\n '.join(elems) + '\n}'
882888

883889

884-
def create_reexports():
890+
def create_reexports(metadata):
885891
assert settings.WASM_ESM_INTEGRATION
886892
exports = '// Re-export imported wasm functions to the JS entry point. These are user-facing and underscore mangled.\n'
887893
wasm_exports = []
888894
for exp in building.user_requested_exports:
889895
if shared.is_c_symbol(exp):
890896
demangled = shared.demangle_c_symbol_name(exp)
891-
if demangled in settings.WASM_EXPORTS:
897+
if demangled in metadata.em_js_funcs:
898+
wasm_exports.append(f'{demangled} as {exp}')
899+
elif demangled in settings.WASM_EXPORTS:
892900
wasm_exports.append(exp)
893-
if demangled == 'main' and '__main_argc_argv' in settings.WASM_EXPORTS:
901+
elif demangled == 'main' and '__main_argc_argv' in settings.WASM_EXPORTS:
894902
wasm_exports.append('_main')
895903
exports += f"export {{ {', '.join(wasm_exports)} }};\n\n"
896904
return exports
@@ -1055,7 +1063,7 @@ def create_module(metadata, function_exports, global_exports, tag_exports,librar
10551063
module.append(create_pointer_conversion_wrappers(metadata))
10561064

10571065
if settings.WASM_ESM_INTEGRATION:
1058-
module.append(create_reexports())
1066+
module.append(create_reexports(metadata))
10591067

10601068
return module
10611069

0 commit comments

Comments
 (0)