emscripten-core / emscripten-core/emscripten

Increase visibility of --extern-post-js for avoiding onRuntimeInitialized misfires; consider Promisifying onRuntimeInitialized

Open
#12,637 11 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.