emscripten-core / emscripten-core/emscripten
Increase visibility of --extern-post-js for avoiding onRuntimeInitialized misfires; consider Promisifying onRuntimeInitialized
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
It appears that emscripten can trigger intermittent timing issues with onRuntimeInitialized in situations where you have your JS files loading from different scripts. For a simple example, assuming you are using emcc/em++ w/ glue, creating a file like public/js/main.js:
```
Module['onRuntimeInitialized'] = function () {
console.log("RUNTIME RDY!");
};
```
It is often the case that onRuntimeInitialized haas been called before the second script tag has loaded. In my local testing, this initially was very infrequent until I started bundling my non-compiled JS like so:
```
```
In this case, bundle.js became quite large as imported node_modules/, through TypeScript compiler, tsify and browserify are inserted into this single file. This different (milliseconds), led to a 100% fail rate of onRuntimeInitialized ever being called.
Moving js/bundle.js to extern-post-js reduced this to a 0% fail rate. As bundling and transpiling are ever-popular in the JS community, I think the chance of folks bumping into this issue and struggling to find it in the docs is likely. I initially thought maybe I could provide --post-js multiple times, so I went to the emscripten docs and searched post-js, but the search doesn't list something clear to find it ( see: https://emscripten.org/search.html?q=post-js ). Luckily, I knew to click on the "compiler front end" option there to get to it and "discovered" extern-post-js flag.
IMHO to be more JS-friendly, I think onRuntimeInitialized should be a Promise, this way even if it has already been called, it is marked as resolved, so if someone .thens() it (and it is already resolved), it just executes immediately. This is a common convention amongst JS devs, to sort of abuse a resolved promise like this:
```
var p = new Promise((resolve, reject) => resolve(true));
p.then(() => console.log("HI!"))
p.then(() => console.log("HI!"))
```
I imagine the that keeping a resolved promise in memory is not a C/C++ engineer's instinct but it is a pretty common way JS devs will interface with such a thing, *and*, it guarantees that developers can depend on onRuntimeInitialized.
Cheers 🍻 thanks for the mind-bogglingly amazing work on this project!
Contributor guide
Assessment
This issue has not been assessed yet.