-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
entire source of module printed when nodejs exception thrown #17228
Comments
Trying to reproduce this, the following works:
I have no idea why node would print the contents of an imported package like that... the error isn't even in the same file! The stack trace even shows that. How bizarre... removing the module import line, the behavior is as expected. Just importing that module, not even using it, is enough to make node print it on an unrelated exception. I'm not sure how to even debug that. Advice from any node experts reading this would be very welcome... |
I can't reproduce this when generating the imported module. For example,
That emits an index.js that, when imported here, does not cause the bug. I tried lots of variations on those flags (which emit something in the same general shape as the binaryen build from npm). If so then perhaps this is specific to |
Did you try calling the default export/making it actually load the wasm? I think it getting interrupted while instantiating the wasm module could be the problem. For whatever reason I'm getting an error with the // required due to bug?
global.__dirname = '/tmp';
// /tmp/lib.mjs was generated via the following:
// emcc tests/hello_world.c -s EXPORT_ES6 -o /tmp/lib.mjs -O3 --closure 1 -s SINGLE_FILE -s MODULARIZE
import test from '/tmp/lib.mjs';
// Load module
console.log(test); // [Function (anonymous)]
test();
// Generate fatal error
let s = 'aaaaaa';
s(111111); Versions and system info is as follows:
The problem stemming from loading wasm would make sense as the index.js file in binaryen.js ends with It's honestly quite likely that this is a bug with node where it was loading things concurrently and highlights the line of code where both were at before the main thread crashed... I'm gonna have to disect the output js |
I have also seen this issue when using Binaryen.js specifically. What appears to happen is that recent versions of Node.js try to print the source code location of where the Error was generated, in turn printing the entire minified JS produced by Emscripten - I guess because it's all a single line. As a workaround, I have found that the issue can be mitigated by running Node.js with |
Interesting. Ok, given that, it would be great if we could make as small a testcase as possible and file a node.js issue with it for them to look at. If we can't reduce it, all of |
This is probably a duplicate of #11532 and #14270, could you try to add Lines 733 to 751 in 854adf6
|
I had the same problem using embind 3.1.23 on NodeJs 18.12: the solution suggested above works for me. |
I confirmed that this is no longer and issue after #18743 since we no longer enable @decodio, I'm a little confused by the fact that you say this problem was mitigated by passing Regardless, I think this issue can now be closed. For folks that don't use |
I can tell for certain that the Node.js flag makes a difference, but I also don't know why exactly. Perhaps it is merely a side-effect of making Node look for a source map in the first place, then suppressing the longish source output, or it only applies to cases where the application that imports Binaryen utilizes source maps itself. Happy if there is a better way, of course :) |
I think this can now be closed |
Hi everyone, I am really struggling with this issue. I am not using emscripten directly, but I am using binaryen.js with This issue keeps happening and I've forked In fact I just tested this without Here's my code import "binaryen";
throw new Error("Should not see all of the code above");
{
"type": "module",
"dependencies": {
"binaryen": "^116.0.0"
}
} Run String("utf-8"):g=null}else typeof window!="undefined"&&typeof window.prompt=="function"?(g=window.prompt("Input: "),g!==null&&(g+=`
Error: Should not see all of the code above
at file:///home/lastmjs/development/test/test_tsx/index.js:3:7
Node.js v20.11.0 |
Presumably this is because the published version of I'm not very familiar with npm best practices but perhaps the JavaScript in npm itself should not be minified and it should be up to users/blunders of binaryen.js to minify the JS? Is it normal to ship minified JS in npm? |
Hmm, I can't reproduce this when I build locally. But I do see it with the npm version. So as @sbc100 said above,
That should have fixed it. And it looks fixed when I build locally in the normal way (as Binaryen does on CI):
The resulting file is 1.65% smaller than the npm build, and it doesn't have the problem. To make sure I am comparing them in the most similar way, I copied the build's JS over the @dcodeIO is the npm build made with different flags? |
@kripken the npm version runs esbuild to bundle a small wrapper file that instantiates and re-exports Binaryen using top-level-await. |
Thanks @CountBleck, that explains what I was seeing - without that await, my version wasn't actually being run. Now that I have that working, I do see that some of the binaryen.js code is quoted in the stack trace even in my build. I see actually a lot less code quoted, because the minified npm build has 9 newlines but the raw emcc optimized output has 477, so it is slightly less minified. (I believe that is intentional in Emscripten, we leave newlines as separators where possible instead of I then confirmed @kleisauke 's suggestion that those two flags @sbc100 you say those flags should not be needed in MODULARIZE mode since some point in time, but we don't seem to use that flag in binaryen.js - I suppose the modularization is done by the bundler or something else, so those flags are needed. |
…#6764) Fixes emscripten-core/emscripten#17228 This seems the right default in binaryen.js which is used as a library through npm mostly. We aren't a main program that wants to control node exclusively.
With WebAssembly/binaryen#6764 landed, this should be fixed in the next build of binaryen.js. |
Hmm, is this correct Node.js behavior though? |
It turns out that there are very few test cases where it helps to enable this settings, so disabling by default makes sense. Fixes: emscripten-core#17228
It turns out that this setting is only needed in very specific circumstances. Specifically its only needed if native code calls `exit` a callback that was not wrapped in callUserCallback. This change removes the need for this setting from all our unit tests and disables the setting by default. Fixes: emscripten-core#17228
It turns out that this setting is only needed in very specific circumstances. Specifically its only needed if native code calls `exit` a callback that was not wrapped in callUserCallback. This change removes the need for this setting from all our unit tests and disables the setting by default. Fixes: emscripten-core#17228
While the stacktrace does remain intact on rethrow (only you throw something that is subclass of Error though), the line that gets printed before the stacktrace is thrown seems to be the rethrow line, and not the original line:
Note that line 8 of the file (the rethrow) is printed and not line 3 (the original throw). If you throw something that isn't an Error subclass all traces of the original throw location seem to be lost in a rethrow. |
I'm uploaded a PR to disable this catching by default: #22257 We could followup by completely removing it I think. |
@sbc100 yeah, I'm observing the same thing. |
It turns out that this setting is only needed in very specific circumstances. Specifically its only needed if native code calls `exit` a callback that was not wrapped in callUserCallback. This change removes the need for this setting from all our unit tests and disables the setting by default. Fixes: emscripten-core#17228
It turns out that this setting is only needed in very specific circumstances. Specifically its only needed if native code calls `exit` a callback that was not wrapped in callUserCallback. This change removes the need for this setting from all our unit tests and disables the setting by default. Fixes: emscripten-core#17228
It turns out that this setting is only needed in very specific circumstances. Specifically its only needed if native code calls `exit` a callback that was not wrapped in callUserCallback. This change removes the need for this setting from all our unit tests and disables the setting by default. Fixes: emscripten-core#17228
It turns out that this setting is only needed in very specific circumstances. Specifically its only needed if native code calls `exit` a callback that was not wrapped in callUserCallback. This change removes the need for this setting from all our unit tests and disables the setting by default. Fixes: emscripten-core#17228
It turns out that this setting is only needed in very specific circumstances. Specifically its only needed if native code calls `exit` a callback that was not wrapped in callUserCallback. This change removes the need for this setting from all our unit tests and disables the setting by default. Fixes: emscripten-core#17228
It turns out that this setting is only needed in very specific circumstances. Specifically its only needed if native code calls `exit` a callback that was not wrapped in callUserCallback. This change removes the need for this setting from all our unit tests and disables the setting by default. Fixes: emscripten-core#17228
It turns out that this setting is only needed in very specific circumstances. Specifically its only needed if native code calls `exit` a callback that was not wrapped in callUserCallback. This change removes the need for this setting from all our unit tests and disables the setting by default. Fixes: emscripten-core#17228
It turns out that this setting is only needed in very specific circumstances. Specifically its only needed if native code calls `exit` a callback that was not wrapped in callUserCallback. This change removes the need for this setting from all our unit tests and disables the setting by default. Fixes: emscripten-core#17228
It turns out that this setting is only needed in very specific circumstances. Specifically its only needed if native code calls `exit` a callback that was not wrapped in callUserCallback. This change removes the need for this setting from all our unit tests and disables the setting by default. Fixes: emscripten-core#17228
It turns out that this setting is only needed in very specific circumstances. Specifically its only needed if native code calls `exit` a callback that was not wrapped in callUserCallback. This change removes the need for this setting from all our unit tests and disables the setting by default. Fixes: #17228
I'm still facing this issue despite setting EMCC_CORES=4
CFLAGS="-O3 -fexceptions"
emcc ./native/usr/lib/libgeos.a ./native/usr/lib/libgeos_c.a -o ./package/geos.js\
-O3 --closure 1 -s SINGLE_FILE=1 -s ALLOW_TABLE_GROWTH=1 -s ERROR_ON_UNDEFINED_SYMBOLS=1\
-s FORCE_FILESYSTEM=0 -s ALLOW_MEMORY_GROWTH=1 -s DISABLE_EXCEPTION_CATCHING=0\
-s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 -s WASM=1 -s EXPORT_ES6=1\
-s MODULARIZE=1 -s 'EXPORT_NAME="CModule"'\
-s EXPORTED_FUNCTIONS="[ '... exported functions ...' ]"\
-s EXPORTED_RUNTIME_METHODS="[ 'addFunction', 'removeFunction', 'setValue', 'getValue', 'ccall', 'cwrap', 'UTF8ToString', 'stringToUTF8' ]" Link to repo with install instructions for reproducability When an error is thrown, I get the correct error and stack trace, yet the entire module is printed before the error: Building with |
I believe this is simply due to the fact that we minify the code so that its all on a single line. Assume that its node itself that is printing this exception (is that correct?) then I'm not sure there is much you can do other than maybe not minifying? You can disable minification with If the exception is being printed by emscripten code itself its possible we could do something, but I think this exception is escaping to the top level, right? |
Thanks for your reply @sbc100! I've been checking again and you're right, node tries to print the line that threw the error, which is part of my library but outside of the binaryen code itself. Since the library is eventually minified to a single line using @rollup/terser still the entire source code is being printed. So in fact nothing that could be changed on the emscripten side! Looking through the terser docs, I found the // ... rollup.config.js
plugins: [
terser({
format: {
semicolons: false
}
})
] With the additional newlines the wall of text vanishes when an uncaught exception occurs! As the docs state, the only downside is that the gzipped bundle sizes might increase insignificantly though. In my case it grew from 782 KB to 783 KB (2.6 MB uncompressed), so indeed insignificantly. Definitely worth not having the console spammed with the entire source code! Leaving this here in case someone stumbles into the same issue. |
In emscripten we use the |
I see, thanks for the explanation! I was expecting the |
This has been an issue that I've experienced with various packages built with emscripten since 2019 and honestly surprised it's still there. It's one of the biggest painpoints of working with emscripten + node.js for me personally
running the above code via
node index.js
results in the following message (which takes several seconds to print) and appears to be generated by emscriptenI've experienced this exact problem with every emscripten package I've used including internal ones at previous company so I don't think this is the fault of the package maintainers.
The text was updated successfully, but these errors were encountered: