@thenick775/mgba-wasm 2.1.0 → 2.1.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mgba.js CHANGED
@@ -48,6 +48,11 @@ var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIR
48
48
  // it with a specific name.
49
49
  var ENVIRONMENT_IS_PTHREAD = ENVIRONMENT_IS_WORKER && self.name?.startsWith('em-pthread');
50
50
 
51
+ if (ENVIRONMENT_IS_PTHREAD) {
52
+ assert(!globalThis.moduleLoaded, 'module should only be loaded once on each pthread worker');
53
+ globalThis.moduleLoaded = true;
54
+ }
55
+
51
56
  // --pre-jses are emitted after the Module integration code, so that they can
52
57
  // refer to Module (if they choose; they can also define Module)
53
58
  // include: /home/mgba/src/src/platform/wasm/pre.js
@@ -479,6 +484,18 @@ Module.setCoreSettings = (coreSettings) => {
479
484
 
480
485
  if (coreSettings?.frameSkip !== undefined)
481
486
  setIntegerCoreSetting('frameSkip', coreSettings.frameSkip);
487
+
488
+ if (coreSettings.audioSampleRate !== undefined)
489
+ setIntegerCoreSetting('audioSampleRate', coreSettings.audioSampleRate);
490
+
491
+ if (coreSettings.audioBufferSize !== undefined)
492
+ setIntegerCoreSetting('audioBufferSize', coreSettings.audioBufferSize);
493
+
494
+ if (coreSettings.videoSync !== undefined)
495
+ setIntegerCoreSetting('videoSync', coreSettings.videoSync);
496
+
497
+ if (coreSettings.audioSync !== undefined)
498
+ setIntegerCoreSetting('audioSync', coreSettings.audioSync);
482
499
  };
483
500
  // end include: /home/mgba/src/src/platform/wasm/pre.js
484
501
 
@@ -508,6 +525,12 @@ function locateFile(path) {
508
525
  // Hooks that are implemented differently in different runtime environments.
509
526
  var readAsync, readBinary;
510
527
 
528
+ if (ENVIRONMENT_IS_SHELL) {
529
+
530
+ if ((typeof process == 'object' && typeof require === 'function') || typeof window == 'object' || typeof WorkerGlobalScope != 'undefined') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)');
531
+
532
+ } else
533
+
511
534
  // Note that this includes Node.js workers when relevant (pthreads is enabled).
512
535
  // Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and
513
536
  // ENVIRONMENT_IS_NODE.
@@ -534,6 +557,8 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
534
557
  scriptDirectory = scriptDirectory.slice(0, scriptDirectory.replace(/[?#].*/, '').lastIndexOf('/')+1);
535
558
  }
536
559
 
560
+ if (!(typeof window == 'object' || typeof WorkerGlobalScope != 'undefined')) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)');
561
+
537
562
  {
538
563
  // include: web_or_worker_shell_read.js
539
564
  if (ENVIRONMENT_IS_WORKER) {
@@ -547,6 +572,7 @@ if (ENVIRONMENT_IS_WORKER) {
547
572
  }
548
573
 
549
574
  readAsync = async (url) => {
575
+ assert(!isFileURI(url), "readAsync does not work with file:// URLs");
550
576
  var response = await fetch(url, { credentials: 'same-origin' });
551
577
  if (response.ok) {
552
578
  return response.arrayBuffer();
@@ -557,6 +583,7 @@ if (ENVIRONMENT_IS_WORKER) {
557
583
  }
558
584
  } else
559
585
  {
586
+ throw new Error('environment detection error');
560
587
  }
561
588
 
562
589
  var out = Module['print'] || console.log.bind(console);
@@ -567,17 +594,49 @@ Object.assign(Module, moduleOverrides);
567
594
  // Free the object hierarchy contained in the overrides, this lets the GC
568
595
  // reclaim data used.
569
596
  moduleOverrides = null;
597
+ checkIncomingModuleAPI();
570
598
 
571
599
  // Emit code to handle expected values on the Module object. This applies Module.x
572
600
  // to the proper local x. This has two benefits: first, we only emit it if it is
573
601
  // expected to arrive, and second, by using a local everywhere else that can be
574
602
  // minified.
575
603
 
576
- if (Module['arguments']) arguments_ = Module['arguments'];
604
+ if (Module['arguments']) arguments_ = Module['arguments'];legacyModuleProp('arguments', 'arguments_');
577
605
 
578
- if (Module['thisProgram']) thisProgram = Module['thisProgram'];
606
+ if (Module['thisProgram']) thisProgram = Module['thisProgram'];legacyModuleProp('thisProgram', 'thisProgram');
579
607
 
580
608
  // perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message
609
+ // Assertions on removed incoming Module JS APIs.
610
+ assert(typeof Module['memoryInitializerPrefixURL'] == 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead');
611
+ assert(typeof Module['pthreadMainPrefixURL'] == 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead');
612
+ assert(typeof Module['cdInitializerPrefixURL'] == 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead');
613
+ assert(typeof Module['filePackagePrefixURL'] == 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead');
614
+ assert(typeof Module['read'] == 'undefined', 'Module.read option was removed');
615
+ assert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)');
616
+ assert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)');
617
+ assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)');
618
+ assert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY');
619
+ legacyModuleProp('asm', 'wasmExports');
620
+ legacyModuleProp('readAsync', 'readAsync');
621
+ legacyModuleProp('readBinary', 'readBinary');
622
+ legacyModuleProp('setWindowTitle', 'setWindowTitle');
623
+ var IDBFS = 'IDBFS is no longer included by default; build with -lidbfs.js';
624
+ var PROXYFS = 'PROXYFS is no longer included by default; build with -lproxyfs.js';
625
+ var WORKERFS = 'WORKERFS is no longer included by default; build with -lworkerfs.js';
626
+ var FETCHFS = 'FETCHFS is no longer included by default; build with -lfetchfs.js';
627
+ var ICASEFS = 'ICASEFS is no longer included by default; build with -licasefs.js';
628
+ var JSFILEFS = 'JSFILEFS is no longer included by default; build with -ljsfilefs.js';
629
+ var OPFS = 'OPFS is no longer included by default; build with -lopfs.js';
630
+
631
+ var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js';
632
+
633
+ assert(
634
+ ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER || ENVIRONMENT_IS_NODE, 'Pthreads do not work in this environment yet (need Web Workers, or an alternative to them)');
635
+
636
+ assert(!ENVIRONMENT_IS_NODE, 'node environment detected but not enabled at build time. Add `node` to `-sENVIRONMENT` to enable.');
637
+
638
+ assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.');
639
+
581
640
  // end include: shell.js
582
641
 
583
642
  // include: preamble.js
@@ -591,7 +650,11 @@ if (Module['thisProgram']) thisProgram = Module['thisProgram'];
591
650
  // An online HTML version (which may be of a different version of Emscripten)
592
651
  // is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
593
652
 
594
- var wasmBinary = Module['wasmBinary'];
653
+ var wasmBinary = Module['wasmBinary'];legacyModuleProp('wasmBinary', 'wasmBinary');
654
+
655
+ if (typeof WebAssembly != 'object') {
656
+ err('no native wasm support detected');
657
+ }
595
658
 
596
659
  // Wasm globals
597
660
 
@@ -620,13 +683,13 @@ var EXITSTATUS;
620
683
  /** @type {function(*, string=)} */
621
684
  function assert(condition, text) {
622
685
  if (!condition) {
623
- // This build was created without ASSERTIONS defined. `assert()` should not
624
- // ever be called in this configuration but in case there are callers in
625
- // the wild leave this simple abort() implementation here for now.
626
- abort(text);
686
+ abort('Assertion failed' + (text ? ': ' + text : ''));
627
687
  }
628
688
  }
629
689
 
690
+ // We used to include malloc/free by default in the past. Show a helpful error in
691
+ // builds with assertions.
692
+
630
693
  // Memory management
631
694
 
632
695
  var HEAP,
@@ -663,10 +726,176 @@ var isFileURI = (filename) => filename.startsWith('file://');
663
726
 
664
727
  // include: runtime_shared.js
665
728
  // include: runtime_stack_check.js
729
+ // Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
730
+ function writeStackCookie() {
731
+ var max = _emscripten_stack_get_end();
732
+ assert((max & 3) == 0);
733
+ // If the stack ends at address zero we write our cookies 4 bytes into the
734
+ // stack. This prevents interference with SAFE_HEAP and ASAN which also
735
+ // monitor writes to address zero.
736
+ if (max == 0) {
737
+ max += 4;
738
+ }
739
+ // The stack grow downwards towards _emscripten_stack_get_end.
740
+ // We write cookies to the final two words in the stack and detect if they are
741
+ // ever overwritten.
742
+ HEAPU32[((max)>>2)] = 0x02135467;
743
+ HEAPU32[(((max)+(4))>>2)] = 0x89BACDFE;
744
+ // Also test the global address 0 for integrity.
745
+ HEAPU32[((0)>>2)] = 1668509029;
746
+ }
747
+
748
+ function checkStackCookie() {
749
+ if (ABORT) return;
750
+ var max = _emscripten_stack_get_end();
751
+ // See writeStackCookie().
752
+ if (max == 0) {
753
+ max += 4;
754
+ }
755
+ var cookie1 = HEAPU32[((max)>>2)];
756
+ var cookie2 = HEAPU32[(((max)+(4))>>2)];
757
+ if (cookie1 != 0x02135467 || cookie2 != 0x89BACDFE) {
758
+ abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`);
759
+ }
760
+ // Also test the global address 0 for integrity.
761
+ if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) {
762
+ abort('Runtime error: The application has corrupted its heap memory area (address zero)!');
763
+ }
764
+ }
666
765
  // end include: runtime_stack_check.js
667
766
  // include: runtime_exceptions.js
668
767
  // end include: runtime_exceptions.js
669
768
  // include: runtime_debug.js
769
+ // Endianness check
770
+ (() => {
771
+ var h16 = new Int16Array(1);
772
+ var h8 = new Int8Array(h16.buffer);
773
+ h16[0] = 0x6373;
774
+ if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)';
775
+ })();
776
+
777
+ if (Module['ENVIRONMENT']) {
778
+ throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)');
779
+ }
780
+
781
+ function legacyModuleProp(prop, newName, incoming=true) {
782
+ if (!Object.getOwnPropertyDescriptor(Module, prop)) {
783
+ Object.defineProperty(Module, prop, {
784
+ configurable: true,
785
+ get() {
786
+ let extra = incoming ? ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)' : '';
787
+ abort(`\`Module.${prop}\` has been replaced by \`${newName}\`` + extra);
788
+
789
+ }
790
+ });
791
+ }
792
+ }
793
+
794
+ function consumedModuleProp(prop) {
795
+ if (!Object.getOwnPropertyDescriptor(Module, prop)) {
796
+ Object.defineProperty(Module, prop, {
797
+ configurable: true,
798
+ set() {
799
+ abort(`Attempt to set \`Module.${prop}\` after it has already been processed. This can happen, for example, when code is injected via '--post-js' rather than '--pre-js'`);
800
+
801
+ }
802
+ });
803
+ }
804
+ }
805
+
806
+ function ignoredModuleProp(prop) {
807
+ if (Object.getOwnPropertyDescriptor(Module, prop)) {
808
+ abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`);
809
+ }
810
+ }
811
+
812
+ // forcing the filesystem exports a few things by default
813
+ function isExportedByForceFilesystem(name) {
814
+ return name === 'FS_createPath' ||
815
+ name === 'FS_createDataFile' ||
816
+ name === 'FS_createPreloadedFile' ||
817
+ name === 'FS_unlink' ||
818
+ name === 'addRunDependency' ||
819
+ // The old FS has some functionality that WasmFS lacks.
820
+ name === 'FS_createLazyFile' ||
821
+ name === 'FS_createDevice' ||
822
+ name === 'removeRunDependency';
823
+ }
824
+
825
+ /**
826
+ * Intercept access to a global symbol. This enables us to give informative
827
+ * warnings/errors when folks attempt to use symbols they did not include in
828
+ * their build, or no symbols that no longer exist.
829
+ */
830
+ function hookGlobalSymbolAccess(sym, func) {
831
+ if (typeof globalThis != 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) {
832
+ Object.defineProperty(globalThis, sym, {
833
+ configurable: true,
834
+ get() {
835
+ func();
836
+ return undefined;
837
+ }
838
+ });
839
+ }
840
+ }
841
+
842
+ function missingGlobal(sym, msg) {
843
+ hookGlobalSymbolAccess(sym, () => {
844
+ warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`);
845
+ });
846
+ }
847
+
848
+ missingGlobal('buffer', 'Please use HEAP8.buffer or wasmMemory.buffer');
849
+ missingGlobal('asm', 'Please use wasmExports instead');
850
+
851
+ function missingLibrarySymbol(sym) {
852
+ hookGlobalSymbolAccess(sym, () => {
853
+ // Can't `abort()` here because it would break code that does runtime
854
+ // checks. e.g. `if (typeof SDL === 'undefined')`.
855
+ var msg = `\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`;
856
+ // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in
857
+ // library.js, which means $name for a JS name with no prefix, or name
858
+ // for a JS name like _name.
859
+ var librarySymbol = sym;
860
+ if (!librarySymbol.startsWith('_')) {
861
+ librarySymbol = '$' + sym;
862
+ }
863
+ msg += ` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`;
864
+ if (isExportedByForceFilesystem(sym)) {
865
+ msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you';
866
+ }
867
+ warnOnce(msg);
868
+ });
869
+
870
+ // Any symbol that is not included from the JS library is also (by definition)
871
+ // not exported on the Module object.
872
+ unexportedRuntimeSymbol(sym);
873
+ }
874
+
875
+ function unexportedRuntimeSymbol(sym) {
876
+ if (ENVIRONMENT_IS_PTHREAD) {
877
+ return;
878
+ }
879
+ if (!Object.getOwnPropertyDescriptor(Module, sym)) {
880
+ Object.defineProperty(Module, sym, {
881
+ configurable: true,
882
+ get() {
883
+ var msg = `'${sym}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`;
884
+ if (isExportedByForceFilesystem(sym)) {
885
+ msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you';
886
+ }
887
+ abort(msg);
888
+ }
889
+ });
890
+ }
891
+ }
892
+
893
+ // Used by XXXXX_DEBUG settings to output debug messages.
894
+ function dbg(...args) {
895
+ // TODO(sbc): Make this configurable somehow. Its not always convenient for
896
+ // logging to show up as warnings.
897
+ console.warn(...args);
898
+ }
670
899
  // end include: runtime_debug.js
671
900
  // include: memoryprofiler.js
672
901
  // end include: memoryprofiler.js
@@ -675,6 +904,10 @@ var isFileURI = (filename) => filename.startsWith('file://');
675
904
  // This code runs only on pthread web workers and handles pthread setup
676
905
  // and communication with the main thread via postMessage.
677
906
 
