From 856048bb68670d53af7c453b621b75e9314b11b4 Mon Sep 17 00:00:00 2001 From: Oleksii Fesenko Date: Wed, 23 Feb 2022 01:27:51 +0200 Subject: [PATCH 01/19] optional param to prevent function overwriting in case of names collisions --- src/utility.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/utility.js b/src/utility.js index d4fcde8e88c4c..7ba6b7863d1ec 100644 --- a/src/utility.js +++ b/src/utility.js @@ -92,7 +92,18 @@ function sum(x) { return x.reduce((a, b) => a + b, 0); } -function mergeInto(obj, other) { +// forbidFuncRedefinition if is true, it shows error in case of function redefinition +function mergeInto(obj, other, forbidFuncRedefinition = false) { + // looking for function redefinition + if (forbidFuncRedefinition) { + for (const key in other) { + if (obj[key] !== undefined) { + error ("JS function is defined more than once: " + key); + return; + } + } + } + return Object.assign(obj, other); } From 2c70906e9bbe55b564db38919da424b109f4e64a Mon Sep 17 00:00:00 2001 From: Oleksii Fesenko Date: Wed, 23 Feb 2022 01:43:28 +0200 Subject: [PATCH 02/19] eslint correction --- src/utility.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utility.js b/src/utility.js index 7ba6b7863d1ec..ddbcc9b7074e4 100644 --- a/src/utility.js +++ b/src/utility.js @@ -98,7 +98,7 @@ function mergeInto(obj, other, forbidFuncRedefinition = false) { if (forbidFuncRedefinition) { for (const key in other) { if (obj[key] !== undefined) { - error ("JS function is defined more than once: " + key); + error('JS function is defined more than once: ' + key); return; } } From f936a5b21ebc3ee029f4c58171296def758d2149 Mon Sep 17 00:00:00 2001 From: Oleksii Fesenko Date: Wed, 23 Feb 2022 15:05:29 +0200 Subject: [PATCH 03/19] corrections according to comments --- src/utility.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/utility.js b/src/utility.js index ddbcc9b7074e4..99b4f3e3f2c66 100644 --- a/src/utility.js +++ b/src/utility.js @@ -92,13 +92,13 @@ function sum(x) { return x.reduce((a, b) => a + b, 0); } -// forbidFuncRedefinition if is true, it shows error in case of function redefinition -function mergeInto(obj, other, forbidFuncRedefinition = false) { - // looking for function redefinition - if (forbidFuncRedefinition) { - for (const key in other) { - if (obj[key] !== undefined) { - error('JS function is defined more than once: ' + key); +// if allowOverride is false, it shows error in case of symbol redefinition +function mergeInto(obj, other, allowOverride = true) { + // check for unintended symbol redefinition + if (!allowOverride) { + for (const key of Object.keys(other)) { + if (obj.hasOwnProperty(key)) { + error('Symbol redefinition: ' + key); return; } } From a902d5ca75f3f48c4f6f69a73c4bb6f65926d3c3 Mon Sep 17 00:00:00 2001 From: Stuont Date: Tue, 29 Mar 2022 14:38:37 +0300 Subject: [PATCH 04/19] test case addition for duplicated javascript functions --- tests/test_core.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/test_core.py b/tests/test_core.py index 7dfac2dc7102f..1a6fb5b46900b 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -5913,6 +5913,40 @@ def test_js_libraries(self): self.emcc_args += ['--js-library', 'mylib1.js', '--js-library', 'mylib2.js'] self.do_runf('main.cpp', 'hello from lib!\n*32*\n') + def test_duplicate_js_functions(self): + create_file('duplicated_func.cpp', ''' + #include + extern "C" { + extern int duplicatedFunc(); + } + int main() { + int res = duplicatedFunc(); + printf("*%d*\\n", res); + return 0; + } + ''') + create_file('duplicated_func_1.js', ''' + mergeInto(LibraryManager.library, { + duplicatedFunc : function() { + return 1; + } + }, false + ); + ''') + create_file('duplicated_func_2.js', ''' + mergeInto(LibraryManager.library, { + duplicatedFunc : function() { + return 2; + } + }, false + ); + ''') + + self.emcc_args += ['--js-library', 'duplicated_func_1.js', '--js-library', 'duplicated_func_2.js'] + # self.run_process([EMCC, 'duplicated_func.cpp'] + self.get_emcc_args()) + err = self.expect_fail([EMCC, test_file('duplicated_func.cpp')] + self.get_emcc_args()) + self.assertContained('duplicatedFunc', err) + def test_unicode_js_library(self): create_file('main.cpp', ''' #include From 26d318f2665e8c25ae209f458bbbbc8f24e10694 Mon Sep 17 00:00:00 2001 From: Stuont Date: Tue, 29 Mar 2022 16:02:14 +0300 Subject: [PATCH 05/19] tabs removal --- tests/test_core.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_core.py b/tests/test_core.py index 1a6fb5b46900b..981ddfe96a6e2 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -5927,17 +5927,17 @@ def test_duplicate_js_functions(self): ''') create_file('duplicated_func_1.js', ''' mergeInto(LibraryManager.library, { - duplicatedFunc : function() { - return 1; - } + duplicatedFunc : function() { + return 1; + } }, false ); ''') create_file('duplicated_func_2.js', ''' mergeInto(LibraryManager.library, { - duplicatedFunc : function() { - return 2; - } + duplicatedFunc : function() { + return 2; + } }, false ); ''') From 38392ed75275fcdbd1947267e215e5f4ca0087b6 Mon Sep 17 00:00:00 2001 From: Stuont Date: Tue, 29 Mar 2022 19:55:20 +0300 Subject: [PATCH 06/19] correction --- src/utility.js | 2 +- tests/test_core.py | 239 ++++++++++++--------------------------------- 2 files changed, 65 insertions(+), 176 deletions(-) diff --git a/src/utility.js b/src/utility.js index 99b4f3e3f2c66..d4b032ef9840d 100644 --- a/src/utility.js +++ b/src/utility.js @@ -98,7 +98,7 @@ function mergeInto(obj, other, allowOverride = true) { if (!allowOverride) { for (const key of Object.keys(other)) { if (obj.hasOwnProperty(key)) { - error('Symbol redefinition: ' + key); + error('Symbol re-definition in JavaScript library: ' + key + '. Use allowOverride if this is intended'); return; } } diff --git a/tests/test_core.py b/tests/test_core.py index fe974b7462c80..1983a97ec2809 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -26,7 +26,7 @@ from common import RunnerCore, path_from_root, requires_native_clang, test_file, create_file from common import skip_if, needs_dylink, no_windows, no_mac, is_slow_test, parameterized from common import env_modify, with_env_modify, disabled, node_pthreads -from common import read_file, read_binary, require_v8, require_node +from common import read_file, read_binary, require_node, require_v8 from common import NON_ZERO, WEBIDL_BINDER, EMBUILDER import clang_native @@ -150,9 +150,9 @@ def also_with_noderawfs(func): def metafunc(self, rawfs): if rawfs: - self.require_node() self.emcc_args += ['-DNODERAWFS'] self.set_setting('NODERAWFS') + self.js_engines = [config.NODE_JS] func(self) metafunc._parameterize = {'': (False,), @@ -853,10 +853,10 @@ def test_multiply_defined_symbols(self): self.emcc('b2.c', ['-c']) self.emcc('main.c', ['-c']) - building.emar('cr', 'liba.a', ['a1.o', 'a2.o']) - building.emar('cr', 'libb.a', ['b1.o', 'b2.o']) + building.emar('cr', 'liba.a', ['a1.c.o', 'a2.c.o']) + building.emar('cr', 'libb.a', ['b1.c.o', 'b2.c.o']) - building.link_to_object(['main.o', 'liba.a', 'libb.a'], 'all.o') + building.link_to_object(['main.c.o', 'liba.a', 'libb.a'], 'all.o') self.emcc('all.o', self.get_emcc_args(), 'all.js') self.do_run('all.js', 'result: 1', no_build=True) @@ -1194,9 +1194,9 @@ def test_exceptions_with_and_without_longjmp(self): self.do_run_from_file(test_file('core/test_exceptions.cpp'), test_file('core/test_exceptions_caught.out')) def test_exceptions_off(self): - self.set_setting('DISABLE_EXCEPTION_CATCHING') for support_longjmp in [0, 1]: - self.do_runf(test_file('core/test_exceptions.cpp'), assert_returncode=NON_ZERO) + self.set_setting('DISABLE_EXCEPTION_CATCHING') + self.do_run_from_file(test_file('core/test_exceptions.cpp'), test_file('core/test_exceptions_uncaught.out'), assert_returncode=NON_ZERO) @no_asan('TODO: ASan support in minimal runtime') def test_exceptions_minimal_runtime(self): @@ -1543,67 +1543,6 @@ def test_exceptions_rethrow_missing(self): create_file('main.cpp', 'int main() { throw; }') self.do_runf('main.cpp', None, assert_returncode=NON_ZERO) - def test_format_exception(self): - self.set_setting('DISABLE_EXCEPTION_CATCHING', 0) - self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', ['$formatException', '__cxa_decrement_exception_refcount', '__cxa_increment_exception_refcount']) - self.set_setting('EXPORTED_FUNCTIONS', ['_main', 'formatException', '_emscripten_format_exception', '_free']) - self.maybe_closure() - src = ''' - #include - #include - #include - using namespace std; - - class myexception : public exception { - virtual const char* what() const throw() { return "My exception happened"; } - } myex; - - EMSCRIPTEN_KEEPALIVE extern "C" void throw_exc(int x) { - if (x == 1) { - throw 1000; - } - if (x == 2) { - throw 'c'; - } - if (x == 3) { - throw runtime_error("abc"); - } - if (x == 4) { - throw myex; - } - if (x == 5) { - throw "abc"; - } - } - - int main() { - EM_ASM({ - for (let i = 1; i < 6; i++){ - try { - Module["_throw_exc"](i); - } catch(p) { - // Because we are catching and handling the exception in JS, the normal - // exception catching C++ code doesn't kick in, so we need to make sure we free - // the exception, if necessary. By incrementing and decrementing the refcount - // we trigger the free'ing of the exception if its refcount was zero. - ___cxa_increment_exception_refcount(p); - console.log(Module["formatException"](p).replace(/0x[0-9a-f]*/, "xxx")); - ___cxa_decrement_exception_refcount(p); - } - } - }); - } - ''' - expected = '''\ -Cpp Exception: The exception is an object of type 'int' at address xxx which does not inherit from std::exception -Cpp Exception: The exception is an object of type 'char' at address xxx which does not inherit from std::exception -Cpp Exception std::runtime_error: abc -Cpp Exception myexception: My exception happened -Cpp Exception: The exception is an object of type 'char const*' at address xxx which does not inherit from std::exception -''' - - self.do_run(src, expected) - @with_both_eh_sjlj def test_bad_typeid(self): self.do_run(r''' @@ -2114,7 +2053,6 @@ def test_em_asm_direct(self): @parameterized({ '': ([], False), - 'pthreads': (['-sUSE_PTHREADS', '-sPROXY_TO_PTHREAD', '-sEXIT_RUNTIME'], False), 'c': ([], True), 'linked': (['-sMAIN_MODULE'], False), 'linked_c': (['-sMAIN_MODULE'], True), @@ -2122,11 +2060,9 @@ def test_em_asm_direct(self): def test_em_js(self, args, force_c): if '-sMAIN_MODULE' in args: self.check_dylink() - else: - self.emcc_args += ['-sEXPORTED_FUNCTIONS=_main,_malloc'] self.emcc_args += args - if '-sUSE_PTHREADS' in args: - self.setup_node_pthreads() + if '-sMAIN_MODULE' not in args: + self.emcc_args += ['-sEXPORTED_FUNCTIONS=_main,_malloc'] self.do_core_test('test_em_js.cpp', force_c=force_c) self.assertContained("no args returning int", read_file('test_em_js.js')) @@ -2581,38 +2517,8 @@ def test_pthread_proxying(self): self.do_run_in_out_file_test('pthread/test_pthread_proxying.c', emcc_args=args, interleaved_output=False) - @node_pthreads - @no_wasm2js('occasionally hangs in wasm2js (#16569)') - def test_pthread_proxying_cpp(self): - self.set_setting('EXIT_RUNTIME') - self.set_setting('PROXY_TO_PTHREAD') - self.set_setting('INITIAL_MEMORY=32mb') - args = [f'-I{path_from_root("system/lib/pthread")}'] - self.do_run_in_out_file_test('pthread/test_pthread_proxying_cpp.cpp', - emcc_args=args, interleaved_output=False) - - @node_pthreads - def test_pthread_proxying_dropped_work(self): - self.set_setting('EXIT_RUNTIME') - self.set_setting('PTHREAD_POOL_SIZE=2') - args = [f'-I{path_from_root("system/lib/pthread")}'] - self.do_run_in_out_file_test('pthread/test_pthread_proxying_dropped_work.c', - emcc_args=args) - - @node_pthreads - def test_pthread_proxying_refcount(self): - self.set_setting('EXIT_RUNTIME') - self.set_setting('PTHREAD_POOL_SIZE=1') - self.set_setting('ASSERTIONS=0') - args = [f'-I{path_from_root("system/lib/pthread")}'] - if '-fsanitize=address' in self.emcc_args or '-fsanitize=leak' in self.emcc_args: - args += ['-DSANITIZER'] - self.do_run_in_out_file_test('pthread/test_pthread_proxying_refcount.c', - emcc_args=args) - @node_pthreads def test_pthread_dispatch_after_exit(self): - self.set_setting('EXIT_RUNTIME') self.do_run_in_out_file_test('pthread/test_pthread_dispatch_after_exit.c', interleaved_output=False) @node_pthreads @@ -5527,7 +5433,7 @@ def test_minimal_runtime_utf8_invalid(self): self.set_setting('EXPORTED_RUNTIME_METHODS', ['UTF8ToString', 'stringToUTF8']) self.set_setting('MINIMAL_RUNTIME') self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')] - for decoder_mode in [0, 1]: + for decoder_mode in [False, True]: self.set_setting('TEXTDECODER', decoder_mode) print(str(decoder_mode)) self.do_runf(test_file('utf8_invalid.cpp'), 'OK.') @@ -5576,7 +5482,6 @@ def test_fs_base(self): @also_with_noderawfs @is_slow_test - @require_node def test_fs_nodefs_rw(self): # TODO(sbc): This test exposes in issue in the way we run closure compiler and # causes it to generate non-ES5 output. @@ -5589,23 +5494,19 @@ def test_fs_nodefs_rw(self): self.do_runf(test_file('fs/test_nodefs_rw.c'), 'success') @also_with_noderawfs - @require_node def test_fs_nodefs_cloexec(self): self.emcc_args += ['-lnodefs.js'] self.do_runf(test_file('fs/test_nodefs_cloexec.c'), 'success') - @require_node def test_fs_nodefs_home(self): self.set_setting('FORCE_FILESYSTEM') self.emcc_args += ['-lnodefs.js'] - self.do_runf(test_file('fs/test_nodefs_home.c'), 'success') + self.do_runf(test_file('fs/test_nodefs_home.c'), 'success', js_engines=[config.NODE_JS]) - @require_node def test_fs_nodefs_nofollow(self): self.emcc_args += ['-lnodefs.js'] - self.do_runf(test_file('fs/test_nodefs_nofollow.c'), 'success') + self.do_runf(test_file('fs/test_nodefs_nofollow.c'), 'success', js_engines=[config.NODE_JS]) - @require_node def test_fs_nodefs_readdir(self): # externally setup an existing folder structure: existing/a os.makedirs(os.path.join(self.working_dir, 'existing', 'a')) @@ -5613,13 +5514,12 @@ def test_fs_nodefs_readdir(self): self.do_runf(test_file('fs/test_nodefs_readdir.c'), 'success') @no_windows('no symlink support on windows') - @require_node def test_fs_noderawfs_nofollow(self): self.set_setting('NODERAWFS') create_file('filename', 'foo') os.symlink('filename', 'linkname') self.emcc_args += ['-lnodefs.js'] - self.do_runf(test_file('fs/test_noderawfs_nofollow.c'), 'success') + self.do_runf(test_file('fs/test_noderawfs_nofollow.c'), 'success', js_engines=[config.NODE_JS]) def test_fs_trackingdelegate(self): self.set_setting('FS_DEBUG') @@ -5627,6 +5527,7 @@ def test_fs_trackingdelegate(self): @also_with_noderawfs def test_fs_writeFile(self): + self.set_setting('DISABLE_EXCEPTION_CATCHING') # see issue 2334 self.do_run_in_out_file_test('fs/test_writeFile.cpp') def test_fs_write(self): @@ -5767,12 +5668,11 @@ def test_unistd_truncate(self): @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") - @require_node def test_unistd_truncate_noderawfs(self): self.uses_es6 = True self.set_setting('NODERAWFS') self.maybe_closure() - self.do_run_in_out_file_test('unistd/truncate.c') + self.do_run_in_out_file_test('unistd/truncate.c', js_engines=[config.NODE_JS]) @also_with_standalone_wasm() def test_unistd_sysconf(self): @@ -5823,29 +5723,26 @@ def test_unistd_unlink(self): def test_unistd_links(self, args, nodefs): self.emcc_args += args - 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. + if WINDOWS and nodefs: + 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') + self.do_run_in_out_file_test('unistd/links.c', js_engines=[config.NODE_JS]) @no_windows('Skipping NODEFS test, since it would require administrative privileges.') - @require_node def test_unistd_symlink_on_nodefs(self): # 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. self.emcc_args += ['-lnodefs.js'] - self.do_run_in_out_file_test('unistd/symlink_on_nodefs.c') + self.do_run_in_out_file_test('unistd/symlink_on_nodefs.c', js_engines=[config.NODE_JS]) @also_with_wasm_bigint def test_unistd_io(self): @@ -5856,11 +5753,6 @@ def test_unistd_io(self): self.emcc_args = orig_compiler_opts + ['-D' + fs] if fs == 'NODEFS': self.emcc_args += ['-lnodefs.js'] - 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') @no_windows('https://github.com/emscripten-core/emscripten/issues/8882') @@ -6051,9 +5943,8 @@ def test_duplicate_js_functions(self): ''') self.emcc_args += ['--js-library', 'duplicated_func_1.js', '--js-library', 'duplicated_func_2.js'] - # self.run_process([EMCC, 'duplicated_func.cpp'] + self.get_emcc_args()) err = self.expect_fail([EMCC, test_file('duplicated_func.cpp')] + self.get_emcc_args()) - self.assertContained('duplicatedFunc', err) + self.assertContained('error: Symbol re-definition in JavaScript library: duplicatedFunc. Use allowOverride if this is intended', err) def test_unicode_js_library(self): create_file('main.cpp', ''' @@ -6265,15 +6156,6 @@ def test_mmap(self): self.do_core_test('test_mmap.c') - @node_pthreads - def test_mmap_pthreads(self): - # Same test with threading enabled so give is some basic sanity - # checks of the locking on the internal data structures. - self.set_setting('PROXY_TO_PTHREAD') - self.set_setting('EXIT_RUNTIME') - self.set_setting('INITIAL_MEMORY', '64mb') - self.do_core_test('test_mmap.c') - def test_mmap_file(self): for extra_args in [[]]: self.emcc_args += ['--embed-file', 'data.dat'] + extra_args @@ -6503,6 +6385,7 @@ def test_freetype(self): @no_asan('local count too large for VMs') @is_slow_test def test_sqlite(self): + self.set_setting('DISABLE_EXCEPTION_CATCHING') self.set_setting('EXPORTED_FUNCTIONS', ['_main', '_sqlite3_open', '_sqlite3_close', '_sqlite3_exec', '_sqlite3_free']) if '-g' in self.emcc_args: print("disabling inlining") # without registerize (which -g disables), we generate huge amounts of code @@ -7013,6 +6896,29 @@ def test_add_function(self): self.set_setting('ASSERTIONS', 2) self.do_run_in_out_file_test('interop/test_add_function.cpp', interleaved_output=False) + def test_getFuncWrapper_sig_alias(self): + self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', ['$getFuncWrapper']) + src = r''' + #include + #include + + void func1(int a) { + printf("func1\n"); + } + void func2(int a, int b) { + printf("func2\n"); + } + + int main() { + EM_ASM({ + getFuncWrapper($0, 'vi')(0); + getFuncWrapper($1, 'vii')(0, 0); + }, func1, func2); + return 0; + } + ''' + self.do_run(src, 'func1\nfunc2\n') + def test_emulate_function_pointer_casts(self): # Forcibly disable EXIT_RUNTIME due to: # https://github.com/emscripten-core/emscripten/issues/15081 @@ -7740,6 +7646,8 @@ def test_setlocale(self): def test_vswprintf_utf8(self): self.do_run_in_out_file_test('vswprintf_utf8.c') + # needs setTimeout which only node has + @require_node @no_memory64('TODO: asyncify for wasm64') def test_async_hello(self): # needs to flush stdio streams @@ -7765,11 +7673,7 @@ def test_async_hello(self): self.do_runf('main.c', 'HelloWorld!99') - @require_v8 - @no_memory64('TODO: asyncify for wasm64') - def test_async_hello_v8(self): - self.test_async_hello() - + @require_node @no_memory64('TODO: asyncify for wasm64') def test_async_ccall_bad(self): # check bad ccall use @@ -7801,6 +7705,7 @@ def test_async_ccall_bad(self): self.emcc_args += ['--pre-js', 'pre.js'] self.do_runf('main.c', 'The call to main is running asynchronously.') + @require_node @no_memory64('TODO: asyncify for wasm64') def test_async_ccall_good(self): # check reasonable ccall use @@ -7838,7 +7743,6 @@ def test_async_ccall_promise(self, exit_runtime): self.set_setting('INVOKE_RUN', 0) self.set_setting('EXIT_RUNTIME', exit_runtime) self.set_setting('EXPORTED_FUNCTIONS', ['_stringf', '_floatf']) - self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', ['$maybeExit']) create_file('main.c', r''' #include #include @@ -8000,7 +7904,7 @@ def test_emscripten_lazy_load_code(self, conditional): # attempts to "break" the wasm by adding an unreachable in $foo_end. returns whether we found it. def break_wasm(name): - wat = self.get_wasm_text(name) + wat = self.run_process([Path(building.get_binaryen_bin(), 'wasm-dis'), name], stdout=PIPE).stdout lines = wat.splitlines() wat = None for i in range(len(lines)): @@ -8895,27 +8799,18 @@ def test_pthread_dylink_exceptions(self): self.emcc_args.append('-fexceptions') self.dylink_testf(test_file('core/pthread/test_pthread_dylink_exceptions.cpp')) - @parameterized({ - '': (True,), - 'no_yield': (False,) - }) @needs_dylink @node_pthreads - def test_pthread_dlopen(self, do_yield): + def test_pthread_dlopen(self): self.set_setting('USE_PTHREADS') self.emcc_args.append('-Wno-experimental') self.build_dlfcn_lib(test_file('core/pthread/test_pthread_dlopen_side.c')) self.prep_dlfcn_main() self.set_setting('EXIT_RUNTIME') + self.set_setting('PTHREAD_POOL_SIZE', 2) self.set_setting('PROXY_TO_PTHREAD') - if do_yield: - self.emcc_args.append('-DYIELD') - self.do_runf(test_file('core/pthread/test_pthread_dlopen.c'), 'done join') - else: - self.do_runf(test_file('core/pthread/test_pthread_dlopen.c'), - 'invalid index into function table', - assert_returncode=NON_ZERO) + self.do_runf(test_file('core/pthread/test_pthread_dlopen.c')) @needs_dylink @node_pthreads @@ -8926,6 +8821,7 @@ def test_pthread_dlsym(self): self.prep_dlfcn_main() self.set_setting('EXIT_RUNTIME') + self.set_setting('PTHREAD_POOL_SIZE', 2) self.set_setting('PROXY_TO_PTHREAD') self.do_runf(test_file('core/pthread/test_pthread_dlsym.c')) @@ -9148,7 +9044,7 @@ def test_syscall_intercept(self): # Generate tests for everything -def make_run(name, emcc_args, settings=None, env=None, node_args=None, require_v8=False, v8_args=None): +def make_run(name, emcc_args, settings=None, env=None, node_args=None): if env is None: env = {} if settings is None: @@ -9167,6 +9063,9 @@ def tearDown(self): for k, v in self.env.items(): del os.environ[k] + if node_args: + self.node_args = TT.original + TT.tearDown = tearDown def setUp(self): @@ -9183,13 +9082,8 @@ def setUp(self): self.emcc_args += emcc_args if node_args: - self.node_args += node_args - - if v8_args: - self.v8_args += v8_args - - if require_v8: - self.require_v8() + TT.original = self.node_args + self.node_args.append(node_args) TT.setUp = setUp @@ -9205,13 +9099,8 @@ def setUp(self): core3 = make_run('core3', emcc_args=['-O3']) cores = make_run('cores', emcc_args=['-Os']) corez = make_run('corez', emcc_args=['-Oz']) - -# MEMORY64=1 -wasm64 = make_run('wasm64', emcc_args=[], settings={'MEMORY64': 1}, - require_v8=True, v8_args=['--experimental-wasm-memory64']) -# MEMORY64=2, or "lowered" -wasm64l = make_run('wasm64l', emcc_args=[], settings={'MEMORY64': 2}, - node_args=['--experimental-wasm-bigint']) +core64 = make_run('core64', emcc_args=['-O0', '-g3'], + settings={'MEMORY64': 2}, env=None, node_args='--experimental-wasm-bigint') lto0 = make_run('lto0', emcc_args=['-flto', '-O0']) lto1 = make_run('lto1', emcc_args=['-flto', '-O1']) From 78cd95f15400742fc0964658593d61c0281e2cd1 Mon Sep 17 00:00:00 2001 From: Stuont Date: Tue, 29 Mar 2022 19:59:10 +0300 Subject: [PATCH 07/19] Revert "correction" This reverts commit 38392ed75275fcdbd1947267e215e5f4ca0087b6. --- src/utility.js | 2 +- tests/test_core.py | 239 +++++++++++++++++++++++++++++++++------------ 2 files changed, 176 insertions(+), 65 deletions(-) diff --git a/src/utility.js b/src/utility.js index d4b032ef9840d..99b4f3e3f2c66 100644 --- a/src/utility.js +++ b/src/utility.js @@ -98,7 +98,7 @@ function mergeInto(obj, other, allowOverride = true) { if (!allowOverride) { for (const key of Object.keys(other)) { if (obj.hasOwnProperty(key)) { - error('Symbol re-definition in JavaScript library: ' + key + '. Use allowOverride if this is intended'); + error('Symbol redefinition: ' + key); return; } } diff --git a/tests/test_core.py b/tests/test_core.py index 1983a97ec2809..fe974b7462c80 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -26,7 +26,7 @@ from common import RunnerCore, path_from_root, requires_native_clang, test_file, create_file from common import skip_if, needs_dylink, no_windows, no_mac, is_slow_test, parameterized from common import env_modify, with_env_modify, disabled, node_pthreads -from common import read_file, read_binary, require_node, require_v8 +from common import read_file, read_binary, require_v8, require_node from common import NON_ZERO, WEBIDL_BINDER, EMBUILDER import clang_native @@ -150,9 +150,9 @@ def also_with_noderawfs(func): def metafunc(self, rawfs): if rawfs: + self.require_node() self.emcc_args += ['-DNODERAWFS'] self.set_setting('NODERAWFS') - self.js_engines = [config.NODE_JS] func(self) metafunc._parameterize = {'': (False,), @@ -853,10 +853,10 @@ def test_multiply_defined_symbols(self): self.emcc('b2.c', ['-c']) self.emcc('main.c', ['-c']) - building.emar('cr', 'liba.a', ['a1.c.o', 'a2.c.o']) - building.emar('cr', 'libb.a', ['b1.c.o', 'b2.c.o']) + building.emar('cr', 'liba.a', ['a1.o', 'a2.o']) + building.emar('cr', 'libb.a', ['b1.o', 'b2.o']) - building.link_to_object(['main.c.o', 'liba.a', 'libb.a'], 'all.o') + building.link_to_object(['main.o', 'liba.a', 'libb.a'], 'all.o') self.emcc('all.o', self.get_emcc_args(), 'all.js') self.do_run('all.js', 'result: 1', no_build=True) @@ -1194,9 +1194,9 @@ def test_exceptions_with_and_without_longjmp(self): self.do_run_from_file(test_file('core/test_exceptions.cpp'), test_file('core/test_exceptions_caught.out')) def test_exceptions_off(self): + self.set_setting('DISABLE_EXCEPTION_CATCHING') for support_longjmp in [0, 1]: - self.set_setting('DISABLE_EXCEPTION_CATCHING') - self.do_run_from_file(test_file('core/test_exceptions.cpp'), test_file('core/test_exceptions_uncaught.out'), assert_returncode=NON_ZERO) + self.do_runf(test_file('core/test_exceptions.cpp'), assert_returncode=NON_ZERO) @no_asan('TODO: ASan support in minimal runtime') def test_exceptions_minimal_runtime(self): @@ -1543,6 +1543,67 @@ def test_exceptions_rethrow_missing(self): create_file('main.cpp', 'int main() { throw; }') self.do_runf('main.cpp', None, assert_returncode=NON_ZERO) + def test_format_exception(self): + self.set_setting('DISABLE_EXCEPTION_CATCHING', 0) + self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', ['$formatException', '__cxa_decrement_exception_refcount', '__cxa_increment_exception_refcount']) + self.set_setting('EXPORTED_FUNCTIONS', ['_main', 'formatException', '_emscripten_format_exception', '_free']) + self.maybe_closure() + src = ''' + #include + #include + #include + using namespace std; + + class myexception : public exception { + virtual const char* what() const throw() { return "My exception happened"; } + } myex; + + EMSCRIPTEN_KEEPALIVE extern "C" void throw_exc(int x) { + if (x == 1) { + throw 1000; + } + if (x == 2) { + throw 'c'; + } + if (x == 3) { + throw runtime_error("abc"); + } + if (x == 4) { + throw myex; + } + if (x == 5) { + throw "abc"; + } + } + + int main() { + EM_ASM({ + for (let i = 1; i < 6; i++){ + try { + Module["_throw_exc"](i); + } catch(p) { + // Because we are catching and handling the exception in JS, the normal + // exception catching C++ code doesn't kick in, so we need to make sure we free + // the exception, if necessary. By incrementing and decrementing the refcount + // we trigger the free'ing of the exception if its refcount was zero. + ___cxa_increment_exception_refcount(p); + console.log(Module["formatException"](p).replace(/0x[0-9a-f]*/, "xxx")); + ___cxa_decrement_exception_refcount(p); + } + } + }); + } + ''' + expected = '''\ +Cpp Exception: The exception is an object of type 'int' at address xxx which does not inherit from std::exception +Cpp Exception: The exception is an object of type 'char' at address xxx which does not inherit from std::exception +Cpp Exception std::runtime_error: abc +Cpp Exception myexception: My exception happened +Cpp Exception: The exception is an object of type 'char const*' at address xxx which does not inherit from std::exception +''' + + self.do_run(src, expected) + @with_both_eh_sjlj def test_bad_typeid(self): self.do_run(r''' @@ -2053,6 +2114,7 @@ def test_em_asm_direct(self): @parameterized({ '': ([], False), + 'pthreads': (['-sUSE_PTHREADS', '-sPROXY_TO_PTHREAD', '-sEXIT_RUNTIME'], False), 'c': ([], True), 'linked': (['-sMAIN_MODULE'], False), 'linked_c': (['-sMAIN_MODULE'], True), @@ -2060,9 +2122,11 @@ def test_em_asm_direct(self): def test_em_js(self, args, force_c): if '-sMAIN_MODULE' in args: self.check_dylink() - self.emcc_args += args - if '-sMAIN_MODULE' not in args: + else: self.emcc_args += ['-sEXPORTED_FUNCTIONS=_main,_malloc'] + self.emcc_args += args + if '-sUSE_PTHREADS' in args: + self.setup_node_pthreads() self.do_core_test('test_em_js.cpp', force_c=force_c) self.assertContained("no args returning int", read_file('test_em_js.js')) @@ -2517,8 +2581,38 @@ def test_pthread_proxying(self): self.do_run_in_out_file_test('pthread/test_pthread_proxying.c', emcc_args=args, interleaved_output=False) + @node_pthreads + @no_wasm2js('occasionally hangs in wasm2js (#16569)') + def test_pthread_proxying_cpp(self): + self.set_setting('EXIT_RUNTIME') + self.set_setting('PROXY_TO_PTHREAD') + self.set_setting('INITIAL_MEMORY=32mb') + args = [f'-I{path_from_root("system/lib/pthread")}'] + self.do_run_in_out_file_test('pthread/test_pthread_proxying_cpp.cpp', + emcc_args=args, interleaved_output=False) + + @node_pthreads + def test_pthread_proxying_dropped_work(self): + self.set_setting('EXIT_RUNTIME') + self.set_setting('PTHREAD_POOL_SIZE=2') + args = [f'-I{path_from_root("system/lib/pthread")}'] + self.do_run_in_out_file_test('pthread/test_pthread_proxying_dropped_work.c', + emcc_args=args) + + @node_pthreads + def test_pthread_proxying_refcount(self): + self.set_setting('EXIT_RUNTIME') + self.set_setting('PTHREAD_POOL_SIZE=1') + self.set_setting('ASSERTIONS=0') + args = [f'-I{path_from_root("system/lib/pthread")}'] + if '-fsanitize=address' in self.emcc_args or '-fsanitize=leak' in self.emcc_args: + args += ['-DSANITIZER'] + self.do_run_in_out_file_test('pthread/test_pthread_proxying_refcount.c', + emcc_args=args) + @node_pthreads def test_pthread_dispatch_after_exit(self): + self.set_setting('EXIT_RUNTIME') self.do_run_in_out_file_test('pthread/test_pthread_dispatch_after_exit.c', interleaved_output=False) @node_pthreads @@ -5433,7 +5527,7 @@ def test_minimal_runtime_utf8_invalid(self): self.set_setting('EXPORTED_RUNTIME_METHODS', ['UTF8ToString', 'stringToUTF8']) self.set_setting('MINIMAL_RUNTIME') self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')] - for decoder_mode in [False, True]: + for decoder_mode in [0, 1]: self.set_setting('TEXTDECODER', decoder_mode) print(str(decoder_mode)) self.do_runf(test_file('utf8_invalid.cpp'), 'OK.') @@ -5482,6 +5576,7 @@ def test_fs_base(self): @also_with_noderawfs @is_slow_test + @require_node def test_fs_nodefs_rw(self): # TODO(sbc): This test exposes in issue in the way we run closure compiler and # causes it to generate non-ES5 output. @@ -5494,19 +5589,23 @@ def test_fs_nodefs_rw(self): self.do_runf(test_file('fs/test_nodefs_rw.c'), 'success') @also_with_noderawfs + @require_node def test_fs_nodefs_cloexec(self): self.emcc_args += ['-lnodefs.js'] self.do_runf(test_file('fs/test_nodefs_cloexec.c'), 'success') + @require_node def test_fs_nodefs_home(self): self.set_setting('FORCE_FILESYSTEM') self.emcc_args += ['-lnodefs.js'] - self.do_runf(test_file('fs/test_nodefs_home.c'), 'success', js_engines=[config.NODE_JS]) + self.do_runf(test_file('fs/test_nodefs_home.c'), 'success') + @require_node def test_fs_nodefs_nofollow(self): self.emcc_args += ['-lnodefs.js'] - self.do_runf(test_file('fs/test_nodefs_nofollow.c'), 'success', js_engines=[config.NODE_JS]) + self.do_runf(test_file('fs/test_nodefs_nofollow.c'), 'success') + @require_node def test_fs_nodefs_readdir(self): # externally setup an existing folder structure: existing/a os.makedirs(os.path.join(self.working_dir, 'existing', 'a')) @@ -5514,12 +5613,13 @@ def test_fs_nodefs_readdir(self): self.do_runf(test_file('fs/test_nodefs_readdir.c'), 'success') @no_windows('no symlink support on windows') + @require_node def test_fs_noderawfs_nofollow(self): self.set_setting('NODERAWFS') create_file('filename', 'foo') os.symlink('filename', 'linkname') self.emcc_args += ['-lnodefs.js'] - self.do_runf(test_file('fs/test_noderawfs_nofollow.c'), 'success', js_engines=[config.NODE_JS]) + self.do_runf(test_file('fs/test_noderawfs_nofollow.c'), 'success') def test_fs_trackingdelegate(self): self.set_setting('FS_DEBUG') @@ -5527,7 +5627,6 @@ def test_fs_trackingdelegate(self): @also_with_noderawfs def test_fs_writeFile(self): - self.set_setting('DISABLE_EXCEPTION_CATCHING') # see issue 2334 self.do_run_in_out_file_test('fs/test_writeFile.cpp') def test_fs_write(self): @@ -5668,11 +5767,12 @@ def test_unistd_truncate(self): @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") + @require_node def test_unistd_truncate_noderawfs(self): self.uses_es6 = True self.set_setting('NODERAWFS') self.maybe_closure() - self.do_run_in_out_file_test('unistd/truncate.c', js_engines=[config.NODE_JS]) + self.do_run_in_out_file_test('unistd/truncate.c') @also_with_standalone_wasm() def test_unistd_sysconf(self): @@ -5723,26 +5823,29 @@ def test_unistd_unlink(self): def test_unistd_links(self, args, nodefs): self.emcc_args += args - if WINDOWS and nodefs: - 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 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. 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', js_engines=[config.NODE_JS]) + self.do_run_in_out_file_test('unistd/links.c') @no_windows('Skipping NODEFS test, since it would require administrative privileges.') + @require_node def test_unistd_symlink_on_nodefs(self): # 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. self.emcc_args += ['-lnodefs.js'] - self.do_run_in_out_file_test('unistd/symlink_on_nodefs.c', js_engines=[config.NODE_JS]) + self.do_run_in_out_file_test('unistd/symlink_on_nodefs.c') @also_with_wasm_bigint def test_unistd_io(self): @@ -5753,6 +5856,11 @@ def test_unistd_io(self): self.emcc_args = orig_compiler_opts + ['-D' + fs] if fs == 'NODEFS': self.emcc_args += ['-lnodefs.js'] + 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') @no_windows('https://github.com/emscripten-core/emscripten/issues/8882') @@ -5943,8 +6051,9 @@ def test_duplicate_js_functions(self): ''') self.emcc_args += ['--js-library', 'duplicated_func_1.js', '--js-library', 'duplicated_func_2.js'] + # self.run_process([EMCC, 'duplicated_func.cpp'] + self.get_emcc_args()) err = self.expect_fail([EMCC, test_file('duplicated_func.cpp')] + self.get_emcc_args()) - self.assertContained('error: Symbol re-definition in JavaScript library: duplicatedFunc. Use allowOverride if this is intended', err) + self.assertContained('duplicatedFunc', err) def test_unicode_js_library(self): create_file('main.cpp', ''' @@ -6156,6 +6265,15 @@ def test_mmap(self): self.do_core_test('test_mmap.c') + @node_pthreads + def test_mmap_pthreads(self): + # Same test with threading enabled so give is some basic sanity + # checks of the locking on the internal data structures. + self.set_setting('PROXY_TO_PTHREAD') + self.set_setting('EXIT_RUNTIME') + self.set_setting('INITIAL_MEMORY', '64mb') + self.do_core_test('test_mmap.c') + def test_mmap_file(self): for extra_args in [[]]: self.emcc_args += ['--embed-file', 'data.dat'] + extra_args @@ -6385,7 +6503,6 @@ def test_freetype(self): @no_asan('local count too large for VMs') @is_slow_test def test_sqlite(self): - self.set_setting('DISABLE_EXCEPTION_CATCHING') self.set_setting('EXPORTED_FUNCTIONS', ['_main', '_sqlite3_open', '_sqlite3_close', '_sqlite3_exec', '_sqlite3_free']) if '-g' in self.emcc_args: print("disabling inlining") # without registerize (which -g disables), we generate huge amounts of code @@ -6896,29 +7013,6 @@ def test_add_function(self): self.set_setting('ASSERTIONS', 2) self.do_run_in_out_file_test('interop/test_add_function.cpp', interleaved_output=False) - def test_getFuncWrapper_sig_alias(self): - self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', ['$getFuncWrapper']) - src = r''' - #include - #include - - void func1(int a) { - printf("func1\n"); - } - void func2(int a, int b) { - printf("func2\n"); - } - - int main() { - EM_ASM({ - getFuncWrapper($0, 'vi')(0); - getFuncWrapper($1, 'vii')(0, 0); - }, func1, func2); - return 0; - } - ''' - self.do_run(src, 'func1\nfunc2\n') - def test_emulate_function_pointer_casts(self): # Forcibly disable EXIT_RUNTIME due to: # https://github.com/emscripten-core/emscripten/issues/15081 @@ -7646,8 +7740,6 @@ def test_setlocale(self): def test_vswprintf_utf8(self): self.do_run_in_out_file_test('vswprintf_utf8.c') - # needs setTimeout which only node has - @require_node @no_memory64('TODO: asyncify for wasm64') def test_async_hello(self): # needs to flush stdio streams @@ -7673,7 +7765,11 @@ def test_async_hello(self): self.do_runf('main.c', 'HelloWorld!99') - @require_node + @require_v8 + @no_memory64('TODO: asyncify for wasm64') + def test_async_hello_v8(self): + self.test_async_hello() + @no_memory64('TODO: asyncify for wasm64') def test_async_ccall_bad(self): # check bad ccall use @@ -7705,7 +7801,6 @@ def test_async_ccall_bad(self): self.emcc_args += ['--pre-js', 'pre.js'] self.do_runf('main.c', 'The call to main is running asynchronously.') - @require_node @no_memory64('TODO: asyncify for wasm64') def test_async_ccall_good(self): # check reasonable ccall use @@ -7743,6 +7838,7 @@ def test_async_ccall_promise(self, exit_runtime): self.set_setting('INVOKE_RUN', 0) self.set_setting('EXIT_RUNTIME', exit_runtime) self.set_setting('EXPORTED_FUNCTIONS', ['_stringf', '_floatf']) + self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', ['$maybeExit']) create_file('main.c', r''' #include #include @@ -7904,7 +8000,7 @@ def test_emscripten_lazy_load_code(self, conditional): # attempts to "break" the wasm by adding an unreachable in $foo_end. returns whether we found it. def break_wasm(name): - wat = self.run_process([Path(building.get_binaryen_bin(), 'wasm-dis'), name], stdout=PIPE).stdout + wat = self.get_wasm_text(name) lines = wat.splitlines() wat = None for i in range(len(lines)): @@ -8799,18 +8895,27 @@ def test_pthread_dylink_exceptions(self): self.emcc_args.append('-fexceptions') self.dylink_testf(test_file('core/pthread/test_pthread_dylink_exceptions.cpp')) + @parameterized({ + '': (True,), + 'no_yield': (False,) + }) @needs_dylink @node_pthreads - def test_pthread_dlopen(self): + def test_pthread_dlopen(self, do_yield): self.set_setting('USE_PTHREADS') self.emcc_args.append('-Wno-experimental') self.build_dlfcn_lib(test_file('core/pthread/test_pthread_dlopen_side.c')) self.prep_dlfcn_main() self.set_setting('EXIT_RUNTIME') - self.set_setting('PTHREAD_POOL_SIZE', 2) self.set_setting('PROXY_TO_PTHREAD') - self.do_runf(test_file('core/pthread/test_pthread_dlopen.c')) + if do_yield: + self.emcc_args.append('-DYIELD') + self.do_runf(test_file('core/pthread/test_pthread_dlopen.c'), 'done join') + else: + self.do_runf(test_file('core/pthread/test_pthread_dlopen.c'), + 'invalid index into function table', + assert_returncode=NON_ZERO) @needs_dylink @node_pthreads @@ -8821,7 +8926,6 @@ def test_pthread_dlsym(self): self.prep_dlfcn_main() self.set_setting('EXIT_RUNTIME') - self.set_setting('PTHREAD_POOL_SIZE', 2) self.set_setting('PROXY_TO_PTHREAD') self.do_runf(test_file('core/pthread/test_pthread_dlsym.c')) @@ -9044,7 +9148,7 @@ def test_syscall_intercept(self): # Generate tests for everything -def make_run(name, emcc_args, settings=None, env=None, node_args=None): +def make_run(name, emcc_args, settings=None, env=None, node_args=None, require_v8=False, v8_args=None): if env is None: env = {} if settings is None: @@ -9063,9 +9167,6 @@ def tearDown(self): for k, v in self.env.items(): del os.environ[k] - if node_args: - self.node_args = TT.original - TT.tearDown = tearDown def setUp(self): @@ -9082,8 +9183,13 @@ def setUp(self): self.emcc_args += emcc_args if node_args: - TT.original = self.node_args - self.node_args.append(node_args) + self.node_args += node_args + + if v8_args: + self.v8_args += v8_args + + if require_v8: + self.require_v8() TT.setUp = setUp @@ -9099,8 +9205,13 @@ def setUp(self): core3 = make_run('core3', emcc_args=['-O3']) cores = make_run('cores', emcc_args=['-Os']) corez = make_run('corez', emcc_args=['-Oz']) -core64 = make_run('core64', emcc_args=['-O0', '-g3'], - settings={'MEMORY64': 2}, env=None, node_args='--experimental-wasm-bigint') + +# MEMORY64=1 +wasm64 = make_run('wasm64', emcc_args=[], settings={'MEMORY64': 1}, + require_v8=True, v8_args=['--experimental-wasm-memory64']) +# MEMORY64=2, or "lowered" +wasm64l = make_run('wasm64l', emcc_args=[], settings={'MEMORY64': 2}, + node_args=['--experimental-wasm-bigint']) lto0 = make_run('lto0', emcc_args=['-flto', '-O0']) lto1 = make_run('lto1', emcc_args=['-flto', '-O1']) From dad04e3984674d0194322c10ba7a7bdb8adb3587 Mon Sep 17 00:00:00 2001 From: Stuont Date: Tue, 29 Mar 2022 20:00:57 +0300 Subject: [PATCH 08/19] changes according to comments --- src/utility.js | 2 +- tests/test_core.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/utility.js b/src/utility.js index 99b4f3e3f2c66..d4b032ef9840d 100644 --- a/src/utility.js +++ b/src/utility.js @@ -98,7 +98,7 @@ function mergeInto(obj, other, allowOverride = true) { if (!allowOverride) { for (const key of Object.keys(other)) { if (obj.hasOwnProperty(key)) { - error('Symbol redefinition: ' + key); + error('Symbol re-definition in JavaScript library: ' + key + '. Use allowOverride if this is intended'); return; } } diff --git a/tests/test_core.py b/tests/test_core.py index fe974b7462c80..7227d4ccbf504 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -6055,6 +6055,39 @@ def test_duplicate_js_functions(self): err = self.expect_fail([EMCC, test_file('duplicated_func.cpp')] + self.get_emcc_args()) self.assertContained('duplicatedFunc', err) + def test_duplicate_js_functions(self): + create_file('duplicated_func.cpp', ''' + #include + extern "C" { + extern int duplicatedFunc(); + } + int main() { + int res = duplicatedFunc(); + printf("*%d*\\n", res); + return 0; + } + ''') + create_file('duplicated_func_1.js', ''' + mergeInto(LibraryManager.library, { + duplicatedFunc : function() { + return 1; + } + }, false + ); + ''') + create_file('duplicated_func_2.js', ''' + mergeInto(LibraryManager.library, { + duplicatedFunc : function() { + return 2; + } + }, false + ); + ''') + + self.emcc_args += ['--js-library', 'duplicated_func_1.js', '--js-library', 'duplicated_func_2.js'] + err = self.expect_fail([EMCC, test_file('duplicated_func.cpp')] + self.get_emcc_args()) + self.assertContained('error: Symbol re-definition in JavaScript library: duplicatedFunc. Use allowOverride if this is intended', err) + def test_unicode_js_library(self): create_file('main.cpp', ''' #include From d2315360f982da474d462ac54ff0cbb8a22cec36 Mon Sep 17 00:00:00 2001 From: Stuont Date: Tue, 29 Mar 2022 20:06:05 +0300 Subject: [PATCH 09/19] correction --- tests/test_core.py | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/tests/test_core.py b/tests/test_core.py index 7227d4ccbf504..6033bb2163417 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -6021,40 +6021,6 @@ def test_js_libraries(self): self.emcc_args += ['--js-library', 'mylib1.js', '--js-library', 'mylib2.js'] self.do_runf('main.cpp', 'hello from lib!\n*32*\n') - def test_duplicate_js_functions(self): - create_file('duplicated_func.cpp', ''' - #include - extern "C" { - extern int duplicatedFunc(); - } - int main() { - int res = duplicatedFunc(); - printf("*%d*\\n", res); - return 0; - } - ''') - create_file('duplicated_func_1.js', ''' - mergeInto(LibraryManager.library, { - duplicatedFunc : function() { - return 1; - } - }, false - ); - ''') - create_file('duplicated_func_2.js', ''' - mergeInto(LibraryManager.library, { - duplicatedFunc : function() { - return 2; - } - }, false - ); - ''') - - self.emcc_args += ['--js-library', 'duplicated_func_1.js', '--js-library', 'duplicated_func_2.js'] - # self.run_process([EMCC, 'duplicated_func.cpp'] + self.get_emcc_args()) - err = self.expect_fail([EMCC, test_file('duplicated_func.cpp')] + self.get_emcc_args()) - self.assertContained('duplicatedFunc', err) - def test_duplicate_js_functions(self): create_file('duplicated_func.cpp', ''' #include From 4cf0de1757b0e24ffd3e32c9b30dd215aaea67b5 Mon Sep 17 00:00:00 2001 From: Stuont Date: Wed, 30 Mar 2022 15:27:43 +0300 Subject: [PATCH 10/19] test fix --- tests/test_core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_core.py b/tests/test_core.py index 6033bb2163417..7c31686fd7a75 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -6051,7 +6051,7 @@ def test_duplicate_js_functions(self): ''') self.emcc_args += ['--js-library', 'duplicated_func_1.js', '--js-library', 'duplicated_func_2.js'] - err = self.expect_fail([EMCC, test_file('duplicated_func.cpp')] + self.get_emcc_args()) + err = self.expect_fail([EMCC, 'duplicated_func.cpp'] + self.get_emcc_args()) self.assertContained('error: Symbol re-definition in JavaScript library: duplicatedFunc. Use allowOverride if this is intended', err) def test_unicode_js_library(self): From 426150eadb9eef704027a19952a319b04e18d35b Mon Sep 17 00:00:00 2001 From: Stuonts Date: Thu, 16 Jun 2022 01:03:43 +0300 Subject: [PATCH 11/19] change according to github comments --- src/utility.js | 8 ++++++-- tests/test_core.py | 33 --------------------------------- tests/test_other.py | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 35 deletions(-) diff --git a/src/utility.js b/src/utility.js index 1da9207005302..9b633d8a7fe4d 100644 --- a/src/utility.js +++ b/src/utility.js @@ -92,10 +92,14 @@ function sum(x) { return x.reduce((a, b) => a + b, 0); } +enum LibraryParam { + DisallowOverride: 1 +} + // if allowOverride is false, it shows error in case of symbol redefinition -function mergeInto(obj, other, allowOverride = true) { +function mergeInto(obj, other, libraryOptions = 0) { // check for unintended symbol redefinition - if (!allowOverride) { + if (libraryOptions === LibraryParam.DisallowOverride) { for (const key of Object.keys(other)) { if (obj.hasOwnProperty(key)) { error('Symbol re-definition in JavaScript library: ' + key + '. Use allowOverride if this is intended'); diff --git a/tests/test_core.py b/tests/test_core.py index 6a9c0ced13d70..0d44bfadfbcee 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -6236,39 +6236,6 @@ def test_js_libraries(self): self.emcc_args += ['--js-library', 'mylib1.js', '--js-library', 'mylib2.js'] self.do_runf('main.cpp', 'hello from lib!\n*32*\n') - def test_duplicate_js_functions(self): - create_file('duplicated_func.cpp', ''' - #include - extern "C" { - extern int duplicatedFunc(); - } - int main() { - int res = duplicatedFunc(); - printf("*%d*\\n", res); - return 0; - } - ''') - create_file('duplicated_func_1.js', ''' - mergeInto(LibraryManager.library, { - duplicatedFunc : function() { - return 1; - } - }, false - ); - ''') - create_file('duplicated_func_2.js', ''' - mergeInto(LibraryManager.library, { - duplicatedFunc : function() { - return 2; - } - }, false - ); - ''') - - self.emcc_args += ['--js-library', 'duplicated_func_1.js', '--js-library', 'duplicated_func_2.js'] - err = self.expect_fail([EMCC, 'duplicated_func.cpp'] + self.get_emcc_args()) - self.assertContained('error: Symbol re-definition in JavaScript library: duplicatedFunc. Use allowOverride if this is intended', err) - def test_unicode_js_library(self): create_file('main.cpp', ''' #include diff --git a/tests/test_other.py b/tests/test_other.py index 8bd983127ae51..4b593fb86a5f1 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -3374,6 +3374,39 @@ def test_compilation_database(self): self.run_process([EMCC, 'a.c', '-MJ', 'hello.json', '-c', '-o', 'test.o']) self.assertContained('"file": "a.c", "output": "test.o"', read_file('hello.json')) + def test_duplicate_js_functions(self): + create_file('duplicated_func.cpp', ''' + #include + extern "C" { + extern int duplicatedFunc(); + } + int main() { + int res = duplicatedFunc(); + printf("*%d*\\n", res); + return 0; + } + ''') + create_file('duplicated_func_1.js', ''' + mergeInto(LibraryManager.library, { + duplicatedFunc : function() { + return 1; + } + }, LibraryParam.DisallowOverride + ); + ''') + create_file('duplicated_func_2.js', ''' + mergeInto(LibraryManager.library, { + duplicatedFunc : function() { + return 2; + } + }, LibraryParam.DisallowOverride + ); + ''') + + self.emcc_args += ['--js-library', 'duplicated_func_1.js', '--js-library', 'duplicated_func_2.js'] + err = self.expect_fail([EMCC, 'duplicated_func.cpp'] + self.get_emcc_args()) + self.assertContained('error: Symbol re-definition in JavaScript library: duplicatedFunc. Use allowOverride if this is intended', err) + def test_js_lib_quoted_key(self): create_file('lib.js', r''' mergeInto(LibraryManager.library, { From 3d4e0b47de2f3a1de38df8483c7ed38f3a36c77e Mon Sep 17 00:00:00 2001 From: Stuonts Date: Thu, 16 Jun 2022 01:11:26 +0300 Subject: [PATCH 12/19] correction --- src/utility.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utility.js b/src/utility.js index 9b633d8a7fe4d..242b0c94923d9 100644 --- a/src/utility.js +++ b/src/utility.js @@ -92,14 +92,14 @@ function sum(x) { return x.reduce((a, b) => a + b, 0); } -enum LibraryParam { +const LibraryParam = Object.freeze({ DisallowOverride: 1 -} +}); // if allowOverride is false, it shows error in case of symbol redefinition -function mergeInto(obj, other, libraryOptions = 0) { +function mergeInto(obj, other, libraryParams = 0) { // check for unintended symbol redefinition - if (libraryOptions === LibraryParam.DisallowOverride) { + if (libraryParams === LibraryParam.DisallowOverride) { for (const key of Object.keys(other)) { if (obj.hasOwnProperty(key)) { error('Symbol re-definition in JavaScript library: ' + key + '. Use allowOverride if this is intended'); From e28feea196c27ece5d1c5b2aa3fa4adce3081627 Mon Sep 17 00:00:00 2001 From: Stuonts Date: Thu, 16 Jun 2022 12:59:09 +0300 Subject: [PATCH 13/19] lint correction --- src/utility.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utility.js b/src/utility.js index 242b0c94923d9..9c08fc29a3de8 100644 --- a/src/utility.js +++ b/src/utility.js @@ -93,7 +93,7 @@ function sum(x) { } const LibraryParam = Object.freeze({ - DisallowOverride: 1 + DisallowOverride: 1, }); // if allowOverride is false, it shows error in case of symbol redefinition From 29d8ac2b0d855801e30074a31385edd80fa9f2f0 Mon Sep 17 00:00:00 2001 From: Stuonts Date: Thu, 16 Jun 2022 14:32:45 +0300 Subject: [PATCH 14/19] correction --- src/utility.js | 4 ++-- tests/test_other.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utility.js b/src/utility.js index 9c08fc29a3de8..9edba920a2efd 100644 --- a/src/utility.js +++ b/src/utility.js @@ -92,7 +92,7 @@ function sum(x) { return x.reduce((a, b) => a + b, 0); } -const LibraryParam = Object.freeze({ +const global.LibraryParam = Object.freeze({ DisallowOverride: 1, }); @@ -102,7 +102,7 @@ function mergeInto(obj, other, libraryParams = 0) { if (libraryParams === LibraryParam.DisallowOverride) { for (const key of Object.keys(other)) { if (obj.hasOwnProperty(key)) { - error('Symbol re-definition in JavaScript library: ' + key + '. Use allowOverride if this is intended'); + error('Symbol re-definition in JavaScript library: ' + key + '. Do not use DisallowOverride if this is intended'); return; } } diff --git a/tests/test_other.py b/tests/test_other.py index 4b593fb86a5f1..b67df9fc9cb10 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -3405,7 +3405,7 @@ def test_duplicate_js_functions(self): self.emcc_args += ['--js-library', 'duplicated_func_1.js', '--js-library', 'duplicated_func_2.js'] err = self.expect_fail([EMCC, 'duplicated_func.cpp'] + self.get_emcc_args()) - self.assertContained('error: Symbol re-definition in JavaScript library: duplicatedFunc. Use allowOverride if this is intended', err) + self.assertContained('error: Symbol re-definition in JavaScript library: duplicatedFunc. Do not use DisallowOverride if this is intended', err) def test_js_lib_quoted_key(self): create_file('lib.js', r''' From 25f919f4e5177424e5725bcf74bfce0707bb5b30 Mon Sep 17 00:00:00 2001 From: Stuonts Date: Thu, 16 Jun 2022 14:46:49 +0300 Subject: [PATCH 15/19] correction --- src/utility.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utility.js b/src/utility.js index 9edba920a2efd..33af5e2ac8a0a 100644 --- a/src/utility.js +++ b/src/utility.js @@ -92,7 +92,7 @@ function sum(x) { return x.reduce((a, b) => a + b, 0); } -const global.LibraryParam = Object.freeze({ +global.LibraryParam = Object.freeze({ DisallowOverride: 1, }); From 27f1479c59aa864841e3ea50182419c2007d9fc3 Mon Sep 17 00:00:00 2001 From: Stuonts Date: Mon, 11 Jul 2022 13:46:57 +0300 Subject: [PATCH 16/19] change according to comments --- src/utility.js | 8 ++------ tests/test_other.py | 6 +++--- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/utility.js b/src/utility.js index db9e765db5245..11fa1baaf4aed 100644 --- a/src/utility.js +++ b/src/utility.js @@ -95,14 +95,10 @@ function sum(x) { return x.reduce((a, b) => a + b, 0); } -global.LibraryParam = Object.freeze({ - DisallowOverride: 1, -}); - // if allowOverride is false, it shows error in case of symbol redefinition -function mergeInto(obj, other, libraryParams = 0) { +function mergeInto(obj, other, options) { // check for unintended symbol redefinition - if (libraryParams === LibraryParam.DisallowOverride) { + if (options.noOverride) { for (const key of Object.keys(other)) { if (obj.hasOwnProperty(key)) { error('Symbol re-definition in JavaScript library: ' + key + '. Do not use DisallowOverride if this is intended'); diff --git a/tests/test_other.py b/tests/test_other.py index 3f4071eea0593..fbac9e6100187 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -3467,7 +3467,7 @@ def test_duplicate_js_functions(self): create_file('duplicated_func.cpp', ''' #include extern "C" { - extern int duplicatedFunc(); + int duplicatedFunc(); } int main() { int res = duplicatedFunc(); @@ -3480,7 +3480,7 @@ def test_duplicate_js_functions(self): duplicatedFunc : function() { return 1; } - }, LibraryParam.DisallowOverride + }, { noOverride: true } ); ''') create_file('duplicated_func_2.js', ''' @@ -3488,7 +3488,7 @@ def test_duplicate_js_functions(self): duplicatedFunc : function() { return 2; } - }, LibraryParam.DisallowOverride + }, { noOverride: true } ); ''') From 34cba573c6815b8c70308cddd0e265080c07aef6 Mon Sep 17 00:00:00 2001 From: Stuonts Date: Tue, 12 Jul 2022 00:33:42 +0300 Subject: [PATCH 17/19] corrections --- src/utility.js | 9 +++++++-- tests/test_other.py | 9 ++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/utility.js b/src/utility.js index 11fa1baaf4aed..bc31aac5e5b5b 100644 --- a/src/utility.js +++ b/src/utility.js @@ -95,8 +95,13 @@ function sum(x) { return x.reduce((a, b) => a + b, 0); } -// if allowOverride is false, it shows error in case of symbol redefinition -function mergeInto(obj, other, options) { +// options is optional input object containing mergeInto params +// currently, it can contain +// +// key: noOverride, value: true +// if it is set, it prevents symbol redefinition and shows error +// in case of redefinition +function mergeInto(obj, other, options = null) { // check for unintended symbol redefinition if (options.noOverride) { for (const key of Object.keys(other)) { diff --git a/tests/test_other.py b/tests/test_other.py index fbac9e6100187..d4c5a6bdeb535 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -3464,11 +3464,10 @@ def test_compilation_database(self): self.assertContained('"file": "a.c", "output": "test.o"', read_file('hello.json')) def test_duplicate_js_functions(self): - create_file('duplicated_func.cpp', ''' + create_file('duplicated_func.c', ''' #include - extern "C" { - int duplicatedFunc(); - } + extern int duplicatedFunc(); + int main() { int res = duplicatedFunc(); printf("*%d*\\n", res); @@ -3493,7 +3492,7 @@ def test_duplicate_js_functions(self): ''') self.emcc_args += ['--js-library', 'duplicated_func_1.js', '--js-library', 'duplicated_func_2.js'] - err = self.expect_fail([EMCC, 'duplicated_func.cpp'] + self.get_emcc_args()) + err = self.expect_fail([EMCC, 'duplicated_func.c'] + self.get_emcc_args()) self.assertContained('error: Symbol re-definition in JavaScript library: duplicatedFunc. Do not use DisallowOverride if this is intended', err) def test_js_lib_quoted_key(self): From fec84e5587765ce812a594b09a83e005f018d6ff Mon Sep 17 00:00:00 2001 From: Stuonts Date: Tue, 12 Jul 2022 01:52:14 +0300 Subject: [PATCH 18/19] correction --- src/utility.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utility.js b/src/utility.js index bc31aac5e5b5b..aaf2625bab7f3 100644 --- a/src/utility.js +++ b/src/utility.js @@ -103,7 +103,7 @@ function sum(x) { // in case of redefinition function mergeInto(obj, other, options = null) { // check for unintended symbol redefinition - if (options.noOverride) { + if (options && options.noOverride) { for (const key of Object.keys(other)) { if (obj.hasOwnProperty(key)) { error('Symbol re-definition in JavaScript library: ' + key + '. Do not use DisallowOverride if this is intended'); From 1ce6b908a53c130ddaa6021b15f6bf685fa9385b Mon Sep 17 00:00:00 2001 From: Stuonts Date: Thu, 21 Jul 2022 20:49:08 +0300 Subject: [PATCH 19/19] name correction in error assertion --- src/utility.js | 2 +- tests/test_other.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utility.js b/src/utility.js index 6f53487a04222..7a49bca4e7308 100644 --- a/src/utility.js +++ b/src/utility.js @@ -97,7 +97,7 @@ function mergeInto(obj, other, options = null) { if (options && options.noOverride) { for (const key of Object.keys(other)) { if (obj.hasOwnProperty(key)) { - error('Symbol re-definition in JavaScript library: ' + key + '. Do not use DisallowOverride if this is intended'); + error('Symbol re-definition in JavaScript library: ' + key + '. Do not use noOverride if this is intended'); return; } } diff --git a/tests/test_other.py b/tests/test_other.py index 31b956123cf96..5df44850d4c43 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -3434,7 +3434,7 @@ def test_duplicate_js_functions(self): self.emcc_args += ['--js-library', 'duplicated_func_1.js', '--js-library', 'duplicated_func_2.js'] err = self.expect_fail([EMCC, 'duplicated_func.c'] + self.get_emcc_args()) - self.assertContained('error: Symbol re-definition in JavaScript library: duplicatedFunc. Do not use DisallowOverride if this is intended', err) + self.assertContained('error: Symbol re-definition in JavaScript library: duplicatedFunc. Do not use noOverride if this is intended', err) def test_js_lib_quoted_key(self): create_file('lib.js', r'''