Skip to content

Commit 14221eb

Browse files
committed
Move modularization code into JS files. NFC
Its much easier to generate JS code using out JS template system than emitting directly from python. Split out from emscripten-core#23261
1 parent 43822b0 commit 14221eb

File tree

3 files changed

+109
-72
lines changed

3 files changed

+109
-72
lines changed

src/modularize_suffix.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Export using a UMD style export, or ES6 exports if selected
2+
#if EXPORT_ES6
3+
export default {{{ EXPORT_NAME }}};
4+
#elif !MINIMAL_RUNTIME
5+
if (typeof exports === 'object' && typeof module === 'object') {
6+
module.exports = {{{ EXPORT_NAME }}};
7+
// This default export looks redundant, but it allows TS to import this
8+
// commonjs style module.
9+
module.exports.default = {{{ EXPORT_NAME }}};
10+
} else if (typeof define === 'function' && define['amd'])
11+
define([], () => {{{ EXPORT_NAME }}});
12+
#endif
13+
14+
15+
#if PTHREADS
16+
17+
// Create code for detecting if we are running in a pthread.
18+
// Normally this detection is done when the module is itself run but
19+
// when running in MODULARIZE mode we need use this to know if we should
20+
// run the module constructor on startup (true only for pthreads).
21+
#if ENVIRONMENT_MAY_BE_WEB || ENVIRONMENT_MAY_BE_WORKER
22+
var isPthread = globalThis.self?.name?.startsWith('em-pthread');
23+
#if ENVIRONMENT_MAY_BE_NODE
24+
// In order to support both web and node we also need to detect node here.
25+
var isNode = {{{ nodeDetectionCode() }}};
26+
if (isNode) isPthread = {{{ nodePthreadDetection() }}}
27+
#endif
28+
#else ENVIRONMENT_MAY_BE_NODE
29+
var isPthread = {{{ nodePthreadDetection() }}}
30+
// When running as a pthread, construct a new instance on startup
31+
#endif
32+
33+
#if MODULARIZE == 'instance'
34+
isPthread && init();
35+
#else
36+
isPthread && {{{ EXPORT_NAME }}}();
37+
#endif
38+
39+
#endif // PTHREADS
40+
41+
#if WASM_WORKERS
42+
43+
// Same as above for for WASM_WORKERS
44+
// Normally this detection is done when the module is itself run but
45+
// when running in MODULARIZE mode we need use this to know if we should
46+
// run the module constructor on startup (true only for pthreads).
47+
#if ENVIRONMENT_MAY_BE_WEB || ENVIRONMENT_MAY_BE_WORKER
48+
var isWW = globalThis.self?.name == 'em-ww';
49+
// In order to support both web and node we also need to detect node here.
50+
#if ENVIRONMENT_MAY_BE_NODE
51+
#if !PTHREADS
52+
var isNode = {{{ nodeDetectionCode() }}};
53+
#endif
54+
if (isNode) isWW = {{{ nodeWWDetection() }}};
55+
#endif
56+
#elif ENVIRONMENT_MAY_BE_NODE
57+
var isWW = {{{ nodeWWDetection() }}};
58+
#endif
59+
60+
#if AUDIO_WORKLET
61+
isWW ||= typeof AudioWorkletGlobalScope !== 'undefined';
62+
// When running as a wasm worker, construct a new instance on startup
63+
#endif
64+
65+
#if MODULARIZE == 'instance'
66+
isWW && init();
67+
#else
68+
isWW && {{{ EXPORT_NAME }}}();
69+
#endif
70+
71+
#endif // WASM_WORKERS

src/parseTools.mjs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,41 @@ function nodeDetectionCode() {
10971097
return "typeof process == 'object' && process.versions?.node && process.type != 'renderer'";
10981098
}
10991099

