From 4d5305644958f2d9b79777c4f448eb93ab2b0c52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 30 Sep 2025 00:54:22 +0300 Subject: [PATCH 01/16] Add feature for Wasm Exnref support and separate test skips for legacy vs Exnref EH skipping. --- .circleci/config.yml | 6 ++++-- src/settings_internal.js | 6 +++++- test/common.py | 21 ++++++++++++--------- tools/feature_matrix.py | 24 +++++++++++++++++++++++- 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index efecb37504ff0..23c5aee8c2d63 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1194,7 +1194,8 @@ jobs: # https://github.com/emscripten-core/emscripten/pull/11382#pullrequestreview-428902638 EMTEST_LACKS_NATIVE_CLANG: "1" EMTEST_SKIP_V8: "1" - EMTEST_SKIP_EH: "1" + EMTEST_SKIP_WASM_LEGACY_EH: "1" + EMTEST_SKIP_WASM_EXNREF_EH: "1" EMTEST_SKIP_WASM64: "1" EMTEST_SKIP_SCONS: "1" EMTEST_SKIP_RUST: "1" @@ -1230,7 +1231,8 @@ jobs: # We don't install d8 or modern node on the mac runner so we skip any # tests that depend on those. EMTEST_SKIP_V8: "1" - EMTEST_SKIP_EH: "1" + EMTEST_SKIP_WASM_LEGACY_EH: "1" + EMTEST_SKIP_WASM_EXNREF_EH: "1" EMTEST_SKIP_WASM64: "1" EMTEST_SKIP_SCONS: "1" EMTEST_SKIP_RUST: "1" diff --git a/src/settings_internal.js b/src/settings_internal.js index 1c16446953d68..5e1d2cb151d4f 100644 --- a/src/settings_internal.js +++ b/src/settings_internal.js @@ -180,7 +180,11 @@ var CAN_ADDRESS_2GB = false; // This has no effect if DWARF is not being emitted. var SEPARATE_DWARF = false; -// New WebAssembly exception handling +// Target WebAssembly exception handling instead of JavaScript-side exception +// handling. Furthermore, if WASM_LEGACY_EXCEPTIONS=1, then old legacy Wasm +// exception handling is used, and if WASM_LEGACY_EXCEPTIONS=0, then new Wasm +// Exnref exception handling is targeted. +// Enabled by passing -fwasm-exceptions on the command line. var WASM_EXCEPTIONS = false; // Set to true if the program has a main function. By default this is diff --git a/test/common.py b/test/common.py index 86ccb115df7c8..e7fd0d2561939 100644 --- a/test/common.py +++ b/test/common.py @@ -1207,18 +1207,21 @@ def require_wasm_legacy_eh(self): self.js_engines = [v8] return - if 'EMTEST_SKIP_EH' in os.environ: - self.skipTest('test requires node >= 17 or d8 (and EMTEST_SKIP_EH is set)') + if 'EMTEST_SKIP_WASM_LEGACY_EH' in os.environ: + self.skipTest('test requires node >= 17 or d8 (and EMTEST_SKIP_WASM_LEGACY_EH is set)') else: - self.fail('either d8 or node >= 17 required to run wasm-eh tests. Use EMTEST_SKIP_EH to skip') + self.fail('either d8 or node >= 17 required to run legacy wasm-eh tests. Use EMTEST_SKIP_WASM_LEGACY_EH to skip') def require_wasm_eh(self): self.set_setting('WASM_LEGACY_EXCEPTIONS', 0) - if self.try_require_node_version(24): - self.node_args.append('--experimental-wasm-exnref') - return if self.is_browser_test(): + if 'EMTEST_SKIP_WASM_EXNREF_EH' in os.environ: + self.skipTest('test requires a browser with new Exnref Wasm exceptions support (and EMTEST_SKIP_WASM_EXNREF_EH is set)') + return + + if self.try_require_node_version(24): + self.node_args.append('--experimental-wasm-exnref') return v8 = self.get_v8() @@ -1228,10 +1231,10 @@ def require_wasm_eh(self): self.v8_args.append('--experimental-wasm-exnref') return - if 'EMTEST_SKIP_EH' in os.environ: - self.skipTest('test requires node v24 or d8 (and EMTEST_SKIP_EH is set)') + if 'EMTEST_SKIP_WASM_EXNREF_EH' in os.environ: + self.skipTest('test requires node v24 or d8 (and EMTEST_SKIP_WASM_EXNREF_EH is set)') else: - self.fail('either d8 or node v24 required to run wasm-eh tests. Use EMTEST_SKIP_EH to skip') + self.fail('either d8 or node v24 required to run Exnref wasm-eh tests. Use EMTEST_SKIP_WASM_EXNREF_EH to skip') def require_jspi(self): # emcc warns about stack switching being experimental, and we build with diff --git a/tools/feature_matrix.py b/tools/feature_matrix.py index 405529e1fcda4..aad1a6431ccf0 100644 --- a/tools/feature_matrix.py +++ b/tools/feature_matrix.py @@ -39,6 +39,8 @@ class Feature(IntEnum): PROMISE_ANY = auto() MEMORY64 = auto() WORKER_ES6_MODULES = auto() + WASM_LEGACY_EXCEPTIONS = auto() + WASM_EXNREF_EXCEPTIONS = auto() disable_override_features = set() @@ -95,6 +97,22 @@ class Feature(IntEnum): 'safari': 150000, 'node': 0, # This is a browser only feature, no requirements on Node.js }, + # Legacy Wasm exceptions was the first (now legacy) format for native exception + # handling in WebAssembly. + Feature.WASM_LEGACY_EXCEPTIONS: { + 'chrome': 95, + 'firefox': 100, + 'safari': 150200, + 'node': 170000, + }, + # Exnref Wasm exceptions is a newer format for native exception handling in + # WebAssembly. + Feature.WASM_EXNREF_EXCEPTIONS: { + 'chrome': 137, + 'firefox': 131, + 'safari': 180400, + 'node': 240000, # Supported with flag --experimental-wasm-exnref (TODO: Change this to unflagged version once it ships) + }, } # Static assertion to check that we actually need each of the above feature flags @@ -155,7 +173,7 @@ def enable_feature(feature, reason, override=False): diagnostics.warning( 'compatibility', f'{name}={user_settings[name]} is not compatible with {reason} ' - f'({min_version} or above required)') + f'({name}={min_version} or above required)') else: # If no conflict, bump the minimum version to accommodate the feature. setattr(settings, name, min_version) @@ -186,3 +204,7 @@ def apply_min_browser_versions(): enable_feature(Feature.WORKER_ES6_MODULES, 'EXPORT_ES6 with -pthread') if settings.EXPORT_ES6 and settings.WASM_WORKERS: enable_feature(Feature.WORKER_ES6_MODULES, 'EXPORT_ES6 with -sWASM_WORKERS') + if settings.WASM_EXCEPTIONS and settings.WASM_LEGACY_EXCEPTIONS: + enable_feature(Feature.WASM_LEGACY_EXCEPTIONS, '-fwasm-exceptions') + if not settings.WASM_LEGACY_EXCEPTIONS: + enable_feature(Feature.WASM_EXNREF_EXCEPTIONS, '-sWASM_LEGACY_EXCEPTIONS=0') From 68e26e3744db01c629ad7c047a7b5007739b3cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 30 Sep 2025 01:16:52 +0300 Subject: [PATCH 02/16] code size --- test/codesize/test_codesize_cxx_except_wasm.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/codesize/test_codesize_cxx_except_wasm.json b/test/codesize/test_codesize_cxx_except_wasm.json index b6fe6f9ed1f94..a376eb1110b0e 100644 --- a/test/codesize/test_codesize_cxx_except_wasm.json +++ b/test/codesize/test_codesize_cxx_except_wasm.json @@ -1,10 +1,10 @@ { - "a.out.js": 19608, - "a.out.js.gz": 8109, + "a.out.js": 19539, + "a.out.js.gz": 8086, "a.out.nodebug.wasm": 144630, "a.out.nodebug.wasm.gz": 54894, - "total": 164238, - "total_gz": 63003, + "total": 164169, + "total_gz": 62980, "sent": [ "_abort_js", "_tzset_js", From 36bd04822303ce7ee2698272ac2796d065e2ed13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 30 Sep 2025 01:34:17 +0300 Subject: [PATCH 03/16] Fix merge --- tools/feature_matrix.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/feature_matrix.py b/tools/feature_matrix.py index 8a2d792fc4e40..17afd99b9dad4 100644 --- a/tools/feature_matrix.py +++ b/tools/feature_matrix.py @@ -106,6 +106,7 @@ class Feature(IntEnum): 'firefox': 105, 'safari': 170000, 'node': 0, # This is a browser only feature, no requirements on Node.js + }, # Legacy Wasm exceptions was the first (now legacy) format for native exception # handling in WebAssembly. Feature.WASM_LEGACY_EXCEPTIONS: { From 32dfa3d40d416dfa69f16d093d4fa6dcf7cf774f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 30 Sep 2025 02:54:06 +0300 Subject: [PATCH 04/16] Fix test expectation --- test/test_other.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_other.py b/test/test_other.py index 51359ae62637a..5440fd82345ac 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -14314,10 +14314,10 @@ def test_reproduce(self): def test_min_browser_version(self): err = self.expect_fail([EMCC, test_file('hello_world.c'), '-Wno-transpile', '-Werror', '-sWASM_BIGINT', '-sMIN_SAFARI_VERSION=130000']) - self.assertContained('emcc: error: MIN_SAFARI_VERSION=130000 is not compatible with WASM_BIGINT (150000 or above required)', err) + self.assertContained('emcc: error: MIN_SAFARI_VERSION=130000 is not compatible with WASM_BIGINT (MIN_SAFARI_VERSION=150000 or above required)', err) err = self.expect_fail([EMCC, test_file('hello_world.c'), '-Wno-transpile', '-Werror', '-pthread', '-sMIN_FIREFOX_VERSION=65']) - self.assertContained('emcc: error: MIN_FIREFOX_VERSION=65 is not compatible with pthreads (79 or above required)', err) + self.assertContained('emcc: error: MIN_FIREFOX_VERSION=65 is not compatible with pthreads (MIN_FIREFOX_VERSION=79 or above required)', err) def test_signext_lowering(self): # Use `-v` to show the sub-commands being run by emcc. From d499c8aef3d4116419be0d8fe41c11c75b48ae32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 30 Sep 2025 03:29:51 +0300 Subject: [PATCH 05/16] 80column --- tools/feature_matrix.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/feature_matrix.py b/tools/feature_matrix.py index 17afd99b9dad4..cf68d0aaa7410 100644 --- a/tools/feature_matrix.py +++ b/tools/feature_matrix.py @@ -107,8 +107,8 @@ class Feature(IntEnum): 'safari': 170000, 'node': 0, # This is a browser only feature, no requirements on Node.js }, - # Legacy Wasm exceptions was the first (now legacy) format for native exception - # handling in WebAssembly. + # Legacy Wasm exceptions was the first (now legacy) format for native + # exception handling in WebAssembly. Feature.WASM_LEGACY_EXCEPTIONS: { 'chrome': 95, 'firefox': 100, @@ -121,7 +121,9 @@ class Feature(IntEnum): 'chrome': 137, 'firefox': 131, 'safari': 180400, - 'node': 240000, # Supported with flag --experimental-wasm-exnref (TODO: Change this to unflagged version once it ships) + # Supported with flag --experimental-wasm-exnref (TODO: Change this to + # unflagged version of Node.js that ships exnref default-on) + 'node': 240000, }, } From fa2dc4fe3d0ab962e00e3e8661e7b5c0372942aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 30 Sep 2025 03:42:20 +0300 Subject: [PATCH 06/16] code size --- test/codesize/test_codesize_cxx_except_wasm.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/codesize/test_codesize_cxx_except_wasm.json b/test/codesize/test_codesize_cxx_except_wasm.json index 95b6cf3994be4..fd85059c9698d 100644 --- a/test/codesize/test_codesize_cxx_except_wasm.json +++ b/test/codesize/test_codesize_cxx_except_wasm.json @@ -1,10 +1,10 @@ { - "a.out.js": 19563, - "a.out.js.gz": 8103, + "a.out.js": 19494, + "a.out.js.gz": 8083, "a.out.nodebug.wasm": 144630, "a.out.nodebug.wasm.gz": 54894, - "total": 164193, - "total_gz": 62997, + "total": 164124, + "total_gz": 62977, "sent": [ "_abort_js", "_tzset_js", From 4dcf581e66e30636cf262304aeb5253fa4609102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 30 Sep 2025 15:21:03 +0300 Subject: [PATCH 07/16] Update feature_matrix check --- tools/feature_matrix.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/feature_matrix.py b/tools/feature_matrix.py index cf68d0aaa7410..be54a3ee3b3b7 100644 --- a/tools/feature_matrix.py +++ b/tools/feature_matrix.py @@ -220,6 +220,6 @@ def apply_min_browser_versions(): if settings.OFFSCREENCANVAS_SUPPORT: enable_feature(Feature.OFFSCREENCANVAS_SUPPORT, 'OFFSCREENCANVAS_SUPPORT') if settings.WASM_EXCEPTIONS and settings.WASM_LEGACY_EXCEPTIONS: - enable_feature(Feature.WASM_LEGACY_EXCEPTIONS, '-fwasm-exceptions') - if not settings.WASM_LEGACY_EXCEPTIONS: - enable_feature(Feature.WASM_EXNREF_EXCEPTIONS, '-sWASM_LEGACY_EXCEPTIONS=0') + enable_feature(Feature.WASM_LEGACY_EXCEPTIONS, 'Wasm Legacy exceptions (-fwasm-exceptions with -sWASM_LEGACY_EXCEPTIONS=1)') + if settings.WASM_EXCEPTIONS and not settings.WASM_LEGACY_EXCEPTIONS: + enable_feature(Feature.WASM_EXNREF_EXCEPTIONS, 'Wasm Exnref exceptions (-fwasm-exceptions with -sWASM_LEGACY_EXCEPTIONS=0)') From 3ab97c9db5320429ca8afc6671f5918a9ca43c0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 30 Sep 2025 15:36:33 +0300 Subject: [PATCH 08/16] Do not use the word Exnref to refer to Wasm exception handling. --- .circleci/config.yml | 4 ++-- ChangeLog.md | 2 +- src/settings_internal.js | 4 ++-- test/common.py | 10 +++++----- test/test_other.py | 2 +- tools/feature_matrix.py | 12 +++++++----- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 23c5aee8c2d63..9d5e6ddbe9992 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1195,7 +1195,7 @@ jobs: EMTEST_LACKS_NATIVE_CLANG: "1" EMTEST_SKIP_V8: "1" EMTEST_SKIP_WASM_LEGACY_EH: "1" - EMTEST_SKIP_WASM_EXNREF_EH: "1" + EMTEST_SKIP_EH: "1" EMTEST_SKIP_WASM64: "1" EMTEST_SKIP_SCONS: "1" EMTEST_SKIP_RUST: "1" @@ -1232,7 +1232,7 @@ jobs: # tests that depend on those. EMTEST_SKIP_V8: "1" EMTEST_SKIP_WASM_LEGACY_EH: "1" - EMTEST_SKIP_WASM_EXNREF_EH: "1" + EMTEST_SKIP_EH: "1" EMTEST_SKIP_WASM64: "1" EMTEST_SKIP_SCONS: "1" EMTEST_SKIP_RUST: "1" diff --git a/ChangeLog.md b/ChangeLog.md index 880a74f4757c5..36d0851c10517 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -317,7 +317,7 @@ See docs/process.md for more on how version tagging works. - Emscripten version was bumped to 4.0.0. Happy new year, happy new major version! While version has a few interesting changes, there is nothing huge that makes it different from any other release. (#19053) -- `-sWASM_LEAGCY_EXCEPTIONS` option is added. (#23365) If true, it will emit +- `-sWASM_LEGACY_EXCEPTIONS` option is added. (#23365) If true, it will emit instructions for the legacy Wasm exception handling proposal (https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/legacy/Exceptions.md), and if false, the new standardized exception handling proposal diff --git a/src/settings_internal.js b/src/settings_internal.js index 5e1d2cb151d4f..2f81a0ea647fc 100644 --- a/src/settings_internal.js +++ b/src/settings_internal.js @@ -182,8 +182,8 @@ var SEPARATE_DWARF = false; // Target WebAssembly exception handling instead of JavaScript-side exception // handling. Furthermore, if WASM_LEGACY_EXCEPTIONS=1, then old legacy Wasm -// exception handling is used, and if WASM_LEGACY_EXCEPTIONS=0, then new Wasm -// Exnref exception handling is targeted. +// exception handling is used, and if WASM_LEGACY_EXCEPTIONS=0, then Wasm +// exception handling is targeted. // Enabled by passing -fwasm-exceptions on the command line. var WASM_EXCEPTIONS = false; diff --git a/test/common.py b/test/common.py index e7fd0d2561939..78c6bf4fcdf28 100644 --- a/test/common.py +++ b/test/common.py @@ -1216,8 +1216,8 @@ def require_wasm_eh(self): self.set_setting('WASM_LEGACY_EXCEPTIONS', 0) if self.is_browser_test(): - if 'EMTEST_SKIP_WASM_EXNREF_EH' in os.environ: - self.skipTest('test requires a browser with new Exnref Wasm exceptions support (and EMTEST_SKIP_WASM_EXNREF_EH is set)') + if 'EMTEST_SKIP_EH' in os.environ: + self.skipTest('test requires a browser with Wasm exceptions support (and EMTEST_SKIP_EH is set)') return if self.try_require_node_version(24): @@ -1231,10 +1231,10 @@ def require_wasm_eh(self): self.v8_args.append('--experimental-wasm-exnref') return - if 'EMTEST_SKIP_WASM_EXNREF_EH' in os.environ: - self.skipTest('test requires node v24 or d8 (and EMTEST_SKIP_WASM_EXNREF_EH is set)') + if 'EMTEST_SKIP_EH' in os.environ: + self.skipTest('test requires node v24 or d8 (and EMTEST_SKIP_EH is set)') else: - self.fail('either d8 or node v24 required to run Exnref wasm-eh tests. Use EMTEST_SKIP_WASM_EXNREF_EH to skip') + self.fail('either d8 or node v24 required to run wasm-eh tests. Use EMTEST_SKIP_EH to skip') def require_jspi(self): # emcc warns about stack switching being experimental, and we build with diff --git a/test/test_other.py b/test/test_other.py index 5440fd82345ac..c8b822b596831 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -3633,7 +3633,7 @@ def test_embind_tsgen_jspi(self): }) def test_embind_tsgen_exceptions(self, legacy): if not legacy and shared.get_node_version(config.NODE_JS)[0] < 22: - self.skipTest('Node version needs to be 22 or greater to run tsgen with exnref') + self.skipTest('Node version needs to be 22 or greater to run tsgen with Wasm EH') self.set_setting('WASM_LEGACY_EXCEPTIONS', legacy) # Check that when Wasm exceptions and assertions are enabled bindings still generate. diff --git a/tools/feature_matrix.py b/tools/feature_matrix.py index be54a3ee3b3b7..b80eae11c17d7 100644 --- a/tools/feature_matrix.py +++ b/tools/feature_matrix.py @@ -41,7 +41,7 @@ class Feature(IntEnum): WORKER_ES6_MODULES = auto() OFFSCREENCANVAS_SUPPORT = auto() WASM_LEGACY_EXCEPTIONS = auto() - WASM_EXNREF_EXCEPTIONS = auto() + WASM_EXCEPTIONS = auto() disable_override_features = set() @@ -115,14 +115,16 @@ class Feature(IntEnum): 'safari': 150200, 'node': 170000, }, - # Exnref Wasm exceptions is a newer format for native exception handling in + # Wasm exceptions is a newer format for native exception handling in # WebAssembly. - Feature.WASM_EXNREF_EXCEPTIONS: { + Feature.WASM_EXCEPTIONS: { 'chrome': 137, 'firefox': 131, 'safari': 180400, # Supported with flag --experimental-wasm-exnref (TODO: Change this to - # unflagged version of Node.js that ships exnref default-on) + # unflagged version of Node.js 260000 that ships Wasm EH enabled, after + # Emscripten unit testing has migrated to Node.js 26, and Emsdk ships + # Node.js 26) 'node': 240000, }, } @@ -222,4 +224,4 @@ def apply_min_browser_versions(): if settings.WASM_EXCEPTIONS and settings.WASM_LEGACY_EXCEPTIONS: enable_feature(Feature.WASM_LEGACY_EXCEPTIONS, 'Wasm Legacy exceptions (-fwasm-exceptions with -sWASM_LEGACY_EXCEPTIONS=1)') if settings.WASM_EXCEPTIONS and not settings.WASM_LEGACY_EXCEPTIONS: - enable_feature(Feature.WASM_EXNREF_EXCEPTIONS, 'Wasm Exnref exceptions (-fwasm-exceptions with -sWASM_LEGACY_EXCEPTIONS=0)') + enable_feature(Feature.WASM_EXCEPTIONS, 'Wasm exceptions (-fwasm-exceptions with -sWASM_LEGACY_EXCEPTIONS=0)') From c003d0c46fa9625822815a792d387a0acd8e91ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 30 Sep 2025 18:28:22 +0300 Subject: [PATCH 09/16] Make SUPPORT_LONGJMP imply Wasm Exceptions --- tools/feature_matrix.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/feature_matrix.py b/tools/feature_matrix.py index b80eae11c17d7..7b2051495b829 100644 --- a/tools/feature_matrix.py +++ b/tools/feature_matrix.py @@ -221,7 +221,8 @@ def apply_min_browser_versions(): enable_feature(Feature.WORKER_ES6_MODULES, 'EXPORT_ES6 with -sWASM_WORKERS') if settings.OFFSCREENCANVAS_SUPPORT: enable_feature(Feature.OFFSCREENCANVAS_SUPPORT, 'OFFSCREENCANVAS_SUPPORT') - if settings.WASM_EXCEPTIONS and settings.WASM_LEGACY_EXCEPTIONS: - enable_feature(Feature.WASM_LEGACY_EXCEPTIONS, 'Wasm Legacy exceptions (-fwasm-exceptions with -sWASM_LEGACY_EXCEPTIONS=1)') - if settings.WASM_EXCEPTIONS and not settings.WASM_LEGACY_EXCEPTIONS: - enable_feature(Feature.WASM_EXCEPTIONS, 'Wasm exceptions (-fwasm-exceptions with -sWASM_LEGACY_EXCEPTIONS=0)') + if settings.WASM_EXCEPTIONS or settings.SUPPORT_LONGJMP == 'wasm': # Wasm longjmp support will lean on Wasm (Legacy) EH + if settings.WASM_LEGACY_EXCEPTIONS: + enable_feature(Feature.WASM_LEGACY_EXCEPTIONS, 'Wasm Legacy exceptions (-fwasm-exceptions with -sWASM_LEGACY_EXCEPTIONS=1)') + else: + enable_feature(Feature.WASM_EXCEPTIONS, 'Wasm exceptions (-fwasm-exceptions with -sWASM_LEGACY_EXCEPTIONS=0)') From 351e67af73f296ee6566c2ae8b21d68e9bc782cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 30 Sep 2025 18:40:49 +0300 Subject: [PATCH 10/16] When user passes EMTEST_SKIP_(WASM_LEGACY_)EH=1, then do skip the tests, even if current environment would support them. --- test/common.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/test/common.py b/test/common.py index 78c6bf4fcdf28..ae198aafa31be 100644 --- a/test/common.py +++ b/test/common.py @@ -1197,6 +1197,9 @@ def require_simd(self): self.fail('either d8 or node >= 16 required to run wasm64 tests. Use EMTEST_SKIP_SIMD to skip') def require_wasm_legacy_eh(self): + if 'EMTEST_SKIP_WASM_LEGACY_EH' in os.environ: + self.skipTest('test requires node >= 17 or d8 (and EMTEST_SKIP_WASM_LEGACY_EH is set)') + self.set_setting('WASM_LEGACY_EXCEPTIONS') if self.try_require_node_version(17): return @@ -1207,17 +1210,14 @@ def require_wasm_legacy_eh(self): self.js_engines = [v8] return - if 'EMTEST_SKIP_WASM_LEGACY_EH' in os.environ: - self.skipTest('test requires node >= 17 or d8 (and EMTEST_SKIP_WASM_LEGACY_EH is set)') - else: - self.fail('either d8 or node >= 17 required to run legacy wasm-eh tests. Use EMTEST_SKIP_WASM_LEGACY_EH to skip') + self.fail('either d8 or node >= 17 required to run legacy wasm-eh tests. Use EMTEST_SKIP_WASM_LEGACY_EH to skip') def require_wasm_eh(self): + if 'EMTEST_SKIP_EH' in os.environ: + self.skipTest('test requires a browser with Wasm exceptions support (and EMTEST_SKIP_EH is set)') self.set_setting('WASM_LEGACY_EXCEPTIONS', 0) if self.is_browser_test(): - if 'EMTEST_SKIP_EH' in os.environ: - self.skipTest('test requires a browser with Wasm exceptions support (and EMTEST_SKIP_EH is set)') return if self.try_require_node_version(24): @@ -1231,10 +1231,7 @@ def require_wasm_eh(self): self.v8_args.append('--experimental-wasm-exnref') return - if 'EMTEST_SKIP_EH' in os.environ: - self.skipTest('test requires node v24 or d8 (and EMTEST_SKIP_EH is set)') - else: - self.fail('either d8 or node v24 required to run wasm-eh tests. Use EMTEST_SKIP_EH to skip') + self.fail('either d8 or node v24 required to run wasm-eh tests. Use EMTEST_SKIP_EH to skip') def require_jspi(self): # emcc warns about stack switching being experimental, and we build with From 1911a9165664e930c0bbe2c07ad765c1f9350692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Wed, 1 Oct 2025 02:44:48 +0300 Subject: [PATCH 11/16] codesize --- test/codesize/test_codesize_cxx_except_wasm.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/codesize/test_codesize_cxx_except_wasm.json b/test/codesize/test_codesize_cxx_except_wasm.json index fd85059c9698d..153a065b82db9 100644 --- a/test/codesize/test_codesize_cxx_except_wasm.json +++ b/test/codesize/test_codesize_cxx_except_wasm.json @@ -1,10 +1,10 @@ { - "a.out.js": 19494, - "a.out.js.gz": 8083, + "a.out.js": 19492, + "a.out.js.gz": 8078, "a.out.nodebug.wasm": 144630, "a.out.nodebug.wasm.gz": 54894, - "total": 164124, - "total_gz": 62977, + "total": 164122, + "total_gz": 62972, "sent": [ "_abort_js", "_tzset_js", From 6047664293f9184400fe48163197a861f9003cde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Wed, 1 Oct 2025 21:46:01 +0300 Subject: [PATCH 12/16] Fix bad git automerge --- test/common.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/common.py b/test/common.py index 54a129f7ea1f5..0e15f0d83719d 100644 --- a/test/common.py +++ b/test/common.py @@ -211,18 +211,18 @@ def skip_if_simple(name, condition, note=''): assert not callable(note) def decorator(func): - assert callable(func) + assert callable(func) - @wraps(func) - def decorated(self, *args, **kwargs): - if condition(self): - explanation_str = name - if note: - explanation_str += ': %s' % note - self.skipTest(explanation_str) - return func(self, *args, **kwargs) + @wraps(func) + def decorated(self, *args, **kwargs): + if condition(self): + explanation_str = name + if note: + explanation_str += ': %s' % note + self.skipTest(explanation_str) + return func(self, *args, **kwargs) - return decorated + return decorated return decorator @@ -1044,7 +1044,7 @@ def require_v8(self): self.skipTest('test requires v8 and EMTEST_SKIP_V8 is set') v8 = self.get_v8() if not v8: - self.fail('d8 required to run this test. Use EMTEST_SKIP_V8 to skip') + self.fail('d8 required to run this test. Use EMTEST_SKIP_V8 to skip') self.require_engine(v8) self.cflags.append('-sENVIRONMENT=shell') @@ -1059,7 +1059,7 @@ def require_node(self): self.skipTest('test requires node and EMTEST_SKIP_NODE is set') nodejs = self.get_nodejs() if not nodejs: - self.fail('node required to run this test. Use EMTEST_SKIP_NODE to skip') + self.fail('node required to run this test. Use EMTEST_SKIP_NODE to skip') self.require_engine(nodejs) return nodejs @@ -1074,7 +1074,7 @@ def require_node_canary(self): self.require_engine(nodejs) return - self.fail('node canary required to run this test. Use EMTEST_SKIP_NODE_CANARY to skip') + self.fail('node canary required to run this test. Use EMTEST_SKIP_NODE_CANARY to skip') def require_engine(self, engine): logger.debug(f'require_engine: {engine}') @@ -1099,7 +1099,7 @@ def require_wasm64(self): self.js_engines = [v8] return - self.fail('either d8 or node >= 24 required to run wasm64 tests. Use EMTEST_SKIP_WASM64 to skip') + self.fail('either d8 or node >= 24 required to run wasm64 tests. Use EMTEST_SKIP_WASM64 to skip') def try_require_node_version(self, major, minor = 0, revision = 0): nodejs = self.get_nodejs() @@ -1127,7 +1127,7 @@ def require_simd(self): self.js_engines = [v8] return - self.fail('either d8 or node >= 16 required to run wasm64 tests. Use EMTEST_SKIP_SIMD to skip') + self.fail('either d8 or node >= 16 required to run wasm64 tests. Use EMTEST_SKIP_SIMD to skip') def require_wasm_legacy_eh(self): if 'EMTEST_SKIP_WASM_LEGACY_EH' in os.environ: From 860c50d46413a4a0749e8af61bed72011092ef54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Wed, 1 Oct 2025 21:46:30 +0300 Subject: [PATCH 13/16] Fix bad git automerge --- test/common.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/common.py b/test/common.py index 0e15f0d83719d..734e6d1b45dc7 100644 --- a/test/common.py +++ b/test/common.py @@ -215,11 +215,11 @@ def decorator(func): @wraps(func) def decorated(self, *args, **kwargs): - if condition(self): - explanation_str = name - if note: - explanation_str += ': %s' % note - self.skipTest(explanation_str) + if condition(self): + explanation_str = name + if note: + explanation_str += ': %s' % note + self.skipTest(explanation_str) return func(self, *args, **kwargs) return decorated From 458d190ae89c45679ac4abd4a41e5b368e467289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Wed, 1 Oct 2025 21:47:59 +0300 Subject: [PATCH 14/16] Fix bad git automerge --- test/common.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/common.py b/test/common.py index 734e6d1b45dc7..fe9cc3731855d 100644 --- a/test/common.py +++ b/test/common.py @@ -1149,14 +1149,13 @@ def require_wasm_eh(self): if 'EMTEST_SKIP_EH' in os.environ: self.skipTest('test requires node v24 or d8 (and EMTEST_SKIP_EH is set)') self.set_setting('WASM_LEGACY_EXCEPTIONS', 0) - - if self.is_browser_test(): - return - if self.try_require_node_version(24): self.node_args.append('--experimental-wasm-exnref') return + if self.is_browser_test(): + return + v8 = self.get_v8() if v8: self.cflags.append('-sENVIRONMENT=shell') @@ -1194,7 +1193,7 @@ def require_jspi(self): self.v8_args += exp_args return - self.fail('either d8 or node v24 required to run JSPI tests. Use EMTEST_SKIP_JSPI to skip') + self.fail('either d8 or node v24 required to run JSPI tests. Use EMTEST_SKIP_JSPI to skip') def require_wasm2js(self): if self.is_wasm64(): From 9fcd1b94dd2ca7fca58f92e83b4e5b4ba11b6ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Thu, 2 Oct 2025 00:26:41 +0300 Subject: [PATCH 15/16] codesize --- test/codesize/test_codesize_cxx_except_wasm.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/codesize/test_codesize_cxx_except_wasm.json b/test/codesize/test_codesize_cxx_except_wasm.json index 153a065b82db9..de9e396eec2ed 100644 --- a/test/codesize/test_codesize_cxx_except_wasm.json +++ b/test/codesize/test_codesize_cxx_except_wasm.json @@ -1,10 +1,10 @@ { - "a.out.js": 19492, - "a.out.js.gz": 8078, + "a.out.js": 19486, + "a.out.js.gz": 8077, "a.out.nodebug.wasm": 144630, "a.out.nodebug.wasm.gz": 54894, - "total": 164122, - "total_gz": 62972, + "total": 164116, + "total_gz": 62971, "sent": [ "_abort_js", "_tzset_js", From 9b89c2c259325d5d8fb6eba132ddb364c91da5df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Thu, 2 Oct 2025 01:42:29 +0300 Subject: [PATCH 16/16] Rename EMTEST_SKIP_EH to EMTEST_SKIP_WASM_EH --- .circleci/config.yml | 4 ++-- test/common.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 149d60a0c1a43..179ea692e2954 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1191,7 +1191,7 @@ jobs: EMTEST_LACKS_NATIVE_CLANG: "1" EMTEST_SKIP_V8: "1" EMTEST_SKIP_WASM_LEGACY_EH: "1" - EMTEST_SKIP_EH: "1" + EMTEST_SKIP_WASM_EH: "1" EMTEST_SKIP_WASM64: "1" EMTEST_SKIP_SCONS: "1" EMTEST_SKIP_RUST: "1" @@ -1228,7 +1228,7 @@ jobs: # tests that depend on those. EMTEST_SKIP_V8: "1" EMTEST_SKIP_WASM_LEGACY_EH: "1" - EMTEST_SKIP_EH: "1" + EMTEST_SKIP_WASM_EH: "1" EMTEST_SKIP_WASM64: "1" EMTEST_SKIP_SCONS: "1" EMTEST_SKIP_RUST: "1" diff --git a/test/common.py b/test/common.py index fe9cc3731855d..22e53ba39640a 100644 --- a/test/common.py +++ b/test/common.py @@ -1146,8 +1146,8 @@ def require_wasm_legacy_eh(self): self.fail('either d8 or node >= 17 required to run legacy wasm-eh tests. Use EMTEST_SKIP_WASM_LEGACY_EH to skip') def require_wasm_eh(self): - if 'EMTEST_SKIP_EH' in os.environ: - self.skipTest('test requires node v24 or d8 (and EMTEST_SKIP_EH is set)') + if 'EMTEST_SKIP_WASM_EH' in os.environ: + self.skipTest('test requires node v24 or d8 (and EMTEST_SKIP_WASM_EH is set)') self.set_setting('WASM_LEGACY_EXCEPTIONS', 0) if self.try_require_node_version(24): self.node_args.append('--experimental-wasm-exnref') @@ -1163,7 +1163,7 @@ def require_wasm_eh(self): self.v8_args.append('--experimental-wasm-exnref') return - self.fail('either d8 or node v24 required to run wasm-eh tests. Use EMTEST_SKIP_EH to skip') + self.fail('either d8 or node v24 required to run wasm-eh tests. Use EMTEST_SKIP_WASM_EH to skip') def require_jspi(self): if 'EMTEST_SKIP_JSPI' in os.environ: