Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/src/postamble_minimal.js
6170 views
1
/**
2
* @license
3
* Copyright 2019 The Emscripten Authors
4
* SPDX-License-Identifier: MIT
5
*/
6
7
#if LOAD_SOURCE_MAP
8
#include "source_map_support.js"
9
#endif
10
11
// === Auto-generated postamble setup entry stuff ===
12
#if HAS_MAIN // Only if user is exporting a C main(), we will generate a run() function that can be used to launch main.
13
14
#if EXIT_RUNTIME
15
function exitRuntime(ret) {
16
<<< ATEXITS >>>
17
#if PTHREADS
18
PThread.terminateAllThreads();
19
#endif
20
21
#if ASSERTIONS
22
runtimeExited = true;
23
#endif
24
25
_proc_exit(ret);
26
27
#if STACK_OVERFLOW_CHECK
28
checkStackCookie();
29
#endif
30
}
31
#endif
32
33
{{{ globalThis.argc_argv = function(condition) {
34
if (!MAIN_READS_PARAMS) return '';
35
return `argc, ${to64('argv')}`;
36
}
37
globalThis.HEAPptr = MEMORY64 ? 'HEAPU64' : 'HEAPU32';
38
null;
39
}}}
40
41
function run() {
42
#if MEMORYPROFILER
43
emscriptenMemoryProfiler.onPreloadComplete();
44
#endif
45
46
<<< ATMAINS >>>
47
48
#if MAIN_READS_PARAMS
49
var args =
50
#if ENVIRONMENT_MAY_BE_NODE
51
// Remove Node.js executable name from argc/argv to emulate C/C++ standards.
52
ENVIRONMENT_IS_NODE ? process.argv.slice(1) :
53
#endif
54
[location.href.split('?')[0], ...location.search.slice(1).split('&').map(decodeURIComponent)];
55
56
// C standard (C17 §5.1.2.2.1/5): "The parameters argc and argv and the
57
// strings pointed to by the argv array shall be modifiable by the program,
58
// and retain their last-stored values between program startup and program
59
// termination."
60
// -> in particular this means that the stackAlloc() that we do below shall
61
// never be undone, and ideally should no longer be considered to be part of
62
// the stack. Though currently it will be. (TODO: figure if this will ever be
63
// a problem)
64
var arg,
65
argc = args.length,
66
argv = stackAlloc(argc * {{{ POINTER_SIZE }}} + {{{ POINTER_SIZE }}}),
67
argvIndex = argv / {{{ POINTER_SIZE }}};
68
69
for (arg of args) {{{ HEAPptr }}}[argvIndex++] = {{{ to64('stringToUTF8OnStack(arg)') }}};
70
71
// C standard (C17 §5.1.2.2.1/2): "argv[argc] shall be a null pointer."
72
{{{ HEAPptr }}}[argvIndex] = {{{ to64(0) }}};
73
74
#endif
75
76
#if PROXY_TO_PTHREAD
77
// User requested the PROXY_TO_PTHREAD option, so call a stub main which
78
// pthread_create()s a new thread that will call the user's real main() for
79
// the application.
80
__emscripten_proxy_main({{{ argc_argv() }}});
81
#elif ASYNCIFY == 2 && EXIT_RUNTIME
82
// In JSPI-enabled build mode, the main() function will return a Promise,
83
// which resolves to the process exit code.
84
_main({{{ argc_argv() }}}).then(exitRuntime);
85
#elif EXIT_RUNTIME
86
// In regular exitRuntime mode, exit with the given return code from main().
87
try {
88
exitRuntime(_main({{{ argc_argv() }}}));
89
} catch(e) {
90
var exitCode = e.match(/^exit\((\d+)\)$/);
91
if (exitCode) {
92
#if RUNTIME_DEBUG
93
dbg(`main() called ${e}.`); // e.g. "main() called exit(0)."
94
#endif
95
#if expectToReceiveOnModule('onExit')
96
// Report to Module that the program exited.
97
Module['onExit']?.(exitCode[1]|0);
98
#endif
99
} else {
100
#if RUNTIME_DEBUG
101
dbg(`main() threw an exception: ${e}.`);
102
#endif
103
// Some other exception occurred - re-throw it.
104
throw e;
105
}
106
}
107
#else
108
// Run a persistent (never-exiting) application starting at main().
109
_main({{{ argc_argv() }}});
110
#endif
111
112
#if STACK_OVERFLOW_CHECK
113
checkStackCookie();
114
#endif
115
<<< ATPOSTRUNS >>>
116
}
117
#endif
118
119
function initRuntime(wasmExports) {
120
#if ASSERTIONS || SAFE_HEAP || USE_ASAN || MODULARIZE
121
runtimeInitialized = true;
122
#endif
123
124
#if PTHREADS
125
PThread.tlsInitFunctions.push(wasmExports['_emscripten_tls_init']);
126
if (ENVIRONMENT_IS_PTHREAD) return;
127
#endif
128
129
#if WASM_WORKERS
130
if (ENVIRONMENT_IS_WASM_WORKER) return _wasmWorkerInitializeRuntime();
131
#endif
132
133
#if STACK_OVERFLOW_CHECK
134
_emscripten_stack_init();
135
#if STACK_OVERFLOW_CHECK >= 2
136
setStackLimits();
137
#endif
138
writeStackCookie();
139
#endif
140
141
<<< ATINITS >>>
142
143
#if hasExportedSymbol('__wasm_call_ctors')
144
wasmExports['__wasm_call_ctors']();
145
#endif
146
147
<<< ATPOSTCTORS >>>
148
}
149
150
// Initialize wasm (asynchronous)
151
152
#if SINGLE_FILE && SINGLE_FILE_BINARY_ENCODE && !WASM2JS
153
Module['wasm'] = binaryDecode("<<< WASM_BINARY_DATA >>>");
154
#elif SINGLE_FILE && WASM == 1 && !WASM2JS
155
Module['wasm'] = base64Decode('<<< WASM_BINARY_DATA >>>');
156
#endif
157
158
#if LibraryManager.has('libexports.js')
159
// emscripten_get_exported_function() requires wasmExports to be defined in the
160
// outer scope.
161
var wasmExports;
162
#endif
163
164
#if PTHREADS || WASM_WORKERS
165
var wasmModule;
166
167
function loadModule() {
168
assignWasmImports();
169
#endif
170
171
#if ASYNCIFY
172
Asyncify.instrumentWasmImports(wasmImports);
173
#endif
174
175
var imports = {
176
#if MINIFY_WASM_IMPORTED_MODULES
177
'a': wasmImports,
178
#else // MINIFY_WASM_IMPORTED_MODULES
179
'env': wasmImports,
180
'{{{ WASI_MODULE_NAME }}}': wasmImports,
181
#endif // MINIFY_WASM_IMPORTED_MODULES
182
};
183
184
#if MINIMAL_RUNTIME_STREAMING_WASM_INSTANTIATION
185
{{{
186
#if EXPORT_ES6 && !ENVIRONMENT_MAY_BE_AUDIO_WORKLET
187
const moduleUrl = `new URL('${TARGET_BASENAME}.wasm', import.meta.url)`;
188
#elif !EXPORT_ES6 || AUDIO_WORKLET
189
const moduleUrl = `'${TARGET_BASENAME}.wasm'`;
190
#else
191
const moduleUrl = `ENVIRONMENT_IS_AUDIO_WORKLET ? '${TARGET_BASENAME}.wasm' : new URL('${TARGET_BASENAME}.wasm', import.meta.url)`;
192
#endif
193
}}}
194
// https://caniuse.com/#feat=wasm and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming
195
#if MIN_SAFARI_VERSION < 150000 || ENVIRONMENT_MAY_BE_NODE
196
#if ASSERTIONS && !WASM2JS
197
// Module['wasm'] should contain a typed array of the Wasm object data, or a
198
// precompiled WebAssembly Module.
199
assert(WebAssembly.instantiateStreaming || Module['wasm'], 'Must load WebAssembly Module in to variable Module.wasm before adding compiled output .js script to the DOM');
200
#endif
201
#if AUDIO_WORKLET
202
instantiatePromise =
203
#endif
204
(WebAssembly.instantiateStreaming
205
#if ENVIRONMENT_MAY_BE_NODE
206
// Node's fetch API cannot be used for local files, so we cannot use instantiateStreaming
207
&& !ENVIRONMENT_IS_NODE
208
#endif
209
? WebAssembly.instantiateStreaming(fetch({{{ moduleUrl }}}), imports)
210
: WebAssembly.instantiate(Module['wasm'], imports)).then((output) => {
211
#else
212
#if AUDIO_WORKLET
213
instantiatePromise =
214
#endif
215
WebAssembly.instantiateStreaming(fetch({{{ moduleUrl }}}), imports).then((output) => {
216
#endif
217
218
#else // Non-streaming instantiation
219
#if ASSERTIONS && !WASM2JS
220
// Module['wasm'] should contain a typed array of the Wasm object data, or a
221
// precompiled WebAssembly Module.
222
assert(Module['wasm'], 'Must load WebAssembly Module in to variable Module.wasm before adding compiled output .js script to the DOM');
223
#endif
224
225
<<< ATMODULES >>>
226
227
{{{ exportJSSymbols() }}}
228
229
// Add missingProperties supression here because closure compiler doesn't know that
230
// WebAssembly.instantiate is polymorphic in its return value.
231
#if AUDIO_WORKLET
232
instantiatePromise =
233
#endif
234
WebAssembly.instantiate(Module['wasm'], imports).then(/** @suppress {missingProperties} */ (output) => {
235
#endif
236
237
#if !LibraryManager.has('libexports.js') && ASYNCIFY != 1
238
// If not using the emscripten_get_exported_function() API, keep the
239
// `wasmExports` variable in local scope to this instantiate function to save
240
// code size. (otherwise access it without to export it to outer scope)
241
var
242
#endif
243
// WebAssembly instantiation API gotcha: if Module['wasm'] above was a typed
244
// array, then the output object will have an output.instance and
245
// output.module objects. But if Module['wasm'] is an already compiled
246
// WebAssembly module, then output is the WebAssembly instance itself.
247
// Depending on the build mode, Module['wasm'] can mean a different thing.
248
#if PTHREADS || WASM_WORKERS
249
// In pthreads and wasm workers, Module['wasm'] is a compiled
250
// WebAssembly.Module. In that case, 'output' is a WebAssembly.Instance.
251
// In main thread, Module['wasm'] is either a typed array or a fetch stream.
252
// In that case, 'output.instance' is the WebAssembly.Instance.
253
wasmExports = (output.instance || output).exports;
254
// Stash the Wasm module for future worker creation.
255
wasmModule = output.module || Module['wasm'];
256
#elif MINIMAL_RUNTIME_STREAMING_WASM_COMPILATION
257
// In MINIMAL_RUNTIME_STREAMING_WASM_COMPILATION mode, Module['wasm'] is the
258
// compiled module so we just get the instance back.
259
wasmExports = output.exports;
260
#else
261
wasmExports = output.instance.exports;
262
#endif
263
264
#if ASYNCIFY
265
wasmExports = Asyncify.instrumentWasmExports(wasmExports);
266
#endif
267
268
#if MEMORY64 || CAN_ADDRESS_2GB
269
wasmExports = applySignatureConversions(wasmExports);
270
#endif
271
272
assignWasmExports(wasmExports);
273
274
#if !IMPORTED_MEMORY
275
updateMemoryViews();
276
#endif
277
<<< ATPRERUNS >>>
278
279
initRuntime(wasmExports);
280
281
{{{ function waitOnStartupPromisesAndEmitReady() {
282
var promises = [];
283
if (PTHREADS && PTHREAD_POOL_SIZE) {
284
promises.push('PThread.loadWasmModuleToAllWorkers()');
285
}
286
if (LOAD_SOURCE_MAP) {
287
promises.push('getSourceMapAsync().then(json=>{receiveSourceMapJSON(json)})');
288
}
289
if (promises.length == 0) {
290
return 'ready();'
291
} else if (promises.length == 1) {
292
return `${promises[0]}.then(ready);`;
293
} else {
294
return `Promise.all(${', '.join(promises)}).then(ready);`
295
}
296
}
297
null;
298
}}}
299
300
#if PTHREADS && PTHREAD_POOL_SIZE && PTHREAD_POOL_DELAY_LOAD
301
// In PTHREAD_POOL_DELAY_LOAD mode, we kick off loading Wasm Module to all
302
// PThread Workers, but do not wait on it.
303
PThread.loadWasmModuleToAllWorkers();
304
#endif
305
306
{{{ waitOnStartupPromisesAndEmitReady(); }}}
307
308
}
309
310
#if WASM == 2
311
, (error) => {
312
#if ASSERTIONS
313
console.error(error);
314
#endif
315
316
#if ENVIRONMENT_MAY_BE_NODE || ENVIRONMENT_MAY_BE_SHELL
317
if (globalThis.location) {
318
#endif
319
// WebAssembly compilation failed, try running the JS fallback instead.
320
var search = location.search;
321
if (search.indexOf('_rwasm=0') < 0) {
322
location.href += (search ? search + '&' : '?') + '_rwasm=0';
323
}
324
#if ENVIRONMENT_MAY_BE_NODE || ENVIRONMENT_MAY_BE_SHELL
325
}
326
#endif
327
}
328
#endif // WASM == 2
329
);
330
331
#if PTHREADS || WASM_WORKERS
332
}
333
334
// When running in a background thread we delay module loading until we have
335
{{{ runIfMainThread('loadModule();') }}}
336
#endif
337
338