The post shows a scene brower crashed without error log.
Here is a cpp interface exposed to typescript.
void Worker::ShowMyself(int value)
{
std::cout << "I am a Worker: " << value << std::endl;
}
As we know, the JS code generated by emsdk has checked the parameters of interfaces. If there is invalid invoking from web, throwBindingError
in the JS code will work.
If your code is completely synchronous, any error that is not caught by try…catch will be immediately printed to the console and usually halt script execution.
How about async invoking logic?
App.tsx:
import { createWorker2 } from './workerUtils.ts'; // Import the new function
//...
const handleCreateWorkerAsync2 = () => {
createWorker2(wasmModule, setWorkerCount)
.then((val) => {})
.catch((error) => { // if we catch here and don't output log, the browser will just hang and not show any error log on the console
//console.error("createWorker2 error: ", error)
})
};
workerUtils.ts:
// Define the interface for the WASM module
interface WasmModule {
Worker: {
new(): any;
};
worker: Worker;
}
// Async function to create a new Worker instance
export const createWorker2 = async (wasmModule: WasmModule | null, setWorkerCount: React.Dispatch<React.SetStateAction<number>>) => {
if (!wasmModule) {
const error = 'WASM module not loaded yet';
console.error(error);
throw new Error(error);
}
const cppObj = new wasmModule.Worker();
console.log('Worker created asynchronously:', cppObj);
setWorkerCount(prev => prev + 1);
wasmModule.worker = cppObj; // Store the Worker instance in the wasmModule
wasmModule.worker.ShowMyself();
};
If there is async function createWorker2, and it returns a Promise. When the wasm interface throws an error, this error will bubble up, causing the Promise returned by createWorker2 to be rejected.
.
If the .catch()
Promise is called at the place where createWorker2
is invoked but no information is output, or if your global unhandledrejection
listener blocks the default console output, you won’t see this error. It didn’t disappear; it just didn’t show up in the way you expected.
Summary: It is highly likely that an error was caught but no specific information was output in our code~

Add console.error in catch block:
const handleCreateWorkerAsync2 = () => {
createWorker2(wasmModule, setWorkerCount)
.then((val) => {})
.catch((error) => { // if we catch here and don't output log, the browser will just hang and not show any error log on the console
console.error("createWorker2 error: ", error)
})
};

.
{
"name": "BindingError",
"message": "function Worker.ShowMyself called with 0 arguments, expected 1 args!",
"stack": "BindingError: function Worker.ShowMyself called with 0 arguments, expected 1 args!\n at BindingError.<anonymous> (<anonymous>:9:27749)\n at new BindingError (eval at createNamedFunction (:9:27458), <anonymous>:4:34)\n at throwBindingError (<anonymous>:9:28190)\n at Worker.Worker$ShowMyself [as ShowMyself] (eval at new_ (:9:47974), <anonymous>:5:1)\n at createWorker2 (http://localhost:3001/static/js/bundle.js:36698:21)\n at handleCreateWorkerAsync2 (http://localhost:3001/main.9dd8a6f91e4456050ae0.hot-update.js:101:67)\n at HTMLUnknownElement.callCallback (http://localhost:3001/static/js/bundle.js:6392:18)\n at Object.invokeGuardedCallbackDev (http://localhost:3001/static/js/bundle.js:6436:20)\n at invokeGuardedCallback (http://localhost:3001/static/js/bundle.js:6493:35)\n at invokeGuardedCallbackAndCatchFirstError (http://localhost:3001/static/js/bundle.js:6507:29)"
}
All code has been uploaded to GitHub:
https://github.com/theArcticOcean/tutorials/tree/main/learnWebAssembly/wrong-wasm-interface