| .. _Modularized-Output: |
| |
| ================== |
| Modularized Output |
| ================== |
| |
| By default, emscripten outputs regular JS scripts which can be loaded on the Web |
| via a ``script`` tag, or on the command line using Node or other JS runtime. |
| |
| In this default configuration the generated :ref:`module` variable (and indeed |
| all of the emscripten internal symbols) are added to the global scope. This |
| means that only one emscripten-built program can be loaded in a given scope |
| (since multiple modules would clobber each other's state). |
| |
| The :ref:`modularize` setting (along with other related settings) can be used to |
| isolate the generated module within its own private scope and/or allow multiple |
| instances of the same module to be created. |
| |
| This section covers the various modularization options available and how to use |
| them. |
| |
| |
| Using -sMODULARIZE |
| ================== |
| |
| The :ref:`modularize` setting has two primary functions. Firstly, it |
| puts all of the generated code inside its own scope so that the global namespace |
| is not polluted when the JS is loaded (for example, via ``script`` tag). |
| Secondly, it allows multiple instances of the module to be created. |
| |
| The generated factory function is async and it returns a promise of an instance |
| of the program. It can be called any number of times to create multiple |
| separate and isolated instances of the same program. |
| |
| By default, the factory function is called ``Module``, but it can be given a |
| unique name via the ``-sEXPORT_NAME`` setting. |
| |
| For example, a program built using ``-sMODULARIZE -sEXPORT_NAME=Foo`` can |
| be instantiated using: |
| |
| :: |
| |
| var myFoo = await Foo({ /* optional params */ }); |
| myFoo._nativeMethod(); |
| |
| |
| or: |
| |
| :: |
| |
| Foo({ /* optional params */ }).then((myFoo) => { |
| myFoo._nativeMethod(); |
| } |
| |
| If node is included in the ``-sENVIRONMENT`` setting then the generated module |
| also acts as a ``CommonJS`` module under node. |
| |
| Because there is no global ``Module`` object in this case any parameters to the |
| module creation are passed via the optional parameter to the factory function. |
| For example, if you wanted to use a custom ``print`` method you could write: |
| |
| :: |
| |
| var myFoo = await Foo({ print: myPrint }); |
| |
| |
| Generating ES6 Modules |
| ====================== |
| |
| The :ref:`EXPORT_ES6` setting can be used to instead output JavaScript in the |
| form of an ES module. (The ES module format did not exist at time when the |
| `MODULARIZE` setting was first created otherwise this would likely be the |
| default). |
| |
| Using an output filename that ends in `.mjs` will automatically enable this |
| setting. |
| |
| In this mode the module has a single default export which is the factory |
| function for creating new instances of the module. For example: |
| |
| :: |
| |
| import Foo from './emcc-output.js'; |
| var myFoo = await Foo({ print: myPrint }); |
| |
| The name ``Foo`` here can be whatever you choose and will always be assigned to |
| the default export of the module. |
| |
| |
| Using -sMODULARIZE=instance (experimental) |
| ========================================== |
| |
| Emscripten has experimental support for performing only the encapsulation part of |
| modularization, and not the ability to create multiple instances. In this |
| mode a module is created that exports a single instance of the program rather |
| than a factory function. |
| |
| This setting implicitly enables :ref:`export_es6` and will not work when |
| :ref:`export_es6` is explictly disabled. |
| |
| In this mode the default export of the module is an initializer function which |
| allows input parameters to be passed to the instance. Other elements normally |
| found on the module object are instead exported directly. For example: |
| |
| :: |
| |
| // Import the default init function and a named native method |
| import init, { _nativeMethod } from './emcc-output.js'; |
| await init({ print: myPrint }); |
| _nativeMethod(); |
| |
| Limitations |
| ----------- |
| |
| Some major features still do not work in this mode. Many of these we hope to |
| fix in future releases. Current limitations include: |
| |
| * Internal usage (e.g. usage within EM_JS / JS library code) of the ``Module`` |
| global does not work. This is because symbols are exported directly using |
| ES6 module syntax rather than using the ``Module`` global. |
| |
| * The ``wasmExports`` internal global does not exist. |
| |
| * `ccall`/`cwrap` are not supported (depends on the ``Module`` global). |
| |
| * :ref:`minimal_runtime` is not supported. |
| |
| * The output of file_packager is not compatible so :ref:`emcc-preload-file` and |
| :ref:`emcc-embed-file` do not work. |
| |
| |
| Source Phase Imports (experimental) |
| =================================== |
| |
| `Source phase imports`_ is a JavaScript proposal that adds support for importing |
| Wasm modules via ES import statements. This allows Emscripten to elide some of |
| the auto-generated code for finding and fetching the Wasm binary. |
| |
| See :ref:`source_phase_imports`. |
| |
| This setting implicitly enables :ref:`export_es6` and will not work when |
| :ref:`export_es6` is explictly disabled. |
| |
| |
| ES Module Integration (experimental) |
| ==================================== |
| |
| `Wasm ESM integration`_ is a WebAssembly proposal that allows Wasm instances to |
| be imported directly as ES modules. This allows Emscripten to elide a lot of |
| boilerplate code for linking up Wasm and JavaScript. |
| |
| See :ref:`wasm_esm_integration`. |
| |
| Limitations |
| ----------- |
| |
| This setting implicitly enables :ref:`export_es6` and sets :ref:`MODULARIZE` to |
| ``instance``. Because of this all the same limitations mentioned above for |
| ``-sMODULARIZE=instance`` apply. |
| |
| Some additional limitations are: |
| |
| * :ref:`wasm_workers` is not yet supported. |
| |
| * :ref:`abort_on_wasm_exceptions` is not supported (requires wrapping wasm |
| exports). |
| |
| * :ref:`asyncify` is not supported (depends on ``wasmExports`` global) |
| |
| * Setting :ref:`wasm` to ``0`` is not supported. |
| |
| * Setting :ref:`wasm_async_compilation` to ``0`` is not supported. |
| |
| |
| .. _Source phase imports: https://github.com/tc39/proposal-source-phase-imports |
| .. _Wasm ESM integration: https://github.com/WebAssembly/esm-integration |