kripken/emscripten — pull request #1273 by inolen (2013-06-10 00:09:28+00:00)
Title: startup refactoring redux

Alright, I took the original branch and stripped out the changes that had to do with _completely_ removing the Module global. Due to that, this pull has about half the amount of changes as the last.

In summary, here is what's going on with the new branch:

1. preInit and preRun no longer happen automatically upon evaluation of the script. They are called from preload (renamed from load as to not conflict with the existing Module.load which is used for some other purpose).
2. Exported addPreInit, addPreRun and addPostRun functions to replace the existing preInit, preRun and postRun properties. Replaced usage of add/removeRuntimeDependency with addPreRun.
3. Added module closure option (-s USE\_MODULE\_CLOSURE=1).
4. Added exports for AMD and CommonJS modules.
5. Added MODULE\_NAME setting to control exported global Module property for browser builds (defaults to 'Module').

While this branch supports the global module for configuration, Module is now declared as a local variable at the top of shell.js. In order to maintain backwards compatibility, we save off the global Module variable if it exists before initializing the local instance, and we merge the global instance's properties back into the local instance at the end, right before autorun is invoked. With this, all of the tests are passing with very few modifications.

The compatibility breaking changes are:
1. preInit / preRun functions now require the callback property to be invoked.
2. preRun tasks are executed as a fifo queue now instead of a stack. It seems the original code intentionally executed them in this order, but that doesn't seem very intuitive to myself at least (it can be changed back to do that if you'd like).
3. If a user is using a custom shell, has async dependencies (e.g. the mem init file) and is manually calling run - they must now use preload() beforehand.

...

To preface this next bit, I realize at this point I may be going down the rabbit hole and the work is unneccessay, however, I'll throw it out there regardless.

After implementing these changes a second time, I do think the startup sequence could still benefit from some slight renaming. As of now, I haven't actually changed the order or naming of anything. Here is an overview of the startup process as it sits:

preload(callback)
`- preInit
| `- preRun
| `- callback

run()
`- setStatus
`- _run
| `- ensureInitRuntime
| `- callRuntimeCallbacks(__ATINIT__)
| `- preMain
| `- callRuntimeCallbacks(__ATMAIN__)
| `- callMain
| `- ensureInitRuntime
| `- callRuntimeCallbacks(__ATINIT__)
| `- _main
| `- exitRuntime
| `- callRuntimeCallbacks(__ATEXIT__)
| `- postRun

However, to me, this seems a bit more clear:

preload(callback)
`- preInit
`- run async tasks added by new addPreloadTask()
`- callback

run()
`- setStatus
`- _run
| `- preInit
| `- ensureInitRuntime
| `- callRuntimeCallbacks(__ATINIT__)
| `- preMain
| `- callRuntimeCallbacks(__ATMAIN__)
| `- callMain
| `- preInit
| `- ensureInitRuntime
| `- callRuntimeCallbacks(__ATINIT__)
| `- _main
| `- postMain
| `- exitRuntime
| `- callRuntimeCallbacks(__ATEXIT__)

From working with the tests, it _seems_ most uses of preRun are postRun are truly synchronous preMain and postMain hooks. Any async asset related preRun task could be converted to addPreloadTask (e.g. the stuff in file_packager.py).

Anyways, again, I realize this may be unneccessay at this point and I don't want to waste your time, but if any changes are going to be made I figured they should at least be something that won't get changed again for a while.