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