mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-04-30 19:09:26 +08:00
ChaiScript relies heavily on C++ exceptions for error propagation, but the Emscripten build was missing the -fwasm-exceptions flag. Without it, any C++ exception in the WASM module causes an abort instead of being catchable by JavaScript. Added -fwasm-exceptions as both a compile and link option, and added a regression test verifying exception propagation through the eval wrapper functions. Co-authored-by: leftibot <leftibot@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e61be76531
commit
0fd9cab654
@ -440,6 +440,10 @@ if(BUILD_TESTING)
|
|||||||
target_link_libraries(emscripten_eval_test ${LIBS})
|
target_link_libraries(emscripten_eval_test ${LIBS})
|
||||||
add_test(NAME Emscripten_Eval_Test COMMAND emscripten_eval_test)
|
add_test(NAME Emscripten_Eval_Test COMMAND emscripten_eval_test)
|
||||||
|
|
||||||
|
add_executable(emscripten_exception_test unittests/emscripten_exception_test.cpp)
|
||||||
|
target_link_libraries(emscripten_exception_test ${LIBS})
|
||||||
|
add_test(NAME Emscripten_Exception_Test COMMAND emscripten_exception_test)
|
||||||
|
|
||||||
add_executable(threading_config_test unittests/threading_config_test.cpp)
|
add_executable(threading_config_test unittests/threading_config_test.cpp)
|
||||||
target_link_libraries(threading_config_test ${LIBS})
|
target_link_libraries(threading_config_test ${LIBS})
|
||||||
add_test(NAME Threading_Config_Test COMMAND threading_config_test)
|
add_test(NAME Threading_Config_Test COMMAND threading_config_test)
|
||||||
|
|||||||
@ -17,9 +17,14 @@ add_definitions(-DCHAISCRIPT_NO_THREADS -DCHAISCRIPT_NO_DYNLOAD)
|
|||||||
add_executable(chaiscript chaiscript_em.cpp)
|
add_executable(chaiscript chaiscript_em.cpp)
|
||||||
target_include_directories(chaiscript PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include)
|
target_include_directories(chaiscript PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include)
|
||||||
|
|
||||||
|
# Enable WASM exception handling — ChaiScript relies on C++ exceptions for
|
||||||
|
# error propagation; without this flag exceptions cause an abort in WASM.
|
||||||
|
target_compile_options(chaiscript PRIVATE -fwasm-exceptions)
|
||||||
|
|
||||||
# Emscripten link flags: enable embind, allow memory growth, export as ES module-compatible
|
# Emscripten link flags: enable embind, allow memory growth, export as ES module-compatible
|
||||||
target_link_options(chaiscript PRIVATE
|
target_link_options(chaiscript PRIVATE
|
||||||
--bind
|
--bind
|
||||||
|
-fwasm-exceptions
|
||||||
-sALLOW_MEMORY_GROWTH=1
|
-sALLOW_MEMORY_GROWTH=1
|
||||||
-sEXPORT_ES6=0
|
-sEXPORT_ES6=0
|
||||||
-sMODULARIZE=0
|
-sMODULARIZE=0
|
||||||
|
|||||||
72
unittests/emscripten_exception_test.cpp
Normal file
72
unittests/emscripten_exception_test.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// Test that validates exception propagation through the Emscripten eval wrapper.
|
||||||
|
// Without proper exception support flags (-fwasm-exceptions) in the WASM build,
|
||||||
|
// C++ exceptions would cause an abort instead of being catchable.
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_NO_THREADS
|
||||||
|
#define CHAISCRIPT_NO_THREADS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||||
|
#define CHAISCRIPT_NO_DYNLOAD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <chaiscript/chaiscript.hpp>
|
||||||
|
#include "../emscripten/chaiscript_eval.hpp"
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// Verify that ChaiScript evaluation errors propagate as exceptions
|
||||||
|
// through the eval wrapper functions. In WASM builds without exception
|
||||||
|
// support, these would abort instead of throwing.
|
||||||
|
|
||||||
|
bool caught = false;
|
||||||
|
|
||||||
|
// Test 1: eval with undefined variable should throw
|
||||||
|
caught = false;
|
||||||
|
try {
|
||||||
|
chaiscript_eval("this_variable_does_not_exist");
|
||||||
|
} catch (const chaiscript::exception::eval_error &) {
|
||||||
|
caught = true;
|
||||||
|
}
|
||||||
|
assert(caught && "eval of undefined variable must throw eval_error");
|
||||||
|
|
||||||
|
// Test 2: evalString with a type mismatch should throw
|
||||||
|
caught = false;
|
||||||
|
try {
|
||||||
|
chaiscript_eval_string("1 + 2");
|
||||||
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||||
|
caught = true;
|
||||||
|
}
|
||||||
|
assert(caught && "evalString with non-string result must throw bad_boxed_cast");
|
||||||
|
|
||||||
|
// Test 3: evalInt with invalid syntax should throw
|
||||||
|
caught = false;
|
||||||
|
try {
|
||||||
|
chaiscript_eval_int("def {}");
|
||||||
|
} catch (const chaiscript::exception::eval_error &) {
|
||||||
|
caught = true;
|
||||||
|
}
|
||||||
|
assert(caught && "evalInt with syntax error must throw eval_error");
|
||||||
|
|
||||||
|
// Test 4: eval with throw statement should propagate exception
|
||||||
|
caught = false;
|
||||||
|
try {
|
||||||
|
chaiscript_eval("throw(\"user exception\")");
|
||||||
|
} catch (const chaiscript::Boxed_Value &) {
|
||||||
|
caught = true;
|
||||||
|
} catch (...) {
|
||||||
|
caught = true;
|
||||||
|
}
|
||||||
|
assert(caught && "ChaiScript throw must propagate as an exception");
|
||||||
|
|
||||||
|
// Test 5: Verify normal operation still works after caught exceptions
|
||||||
|
chaiscript_eval("var post_exception_test = 100");
|
||||||
|
const int result = chaiscript_eval_int("post_exception_test");
|
||||||
|
assert(result == 100 && "normal eval must work after caught exceptions");
|
||||||
|
|
||||||
|
std::cout << "All emscripten exception tests passed.\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user