907
+ // Unique ID of the current pthread worker (zero on non-pthread-workers
908
+ // including the main thread).
909
+ var workerID = 0;
910
+
678
911
  if (ENVIRONMENT_IS_PTHREAD) {
679
912
  var wasmModuleReceived;
680
913
 
@@ -688,6 +921,7 @@ if (ENVIRONMENT_IS_PTHREAD) {
688
921
 
689
922
  if (!Module['printErr'])
690
923
  err = threadPrintErr;
924
+ dbg = threadPrintErr;
691
925
  function threadAlert(...args) {
692
926
  var text = args.join(' ');
693
927
  postMessage({cmd: 'alert', text, threadId: _pthread_self()});
@@ -704,6 +938,7 @@ if (ENVIRONMENT_IS_PTHREAD) {
704
938
  //dbg('msgData: ' + Object.keys(msgData));
705
939
  var cmd = msgData.cmd;
706
940
  if (cmd === 'load') { // Preload command that is called once per worker to parse and load the Emscripten code.
941
+ workerID = msgData.workerID;
707
942
 
708
943
  // Until we initialize the runtime, queue up any further incoming messages.
709
944
  let messageQueue = [];
@@ -742,6 +977,7 @@ if (ENVIRONMENT_IS_PTHREAD) {
742
977
 
743
978
  wasmModuleReceived(msgData.wasmModule);
744
979
  } else if (cmd === 'run') {
980
+ assert(msgData.pthread_ptr);
745
981
  // Call inside JS module to set up the stack frame for this pthread in JS module scope.
746
982
  // This needs to be the first thing that we do, as we cannot call to any C/C++ functions
747
983
  // until the thread stack is initialized.
@@ -784,6 +1020,8 @@ if (ENVIRONMENT_IS_PTHREAD) {
784
1020
  err(msgData);
785
1021
  }
786
1022
  } catch(ex) {
1023
+ err(`worker: onmessage() captured an uncaught exception: ${ex}`);
1024
+ if (ex?.stack) err(ex.stack);
787
1025
  __emscripten_thread_crashed();
788
1026
  throw ex;
789
1027
  }
@@ -810,6 +1048,11 @@ function updateMemoryViews() {
810
1048
  }
811
1049
 
812
1050
  // end include: runtime_shared.js
1051
+ assert(!Module['STACK_SIZE'], 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time')
1052
+
1053
+ assert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray != undefined && Int32Array.prototype.set != undefined,
1054
+ 'JS engine does not provide full typed array support');
1055
+
813
1056
  // In non-standalone/normal mode, we create the memory here.
814
1057
  // include: runtime_init_memory.js
815
1058
  // Create the wasm memory. (Note: this only applies if IMPORTED_MEMORY is defined)
@@ -822,8 +1065,9 @@ if (!ENVIRONMENT_IS_PTHREAD) {
822
1065
  wasmMemory = Module['wasmMemory'];
823
1066
  } else
824
1067
  {
825
- var INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 268435456;
1068
+ var INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 268435456;legacyModuleProp('INITIAL_MEMORY', 'INITIAL_MEMORY');
826
1069
 
1070
+ assert(INITIAL_MEMORY >= 65536, 'INITIAL_MEMORY should be larger than STACK_SIZE, was ' + INITIAL_MEMORY + '! (STACK_SIZE=' + 65536 + ')');
827
1071
  /** @suppress {checkTypes} */
828
1072
  wasmMemory = new WebAssembly.Memory({
829
1073
  'initial': INITIAL_MEMORY / 65536,
@@ -838,20 +1082,25 @@ if (!ENVIRONMENT_IS_PTHREAD) {
838
1082
  // end include: runtime_init_memory.js
839
1083
 
840
1084
  function preRun() {
1085
+ assert(!ENVIRONMENT_IS_PTHREAD); // PThreads reuse the runtime from the main thread.
841
1086
  if (Module['preRun']) {
842
1087
  if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
843
1088
  while (Module['preRun'].length) {
844
1089
  addOnPreRun(Module['preRun'].shift());
845
1090
  }
846
1091
  }
1092
+ consumedModuleProp('preRun');
847
1093
  callRuntimeCallbacks(onPreRuns);
848
1094
  }
849
1095
 
850
1096
  function initRuntime() {
1097
+ assert(!runtimeInitialized);
851
1098
  runtimeInitialized = true;
852
1099
 
853
1100
  if (ENVIRONMENT_IS_PTHREAD) return startWorker(Module);
854
1101
 
1102
+ checkStackCookie();
1103
+
855
1104
  if (!Module['noFSInit'] && !FS.initialized) FS.init();
856
1105
  TTY.init();
857
1106
 
@@ -861,10 +1110,12 @@ TTY.init();
861
1110
  }
862
1111
 
863
1112
  function preMain() {
1113
+ checkStackCookie();
864
1114
 
865
1115
  }
866
1116
 
867
1117
  function postRun() {
1118
+ checkStackCookie();
868
1119
  if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread.
869
1120
 
870
1121
  if (Module['postRun']) {
@@ -873,6 +1124,7 @@ function postRun() {
873
1124
  addOnPostRun(Module['postRun'].shift());
874
1125
  }
875
1126
  }
1127
+ consumedModuleProp('postRun');
876
1128
 
877
1129
  callRuntimeCallbacks(onPostRuns);
878
1130
  }
@@ -886,9 +1138,15 @@ function postRun() {
886
1138
  // the dependencies are met.
887
1139
  var runDependencies = 0;
888
1140
  var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled
1141
+ var runDependencyTracking = {};
1142
+ var runDependencyWatcher = null;
889
1143
 
890
1144
  function getUniqueRunDependency(id) {
891
- return id;
1145
+ var orig = id;
1146
+ while (1) {
1147
+ if (!runDependencyTracking[id]) return id;
1148
+ id = orig + Math.random();
1149
+ }
892
1150
  }
893
1151
 
894
1152
  function addRunDependency(id) {
@@ -896,6 +1154,33 @@ function addRunDependency(id) {
896
1154
 
897
1155
  Module['monitorRunDependencies']?.(runDependencies);
898
1156
 
1157
+ if (id) {
1158
+ assert(!runDependencyTracking[id]);
1159
+ runDependencyTracking[id] = 1;
1160
+ if (runDependencyWatcher === null && typeof setInterval != 'undefined') {
1161
+ // Check for missing dependencies every few seconds
1162
+ runDependencyWatcher = setInterval(() => {
1163
+ if (ABORT) {
1164
+ clearInterval(runDependencyWatcher);
1165
+ runDependencyWatcher = null;
1166
+ return;
1167
+ }
1168
+ var shown = false;
1169
+ for (var dep in runDependencyTracking) {
1170
+ if (!shown) {
1171
+ shown = true;
1172
+ err('still waiting on run dependencies:');
1173
+ }
1174
+ err(`dependency: ${dep}`);
1175
+ }
1176
+ if (shown) {
1177
+ err('(end of list)');
1178
+ }
1179
+ }, 10000);
1180
+ }
1181
+ } else {
1182
+ err('warning: run dependency added without ID');
1183
+ }
899
1184
  }
900
1185
 
901
1186
  function removeRunDependency(id) {
@@ -903,7 +1188,17 @@ function removeRunDependency(id) {
903
1188
 
904
1189
  Module['monitorRunDependencies']?.(runDependencies);
905
1190
 
1191
+ if (id) {
1192
+ assert(runDependencyTracking[id]);
1193
+ delete runDependencyTracking[id];
1194
+ } else {
1195
+ err('warning: run dependency removed without ID');
1196
+ }
906
1197
  if (runDependencies == 0) {
1198
+ if (runDependencyWatcher !== null) {
1199
+ clearInterval(runDependencyWatcher);
1200
+ runDependencyWatcher = null;
1201
+ }
907
1202
  if (dependenciesFulfilled) {
908
1203
  var callback = dependenciesFulfilled;
909
1204
  dependenciesFulfilled = null;
@@ -923,8 +1218,6 @@ function abort(what) {
923
1218
 
924
1219
  ABORT = true;
925
1220
 
926
- what += '. Build with -sASSERTIONS for more info.';
927
-
928
1221
  // Use a wasm runtime error, because a JS error might be seen as a foreign
929
1222
  // exception, which means we'd run destructors on it. We need the error to
930
1223
  // simply make the program stop.
@@ -948,6 +1241,17 @@ function abort(what) {
948
1241
  throw e;
949
1242
  }
950
1243
 
1244
+ function createExportWrapper(name, nargs) {
1245
+ return (...args) => {
1246
+ assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`);
1247
+ var f = wasmExports[name];
1248
+ assert(f, `exported native function \`${name}\` not found`);
1249
+ // Only assert for too many arguments. Too few can be valid since the missing arguments will be zero filled.
1250
+ assert(args.length <= nargs, `native function \`${name}\` called with ${args.length} args but expects ${nargs}`);
1251
+ return f(...args);
1252
+ };
1253
+ }
1254
+
951
1255
  var wasmBinaryFile;
952
1256
  function findWasmBinary() {
953
1257
  if (Module['locateFile']) {
@@ -991,6 +1295,10 @@ async function instantiateArrayBuffer(binaryFile, imports) {
991
1295
  } catch (reason) {
992
1296
  err(`failed to asynchronously prepare wasm: ${reason}`);
993
1297
 
1298
+ // Warn on some common problems.
1299
+ if (isFileURI(wasmBinaryFile)) {
1300
+ err(`warning: Loading from a file URI (${wasmBinaryFile}) 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`);
1301
+ }
994
1302
  abort(reason);
995
1303
  }
996
1304
  }
@@ -1038,6 +1346,7 @@ async function createWasm() {
1038
1346
 
1039
1347
  wasmTable = wasmExports['__indirect_function_table'];
1040
1348
 
1349
+ assert(wasmTable, 'table not found in wasm exports');
1041
1350
 
1042
1351
  // We now have the Wasm module loaded up, keep a reference to the compiled module so we can post it to the workers.
1043
1352
  wasmModule = module;
@@ -1048,9 +1357,15 @@ async function createWasm() {
1048
1357
  addRunDependency('wasm-instantiate');
1049
1358
 
1050
1359
  // Prefer streaming instantiation if available.
1360
+ // Async compilation can be confusing when an error on the page overwrites Module
1361
+ // (for example, if the order of elements is wrong, and the one defining Module is
1362
+ // later), so we save Module and check it later.
1363
+ var trueModule = Module;
1051
1364
  function receiveInstantiationResult(result) {
1052
1365
  // 'result' is a ResultObject object which has both the module and instance.
1053
1366
  // receiveInstance() will swap in the exports (to Module.asm) so they can be called
1367
+ assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?');
1368
+ trueModule = null;
1054
1369
  return receiveInstance(result['instance'], result['module']);
1055
1370
  }
1056
1371
 
@@ -1064,10 +1379,15 @@ async function createWasm() {
1064
1379
  // path.
1065
1380
  if (Module['instantiateWasm']) {
1066
1381
  return new Promise((resolve, reject) => {
1382
+ try {
1067
1383
  Module['instantiateWasm'](info, (mod, inst) => {
1068
1384
  receiveInstance(mod, inst);
1069
1385
  resolve(mod.exports);
1070
1386
  });
1387
+ } catch(e) {
1388
+ err(`Module.instantiateWasm callback failed with error: ${e}`);
1389
+ reject(e);
1390
+ }
1071
1391
  });
1072
1392
  }
1073
1393
 
@@ -1098,32 +1418,39 @@ async function createWasm() {
1098
1418
  // === Body ===
1099
1419
 
1100
1420
  var ASM_CONSTS = {
1101
- 310240: () => { console.error("thread instantiation failed") },
1102
- 310289: ($0, $1) => { Module.canvas.width = $0; Module.canvas.height = $1; },
1103
- 310346: ($0, $1, $2, $3, $4, $5, $6) => { Module.version = { gitCommit : UTF8ToString($0), gitShort : UTF8ToString($1), gitBranch : UTF8ToString($2), gitRevision : $3, binaryName : UTF8ToString($4), projectName : UTF8ToString($5), projectVersion : UTF8ToString($6) }; },
1104
- 310578: ($0, $1) => { const funcPtr = $0; const ctx = $1; const func = wasmTable.get(funcPtr); if (func) func(ctx); },
1105
- 310676: ($0, $1) => { const funcPtr = $0; const ctx = $1; const func = wasmTable.get(funcPtr); if (func) func(ctx); },
1106
- 310774: ($0, $1) => { const funcPtr = $0; const ctx = $1; const func = wasmTable.get(funcPtr); if (func) func(ctx); },
1107
- 310872: ($0, $1) => { const funcPtr = $0; const ctx = $1; const func = wasmTable.get(funcPtr); if (func) func(ctx); },
1108
- 310970: ($0, $1) => { const funcPtr = $0; const ctx = $1; const func = wasmTable.get(funcPtr); if (func) func(ctx); },
1109
- 311068: ($0, $1) => { const funcPtr = $0; const ctx = $1; const func = wasmTable.get(funcPtr); if (func) func(ctx); },
1110
- 311166: () => { FS.syncfs(function (err) { assert(!err); }) },
1111
- 311210: ($0) => { var str = UTF8ToString($0) + '\n\n' + 'Abort/Retry/Ignore/AlwaysIgnore? [ariA] :'; var reply = window.prompt(str, "i"); if (reply === null) { reply = "i"; } return allocate(intArrayFromString(reply), 'i8', ALLOC_NORMAL); },
1112
- 311435: () => { if (typeof(AudioContext) !== 'undefined') { return true; } else if (typeof(webkitAudioContext) !== 'undefined') { return true; } return false; },
1113
- 311582: () => { if ((typeof(navigator.mediaDevices) !== 'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !== 'undefined')) { return true; } else if (typeof(navigator.webkitGetUserMedia) !== 'undefined') { return true; } return false; },
1114
- 311816: ($0) => { if(typeof(Module['SDL2']) === 'undefined') { Module['SDL2'] = {}; } var SDL2 = Module['SDL2']; if (!$0) { SDL2.audio = {}; } else { SDL2.capture = {}; } if (!SDL2.audioContext) { if (typeof(AudioContext) !== 'undefined') { SDL2.audioContext = new AudioContext(); } else if (typeof(webkitAudioContext) !== 'undefined') { SDL2.audioContext = new webkitAudioContext(); } if (SDL2.audioContext) { if ((typeof navigator.userActivation) === 'undefined') { autoResumeAudioContext(SDL2.audioContext); } } } return SDL2.audioContext === undefined ? -1 : 0; },
1115
- 312368: () => { var SDL2 = Module['SDL2']; return SDL2.audioContext.sampleRate; },
1116
- 312436: ($0, $1, $2, $3) => { var SDL2 = Module['SDL2']; var have_microphone = function(stream) { if (SDL2.capture.silenceTimer !== undefined) { clearInterval(SDL2.capture.silenceTimer); SDL2.capture.silenceTimer = undefined; SDL2.capture.silenceBuffer = undefined } SDL2.capture.mediaStreamNode = SDL2.audioContext.createMediaStreamSource(stream); SDL2.capture.scriptProcessorNode = SDL2.audioContext.createScriptProcessor($1, $0, 1); SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) { if ((SDL2 === undefined) || (SDL2.capture === undefined)) { return; } audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0); SDL2.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer; dynCall('vi', $2, [$3]); }; SDL2.capture.mediaStreamNode.connect(SDL2.capture.scriptProcessorNode); SDL2.capture.scriptProcessorNode.connect(SDL2.audioContext.destination); SDL2.capture.stream = stream; }; var no_microphone = function(error) { }; SDL2.capture.silenceBuffer = SDL2.audioContext.createBuffer($0, $1, SDL2.audioContext.sampleRate); SDL2.capture.silenceBuffer.getChannelData(0).fill(0.0); var silence_callback = function() { SDL2.capture.currentCaptureBuffer = SDL2.capture.silenceBuffer; dynCall('vi', $2, [$3]); }; SDL2.capture.silenceTimer = setInterval(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1000); if ((navigator.mediaDevices !== undefined) && (navigator.mediaDevices.getUserMedia !== undefined)) { navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(have_microphone).catch(no_microphone); } else if (navigator.webkitGetUserMedia !== undefined) { navigator.webkitGetUserMedia({ audio: true, video: false }, have_microphone, no_microphone); } },
1117
- 314129: ($0, $1, $2, $3) => { var SDL2 = Module['SDL2']; SDL2.audio.scriptProcessorNode = SDL2.audioContext['createScriptProcessor']($1, 0, $0); SDL2.audio.scriptProcessorNode['onaudioprocess'] = function (e) { if ((SDL2 === undefined) || (SDL2.audio === undefined)) { return; } if (SDL2.audio.silenceTimer !== undefined) { clearInterval(SDL2.audio.silenceTimer); SDL2.audio.silenceTimer = undefined; SDL2.audio.silenceBuffer = undefined; } SDL2.audio.currentOutputBuffer = e['outputBuffer']; dynCall('vi', $2, [$3]); }; SDL2.audio.scriptProcessorNode['connect'](SDL2.audioContext['destination']); if (SDL2.audioContext.state === 'suspended') { SDL2.audio.silenceBuffer = SDL2.audioContext.createBuffer($0, $1, SDL2.audioContext.sampleRate); SDL2.audio.silenceBuffer.getChannelData(0).fill(0.0); var silence_callback = function() { if ((typeof navigator.userActivation) !== 'undefined') { if (navigator.userActivation.hasBeenActive) { SDL2.audioContext.resume(); } } SDL2.audio.currentOutputBuffer = SDL2.audio.silenceBuffer; dynCall('vi', $2, [$3]); SDL2.audio.currentOutputBuffer = undefined; }; SDL2.audio.silenceTimer = setInterval(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1000); } },
1118
- 315304: ($0, $1) => { var SDL2 = Module['SDL2']; var numChannels = SDL2.capture.currentCaptureBuffer.numberOfChannels; for (var c = 0; c < numChannels; ++c) { var channelData = SDL2.capture.currentCaptureBuffer.getChannelData(c); if (channelData.length != $1) { throw 'Web Audio capture buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!'; } if (numChannels == 1) { for (var j = 0; j < $1; ++j) { setValue($0 + (j * 4), channelData[j], 'float'); } } else { for (var j = 0; j < $1; ++j) { setValue($0 + (((j * numChannels) + c) * 4), channelData[j], 'float'); } } } },
1119
- 315909: ($0, $1) => { var SDL2 = Module['SDL2']; var buf = $0 >>> 2; var numChannels = SDL2.audio.currentOutputBuffer['numberOfChannels']; for (var c = 0; c < numChannels; ++c) { var channelData = SDL2.audio.currentOutputBuffer['getChannelData'](c); if (channelData.length != $1) { throw 'Web Audio output buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!'; } for (var j = 0; j < $1; ++j) { channelData[j] = HEAPF32[buf + (j*numChannels + c)]; } } },
1120
- 316398: ($0) => { var SDL2 = Module['SDL2']; if ($0) { if (SDL2.capture.silenceTimer !== undefined) { clearInterval(SDL2.capture.silenceTimer); } if (SDL2.capture.stream !== undefined) { var tracks = SDL2.capture.stream.getAudioTracks(); for (var i = 0; i < tracks.length; i++) { SDL2.capture.stream.removeTrack(tracks[i]); } } if (SDL2.capture.scriptProcessorNode !== undefined) { SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {}; SDL2.capture.scriptProcessorNode.disconnect(); } if (SDL2.capture.mediaStreamNode !== undefined) { SDL2.capture.mediaStreamNode.disconnect(); } SDL2.capture = undefined; } else { if (SDL2.audio.scriptProcessorNode != undefined) { SDL2.audio.scriptProcessorNode.disconnect(); } if (SDL2.audio.silenceTimer !== undefined) { clearInterval(SDL2.audio.silenceTimer); } SDL2.audio = undefined; } if ((SDL2.audioContext !== undefined) && (SDL2.audio === undefined) && (SDL2.capture === undefined)) { SDL2.audioContext.close(); SDL2.audioContext = undefined; } },
1121
- 317404: ($0, $1, $2) => { var w = $0; var h = $1; var pixels = $2; if (!Module['SDL2']) Module['SDL2'] = {}; var SDL2 = Module['SDL2']; if (SDL2.ctxCanvas !== Module['canvas']) { SDL2.ctx = Module['createContext'](Module['canvas'], false, true); SDL2.ctxCanvas = Module['canvas']; } if (SDL2.w !== w || SDL2.h !== h || SDL2.imageCtx !== SDL2.ctx) { SDL2.image = SDL2.ctx.createImageData(w, h); SDL2.w = w; SDL2.h = h; SDL2.imageCtx = SDL2.ctx; } var data = SDL2.image.data; var src = pixels / 4; var dst = 0; var num; if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) { num = data.length; while (dst < num) { var val = HEAP32[src]; data[dst ] = val & 0xff; data[dst+1] = (val >> 8) & 0xff; data[dst+2] = (val >> 16) & 0xff; data[dst+3] = 0xff; src++; dst += 4; } } else { if (SDL2.data32Data !== data) { SDL2.data32 = new Int32Array(data.buffer); SDL2.data8 = new Uint8Array(data.buffer); SDL2.data32Data = data; } var data32 = SDL2.data32; num = data32.length; data32.set(HEAP32.subarray(src, src + num)); var data8 = SDL2.data8; var i = 3; var j = i + 4*num; if (num % 8 == 0) { while (i < j) { data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; } } else { while (i < j) { data8[i] = 0xff; i = i + 4 | 0; } } } SDL2.ctx.putImageData(SDL2.image, 0, 0); },
1122
- 318872: ($0, $1, $2, $3, $4) => { var w = $0; var h = $1; var hot_x = $2; var hot_y = $3; var pixels = $4; var canvas = document.createElement("canvas"); canvas.width = w; canvas.height = h; var ctx = canvas.getContext("2d"); var image = ctx.createImageData(w, h); var data = image.data; var src = pixels / 4; var dst = 0; var num; if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) { num = data.length; while (dst < num) { var val = HEAP32[src]; data[dst ] = val & 0xff; data[dst+1] = (val >> 8) & 0xff; data[dst+2] = (val >> 16) & 0xff; data[dst+3] = (val >> 24) & 0xff; src++; dst += 4; } } else { var data32 = new Int32Array(data.buffer); num = data32.length; data32.set(HEAP32.subarray(src, src + num)); } ctx.putImageData(image, 0, 0); var url = hot_x === 0 && hot_y === 0 ? "url(" + canvas.toDataURL() + "), auto" : "url(" + canvas.toDataURL() + ") " + hot_x + " " + hot_y + ", auto"; var urlBuf = _malloc(url.length + 1); stringToUTF8(url, urlBuf, url.length + 1); return urlBuf; },
1123
- 319860: ($0) => { if (Module['canvas']) { Module['canvas'].style['cursor'] = UTF8ToString($0); } },
1124
- 319943: () => { if (Module['canvas']) { Module['canvas'].style['cursor'] = 'none'; } },
1125
- 320012: () => { return window.innerWidth; },
1126
- 320042: () => { return window.innerHeight; }
1421
+ 311808: () => { console.error("thread instantiation failed") },
1422
+ 311857: ($0, $1) => { console.log("using videoSync/audioSync", $0, $1) },
1423
+ 311910: ($0) => { console.log('setting core audio buffer size:', $0) },
1424
+ 311965: ($0, $1) => { Module.canvas.width = $0; Module.canvas.height = $1; },
1425
+ 312022: ($0) => { console.log('setting audioSampleRate', $0) },
1426
+ 312069: ($0) => { console.log('setting audioBufferSize', $0) },
1427
+ 312116: ($0) => { console.log('setting videoSync', $0) },
1428
+ 312157: ($0) => { console.log('setting audioSync', $0) },
1429
+ 312198: ($0, $1, $2, $3, $4, $5, $6) => { Module.version = { gitCommit : UTF8ToString($0), gitShort : UTF8ToString($1), gitBranch : UTF8ToString($2), gitRevision : $3, binaryName : UTF8ToString($4), projectName : UTF8ToString($5), projectVersion : UTF8ToString($6) }; },
1430
+ 312430: ($0, $1) => { const funcPtr = $0; const ctx = $1; const func = wasmTable.get(funcPtr); if (func) func(ctx); },
1431
+ 312528: ($0, $1) => { const funcPtr = $0; const ctx = $1; const func = wasmTable.get(funcPtr); if (func) func(ctx); },
1432
+ 312626: ($0, $1) => { const funcPtr = $0; const ctx = $1; const func = wasmTable.get(funcPtr); if (func) func(ctx); },
1433
+ 312724: ($0, $1) => { const funcPtr = $0; const ctx = $1; const func = wasmTable.get(funcPtr); if (func) func(ctx); },
1434
+ 312822: ($0, $1) => { const funcPtr = $0; const ctx = $1; const func = wasmTable.get(funcPtr); if (func) func(ctx); },
1435
+ 312920: ($0, $1) => { const funcPtr = $0; const ctx = $1; const func = wasmTable.get(funcPtr); if (func) func(ctx); },
1436
+ 313018: ($0, $1, $2, $3) => { console.log("desired spec values: sampleRate/samples", $0, $1); console.log("obtained spec values: sampleRate/samples", $2, $3) },
1437
+ 313150: () => { FS.syncfs(function (err) { assert(!err); }) },
1438
+ 313194: ($0) => { var str = UTF8ToString($0) + '\n\n' + 'Abort/Retry/Ignore/AlwaysIgnore? [ariA] :'; var reply = window.prompt(str, "i"); if (reply === null) { reply = "i"; } return allocate(intArrayFromString(reply), 'i8', ALLOC_NORMAL); },
1439
+ 313419: () => { if (typeof(AudioContext) !== 'undefined') { return true; } else if (typeof(webkitAudioContext) !== 'undefined') { return true; } return false; },
1440
+ 313566: () => { if ((typeof(navigator.mediaDevices) !== 'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !== 'undefined')) { return true; } else if (typeof(navigator.webkitGetUserMedia) !== 'undefined') { return true; } return false; },
1441
+ 313800: ($0) => { if(typeof(Module['SDL2']) === 'undefined') { Module['SDL2'] = {}; } var SDL2 = Module['SDL2']; if (!$0) { SDL2.audio = {}; } else { SDL2.capture = {}; } if (!SDL2.audioContext) { if (typeof(AudioContext) !== 'undefined') { SDL2.audioContext = new AudioContext(); } else if (typeof(webkitAudioContext) !== 'undefined') { SDL2.audioContext = new webkitAudioContext(); } if (SDL2.audioContext) { if ((typeof navigator.userActivation) === 'undefined') { autoResumeAudioContext(SDL2.audioContext); } } } return SDL2.audioContext === undefined ? -1 : 0; },
1442
+ 314352: () => { var SDL2 = Module['SDL2']; return SDL2.audioContext.sampleRate; },
1443
+ 314420: ($0, $1, $2, $3) => { var SDL2 = Module['SDL2']; var have_microphone = function(stream) { if (SDL2.capture.silenceTimer !== undefined) { clearInterval(SDL2.capture.silenceTimer); SDL2.capture.silenceTimer = undefined; SDL2.capture.silenceBuffer = undefined } SDL2.capture.mediaStreamNode = SDL2.audioContext.createMediaStreamSource(stream); SDL2.capture.scriptProcessorNode = SDL2.audioContext.createScriptProcessor($1, $0, 1); SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) { if ((SDL2 === undefined) || (SDL2.capture === undefined)) { return; } audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0); SDL2.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer; dynCall('vi', $2, [$3]); }; SDL2.capture.mediaStreamNode.connect(SDL2.capture.scriptProcessorNode); SDL2.capture.scriptProcessorNode.connect(SDL2.audioContext.destination); SDL2.capture.stream = stream; }; var no_microphone = function(error) { }; SDL2.capture.silenceBuffer = SDL2.audioContext.createBuffer($0, $1, SDL2.audioContext.sampleRate); SDL2.capture.silenceBuffer.getChannelData(0).fill(0.0); var silence_callback = function() { SDL2.capture.currentCaptureBuffer = SDL2.capture.silenceBuffer; dynCall('vi', $2, [$3]); }; SDL2.capture.silenceTimer = setInterval(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1000); if ((navigator.mediaDevices !== undefined) && (navigator.mediaDevices.getUserMedia !== undefined)) { navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(have_microphone).catch(no_microphone); } else if (navigator.webkitGetUserMedia !== undefined) { navigator.webkitGetUserMedia({ audio: true, video: false }, have_microphone, no_microphone); } },
1444
+ 316113: ($0, $1, $2, $3) => { var SDL2 = Module['SDL2']; SDL2.audio.scriptProcessorNode = SDL2.audioContext['createScriptProcessor']($1, 0, $0); SDL2.audio.scriptProcessorNode['onaudioprocess'] = function (e) { if ((SDL2 === undefined) || (SDL2.audio === undefined)) { return; } if (SDL2.audio.silenceTimer !== undefined) { clearInterval(SDL2.audio.silenceTimer); SDL2.audio.silenceTimer = undefined; SDL2.audio.silenceBuffer = undefined; } SDL2.audio.currentOutputBuffer = e['outputBuffer']; dynCall('vi', $2, [$3]); }; SDL2.audio.scriptProcessorNode['connect'](SDL2.audioContext['destination']); if (SDL2.audioContext.state === 'suspended') { SDL2.audio.silenceBuffer = SDL2.audioContext.createBuffer($0, $1, SDL2.audioContext.sampleRate); SDL2.audio.silenceBuffer.getChannelData(0).fill(0.0); var silence_callback = function() { if ((typeof navigator.userActivation) !== 'undefined') { if (navigator.userActivation.hasBeenActive) { SDL2.audioContext.resume(); } } SDL2.audio.currentOutputBuffer = SDL2.audio.silenceBuffer; dynCall('vi', $2, [$3]); SDL2.audio.currentOutputBuffer = undefined; }; SDL2.audio.silenceTimer = setInterval(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1000); } },
1445
+ 317288: ($0, $1) => { var SDL2 = Module['SDL2']; var numChannels = SDL2.capture.currentCaptureBuffer.numberOfChannels; for (var c = 0; c < numChannels; ++c) { var channelData = SDL2.capture.currentCaptureBuffer.getChannelData(c); if (channelData.length != $1) { throw 'Web Audio capture buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!'; } if (numChannels == 1) { for (var j = 0; j < $1; ++j) { setValue($0 + (j * 4), channelData[j], 'float'); } } else { for (var j = 0; j < $1; ++j) { setValue($0 + (((j * numChannels) + c) * 4), channelData[j], 'float'); } } } },
1446
+ 317893: ($0, $1) => { var SDL2 = Module['SDL2']; var buf = $0 >>> 2; var numChannels = SDL2.audio.currentOutputBuffer['numberOfChannels']; for (var c = 0; c < numChannels; ++c) { var channelData = SDL2.audio.currentOutputBuffer['getChannelData'](c); if (channelData.length != $1) { throw 'Web Audio output buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!'; } for (var j = 0; j < $1; ++j) { channelData[j] = HEAPF32[buf + (j*numChannels + c)]; } } },
1447
+ 318382: ($0) => { var SDL2 = Module['SDL2']; if ($0) { if (SDL2.capture.silenceTimer !== undefined) { clearInterval(SDL2.capture.silenceTimer); } if (SDL2.capture.stream !== undefined) { var tracks = SDL2.capture.stream.getAudioTracks(); for (var i = 0; i < tracks.length; i++) { SDL2.capture.stream.removeTrack(tracks[i]); } } if (SDL2.capture.scriptProcessorNode !== undefined) { SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {}; SDL2.capture.scriptProcessorNode.disconnect(); } if (SDL2.capture.mediaStreamNode !== undefined) { SDL2.capture.mediaStreamNode.disconnect(); } SDL2.capture = undefined; } else { if (SDL2.audio.scriptProcessorNode != undefined) { SDL2.audio.scriptProcessorNode.disconnect(); } if (SDL2.audio.silenceTimer !== undefined) { clearInterval(SDL2.audio.silenceTimer); } SDL2.audio = undefined; } if ((SDL2.audioContext !== undefined) && (SDL2.audio === undefined) && (SDL2.capture === undefined)) { SDL2.audioContext.close(); SDL2.audioContext = undefined; } },
1448
+ 319388: ($0, $1, $2) => { var w = $0; var h = $1; var pixels = $2; if (!Module['SDL2']) Module['SDL2'] = {}; var SDL2 = Module['SDL2']; if (SDL2.ctxCanvas !== Module['canvas']) { SDL2.ctx = Module['createContext'](Module['canvas'], false, true); SDL2.ctxCanvas = Module['canvas']; } if (SDL2.w !== w || SDL2.h !== h || SDL2.imageCtx !== SDL2.ctx) { SDL2.image = SDL2.ctx.createImageData(w, h); SDL2.w = w; SDL2.h = h; SDL2.imageCtx = SDL2.ctx; } var data = SDL2.image.data; var src = pixels / 4; var dst = 0; var num; if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) { num = data.length; while (dst < num) { var val = HEAP32[src]; data[dst ] = val & 0xff; data[dst+1] = (val >> 8) & 0xff; data[dst+2] = (val >> 16) & 0xff; data[dst+3] = 0xff; src++; dst += 4; } } else { if (SDL2.data32Data !== data) { SDL2.data32 = new Int32Array(data.buffer); SDL2.data8 = new Uint8Array(data.buffer); SDL2.data32Data = data; } var data32 = SDL2.data32; num = data32.length; data32.set(HEAP32.subarray(src, src + num)); var data8 = SDL2.data8; var i = 3; var j = i + 4*num; if (num % 8 == 0) { while (i < j) { data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; data8[i] = 0xff; i = i + 4 | 0; } } else { while (i < j) { data8[i] = 0xff; i = i + 4 | 0; } } } SDL2.ctx.putImageData(SDL2.image, 0, 0); },
1449
+ 320856: ($0, $1, $2, $3, $4) => { var w = $0; var h = $1; var hot_x = $2; var hot_y = $3; var pixels = $4; var canvas = document.createElement("canvas"); canvas.width = w; canvas.height = h; var ctx = canvas.getContext("2d"); var image = ctx.createImageData(w, h); var data = image.data; var src = pixels / 4; var dst = 0; var num; if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) { num = data.length; while (dst < num) { var val = HEAP32[src]; data[dst ] = val & 0xff; data[dst+1] = (val >> 8) & 0xff; data[dst+2] = (val >> 16) & 0xff; data[dst+3] = (val >> 24) & 0xff; src++; dst += 4; } } else { var data32 = new Int32Array(data.buffer); num = data32.length; data32.set(HEAP32.subarray(src, src + num)); } ctx.putImageData(image, 0, 0); var url = hot_x === 0 && hot_y === 0 ? "url(" + canvas.toDataURL() + "), auto" : "url(" + canvas.toDataURL() + ") " + hot_x + " " + hot_y + ", auto"; var urlBuf = _malloc(url.length + 1); stringToUTF8(url, urlBuf, url.length + 1); return urlBuf; },
1450
+ 321844: ($0) => { if (Module['canvas']) { Module['canvas'].style['cursor'] = UTF8ToString($0); } },
1451
+ 321927: () => { if (Module['canvas']) { Module['canvas'].style['cursor'] = 'none'; } },
1452
+ 321996: () => { return window.innerWidth; },
1453
+ 322026: () => { return window.innerHeight; }
1127
1454
  };
1128
1455
 
1129
1456
  // end include: preamble.js
@@ -1146,11 +1473,16 @@ var ASM_CONSTS = {
1146
1473
  // out its message handler here. This avoids having to check in each of
1147
1474
  // the onmessage handlers if the message was coming from valid worker.
1148
1475
  worker.onmessage = (e) => {
1476
+ var cmd = e['data'].cmd;
1477
+ err(`received "${cmd}" command from terminated worker: ${worker.workerID}`);
1149
1478
  };
1150
1479
  };
1151
1480
 
1152
1481
  var cleanupThread = (pthread_ptr) => {
1482
+ assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! cleanupThread() can only ever be called from main application thread!');
1483
+ assert(pthread_ptr, 'Internal Error! Null pthread_ptr in cleanupThread!');
1153
1484
  var worker = PThread.pthreads[pthread_ptr];
1485
+ assert(worker);
1154
1486
  PThread.returnWorkerToPool(worker);
1155
1487
  };
1156
1488
 
@@ -1164,12 +1496,15 @@ var ASM_CONSTS = {
1164
1496
  var addOnPreRun = (cb) => onPreRuns.unshift(cb);
1165
1497
 
1166
1498
  var spawnThread = (threadParams) => {
1499
+ assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! spawnThread() can only ever be called from main application thread!');
1500
+ assert(threadParams.pthread_ptr, 'Internal error, no pthread ptr!');
1167
1501
 
1168
1502
  var worker = PThread.getNewWorker();
1169
1503
  if (!worker) {
1170
1504
  // No available workers in the PThread pool.
1171
1505
  return 6;
1172
1506
  }
1507
+ assert(!worker.pthread_ptr, 'Internal error!');
1173
1508
 
1174
1509
  PThread.runningWorkers.push(worker);
1175
1510
 
@@ -1261,6 +1596,7 @@ var ASM_CONSTS = {
1261
1596
 
1262
1597
 
1263
1598
 
1599
+
1264
1600
  var handleException = (e) => {
1265
1601
  // Certain exception types we do not treat as errors since they are used for
1266
1602
  // internal control flow.
@@ -1270,6 +1606,12 @@ var ASM_CONSTS = {
1270
1606
  if (e instanceof ExitStatus || e == 'unwind') {
1271
1607
  return EXITSTATUS;
1272
1608
  }
1609
+ checkStackCookie();
1610
+ if (e instanceof WebAssembly.RuntimeError) {
1611
+ if (_emscripten_stack_get_current() <= 0) {
1612
+ err('Stack overflow detected. You can try increasing -sSTACK_SIZE (currently set to 65536)');
1613
+ }
1614
+ }
1273
1615
  quit_(1, e);
1274
1616
  };
1275
1617
 
@@ -1283,13 +1625,17 @@ var ASM_CONSTS = {
1283
1625
 
1284
1626
  }
1285
1627
 
1628
+
1286
1629
  /** @suppress {duplicate } */
1287
1630
  /** @param {boolean|number=} implicit */
1288
1631
  var exitJS = (status, implicit) => {
1289
1632
  EXITSTATUS = status;
1290
1633
 
1634
+ checkUnflushedContent();
1635
+
1291
1636
  if (ENVIRONMENT_IS_PTHREAD) {
1292
1637
  // implicit exit can never happen on a pthread
1638
+ assert(!implicit);
1293
1639
  // When running in a pthread we propagate the exit back to the main thread
1294
1640
  // where it can decide if the whole process should be shut down or not.
1295
1641
  // The pthread may have decided not to exit its own runtime, for example
@@ -1298,10 +1644,24 @@ var ASM_CONSTS = {
1298
1644
  throw 'unwind';
1299
1645
  }
1300
1646
 
1647
+ // if exit() was called explicitly, warn the user if the runtime isn't actually being shut down
1648
+ if (keepRuntimeAlive() && !implicit) {
1649
+ var msg = `program exited (with status: ${status}), but keepRuntimeAlive() is set (counter=${runtimeKeepaliveCounter}) due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)`;
1650
+ readyPromiseReject(msg);
1651
+ err(msg);
1652
+ }
1653
+
1301
1654
  _proc_exit(status);
1302
1655
  };
1303
1656
  var _exit = exitJS;
1304
1657
 
1658
+ var ptrToString = (ptr) => {
1659
+ assert(typeof ptr === 'number');
1660
+ // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
1661
+ ptr >>>= 0;
1662
+ return '0x' + ptr.toString(16).padStart(8, '0');
1663
+ };
1664
+
1305
1665
 
1306
1666
  var PThread = {
1307
1667
  unusedWorkers:[],
@@ -1309,13 +1669,29 @@ var ASM_CONSTS = {
1309
1669
  tlsInitFunctions:[],
1310
1670
  pthreads:{
1311
1671
  },
1672
+ nextWorkerID:1,
1673
+ debugInit() {
1674
+ function pthreadLogPrefix() {
1675
+ var t = 0;
1676
+ if (runtimeInitialized && typeof _pthread_self != 'undefined'
1677
+ ) {
1678
+ t = _pthread_self();
1679
+ }
1680
+ return `w:${workerID},t:${ptrToString(t)}: `;
1681
+ }
1682
+
1683
+ // Prefix all err()/dbg() messages with the calling thread ID.
1684
+ var origDbg = dbg;
1685
+ dbg = (...args) => origDbg(pthreadLogPrefix() + args.join(' '));
1686
+ },
1312
1687
  init() {
1688
+ PThread.debugInit();
1313
1689
  if ((!(ENVIRONMENT_IS_PTHREAD))) {
1314
1690
  PThread.initMainThread();
1315
1691
  }
1316
1692
  },
1317
1693
  initMainThread() {
1318
- var pthreadPoolSize = 3;
1694
+ var pthreadPoolSize = 5;
1319
1695
  // Start loading up the Worker pool, if requested.
1320
1696
  while (pthreadPoolSize--) {
1321
1697
  PThread.allocateUnusedWorker();
@@ -1328,6 +1704,7 @@ var ASM_CONSTS = {
1328
1704
  });
1329
1705
  },
1330
1706
  terminateAllThreads:() => {
1707
+ assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! terminateAllThreads() can only ever be called from main application thread!');
1331
1708
  // Attempt to kill all workers. Sadly (at least on the web) there is no
1332
1709
  // way to terminate a worker synchronously, or to be notified when a
1333
1710
  // worker in actually terminated. This means there is some risk that
@@ -1415,10 +1792,16 @@ var ASM_CONSTS = {
1415
1792
 
1416
1793
  worker.onerror = (e) => {
1417
1794
  var message = 'worker sent an error!';
1795
+ if (worker.pthread_ptr) {
1796
+ message = `Pthread ${ptrToString(worker.pthread_ptr)} sent an error!`;
1797
+ }
1418
1798
  err(`${message} ${e.filename}:${e.lineno}: ${e.message}`);
1419
1799
  throw e;
1420
1800
  };
1421
1801
 
1802
+ assert(wasmMemory instanceof WebAssembly.Memory, 'WebAssembly memory should have been loaded by now!');
1803
+ assert(wasmModule instanceof WebAssembly.Module, 'WebAssembly Module should have been loaded by now!');
1804
+
1422
1805
  // When running on a pthread, none of the incoming parameters on the module
1423
1806
  // object are present. Proxy known handlers back to the main thread if specified.
1424
1807
  var handlers = [];
@@ -1434,12 +1817,15 @@ var ASM_CONSTS = {
1434
1817
  }
1435
1818
  }
1436
1819
 
1820
+ worker.workerID = PThread.nextWorkerID++;
1821
+
1437
1822
  // Ask the new worker to load up the Emscripten-compiled page. This is a heavy operation.
1438
1823
  worker.postMessage({
1439
1824
  cmd: 'load',
1440
1825
  handlers: handlers,
1441
1826
  wasmMemory,
1442
1827
  wasmModule,
1828
+ 'workerID': worker.workerID,
1443
1829
  });
1444
1830
  }),
1445
1831
  loadWasmModuleToAllWorkers(onMaybeReady) {
@@ -1464,13 +1850,20 @@ var ASM_CONSTS = {
1464
1850
  'type': 'module',
1465
1851
  // This is the way that we signal to the Web Worker that it is hosting
1466
1852
  // a pthread.
1467
- 'name': 'em-pthread',
1853
+ 'name': 'em-pthread-' + PThread.nextWorkerID,
1468
1854
  });
1469
1855
  PThread.unusedWorkers.push(worker);
1470
1856
  },
1471
1857
  getNewWorker() {
1472
1858
  if (PThread.unusedWorkers.length == 0) {
1473
1859
  // PTHREAD_POOL_SIZE_STRICT should show a warning and, if set to level `2`, return from the function.
1860
+ // However, if we're in Node.js, then we can create new workers on the fly and PTHREAD_POOL_SIZE_STRICT
1861
+ // should be ignored altogether.
1862
+ err('Tried to spawn a new thread, but the thread pool is exhausted.\n' +
1863
+ 'This might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.\n' +
1864
+ 'If you want to increase the pool size, use setting `-sPTHREAD_POOL_SIZE=...`.'
1865
+ + '\nIf you want to throw an explicit error instead of the risk of deadlocking in those cases, use setting `-sPTHREAD_POOL_SIZE_STRICT=2`.'
1866
+ );
1474
1867
  PThread.allocateUnusedWorker();
1475
1868
  PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]);
1476
1869
  }
@@ -1489,6 +1882,9 @@ var ASM_CONSTS = {
1489
1882
  var stackHigh = HEAPU32[(((pthread_ptr)+(52))>>2)];
1490
1883
  var stackSize = HEAPU32[(((pthread_ptr)+(56))>>2)];
1491
1884
  var stackLow = stackHigh - stackSize;
1885
+ assert(stackHigh != 0);
1886
+ assert(stackLow != 0);
1887
+ assert(stackHigh > stackLow, 'stackHigh must be higher then stackLow');
1492
1888
  // Set stack limits used by `emscripten/stack.h` function. These limits are
1493
1889
  // cached in wasm-side globals to make checks as fast as possible.
1494
1890
  _emscripten_stack_set_limits(stackHigh, stackLow);
@@ -1496,6 +1892,9 @@ var ASM_CONSTS = {
1496
1892
  // Call inside wasm module to set up the stack frame for this pthread in wasm module scope
1497
1893
  stackRestore(stackHigh);
1498
1894
 
1895
+ // Write the stack cookie last, after we have set up the proper bounds and
1896
+ // current position of the stack.
1897
+ writeStackCookie();
1499
1898
  };
1500
1899
 
1501
1900
 
@@ -1533,6 +1932,8 @@ var ASM_CONSTS = {
1533
1932
  /** @suppress {checkTypes} */
1534
1933
  wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
1535
1934
  }
1935
+ /** @suppress {checkTypes} */
1936
+ assert(wasmTable.get(funcPtr) == func, 'JavaScript-side Wasm function table mirror is out of date!');
1536
1937
  return func;
1537
1938
  };
1538
1939
  var invokeEntryPoint = (ptr, arg) => {
@@ -1561,6 +1962,7 @@ var ASM_CONSTS = {
1561
1962
 
1562
1963
  var result = getWasmTableEntry(ptr)(arg);
1563
1964
 
1965
+ checkStackCookie();
1564
1966
  function finish(result) {
1565
1967
  if (keepRuntimeAlive()) {
1566
1968
  EXITSTATUS = result;
@@ -1573,6 +1975,7 @@ var ASM_CONSTS = {
1573
1975
 
1574
1976
  var noExitRuntime = Module['noExitRuntime'] || true;
1575
1977
 
1978
+
1576
1979
  var registerTLSInit = (tlsInitFunc) => PThread.tlsInitFunctions.push(tlsInitFunc);
1577
1980
 
1578
1981
 
@@ -1598,6 +2001,14 @@ var ASM_CONSTS = {
1598
2001
 
1599
2002
 
1600
2003
 
2004
+ var warnOnce = (text) => {
2005
+ warnOnce.shown ||= {};
2006
+ if (!warnOnce.shown[text]) {
2007
+ warnOnce.shown[text] = 1;
2008
+ err(text);
2009
+ }
2010
+ };
2011
+
1601
2012
  var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder() : undefined;
1602
2013
 
1603
2014
  /**
@@ -1638,6 +2049,7 @@ var ASM_CONSTS = {
1638
2049
  if ((u0 & 0xF0) == 0xE0) {
1639
2050
  u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
1640
2051
  } else {
2052
+ if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!');
1641
2053
  u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
1642
2054
  }
1643
2055
 
@@ -1667,6 +2079,7 @@ var ASM_CONSTS = {
1667
2079
  * @return {string}
1668
2080
  */
1669
2081
  var UTF8ToString = (ptr, maxBytesToRead) => {
2082
+ assert(typeof ptr == 'number', `UTF8ToString expects a number (got ${typeof ptr})`);
1670
2083
  return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : '';
1671
2084
  };
1672
2085
  var ___assert_fail = (condition, filename, line, func) =>
@@ -1690,6 +2103,7 @@ var ASM_CONSTS = {
1690
2103
 
1691
2104
  var ___pthread_create_js = (pthread_ptr, attr, startRoutine, arg) => {
1692
2105
  if (!_emscripten_has_threading_support()) {
2106
+ dbg('pthread_create: environment does not support SharedArrayBuffer, pthreads are not available');
1693
2107
  return 6;
1694
2108
  }
1695
2109
 
@@ -1733,6 +2147,7 @@ var ASM_CONSTS = {
1733
2147
 
1734
2148
  /** @suppress {duplicate } */
1735
2149
  var syscallGetVarargI = () => {
2150
+ assert(SYSCALLS.varargs != undefined);
1736
2151
  // the `+` prepended here is necessary to convince the JSCompiler that varargs is indeed a number.
1737
2152
  var ret = HEAP32[((+SYSCALLS.varargs)>>2)];
1738
2153
  SYSCALLS.varargs += 4;
@@ -1895,6 +2310,7 @@ var ASM_CONSTS = {
1895
2310
  };
1896
2311
 
1897
2312
  var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
2313
+ assert(typeof str === 'string', `stringToUTF8Array expects a string (got ${typeof str})`);
1898
2314
  // Parameter maxBytesToWrite is not optional. Negative values, 0, null,
1899
2315
  // undefined and false each don't write out any bytes.
1900
2316
  if (!(maxBytesToWrite > 0))
@@ -1929,6 +2345,7 @@ var ASM_CONSTS = {
1929
2345
  heap[outIdx++] = 0x80 | (u & 63);
1930
2346
  } else {
1931
2347
  if (outIdx + 3 >= endIdx) break;
2348
+ if (u > 0x10FFFF) warnOnce('Invalid Unicode code point ' + ptrToString(u) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).');
1932
2349
  heap[outIdx++] = 0xF0 | (u >> 18);
1933
2350
  heap[outIdx++] = 0x80 | ((u >> 12) & 63);
1934
2351
  heap[outIdx++] = 0x80 | ((u >> 6) & 63);
@@ -2114,6 +2531,7 @@ var ASM_CONSTS = {
2114
2531
  };
2115
2532
 
2116
2533
  var alignMemory = (size, alignment) => {
2534
+ assert(alignment, "alignment argument is required");
2117
2535
  return Math.ceil(size / alignment) * alignment;
2118
2536
  };
2119
2537
  var mmapAlloc = (size) => {
@@ -2279,7 +2697,7 @@ var ASM_CONSTS = {
2279
2697
  }
2280
2698
  },
2281
2699
  lookup(parent, name) {
2282
- throw MEMFS.doesNotExistError;
2700
+ throw new FS.ErrnoError(44);
2283
2701
  },
2284
2702
  mknod(parent, name, mode, dev) {
2285
2703
  return MEMFS.createNode(parent, name, mode, dev);
@@ -2336,6 +2754,7 @@ var ASM_CONSTS = {
2336
2754
  var contents = stream.node.contents;
2337
2755
  if (position >= stream.node.usedBytes) return 0;
2338
2756
  var size = Math.min(stream.node.usedBytes - position, length);
2757
+ assert(size >= 0);
2339
2758
  if (size > 8 && contents.subarray) { // non-trivial, and typed array
2340
2759
  buffer.set(contents.subarray(position, position + size), offset);
2341
2760
  } else {
@@ -2344,6 +2763,8 @@ var ASM_CONSTS = {
2344
2763
  return size;
2345
2764
  },
2346
2765
  write(stream, buffer, offset, length, position, canOwn) {
2766
+ // The data buffer should be a typed array view
2767
+ assert(!(buffer instanceof ArrayBuffer));
2347
2768
 
2348
2769
  if (!length) return 0;
2349
2770
  var node = stream.node;
@@ -2351,6 +2772,7 @@ var ASM_CONSTS = {
2351
2772
 
2352
2773
  if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array?
2353
2774
  if (canOwn) {
2775
+ assert(position === 0, 'canOwn must imply no weird position inside the file');
2354
2776
  node.contents = buffer.subarray(offset, offset + length);
2355
2777
  node.usedBytes = length;
2356
2778
  return length;
@@ -2438,6 +2860,7 @@ var ASM_CONSTS = {
2438
2860
 
2439
2861
  var asyncLoad = async (url) => {
2440
2862
  var arrayBuffer = await readAsync(url);
2863
+ assert(arrayBuffer, `Loading data file "${url}" failed (no arrayBuffer).`);
2441
2864
  return new Uint8Array(arrayBuffer);
2442
2865
  };
2443
2866
 
@@ -2526,6 +2949,7 @@ var ASM_CONSTS = {
2526
2949
  if (typeof indexedDB != 'undefined') return indexedDB;
2527
2950
  var ret = null;
2528
2951
  if (typeof window == 'object') ret = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
2952
+ assert(ret, 'IDBFS used, but indexedDB not supported');
2529
2953
  return ret;
2530
2954
  },
2531
2955
  DB_VERSION:21,
@@ -2888,6 +3312,134 @@ var ASM_CONSTS = {
2888
3312
  });
2889
3313
  },
2890
3314
  };
3315
+
3316
+
3317
+
3318
+ var strError = (errno) => UTF8ToString(_strerror(errno));
3319
+
3320
+ var ERRNO_CODES = {
3321
+ 'EPERM': 63,
3322
+ 'ENOENT': 44,
3323
+ 'ESRCH': 71,
3324
+ 'EINTR': 27,
3325
+ 'EIO': 29,
3326
+ 'ENXIO': 60,
3327
+ 'E2BIG': 1,
3328
+ 'ENOEXEC': 45,
3329
+ 'EBADF': 8,
3330
+ 'ECHILD': 12,
3331
+ 'EAGAIN': 6,
3332
+ 'EWOULDBLOCK': 6,
3333
+ 'ENOMEM': 48,
3334
+ 'EACCES': 2,
3335
+ 'EFAULT': 21,
3336
+ 'ENOTBLK': 105,
3337
+ 'EBUSY': 10,
3338
+ 'EEXIST': 20,
3339
+ 'EXDEV': 75,
3340
+ 'ENODEV': 43,
3341
+ 'ENOTDIR': 54,
3342
+ 'EISDIR': 31,
3343
+ 'EINVAL': 28,
3344
+ 'ENFILE': 41,
3345
+ 'EMFILE': 33,
3346
+ 'ENOTTY': 59,
3347
+ 'ETXTBSY': 74,
3348
+ 'EFBIG': 22,
3349
+ 'ENOSPC': 51,
3350
+ 'ESPIPE': 70,
3351
+ 'EROFS': 69,
3352
+ 'EMLINK': 34,
3353
+ 'EPIPE': 64,
3354
+ 'EDOM': 18,
3355
+ 'ERANGE': 68,
3356
+ 'ENOMSG': 49,
3357
+ 'EIDRM': 24,
3358
+ 'ECHRNG': 106,
3359
+ 'EL2NSYNC': 156,
3360
+ 'EL3HLT': 107,
3361
+ 'EL3RST': 108,
3362
+ 'ELNRNG': 109,
3363
+ 'EUNATCH': 110,
3364
+ 'ENOCSI': 111,
3365
+ 'EL2HLT': 112,
3366
+ 'EDEADLK': 16,
3367
+ 'ENOLCK': 46,
3368
+ 'EBADE': 113,
3369
+ 'EBADR': 114,
3370
+ 'EXFULL': 115,
3371
+ 'ENOANO': 104,
3372
+ 'EBADRQC': 103,
3373
+ 'EBADSLT': 102,
3374
+ 'EDEADLOCK': 16,
3375
+ 'EBFONT': 101,
3376
+ 'ENOSTR': 100,
3377
+ 'ENODATA': 116,
3378
+ 'ETIME': 117,
3379
+ 'ENOSR': 118,
3380
+ 'ENONET': 119,
3381
+ 'ENOPKG': 120,
3382
+ 'EREMOTE': 121,
3383
+ 'ENOLINK': 47,
3384
+ 'EADV': 122,
3385
+ 'ESRMNT': 123,
3386
+ 'ECOMM': 124,
3387
+ 'EPROTO': 65,
3388
+ 'EMULTIHOP': 36,
3389
+ 'EDOTDOT': 125,
3390
+ 'EBADMSG': 9,
3391
+ 'ENOTUNIQ': 126,
3392
+ 'EBADFD': 127,
3393
+ 'EREMCHG': 128,
3394
+ 'ELIBACC': 129,
3395
+ 'ELIBBAD': 130,
3396
+ 'ELIBSCN': 131,
3397
+ 'ELIBMAX': 132,
3398
+ 'ELIBEXEC': 133,
3399
+ 'ENOSYS': 52,
3400
+ 'ENOTEMPTY': 55,
3401
+ 'ENAMETOOLONG': 37,
3402
+ 'ELOOP': 32,
3403
+ 'EOPNOTSUPP': 138,
3404
+ 'EPFNOSUPPORT': 139,
3405
+ 'ECONNRESET': 15,
3406
+ 'ENOBUFS': 42,
3407
+ 'EAFNOSUPPORT': 5,
3408
+ 'EPROTOTYPE': 67,
3409
+ 'ENOTSOCK': 57,
3410
+ 'ENOPROTOOPT': 50,
3411
+ 'ESHUTDOWN': 140,
3412
+ 'ECONNREFUSED': 14,
3413
+ 'EADDRINUSE': 3,
3414
+ 'ECONNABORTED': 13,
3415
+ 'ENETUNREACH': 40,
3416
+ 'ENETDOWN': 38,
3417
+ 'ETIMEDOUT': 73,
3418
+ 'EHOSTDOWN': 142,
3419
+ 'EHOSTUNREACH': 23,
3420
+ 'EINPROGRESS': 26,
3421
+ 'EALREADY': 7,
3422
+ 'EDESTADDRREQ': 17,
3423
+ 'EMSGSIZE': 35,
3424
+ 'EPROTONOSUPPORT': 66,
3425
+ 'ESOCKTNOSUPPORT': 137,
3426
+ 'EADDRNOTAVAIL': 4,
3427
+ 'ENETRESET': 39,
3428
+ 'EISCONN': 30,
3429
+ 'ENOTCONN': 53,
3430
+ 'ETOOMANYREFS': 141,
3431
+ 'EUSERS': 136,
3432
+ 'EDQUOT': 19,
3433
+ 'ESTALE': 72,
3434
+ 'ENOTSUP': 138,
3435
+ 'ENOMEDIUM': 148,
3436
+ 'EILSEQ': 25,
3437
+ 'EOVERFLOW': 61,
3438
+ 'ECANCELED': 11,
3439
+ 'ENOTRECOVERABLE': 56,
3440
+ 'EOWNERDEAD': 62,
3441
+ 'ESTRPIPE': 135,
3442
+ };
2891
3443
  var FS = {
2892
3444
  root:null,
2893
3445
  mounts:[],
@@ -2903,7 +3455,7 @@ var ASM_CONSTS = {
2903
3455
  syncFSRequests:0,
2904
3456
  readFiles:{
2905
3457
  },
2906
- ErrnoError:class {
3458
+ ErrnoError:class extends Error {
2907
3459
  name = 'ErrnoError';
2908
3460
  // We set the `name` property to be able to identify `FS.ErrnoError`
2909
3461
  // - the `name` is a standard ECMA-262 property of error objects. Kind of good to have it anyway.
@@ -2912,7 +3464,14 @@ var ASM_CONSTS = {
2912
3464
  // the test `err instanceof FS.ErrnoError` won't detect an error coming from another filesystem, causing bugs.
2913
3465
  // we'll use the reliable test `err.name == "ErrnoError"` instead
2914
3466
  constructor(errno) {
3467
+ super(runtimeInitialized ? strError(errno) : '');
2915
3468
  this.errno = errno;
3469
+ for (var key in ERRNO_CODES) {
3470
+ if (ERRNO_CODES[key] === errno) {
3471
+ this.code = key;
3472
+ break;
3473
+ }
3474
+ }
2916
3475
  }
2917
3476
  },
2918
3477
  FSStream:class {
@@ -3110,6 +3669,7 @@ var ASM_CONSTS = {
3110
3669
  return FS.lookup(parent, name);
3111
3670
  },
3112
3671
  createNode(parent, name, mode, rdev) {
3672
+ assert(typeof parent == 'object')
3113
3673
  var node = new FS.FSNode(parent, name, mode, rdev);
3114
3674
 
3115
3675
  FS.hashAddNode(node);
@@ -3248,6 +3808,7 @@ var ASM_CONSTS = {
3248
3808
  },
3249
3809
  getStream:(fd) => FS.streams[fd],
3250
3810
  createStream(stream, fd = -1) {
3811
+ assert(fd >= -1);
3251
3812
 
3252
3813
  // clone it, so we can return an instance of FSStream
3253
3814
  stream = Object.assign(new FS.FSStream(), stream);
@@ -3322,6 +3883,7 @@ var ASM_CONSTS = {
3322
3883
  var completed = 0;
3323
3884
 
3324
3885
  function doCallback(errCode) {
3886
+ assert(FS.syncFSRequests > 0);
3325
3887
  FS.syncFSRequests--;
3326
3888
  return callback(errCode);
3327
3889
  }
@@ -3348,6 +3910,11 @@ var ASM_CONSTS = {
3348
3910
  });
3349
3911
  },
3350
3912
  mount(type, opts, mountpoint) {
3913
+ if (typeof type == 'string') {
3914
+ // The filesystem was not included, and instead we have an error
3915
+ // message stored in the variable.
3916
+ throw type;
3917
+ }
3351
3918
  var root = mountpoint === '/';
3352
3919
  var pseudo = !mountpoint;
3353
3920
  var node;
@@ -3426,6 +3993,7 @@ var ASM_CONSTS = {
3426
3993
 
3427
3994
  // remove this mount from the child mounts
3428
3995
  var idx = node.mount.mounts.indexOf(mount);
3996
+ assert(idx !== -1);
3429
3997
  node.mount.mounts.splice(idx, 1);
3430
3998
  },
3431
3999
  lookup(parent, name) {
@@ -3918,6 +4486,7 @@ var ASM_CONSTS = {
3918
4486
  return stream.position;
3919
4487
  },
3920
4488
  read(stream, buffer, offset, length, position) {
4489
+ assert(offset >= 0);
3921
4490
  if (length < 0 || position < 0) {
3922
4491
  throw new FS.ErrnoError(28);
3923
4492
  }
@@ -3944,6 +4513,7 @@ var ASM_CONSTS = {
3944
4513
  return bytesRead;
3945
4514
  },
3946
4515
  write(stream, buffer, offset, length, position, canOwn) {
4516
+ assert(offset >= 0);
3947
4517
  if (length < 0 || position < 0) {
3948
4518
  throw new FS.ErrnoError(28);
3949
4519
  }
@@ -4015,6 +4585,7 @@ var ASM_CONSTS = {
4015
4585
  return stream.stream_ops.mmap(stream, length, position, prot, flags);
4016
4586
  },
4017
4587
  msync(stream, buffer, offset, length, mmapFlags) {
4588
+ assert(offset >= 0);
4018
4589
  if (!stream.stream_ops.msync) {
4019
4590
  return 0;
4020
4591
  }
@@ -4178,6 +4749,9 @@ var ASM_CONSTS = {
4178
4749
  var stdin = FS.open('/dev/stdin', 0);
4179
4750
  var stdout = FS.open('/dev/stdout', 1);
4180
4751
  var stderr = FS.open('/dev/stderr', 1);
4752
+ assert(stdin.fd === 0, `invalid handle for stdin (${stdin.fd})`);
4753
+ assert(stdout.fd === 1, `invalid handle for stdout (${stdout.fd})`);
4754
+ assert(stderr.fd === 2, `invalid handle for stderr (${stderr.fd})`);
4181
4755
  },
4182
4756
  staticInit() {
4183
4757
  FS.nameTable = new Array(4096);
@@ -4194,6 +4768,7 @@ var ASM_CONSTS = {
4194
4768
  };
4195
4769
  },
4196
4770
  init(input, output, error) {
4771
+ assert(!FS.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)');
4197
4772
  FS.initialized = true;
4198
4773
 
4199
4774
  // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here
@@ -4206,6 +4781,7 @@ var ASM_CONSTS = {
4206
4781
  quit() {
4207
4782
  FS.initialized = false;
4208
4783
  // force-flush all streams, so we get musl std streams printed out
4784
+ _fflush(0);
4209
4785
  // close all of our streams
4210
4786
  for (var i = 0; i < FS.streams.length; i++) {
4211
4787
  var stream = FS.streams[i];
@@ -4492,6 +5068,7 @@ var ASM_CONSTS = {
4492
5068
  if (position >= contents.length)
4493
5069
  return 0;
4494
5070
  var size = Math.min(contents.length - position, length);
5071
+ assert(size >= 0);
4495
5072
  if (contents.slice) { // normal array
4496
5073
  for (var i = 0; i < size; i++) {
4497
5074
  buffer[offset + i] = contents[position + i];
@@ -4521,6 +5098,24 @@ var ASM_CONSTS = {
4521
5098
  node.stream_ops = stream_ops;
4522
5099
  return node;
4523
5100
  },
5101
+ absolutePath() {
5102
+ abort('FS.absolutePath has been removed; use PATH_FS.resolve instead');
5103
+ },
5104
+ createFolder() {
5105
+ abort('FS.createFolder has been removed; use FS.mkdir instead');
5106
+ },
5107
+ createLink() {
5108
+ abort('FS.createLink has been removed; use FS.symlink instead');
5109
+ },
5110
+ joinPath() {
5111
+ abort('FS.joinPath has been removed; use PATH.join instead');
5112
+ },
5113
+ mmapAlloc() {
5114
+ abort('FS.mmapAlloc has been replaced by the top level function mmapAlloc');
5115
+ },
5116
+ standardizePath() {
5117
+ abort('FS.standardizePath has been removed; use PATH.normalize instead');
5118
+ },
4524
5119
  };
4525
5120
 
4526
5121
  var SYSCALLS = {
@@ -4699,6 +5294,7 @@ var ASM_CONSTS = {
4699
5294
 
4700
5295
 
4701
5296
  var stringToUTF8 = (str, outPtr, maxBytesToWrite) => {
5297
+ assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
4702
5298
  return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
4703
5299
  };
4704
5300
 
@@ -4772,6 +5368,7 @@ var ASM_CONSTS = {
4772
5368
  FS.isLink(child.mode) ? 10 : // DT_LNK, symbolic link.
4773
5369
  8; // DT_REG, regular file.
4774
5370
  }
5371
+ assert(id);
4775
5372
  HEAP64[((dirp + pos)>>3)] = BigInt(id);
4776
5373
  HEAP64[(((dirp + pos)+(8))>>3)] = BigInt((idx + 1) * struct_size);
4777
5374
  HEAP16[(((dirp + pos)+(16))>>1)] = 280;
@@ -4942,6 +5539,7 @@ var ASM_CONSTS = {
4942
5539
  var nofollow = flags & 256;
4943
5540
  var allowEmpty = flags & 4096;
4944
5541
  flags = flags & (~6400);
5542
+ assert(!flags, `unknown flags in __syscall_newfstatat: ${flags}`);
4945
5543
  path = SYSCALLS.calculateAt(dirfd, path, allowEmpty);
4946
5544
  return SYSCALLS.writeStat(buf, nofollow ? FS.lstat(path) : FS.stat(path));
4947
5545
  } catch (e) {
@@ -5080,6 +5678,7 @@ var ASM_CONSTS = {
5080
5678
  try {
5081
5679
 
5082
5680
  path = SYSCALLS.getStr(path);
5681
+ assert(flags === 0);
5083
5682
  path = SYSCALLS.calculateAt(dirfd, path, true);
5084
5683
  var now = Date.now(), atime, mtime;
5085
5684
  if (!times) {
@@ -5121,7 +5720,7 @@ var ASM_CONSTS = {
5121
5720
 
5122
5721
 
5123
5722
  var __abort_js = () =>
5124
- abort('');
5723
+ abort('native code called abort()');
5125
5724
 
5126
5725
  var __emscripten_init_main_thread_js = (tb) => {
5127
5726
  // Pass the thread address to the native code where they stored in wasm
@@ -5155,6 +5754,7 @@ var ASM_CONSTS = {
5155
5754
  };
5156
5755
  var callUserCallback = (func) => {
5157
5756
  if (ABORT) {
5757
+ err('user callback triggered after runtime exited or application aborted. Ignoring.');
5158
5758
  return;
5159
5759
  }
5160
5760
  try {
@@ -5174,6 +5774,7 @@ var ASM_CONSTS = {
5174
5774
  // thread.
5175
5775
  // TODO: How to make this work with wasm64?
5176
5776
  var wait = Atomics.waitAsync(HEAP32, ((pthread_ptr)>>2), pthread_ptr);
5777
+ assert(wait.async);
5177
5778
  wait.value.then(checkMailbox);
5178
5779
  var waitingAsync = pthread_ptr + 128;
5179
5780
  Atomics.store(HEAP32, ((waitingAsync)>>2), 1);
@@ -5204,6 +5805,7 @@ var ASM_CONSTS = {
5204
5805
  } else {
5205
5806
  var worker = PThread.pthreads[targetThread];
5206
5807
  if (!worker) {
5808
+ err(`Cannot send message to thread with ID ${targetThread}, unknown thread ID!`);
5207
5809
  return;
5208
5810
  }
5209
5811
  worker.postMessage({cmd: 'checkMailbox'});
@@ -5232,9 +5834,15 @@ var ASM_CONSTS = {
5232
5834
  }
5233
5835
  // Proxied JS library funcs use funcIndex and EM_ASM functions use emAsmAddr
5234
5836
  var func = emAsmAddr ? ASM_CONSTS[emAsmAddr] : proxiedFunctionTable[funcIndex];
5837
+ assert(!(funcIndex && emAsmAddr));
5838
+ assert(func.length == numCallArgs, 'Call args mismatch in _emscripten_receive_on_main_thread_js');
5235
5839
  PThread.currentProxiedOperationCallerThread = callingThread;
5236
5840
  var rtn = func(...proxiedJSCallArgs);
5237
5841
  PThread.currentProxiedOperationCallerThread = 0;
5842
+ // Proxied functions can return any type except bigint. All other types
5843
+ // cooerce to f64/double (the return type of this function in C) but not
5844
+ // bigint.
5845
+ assert(typeof rtn != "bigint");
5238
5846
  return rtn;
5239
5847
  };
5240
5848
 
@@ -5438,6 +6046,7 @@ var ASM_CONSTS = {
5438
6046
  }
5439
6047
 
5440
6048
 
6049
+
5441
6050
  var __tzset_js = (timezone, daylight, std_name, dst_name) => {
5442
6051
  // TODO: Use (malleable) environment variables instead of system settings.
5443
6052
  var currentYear = new Date().getFullYear();
@@ -5477,6 +6086,10 @@ var ASM_CONSTS = {
5477
6086
 
5478
6087
  var winterName = extractZone(winterOffset);
5479
6088
  var summerName = extractZone(summerOffset);
6089
+ assert(winterName);
6090
+ assert(summerName);
6091
+ assert(lengthBytesUTF8(winterName) <= 16, `timezone name truncated to fit in TZNAME_MAX (${winterName})`);
6092
+ assert(lengthBytesUTF8(summerName) <= 16, `timezone name truncated to fit in TZNAME_MAX (${summerName})`);
5480
6093
  if (summerOffset < winterOffset) {
5481
6094
  // Northern hemisphere
5482
6095
  stringToUTF8(winterName, std_name, 17);
@@ -5525,6 +6138,7 @@ var ASM_CONSTS = {
5525
6138
  };
5526
6139
 
5527
6140
  var runtimeKeepalivePop = () => {
6141
+ assert(runtimeKeepaliveCounter > 0);
5528
6142
  runtimeKeepaliveCounter -= 1;
5529
6143
  };
5530
6144
  /** @param {number=} timeout */
@@ -5536,13 +6150,6 @@ var ASM_CONSTS = {
5536
6150
  }, timeout);
5537
6151
  };
5538
6152
 
5539
- var warnOnce = (text) => {
5540
- warnOnce.shown ||= {};
5541
- if (!warnOnce.shown[text]) {
5542
- warnOnce.shown[text] = 1;
5543
- err(text);
5544
- }
5545
- };
5546
6153
 
5547
6154
 
5548
6155
  var Browser = {
@@ -5579,8 +6186,10 @@ var ASM_CONSTS = {
5579
6186
  b = new Blob([(new Uint8Array(byteArray)).buffer], { type: Browser.getMimetype(name) });
5580
6187
  }
5581
6188
  var url = URL.createObjectURL(b);
6189
+ assert(typeof url == 'string', 'createObjectURL must return a url as a string');
5582
6190
  var img = new Image();
5583
6191
  img.onload = () => {
6192
+ assert(img.complete, `Image ${name} could not be decoded`);
5584
6193
  var canvas = /** @type {!HTMLCanvasElement} */ (document.createElement('canvas'));
5585
6194
  canvas.width = img.width;
5586
6195
  canvas.height = img.height;
@@ -5618,6 +6227,7 @@ var ASM_CONSTS = {
5618
6227
  }
5619
6228
  var b = new Blob([byteArray], { type: Browser.getMimetype(name) });
5620
6229
  var url = URL.createObjectURL(b); // XXX we never revoke this!
6230
+ assert(typeof url == 'string', 'createObjectURL must return a url as a string');
5621
6231
  var audio = new Audio();
5622
6232
  audio.addEventListener('canplaythrough', () => finish(audio), false); // use addEventListener due to chromium bug 124926
5623
6233
  audio.onerror = function audio_onerror(event) {
@@ -5734,6 +6344,7 @@ var ASM_CONSTS = {
5734
6344
  if (!ctx) return null;
5735
6345
 
5736
6346
  if (setInModule) {
6347
+ if (!useWebGL) assert(typeof GLctx == 'undefined', 'cannot set in module if GLctx is used, but we are a non-GL context that would replace it');
5737
6348
  Module['ctx'] = ctx;
5738
6349
  if (useWebGL) GL.makeContextCurrent(contextHandle);
5739
6350
  Browser.useWebGL = useWebGL;
@@ -5803,6 +6414,9 @@ var ASM_CONSTS = {
5803
6414
 
5804
6415
  canvasContainer.requestFullscreen();
5805
6416
  },
6417
+ requestFullScreen() {
6418
+ abort('Module.requestFullScreen has been replaced by Module.requestFullscreen (without a capital S)');
6419
+ },
5806
6420
  exitFullscreen() {
5807
6421
  // This is workaround for chrome. Trying to exit from fullscreen
5808
6422
  // not in fullscreen state will cause "TypeError: Document not active"
@@ -5908,6 +6522,9 @@ var ASM_CONSTS = {
5908
6522
  // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/)
5909
6523
  var scrollX = ((typeof window.scrollX != 'undefined') ? window.scrollX : window.pageXOffset);
5910
6524
  var scrollY = ((typeof window.scrollY != 'undefined') ? window.scrollY : window.pageYOffset);
6525
+ // If this assert lands, it's likely because the browser doesn't support scrollX or pageXOffset
6526
+ // and we have no viable fallback.
6527
+ assert((typeof scrollX != 'undefined') && (typeof scrollY != 'undefined'), 'Unable to retrieve scroll position, mouse positions likely broken.');
5911
6528
  var adjustedX = pageX - (scrollX + rect.left);
5912
6529
  var adjustedY = pageY - (scrollY + rect.top);
5913
6530
 
@@ -6799,6 +7416,7 @@ var ASM_CONSTS = {
6799
7416
  * @param {boolean=} noSetTiming
6800
7417
  */
6801
7418
  var setMainLoop = (iterFunc, fps, simulateInfiniteLoop, arg, noSetTiming) => {
7419
+ assert(!MainLoop.func, 'emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.');
6802
7420
  MainLoop.func = iterFunc;
6803
7421
  MainLoop.arg = arg;
6804
7422
 
@@ -6857,6 +7475,11 @@ var ASM_CONSTS = {
6857
7475
  MainLoop.tickStartTime = _emscripten_get_now();
6858
7476
  }
6859
7477
 
7478
+ if (MainLoop.method === 'timeout' && Module['ctx']) {
7479
+ warnOnce('Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!');
7480
+ MainLoop.method = ''; // just warn once per call to set main loop
7481
+ }
7482
+
6860
7483
  MainLoop.runIter(iterFunc);
6861
7484
 
6862
7485
  // catch pauses from the main loop itself
@@ -6942,6 +7565,7 @@ var ASM_CONSTS = {
6942
7565
  for (var post of MainLoop.postMainLoop) {
6943
7566
  post();
6944
7567
  }
7568
+ checkStackCookie();
6945
7569
  },
6946
7570
  nextRAF:0,
6947
7571
  fakeRequestAnimationFrame(func) {
@@ -6972,6 +7596,7 @@ var ASM_CONSTS = {
6972
7596
  MainLoop.timingValue = value;
6973
7597
 
6974
7598
  if (!MainLoop.func) {
7599
+ err('emscripten_set_main_loop_timing: Cannot set timing mode for main loop since a main loop does not exist! Call emscripten_set_main_loop first to set one up.');
6975
7600
  return 1; // Return non-zero on failure, can't set timing mode when there is no main loop.
6976
7601
  }
6977
7602
 
@@ -7094,11 +7719,20 @@ var ASM_CONSTS = {
7094
7719
 
7095
7720
  var readEmAsmArgsArray = [];
7096
7721
  var readEmAsmArgs = (sigPtr, buf) => {
7722
+ // Nobody should have mutated _readEmAsmArgsArray underneath us to be something else than an array.
7723
+ assert(Array.isArray(readEmAsmArgsArray));
7724
+ // The input buffer is allocated on the stack, so it must be stack-aligned.
7725
+ assert(buf % 16 == 0);
7097
7726
  readEmAsmArgsArray.length = 0;
7098
7727
  var ch;
7099
7728
  // Most arguments are i32s, so shift the buffer pointer so it is a plain
7100
7729
  // index into HEAP32.
7101
7730
  while (ch = HEAPU8[sigPtr++]) {
7731
+ var chr = String.fromCharCode(ch);
7732
+ var validChars = ['d', 'f', 'i', 'p'];
7733
+ // In WASM_BIGINT mode we support passing i64 values as bigint.
7734
+ validChars.push('j');
7735
+ assert(validChars.includes(chr), `Invalid character ${ch}("${chr}") in readEmAsmArgs! Use only [${validChars}], and do not specify "v" for void return argument.`);
7102
7736
  // Floats are always passed as doubles, so all types except for 'i'
7103
7737
  // are 8 bytes and require alignment.
7104
7738
  var wide = (ch != 105);
@@ -7118,6 +7752,7 @@ var ASM_CONSTS = {
7118
7752
  };
7119
7753
  var runEmAsmFunction = (code, sigPtr, argbuf) => {
7120
7754
  var args = readEmAsmArgs(sigPtr, argbuf);
7755
+ assert(ASM_CONSTS.hasOwnProperty(code), `No EM_ASM constant found at address ${code}. The loaded WebAssembly file is likely out of sync with the generated JavaScript.`);
7121
7756
  return ASM_CONSTS[code](...args);
7122
7757
  };
7123
7758
  var _emscripten_asm_const_int = (code, sigPtr, argbuf) => {
@@ -7139,6 +7774,7 @@ var ASM_CONSTS = {
7139
7774
  // code paths as similar as possible on both sides.)
7140
7775
  return proxyToMainThread(0, emAsmAddr, sync, ...args);
7141
7776
  }
7777
+ assert(ASM_CONSTS.hasOwnProperty(emAsmAddr), `No EM_ASM constant found at address ${emAsmAddr}. The loaded WebAssembly file is likely out of sync with the generated JavaScript.`);
7142
7778
  return ASM_CONSTS[emAsmAddr](...args);
7143
7779
  };
7144
7780
  var _emscripten_asm_const_int_sync_on_main_thread = (emAsmAddr, sigPtr, argbuf) => runMainThreadEmAsm(emAsmAddr, sigPtr, argbuf, 1);
@@ -7152,6 +7788,11 @@ var ASM_CONSTS = {
7152
7788
 
7153
7789
 
7154
7790
  var _emscripten_check_blocking_allowed = () => {
7791
+
7792
+ if (ENVIRONMENT_IS_WORKER) return; // Blocking in a worker/pthread is fine.
7793
+
7794
+ warnOnce('Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread');
7795
+
7155
7796
  };
7156
7797
 
7157
7798
 
@@ -7234,6 +7875,8 @@ var ASM_CONSTS = {
7234
7875
  },
7235
7876
  registerOrRemoveHandler(eventHandler) {
7236
7877
  if (!eventHandler.target) {
7878
+ err('registerOrRemoveHandler: the target element for event handler registration does not exist, when processing the following event handler registration:');
7879
+ console.dir(eventHandler);
7237
7880
  return -4;
7238
7881
  }
7239
7882
  if (eventHandler.callbackfunc) {
@@ -7662,10 +8305,12 @@ var ASM_CONSTS = {
7662
8305
 
7663
8306
 
7664
8307
 
8308
+
7665
8309
  function _emscripten_force_exit(status) {
7666
8310
  if (ENVIRONMENT_IS_PTHREAD)
7667
8311
  return proxyToMainThread(42, 0, 1, status);
7668
8312
 
8313
+ warnOnce('emscripten_force_exit cannot actually shut down the runtime, as the build does not have EXIT_RUNTIME set');
7669
8314
  __emscripten_runtime_keepalive_clear();
7670
8315
  _exit(status);
7671
8316
 
@@ -7737,6 +8382,7 @@ var ASM_CONSTS = {
7737
8382
  if (ENVIRONMENT_IS_PTHREAD)
7738
8383
  return proxyToMainThread(45, 0, 1, index, gamepadState);
7739
8384
 
8385
+ if (!JSEvents.lastGamepadState) throw 'emscripten_get_gamepad_status() can only be called after having first called emscripten_sample_gamepad_data() and that function has returned EMSCRIPTEN_RESULT_SUCCESS!';
7740
8386
  // INVALID_PARAM is returned on a Gamepad index that never was there.
7741
8387
  if (index < 0 || index >= JSEvents.lastGamepadState.length) return -5;
7742
8388
 
@@ -7764,6 +8410,7 @@ var ASM_CONSTS = {
7764
8410
  if (ENVIRONMENT_IS_PTHREAD)
7765
8411
  return proxyToMainThread(46, 0, 1);
7766
8412
 
8413
+ if (!JSEvents.lastGamepadState) throw 'emscripten_get_num_gamepads() can only be called after having first called emscripten_sample_gamepad_data() and that function has returned EMSCRIPTEN_RESULT_SUCCESS!';
7767
8414
  // N.B. Do not call emscripten_get_num_gamepads() unless having first called emscripten_sample_gamepad_data(), and that has returned EMSCRIPTEN_RESULT_SUCCESS.
7768
8415
  // Otherwise the following line will throw an exception.
7769
8416
  return JSEvents.lastGamepadState.length;
@@ -8683,10 +9330,17 @@ var ASM_CONSTS = {
8683
9330
  GLctx.getAttribLocation(GL.programs[program], UTF8ToString(name));
8684
9331
  var _emscripten_glGetAttribLocation = _glGetAttribLocation;
8685
9332
 
9333
+
9334
+ var readI53FromU64 = (ptr) => {
9335
+ return HEAPU32[((ptr)>>2)] + HEAPU32[(((ptr)+(4))>>2)] * 4294967296;
9336
+ };
8686
9337
  var writeI53ToI64 = (ptr, num) => {
8687
9338
  HEAPU32[((ptr)>>2)] = num;
8688
9339
  var lower = HEAPU32[((ptr)>>2)];
8689
9340
  HEAPU32[(((ptr)+(4))>>2)] = (num - lower)/4294967296;
9341
+ var deserialized = (num >= 0) ? readI53FromU64(ptr) : readI53FromI64(ptr);
9342
+ var offset = ((ptr)>>2);
9343
+ if (deserialized != num) warnOnce(`writeI53ToI64() out of range: serialized JS Number ${num} to Wasm heap as bytes lo=${ptrToString(HEAPU32[offset])}, hi=${ptrToString(HEAPU32[offset+1])}, which deserializes back to ${deserialized} instead!`);
8690
9344
  };
8691
9345
 
8692
9346
 
@@ -10600,7 +11254,7 @@ var ASM_CONSTS = {
10600
11254
 
10601
11255
 
10602
11256
  var abortOnCannotGrowMemory = (requestedSize) => {
10603
- abort('OOM');
11257
+ abort(`Cannot enlarge memory arrays to size ${requestedSize} bytes (OOM). Either (1) compile with -sINITIAL_MEMORY=X with X higher than the current value ${HEAP8.length}, (2) compile with -sALLOW_MEMORY_GROWTH which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -sABORTING_MALLOC=0`);
10604
11258
  };
10605
11259
  var _emscripten_resize_heap = (requestedSize) => {
10606
11260
  var oldSize = HEAPU8.length;
@@ -10622,6 +11276,7 @@ var ASM_CONSTS = {
10622
11276
  if (navigator.getGamepads) return (JSEvents.lastGamepadState = navigator.getGamepads())
10623
11277
  ? 0 : -1;
10624
11278
  } catch(e) {
11279
+ err(`navigator.getGamepads() exists, but failed to execute with exception ${e}. Disabling Gamepad access.`);
10625
11280
  navigator.getGamepads = null; // Disable getGamepads() so that it won't be attempted to be used again.
10626
11281
  }
10627
11282
  return -1;
@@ -10872,6 +11527,7 @@ var ASM_CONSTS = {
10872
11527
  JSEvents.keyEvent ||= _malloc(160);
10873
11528
 
10874
11529
  var keyEventHandlerFunc = (e) => {
11530
+ assert(e);
10875
11531
 
10876
11532
  var keyEventData = targetThread ? _malloc(160) : JSEvents.keyEvent; // This allocated block is passed as satellite data to the proxied function call, so the call frees up the data block when done.
10877
11533
  HEAPF64[((keyEventData)>>3)] = e.timeStamp;
@@ -10944,6 +11600,7 @@ var ASM_CONSTS = {
10944
11600
 
10945
11601
 
10946
11602
  var fillMouseEventData = (eventStruct, e, target) => {
11603
+ assert(eventStruct % 4 == 0);
10947
11604
  HEAPF64[((eventStruct)>>3)] = e.timeStamp;
10948
11605
  var idx = ((eventStruct)>>2);
10949
11606
  HEAP32[idx + 2] = e.screenX;
@@ -11172,6 +11829,7 @@ var ASM_CONSTS = {
11172
11829
  target = findEventTarget(target);
11173
11830
 
11174
11831
  var touchEventHandlerFunc = (e) => {
11832
+ assert(e);
11175
11833
  var t, touches = {}, et = e.touches;
11176
11834
  // To ease marshalling different kinds of touches that browser reports (all touches are listed in e.touches,
11177
11835
  // only changed touches in e.changedTouches, and touches on target at a.targetTouches), mark a boolean in
@@ -11427,6 +12085,7 @@ var ASM_CONSTS = {
11427
12085
 
11428
12086
  var stringToAscii = (str, buffer) => {
11429
12087
  for (var i = 0; i < str.length; ++i) {
12088
+ assert(str.charCodeAt(i) === (str.charCodeAt(i) & 0xff));
11430
12089
  HEAP8[buffer++] = str.charCodeAt(i);
11431
12090
  }
11432
12091
  // Null-terminate the string
@@ -11635,6 +12294,7 @@ var ASM_CONSTS = {
11635
12294
  };
11636
12295
 
11637
12296
  var dynCall = (sig, ptr, args = []) => {
12297
+ assert(getWasmTableEntry(ptr), `missing table entry in dynCall: ${ptr}`);
11638
12298
  var rtn = getWasmTableEntry(ptr)(...args);
11639
12299
  return rtn;
11640
12300
  };
@@ -11645,11 +12305,13 @@ var ASM_CONSTS = {
11645
12305
 
11646
12306
  var getCFunc = (ident) => {
11647
12307
  var func = Module['_' + ident]; // closure exported function
12308
+ assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported');
11648
12309
  return func;
11649
12310
  };
11650
12311
 
11651
12312
 
11652
12313
  var writeArrayToMemory = (array, buffer) => {
12314
+ assert(array.length >= 0, 'writeArrayToMemory array must have a length (should be an array or typed array)')
11653
12315
  HEAP8.set(array, buffer);
11654
12316
  };
11655
12317
 
@@ -11692,6 +12354,7 @@ var ASM_CONSTS = {
11692
12354
  var func = getCFunc(ident);
11693
12355
  var cArgs = [];
11694
12356
  var stack = 0;
12357
+ assert(returnType !== 'array', 'Return type should not be "array".');
11695
12358
  if (args) {
11696
12359
  for (var i = 0; i < args.length; i++) {
11697
12360
  var converter = toC[argTypes[i]];
@@ -11719,17 +12382,11 @@ var ASM_CONSTS = {
11719
12382
  * @param {Object=} opts
11720
12383
  */
11721
12384
  var cwrap = (ident, returnType, argTypes, opts) => {
11722
- // When the function takes numbers and returns a number, we can just return
11723
- // the original function
11724
- var numericArgs = !argTypes || argTypes.every((type) => type === 'number' || type === 'boolean');
11725
- var numericRet = returnType !== 'string';
11726
- if (numericRet && numericArgs && !opts) {
11727
- return getCFunc(ident);
11728
- }
11729
12385
  return (...args) => ccall(ident, returnType, argTypes, args, opts);
11730
12386
  };
11731
12387
 
11732
12388
  var uleb128Encode = (n, target) => {
12389
+ assert(n < 16384);
11733
12390
  if (n < 128) {
11734
12391
  target.push(n);
11735
12392
  } else {
@@ -11751,6 +12408,7 @@ var ASM_CONSTS = {
11751
12408
  results: sig[0] == 'v' ? [] : [typeNames[sig[0]]]
11752
12409
  };
11753
12410
  for (var i = 1; i < sig.length; ++i) {
12411
+ assert(sig[i] in typeNames, 'invalid signature char: ' + sig[i]);
11754
12412
  type.parameters.push(typeNames[sig[i]]);
11755
12413
  }
11756
12414
  return type;
@@ -11772,6 +12430,7 @@ var ASM_CONSTS = {
11772
12430
  target.push(0x60 /* form: func */);
11773
12431
  uleb128Encode(sigParam.length, target);
11774
12432
  for (var i = 0; i < sigParam.length; ++i) {
12433
+ assert(sigParam[i] in typeCodes, 'invalid signature char: ' + sigParam[i]);
11775
12434
  target.push(typeCodes[sigParam[i]]);
11776
12435
  }
11777
12436
 
@@ -11887,6 +12546,7 @@ var ASM_CONSTS = {
11887
12546
 
11888
12547
  /** @param {string=} sig */
11889
12548
  var addFunction = (func, sig) => {
12549
+ assert(typeof func != 'undefined');
11890
12550
  // Check if the function is already in the table, to ensure each function
11891
12551
  // gets a unique index.
11892
12552
  var rtn = getFunctionAddress(func);
@@ -11906,6 +12566,7 @@ var ASM_CONSTS = {
11906
12566
  if (!(err instanceof TypeError)) {
11907
12567
  throw err;
11908
12568
  }
12569
+ assert(typeof sig != 'undefined', 'Missing signature argument to addFunction: ' + func);
11909
12570
  var wrapped = convertJsFunctionToWasm(func, sig);
11910
12571
  setWasmTableEntry(ret, wrapped);
11911
12572
  }
@@ -11931,15 +12592,9 @@ PThread.init();;
11931
12592
  // Set module methods based on EXPORTED_RUNTIME_METHODS
11932
12593
  ;
11933
12594
 
11934
- // This error may happen quite a bit. To avoid overhead we reuse it (and
11935
- // suffer a lack of stack info).
11936
- MEMFS.doesNotExistError = new FS.ErrnoError(44);
11937
- /** @suppress {checkTypes} */
11938
- MEMFS.doesNotExistError.stack = '<generic error, no stack>';
11939
- ;
11940
-
11941
12595
  // exports
11942
12596
  Module['requestFullscreen'] = Browser.requestFullscreen;
12597
+ Module['requestFullScreen'] = Browser.requestFullScreen;
11943
12598
  Module['setCanvasSize'] = Browser.setCanvasSize;
11944
12599
  Module['getUserMedia'] = Browser.getUserMedia;
11945
12600
  Module['createContext'] = Browser.createContext;
@@ -12040,6 +12695,9 @@ var proxiedFunctionTable = [
12040
12695
  _fd_write
12041
12696
  ];
12042
12697
 
12698
+ function checkIncomingModuleAPI() {
12699
+ ignoredModuleProp('fetchSettings');
12700
+ }
12043
12701
  var wasmImports;
12044
12702
  function assignWasmImports() {
12045
12703
  wasmImports = {
@@ -12840,67 +13498,73 @@ function assignWasmImports() {
12840
13498
  };
12841
13499
  }
12842
13500
  var wasmExports = await createWasm();
12843
- var ___wasm_call_ctors = () => (___wasm_call_ctors = wasmExports['__wasm_call_ctors'])();
12844
- var _screenshot = Module['_screenshot'] = (a0) => (_screenshot = Module['_screenshot'] = wasmExports['screenshot'])(a0);
12845
- var _buttonPress = Module['_buttonPress'] = (a0) => (_buttonPress = Module['_buttonPress'] = wasmExports['buttonPress'])(a0);
12846
- var _buttonUnpress = Module['_buttonUnpress'] = (a0) => (_buttonUnpress = Module['_buttonUnpress'] = wasmExports['buttonUnpress'])(a0);
12847
- var _toggleRewind = Module['_toggleRewind'] = (a0) => (_toggleRewind = Module['_toggleRewind'] = wasmExports['toggleRewind'])(a0);
12848
- var _setVolume = Module['_setVolume'] = (a0) => (_setVolume = Module['_setVolume'] = wasmExports['setVolume'])(a0);
12849
- var _getVolume = Module['_getVolume'] = () => (_getVolume = Module['_getVolume'] = wasmExports['getVolume'])();
12850
- var _getMainLoopTimingMode = Module['_getMainLoopTimingMode'] = () => (_getMainLoopTimingMode = Module['_getMainLoopTimingMode'] = wasmExports['getMainLoopTimingMode'])();
12851
- var _getMainLoopTimingValue = Module['_getMainLoopTimingValue'] = () => (_getMainLoopTimingValue = Module['_getMainLoopTimingValue'] = wasmExports['getMainLoopTimingValue'])();
12852
- var _setMainLoopTiming = Module['_setMainLoopTiming'] = (a0, a1) => (_setMainLoopTiming = Module['_setMainLoopTiming'] = wasmExports['setMainLoopTiming'])(a0, a1);
12853
- var _setFastForwardMultiplier = Module['_setFastForwardMultiplier'] = (a0) => (_setFastForwardMultiplier = Module['_setFastForwardMultiplier'] = wasmExports['setFastForwardMultiplier'])(a0);
12854
- var _getFastForwardMultiplier = Module['_getFastForwardMultiplier'] = () => (_getFastForwardMultiplier = Module['_getFastForwardMultiplier'] = wasmExports['getFastForwardMultiplier'])();
12855
- var _quitGame = Module['_quitGame'] = () => (_quitGame = Module['_quitGame'] = wasmExports['quitGame'])();
12856
- var _free = (a0) => (_free = wasmExports['free'])(a0);
12857
- var _quitMgba = Module['_quitMgba'] = () => (_quitMgba = Module['_quitMgba'] = wasmExports['quitMgba'])();
12858
- var _quickReload = Module['_quickReload'] = () => (_quickReload = Module['_quickReload'] = wasmExports['quickReload'])();
12859
- var _pauseGame = Module['_pauseGame'] = () => (_pauseGame = Module['_pauseGame'] = wasmExports['pauseGame'])();
12860
- var _resumeGame = Module['_resumeGame'] = () => (_resumeGame = Module['_resumeGame'] = wasmExports['resumeGame'])();
12861
- var _setEventEnable = Module['_setEventEnable'] = (a0) => (_setEventEnable = Module['_setEventEnable'] = wasmExports['setEventEnable'])(a0);
12862
- var _bindKey = Module['_bindKey'] = (a0, a1) => (_bindKey = Module['_bindKey'] = wasmExports['bindKey'])(a0, a1);
12863
- var _saveState = Module['_saveState'] = (a0) => (_saveState = Module['_saveState'] = wasmExports['saveState'])(a0);
12864
- var _loadState = Module['_loadState'] = (a0) => (_loadState = Module['_loadState'] = wasmExports['loadState'])(a0);
12865
- var _autoLoadCheats = Module['_autoLoadCheats'] = () => (_autoLoadCheats = Module['_autoLoadCheats'] = wasmExports['autoLoadCheats'])();
12866
- var _loadGame = Module['_loadGame'] = (a0, a1) => (_loadGame = Module['_loadGame'] = wasmExports['loadGame'])(a0, a1);
12867
- var _saveStateSlot = Module['_saveStateSlot'] = (a0, a1) => (_saveStateSlot = Module['_saveStateSlot'] = wasmExports['saveStateSlot'])(a0, a1);
12868
- var _loadStateSlot = Module['_loadStateSlot'] = (a0, a1) => (_loadStateSlot = Module['_loadStateSlot'] = wasmExports['loadStateSlot'])(a0, a1);
12869
- var _addCoreCallbacks = Module['_addCoreCallbacks'] = (a0, a1, a2, a3, a4, a5) => (_addCoreCallbacks = Module['_addCoreCallbacks'] = wasmExports['addCoreCallbacks'])(a0, a1, a2, a3, a4, a5);
12870
- var _setIntegerCoreSetting = Module['_setIntegerCoreSetting'] = (a0, a1) => (_setIntegerCoreSetting = Module['_setIntegerCoreSetting'] = wasmExports['setIntegerCoreSetting'])(a0, a1);
12871
- var _setupConstants = Module['_setupConstants'] = () => (_setupConstants = Module['_setupConstants'] = wasmExports['setupConstants'])();
12872
- var _main = Module['_main'] = (a0, a1) => (_main = Module['_main'] = wasmExports['main'])(a0, a1);
12873
- var _malloc = (a0) => (_malloc = wasmExports['malloc'])(a0);
13501
+ var ___wasm_call_ctors = createExportWrapper('__wasm_call_ctors', 0);
13502
+ var _screenshot = Module['_screenshot'] = createExportWrapper('screenshot', 1);
13503
+ var _buttonPress = Module['_buttonPress'] = createExportWrapper('buttonPress', 1);
13504
+ var _buttonUnpress = Module['_buttonUnpress'] = createExportWrapper('buttonUnpress', 1);
13505
+ var _toggleRewind = Module['_toggleRewind'] = createExportWrapper('toggleRewind', 1);
13506
+ var _setVolume = Module['_setVolume'] = createExportWrapper('setVolume', 1);
13507
+ var _getVolume = Module['_getVolume'] = createExportWrapper('getVolume', 0);
13508
+ var _getMainLoopTimingMode = Module['_getMainLoopTimingMode'] = createExportWrapper('getMainLoopTimingMode', 0);
13509
+ var _getMainLoopTimingValue = Module['_getMainLoopTimingValue'] = createExportWrapper('getMainLoopTimingValue', 0);
13510
+ var _setMainLoopTiming = Module['_setMainLoopTiming'] = createExportWrapper('setMainLoopTiming', 2);
13511
+ var _setFastForwardMultiplier = Module['_setFastForwardMultiplier'] = createExportWrapper('setFastForwardMultiplier', 1);
13512
+ var _getFastForwardMultiplier = Module['_getFastForwardMultiplier'] = createExportWrapper('getFastForwardMultiplier', 0);
13513
+ var _quitGame = Module['_quitGame'] = createExportWrapper('quitGame', 0);
13514
+ var _free = createExportWrapper('free', 1);
13515
+ var _quitMgba = Module['_quitMgba'] = createExportWrapper('quitMgba', 0);
13516
+ var _quickReload = Module['_quickReload'] = createExportWrapper('quickReload', 0);
13517
+ var _pauseGame = Module['_pauseGame'] = createExportWrapper('pauseGame', 0);
13518
+ var _resumeGame = Module['_resumeGame'] = createExportWrapper('resumeGame', 0);
13519
+ var _setEventEnable = Module['_setEventEnable'] = createExportWrapper('setEventEnable', 1);
13520
+ var _bindKey = Module['_bindKey'] = createExportWrapper('bindKey', 2);
13521
+ var _saveState = Module['_saveState'] = createExportWrapper('saveState', 1);
13522
+ var _loadState = Module['_loadState'] = createExportWrapper('loadState', 1);
13523
+ var _autoLoadCheats = Module['_autoLoadCheats'] = createExportWrapper('autoLoadCheats', 0);
13524
+ var _loadGame = Module['_loadGame'] = createExportWrapper('loadGame', 2);
13525
+ var _saveStateSlot = Module['_saveStateSlot'] = createExportWrapper('saveStateSlot', 2);
13526
+ var _loadStateSlot = Module['_loadStateSlot'] = createExportWrapper('loadStateSlot', 2);
13527
+ var _addCoreCallbacks = Module['_addCoreCallbacks'] = createExportWrapper('addCoreCallbacks', 6);
13528
+ var _setIntegerCoreSetting = Module['_setIntegerCoreSetting'] = createExportWrapper('setIntegerCoreSetting', 2);
13529
+ var _setupConstants = Module['_setupConstants'] = createExportWrapper('setupConstants', 0);
13530
+ var _main = Module['_main'] = createExportWrapper('main', 2);
13531
+ var _malloc = createExportWrapper('malloc', 1);
13532
+ var _strerror = createExportWrapper('strerror', 1);
13533
+ var _fflush = createExportWrapper('fflush', 1);
12874
13534
  var _pthread_self = () => (_pthread_self = wasmExports['pthread_self'])();
12875
- var __emscripten_tls_init = () => (__emscripten_tls_init = wasmExports['_emscripten_tls_init'])();
12876
- var _emscripten_builtin_memalign = (a0, a1) => (_emscripten_builtin_memalign = wasmExports['emscripten_builtin_memalign'])(a0, a1);
12877
- var __emscripten_run_callback_on_thread = (a0, a1, a2, a3, a4) => (__emscripten_run_callback_on_thread = wasmExports['_emscripten_run_callback_on_thread'])(a0, a1, a2, a3, a4);
12878
- var __emscripten_thread_init = (a0, a1, a2, a3, a4, a5) => (__emscripten_thread_init = wasmExports['_emscripten_thread_init'])(a0, a1, a2, a3, a4, a5);
12879
- var __emscripten_thread_crashed = () => (__emscripten_thread_crashed = wasmExports['_emscripten_thread_crashed'])();
12880
- var __emscripten_run_on_main_thread_js = (a0, a1, a2, a3, a4) => (__emscripten_run_on_main_thread_js = wasmExports['_emscripten_run_on_main_thread_js'])(a0, a1, a2, a3, a4);
12881
- var __emscripten_thread_free_data = (a0) => (__emscripten_thread_free_data = wasmExports['_emscripten_thread_free_data'])(a0);
12882
- var __emscripten_thread_exit = (a0) => (__emscripten_thread_exit = wasmExports['_emscripten_thread_exit'])(a0);
12883
- var __emscripten_check_mailbox = () => (__emscripten_check_mailbox = wasmExports['_emscripten_check_mailbox'])();
12884
- var _setThrew = (a0, a1) => (_setThrew = wasmExports['setThrew'])(a0, a1);
13535
+ var __emscripten_tls_init = createExportWrapper('_emscripten_tls_init', 0);
13536
+ var _emscripten_builtin_memalign = createExportWrapper('emscripten_builtin_memalign', 2);
13537
+ var __emscripten_run_callback_on_thread = createExportWrapper('_emscripten_run_callback_on_thread', 5);
13538
+ var __emscripten_thread_init = createExportWrapper('_emscripten_thread_init', 6);
13539
+ var __emscripten_thread_crashed = createExportWrapper('_emscripten_thread_crashed', 0);
13540
+ var _emscripten_stack_get_base = () => (_emscripten_stack_get_base = wasmExports['emscripten_stack_get_base'])();
13541
+ var _emscripten_stack_get_end = () => (_emscripten_stack_get_end = wasmExports['emscripten_stack_get_end'])();
13542
+ var __emscripten_run_on_main_thread_js = createExportWrapper('_emscripten_run_on_main_thread_js', 5);
13543
+ var __emscripten_thread_free_data = createExportWrapper('_emscripten_thread_free_data', 1);
13544
+ var __emscripten_thread_exit = createExportWrapper('_emscripten_thread_exit', 1);
13545
+ var __emscripten_check_mailbox = createExportWrapper('_emscripten_check_mailbox', 0);
13546
+ var _setThrew = createExportWrapper('setThrew', 2);
13547
+ var _emscripten_stack_init = () => (_emscripten_stack_init = wasmExports['emscripten_stack_init'])();
12885
13548
  var _emscripten_stack_set_limits = (a0, a1) => (_emscripten_stack_set_limits = wasmExports['emscripten_stack_set_limits'])(a0, a1);
13549
+ var _emscripten_stack_get_free = () => (_emscripten_stack_get_free = wasmExports['emscripten_stack_get_free'])();
12886
13550
  var __emscripten_stack_restore = (a0) => (__emscripten_stack_restore = wasmExports['_emscripten_stack_restore'])(a0);
12887
13551
  var __emscripten_stack_alloc = (a0) => (__emscripten_stack_alloc = wasmExports['_emscripten_stack_alloc'])(a0);
12888
13552
  var _emscripten_stack_get_current = () => (_emscripten_stack_get_current = wasmExports['emscripten_stack_get_current'])();
12889
- var _GBAInputInfo = Module['_GBAInputInfo'] = 122320;
12890
- var _binaryName = Module['_binaryName'] = 198352;
12891
- var _projectName = Module['_projectName'] = 198356;
12892
- var _projectVersion = Module['_projectVersion'] = 198360;
12893
- var _gitCommit = Module['_gitCommit'] = 198336;
12894
- var _gitCommitShort = Module['_gitCommitShort'] = 198340;
12895
- var _gitBranch = Module['_gitBranch'] = 198344;
12896
- var _gitRevision = Module['_gitRevision'] = 198348;
12897
- var _GBIORegisterNames = Module['_GBIORegisterNames'] = 60688;
12898
- var _GBSavestateMagic = Module['_GBSavestateMagic'] = 75952;
12899
- var _GBSavestateVersion = Module['_GBSavestateVersion'] = 75956;
12900
- var _GBA_LUX_LEVELS = Module['_GBA_LUX_LEVELS'] = 105424;
12901
- var _GBAVideoObjSizes = Module['_GBAVideoObjSizes'] = 149760;
12902
- var _GBASavestateMagic = Module['_GBASavestateMagic'] = 149536;
12903
- var _GBASavestateVersion = Module['_GBASavestateVersion'] = 149540;
13553
+ var _GBAInputInfo = Module['_GBAInputInfo'] = 123872;
13554
+ var _binaryName = Module['_binaryName'] = 199904;
13555
+ var _projectName = Module['_projectName'] = 199908;
13556
+ var _projectVersion = Module['_projectVersion'] = 199912;
13557
+ var _gitCommit = Module['_gitCommit'] = 199888;
13558
+ var _gitCommitShort = Module['_gitCommitShort'] = 199892;
13559
+ var _gitBranch = Module['_gitBranch'] = 199896;
13560
+ var _gitRevision = Module['_gitRevision'] = 199900;
13561
+ var _GBIORegisterNames = Module['_GBIORegisterNames'] = 62240;
13562
+ var _GBSavestateMagic = Module['_GBSavestateMagic'] = 77504;
13563
+ var _GBSavestateVersion = Module['_GBSavestateVersion'] = 77508;
13564
+ var _GBA_LUX_LEVELS = Module['_GBA_LUX_LEVELS'] = 106976;
13565
+ var _GBAVideoObjSizes = Module['_GBAVideoObjSizes'] = 151312;
13566
+ var _GBASavestateMagic = Module['_GBASavestateMagic'] = 151088;
13567
+ var _GBASavestateVersion = Module['_GBASavestateVersion'] = 151092;
12904
13568
  function invoke_iiiii(index,a1,a2,a3,a4) {
12905
13569
  var sp = stackSave();
12906
13570
  try {
@@ -13019,9 +13683,316 @@ Module['cwrap'] = cwrap;
13019
13683
  Module['addFunction'] = addFunction;
13020
13684
  Module['removeFunction'] = removeFunction;
13021
13685
  Module['FS'] = FS;
13686
+ var missingLibrarySymbols = [
13687
+ 'writeI53ToI64Clamped',
13688
+ 'writeI53ToI64Signaling',
13689
+ 'writeI53ToU64Clamped',
13690
+ 'writeI53ToU64Signaling',
13691
+ 'convertI32PairToI53',
13692
+ 'convertI32PairToI53Checked',
13693
+ 'convertU32PairToI53',
13694
+ 'getTempRet0',
13695
+ 'setTempRet0',
13696
+ 'growMemory',
13697
+ 'inetPton4',
13698
+ 'inetNtop4',
13699
+ 'inetPton6',
13700
+ 'inetNtop6',
13701
+ 'readSockaddr',
13702
+ 'writeSockaddr',
13703
+ 'emscriptenLog',
13704
+ 'getDynCaller',
13705
+ 'asmjsMangle',
13706
+ 'HandleAllocator',
13707
+ 'getNativeTypeSize',
13708
+ 'addOnInit',
13709
+ 'addOnPostCtor',
13710
+ 'addOnPreMain',
13711
+ 'STACK_SIZE',
13712
+ 'STACK_ALIGN',
13713
+ 'POINTER_SIZE',
13714
+ 'ASSERTIONS',
13715
+ 'reallyNegative',
13716
+ 'unSign',
13717
+ 'strLen',
13718
+ 'reSign',
13719
+ 'formatString',
13720
+ 'intArrayToString',
13721
+ 'AsciiToString',
13722
+ 'UTF16ToString',
13723
+ 'stringToUTF16',
13724
+ 'lengthBytesUTF16',
13725
+ 'UTF32ToString',
13726
+ 'stringToUTF32',
13727
+ 'lengthBytesUTF32',
13728
+ 'fillDeviceOrientationEventData',
13729
+ 'registerDeviceOrientationEventCallback',
13730
+ 'fillDeviceMotionEventData',
13731
+ 'registerDeviceMotionEventCallback',
13732
+ 'screenOrientation',
13733
+ 'fillOrientationChangeEventData',
13734
+ 'registerOrientationChangeEventCallback',
13735
+ 'hideEverythingExceptGivenElement',
13736
+ 'restoreHiddenElements',
13737
+ 'softFullscreenResizeWebGLRenderTarget',
13738
+ 'registerPointerlockErrorEventCallback',
13739
+ 'fillBatteryEventData',
13740
+ 'battery',
13741
+ 'registerBatteryEventCallback',
13742
+ 'jsStackTrace',
13743
+ 'getCallstack',
13744
+ 'convertPCtoSourceLocation',
13745
+ 'wasiRightsToMuslOFlags',
13746
+ 'wasiOFlagsToMuslOFlags',
13747
+ 'setImmediateWrapped',
13748
+ 'safeRequestAnimationFrame',
13749
+ 'clearImmediateWrapped',
13750
+ 'registerPostMainLoop',
13751
+ 'registerPreMainLoop',
13752
+ 'getPromise',
13753
+ 'makePromise',
13754
+ 'idsToPromises',
13755
+ 'makePromiseCallback',
13756
+ 'ExceptionInfo',
13757
+ 'findMatchingCatch',
13758
+ 'Browser_asyncPrepareDataCounter',
13759
+ 'arraySum',
13760
+ 'addDays',
13761
+ 'getSocketFromFD',
13762
+ 'getSocketAddress',
13763
+ 'FS_unlink',
13764
+ 'FS_mkdirTree',
13765
+ '_setNetworkCallback',
13766
+ 'writeGLArray',
13767
+ 'emscripten_webgl_destroy_context_before_on_calling_thread',
13768
+ 'registerWebGlEventCallback',
13769
+ 'runAndAbortIfError',
13770
+ 'ALLOC_NORMAL',
13771
+ 'ALLOC_STACK',
13772
+ 'allocate',
13773
+ 'writeStringToMemory',
13774
+ 'writeAsciiToMemory',
13775
+ 'setErrNo',
13776
+ 'demangle',
13777
+ 'stackTrace',
13778
+ ];
13779
+ missingLibrarySymbols.forEach(missingLibrarySymbol)
13780
+
13781
+ var unexportedSymbols = [
13782
+ 'run',
13783
+ 'addRunDependency',
13784
+ 'removeRunDependency',
13785
+ 'out',
13786
+ 'err',
13787
+ 'callMain',
13788
+ 'abort',
13789
+ 'wasmMemory',
13790
+ 'wasmExports',
13791
+ 'writeStackCookie',
13792
+ 'checkStackCookie',
13793
+ 'writeI53ToI64',
13794
+ 'readI53FromI64',
13795
+ 'readI53FromU64',
13796
+ 'INT53_MAX',
13797
+ 'INT53_MIN',
13798
+ 'bigintToI53Checked',
13799
+ 'stackSave',
13800
+ 'stackRestore',
13801
+ 'stackAlloc',
13802
+ 'ptrToString',
13803
+ 'zeroMemory',
13804
+ 'exitJS',
13805
+ 'getHeapMax',
13806
+ 'abortOnCannotGrowMemory',
13807
+ 'ENV',
13808
+ 'ERRNO_CODES',
13809
+ 'strError',
13810
+ 'DNS',
13811
+ 'Protocols',
13812
+ 'Sockets',
13813
+ 'timers',
13814
+ 'warnOnce',
13815
+ 'readEmAsmArgsArray',
13816
+ 'readEmAsmArgs',
13817
+ 'runEmAsmFunction',
13818
+ 'runMainThreadEmAsm',
13819
+ 'jstoi_q',
13820
+ 'jstoi_s',
13821
+ 'getExecutableName',
13822
+ 'listenOnce',
13823
+ 'autoResumeAudioContext',
13824
+ 'dynCall',
13825
+ 'handleException',
13826
+ 'keepRuntimeAlive',
13827
+ 'runtimeKeepalivePush',
13828
+ 'runtimeKeepalivePop',
13829
+ 'callUserCallback',
13830
+ 'maybeExit',
13831
+ 'asyncLoad',
13832
+ 'alignMemory',
13833
+ 'mmapAlloc',
13834
+ 'wasmTable',
13835
+ 'noExitRuntime',
13836
+ 'addOnPreRun',
13837
+ 'addOnExit',
13838
+ 'addOnPostRun',
13839
+ 'getCFunc',
13840
+ 'ccall',
13841
+ 'uleb128Encode',
13842
+ 'sigToWasmTypes',
13843
+ 'generateFuncType',
13844
+ 'convertJsFunctionToWasm',
13845
+ 'freeTableIndexes',
13846
+ 'functionsInTableMap',
13847
+ 'getEmptyTableSlot',
13848
+ 'updateTableMap',
13849
+ 'getFunctionAddress',
13850
+ 'setValue',
13851
+ 'getValue',
13852
+ 'PATH',
13853
+ 'PATH_FS',
13854
+ 'UTF8Decoder',
13855
+ 'UTF8ArrayToString',
13856
+ 'UTF8ToString',
13857
+ 'stringToUTF8Array',
13858
+ 'stringToUTF8',
13859
+ 'lengthBytesUTF8',
13860
+ 'intArrayFromString',
13861
+ 'stringToAscii',
13862
+ 'UTF16Decoder',
13863
+ 'stringToNewUTF8',
13864
+ 'stringToUTF8OnStack',
13865
+ 'writeArrayToMemory',
13866
+ 'JSEvents',
13867
+ 'registerKeyEventCallback',
13868
+ 'specialHTMLTargets',
13869
+ 'maybeCStringToJsString',
13870
+ 'findEventTarget',
13871
+ 'findCanvasEventTarget',
13872
+ 'getBoundingClientRect',
13873
+ 'fillMouseEventData',
13874
+ 'registerMouseEventCallback',
13875
+ 'registerWheelEventCallback',
13876
+ 'registerUiEventCallback',
13877
+ 'registerFocusEventCallback',
13878
+ 'fillFullscreenChangeEventData',
13879
+ 'registerFullscreenChangeEventCallback',
13880
+ 'JSEvents_requestFullscreen',
13881
+ 'JSEvents_resizeCanvasForFullscreen',
13882
+ 'registerRestoreOldStyle',
13883
+ 'setLetterbox',
13884
+ 'currentFullscreenStrategy',
13885
+ 'restoreOldWindowedStyle',
13886
+ 'doRequestFullscreen',
13887
+ 'fillPointerlockChangeEventData',
13888
+ 'registerPointerlockChangeEventCallback',
13889
+ 'requestPointerLock',
13890
+ 'fillVisibilityChangeEventData',
13891
+ 'registerVisibilityChangeEventCallback',
13892
+ 'registerTouchEventCallback',
13893
+ 'fillGamepadEventData',
13894
+ 'registerGamepadEventCallback',
13895
+ 'registerBeforeUnloadEventCallback',
13896
+ 'setCanvasElementSizeCallingThread',
13897
+ 'setCanvasElementSizeMainThread',
13898
+ 'setCanvasElementSize',
13899
+ 'getCanvasSizeCallingThread',
13900
+ 'getCanvasSizeMainThread',
13901
+ 'getCanvasElementSize',
13902
+ 'UNWIND_CACHE',
13903
+ 'ExitStatus',
13904
+ 'getEnvStrings',
13905
+ 'checkWasiClock',
13906
+ 'doReadv',
13907
+ 'doWritev',
13908
+ 'initRandomFill',
13909
+ 'randomFill',
13910
+ 'safeSetTimeout',
13911
+ 'emSetImmediate',
13912
+ 'emClearImmediate_deps',
13913
+ 'emClearImmediate',
13914
+ 'promiseMap',
13915
+ 'uncaughtExceptionCount',
13916
+ 'exceptionLast',
13917
+ 'exceptionCaught',
13918
+ 'Browser',
13919
+ 'getPreloadedImageData__data',
13920
+ 'wget',
13921
+ 'MONTH_DAYS_REGULAR',
13922
+ 'MONTH_DAYS_LEAP',
13923
+ 'MONTH_DAYS_REGULAR_CUMULATIVE',
13924
+ 'MONTH_DAYS_LEAP_CUMULATIVE',
13925
+ 'isLeapYear',
13926
+ 'ydayFromDate',
13927
+ 'SYSCALLS',
13928
+ 'preloadPlugins',
13929
+ 'FS_createPreloadedFile',
13930
+ 'FS_modeStringToFlags',
13931
+ 'FS_getMode',
13932
+ 'FS_stdin_getChar_buffer',
13933
+ 'FS_stdin_getChar',
13934
+ 'FS_createPath',
13935
+ 'FS_createDevice',
13936
+ 'FS_readFile',
13937
+ 'FS_createDataFile',
13938
+ 'FS_createLazyFile',
13939
+ 'MEMFS',
13940
+ 'TTY',
13941
+ 'PIPEFS',
13942
+ 'SOCKFS',
13943
+ 'tempFixedLengthArray',
13944
+ 'miniTempWebGLFloatBuffers',
13945
+ 'miniTempWebGLIntBuffers',
13946
+ 'heapObjectForWebGLType',
13947
+ 'toTypedArrayIndex',
13948
+ 'webgl_enable_WEBGL_multi_draw',
13949
+ 'webgl_enable_EXT_polygon_offset_clamp',
13950
+ 'webgl_enable_EXT_clip_control',
13951
+ 'webgl_enable_WEBGL_polygon_mode',
13952
+ 'GL',
13953
+ 'emscriptenWebGLGet',
13954
+ 'computeUnpackAlignedImageSize',
13955
+ 'colorChannelsInGlTextureFormat',
13956
+ 'emscriptenWebGLGetTexPixelData',
13957
+ 'emscriptenWebGLGetUniform',
13958
+ 'webglGetUniformLocation',
13959
+ 'webglPrepareUniformLocationsBeforeFirstUse',
13960
+ 'webglGetLeftBracePos',
13961
+ 'emscriptenWebGLGetVertexAttrib',
13962
+ '__glGetActiveAttribOrUniform',
13963
+ 'AL',
13964
+ 'GLUT',
13965
+ 'EGL',
13966
+ 'GLEW',
13967
+ 'IDBStore',
13968
+ 'emscriptenWebGLGetIndexed',
13969
+ 'webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance',
13970
+ 'webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance',
13971
+ 'allocateUTF8',
13972
+ 'allocateUTF8OnStack',
13973
+ 'print',
13974
+ 'printErr',
13975
+ 'PThread',
13976
+ 'terminateWorker',
13977
+ 'cleanupThread',
13978
+ 'registerTLSInit',
13979
+ 'spawnThread',
13980
+ 'exitOnMainThread',
13981
+ 'proxyToMainThread',
13982
+ 'proxiedJSCallArgs',
13983
+ 'invokeEntryPoint',
13984
+ 'checkMailbox',
13985
+ 'IDBFS',
13986
+ ];
13987
+ unexportedSymbols.forEach(unexportedRuntimeSymbol);
13022
13988
 
13023
13989
 
13990
+
13991
+ var calledRun;
13992
+
13024
13993
  function callMain() {
13994
+ assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on Module["onRuntimeInitialized"])');
13995
+ assert(typeof onPreRuns === 'undefined' || onPreRuns.length == 0, 'cannot call main when preRun functions remain to be called');
13025
13996
 
13026
13997
  var entryFunction = _main;
13027
13998
 
@@ -13040,6 +14011,17 @@ function callMain() {
13040
14011
  }
13041
14012
  }
13042
14013
 
14014
+ function stackCheckInit() {
14015
+ // This is normally called automatically during __wasm_call_ctors but need to
14016
+ // get these values before even running any of the ctors so we call it redundantly
14017
+ // here.
14018
+ // See $establishStackSpace for the equivalent code that runs on a thread
14019
+ assert(!ENVIRONMENT_IS_PTHREAD);
14020
+ _emscripten_stack_init();
14021
+ // TODO(sbc): Move writeStackCookie to native to to avoid this.
14022
+ writeStackCookie();
14023
+ }
14024
+
13043
14025
  function run() {
13044
14026
 
13045
14027
  if (runDependencies > 0) {
@@ -13053,6 +14035,8 @@ function run() {
13053
14035
  return;
13054
14036
  }
13055
14037
 
14038
+ stackCheckInit();
14039
+
13056
14040
  preRun();
13057
14041
 
13058
14042
  // a preRun added a dependency, run will be called later
@@ -13064,6 +14048,8 @@ function run() {
13064
14048
  function doRun() {
13065
14049
  // run may have just been called through dependencies being fulfilled just in this very frame,
13066
14050
  // or while the async setStatus time below was happening
14051
+ assert(!calledRun);
14052
+ calledRun = true;
13067
14053
  Module['calledRun'] = true;
13068
14054
 
13069
14055
  if (ABORT) return;
@@ -13074,8 +14060,9 @@ function run() {
13074
14060
 
13075
14061
  readyPromiseResolve(Module);
13076
14062
  Module['onRuntimeInitialized']?.();
14063
+ consumedModuleProp('onRuntimeInitialized');
13077
14064
 
13078
- var noInitialRun = Module['noInitialRun'];
14065
+ var noInitialRun = Module['noInitialRun'];legacyModuleProp('noInitialRun', 'noInitialRun');
13079
14066
  if (!noInitialRun) callMain();
13080
14067
 
13081
14068
  postRun();
@@ -13091,6 +14078,46 @@ function run() {
13091
14078
  {
13092
14079
  doRun();
13093
14080
  }
14081
+ checkStackCookie();
14082
+ }
14083
+
14084
+ function checkUnflushedContent() {
14085
+ // Compiler settings do not allow exiting the runtime, so flushing
14086
+ // the streams is not possible. but in ASSERTIONS mode we check
14087
+ // if there was something to flush, and if so tell the user they
14088
+ // should request that the runtime be exitable.
14089
+ // Normally we would not even include flush() at all, but in ASSERTIONS
14090
+ // builds we do so just for this check, and here we see if there is any
14091
+ // content to flush, that is, we check if there would have been
14092
+ // something a non-ASSERTIONS build would have not seen.
14093
+ // How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0
14094
+ // mode (which has its own special function for this; otherwise, all
14095
+ // the code is inside libc)
14096
+ var oldOut = out;
14097
+ var oldErr = err;
14098
+ var has = false;
14099
+ out = err = (x) => {
14100
+ has = true;
14101
+ }
14102
+ try { // it doesn't matter if it fails
14103
+ _fflush(0);
14104
+ // also flush in the JS FS layer
14105
+ ['stdout', 'stderr'].forEach((name) => {
14106
+ var info = FS.analyzePath('/dev/' + name);
14107
+ if (!info) return;
14108
+ var stream = info.object;
14109
+ var rdev = stream.rdev;
14110
+ var tty = TTY.ttys[rdev];
14111
+ if (tty?.output?.length) {
14112
+ has = true;
14113
+ }
14114
+ });
14115
+ } catch(e) {}
14116
+ out = oldOut;
14117
+ err = oldErr;
14118
+ if (has) {
14119
+ 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.');
14120
+ }
13094
14121
  }
13095
14122
 
13096
14123
  if (Module['preInit']) {
@@ -13099,6 +14126,7 @@ if (Module['preInit']) {
13099
14126
  Module['preInit'].pop()();
13100
14127
  }
13101
14128
  }
14129
+ consumedModuleProp('preInit');
13102
14130
 
13103
14131
  run();
13104
14132
 
@@ -13113,6 +14141,21 @@ run();
13113
14141
 
13114
14142
  moduleRtn = readyPromise;
13115
14143
 
14144
+ // Assertion for attempting to access module properties on the incoming
14145
+ // moduleArg. In the past we used this object as the prototype of the module
14146
+ // and assigned properties to it, but now we return a distinct object. This
14147
+ // keeps the instance private until it is ready (i.e the promise has been
14148
+ // resolved).
14149
+ for (const prop of Object.keys(Module)) {
14150
+ if (!(prop in moduleArg)) {
14151
+ Object.defineProperty(moduleArg, prop, {
14152
+ configurable: true,
14153
+ get() {
14154
+ abort(`Access to module property ('${prop}') is no longer possible via the module constructor argument; Instead, use the result of the module constructor.`)
14155
+ }
14156
+ });
14157
+ }
14158
+ }
13116
14159
  // end include: postamble_modularize.js
13117
14160
 
13118
14161
 
@@ -13121,6 +14164,15 @@ moduleRtn = readyPromise;
13121
14164
  }
13122
14165
  );
13123
14166
  })();
14167
+ (() => {
14168
+ // Create a small, never-async wrapper around mGBA which
14169
+ // checks for callers incorrectly using it with `new`.
14170
+ var real_mGBA = mGBA;
14171
+ mGBA = function(arg) {
14172
+ if (new.target) throw new Error("mGBA() should not be called with `new mGBA()`");
14173
+ return real_mGBA(arg);
14174
+ }
14175
+ })();
13124
14176
  export default mGBA;
13125
14177
  var isPthread = globalThis.self?.name?.startsWith('em-pthread');
13126
14178
  // When running as a pthread, construct a new instance on startup