diff --git a/src/polyfill/atob.js b/src/polyfill/atob.js index 5de121d14a13f..4626cb72a1f1f 100644 --- a/src/polyfill/atob.js +++ b/src/polyfill/atob.js @@ -14,6 +14,7 @@ if (typeof atob == 'undefined') { if (typeof global != 'undefined' && typeof globalThis == 'undefined') { + /** @suppress{checkTypes} */ globalThis = global; } diff --git a/test/common.py b/test/common.py index 8ff05424e146f..7f5844adac982 100644 --- a/test/common.py +++ b/test/common.py @@ -379,8 +379,9 @@ def metafunc(self, wasmfs, *args, **kwargs): if DEBUG: print('parameterize:wasmfs=%d' % wasmfs) if wasmfs: - self.set_setting('WASMFS') - self.emcc_args.append('-DWASMFS') + self.setup_wasmfs_test() + else: + self.emcc_args += ['-DMEMFS'] f(self, *args, **kwargs) parameterize(metafunc, {'': (False,), @@ -388,6 +389,68 @@ def metafunc(self, wasmfs, *args, **kwargs): return metafunc +def also_with_nodefs(func): + @wraps(func) + def metafunc(self, fs, *args, **kwargs): + if DEBUG: + print('parameterize:fs=%s' % (fs)) + if fs == 'nodefs': + self.setup_nodefs_test() + else: + self.emcc_args += ['-DMEMFS'] + assert fs is None + func(self, *args, **kwargs) + + parameterize(metafunc, {'': (None,), + 'nodefs': ('nodefs',)}) + return metafunc + + +def also_with_nodefs_both(func): + @wraps(func) + def metafunc(self, fs, *args, **kwargs): + if DEBUG: + print('parameterize:fs=%s' % (fs)) + if fs == 'nodefs': + self.setup_nodefs_test() + elif fs == 'rawfs': + self.setup_noderawfs_test() + else: + self.emcc_args += ['-DMEMFS'] + assert fs is None + func(self, *args, **kwargs) + + parameterize(metafunc, {'': (None,), + 'nodefs': ('nodefs',), + 'rawfs': ('rawfs',)}) + return metafunc + + +def with_all_fs(func): + @wraps(func) + def metafunc(self, fs, *args, **kwargs): + if DEBUG: + print('parameterize:fs=%s' % (fs)) + if fs == 'nodefs': + self.setup_nodefs_test() + elif fs == 'rawfs': + self.setup_noderawfs_test() + elif fs == 'wasmfs': + self.setup_wasmfs_test() + else: + self.emcc_args += ['-DMEMFS'] + assert fs is None + func(self, *args, **kwargs) + + # TODO(sbc): rather than treat WASMFS as orthogonal we should + # probably make it combinatorial with nodefs and noderawfs. + parameterize(metafunc, {'': (None,), + 'nodefs': ('nodefs',), + 'rawfs': ('rawfs',), + 'wasmfs': ('wasmfs',)}) + return metafunc + + def also_with_noderawfs(func): assert callable(func) @@ -396,9 +459,9 @@ def metafunc(self, rawfs, *args, **kwargs): if DEBUG: print('parameterize:rawfs=%d' % rawfs) if rawfs: - self.require_node() - self.emcc_args += ['-DNODERAWFS'] - self.set_setting('NODERAWFS') + self.setup_noderawfs_test() + else: + self.emcc_args += ['-DMEMFS'] func(self, *args, **kwargs) parameterize(metafunc, {'': (False,), @@ -1025,7 +1088,19 @@ def require_wasm2js(self): def setup_nodefs_test(self): self.require_node() - self.emcc_args += ['-lnodefs.js', '--pre-js', test_file('setup_nodefs.js')] + if self.get_setting('WASMFS'): + # without this the JS setup code in setup_nodefs.js doesn't work + self.set_setting('FORCE_FILESYSTEM') + self.emcc_args += ['-DNODEFS', '-lnodefs.js', '--pre-js', test_file('setup_nodefs.js')] + + def setup_noderawfs_test(self): + self.require_node() + self.emcc_args += ['-DNODERAWFS'] + self.set_setting('NODERAWFS') + + def setup_wasmfs_test(self): + self.set_setting('WASMFS') + self.emcc_args += ['-DWASMFS'] def setup_node_pthreads(self): self.require_node() diff --git a/test/test_core.py b/test/test_core.py index 930bbda052810..a60f946740009 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -27,7 +27,7 @@ from common import env_modify, with_env_modify, disabled, flaky, node_pthreads, also_with_wasm_bigint from common import read_file, read_binary, requires_v8, requires_node, requires_wasm2js, requires_node_canary from common import compiler_for, crossplatform, no_4gb, no_2gb, also_with_minimal_runtime -from common import also_with_noderawfs, also_with_wasmfs +from common import with_all_fs, also_with_nodefs, also_with_nodefs_both, also_with_noderawfs, also_with_wasmfs from common import with_all_eh_sjlj, with_all_sjlj, also_with_standalone_wasm, can_do_standalone, no_wasm64, requires_wasm_exnref from common import NON_ZERO, WEBIDL_BINDER, EMBUILDER, PYTHON import clang_native @@ -5389,15 +5389,9 @@ def test_proc_self_fd(self): def test_fwrite_0(self): self.do_core_test('test_fwrite_0.c') - @parameterized({ - '': (['MEMFS']), - 'nodefs': (['NODEFS']) - }) - def test_fgetc_ungetc(self, fs): + @also_with_nodefs_both + def test_fgetc_ungetc(self): print('TODO: update this test once the musl ungetc-on-EOF-stream bug is fixed upstream and reaches us') - self.emcc_args += ['-D' + fs] - if fs == 'NODEFS': - self.setup_nodefs_test() self.do_runf('stdio/test_fgetc_ungetc.c', 'success') def test_fgetc_unsigned(self): @@ -5770,21 +5764,11 @@ def test_fs_enotdir(self): def test_fs_append(self): self.do_runf('fs/test_append.c', 'success') - @parameterized({ - '': ['MEMFS'], - 'nodefs': ['NODEFS'], - 'noderaswfs': ['NODERAWFS'], - 'wasmfs': ['WASMFS'] - }) - def test_fs_mmap(self, fs): - if fs == 'NODEFS': - self.setup_nodefs_test() - if fs == 'NODERAWFS': - self.require_node() - self.emcc_args += ['-lnodefs.js', '-lnoderawfs.js'] - if fs == 'WASMFS': - self.emcc_args += ['-sWASMFS', '-sFORCE_FILESYSTEM'] - self.do_run_in_out_file_test('fs/test_mmap.c', emcc_args=['-D' + fs]) + @with_all_fs + def test_fs_mmap(self): + if self.get_setting('WASMFS'): + self.set_setting('FORCE_FILESYSTEM') + self.do_run_in_out_file_test('fs/test_mmap.c') @no_wasmfs('wasmfs will (?) need a non-JS mechanism to ignore permissions during startup') @parameterized({ @@ -5856,34 +5840,23 @@ def test_fs_64bit(self): @requires_node @crossplatform - @parameterized({ - '': ([],), - 'nodefs': (['-DNODEFS', '-lnodefs.js'],), - 'noderawfs': (['-sNODERAWFS'],), - }) - def test_fs_symlink_resolution(self, args): - nodefs = '-DNODEFS' in args or '-sNODERAWFS' in args - if nodefs and WINDOWS: - self.skipTest('No symlinks on Windows') + @with_all_fs + def test_fs_symlink_resolution(self): + nodefs = '-DNODEFS' in self.emcc_args or '-DNODERAWFS' in self.emcc_args if self.get_setting('WASMFS'): - if nodefs: - self.skipTest('NODEFS in WasmFS') self.set_setting('FORCE_FILESYSTEM') - if '-DNODEFS' in args: - self.setup_nodefs_test() - self.do_runf('fs/test_fs_symlink_resolution.c', 'success', emcc_args=args) + if nodefs: + if WINDOWS: + self.skipTest('No symlinks on Windows') + if self.get_setting('WASMFS'): + self.skipTest('NODEFS in WasmFS') + self.do_runf('fs/test_fs_symlink_resolution.c', 'success') - @parameterized({ - '': ([],), - 'nodefs': (['-DNODEFS', '-lnodefs.js'],), - 'noderawfs': (['-sNODERAWFS'],) - }) - def test_fs_rename_on_existing(self, args): + @with_all_fs + def test_fs_rename_on_existing(self): if self.get_setting('WASMFS'): self.set_setting('FORCE_FILESYSTEM') - if '-DNODEFS' in args: - self.setup_nodefs_test() - self.do_runf('fs/test_fs_rename_on_existing.c', 'success', emcc_args=args) + self.do_runf('fs/test_fs_rename_on_existing.c', 'success') def test_sigalrm(self): self.do_runf('test_sigalrm.c', 'Received alarm!') @@ -5908,29 +5881,21 @@ def test_sigaction_default(self, signal, exit_code, assert_identical): assert_returncode=exit_code ) - @requires_node @crossplatform - @parameterized({ - '': (['-DMEMFS'],), - 'nodefs': (['-DNODEFS', '-lnodefs.js'],), - 'noderawfs': (['-DNODERAWFS', '-sNODERAWFS'],) - }) - def test_unistd_access(self, args): - self.emcc_args += args - nodefs = '-DNODEFS' in args or '-DNODERAWFS' in args + @also_with_nodefs_both + def test_unistd_access(self): + nodefs = '-DNODEFS' in self.emcc_args or '-DNODERAWFS' in self.emcc_args if self.get_setting('WASMFS'): + self.set_setting('FORCE_FILESYSTEM') if nodefs: self.skipTest('NODEFS in WasmFS') - self.emcc_args += ['-sFORCE_FILESYSTEM'] - if '-DNODEFS' in args: - self.setup_nodefs_test() # On windows we have slighly different output because we the same # level of permissions are not available. For example, on windows # its not possible have a file that is not readable, but writable. # We also report all files as executable since there is no x bit # recorded there. # See https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/chmod-wchmod?view=msvc-170#remarks - if WINDOWS and '-DNODERAWFS' in args: + if WINDOWS and '-DNODERAWFS' in self.emcc_args: out_suffix = '.win' else: out_suffix = '' @@ -5956,27 +5921,15 @@ def test_unistd_pipe(self): def test_unistd_dup(self): self.do_run_in_out_file_test('unistd/dup.c') - @parameterized({ - '': (['MEMFS']), - 'nodefs': (['NODEFS']) - }) - def test_unistd_truncate(self, fs): - orig_compiler_opts = self.emcc_args.copy() - self.emcc_args = orig_compiler_opts + ['-D' + fs] + @with_all_fs + def test_unistd_truncate(self): + nodefs = '-DNODEFS' in self.emcc_args or '-DNODERAWFS' in self.emcc_args if self.get_setting('WASMFS'): - if fs == 'NODEFS': + self.set_setting('FORCE_FILESYSTEM') + if nodefs: self.skipTest('TODO: NODEFS in WasmFS') - self.emcc_args += ['-sFORCE_FILESYSTEM'] - if fs == 'NODEFS': - self.setup_nodefs_test() - self.do_run_in_out_file_test('unistd/truncate.c') - - @no_windows("Windows throws EPERM rather than EACCES or EINVAL") - @unittest.skipIf(WINDOWS or os.geteuid() == 0, "Root access invalidates this test by being able to write on readonly files") - @requires_node - def test_unistd_truncate_noderawfs(self): - self.set_setting('NODERAWFS') - self.maybe_closure() + if WINDOWS or os.geteuid() == 0: + self.skipTest('Root access invalidates this test by being able to write on readonly files') self.do_run_in_out_file_test('unistd/truncate.c') @also_with_standalone_wasm() @@ -6004,22 +5957,15 @@ def test_unistd_sysconf_phys_pages(self): self.do_runf(filename, str(expected) + ', errno: 0') @no_windows('https://github.com/emscripten-core/emscripten/issues/8882') - @parameterized({ - '': (['MEMFS']), - 'nodefs': (['NODEFS']), - 'noderawfs': (['NODERAWFS']), - }) - def test_unistd_unlink(self, fs): - if fs in ('NODEFS', 'NODERAWFS'): - self.require_node() - if self.get_setting('WASMFS'): - self.skipTest('NODEFS in WasmFS') + @with_all_fs + def test_unistd_unlink(self): + nodefs = '-DNODEFS' in self.emcc_args or '-DNODERAWFS' in self.emcc_args + if self.get_setting('WASMFS') and nodefs: + self.skipTest('NODEFS in WasmFS') - self.emcc_args += ['-D' + fs] # symlinks on node.js on non-linux behave differently (e.g. on Windows they require administrative privileges) # so skip testing those bits on that combination. - if fs == 'NODEFS': - self.emcc_args += ['-lnodefs.js'] + if '-DNODEFS' in self.emcc_args: if WINDOWS: self.emcc_args += ['-DNO_SYMLINK=1'] if MACOS: @@ -6027,35 +5973,27 @@ def test_unistd_unlink(self, fs): # Several differences/bugs on non-linux including https://github.com/nodejs/node/issues/18014 # TODO: NODERAWFS in WasmFS - if fs == 'NODERAWFS': - self.set_setting('NODERAWFS') + if '-DNODERAWFS' in self.emcc_args and os.geteuid() == 0: # 0 if root user - if os.geteuid() == 0: - self.emcc_args += ['-DSKIP_ACCESS_TESTS'] - if fs == 'NODEFS': - self.setup_nodefs_test() + self.emcc_args += ['-DSKIP_ACCESS_TESTS'] self.do_runf('unistd/unlink.c', 'success') - @parameterized({ - '': ([], False), - 'nodefs': (['-DNODEFS', '-lnodefs.js'], True) - }) - def test_unistd_links(self, args, nodefs): - if nodefs: - self.require_node() - if WINDOWS: - self.skipTest('Skipping NODEFS part of this test for test_unistd_links on Windows, since it would require administrative privileges.') - # Also, other detected discrepancies if you do end up running this test on NODEFS: - # test expects /, but Windows gives \ as path slashes. - # Calling readlink() on a non-link gives error 22 EINVAL on Unix, but simply error 0 OK on Windows. + @also_with_nodefs + def test_unistd_links(self): + nodefs = '-DNODEFS' in self.emcc_args + if nodefs and WINDOWS: + self.skipTest('Skipping NODEFS part of this test for test_unistd_links on Windows, since it would require administrative privileges.') + # Also, other detected discrepancies if you do end up running this test on NODEFS: + # test expects /, but Windows gives \ as path slashes. + # Calling readlink() on a non-link gives error 22 EINVAL on Unix, but simply error 0 OK on Windows. if self.get_setting('WASMFS'): if nodefs: self.skipTest('TODO: wasmfs+node') self.emcc_args += ['-sFORCE_FILESYSTEM'] - self.do_run_in_out_file_test('unistd/links.c', emcc_args=args) + self.do_run_in_out_file_test('unistd/links.c') @also_with_noderawfs def test_unistd_write_broken_link(self): @@ -6071,30 +6009,17 @@ def test_unistd_symlink_on_nodefs(self): self.do_run_in_out_file_test('unistd/symlink_on_nodefs.c') @also_with_wasm_bigint + @also_with_nodefs def test_unistd_io(self): - orig_compiler_opts = self.emcc_args.copy() - for fs in ('MEMFS', 'NODEFS'): - self.clear() - self.emcc_args = orig_compiler_opts + ['-D' + fs] - if fs == 'NODEFS': - self.emcc_args += ['-lnodefs.js'] - self.require_node() - if self.get_setting('WASMFS'): - if fs == 'NODEFS': - # TODO: NODEFS in WasmFS - continue - self.emcc_args += ['-sFORCE_FILESYSTEM'] - self.do_run_in_out_file_test('unistd/io.c') + if self.get_setting('WASMFS'): + if '-DNODEFS' in self.emcc_args: + self.skipTest('NODEFS in WasmFS') + self.set_setting('FORCE_FILESYSTEM') + self.do_run_in_out_file_test('unistd/io.c') @no_windows('https://github.com/emscripten-core/emscripten/issues/8882') - @parameterized({ - '': (['MEMFS']), - 'nodefs': (['NODEFS']), - }) - def test_unistd_misc(self, fs): - self.emcc_args += ['-D' + fs] - if fs == 'NODEFS': - self.setup_nodefs_test() + @also_with_nodefs + def test_unistd_misc(self): self.do_run_in_out_file_test('unistd/misc.c', interleaved_output=False) @also_with_standalone_wasm() diff --git a/test/test_other.py b/test/test_other.py index 3adbe4b84ad59..e44c647af12a6 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -115,8 +115,7 @@ def wasmfs_all_backends(f): @wraps(f) def metafunc(self, backend, *args, **kwargs): - self.set_setting('WASMFS') - self.emcc_args.append('-DWASMFS') + self.setup_wasmfs_test() self.emcc_args.append(f'-D{backend}') f(self, *args, **kwargs) @@ -131,8 +130,7 @@ def also_with_wasmfs_all_backends(f): @wraps(f) def metafunc(self, backend, *args, **kwargs): if backend: - self.set_setting('WASMFS') - self.emcc_args.append('-DWASMFS') + self.setup_wasmfs_test() self.emcc_args.append(f'-D{backend}') f(self, *args, **kwargs) diff --git a/test/unistd/links.c b/test/unistd/links.c index 81de30c60b2be..718578359ba06 100644 --- a/test/unistd/links.c +++ b/test/unistd/links.c @@ -41,11 +41,11 @@ void changedir(const char *dir) { } void setup() { - makedir("working"); + makedir("/working"); #if defined(__EMSCRIPTEN__) && defined(NODEFS) - EM_ASM(FS.mount(NODEFS, { root: '.' }, 'working')); + EM_ASM(FS.mount(NODEFS, { root: '.' }, '/working')); #endif - changedir("working"); + changedir("/working"); makelink("../test/../there!", "link"); makefile("file", "test"); makedir("directory");