Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,6 @@ jobs:
test -f nec2pp.js
test -f nec2pp.wasm
echo "WASM artifacts present: $(ls -la nec2pp.js nec2pp.wasm)"

- name: WASM runtime smoke test
run: node tests/wasm_smoke.js nec2pp.js
6 changes: 6 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,15 @@ if(NECPP_BUILD_WASM)
${CMAKE_CURRENT_SOURCE_DIR}
${NECPP_EIGEN_DIR}
${CMAKE_BINARY_DIR})
# Emscripten disables exception catching by default. nec_context throws to
# unwind a finished solve, so without this the catch is elided and every
# completed run escapes as an uncaught error. Needed at compile, not just
# link: the link flag cannot restore a catch already dropped.
target_compile_options(nec2pp_wasm PRIVATE -fexceptions)
# Flags carried verbatim from the old Makefile wasm target.
target_link_options(nec2pp_wasm PRIVATE
-sWASM=1
-fexceptions
"-sEXPORTED_FUNCTIONS=[\"_nec_create_context\",\"_nec_delete_context\",\"_nec_process_input\",\"_nec_get_output\",\"_nec_get_output_length\",\"_nec_free\"]"
"-sEXPORTED_RUNTIME_METHODS=[\"ccall\",\"cwrap\",\"UTF8ToString\",\"lengthBytesUTF8\"]"
-sALLOW_MEMORY_GROWTH=1
Expand Down
48 changes: 48 additions & 0 deletions tests/wasm_smoke.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Runtime smoke test for the Emscripten build (nec2pp.js + nec2pp.wasm).
//
// Usage: node tests/wasm_smoke.js [path/to/nec2pp.js]
//
// Feeds nec_process_input a deck that makes the geometry parser throw a
// nec_exception and checks it comes back as rc -2 with the message in the
// output buffer. If the build lacks C++ exception catching, the throw
// escapes into JS instead and this test fails.
//
// nec_process_input is still a stub that parses geometry from stdin rather
// than from its input string, so stdin is set to EOF here.
'use strict';

const path = require('path');

const jsPath = path.resolve(process.argv[2] || 'nec2pp.js');
const M = require(jsPath);

function fail(msg) {
console.error('FAIL: ' + msg);
process.exit(1);
}

M.stdin = () => null;
M.onAbort = (what) => fail('module aborted: ' + what);
M.onRuntimeInitialized = () => {
const ctx = M.ccall('nec_create_context', 'number', [], []);
if (!ctx)
fail('nec_create_context returned null');

let rc;
try {
rc = M.ccall('nec_process_input', 'number', ['number', 'string'],
[ctx, 'CE\nEN\n']);
} catch (e) {
fail('nec_process_input threw into JS (exception catching disabled?): ' + e);
}

const out = M.UTF8ToString(M.ccall('nec_get_output', 'number', ['number'], [ctx]));
M.ccall('nec_delete_context', null, ['number'], [ctx]);

if (rc !== -2)
fail('expected rc -2, got ' + rc + ' (output: ' + JSON.stringify(out) + ')');
if (!out.startsWith('Error: GEOMETRY DATA CARD ERROR'))
fail('unexpected output: ' + JSON.stringify(out));

console.log('WASM smoke test passed: ' + out);
};
Loading