-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Add an experimental way to export a instance ES module. #22867
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
Changes from 1 commit
5c0d413
b9e19a0
f6b40ee
ecf9e4f
9dcdfed
dcc5a8a
8c8ef1d
694fb8a
a7d28ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,7 @@ moduleRtn = Module; | |
|
|
||
| #endif // WASM_ASYNC_COMPILATION | ||
|
|
||
| #if ASSERTIONS | ||
| #if ASSERTIONS && MODULARIZE != 'static' | ||
|
||
| // Assertion for attempting to access module properties on the incoming | ||
| // moduleArg. In the past we used this object as the prototype of the module | ||
| // and assigned properties to it, but now we return a distinct object. This | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1325,8 +1325,25 @@ var DETERMINISTIC = false; | |
| // --pre-js and --post-js happen to do that in non-MODULARIZE mode, their | ||
| // intended usage is to add code that is optimized with the rest of the emitted | ||
| // code, allowing better dead code elimination and minification. | ||
| // | ||
| // Experimental Feature - Static ES Modules: | ||
| // | ||
| // Note this feature is still under active development and is subject to change! | ||
| // | ||
| // To enable this feature use -sMODULARIZE=static. Enabling this mode will | ||
| // produce an ES module that is a singleton with static ES module exports. The | ||
| // module will export a default value that is an async init function and will | ||
| // also export named values that correspond to the Wasm exports and runtime | ||
| // exports. The init function must be called before any of the exports can be | ||
| // used. An example of using the module is below. | ||
| // | ||
| // import init, { foo, bar } from "./my_module.mjs" | ||
| // await init(optionalArguments); | ||
| // foo(); | ||
| // bar(); | ||
| // | ||
| // [link] | ||
| var MODULARIZE = false; | ||
| var MODULARIZE = ''; | ||
|
||
|
|
||
| // Export using an ES6 Module export rather than a UMD export. MODULARIZE must | ||
| // be enabled for ES6 exports and is implicitly enabled if not already set. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -757,7 +757,13 @@ def phase_linker_setup(options, state, newargs): | |
|
|
||
| if options.oformat == OFormat.MJS: | ||
| settings.EXPORT_ES6 = 1 | ||
| settings.MODULARIZE = 1 | ||
| if not settings.MODULARIZE: | ||
brendandahl marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| settings.MODULARIZE = 1 | ||
|
|
||
| if settings.MODULARIZE == 'static': | ||
| diagnostics.warning('experimental', '-sMODULARIZE=static is still experimental. Many features may not work or will change.') | ||
| if options.oformat != OFormat.MJS: | ||
| exit_with_error('emcc: MODULARIZE static is only compatible with .mjs output files') | ||
|
|
||
| if options.oformat in (OFormat.WASM, OFormat.BARE): | ||
| if options.emit_tsd: | ||
|
|
@@ -2394,7 +2400,20 @@ def modularize(): | |
| if async_emit != '' and settings.EXPORT_NAME == 'config': | ||
| diagnostics.warning('emcc', 'EXPORT_NAME should not be named "config" when targeting Safari') | ||
|
|
||
| src = ''' | ||
| if settings.MODULARIZE == 'static': | ||
| src = ''' | ||
| export default async function init(moduleArg = {}) { | ||
| var moduleRtn; | ||
|
|
||
| %(src)s | ||
|
|
||
| return await moduleRtn; | ||
| } | ||
| ''' % { | ||
| 'src': src, | ||
| } | ||
| else: | ||
| src = ''' | ||
brendandahl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| %(maybe_async)sfunction(moduleArg = {}) { | ||
| var moduleRtn; | ||
|
|
||
|
|
@@ -2403,9 +2422,9 @@ def modularize(): | |
| return moduleRtn; | ||
| } | ||
| ''' % { | ||
| 'maybe_async': async_emit, | ||
| 'src': src, | ||
| } | ||
| 'maybe_async': async_emit, | ||
| 'src': src, | ||
| } | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this indentation better than before? Maybe revert this?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Flake wants this because of the new if/else above. |
||
|
|
||
| if settings.MINIMAL_RUNTIME and not settings.PTHREADS: | ||
| # Single threaded MINIMAL_RUNTIME programs do not need access to | ||
|
|
@@ -2424,19 +2443,31 @@ def modularize(): | |
| script_url = "typeof document != 'undefined' ? document.currentScript?.src : undefined" | ||
| if shared.target_environment_may_be('node'): | ||
| script_url_node = "if (typeof __filename != 'undefined') _scriptName = _scriptName || __filename;" | ||
| src = '''%(node_imports)s | ||
| if settings.MODULARIZE == 'static': | ||
| src = '''%(node_imports)s | ||
| var _scriptName = %(script_url)s; | ||
| %(script_url_node)s | ||
| %(src)s | ||
| ''' % { | ||
| 'node_imports': node_es6_imports(), | ||
| 'script_url': script_url, | ||
| 'script_url_node': script_url_node, | ||
| 'src': src, | ||
| } | ||
| else: | ||
| src = '''%(node_imports)s | ||
| var %(EXPORT_NAME)s = (() => { | ||
| var _scriptName = %(script_url)s; | ||
| %(script_url_node)s | ||
| return (%(src)s); | ||
| })(); | ||
| ''' % { | ||
| 'node_imports': node_es6_imports(), | ||
| 'EXPORT_NAME': settings.EXPORT_NAME, | ||
| 'script_url': script_url, | ||
| 'script_url_node': script_url_node, | ||
| 'src': src, | ||
| } | ||
| 'node_imports': node_es6_imports(), | ||
| 'EXPORT_NAME': settings.EXPORT_NAME, | ||
| 'script_url': script_url, | ||
| 'script_url_node': script_url_node, | ||
| 'src': src, | ||
| } | ||
|
|
||
| # Given the async nature of how the Module function and Module object | ||
| # come into existence in AudioWorkletGlobalScope, store the Module | ||
|
|
@@ -2448,9 +2479,18 @@ def modularize(): | |
| src += f'globalThis.AudioWorkletModule = {settings.EXPORT_NAME};\n' | ||
|
|
||
| # Export using a UMD style export, or ES6 exports if selected | ||
| if settings.EXPORT_ES6: | ||
| if settings.EXPORT_ES6 and settings.MODULARIZE != 'static': | ||
| src += 'export default %s;\n' % settings.EXPORT_NAME | ||
|
|
||
| if settings.MODULARIZE == 'static': | ||
| exports = settings.EXPORTED_FUNCTIONS + settings.EXPORTED_RUNTIME_METHODS | ||
| # Declare a top level var for each export so that code in the init function | ||
| # can assign to it and update the live module bindings. | ||
| src += "var " + ", ".join(['x_' + export for export in exports]) + ";\n" | ||
| # Export the functions with their original name. | ||
| exports = ['x_' + export + ' as ' + export for export in exports] | ||
| src += "export {" + ", ".join(exports) + "};\n" | ||
brendandahl marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| elif not settings.MINIMAL_RUNTIME: | ||
| src += '''\ | ||
| if (typeof exports === 'object' && typeof module === 'object') | ||
|
|
@@ -2473,7 +2513,10 @@ def modularize(): | |
| elif settings.ENVIRONMENT_MAY_BE_NODE: | ||
| src += f'var isPthread = {node_pthread_detection()}\n' | ||
| src += '// When running as a pthread, construct a new instance on startup\n' | ||
| src += 'isPthread && %s();\n' % settings.EXPORT_NAME | ||
| if settings.MODULARIZE == 'static': | ||
| src += 'isPthread && init();\n' | ||
| else: | ||
| src += 'isPthread && %s();\n' % settings.EXPORT_NAME | ||
|
|
||
| final_js += '.modular.js' | ||
| write_file(final_js, src) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.