diff --git a/.circleci/config.yml b/.circleci/config.yml index 72d3c7bf017c4..179ea692e2954 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1190,7 +1190,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_EH: "1" EMTEST_SKIP_WASM64: "1" EMTEST_SKIP_SCONS: "1" EMTEST_SKIP_RUST: "1" @@ -1226,7 +1227,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_EH: "1" EMTEST_SKIP_WASM64: "1" EMTEST_SKIP_SCONS: "1" EMTEST_SKIP_RUST: "1" diff --git a/ChangeLog.md b/ChangeLog.md index 4788c9e13cdee..d22df7fda65b3 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -322,7 +322,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 1c16446953d68..2f81a0ea647fc 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 Wasm +// 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/codesize/test_codesize_cxx_except_wasm.json b/test/codesize/test_codesize_cxx_except_wasm.json index 6ac496e63b2eb..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": 19555, - "a.out.js.gz": 8099, + "a.out.js": 19486, + "a.out.js.gz": 8077, "a.out.nodebug.wasm": 144630, "a.out.nodebug.wasm.gz": 54894, - "total": 164185, - "total_gz": 62993, + "total": 164116, + "total_gz": 62971, "sent": [ "_abort_js", "_tzset_js", diff --git a/test/common.py b/test/common.py index cc38eb8f85cf3..22e53ba39640a 100644 --- a/test/common.py +++ b/test/common.py @@ -1130,8 +1130,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_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)') + self.set_setting('WASM_LEGACY_EXCEPTIONS') if self.try_require_node_version(17): return @@ -1142,11 +1143,11 @@ def require_wasm_legacy_eh(self): self.js_engines = [v8] return - 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): - 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') @@ -1162,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: diff --git a/test/test_other.py b/test/test_other.py index 5a510607b098a..c38a71ef9eb38 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -3644,7 +3644,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. @@ -14332,10 +14332,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. diff --git a/tools/feature_matrix.py b/tools/feature_matrix.py index 2839d32f10f21..7b2051495b829 100644 --- a/tools/feature_matrix.py +++ b/tools/feature_matrix.py @@ -40,6 +40,8 @@ class Feature(IntEnum): MEMORY64 = auto() WORKER_ES6_MODULES = auto() OFFSCREENCANVAS_SUPPORT = auto() + WASM_LEGACY_EXCEPTIONS = auto() + WASM_EXCEPTIONS = auto() disable_override_features = set() @@ -105,6 +107,26 @@ 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. + Feature.WASM_LEGACY_EXCEPTIONS: { + 'chrome': 95, + 'firefox': 100, + 'safari': 150200, + 'node': 170000, + }, + # Wasm exceptions is a newer format for native exception handling in + # WebAssembly. + Feature.WASM_EXCEPTIONS: { + 'chrome': 137, + 'firefox': 131, + 'safari': 180400, + # Supported with flag --experimental-wasm-exnref (TODO: Change this to + # 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, + }, } # Static assertion to check that we actually need each of the above feature flags @@ -165,7 +187,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. logger.debug(f'Enabling {name}={min_version} to accommodate {reason}') @@ -199,3 +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 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)')