From 207c5921745831304cd8e320b01c0962213b8594 Mon Sep 17 00:00:00 2001 From: anutosh491 Date: Thu, 20 Nov 2025 22:58:38 +0530 Subject: [PATCH] Update wasm exception handling model (use wasm-exceptions instead of exceptions) Add tests --- .github/workflows/deploy-github-page.yml | 3 -- .github/workflows/main.yml | 3 -- CMakeLists.txt | 2 + CONTRIBUTING.md | 5 +- README.md | 5 +- docs/source/InstallationAndUsage.rst | 5 +- environment-wasm-build.yml | 4 +- environment-wasm-host.yml | 2 +- .../jupyter/kernels/xc11/wasm_kernel.json.in | 3 +- .../jupyter/kernels/xc17/wasm_kernel.json.in | 3 +- .../jupyter/kernels/xc23/wasm_kernel.json.in | 3 +- .../kernels/xcpp17/wasm_kernel.json.in | 4 +- .../kernels/xcpp20/wasm_kernel.json.in | 4 +- .../kernels/xcpp23/wasm_kernel.json.in | 4 +- test/CMakeLists.txt | 6 +-- test/test_interpreter.cpp | 49 +++++++++++++++++-- 16 files changed, 69 insertions(+), 36 deletions(-) diff --git a/.github/workflows/deploy-github-page.yml b/.github/workflows/deploy-github-page.yml index fc6c728e..c93f4e2c 100644 --- a/.github/workflows/deploy-github-page.yml +++ b/.github/workflows/deploy-github-page.yml @@ -56,9 +56,6 @@ jobs: echo "PREFIX=$PREFIX" >> $GITHUB_ENV export SYSROOT_PATH=$BUILD_PREFIX/opt/emsdk/upstream/emscripten/cache/sysroot - micromamba create -n node-env -c conda-forge nodejs=22 - export PATH="$MAMBA_ROOT_PREFIX/envs/node-env/bin:$PATH" - emcmake cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=$PREFIX \ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 66278c66..c350d297 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -241,9 +241,6 @@ jobs: echo "PREFIX=$PREFIX" >> $GITHUB_ENV export SYSROOT_PATH=$BUILD_PREFIX/opt/emsdk/upstream/emscripten/cache/sysroot - micromamba create -n node-env -c conda-forge nodejs=22 - export PATH="$MAMBA_ROOT_PREFIX/envs/node-env/bin:$PATH" - emcmake cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=$PREFIX \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e1648fd..c2275b56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,6 +219,8 @@ macro(xeus_cpp_set_common_options target_name) target_compile_options(${target_name} PUBLIC /wd4251 /wd4141) target_compile_options(${target_name} PUBLIC /wd4018 /wd4267 /wd4715 /wd4146 /wd4129) target_compile_options(${target_name} PUBLIC /EHsc) + elseif (EMSCRIPTEN) + target_compile_options(${target_name} PUBLIC -fwasm-exceptions) else () target_compile_options(${target_name} PUBLIC -fexceptions) endif () diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7185b7b0..c22fe32d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,7 +71,7 @@ micromamba create -f environment-wasm-build.yml -y micromamba activate xeus-cpp-wasm-build ``` -You are now in a position to build the xeus-cpp kernel. You build and test it in node by executing the following. Prefer using node 22 and above as prior versions lead to flaky test runs. Once the test pass, run the install command. +You are now in a position to build the xeus-cpp kernel. You build and test it in node by executing the following. Once the test pass, run the install command. ```bash micromamba create -f environment-wasm-host.yml --platform=emscripten-wasm32 @@ -81,9 +81,6 @@ export BUILD_PREFIX=$MAMBA_ROOT_PREFIX/envs/xeus-cpp-wasm-build export PREFIX=$MAMBA_ROOT_PREFIX/envs/xeus-cpp-wasm-host export SYSROOT_PATH=$BUILD_PREFIX/opt/emsdk/upstream/emscripten/cache/sysroot -micromamba create -n node-env -c conda-forge nodejs=22 -export PATH="$MAMBA_ROOT_PREFIX/envs/node-env/bin:$PATH" - emcmake cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=$PREFIX \ diff --git a/README.md b/README.md index e7de09c1..e9b9e9f8 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ micromamba create -f environment-wasm-build.yml -y micromamba activate xeus-cpp-wasm-build ``` -You are now in a position to build the xeus-cpp kernel. You build and test it in node by executing the following. Prefer using node 22 and above as prior versions lead to flaky test runs. Once the test pass, run the install command. +You are now in a position to build the xeus-cpp kernel. You build and test it in node by executing the following. Once the test pass, run the install command. ```bash micromamba create -f environment-wasm-host.yml --platform=emscripten-wasm32 mkdir build @@ -97,9 +97,6 @@ export BUILD_PREFIX=$MAMBA_ROOT_PREFIX/envs/xeus-cpp-wasm-build export PREFIX=$MAMBA_ROOT_PREFIX/envs/xeus-cpp-wasm-host export SYSROOT_PATH=$BUILD_PREFIX/opt/emsdk/upstream/emscripten/cache/sysroot -micromamba create -n node-env -c conda-forge nodejs=22 -export PATH="$MAMBA_ROOT_PREFIX/envs/node-env/bin:$PATH" - emcmake cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=$PREFIX \ diff --git a/docs/source/InstallationAndUsage.rst b/docs/source/InstallationAndUsage.rst index e3b95a25..690d4dd4 100644 --- a/docs/source/InstallationAndUsage.rst +++ b/docs/source/InstallationAndUsage.rst @@ -66,7 +66,7 @@ the following micromamba create -f environment-wasm-build.yml -y micromamba activate xeus-cpp-wasm-build -You are now in a position to build the xeus-cpp kernel. You build and test it in node by executing the following. Prefer using node 22 and above as prior versions lead to flaky test runs. Once the test pass, run the install command. +You are now in a position to build the xeus-cpp kernel. You build and test it in node by executing the following. Once the test pass, run the install command. .. code-block:: bash @@ -77,9 +77,6 @@ You are now in a position to build the xeus-cpp kernel. You build and test it in export PREFIX=$MAMBA_ROOT_PREFIX/envs/xeus-cpp-wasm-host export SYSROOT_PATH=$BUILD_PREFIX/opt/emsdk/upstream/emscripten/cache/sysroot - micromamba create -n node-env -c conda-forge nodejs=22 - export PATH="$MAMBA_ROOT_PREFIX/envs/node-env/bin:$PATH" - emcmake cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=$PREFIX \ diff --git a/environment-wasm-build.yml b/environment-wasm-build.yml index cf716ed5..be953293 100644 --- a/environment-wasm-build.yml +++ b/environment-wasm-build.yml @@ -1,7 +1,7 @@ name: xeus-cpp-wasm-build channels: - - https://prefix.dev/emscripten-forge-dev + - https://prefix.dev/emscripten-forge-4x - https://prefix.dev/conda-forge dependencies: - cmake - - emscripten_emscripten-wasm32==3.1.73 \ No newline at end of file + - emscripten_emscripten-wasm32==4.0.9 \ No newline at end of file diff --git a/environment-wasm-host.yml b/environment-wasm-host.yml index 54aa77ca..0230026c 100644 --- a/environment-wasm-host.yml +++ b/environment-wasm-host.yml @@ -1,6 +1,6 @@ name: xeus-cpp-wasm-host channels: - - https://prefix.dev/emscripten-forge-dev + - https://prefix.dev/emscripten-forge-4x - https://prefix.dev/conda-forge dependencies: - nlohmann_json diff --git a/share/jupyter/kernels/xc11/wasm_kernel.json.in b/share/jupyter/kernels/xc11/wasm_kernel.json.in index 009f8a98..a6ea1929 100644 --- a/share/jupyter/kernels/xc11/wasm_kernel.json.in +++ b/share/jupyter/kernels/xc11/wasm_kernel.json.in @@ -6,7 +6,8 @@ "-Xclang", "-iwithsysroot/include/compat", "-xc", "-std=c11", - "-mllvm", "-enable-emscripten-sjlj", + "-fwasm-exceptions", + "-mllvm", "-wasm-enable-sjlj", "-msimd128" ], "language": "c", diff --git a/share/jupyter/kernels/xc17/wasm_kernel.json.in b/share/jupyter/kernels/xc17/wasm_kernel.json.in index 4d6e92a4..d55a4b59 100644 --- a/share/jupyter/kernels/xc17/wasm_kernel.json.in +++ b/share/jupyter/kernels/xc17/wasm_kernel.json.in @@ -6,7 +6,8 @@ "-Xclang", "-iwithsysroot/include/compat", "-xc", "-std=c17", - "-mllvm", "-enable-emscripten-sjlj", + "-fwasm-exceptions", + "-mllvm", "-wasm-enable-sjlj", "-msimd128" ], "language": "c", diff --git a/share/jupyter/kernels/xc23/wasm_kernel.json.in b/share/jupyter/kernels/xc23/wasm_kernel.json.in index 9913d6ea..c733cd3e 100644 --- a/share/jupyter/kernels/xc23/wasm_kernel.json.in +++ b/share/jupyter/kernels/xc23/wasm_kernel.json.in @@ -6,7 +6,8 @@ "-Xclang", "-iwithsysroot/include/compat", "-xc", "-std=c23", - "-mllvm", "-enable-emscripten-sjlj", + "-fwasm-exceptions", + "-mllvm", "-wasm-enable-sjlj", "-msimd128" ], "language": "c", diff --git a/share/jupyter/kernels/xcpp17/wasm_kernel.json.in b/share/jupyter/kernels/xcpp17/wasm_kernel.json.in index a8de4ed0..bcd75ded 100644 --- a/share/jupyter/kernels/xcpp17/wasm_kernel.json.in +++ b/share/jupyter/kernels/xcpp17/wasm_kernel.json.in @@ -4,8 +4,8 @@ "@XEUS_CPP_KERNELSPEC_PATH@xcpp", "-resource-dir", "/lib/clang/@CPPINTEROP_LLVM_VERSION_MAJOR@", "-Xclang", "-iwithsysroot/include/compat", - "-std=c++17", "-mllvm", "-enable-emscripten-cxx-exceptions", - "-mllvm", "-enable-emscripten-sjlj", "-msimd128" + "-std=c++17", "-fwasm-exceptions", + "-mllvm", "-wasm-enable-sjlj", "-msimd128" ], "language": "cpp", "metadata": { diff --git a/share/jupyter/kernels/xcpp20/wasm_kernel.json.in b/share/jupyter/kernels/xcpp20/wasm_kernel.json.in index a36fa59b..b7cfd673 100644 --- a/share/jupyter/kernels/xcpp20/wasm_kernel.json.in +++ b/share/jupyter/kernels/xcpp20/wasm_kernel.json.in @@ -4,8 +4,8 @@ "@XEUS_CPP_KERNELSPEC_PATH@xcpp", "-resource-dir", "/lib/clang/@CPPINTEROP_LLVM_VERSION_MAJOR@", "-Xclang", "-iwithsysroot/include/compat", - "-std=c++20", "-mllvm", "-enable-emscripten-cxx-exceptions", - "-mllvm", "-enable-emscripten-sjlj", "-msimd128" + "-std=c++20", "-fwasm-exceptions", + "-mllvm", "-wasm-enable-sjlj", "-msimd128" ], "language": "cpp", "metadata": { diff --git a/share/jupyter/kernels/xcpp23/wasm_kernel.json.in b/share/jupyter/kernels/xcpp23/wasm_kernel.json.in index 3fdd0422..960a7963 100644 --- a/share/jupyter/kernels/xcpp23/wasm_kernel.json.in +++ b/share/jupyter/kernels/xcpp23/wasm_kernel.json.in @@ -4,8 +4,8 @@ "@XEUS_CPP_KERNELSPEC_PATH@xcpp", "-resource-dir", "/lib/clang/@CPPINTEROP_LLVM_VERSION_MAJOR@", "-Xclang", "-iwithsysroot/include/compat", - "-std=c++23", "-mllvm", "-enable-emscripten-cxx-exceptions", - "-mllvm", "-enable-emscripten-sjlj", "-msimd128" + "-std=c++23", "-fwasm-exceptions", + "-mllvm", "-wasm-enable-sjlj", "-msimd128" ], "language": "cpp", "metadata": { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 01c013ba..b74d2d28 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -54,7 +54,7 @@ if(EMSCRIPTEN) target_link_libraries(test_xeus_cpp PRIVATE xeus-cpp-static doctest::doctest) target_compile_options(test_xeus_cpp - PUBLIC "SHELL: -fexceptions" + PUBLIC "SHELL: -fwasm-exceptions" ) # So we create a html file, as well as the javascript file set_target_properties(test_xeus_cpp PROPERTIES @@ -67,10 +67,10 @@ if(EMSCRIPTEN) # Without this MINIFY_HTML=0 flag you end up with the situation where the creation of the # test_xeus_cpp.html file breaks on MacOS, but not Ubuntu target_link_options(test_xeus_cpp - PUBLIC "SHELL: -fexceptions" + PUBLIC "SHELL: -fwasm-exceptions" PUBLIC "SHELL: -s MAIN_MODULE=1" PUBLIC "SHELL: -s WASM_BIGINT" - PUBLIC "SHELL: -s ASSERTIONS=1" + PUBLIC "SHELL: -s ASSERTIONS=0" PUBLIC "SHELL: -s ALLOW_MEMORY_GROWTH=1" PUBLIC "SHELL: -s STACK_SIZE=32mb" PUBLIC "SHELL: -s INITIAL_MEMORY=128mb" diff --git a/test/test_interpreter.cpp b/test/test_interpreter.cpp index 3c66443b..45c1888d 100644 --- a/test/test_interpreter.cpp +++ b/test/test_interpreter.cpp @@ -70,7 +70,10 @@ TEST_SUITE("execute_request") { TEST_CASE("stl") { - std::vector Args = {"stl-test-case", "-v"}; + std::vector Args = { + "-v", + "-Xclang", "-iwithsysroot/include/compat" + }; xcpp::interpreter interpreter((int)Args.size(), Args.data()); std::string code = "#include "; nl::json user_expressions = nl::json::object(); @@ -99,7 +102,6 @@ TEST_SUITE("execute_request") REQUIRE(result["status"] == "ok"); } -#if defined(XEUS_CPP_EMSCRIPTEN_WASM_BUILD) TEST_CASE("headers found in sysroot/include/compat") { std::vector Args = { @@ -124,6 +126,44 @@ TEST_SUITE("execute_request") promise.set_value(result); }; + interpreter.execute_request( + std::move(context), + std::move(callback), + code, + std::move(config), + user_expressions + ); + nl::json result = future.get(); + REQUIRE(result["status"] == "ok"); + } + +#if defined(XEUS_CPP_EMSCRIPTEN_WASM_BUILD) + TEST_CASE("Emscripten Exception Handling") + { + std::vector Args = { + "-std=c++20", + "-v", + "-fwasm-exceptions", + "-mllvm", "-wasm-enable-sjlj" + }; + + xcpp::interpreter interpreter((int)Args.size(), Args.data()); + std::string code = "try { throw 1; } catch (...) { 0; }"; + nl::json user_expressions = nl::json::object(); + xeus::execute_request_config config; + config.silent = false; + config.store_history = false; + config.allow_stdin = false; + nl::json header = nl::json::object(); + xeus::xrequest_context::guid_list id = {}; + xeus::xrequest_context context(header, id); + + std::promise promise; + std::future future = promise.get_future(); + auto callback = [&promise](nl::json result) { + promise.set_value(result); + }; + interpreter.execute_request( std::move(context), std::move(callback), @@ -810,7 +850,10 @@ TEST_SUITE("complete_request") { TEST_CASE("completion_test") { - std::vector Args = {/*"-v", "resource-dir", "....."*/}; + std::vector Args = { + "-v", + "-Xclang", "-iwithsysroot/include/compat" + }; xcpp::interpreter interpreter((int)Args.size(), Args.data()); std::string code1 = "#include "; nl::json user_expressions = nl::json::object();