Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/src/postamble.js
6170 views
1
/**
2
* @license
3
* Copyright 2010 The Emscripten Authors
4
* SPDX-License-Identifier: MIT
5
*/
6
7
// === Auto-generated postamble setup entry stuff ===
8
9
#if LOAD_SOURCE_MAP
10
#include "source_map_support.js"
11
#endif
12
13
#if DETERMINISTIC
14
#include "deterministic.js"
15
#endif
16
17
#if ASSERTIONS
18
var calledRun;
19
#endif
20
21
#if STANDALONE_WASM && MAIN_READS_PARAMS
22
var mainArgs = undefined;
23
#endif
24
25
#if HAS_MAIN
26
#if MAIN_READS_PARAMS
27
{{{ asyncIf(ASYNCIFY == 2) }}}function callMain(args = []) {
28
#else
29
{{{ asyncIf(ASYNCIFY == 2) }}}function callMain() {
30
#endif
31
#if ASSERTIONS
32
#if '$runDependencies' in addedLibraryItems
33
assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on Module["onRuntimeInitialized"])');
34
#endif
35
assert(typeof onPreRuns === 'undefined' || onPreRuns.length == 0, 'cannot call main when preRun functions remain to be called');
36
#endif
37
38
var entryFunction = {{{ getEntryFunction() }}};
39
40
#if PROXY_TO_PTHREAD
41
// With PROXY_TO_PTHREAD make sure we keep the runtime alive until the
42
// proxied main calls exit (see exitOnMainThread() for where Pop is called).
43
{{{ runtimeKeepalivePush() }}}
44
#endif
45
46
#if MAIN_MODULE
47
// Main modules can't tell if they have main() at compile time, since it may
48
// arrive from a dynamic library.
49
if (!entryFunction) return;
50
#endif
51
52
#if MAIN_READS_PARAMS && STANDALONE_WASM
53
mainArgs = [thisProgram].concat(args)
54
#elif MAIN_READS_PARAMS
55
args.unshift(thisProgram);
56
57
var argc = args.length;
58
var argv = stackAlloc((argc + 1) * {{{ POINTER_SIZE }}});
59
var argv_ptr = argv;
60
for (var arg of args) {
61
{{{ makeSetValue('argv_ptr', 0, 'stringToUTF8OnStack(arg)', '*') }}};
62
argv_ptr += {{{ POINTER_SIZE }}};
63
}
64
{{{ makeSetValue('argv_ptr', 0, 0, '*') }}};
65
#else
66
var argc = 0;
67
var argv = 0;
68
#endif // MAIN_READS_PARAMS
69
70
try {
71
#if ABORT_ON_WASM_EXCEPTIONS
72
// See abortWrapperDepth in preamble.js!
73
abortWrapperDepth++;
74
#endif
75
76
#if STANDALONE_WASM
77
entryFunction();
78
// _start (in crt1.c) will call exit() if main return non-zero. So we know
79
// that if we get here main returned zero.
80
var ret = 0;
81
#else
82
var ret = entryFunction(argc, {{{ to64('argv') }}});
83
#endif // STANDALONE_WASM
84
85
#if ASYNCIFY == 2 && !PROXY_TO_PTHREAD
86
// The current spec of JSPI returns a promise only if the function suspends
87
// and a plain value otherwise. This will likely change:
88
// https://github.com/WebAssembly/js-promise-integration/issues/11
89
ret = await ret;
90
#endif // ASYNCIFY == 2
91
// if we're not running an evented main loop, it's time to exit
92
exitJS(ret, /* implicit = */ true);
93
return ret;
94
} catch (e) {
95
return handleException(e);
96
}
97
#if ABORT_ON_WASM_EXCEPTIONS
98
finally {
99
// See abortWrapperDepth in preamble.js!
100
abortWrapperDepth--;
101
}
102
#endif
103
}
104
#endif // HAS_MAIN
105
106
#if STACK_OVERFLOW_CHECK
107
function stackCheckInit() {
108
// This is normally called automatically during __wasm_call_ctors but need to
109
// get these values before even running any of the ctors so we call it redundantly
110
// here.
111
#if ASSERTIONS && PTHREADS
112
// See $establishStackSpace for the equivalent code that runs on a thread
113
assert(!ENVIRONMENT_IS_PTHREAD);
114
#endif
115
#if RELOCATABLE
116
_emscripten_stack_set_limits({{{ STACK_HIGH }}} , {{{ STACK_LOW }}});
117
#else
118
_emscripten_stack_init();
119
#endif
120
// TODO(sbc): Move writeStackCookie to native to to avoid this.
121
writeStackCookie();
122
}
123
#endif
124
125
#if MAIN_READS_PARAMS
126
function run(args = arguments_) {
127
#else
128
function run() {
129
#endif
130
131
#if '$runDependencies' in addedLibraryItems
132
if (runDependencies > 0) {
133
#if RUNTIME_DEBUG
134
dbg('run() called, but dependencies remain, so not running');
135
#endif
136
dependenciesFulfilled = run;
137
return;
138
}
139
#endif
140
141
#if PTHREADS || WASM_WORKERS
142
if ({{{ ENVIRONMENT_IS_WORKER_THREAD() }}}) {
143
#if MODULARIZE
144
readyPromiseResolve?.(Module);
145
#endif
146
initRuntime();
147
return;
148
}
149
#endif
150
151
#if STACK_OVERFLOW_CHECK
152
stackCheckInit();
153
#endif
154
155
preRun();
156
157
#if '$runDependencies' in addedLibraryItems
158
// a preRun added a dependency, run will be called later
159
if (runDependencies > 0) {
160
#if RUNTIME_DEBUG
161
dbg('run() called, but dependencies remain, so not running');
162
#endif
163
dependenciesFulfilled = run;
164
return;
165
}
166
#endif
167
168
{{{ asyncIf(ASYNCIFY == 2) }}}function doRun() {
169
// run may have just been called through dependencies being fulfilled just in this very frame,
170
// or while the async setStatus time below was happening
171
#if ASSERTIONS
172
assert(!calledRun);
173
calledRun = true;
174
#endif
175
Module['calledRun'] = true;
176
177
if (ABORT) return;
178
179
initRuntime();
180
181
#if HAS_MAIN
182
preMain();
183
#endif
184
185
#if MODULARIZE
186
readyPromiseResolve?.(Module);
187
#endif
188
#if expectToReceiveOnModule('onRuntimeInitialized')
189
Module['onRuntimeInitialized']?.();
190
#if ASSERTIONS
191
consumedModuleProp('onRuntimeInitialized');
192
#endif
193
#endif
194
195
#if HAS_MAIN
196
var noInitialRun = {{{ makeModuleReceiveExpr('noInitialRun', !INVOKE_RUN) }}};
197
#if MAIN_READS_PARAMS
198
if (!noInitialRun) {{{ awaitIf(ASYNCIFY == 2) }}}callMain(args);
199
#else
200
if (!noInitialRun) {{{ awaitIf(ASYNCIFY == 2) }}}callMain();
201
#endif
202
#else
203
#if ASSERTIONS
204
assert(!Module['_main'], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');
205
#endif // ASSERTIONS
206
#endif // HAS_MAIN
207
208
postRun();
209
}
210
211
#if expectToReceiveOnModule('setStatus')
212
if (Module['setStatus']) {
213
Module['setStatus']('Running...');
214
setTimeout(() => {
215
setTimeout(() => Module['setStatus'](''), 1);
216
doRun();
217
}, 1);
218
} else
219
#endif
220
{
221
doRun();
222
}
223
#if STACK_OVERFLOW_CHECK
224
checkStackCookie();
225
#endif
226
}
227
228
#if ASSERTIONS
229
#if EXIT_RUNTIME == 0
230
function checkUnflushedContent() {
231
// Compiler settings do not allow exiting the runtime, so flushing
232
// the streams is not possible. but in ASSERTIONS mode we check
233
// if there was something to flush, and if so tell the user they
234
// should request that the runtime be exitable.
235
// Normally we would not even include flush() at all, but in ASSERTIONS
236
// builds we do so just for this check, and here we see if there is any
237
// content to flush, that is, we check if there would have been
238
// something a non-ASSERTIONS build would have not seen.
239
// How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0
240
// mode (which has its own special function for this; otherwise, all
241
// the code is inside libc)
242
var oldOut = out;
243
var oldErr = err;
244
var has = false;
245
out = err = (x) => {
246
has = true;
247
}
248
try { // it doesn't matter if it fails
249
#if SYSCALLS_REQUIRE_FILESYSTEM == 0 && '$flush_NO_FILESYSTEM' in addedLibraryItems
250
flush_NO_FILESYSTEM();
251
#elif WASMFS && hasExportedSymbol('wasmfs_flush')
252
// In WasmFS we must also flush the WasmFS internal buffers, for this check
253
// to work.
254
_wasmfs_flush();
255
#elif hasExportedSymbol('fflush')
256
_fflush(0);
257
#endif
258
#if '$FS' in addedLibraryItems && '$TTY' in addedLibraryItems
259
// also flush in the JS FS layer
260
for (var name of ['stdout', 'stderr']) {
261
var info = FS.analyzePath('/dev/' + name);
262
if (!info) return;
263
var stream = info.object;
264
var rdev = stream.rdev;
265
var tty = TTY.ttys[rdev];
266
if (tty?.output?.length) {
267
has = true;
268
}
269
}
270
#endif
271
} catch(e) {}
272
out = oldOut;
273
err = oldErr;
274
if (has) {
275
warnOnce('stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the Emscripten FAQ), or make sure to emit a newline when you printf etc.');
276
#if FILESYSTEM == 0 || SYSCALLS_REQUIRE_FILESYSTEM == 0
277
warnOnce('(this may also be due to not including full filesystem support - try building with -sFORCE_FILESYSTEM)');
278
#endif
279
}
280
}
281
#endif // EXIT_RUNTIME
282
#endif // ASSERTIONS
283
284
var wasmExports;
285
#if SPLIT_MODULE
286
var wasmRawExports;
287
#endif
288
289
#if MODULARIZE == 'instance'
290
// In MODULARIZE=instance mode we delay most of the initialization work until
291
// the `init` function is called.
292
#if ASSERTIONS
293
var initCalled = false;
294
#endif
295
export default async function init(moduleArg = {}) {
296
#if ASSERTIONS
297
assert(!initCalled);
298
initCalled = true;
299
#endif
300
Object.assign(Module, moduleArg);
301
processModuleArgs();
302
#if WASM_ESM_INTEGRATION
303
#if PTHREADS
304
registerTLSInit(__emscripten_tls_init);
305
#endif
306
updateMemoryViews();
307
#if DYNCALLS && '$dynCalls' in addedLibraryItems
308
309
assignDynCalls();
310
#endif
311
#else
312
wasmExports = await createWasm();
313
#endif
314
run();
315
}
316
317
#if ENVIRONMENT_MAY_BE_NODE
318
// When run as the main script under node we run `init` immediately.
319
if (ENVIRONMENT_IS_NODE
320
#if PTHREADS || WASM_WORKERS
321
&& !{{{ ENVIRONMENT_IS_WORKER_THREAD() }}}
322
#endif
323
)
324
{
325
const url = await import('node:url');
326
const isMainModule = url.pathToFileURL(process.argv[1]).href === import.meta.url;
327
if (isMainModule) await init();
328
}
329
#endif
330
331
#if ENVIRONMENT_MAY_BE_SHELL
332
if (ENVIRONMENT_IS_SHELL) {
333
// When run in a shell we run `init` immediately.
334
await init();
335
}
336
#endif
337
338
#else // MODULARIZE == instance
339
340
#if WASM_WORKERS || PTHREADS
341
if ({{{ ENVIRONMENT_IS_MAIN_THREAD() }}}) {
342
// Call createWasm on startup if we are the main thread.
343
// Worker threads call this once they receive the module via postMessage
344
#endif
345
346
#if WASM_ASYNC_COMPILATION
347
348
#if MODULARIZE
349
// In modularize mode the generated code is within a factory function so we
350
// can use await here (since it's not top-level-await).
351
wasmExports = await createWasm();
352
#else
353
// With async instantation wasmExports is assigned asynchronously when the
354
// instance is received.
355
createWasm();
356
#endif
357
358
#else
359
wasmExports = createWasm();
360
#endif
361
362
run();
363
364
#if WASM_WORKERS || PTHREADS
365
}
366
#endif
367
368
#endif // MODULARIZE != instance
369
370