1100+
function nodePthreadDetection() {
1101+
// Under node we detect that we are running in a pthread by checking the
1102+
// workerData property.
1103+
if (EXPORT_ES6) {
1104+
return "(await import('worker_threads')).workerData === 'em-pthread'";
1105+
} else {
1106+
return "require('worker_threads').workerData === 'em-pthread'";
1107+
}
1108+
}
1109+
1110+
function nodeWWDetection() {
1111+
// Under node we detect that we are running in a wasm worker by checking the
1112+
// workerData property.
1113+
if (EXPORT_ES6) {
1114+
return "(await import('worker_threads')).workerData === 'em-ww'";
1115+
} else {
1116+
return "require('worker_threads').workerData === 'em-ww'";
1117+
}
1118+
}
1119+
1120+
function declareInstanceExports() {
1121+
const allExports = Array.from(EXPORTED_FUNCTIONS.keys()).concat(
1122+
Array.from(EXPORTED_RUNTIME_METHODS.keys()),
1123+
);
1124+
const mangledExports = allExports.map((e) => `__exp_${e}`);
1125+
const mangledExportsAs = allExports.map((e) => `__exp_${e} as ${e}`);
1126+
// Declare a top level var for each export so that code in the init function
1127+
// can assign to it and update the live module bindings.
1128+
if (allExports.length == 0) return '';
1129+
let rtn = 'var ' + mangledExports.join(', ') + ';\n';
1130+
// Export the functions with their original name.
1131+
rtn += 'export {' + mangledExportsAs.join(', ') + '};\n';
1132+
return rtn;
1133+
}
1134+
11001135
addToCompileTimeContext({
11011136
ATEXITS,
11021137
ATPRERUNS,
@@ -1169,4 +1204,6 @@ addToCompileTimeContext({
11691204
storeException,
11701205
to64,
11711206
toIndexType,
1207+
nodePthreadDetection,
1208+
nodeWWDetection,
11721209
});

tools/link.py

Lines changed: 1 addition & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2445,24 +2445,6 @@ def phase_binaryen(target, options, wasm_target):
24452445
write_file(final_js, js)
24462446

24472447

2448-
def node_pthread_detection():
2449-
# Under node we detect that we are running in a pthread by checking the
2450-
# workerData property.
2451-
if settings.EXPORT_ES6:
2452-
return "(await import('worker_threads')).workerData === 'em-pthread';\n"
2453-
else:
2454-
return "require('worker_threads').workerData === 'em-pthread'\n"
2455-
2456-
2457-
def node_ww_detection():
2458-
# Under node we detect that we are running in a wasm worker by checking the
2459-
# workerData property.
2460-
if settings.EXPORT_ES6:
2461-
return "(await import('worker_threads')).workerData === 'em-ww';\n"
2462-
else:
2463-
return "require('worker_threads').workerData === 'em-ww'\n"
2464-
2465-
24662448
def modularize():
24672449
global final_js
24682450
logger.debug(f'Modularizing, assigning to var {settings.EXPORT_NAME}')
@@ -2513,60 +2495,7 @@ def modularize():
25132495
if settings.SOURCE_PHASE_IMPORTS:
25142496
src = f"import source wasmModule from './{settings.WASM_BINARY_FILE}';\n\n" + src
25152497

2516-
# Export using a UMD style export, or ES6 exports if selected
2517-
if settings.EXPORT_ES6:
2518-
src += 'export default %s;\n' % settings.EXPORT_NAME
2519-
elif not settings.MINIMAL_RUNTIME:
2520-
src += '''\
2521-
if (typeof exports === 'object' && typeof module === 'object') {
2522-
module.exports = %(EXPORT_NAME)s;
2523-
// This default export looks redundant, but it allows TS to import this
2524-
// commonjs style module.
2525-
module.exports.default = %(EXPORT_NAME)s;
2526-
} else if (typeof define === 'function' && define['amd'])
2527-
define([], () => %(EXPORT_NAME)s);
2528-
''' % {'EXPORT_NAME': settings.EXPORT_NAME}
2529-
2530-
if settings.PTHREADS:
2531-
# Create code for detecting if we are running in a pthread.
2532-
# Normally this detection is done when the module is itself run but
2533-
# when running in MODULARIZE mode we need use this to know if we should
2534-
# run the module constructor on startup (true only for pthreads).
2535-
if settings.ENVIRONMENT_MAY_BE_WEB or settings.ENVIRONMENT_MAY_BE_WORKER:
2536-
src += "var isPthread = globalThis.self?.name?.startsWith('em-pthread');\n"
2537-
# In order to support both web and node we also need to detect node here.
2538-
if settings.ENVIRONMENT_MAY_BE_NODE:
2539-
src += f'var isNode = {node_detection_code()};\n'
2540-
src += f'if (isNode) isPthread = {node_pthread_detection()}\n'
2541-
elif settings.ENVIRONMENT_MAY_BE_NODE:
2542-
src += f'var isPthread = {node_pthread_detection()}\n'
2543-
src += '// When running as a pthread, construct a new instance on startup\n'
2544-
if settings.MODULARIZE == 'instance':
2545-
src += 'isPthread && init();\n'
2546-
else:
2547-
src += 'isPthread && %s();\n' % settings.EXPORT_NAME
2548-
2549-
if settings.WASM_WORKERS:
2550-
# Same as above for for WASM_WORKERS
2551-
# Normally this detection is done when the module is itself run but
2552-
# when running in MODULARIZE mode we need use this to know if we should
2553-
# run the module constructor on startup (true only for pthreads).
2554-
if settings.ENVIRONMENT_MAY_BE_WEB or settings.ENVIRONMENT_MAY_BE_WORKER:
2555-
src += "var isWW = globalThis.self?.name == 'em-ww';\n"
2556-
# In order to support both web and node we also need to detect node here.
2557-
if settings.ENVIRONMENT_MAY_BE_NODE:
2558-
if not settings.PTHREADS:
2559-
src += f'var isNode = {node_detection_code()};\n'
2560-
src += f'if (isNode) isWW = {node_ww_detection()}\n'
2561-
elif settings.ENVIRONMENT_MAY_BE_NODE:
2562-
src += f'var isWW = {node_ww_detection()}\n'
2563-
if settings.AUDIO_WORKLET:
2564-
src += "isWW ||= typeof AudioWorkletGlobalScope !== 'undefined';\n"
2565-
src += '// When running as a wasm worker, construct a new instance on startup\n'
2566-
if settings.MODULARIZE == 'instance':
2567-
src += 'isWW && init();\n'
2568-
else:
2569-
src += 'isWW && %s();\n' % settings.EXPORT_NAME
2498+
src += building.read_and_preprocess(utils.path_from_root('src/modularize_suffix.js'), expand_macros=True)
25702499

25712500
final_js += '.modular.js'
25722501
write_file(final_js, src)

0 commit comments

Comments
 (0)