Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/src/preamble.js
6162 views
1
/**
2
* @license
3
* Copyright 2010 The Emscripten Authors
4
* SPDX-License-Identifier: MIT
5
*/
6
7
// === Preamble library stuff ===
8
9
// Documentation for the public APIs defined in this file must be updated in:
10
// site/source/docs/api_reference/preamble.js.rst
11
// A prebuilt local version of the documentation is available at:
12
// site/build/text/docs/api_reference/preamble.js.txt
13
// You can also build docs locally as HTML or other formats in site/
14
// An online HTML version (which may be of a different version of Emscripten)
15
// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
16
17
#if MAIN_MODULE
18
{{{ makeModuleReceiveWithVar('dynamicLibraries', undefined, '[]') }}}
19
#endif
20
21
{{{ makeModuleReceiveWithVar('wasmBinary') }}}
22
23
#if WASM2JS
24
#if WASM != 2
25
// WASM == 2 includes wasm2js.js separately.
26
#include "wasm2js.js"
27
#endif
28
29
if (WebAssembly.isWasm2js) {
30
// We don't need to actually download a wasm binary, mark it as present but
31
// empty.
32
wasmBinary = [];
33
}
34
#endif
35
36
#if ASSERTIONS && WASM == 1
37
if (!globalThis.WebAssembly) {
38
err('no native wasm support detected');
39
}
40
#endif
41
42
// Wasm globals
43
44
#if SHARED_MEMORY
45
// For sending to workers.
46
var wasmModule;
47
#endif // SHARED_MEMORY
48
49
//========================================
50
// Runtime essentials
51
//========================================
52
53
// whether we are quitting the application. no code should run after this.
54
// set in exit() and abort()
55
var ABORT = false;
56
57
// set by exit() and abort(). Passed to 'onExit' handler.
58
// NOTE: This is also used as the process return code in shell environments
59
// but only when noExitRuntime is false.
60
var EXITSTATUS;
61
62
#if ASSERTIONS || !STRICT
63
// In STRICT mode, we only define assert() when ASSERTIONS is set. i.e. we
64
// don't define it at all in release modes. This matches the behaviour of
65
// MINIMAL_RUNTIME.
66
// TODO(sbc): Make this the default even without STRICT enabled.
67
/** @type {function(*, string=)} */
68
function assert(condition, text) {
69
if (!condition) {
70
#if ASSERTIONS
71
abort('Assertion failed' + (text ? ': ' + text : ''));
72
#else
73
// This build was created without ASSERTIONS defined. `assert()` should not
74
// ever be called in this configuration but in case there are callers in
75
// the wild leave this simple abort() implementation here for now.
76
abort(text);
77
#endif
78
}
79
}
80
#endif
81
82
#if ASSERTIONS
83
// We used to include malloc/free by default in the past. Show a helpful error in
84
// builds with assertions.
85
#if !hasExportedSymbol('malloc')
86
function _malloc() {
87
abort('malloc() called but not included in the build - add `_malloc` to EXPORTED_FUNCTIONS');
88
}
89
#endif // malloc
90
#if !hasExportedSymbol('free')
91
function _free() {
92
// Show a helpful error since we used to include free by default in the past.
93
abort('free() called but not included in the build - add `_free` to EXPORTED_FUNCTIONS');
94
}
95
#endif // free
96
#endif // ASSERTIONS
97
98
/**
99
* Indicates whether filename is delivered via file protocol (as opposed to http/https)
100
* @noinline
101
*/
102
var isFileURI = (filename) => filename.startsWith('file://');
103
104
#include "runtime_common.js"
105
106
#if ASSERTIONS
107
assert(globalThis.Int32Array && globalThis.Float64Array && Int32Array.prototype.subarray && Int32Array.prototype.set,
108
'JS engine does not provide full typed array support');
109
#endif
110
111
#if RELOCATABLE || MAIN_MODULE
112
var __RELOC_FUNCS__ = [];
113
#endif
114
115
function preRun() {
116
#if ASSERTIONS && PTHREADS
117
assert(!ENVIRONMENT_IS_PTHREAD); // PThreads reuse the runtime from the main thread.
118
#endif
119
#if expectToReceiveOnModule('preRun')
120
if (Module['preRun']) {
121
if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
122
while (Module['preRun'].length) {
123
addOnPreRun(Module['preRun'].shift());
124
}
125
}
126
#if ASSERTIONS
127
consumedModuleProp('preRun');
128
#endif
129
#endif
130
<<< ATPRERUNS >>>
131
}
132
133
function initRuntime() {
134
#if RUNTIME_DEBUG
135
dbg('initRuntime');
136
#endif
137
#if ASSERTIONS
138
assert(!runtimeInitialized);
139
#endif
140
runtimeInitialized = true;
141
142
#if WASM_WORKERS
143
if (ENVIRONMENT_IS_WASM_WORKER) return _wasmWorkerInitializeRuntime();
144
#endif
145
146
#if PTHREADS
147
if (ENVIRONMENT_IS_PTHREAD) return startWorker();
148
#endif
149
150
#if STACK_OVERFLOW_CHECK >= 2
151
setStackLimits();
152
#endif
153
154
#if STACK_OVERFLOW_CHECK
155
checkStackCookie();
156
#endif
157
158
#if MAIN_MODULE || RELOCATABLE
159
callRuntimeCallbacks(__RELOC_FUNCS__);
160
#endif
161
162
<<< ATINITS >>>
163
164
#if hasExportedSymbol('__wasm_call_ctors')
165
#if WASM_ESM_INTEGRATION
166
___wasm_call_ctors();
167
#else
168
wasmExports['__wasm_call_ctors']();
169
#endif
170
#if RUNTIME_DEBUG
171
dbg('done __wasm_call_ctors');
172
#endif
173
#endif
174
175
<<< ATPOSTCTORS >>>
176
#if RUNTIME_DEBUG
177
dbg('done ATPOSTCTORS');
178
#endif
179
}
180
181
#if HAS_MAIN
182
function preMain() {
183
#if STACK_OVERFLOW_CHECK
184
checkStackCookie();
185
#endif
186
<<< ATMAINS >>>
187
}
188
#endif
189
190
#if EXIT_RUNTIME
191
function exitRuntime() {
192
#if RUNTIME_DEBUG
193
dbg('exitRuntime');
194
#endif
195
#if ASSERTIONS
196
assert(!runtimeExited);
197
#endif
198
#if ASYNCIFY == 1 && ASSERTIONS
199
// ASYNCIFY cannot be used once the runtime starts shutting down.
200
Asyncify.state = Asyncify.State.Disabled;
201
#endif
202
#if STACK_OVERFLOW_CHECK
203
checkStackCookie();
204
#endif
205
{{{ runIfWorkerThread('return;') }}} // PThreads reuse the runtime from the main thread.
206
#if !STANDALONE_WASM
207
___funcs_on_exit(); // Native atexit() functions
208
#endif
209
<<< ATEXITS >>>
210
#if PTHREADS
211
PThread.terminateAllThreads();
212
#endif
213
runtimeExited = true;
214
}
215
#endif
216
217
function postRun() {
218
#if STACK_OVERFLOW_CHECK
219
checkStackCookie();
220
#endif
221
{{{ runIfWorkerThread('return;') }}} // PThreads reuse the runtime from the main thread.
222
223
#if expectToReceiveOnModule('postRun')
224
if (Module['postRun']) {
225
if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
226
while (Module['postRun'].length) {
227
addOnPostRun(Module['postRun'].shift());
228
}
229
}
230
#if ASSERTIONS
231
consumedModuleProp('postRun');
232
#endif
233
#endif
234
235
<<< ATPOSTRUNS >>>
236
}
237
238
/** @param {string|number=} what */
239
function abort(what) {
240
#if expectToReceiveOnModule('onAbort')
241
Module['onAbort']?.(what);
242
#endif
243
244
what = 'Aborted(' + what + ')';
245
// TODO(sbc): Should we remove printing and leave it up to whoever
246
// catches the exception?
247
err(what);
248
249
ABORT = true;
250
251
#if ASSERTIONS == 0
252
what += '. Build with -sASSERTIONS for more info.';
253
#elif ASYNCIFY == 1
254
if (what.search(/RuntimeError: [Uu]nreachable/) >= 0) {
255
what += '. "unreachable" may be due to ASYNCIFY_STACK_SIZE not being large enough (try increasing it)';
256
}
257
#endif // ASSERTIONS
258
259
// Use a wasm runtime error, because a JS error might be seen as a foreign
260
// exception, which means we'd run destructors on it. We need the error to
261
// simply make the program stop.
262
// FIXME This approach does not work in Wasm EH because it currently does not assume
263
// all RuntimeErrors are from traps; it decides whether a RuntimeError is from
264
// a trap or not based on a hidden field within the object. So at the moment
265
// we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that
266
// allows this in the wasm spec.
267
268
// Suppress closure compiler warning here. Closure compiler's builtin extern
269
// definition for WebAssembly.RuntimeError claims it takes no arguments even
270
// though it can.
271
// TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed.
272
#if WASM_EXCEPTIONS == 1
273
// See above, in the meantime, we resort to wasm code for trapping.
274
//
275
// In case abort() is called before the module is initialized, wasmExports
276
// and its exported '__trap' function is not available, in which case we throw
277
// a RuntimeError.
278
//
279
// We trap instead of throwing RuntimeError to prevent infinite-looping in
280
// Wasm EH code (because RuntimeError is considered as a foreign exception and
281
// caught by 'catch_all'), but in case throwing RuntimeError is fine because
282
// the module has not even been instantiated, even less running.
283
if (runtimeInitialized) {
284
___trap();
285
}
286
#endif
287
/** @suppress {checkTypes} */
288
var e = new WebAssembly.RuntimeError(what);
289
290
#if MODULARIZE
291
readyPromiseReject?.(e);
292
#endif
293
// Throw the error whether or not MODULARIZE is set because abort is used
294
// in code paths apart from instantiation where an exception is expected
295
// to be thrown when abort is called.
296
throw e;
297
}
298
299
#if ASSERTIONS && !('$FS' in addedLibraryItems)
300
// show errors on likely calls to FS when it was not included
301
var FS = {
302
error() {
303
abort('Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -sFORCE_FILESYSTEM');
304
},
305
init() { FS.error() },
306
createDataFile() { FS.error() },
307
createPreloadedFile() { FS.error() },
308
createLazyFile() { FS.error() },
309
open() { FS.error() },
310
mkdev() { FS.error() },
311
registerDevice() { FS.error() },
312
analyzePath() { FS.error() },
313
314
ErrnoError() { FS.error() },
315
};
316
{{{
317
addAtModule(`
318
Module['FS_createDataFile'] = FS.createDataFile;
319
Module['FS_createPreloadedFile'] = FS.createPreloadedFile;
320
`);
321
}}}
322
#endif
323
324
#if ASSERTIONS
325
function createExportWrapper(name, nargs) {
326
return (...args) => {
327
assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`);
328
#if EXIT_RUNTIME
329
assert(!runtimeExited, `native function \`${name}\` called after runtime exit (use NO_EXIT_RUNTIME to keep it alive after main() exits)`);
330
#endif
331
var f = wasmExports[name];
332
assert(f, `exported native function \`${name}\` not found`);
333
// Only assert for too many arguments. Too few can be valid since the missing arguments will be zero filled.
334
assert(args.length <= nargs, `native function \`${name}\` called with ${args.length} args but expects ${nargs}`);
335
return f(...args);
336
};
337
}
338
#endif
339
340
#if ABORT_ON_WASM_EXCEPTIONS
341
// `abortWrapperDepth` counts the recursion level of the wrapper function so
342
// that we only handle exceptions at the top level letting the exception
343
// mechanics work uninterrupted at the inner level. Additionally,
344
// `abortWrapperDepth` is also manually incremented in callMain so that we know
345
// to ignore exceptions from there since they're handled by callMain directly.
346
var abortWrapperDepth = 0;
347
348
function makeAbortWrapper(original) {
349
return (...args) => {
350
// Don't allow this function to be called if we're aborted!
351
if (ABORT) {
352
throw new Error('program has already aborted!');
353
}
354
355
abortWrapperDepth++;
356
try {
357
return original(...args);
358
} catch (e) {
359
if (
360
ABORT // rethrow exception if abort() was called in the original function call above
361
|| abortWrapperDepth > 1 // rethrow exceptions not caught at the top level if exception catching is enabled; rethrow from exceptions from within callMain
362
#if SUPPORT_LONGJMP == 'emscripten' // Rethrow longjmp if enabled
363
#if EXCEPTION_STACK_TRACES
364
|| e instanceof EmscriptenSjLj // EXCEPTION_STACK_TRACES=1 will throw an instance of EmscriptenSjLj
365
#else
366
|| e === Infinity // EXCEPTION_STACK_TRACES=0 will throw Infinity
367
#endif // EXCEPTION_STACK_TRACES
368
#endif
369
|| e === 'unwind'
370
) {
371
throw e;
372
}
373
374
abort('unhandled exception: ' + [e, e.stack]);
375
}
376
finally {
377
abortWrapperDepth--;
378
}
379
}
380
}
381
382
// Instrument all the exported functions to:
383
// - abort if an unhandled exception occurs
384
// - throw an exception if someone tries to call them after the program has aborted
385
// See settings.ABORT_ON_WASM_EXCEPTIONS for more info.
386
function instrumentWasmExportsWithAbort(exports) {
387
// Override the exported functions with the wrappers and copy over any other symbols
388
var instExports = {};
389
for (var name in exports) {
390
var original = exports[name];
391
if (typeof original == 'function') {
392
instExports[name] = makeAbortWrapper(original);
393
} else {
394
instExports[name] = original;
395
}
396
}
397
398
return instExports;
399
}
400
401
function instrumentWasmTableWithAbort() {
402
// Override the wasmTable get function to return the wrappers
403
var realGet = wasmTable.get;
404
var wrapperCache = {};
405
wasmTable.get = (i) => {
406
var func = realGet.call(wasmTable, {{{ toIndexType('i') }}});
407
var cached = wrapperCache[i];
408
if (!cached || cached.func !== func) {
409
cached = wrapperCache[i] = {
410
func,
411
wrapper: makeAbortWrapper(func)
412
}
413
}
414
return cached.wrapper;
415
};
416
}
417
#endif
418
419
#if !SOURCE_PHASE_IMPORTS && !WASM_ESM_INTEGRATION
420
var wasmBinaryFile;
421
422
#if WASM2JS && WASM != 2
423
424
// When building with wasm2js these 3 functions all no-ops.
425
function findWasmBinary(file) {}
426
function getBinarySync(file) {}
427
function getWasmBinary(file) {}
428
429
#else
430
431
function findWasmBinary() {
432
#if SINGLE_FILE && SINGLE_FILE_BINARY_ENCODE && !WASM2JS
433
return binaryDecode("<<< WASM_BINARY_DATA >>>");
434
#elif SINGLE_FILE
435
return base64Decode('<<< WASM_BINARY_DATA >>>');
436
#elif AUDIO_WORKLET || !EXPORT_ES6 // For an Audio Worklet, we cannot use `new URL()`.
437
return locateFile('{{{ WASM_BINARY_FILE }}}');
438
#else
439
440
#if ENVIRONMENT_MAY_BE_SHELL
441
if (ENVIRONMENT_IS_SHELL) {
442
return '{{{ WASM_BINARY_FILE }}}';
443
}
444
#endif
445
446
#if ENVIRONMENT_MAY_BE_AUDIO_WORKLET && !AUDIO_WORKLET // AUDIO_WORKLET handled above
447
if (ENVIRONMENT_IS_AUDIO_WORKLET) {
448
return '{{{ WASM_BINARY_FILE }}}';
449
}
450
#endif
451
452
if (Module['locateFile']) {
453
return locateFile('{{{ WASM_BINARY_FILE }}}');
454
}
455
456
// Use bundler-friendly `new URL(..., import.meta.url)` pattern; works in browsers too.
457
return new URL('{{{ WASM_BINARY_FILE }}}', import.meta.url).href;
458
459
#endif
460
}
461
462
function getBinarySync(file) {
463
#if SINGLE_FILE && SINGLE_FILE_BINARY_ENCODE
464
return file;
465
#else
466
#if SINGLE_FILE
467
if (ArrayBuffer.isView(file)) {
468
return file;
469
}
470
#endif
471
#if expectToReceiveOnModule('wasmBinary') || WASM2JS
472
if (file == wasmBinaryFile && wasmBinary) {
473
return new Uint8Array(wasmBinary);
474
}
475
#endif
476
if (readBinary) {
477
return readBinary(file);
478
}
479
// Throwing a plain string here, even though it not normally advisable since
480
// this gets turning into an `abort` in instantiateArrayBuffer.
481
#if WASM_ASYNC_COMPILATION
482
throw 'both async and sync fetching of the wasm failed';
483
#else
484
throw 'sync fetching of the wasm failed: you can preload it to Module["wasmBinary"] manually, or emcc.py will do that for you when generating HTML (but not JS)';
485
#endif
486
#endif
487
}
488
489
async function getWasmBinary(binaryFile) {
490
#if !SINGLE_FILE
491
// If we don't have the binary yet, load it asynchronously using readAsync.
492
if (!wasmBinary) {
493
// Fetch the binary using readAsync
494
try {
495
var response = await readAsync(binaryFile);
496
return new Uint8Array(response);
497
} catch {
498
// Fall back to getBinarySync below;
499
}
500
}
501
#endif
502
503
// Otherwise, getBinarySync should be able to get it synchronously
504
return getBinarySync(binaryFile);
505
}
506
#endif
507
508
#if SPLIT_MODULE
509
{{{ makeModuleReceiveWithVar('loadSplitModule', undefined, 'instantiateSync') }}}
510
var splitModuleProxyHandler = {
511
get(target, moduleName, receiver) {
512
if (moduleName.startsWith('placeholder')) {
513
let secondaryFile;
514
if (moduleName == 'placeholder') { // old format
515
secondaryFile = wasmBinaryFile.slice(0, -5) + '.deferred.wasm';
516
} else { // new format
517
let moduleID = moduleName.split('.')[1];
518
secondaryFile = wasmBinaryFile.slice(0, -5) + '.' + moduleID + '.wasm';
519
}
520
return new Proxy({}, {
521
get(target, base, receiver) {
522
return (...args) => {
523
#if ASYNCIFY == 2
524
throw new Error('Placeholder function "' + base + '" should not be called when using JSPI.');
525
#else
526
#if RUNTIME_DEBUG
527
dbg(`placeholder function called: ${base}`);
528
#endif
529
var imports = {'primary': wasmRawExports};
530
// Replace '.wasm' suffix with '.deferred.wasm'.
531
loadSplitModule(secondaryFile, imports, base);
532
#if RUNTIME_DEBUG
533
dbg('instantiated deferred module, continuing');
534
#endif
535
#if RELOCATABLE
536
// When the table is dynamically laid out, the placeholder functions names
537
// are offsets from the table base. In the main module, the table base is
538
// always 1.
539
base = 1 + parseInt(base);
540
#endif
541
return wasmTable.get({{{ toIndexType('base') }}})(...args);
542
#endif
543
}
544
}
545
});
546
}
547
return target[moduleName];
548
}
549
};
550
#endif
551
552
#if SPLIT_MODULE || !WASM_ASYNC_COMPILATION
553
function instantiateSync(file, info) {
554
var module;
555
var binary = getBinarySync(file);
556
#if NODE_CODE_CACHING
557
if (ENVIRONMENT_IS_NODE) {
558
var v8 = require('node:v8');
559
// Include the V8 version in the cache name, so that we don't try to
560
// load cached code from another version, which fails silently (it seems
561
// to load ok, but we do actually recompile the binary every time).
562
var cachedCodeFile = '{{{ WASM_BINARY_FILE }}}.' + v8.cachedDataVersionTag() + '.cached';
563
cachedCodeFile = locateFile(cachedCodeFile);
564
var hasCached = fs.existsSync(cachedCodeFile);
565
if (hasCached) {
566
#if RUNTIME_DEBUG
567
dbg('NODE_CODE_CACHING: loading module');
568
#endif
569
try {
570
module = v8.deserialize(fs.readFileSync(cachedCodeFile));
571
} catch (e) {
572
err(`NODE_CODE_CACHING: failed to deserialize, bad cache file? (${cachedCodeFile})`);
573
// Save the new compiled code when we have it.
574
hasCached = false;
575
}
576
}
577
}
578
module ||= new WebAssembly.Module(binary);
579
if (ENVIRONMENT_IS_NODE && !hasCached) {
580
#if RUNTIME_DEBUG
581
dbg('NODE_CODE_CACHING: saving module');
582
#endif
583
fs.writeFileSync(cachedCodeFile, v8.serialize(module));
584
}
585
#else // NODE_CODE_CACHING
586
module = new WebAssembly.Module(binary);
587
#endif // NODE_CODE_CACHING
588
var instance = new WebAssembly.Instance(module, info);
589
return [instance, module];
590
}
591
#endif
592
593
#if WASM_ASYNC_COMPILATION
594
async function instantiateArrayBuffer(binaryFile, imports) {
595
try {
596
var binary = await getWasmBinary(binaryFile);
597
var instance = await WebAssembly.instantiate(binary, imports);
598
return instance;
599
} catch (reason) {
600
err(`failed to asynchronously prepare wasm: ${reason}`);
601
#if WASM == 2
602
#if ENVIRONMENT_MAY_BE_NODE || ENVIRONMENT_MAY_BE_SHELL
603
if (globalThis.location) {
604
#endif
605
// WebAssembly compilation failed, try running the JS fallback instead.
606
var search = location.search;
607
if (search.indexOf('_rwasm=0') < 0) {
608
// Reload the page with the `_rwasm=0` argument
609
location.href += (search ? search + '&' : '?') + '_rwasm=0';
610
// Return a promise that never resolves. We don't want to
611
// call abort below, or return an error to our caller.
612
return new Promise(() => {});
613
}
614
#if ENVIRONMENT_MAY_BE_NODE || ENVIRONMENT_MAY_BE_SHELL
615
}
616
#endif
617
#endif // WASM == 2
618
619
#if ASSERTIONS
620
// Warn on some common problems.
621
if (isFileURI(binaryFile)) {
622
err(`warning: Loading from a file URI (${binaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`);
623
}
624
#endif
625
abort(reason);
626
}
627
}
628
629
async function instantiateAsync(binary, binaryFile, imports) {
630
#if !SINGLE_FILE
631
if (!binary
632
#if MIN_SAFARI_VERSION < 150000
633
// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming
634
&& WebAssembly.instantiateStreaming
635
#endif
636
#if ENVIRONMENT_MAY_BE_WEBVIEW
637
// Don't use streaming for file:// delivered objects in a webview, fetch them synchronously.
638
&& !isFileURI(binaryFile)
639
#endif
640
#if ENVIRONMENT_MAY_BE_NODE
641
// Avoid instantiateStreaming() on Node.js environment for now, as while
642
// Node.js v18.1.0 implements it, it does not have a full fetch()
643
// implementation yet.
644
//
645
// Reference:
646
// https://github.com/emscripten-core/emscripten/pull/16917
647
&& !ENVIRONMENT_IS_NODE
648
#endif
649
#if ENVIRONMENT_MAY_BE_SHELL
650
// Shell environments don't have fetch.
651
&& !ENVIRONMENT_IS_SHELL
652
#endif
653
) {
654
try {
655
var response = fetch(binaryFile, {{{ makeModuleReceiveExpr('fetchSettings', "{ credentials: 'same-origin' }") }}});
656
var instantiationResult = await WebAssembly.instantiateStreaming(response, imports);
657
return instantiationResult;
658
} catch (reason) {
659
// We expect the most common failure cause to be a bad MIME type for the binary,
660
// in which case falling back to ArrayBuffer instantiation should work.
661
err(`wasm streaming compile failed: ${reason}`);
662
err('falling back to ArrayBuffer instantiation');
663
// fall back of instantiateArrayBuffer below
664
};
665
}
666
#endif
667
return instantiateArrayBuffer(binaryFile, imports);
668
}
669
#endif // WASM_ASYNC_COMPILATION
670
#endif // SOURCE_PHASE_IMPORTS
671
672
#if !WASM_ESM_INTEGRATION
673
function getWasmImports() {
674
#if PTHREADS || WASM_WORKERS || (IMPORTED_MEMORY && MODULARIZE == 'instance')
675
assignWasmImports();
676
#endif
677
#if ASYNCIFY && (ASSERTIONS || ASYNCIFY == 2)
678
// instrumenting imports is used in asyncify in two ways: to add assertions
679
// that check for proper import use, and for JSPI we use them to set up
680
// the Promise API on the import side.
681
#if PTHREADS
682
// In pthreads builds getWasmImports is called more than once but we only
683
// and the instrument the imports once.
684
if (!wasmImports.__instrumented) {
685
wasmImports.__instrumented = true;
686
Asyncify.instrumentWasmImports(wasmImports);
687
}
688
#else
689
Asyncify.instrumentWasmImports(wasmImports);
690
#endif
691
#endif
692
// prepare imports
693
#if MAIN_MODULE || RELOCATABLE
694
var GOTProxyHandler = new Proxy(new Set({{{ JSON.stringify(Array.from(WEAK_IMPORTS)) }}}), GOTHandler);
695
#endif
696
var imports = {
697
#if MINIFY_WASM_IMPORTED_MODULES
698
'a': wasmImports,
699
#else // MINIFY_WASM_IMPORTED_MODULES
700
'env': wasmImports,
701
'{{{ WASI_MODULE_NAME }}}': wasmImports,
702
#endif // MINIFY_WASM_IMPORTED_MODULES
703
#if MAIN_MODULE || RELOCATABLE
704
'GOT.mem': GOTProxyHandler,
705
'GOT.func': GOTProxyHandler,
706
#endif
707
};
708
#if SPLIT_MODULE
709
imports = new Proxy(imports, splitModuleProxyHandler);
710
#endif
711
return imports;
712
}
713
714
// Create the wasm instance.
715
// Receives the wasm imports, returns the exports.
716
{{{ asyncIf(WASM_ASYNC_COMPILATION) }}}function createWasm() {
717
// Load the wasm module and create an instance of using native support in the JS engine.
718
// handle a generated wasm instance, receiving its exports and
719
// performing other necessary setup
720
/** @param {WebAssembly.Module=} module*/
721
function receiveInstance(instance, module) {
722
#if RUNTIME_DEBUG
723
dbg('receiveInstance')
724
#endif
725
wasmExports = instance.exports;
726
727
#if MAIN_MODULE
728
#if RELOCATABLE
729
wasmExports = relocateExports(wasmExports, {{{ GLOBAL_BASE }}});
730
#endif
731
var origExports = wasmExports;
732
#endif
733
#if SPLIT_MODULE
734
wasmRawExports = wasmExports;
735
#endif
736
737
#if ASYNCIFY
738
wasmExports = Asyncify.instrumentWasmExports(wasmExports);
739
#endif
740
741
#if MAIN_MODULE
742
mergeLibSymbols(wasmExports, 'main')
743
var metadata = getDylinkMetadata(module);
744
#if AUTOLOAD_DYLIBS
745
if (metadata.neededDynlibs) {
746
dynamicLibraries = metadata.neededDynlibs.concat(dynamicLibraries);
747
}
748
#endif
749
#endif
750
751
#if ABORT_ON_WASM_EXCEPTIONS
752
wasmExports = instrumentWasmExportsWithAbort(wasmExports);
753
#endif
754
755
#if MEMORY64 || CAN_ADDRESS_2GB
756
wasmExports = applySignatureConversions(wasmExports);
757
#endif
758
759
#if PTHREADS
760
#if MAIN_MODULE
761
registerTLSInit(wasmExports['_emscripten_tls_init'], instance.exports, metadata);
762
#else
763
registerTLSInit(wasmExports['_emscripten_tls_init']);
764
#endif
765
#endif
766
767
#if hasExportedSymbol('__wasm_apply_data_relocs')
768
__RELOC_FUNCS__.push(wasmExports['__wasm_apply_data_relocs']);
769
#endif
770
771
#if RUNTIME_DEBUG
772
dbg('assigning exports')
773
#endif
774
assignWasmExports(wasmExports);
775
776
#if MAIN_MODULE
777
updateGOT(origExports);
778
#endif
779
780
#if EXPORTED_RUNTIME_METHODS.includes('wasmExports')
781
Module['wasmExports'] = wasmExports;
782
#endif
783
784
#if MAIN_MODULE
785
#if '$LDSO' in addedLibraryItems
786
LDSO.init();
787
#endif
788
loadDylibs();
789
#elif RELOCATABLE
790
reportUndefinedSymbols();
791
#endif
792
793
#if ABORT_ON_WASM_EXCEPTIONS
794
instrumentWasmTableWithAbort();
795
#endif
796
797
#if !IMPORTED_MEMORY
798
updateMemoryViews();
799
#endif
800
801
#if PTHREADS || WASM_WORKERS
802
// We now have the Wasm module loaded up, keep a reference to the compiled module so we can post it to the workers.
803
wasmModule = module;
804
#endif
805
#if WASM_ASYNC_COMPILATION && !MODULARIZE
806
removeRunDependency('wasm-instantiate');
807
#endif
808
return wasmExports;
809
}
810
#if WASM_ASYNC_COMPILATION && !MODULARIZE
811
addRunDependency('wasm-instantiate');
812
#endif
813
814
// Prefer streaming instantiation if available.
815
#if WASM_ASYNC_COMPILATION
816
#if ASSERTIONS
817
// Async compilation can be confusing when an error on the page overwrites Module
818
// (for example, if the order of elements is wrong, and the one defining Module is
819
// later), so we save Module and check it later.
820
var trueModule = Module;
821
#endif
822
function receiveInstantiationResult(result) {
823
// 'result' is a ResultObject object which has both the module and instance.
824
// receiveInstance() will swap in the exports (to Module.asm) so they can be called
825
#if ASSERTIONS
826
assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?');
827
trueModule = null;
828
#endif
829
#if SHARED_MEMORY || MAIN_MODULE
830
return receiveInstance(result['instance'], result['module']);
831
#else
832
// TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line.
833
// When the regression is fixed, can restore the above PTHREADS-enabled path.
834
return receiveInstance(result['instance']);
835
#endif
836
}
837
#endif // WASM_ASYNC_COMPILATION
838
839
var info = getWasmImports();
840
841
#if expectToReceiveOnModule('instantiateWasm')
842
// User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
843
// to manually instantiate the Wasm module themselves. This allows pages to
844
// run the instantiation parallel to any other async startup actions they are
845
// performing.
846
// Also pthreads and wasm workers initialize the wasm instance through this
847
// path.
848
if (Module['instantiateWasm']) {
849
return new Promise((resolve, reject) => {
850
#if ASSERTIONS
851
try {
852
#endif
853
Module['instantiateWasm'](info, (inst, mod) => {
854
resolve(receiveInstance(inst, mod));
855
});
856
#if ASSERTIONS
857
} catch(e) {
858
err(`Module.instantiateWasm callback failed with error: ${e}`);
859
reject(e);
860
}
861
#endif
862
});
863
}
864
#endif
865
866
#if PTHREADS || WASM_WORKERS
867
if ({{{ ENVIRONMENT_IS_WORKER_THREAD() }}}) {
868
// Instantiate from the module that was received via postMessage from
869
// the main thread. We can just use sync instantiation in the worker.
870
#if ASSERTIONS
871
assert(wasmModule, "wasmModule should have been received via postMessage");
872
#endif
873
var instance = new WebAssembly.Instance(wasmModule, getWasmImports());
874
return receiveInstance(instance, wasmModule);
875
}
876
#endif
877
878
#if SOURCE_PHASE_IMPORTS
879
var instance = await WebAssembly.instantiate(wasmModule, info);
880
var exports = receiveInstantiationResult({instance, 'module':wasmModule});
881
return exports;
882
#else
883
wasmBinaryFile ??= findWasmBinary();
884
#if WASM_ASYNC_COMPILATION
885
#if RUNTIME_DEBUG
886
dbg('asynchronously preparing wasm');
887
#endif
888
var result = await instantiateAsync(wasmBinary, wasmBinaryFile, info);
889
var exports = receiveInstantiationResult(result);
890
return exports;
891
#else // WASM_ASYNC_COMPILATION
892
var result = instantiateSync(wasmBinaryFile, info);
893
#if PTHREADS || MAIN_MODULE
894
return receiveInstance(result[0], result[1]);
895
#else
896
// TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193,
897
// the above line no longer optimizes out down to the following line.
898
// When the regression is fixed, we can remove this if/else.
899
return receiveInstance(result[0]);
900
#endif
901
#endif // WASM_ASYNC_COMPILATION
902
#endif // SOURCE_PHASE_IMPORTS
903
}
904
#endif // WASM_ESM_INTEGRATION
905
906
#if !WASM_BIGINT
907
// Globals used by JS i64 conversions (see makeSetValue)
908
var tempDouble;
909
var tempI64;
910
#endif
911
912
#if RETAIN_COMPILER_SETTINGS
913
var compilerSettings = {{{ JSON.stringify(makeRetainedCompilerSettings()) }}} ;
914
915
function getCompilerSetting(name) {
916
if (!(name in compilerSettings)) return 'invalid compiler setting: ' + name;
917
return compilerSettings[name];
918
}
919
#endif // RETAIN_COMPILER_SETTINGS
920
921
#if MAIN_MODULE && ASYNCIFY
922
// With MAIN_MODULE + ASYNCIFY the normal method of placing stub functions in
923
// wasmImports for as-yet-undefined symbols doesn't work since ASYNCIFY then
924
// wraps these stub functions and we can't then replace them directly. Instead
925
// the stub functions call into `asyncifyStubs` which gets populated by the
926
// dynamic linker as symbols are loaded.
927
var asyncifyStubs = {};
928
#endif
929
930