funicular 0.3.0 → 0.5.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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +486 -1
  3. data/demo/local_notes.html +207 -0
  4. data/demo/test_chartjs.html +9 -9
  5. data/demo/test_component.html +8 -8
  6. data/demo/test_error_boundary.html +44 -41
  7. data/demo/test_router.html +48 -48
  8. data/demo/tic-tac-toe.html +25 -25
  9. data/docs/architecture.md +227 -12
  10. data/docs/local_database.md +1035 -0
  11. data/lib/funicular/assets/funicular.rb +14 -0
  12. data/lib/funicular/configuration.rb +65 -0
  13. data/lib/funicular/epoch_header.rb +69 -0
  14. data/lib/funicular/epoch_stamping.rb +66 -0
  15. data/lib/funicular/helpers/picoruby_helper.rb +96 -1
  16. data/lib/funicular/railtie.rb +30 -0
  17. data/lib/funicular/schema.rb +45 -12
  18. data/lib/funicular/session_epoch.rb +110 -0
  19. data/lib/funicular/ssr/runtime.rb +58 -12
  20. data/lib/funicular/ssr.rb +25 -0
  21. data/lib/funicular/testing/node_runner.mjs +19 -0
  22. data/lib/funicular/testing.rb +47 -0
  23. data/lib/funicular/vendor/mrbc/VERSION +1 -1
  24. data/lib/funicular/vendor/mrbc/mrbc.js +655 -574
  25. data/lib/funicular/vendor/mrbc/mrbc.wasm +0 -0
  26. data/lib/funicular/vendor/picoruby/VERSION +1 -1
  27. data/lib/funicular/vendor/picoruby/debug/picoruby.js +800 -530
  28. data/lib/funicular/vendor/picoruby/debug/picoruby.wasm +0 -0
  29. data/lib/funicular/vendor/picoruby/dist/picoruby.js +2 -2
  30. data/lib/funicular/vendor/picoruby/dist/picoruby.wasm +0 -0
  31. data/lib/funicular/vendor/picoruby-test-node/VERSION +1 -1
  32. data/lib/funicular/vendor/picoruby-test-node/picoruby.js +2 -6909
  33. data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm +0 -0
  34. data/lib/funicular/version.rb +1 -1
  35. data/lib/funicular.rb +1 -0
  36. data/lib/generators/funicular/chat/templates/funicular_chat_component.rb.tt +37 -38
  37. data/lib/tasks/funicular.rake +10 -2
  38. data/minitest/callback_error_visibility_test.rb +48 -0
  39. data/minitest/configuration_test.rb +78 -0
  40. data/minitest/dsl_test.rb +264 -0
  41. data/minitest/epoch_header_test.rb +149 -0
  42. data/minitest/epoch_stamping_test.rb +225 -0
  43. data/minitest/fixtures/funicular_app/components/greeting_component.rb +5 -5
  44. data/minitest/fixtures/funicular_app/components/probe_component.rb +15 -0
  45. data/minitest/form_for_test.rb +2 -2
  46. data/minitest/hydration_test.rb +2 -2
  47. data/minitest/navigation_guard_test.rb +65 -0
  48. data/minitest/picoruby_helper_test.rb +236 -0
  49. data/minitest/schema_test.rb +47 -0
  50. data/minitest/session_epoch_test.rb +122 -0
  51. data/minitest/sig_tags_test.rb +30 -0
  52. data/minitest/ssr_database_test.rb +78 -0
  53. data/minitest/ssr_reload_test.rb +106 -0
  54. data/minitest/ssr_test.rb +41 -0
  55. data/minitest/testing_ensure_compiled_test.rb +52 -0
  56. data/minitest/validations_test.rb +35 -5
  57. data/minitest/view_context_test.rb +15 -15
  58. data/mrbgem.rake +2 -0
  59. data/mrblib/0_tags.rb +62 -0
  60. data/mrblib/cable.rb +1 -1
  61. data/mrblib/component.rb +226 -24
  62. data/mrblib/db.rb +3116 -0
  63. data/mrblib/error_boundary.rb +25 -19
  64. data/mrblib/file_upload.rb +17 -7
  65. data/mrblib/form_builder.rb +10 -10
  66. data/mrblib/funicular.rb +136 -17
  67. data/mrblib/http.rb +84 -107
  68. data/mrblib/model.rb +1178 -23
  69. data/mrblib/relation.rb +342 -0
  70. data/mrblib/router.rb +45 -4
  71. data/mrblib/styles.rb +122 -12
  72. data/mrblib/view_context.rb +3 -32
  73. data/sig/component.rbs +25 -4
  74. data/sig/db.rbs +328 -0
  75. data/sig/error_boundary.rbs +4 -4
  76. data/sig/funicular.rbs +5 -0
  77. data/sig/http.rbs +8 -21
  78. data/sig/model.rbs +101 -7
  79. data/sig/relation.rbs +44 -0
  80. data/sig/router.rbs +1 -0
  81. data/sig/styles.rbs +19 -5
  82. data/sig/tags.rbs +54 -0
  83. data/sig/view_context.rbs +47 -34
  84. metadata +23 -2
  85. data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm.map +0 -1
@@ -4,8 +4,7 @@
4
4
  // When targeting node and ES6 we use `await import ..` in the generated code
5
5
  // so the outer function needs to be marked as async.
6
6
  async function Module(moduleArg = {}) {
7
- var moduleRtn;
8
-
7
+ var Module = moduleArg;
9
8
  // include: shell.js
10
9
  // include: minimum_runtime_check.js
11
10
  (function() {
@@ -24,12 +23,17 @@ async function Module(moduleArg = {}) {
24
23
 
25
24
  // Note: We use a typeof check here instead of optional chaining using
26
25
  // globalThis because older browsers might not have globalThis defined.
27
- var currentNodeVersion = typeof process !== 'undefined' && process.versions?.node ? humanReadableVersionToPacked(process.versions.node) : TARGET_NOT_SUPPORTED;
28
- if (currentNodeVersion < TARGET_NOT_SUPPORTED) {
29
- 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?)');
30
- }
31
- if (currentNodeVersion < 2147483647) {
32
- throw new Error(`This emscripten-generated code requires node v${ packedVersionToHumanReadable(2147483647) } (detected v${packedVersionToHumanReadable(currentNodeVersion)})`);
26
+
27
+ // We skip the node version checking when running on Bun/Deno since the node
28
+ // version they report doesn't seem to be useful.
29
+ if (typeof process !== 'undefined' && !process.versions?.bun && typeof Deno == "undefined") {
30
+ var currentNodeVersion = process.versions?.node ? humanReadableVersionToPacked(process.versions.node) : TARGET_NOT_SUPPORTED;
31
+ if (currentNodeVersion < TARGET_NOT_SUPPORTED) {
32
+ 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?)');
33
+ }
34
+ if (currentNodeVersion < 2147483647) {
35
+ throw new Error(`This emscripten-generated code requires node v${ packedVersionToHumanReadable(2147483647) } (detected v${packedVersionToHumanReadable(currentNodeVersion)})`);
36
+ }
33
37
  }
34
38
 
35
39
  var userAgent = typeof navigator !== 'undefined' && navigator.userAgent;
@@ -67,7 +71,6 @@ async function Module(moduleArg = {}) {
67
71
  // after the generated code, you will need to define var Module = {};
68
72
  // before the code. Then that object will be used in the code, and you
69
73
  // can continue to use Module afterwards as well.
70
- var Module = moduleArg;
71
74
 
72
75
  // Determine the runtime environment we are in. You can customize this by
73
76
  // setting the ENVIRONMENT setting at compile time (see settings.js).
@@ -84,7 +87,7 @@ var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIR
84
87
  // refer to Module (if they choose; they can also define Module)
85
88
 
86
89
 
87
- var arguments_ = [];
90
+ var programArgs = [];
88
91
  var thisProgram = './this.program';
89
92
  var quit_ = (status, toThrow) => {
90
93
  throw toThrow;
@@ -154,11 +157,11 @@ var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js';
154
157
  // perform assertions in shell.js after we set up out() and err(), as otherwise
155
158
  // if an assertion fails it cannot print the message
156
159
 
157
- assert(!ENVIRONMENT_IS_WORKER, 'worker environment detected but not enabled at build time. Add `worker` to `-sENVIRONMENT` to enable.');
160
+ assert(!ENVIRONMENT_IS_WORKER, 'worker environment detected but not enabled at build time (add `worker` to `-sENVIRONMENT` to enable)');
158
161
 
159
- assert(!ENVIRONMENT_IS_NODE, 'node environment detected but not enabled at build time. Add `node` to `-sENVIRONMENT` to enable.');
162
+ assert(!ENVIRONMENT_IS_NODE, 'node environment detected but not enabled at build time (add `node` to `-sENVIRONMENT` to enable)');
160
163
 
161
- assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.');
164
+ assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time (add `shell` to `-sENVIRONMENT` to enable)');
162
165
 
163
166
  // end include: shell.js
164
167
 
@@ -215,45 +218,12 @@ function assert(condition, text) {
215
218
  var isFileURI = (filename) => filename.startsWith('file://');
216
219
 
217
220
  // include: runtime_common.js
218
- // include: runtime_stack_check.js
219
- // Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
220
- function writeStackCookie() {
221
- var max = _emscripten_stack_get_end();
222
- assert((max & 3) == 0);
223
- // If the stack ends at address zero we write our cookies 4 bytes into the
224
- // stack. This prevents interference with SAFE_HEAP and ASAN which also
225
- // monitor writes to address zero.
226
- if (max == 0) {
227
- max += 4;
228
- }
229
- // The stack grow downwards towards _emscripten_stack_get_end.
230
- // We write cookies to the final two words in the stack and detect if they are
231
- // ever overwritten.
232
- HEAPU32[((max)>>2)] = 0x02135467;
233
- HEAPU32[(((max)+(4))>>2)] = 0x89BACDFE;
234
- // Also test the global address 0 for integrity.
235
- HEAPU32[((0)>>2)] = 1668509029;
236
- }
237
-
238
- function checkStackCookie() {
239
- if (ABORT) return;
240
- var max = _emscripten_stack_get_end();
241
- // See writeStackCookie().
242
- if (max == 0) {
243
- max += 4;
244
- }
245
- var cookie1 = HEAPU32[((max)>>2)];
246
- var cookie2 = HEAPU32[(((max)+(4))>>2)];
247
- if (cookie1 != 0x02135467 || cookie2 != 0x89BACDFE) {
248
- abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`);
249
- }
250
- // Also test the global address 0 for integrity.
251
- if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) {
252
- abort('Runtime error: The application has corrupted its heap memory area (address zero)!');
253
- }
254
- }
255
- // end include: runtime_stack_check.js
256
221
  // include: runtime_exceptions.js
222
+ // Base Emscripten EH error class
223
+ class EmscriptenEH {}
224
+
225
+ class EmscriptenSjLj extends EmscriptenEH {}
226
+
257
227
  // end include: runtime_exceptions.js
258
228
  // include: runtime_debug.js
259
229
  var runtimeDebug = true; // Switch to false at runtime to disable logging at the right times
@@ -275,15 +245,31 @@ function dbg(...args) {
275
245
  })();
276
246
 
277
247
  function consumedModuleProp(prop) {
278
- if (!Object.getOwnPropertyDescriptor(Module, prop)) {
279
- Object.defineProperty(Module, prop, {
280
- configurable: true,
281
- set() {
282
- 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'`);
283
-
248
+ var value = Module[prop];
249
+ var msg = `Attempt to modify \`Module.${prop}\` after it has already been processed. This can happen, for example, when code is injected via '--post-js' rather than '--pre-js'`;
250
+ if (Array.isArray(value)) {
251
+ value = new Proxy(value, {
252
+ set(target, key, val) {
253
+ abort(msg);
254
+ return false;
255
+ },
256
+ defineProperty(target, key, descriptor) {
257
+ abort(msg);
258
+ return false;
259
+ },
260
+ deleteProperty(target, key) {
261
+ abort(msg);
262
+ return false;
284
263
  }
285
264
  });
286
265
  }
266
+ Object.defineProperty(Module, prop, {
267
+ configurable: true,
268
+ get() { return value; },
269
+ set() {
270
+ abort(msg);
271
+ }
272
+ });
287
273
  }
288
274
 
289
275
  function makeInvalidEarlyAccess(name) {
@@ -334,41 +320,68 @@ function unexportedRuntimeSymbol(sym) {
334
320
  }
335
321
 
336
322
  // end include: runtime_debug.js
337
- var readyPromiseResolve, readyPromiseReject;
323
+ // include: runtime_stack_check.js
324
+ const stackCookie1 = 0x02135467;
325
+ const stackCookie2 = 0x89BACDFE;
338
326
 
327
+ // Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
328
+ function writeStackCookie() {
329
+ var max = _emscripten_stack_get_end();
330
+ assert((max & 3) == 0);
331
+ // If the stack ends at address zero we write our cookies 4 bytes into the
332
+ // stack. This prevents interference with SAFE_HEAP and ASAN which also
333
+ // monitor writes to address zero.
334
+ if (max == 0) {
335
+ max += 4;
336
+ }
337
+ // The stack grow downwards towards _emscripten_stack_get_end.
338
+ // We write cookies to the final two words in the stack and detect if they are
339
+ // ever overwritten.
340
+ HEAPU32[((max)>>2)] = stackCookie1;
341
+ HEAPU32[(((max)+(4))>>2)] = stackCookie2;
342
+ // Also test the global address 0 for integrity.
343
+ HEAPU32[((0)>>2)] = 1668509029;
344
+ }
345
+
346
+ function u32ToHexString(num) {
347
+ return '0x' + (num >>> 0).toString(16).padStart(8, '0');
348
+ }
349
+
350
+ function checkStackCookie() {
351
+ if (ABORT) return;
352
+ var max = _emscripten_stack_get_end();
353
+ // See writeStackCookie().
354
+ if (max == 0) {
355
+ max += 4;
356
+ }
357
+ var val1 = HEAPU32[((max)>>2)];
358
+ var val2 = HEAPU32[(((max)+(4))>>2)];
359
+ if (val1 != stackCookie1 || val2 != stackCookie2) {
360
+ abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords ${u32ToHexString(stackCookie2)} and ${u32ToHexString(stackCookie1)}, but received ${u32ToHexString(val2)} ${u32ToHexString(val1)}`);
361
+ }
362
+ // Also test the global address 0 for integrity.
363
+ if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) {
364
+ abort('Runtime error: The application has corrupted its heap memory area (address zero)!');
365
+ }
366
+ }
367
+ // end include: runtime_stack_check.js
339
368
  // Memory management
340
- var
341
- /** @type {!Int8Array} */
342
- HEAP8,
343
- /** @type {!Uint8Array} */
344
- HEAPU8,
345
- /** @type {!Int16Array} */
346
- HEAP16,
347
- /** @type {!Uint16Array} */
348
- HEAPU16,
349
- /** @type {!Int32Array} */
350
- HEAP32,
351
- /** @type {!Uint32Array} */
352
- HEAPU32,
353
- /** @type {!Float32Array} */
354
- HEAPF32,
355
- /** @type {!Float64Array} */
356
- HEAPF64;
357
-
358
- // BigInt64Array type is not correctly defined in closure
359
- var
360
- /** not-@type {!BigInt64Array} */
361
- HEAP64,
362
- /* BigUint64Array type is not correctly defined in closure
363
- /** not-@type {!BigUint64Array} */
364
- HEAPU64;
365
369
 
366
370
  var runtimeInitialized = false;
367
371
 
368
372
 
369
373
 
374
+ // When ALLOW_MEMORY_GROWTH is enabled, the conversion from Wasm
375
+ // memory to ArrayBuffer requires some additional logic.
376
+ function getMemoryBuffer() {
377
+ return wasmMemory.buffer;
378
+ }
379
+
370
380
  function updateMemoryViews() {
371
- var b = wasmMemory.buffer;
381
+ // If we already have a heap that is resizeable/growable buffer we don't
382
+ // need to do anything in updateMemoryViews.
383
+ if (HEAP8?.buffer?.resizable) return;
384
+ var b = getMemoryBuffer();
372
385
  HEAP8 = new Int8Array(b);
373
386
  HEAP16 = new Int16Array(b);
374
387
  Module['HEAPU8'] = HEAPU8 = new Uint8Array(b);
@@ -388,11 +401,10 @@ assert(globalThis.Int32Array && globalThis.Float64Array && Int32Array.prototype.
388
401
  'JS engine does not provide full typed array support');
389
402
 
390
403
  function preRun() {
391
- if (Module['preRun']) {
392
- if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
393
- while (Module['preRun'].length) {
394
- addOnPreRun(Module['preRun'].shift());
395
- }
404
+ var preRun = Module['preRun'];
405
+ if (preRun) {
406
+ if (typeof preRun == 'function') preRun = [preRun];
407
+ onPreRuns.push(...preRun);
396
408
  }
397
409
  consumedModuleProp('preRun');
398
410
  // Begin ATPRERUNS hooks
@@ -417,17 +429,17 @@ PIPEFS.root = FS.mount(PIPEFS, {}, null);
417
429
  // Begin ATPOSTCTORS hooks
418
430
  FS.ignorePermissions = false;
419
431
  // End ATPOSTCTORS hooks
432
+
433
+ checkStackCookie();
420
434
  }
421
435
 
422
436
  function postRun() {
423
437
  checkStackCookie();
424
- // PThreads reuse the runtime from the main thread.
425
438
 
426
- if (Module['postRun']) {
427
- if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
428
- while (Module['postRun'].length) {
429
- addOnPostRun(Module['postRun'].shift());
430
- }
439
+ var postRun = Module['postRun'];
440
+ if (postRun) {
441
+ if (typeof postRun == 'function') postRun = [postRun];
442
+ onPostRuns.push(...postRun);
431
443
  }
432
444
  consumedModuleProp('postRun');
433
445
 
@@ -436,11 +448,13 @@ function postRun() {
436
448
  // End ATPOSTRUNS hooks
437
449
  }
438
450
 
439
- /** @param {string|number=} what */
451
+ /**
452
+ * @param {string|number=} what
453
+ */
440
454
  function abort(what) {
441
455
  Module['onAbort']?.(what);
442
456
 
443
- what = 'Aborted(' + what + ')';
457
+ what = `Aborted(${what})`;
444
458
  // TODO(sbc): Should we remove printing and leave it up to whoever
445
459
  // catches the exception?
446
460
  err(what);
@@ -463,21 +477,19 @@ function abort(what) {
463
477
  /** @suppress {checkTypes} */
464
478
  var e = new WebAssembly.RuntimeError(what);
465
479
 
466
- readyPromiseReject?.(e);
467
480
  // Throw the error whether or not MODULARIZE is set because abort is used
468
481
  // in code paths apart from instantiation where an exception is expected
469
482
  // to be thrown when abort is called.
470
483
  throw e;
471
484
  }
472
485
 
473
- function createExportWrapper(name, nargs) {
486
+ function createExportWrapper(name, func, nargs) {
487
+ assert(func);
474
488
  return (...args) => {
475
489
  assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`);
476
- var f = wasmExports[name];
477
- assert(f, `exported native function \`${name}\` not found`);
478
490
  // Only assert for too many arguments. Too few can be valid since the missing arguments will be zero filled.
479
491
  assert(args.length <= nargs, `native function \`${name}\` called with ${args.length} args but expects ${nargs}`);
480
- return f(...args);
492
+ return func(...args);
481
493
  };
482
494
  }
483
495
 
@@ -495,9 +507,6 @@ function findWasmBinary() {
495
507
  }
496
508
 
497
509
  function getBinarySync(file) {
498
- if (file == wasmBinaryFile && wasmBinary) {
499
- return new Uint8Array(wasmBinary);
500
- }
501
510
  if (readBinary) {
502
511
  return readBinary(file);
503
512
  }
@@ -571,8 +580,7 @@ async function createWasm() {
571
580
  // Load the wasm module and create an instance of using native support in the JS engine.
572
581
  // handle a generated wasm instance, receiving its exports and
573
582
  // performing other necessary setup
574
- /** @param {WebAssembly.Module=} module*/
575
- function receiveInstance(instance, module) {
583
+ function receiveInstance(instance) {
576
584
  wasmExports = instance.exports;
577
585
 
578
586
  assignWasmExports(wasmExports);
@@ -605,15 +613,14 @@ async function createWasm() {
605
613
  // performing.
606
614
  // Also pthreads and wasm workers initialize the wasm instance through this
607
615
  // path.
608
- if (Module['instantiateWasm']) {
609
- return new Promise((resolve, reject) => {
616
+ var instantiateWasm = Module['instantiateWasm'];
617
+ if (instantiateWasm) {
618
+ return new Promise((resolve) => {
610
619
  try {
611
- Module['instantiateWasm'](info, (inst, mod) => {
612
- resolve(receiveInstance(inst, mod));
613
- });
620
+ instantiateWasm(info, (inst) => resolve(receiveInstance(inst)));
614
621
  } catch(e) {
615
622
  err(`Module.instantiateWasm callback failed with error: ${e}`);
616
- reject(e);
623
+ throw e;
617
624
  }
618
625
  });
619
626
  }
@@ -637,6 +644,15 @@ async function createWasm() {
637
644
  }
638
645
  }
639
646
 
647
+ /** @type {!Int32Array} */
648
+ var HEAP32;
649
+
650
+ /** @type {!Int8Array} */
651
+ var HEAP8;
652
+
653
+ /** @type {!Uint32Array} */
654
+ var HEAPU32;
655
+
640
656
  var callRuntimeCallbacks = (callbacks) => {
641
657
  while (callbacks.length > 0) {
642
658
  // Pass the module as the first argument.
@@ -650,55 +666,14 @@ async function createWasm() {
650
666
  var addOnPreRun = (cb) => onPreRuns.push(cb);
651
667
 
652
668
 
653
-
654
- /**
655
- * @param {number} ptr
656
- * @param {string} type
657
- */
658
- function getValue(ptr, type = 'i8') {
659
- if (type.endsWith('*')) type = '*';
660
- switch (type) {
661
- case 'i1': return HEAP8[ptr];
662
- case 'i8': return HEAP8[ptr];
663
- case 'i16': return HEAP16[((ptr)>>1)];
664
- case 'i32': return HEAP32[((ptr)>>2)];
665
- case 'i64': return HEAP64[((ptr)>>3)];
666
- case 'float': return HEAPF32[((ptr)>>2)];
667
- case 'double': return HEAPF64[((ptr)>>3)];
668
- case '*': return HEAPU32[((ptr)>>2)];
669
- default: abort(`invalid type for getValue: ${type}`);
670
- }
671
- }
672
-
673
669
  var noExitRuntime = true;
674
670
 
675
- var ptrToString = (ptr) => {
671
+ function ptrToString(ptr) {
676
672
  assert(typeof ptr === 'number', `ptrToString expects a number, got ${typeof ptr}`);
677
673
  // Convert to 32-bit unsigned value
678
674
  ptr >>>= 0;
679
675
  return '0x' + ptr.toString(16).padStart(8, '0');
680
- };
681
-
682
-
683
- /**
684
- * @param {number} ptr
685
- * @param {number} value
686
- * @param {string} type
687
- */
688
- function setValue(ptr, value, type = 'i8') {
689
- if (type.endsWith('*')) type = '*';
690
- switch (type) {
691
- case 'i1': HEAP8[ptr] = value; break;
692
- case 'i8': HEAP8[ptr] = value; break;
693
- case 'i16': HEAP16[((ptr)>>1)] = value; break;
694
- case 'i32': HEAP32[((ptr)>>2)] = value; break;
695
- case 'i64': HEAP64[((ptr)>>3)] = BigInt(value); break;
696
- case 'float': HEAPF32[((ptr)>>2)] = value; break;
697
- case 'double': HEAPF64[((ptr)>>3)] = value; break;
698
- case '*': HEAPU32[((ptr)>>2)] = value; break;
699
- default: abort(`invalid type for setValue: ${type}`);
700
676
  }
701
- }
702
677
 
703
678
  var stackRestore = (val) => __emscripten_stack_restore(val);
704
679
 
@@ -716,6 +691,14 @@ async function createWasm() {
716
691
 
717
692
  var UTF8Decoder = globalThis.TextDecoder && new TextDecoder();
718
693
 
694
+
695
+ /**
696
+ * heapOrArray is either a regular array, or a JavaScript typed array view.
697
+ * @param {number} idx
698
+ * @param {number=} maxBytesToRead
699
+ * @param {boolean=} ignoreNul
700
+ * @return {number}
701
+ */
719
702
  var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => {
720
703
  var maxIdx = idx + maxBytesToRead;
721
704
  if (ignoreNul) return maxIdx;
@@ -760,7 +743,7 @@ async function createWasm() {
760
743
  if ((u0 & 0xF0) == 0xE0) {
761
744
  u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
762
745
  } else {
763
- 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!');
746
+ 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!`);
764
747
  u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
765
748
  }
766
749
 
@@ -774,6 +757,9 @@ async function createWasm() {
774
757
  return str;
775
758
  };
776
759
 
760
+ /** @type {!Uint8Array} */
761
+ var HEAPU8;
762
+
777
763
  /**
778
764
  * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
779
765
  * emscripten HEAP, returns a copy of that string as a Javascript String object.
@@ -804,7 +790,7 @@ async function createWasm() {
804
790
  wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
805
791
  }
806
792
  /** @suppress {checkTypes} */
807
- assert(wasmTable.get(funcPtr) == func, 'JavaScript-side Wasm function table mirror is out of date!');
793
+ assert(wasmTable.get(funcPtr) == func, 'table mirror is out of date');
808
794
  return func;
809
795
  };
810
796
  var ___call_sighandler = (fp, sig) => getWasmTableEntry(fp)(sig);
@@ -872,12 +858,9 @@ join2:(l, r) => PATH.normalize(l + '/' + r),
872
858
 
873
859
  var initRandomFill = () => {
874
860
 
875
- return (view) => crypto.getRandomValues(view);
876
- };
877
- var randomFill = (view) => {
878
- // Lazily init on the first invocation.
879
- (randomFill = initRandomFill())(view);
861
+ return (view) => (crypto.getRandomValues(view), 0);
880
862
  };
863
+ var randomFill = (view) => (randomFill = initRandomFill())(view);
881
864
 
882
865
 
883
866
 
@@ -988,7 +971,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
988
971
  heap[outIdx++] = 0x80 | (u & 63);
989
972
  } else {
990
973
  if (outIdx + 3 >= endIdx) break;
991
- 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).');
974
+ 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).`);
992
975
  heap[outIdx++] = 0xF0 | (u >> 18);
993
976
  heap[outIdx++] = 0x80 | ((u >> 12) & 63);
994
977
  heap[outIdx++] = 0x80 | ((u >> 6) & 63);
@@ -1083,7 +1066,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1083
1066
  } catch (e) {
1084
1067
  throw new FS.ErrnoError(29);
1085
1068
  }
1086
- if (result === undefined && bytesRead === 0) {
1069
+ if (result === undefined && !bytesRead) {
1087
1070
  throw new FS.ErrnoError(6);
1088
1071
  }
1089
1072
  if (result === null || result === undefined) break;
@@ -1174,7 +1157,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1174
1157
  var zeroMemory = (ptr, size) => HEAPU8.fill(0, ptr, ptr + size);
1175
1158
 
1176
1159
  var alignMemory = (size, alignment) => {
1177
- assert(alignment, "alignment argument is required");
1160
+ assert(alignment, 'alignment argument is required');
1178
1161
  return Math.ceil(size / alignment) * alignment;
1179
1162
  };
1180
1163
  var mmapAlloc = (size) => {
@@ -1183,6 +1166,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1183
1166
  if (ptr) zeroMemory(ptr, size);
1184
1167
  return ptr;
1185
1168
  };
1169
+
1186
1170
  var MEMFS = {
1187
1171
  ops_table:null,
1188
1172
  mount(mount) {
@@ -1247,11 +1231,14 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1247
1231
  } else if (FS.isFile(node.mode)) {
1248
1232
  node.node_ops = MEMFS.ops_table.file.node;
1249
1233
  node.stream_ops = MEMFS.ops_table.file.stream;
1250
- node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity.
1251
- // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred
1252
- // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size
1253
- // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme.
1254
- node.contents = null;
1234
+ // The actual number of bytes used in the typed array, as opposed to
1235
+ // contents.length which gives the whole capacity.
1236
+ node.usedBytes = 0;
1237
+ // The byte data of the file is stored in a typed array.
1238
+ // Note: typed arrays are not resizable like normal JS arrays are, so
1239
+ // there is a small penalty involved for appending file writes that
1240
+ // continuously grow a file similar to std::vector capacity vs used.
1241
+ node.contents = MEMFS.emptyFileContents ??= new Uint8Array(0);
1255
1242
  } else if (FS.isLink(node.mode)) {
1256
1243
  node.node_ops = MEMFS.ops_table.link.node;
1257
1244
  node.stream_ops = MEMFS.ops_table.link.stream;
@@ -1268,36 +1255,30 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1268
1255
  return node;
1269
1256
  },
1270
1257
  getFileDataAsTypedArray(node) {
1271
- if (!node.contents) return new Uint8Array(0);
1272
- if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes.
1273
- return new Uint8Array(node.contents);
1258
+ assert(FS.isFile(node.mode), 'getFileDataAsTypedArray called on non-file');
1259
+ return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes.
1274
1260
  },
1275
1261
  expandFileStorage(node, newCapacity) {
1276
- var prevCapacity = node.contents ? node.contents.length : 0;
1262
+ var prevCapacity = node.contents.length;
1277
1263
  if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough.
1278
- // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity.
1279
- // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to
1280
- // avoid overshooting the allocation cap by a very large margin.
1264
+ // Don't expand strictly to the given requested limit if it's only a very
1265
+ // small increase, but instead geometrically grow capacity.
1266
+ // For small filesizes (<1MB), perform size*2 geometric increase, but for
1267
+ // large sizes, do a much more conservative size*1.125 increase to avoid
1268
+ // overshooting the allocation cap by a very large margin.
1281
1269
  var CAPACITY_DOUBLING_MAX = 1024 * 1024;
1282
1270
  newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0);
1283
- if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.
1284
- var oldContents = node.contents;
1271
+ if (prevCapacity) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.
1272
+ var oldContents = MEMFS.getFileDataAsTypedArray(node);
1285
1273
  node.contents = new Uint8Array(newCapacity); // Allocate new storage.
1286
- if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage.
1274
+ node.contents.set(oldContents);
1287
1275
  },
1288
1276
  resizeFileStorage(node, newSize) {
1289
1277
  if (node.usedBytes == newSize) return;
1290
- if (newSize == 0) {
1291
- node.contents = null; // Fully decommit when requesting a resize to zero.
1292
- node.usedBytes = 0;
1293
- } else {
1294
- var oldContents = node.contents;
1295
- node.contents = new Uint8Array(newSize); // Allocate new storage.
1296
- if (oldContents) {
1297
- node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage.
1298
- }
1299
- node.usedBytes = newSize;
1300
- }
1278
+ var oldContents = node.contents;
1279
+ node.contents = new Uint8Array(newSize); // Allocate new storage.
1280
+ node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage.
1281
+ node.usedBytes = newSize;
1301
1282
  },
1302
1283
  node_ops:{
1303
1284
  getattr(node) {
@@ -1329,7 +1310,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1329
1310
  return attr;
1330
1311
  },
1331
1312
  setattr(node, attr) {
1332
- for (const key of ["mode", "atime", "mtime", "ctime"]) {
1313
+ for (const key of ['mode', 'atime', 'mtime', 'ctime']) {
1333
1314
  if (attr[key] != null) {
1334
1315
  node[key] = attr[key];
1335
1316
  }
@@ -1397,16 +1378,11 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1397
1378
  if (position >= stream.node.usedBytes) return 0;
1398
1379
  var size = Math.min(stream.node.usedBytes - position, length);
1399
1380
  assert(size >= 0);
1400
- if (size > 8 && contents.subarray) { // non-trivial, and typed array
1401
- buffer.set(contents.subarray(position, position + size), offset);
1402
- } else {
1403
- for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
1404
- }
1381
+ buffer.set(contents.subarray(position, position + size), offset);
1405
1382
  return size;
1406
1383
  },
1407
1384
  write(stream, buffer, offset, length, position, canOwn) {
1408
- // The data buffer should be a typed array view
1409
- assert(!(buffer instanceof ArrayBuffer));
1385
+ assert(buffer.subarray, 'FS.write expects a TypedArray');
1410
1386
  // If the buffer is located in main memory (HEAP), and if
1411
1387
  // memory can grow, we can't hold on to references of the
1412
1388
  // memory buffer, as they may get invalidated. That means we
@@ -1419,33 +1395,19 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1419
1395
  var node = stream.node;
1420
1396
  node.mtime = node.ctime = Date.now();
1421
1397
 
1422
- if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array?
1423
- if (canOwn) {
1424
- assert(position === 0, 'canOwn must imply no weird position inside the file');
1425
- node.contents = buffer.subarray(offset, offset + length);
1426
- node.usedBytes = length;
1427
- return length;
1428
- } else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data.
1429
- node.contents = buffer.slice(offset, offset + length);
1430
- node.usedBytes = length;
1431
- return length;
1432
- } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file?
1433
- node.contents.set(buffer.subarray(offset, offset + length), position);
1434
- return length;
1435
- }
1436
- }
1437
-
1438
- // Appending to an existing file and we need to reallocate, or source data did not come as a typed array.
1439
- MEMFS.expandFileStorage(node, position+length);
1440
- if (node.contents.subarray && buffer.subarray) {
1398
+ if (canOwn) {
1399
+ assert(!position, 'canOwn must imply no weird position inside the file');
1400
+ node.contents = buffer.subarray(offset, offset + length);
1401
+ node.usedBytes = length;
1402
+ } else if (!node.usedBytes && !position) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data.
1403
+ node.contents = buffer.slice(offset, offset + length);
1404
+ node.usedBytes = length;
1405
+ } else {
1406
+ MEMFS.expandFileStorage(node, position+length);
1441
1407
  // Use typed array write which is available.
1442
1408
  node.contents.set(buffer.subarray(offset, offset + length), position);
1443
- } else {
1444
- for (var i = 0; i < length; i++) {
1445
- node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not.
1446
- }
1409
+ node.usedBytes = Math.max(node.usedBytes, position + length);
1447
1410
  }
1448
- node.usedBytes = Math.max(node.usedBytes, position + length);
1449
1411
  return length;
1450
1412
  },
1451
1413
  llseek(stream, offset, whence) {
@@ -1470,7 +1432,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1470
1432
  var allocated;
1471
1433
  var contents = stream.node.contents;
1472
1434
  // Only make a new copy when MAP_PRIVATE is specified.
1473
- if (!(flags & 2) && contents && contents.buffer === HEAP8.buffer) {
1435
+ if (!(flags & 2) && contents.buffer === HEAP8.buffer) {
1474
1436
  // We can't emulate MAP_SHARED when the file is not backed by the
1475
1437
  // buffer we're mapping to (e.g. the HEAP buffer).
1476
1438
  allocated = false;
@@ -1504,6 +1466,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1504
1466
  };
1505
1467
 
1506
1468
  var FS_modeStringToFlags = (str) => {
1469
+ if (typeof str != 'string') return str;
1507
1470
  var flagModes = {
1508
1471
  'r': 0,
1509
1472
  'r+': 2,
@@ -1519,6 +1482,16 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1519
1482
  return flags;
1520
1483
  };
1521
1484
 
1485
+ var FS_fileDataToTypedArray = (data) => {
1486
+ if (typeof data == 'string') {
1487
+ data = intArrayFromString(data, true);
1488
+ }
1489
+ if (!data.subarray) {
1490
+ data = new Uint8Array(data);
1491
+ }
1492
+ return data;
1493
+ };
1494
+
1522
1495
  var FS_getMode = (canRead, canWrite) => {
1523
1496
  var mode = 0;
1524
1497
  if (canRead) mode |= 292 | 73;
@@ -1672,10 +1645,12 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1672
1645
  }
1673
1646
  };
1674
1647
 
1648
+ var dependenciesPromise = null;
1649
+ var resolveRunDependencies = async () => dependenciesPromise;
1675
1650
  var runDependencies = 0;
1676
1651
 
1677
1652
 
1678
- var dependenciesFulfilled = null;
1653
+ var dependenciesPromiseResolve = null;
1679
1654
 
1680
1655
  var runDependencyTracking = {
1681
1656
  };
@@ -1689,21 +1664,22 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1689
1664
  assert(id, 'removeRunDependency requires an ID');
1690
1665
  assert(runDependencyTracking[id]);
1691
1666
  delete runDependencyTracking[id];
1692
- if (runDependencies == 0) {
1667
+ if (!runDependencies) {
1693
1668
  if (runDependencyWatcher !== null) {
1694
1669
  clearInterval(runDependencyWatcher);
1695
1670
  runDependencyWatcher = null;
1696
1671
  }
1697
- if (dependenciesFulfilled) {
1698
- var callback = dependenciesFulfilled;
1699
- dependenciesFulfilled = null;
1700
- callback(); // can add another dependenciesFulfilled
1701
- }
1672
+ dependenciesPromiseResolve();
1702
1673
  }
1703
1674
  };
1704
1675
 
1705
1676
 
1677
+
1678
+
1706
1679
  var addRunDependency = (id) => {
1680
+ if (!runDependencies) {
1681
+ dependenciesPromise = new Promise((resolve) => dependenciesPromiseResolve = resolve);
1682
+ }
1707
1683
  runDependencies++;
1708
1684
 
1709
1685
  Module['monitorRunDependencies']?.(runDependencies);
@@ -1711,7 +1687,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1711
1687
  assert(id, 'addRunDependency requires an ID')
1712
1688
  assert(!runDependencyTracking[id]);
1713
1689
  runDependencyTracking[id] = 1;
1714
- if (runDependencyWatcher === null && globalThis.setInterval) {
1690
+ if (!runDependencyWatcher && globalThis.setInterval) {
1715
1691
  // Check for missing dependencies every few seconds
1716
1692
  runDependencyWatcher = setInterval(() => {
1717
1693
  if (ABORT) {
@@ -1775,6 +1751,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1775
1751
  var FS_createPreloadedFile = (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => {
1776
1752
  FS_preloadFile(parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish).then(onload).catch(onerror);
1777
1753
  };
1754
+
1778
1755
  var FS = {
1779
1756
  root:null,
1780
1757
  mounts:[],
@@ -1873,6 +1850,48 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1873
1850
  get isDevice() {
1874
1851
  return FS.isChrdev(this.mode);
1875
1852
  }
1853
+ // The per-inode readiness wait-queue. The node carries a Set of listener
1854
+ // entries {cb}; producers (SOCKFS, PIPEFS) call notifyListeners on a
1855
+ // readiness transition, and poll()/epoll consume it. It lives on the node
1856
+ // (not the fd) so dup'd fds share one queue. Only nodes that derive real
1857
+ // readiness (sockets, pipes, and an epoll's own node) ever use this -
1858
+ // always-ready types (regular files, ttys) never register or notify.
1859
+ addListener(cb, exclusive = false) {
1860
+ var entry = {cb, exclusive};
1861
+ var listeners = (this.listeners ??= new Set());
1862
+ listeners.add(entry);
1863
+ return {listeners, entry};
1864
+ }
1865
+ notifyListeners(flags) {
1866
+ // Iterates the set without copying, which is safe ONLY under a
1867
+ // load-bearing contract that every internal listener must honour:
1868
+ // 1. A listener must not run user code synchronously (a poll waiter only
1869
+ // resolves a Promise; an epoll registration only re-lists +
1870
+ // re-notifies; the epoll callback only schedules a tick). User code
1871
+ // runs on a later tick, never inside this loop.
1872
+ // 2. A listener may delete entries only from ITS OWN waiter, never from
1873
+ // a sibling node's set that may be mid-iteration. (Deleting an entry
1874
+ // of the set being iterated here is fine - a Set tolerates removal of
1875
+ // a not-yet-visited entry mid-iteration; mutating a *different* node's
1876
+ // set is fine because that set is not being iterated.)
1877
+ // Violating either gives silently skipped wakeups that are near-impossible
1878
+ // to reproduce. Any new producer/listener must preserve it.
1879
+ if (!this.listeners) return;
1880
+ // Fire every non-exclusive listener. Among EPOLLEXCLUSIVE registrations
1881
+ // (one fd watched by several epolls) wake only one, rotating round-robin
1882
+ // per node, to avoid a thundering herd. (Only epoll registrations are ever
1883
+ // exclusive; poll waiters and a node's own consumers are not.)
1884
+ var excl;
1885
+ for (var entry of this.listeners) {
1886
+ if (entry.exclusive) (excl ||= []).push(entry);
1887
+ else entry.cb(flags);
1888
+ }
1889
+ if (excl) {
1890
+ var i = (this.exclTurn || 0) % excl.length;
1891
+ this.exclTurn = i + 1;
1892
+ excl[i].cb(flags);
1893
+ }
1894
+ }
1876
1895
  },
1877
1896
  lookupPath(path, opts = {}) {
1878
1897
  if (!path) {
@@ -1884,7 +1903,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
1884
1903
  path = FS.cwd() + '/' + path;
1885
1904
  }
1886
1905
 
1887
- // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
1906
+ // limit max consecutive symlinks to SYMLOOP_MAX.
1888
1907
  linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) {
1889
1908
  // split the absolute path
1890
1909
  var parts = path.split('/').filter((p) => !!p);
@@ -2176,7 +2195,14 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
2176
2195
  var arg = setattr ? stream : node;
2177
2196
  setattr ??= node.node_ops.setattr;
2178
2197
  FS.checkOpExists(setattr, 63)
2179
- setattr(arg, attr);
2198
+ try {
2199
+ setattr(arg, attr);
2200
+ } catch (e) {
2201
+ if (e instanceof RangeError) {
2202
+ throw new FS.ErrnoError(22);
2203
+ }
2204
+ throw e;
2205
+ }
2180
2206
  },
2181
2207
  chrdev_stream_ops:{
2182
2208
  open(stream) {
@@ -2443,6 +2469,25 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
2443
2469
  }
2444
2470
  return parent.node_ops.symlink(parent, newname, oldpath);
2445
2471
  },
2472
+ link(oldpath, newpath, flags) {
2473
+ var lookup = FS.lookupPath(newpath, { parent: true });
2474
+ var parent = lookup.node;
2475
+ if (!parent) {
2476
+ throw new FS.ErrnoError(44);
2477
+ }
2478
+ var newname = PATH.basename(newpath);
2479
+ var errCode = FS.mayCreate(parent, newname);
2480
+ if (errCode) {
2481
+ throw new FS.ErrnoError(errCode);
2482
+ }
2483
+ // Hardlinks are only supported by filesystem backends that provide a
2484
+ // `link` node op (e.g. NODERAWFS backed by the host). NODEFS omits it:
2485
+ // a host hardlink cannot be confined to the mount root.
2486
+ if (!parent.node_ops.link) {
2487
+ throw new FS.ErrnoError(34);
2488
+ }
2489
+ return parent.node_ops.link(parent, newname, oldpath, flags);
2490
+ },
2446
2491
  rename(old_path, new_path) {
2447
2492
  var old_dirname = PATH.dirname(old_path);
2448
2493
  var new_dirname = PATH.dirname(new_path);
@@ -2689,20 +2734,19 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
2689
2734
  }
2690
2735
  FS.doTruncate(stream, stream.node, len);
2691
2736
  },
2692
- utime(path, atime, mtime) {
2693
- var lookup = FS.lookupPath(path, { follow: true });
2694
- var node = lookup.node;
2695
- var setattr = FS.checkOpExists(node.node_ops.setattr, 63);
2696
- setattr(node, {
2737
+ utime(path, atime, mtime, dontFollow) {
2738
+ var lookup = FS.lookupPath(path, { follow: !dontFollow });
2739
+ FS.doSetAttr(null, lookup.node, {
2697
2740
  atime: atime,
2698
- mtime: mtime
2741
+ mtime: mtime,
2742
+ dontFollow
2699
2743
  });
2700
2744
  },
2701
2745
  open(path, flags, mode = 0o666) {
2702
- if (path === "") {
2746
+ if (path === '') {
2703
2747
  throw new FS.ErrnoError(44);
2704
2748
  }
2705
- flags = typeof flags == 'string' ? FS_modeStringToFlags(flags) : flags;
2749
+ flags = FS_modeStringToFlags(flags);
2706
2750
  if ((flags & 64)) {
2707
2751
  mode = (mode & 4095) | 32768;
2708
2752
  } else {
@@ -2713,7 +2757,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
2713
2757
  if (typeof path == 'object') {
2714
2758
  node = path;
2715
2759
  } else {
2716
- isDirPath = path.endsWith("/");
2760
+ isDirPath = path.endsWith('/');
2717
2761
  // noent_okay makes it so that if the final component of the path
2718
2762
  // doesn't exist, lookupPath returns `node: undefined`. `path` will be
2719
2763
  // updated to point to the target of all symlinks.
@@ -2796,6 +2840,11 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
2796
2840
  throw new FS.ErrnoError(8);
2797
2841
  }
2798
2842
  if (stream.getdents) stream.getdents = null; // free readdir state
2843
+ // The fd is going away: wake anything waiting on it (poll/epoll) with
2844
+ // POLLNVAL so a blocking wait unblocks and an epoll registration is evicted
2845
+ // on its next derive. Only sockets/pipes/epoll ever carry a wait-queue, so
2846
+ // for every other stream (incl. nodeless noderawfs stdio) this is a no-op.
2847
+ stream.node?.notifyListeners(32);
2799
2848
  try {
2800
2849
  if (stream.stream_ops.close) {
2801
2850
  stream.stream_ops.close(stream);
@@ -2853,6 +2902,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
2853
2902
  },
2854
2903
  write(stream, buffer, offset, length, position, canOwn) {
2855
2904
  assert(offset >= 0);
2905
+ assert(buffer.subarray, 'FS.write expects a TypedArray');
2856
2906
  if (length < 0 || position < 0) {
2857
2907
  throw new FS.ErrnoError(28);
2858
2908
  }
@@ -2889,8 +2939,8 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
2889
2939
  // to write to file opened in read-only mode with MAP_PRIVATE flag,
2890
2940
  // as all modifications will be visible only in the memory of
2891
2941
  // the current process.
2892
- if ((prot & 2) !== 0
2893
- && (flags & 2) === 0
2942
+ if ((prot & 2)
2943
+ && !(flags & 2)
2894
2944
  && (stream.flags & 2097155) !== 2) {
2895
2945
  throw new FS.ErrnoError(2);
2896
2946
  }
@@ -2919,8 +2969,8 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
2919
2969
  return stream.stream_ops.ioctl(stream, cmd, arg);
2920
2970
  },
2921
2971
  readFile(path, opts = {}) {
2922
- opts.flags = opts.flags || 0;
2923
- opts.encoding = opts.encoding || 'binary';
2972
+ opts.flags = opts.flags ?? 0;
2973
+ opts.encoding = opts.encoding ?? 'binary';
2924
2974
  if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') {
2925
2975
  abort(`Invalid encoding type "${opts.encoding}"`);
2926
2976
  }
@@ -2936,16 +2986,10 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
2936
2986
  return buf;
2937
2987
  },
2938
2988
  writeFile(path, data, opts = {}) {
2939
- opts.flags = opts.flags || 577;
2989
+ opts.flags = opts.flags ?? 577;
2940
2990
  var stream = FS.open(path, opts.flags, opts.mode);
2941
- if (typeof data == 'string') {
2942
- data = new Uint8Array(intArrayFromString(data, true));
2943
- }
2944
- if (ArrayBuffer.isView(data)) {
2945
- FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
2946
- } else {
2947
- abort('Unsupported data type');
2948
- }
2991
+ data = FS_fileDataToTypedArray(data);
2992
+ FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
2949
2993
  FS.close(stream);
2950
2994
  },
2951
2995
  cwd:() => FS.currentPath,
@@ -2989,7 +3033,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
2989
3033
  // use a buffer to avoid overhead of individual crypto calls per byte
2990
3034
  var randomBuffer = new Uint8Array(1024), randomLeft = 0;
2991
3035
  var randomByte = () => {
2992
- if (randomLeft === 0) {
3036
+ if (!randomLeft) {
2993
3037
  randomFill(randomBuffer);
2994
3038
  randomLeft = randomBuffer.byteLength;
2995
3039
  }
@@ -3170,11 +3214,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3170
3214
  var mode = FS_getMode(canRead, canWrite);
3171
3215
  var node = FS.create(path, mode);
3172
3216
  if (data) {
3173
- if (typeof data == 'string') {
3174
- var arr = new Array(data.length);
3175
- for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
3176
- data = arr;
3177
- }
3217
+ data = FS_fileDataToTypedArray(data);
3178
3218
  // make sure we can write to the file
3179
3219
  FS.chmod(node, mode | 146);
3180
3220
  var stream = FS.open(node, 577);
@@ -3209,7 +3249,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3209
3249
  } catch (e) {
3210
3250
  throw new FS.ErrnoError(29);
3211
3251
  }
3212
- if (result === undefined && bytesRead === 0) {
3252
+ if (result === undefined && !bytesRead) {
3213
3253
  throw new FS.ErrnoError(6);
3214
3254
  }
3215
3255
  if (result === null || result === undefined) break;
@@ -3240,7 +3280,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3240
3280
  forceLoadFile(obj) {
3241
3281
  if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
3242
3282
  if (globalThis.XMLHttpRequest) {
3243
- abort("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");
3283
+ abort('Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.');
3244
3284
  } else { // Command-line.
3245
3285
  try {
3246
3286
  obj.contents = readBinary(obj.url);
@@ -3271,11 +3311,11 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3271
3311
  var xhr = new XMLHttpRequest();
3272
3312
  xhr.open('HEAD', url, false);
3273
3313
  xhr.send(null);
3274
- if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr.status);
3275
- var datalength = Number(xhr.getResponseHeader("Content-length"));
3314
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort(`Couldn't load ${url}. Status: ${xhr.status}`);
3315
+ var datalength = Number(xhr.getResponseHeader('Content-length'));
3276
3316
  var header;
3277
- var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
3278
- var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip";
3317
+ var hasByteServing = (header = xhr.getResponseHeader('Accept-Ranges')) && header === 'bytes';
3318
+ var usesGzip = (header = xhr.getResponseHeader('Content-Encoding')) && header === 'gzip';
3279
3319
 
3280
3320
  var chunkSize = 1024*1024; // Chunk size in bytes
3281
3321
 
@@ -3283,13 +3323,13 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3283
3323
 
3284
3324
  // Function to get a range from the remote URL.
3285
3325
  var doXHR = (from, to) => {
3286
- if (from > to) abort("invalid range (" + from + ", " + to + ") or no bytes requested!");
3287
- if (to > datalength-1) abort("only " + datalength + " bytes available! programmer error!");
3326
+ if (from > to) abort(`invalid range (${from}, ${to}) or no bytes requested!`);
3327
+ if (to > datalength-1) abort(`only ${datalength} bytes available! programmer error!`);
3288
3328
 
3289
3329
  // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
3290
3330
  var xhr = new XMLHttpRequest();
3291
3331
  xhr.open('GET', url, false);
3292
- if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
3332
+ if (datalength !== chunkSize) xhr.setRequestHeader('Range', `bytes=${from}-${to}`);
3293
3333
 
3294
3334
  // Some hints to the browser that we want binary data.
3295
3335
  xhr.responseType = 'arraybuffer';
@@ -3298,11 +3338,11 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3298
3338
  }
3299
3339
 
3300
3340
  xhr.send(null);
3301
- if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr.status);
3341
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort(`Couldn't load ${url}. Status: ${xhr.status}`);
3302
3342
  if (xhr.response !== undefined) {
3303
3343
  return new Uint8Array(/** @type{Array<number>} */(xhr.response || []));
3304
3344
  }
3305
- return intArrayFromString(xhr.responseText || '', true);
3345
+ return intArrayFromString(xhr.responseText ?? '', true);
3306
3346
  };
3307
3347
  var lazyArray = this;
3308
3348
  lazyArray.setDataGetter((chunkNum) => {
@@ -3321,7 +3361,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3321
3361
  chunkSize = datalength = 1; // this will force getter(0)/doXHR do download the whole file
3322
3362
  datalength = this.getter(0).length;
3323
3363
  chunkSize = datalength;
3324
- out("LazyFiles on gzip forces download of the whole file when length is accessed");
3364
+ out('LazyFiles on gzip forces download of the whole file when length is accessed');
3325
3365
  }
3326
3366
 
3327
3367
  this._length = datalength;
@@ -3409,27 +3449,16 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3409
3449
  node.stream_ops = stream_ops;
3410
3450
  return node;
3411
3451
  },
3412
- absolutePath() {
3413
- abort('FS.absolutePath has been removed; use PATH_FS.resolve instead');
3414
- },
3415
- createFolder() {
3416
- abort('FS.createFolder has been removed; use FS.mkdir instead');
3417
- },
3418
- createLink() {
3419
- abort('FS.createLink has been removed; use FS.symlink instead');
3420
- },
3421
- joinPath() {
3422
- abort('FS.joinPath has been removed; use PATH.join instead');
3423
- },
3424
- mmapAlloc() {
3425
- abort('FS.mmapAlloc has been replaced by the top level function mmapAlloc');
3426
- },
3427
- standardizePath() {
3428
- abort('FS.standardizePath has been removed; use PATH.normalize instead');
3429
- },
3430
3452
  };
3431
3453
 
3454
+
3455
+
3456
+
3457
+
3458
+ /** not-@type {!BigInt64Array} */
3459
+ var HEAP64;
3432
3460
  var SYSCALLS = {
3461
+ currentUmask:18,
3433
3462
  calculateAt(dirfd, path, allowEmpty) {
3434
3463
  if (PATH.isAbs(path)) {
3435
3464
  return path;
@@ -3492,7 +3521,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3492
3521
  // MAP_PRIVATE calls need not to be synced back to underlying fs
3493
3522
  return 0;
3494
3523
  }
3495
- var buffer = HEAPU8.slice(addr, addr + len);
3524
+ var buffer = HEAPU8.subarray(addr, addr + len);
3496
3525
  FS.msync(stream, buffer, offset, len, flags);
3497
3526
  },
3498
3527
  getStreamFromFD(fd) {
@@ -3516,6 +3545,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3516
3545
  return -e.errno;
3517
3546
  }
3518
3547
  }
3548
+
3519
3549
 
3520
3550
  function ___syscall_chmod(path, mode) {
3521
3551
  try {
@@ -3528,6 +3558,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3528
3558
  return -e.errno;
3529
3559
  }
3530
3560
  }
3561
+
3531
3562
 
3532
3563
  function ___syscall_dup(fd) {
3533
3564
  try {
@@ -3539,23 +3570,29 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3539
3570
  return -e.errno;
3540
3571
  }
3541
3572
  }
3573
+
3542
3574
 
3543
3575
  function ___syscall_dup3(fd, newfd, flags) {
3544
3576
  try {
3545
3577
 
3578
+ if (fd === newfd) return -28;
3579
+ if (flags & ~524288) return -28;
3546
3580
  var old = SYSCALLS.getStreamFromFD(fd);
3547
- assert(!flags);
3548
- if (old.fd === newfd) return -28;
3549
3581
  // Check newfd is within range of valid open file descriptors.
3550
3582
  if (newfd < 0 || newfd >= FS.MAX_OPEN_FDS) return -8;
3551
3583
  var existing = FS.getStream(newfd);
3552
3584
  if (existing) FS.close(existing);
3553
- return FS.dupStream(old, newfd).fd;
3585
+ var stream = FS.dupStream(old, newfd);
3586
+ if (flags & 524288) {
3587
+ stream.flags |= 524288;
3588
+ }
3589
+ return stream.fd;
3554
3590
  } catch (e) {
3555
3591
  if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
3556
3592
  return -e.errno;
3557
3593
  }
3558
3594
  }
3595
+
3559
3596
 
3560
3597
  var syscallGetVarargI = () => {
3561
3598
  assert(SYSCALLS.varargs != undefined);
@@ -3567,6 +3604,9 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3567
3604
  var syscallGetVarargP = syscallGetVarargI;
3568
3605
 
3569
3606
 
3607
+
3608
+ /** @type {!Int16Array} */
3609
+ var HEAP16;
3570
3610
  function ___syscall_fcntl64(fd, cmd, varargs) {
3571
3611
  SYSCALLS.varargs = varargs;
3572
3612
  try {
@@ -3592,7 +3632,8 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3592
3632
  return stream.flags;
3593
3633
  case 4: {
3594
3634
  var arg = syscallGetVarargI();
3595
- stream.flags |= arg;
3635
+ var mask = 289792;
3636
+ stream.flags = (stream.flags & ~mask) | (arg & mask);
3596
3637
  return 0;
3597
3638
  }
3598
3639
  case 12: {
@@ -3616,6 +3657,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3616
3657
  return -e.errno;
3617
3658
  }
3618
3659
  }
3660
+
3619
3661
 
3620
3662
  function ___syscall_fstat64(fd, buf) {
3621
3663
  try {
@@ -3626,6 +3668,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3626
3668
  return -e.errno;
3627
3669
  }
3628
3670
  }
3671
+
3629
3672
 
3630
3673
  var INT53_MAX = 9007199254740992;
3631
3674
 
@@ -3637,7 +3680,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3637
3680
 
3638
3681
  try {
3639
3682
 
3640
- if (isNaN(length)) return -61;
3683
+ if (isNaN(length)) return -22;
3641
3684
  FS.ftruncate(fd, length);
3642
3685
  return 0;
3643
3686
  } catch (e) {
@@ -3648,14 +3691,15 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3648
3691
  }
3649
3692
 
3650
3693
 
3694
+
3651
3695
  var stringToUTF8 = (str, outPtr, maxBytesToWrite) => {
3652
- assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
3696
+ assert(typeof maxBytesToWrite == 'number', 'stringToUTF8 requires a third parameter that specifies the length of the output buffer');
3653
3697
  return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
3654
3698
  };
3655
3699
  function ___syscall_getcwd(buf, size) {
3656
3700
  try {
3657
3701
 
3658
- if (size === 0) return -28;
3702
+ if (!size) return -28;
3659
3703
  var cwd = FS.cwd();
3660
3704
  var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1;
3661
3705
  if (size < cwdLengthInBytes) return -68;
@@ -3666,8 +3710,12 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3666
3710
  return -e.errno;
3667
3711
  }
3668
3712
  }
3713
+
3669
3714
 
3670
3715
 
3716
+
3717
+
3718
+
3671
3719
  function ___syscall_getdents64(fd, dirp, count) {
3672
3720
  try {
3673
3721
 
@@ -3726,8 +3774,12 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3726
3774
  return -e.errno;
3727
3775
  }
3728
3776
  }
3777
+
3729
3778
 
3730
3779
 
3780
+
3781
+
3782
+
3731
3783
  function ___syscall_ioctl(fd, op, varargs) {
3732
3784
  SYSCALLS.varargs = varargs;
3733
3785
  try {
@@ -3823,6 +3875,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3823
3875
  return -e.errno;
3824
3876
  }
3825
3877
  }
3878
+
3826
3879
 
3827
3880
  function ___syscall_lstat64(path, buf) {
3828
3881
  try {
@@ -3834,12 +3887,14 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3834
3887
  return -e.errno;
3835
3888
  }
3836
3889
  }
3890
+
3837
3891
 
3838
3892
  function ___syscall_mkdirat(dirfd, path, mode) {
3839
3893
  try {
3840
3894
 
3841
3895
  path = SYSCALLS.getStr(path);
3842
3896
  path = SYSCALLS.calculateAt(dirfd, path);
3897
+ mode &= ~SYSCALLS.currentUmask;
3843
3898
  FS.mkdir(path, mode, 0);
3844
3899
  return 0;
3845
3900
  } catch (e) {
@@ -3847,6 +3902,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3847
3902
  return -e.errno;
3848
3903
  }
3849
3904
  }
3905
+
3850
3906
 
3851
3907
  function ___syscall_newfstatat(dirfd, path, buf, flags) {
3852
3908
  try {
@@ -3863,6 +3919,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3863
3919
  return -e.errno;
3864
3920
  }
3865
3921
  }
3922
+
3866
3923
 
3867
3924
 
3868
3925
  function ___syscall_openat(dirfd, path, flags, varargs) {
@@ -3872,13 +3929,18 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3872
3929
  path = SYSCALLS.getStr(path);
3873
3930
  path = SYSCALLS.calculateAt(dirfd, path);
3874
3931
  var mode = varargs ? syscallGetVarargI() : 0;
3932
+ if (flags & 64) {
3933
+ mode &= ~SYSCALLS.currentUmask;
3934
+ }
3875
3935
  return FS.open(path, flags, mode).fd;
3876
3936
  } catch (e) {
3877
3937
  if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
3878
3938
  return -e.errno;
3879
3939
  }
3880
3940
  }
3941
+
3881
3942
 
3943
+
3882
3944
  var PIPEFS = {
3883
3945
  BUCKET_BUFFER_SIZE:8192,
3884
3946
  mount(mount) {
@@ -3889,9 +3951,15 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3889
3951
  createPipe() {
3890
3952
  var pipe = {
3891
3953
  buckets: [],
3892
- // refcnt 2 because pipe has a read end and a write end. We need to be
3893
- // able to read from the read end after write end is closed.
3894
- refcnt : 2,
3954
+ // Open write ends. When it drops to 0 the reader sees EOF and poll must
3955
+ // report POLLHUP (Linux semantics). Buckets are freed once both counts
3956
+ // reach 0.
3957
+ writerCount: 1,
3958
+ writeClosed: false,
3959
+ // Open read ends. When it drops to 0 the writer sees POLLERR (a further
3960
+ // write would get EPIPE).
3961
+ readerCount: 1,
3962
+ readClosed: false,
3895
3963
  timestamp: new Date(),
3896
3964
  };
3897
3965
 
@@ -3908,6 +3976,10 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3908
3976
 
3909
3977
  rNode.pipe = pipe;
3910
3978
  wNode.pipe = pipe;
3979
+ // The read end's node carries the reader poll wait-queue (writes wake it);
3980
+ // the write end's node carries the writer wait-queue (read-end close wakes it).
3981
+ pipe.readNode = rNode;
3982
+ pipe.writeNode = wNode;
3911
3983
 
3912
3984
  var readableStream = FS.createStream({
3913
3985
  path: rName,
@@ -3952,24 +4024,50 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
3952
4024
  blocks: 0,
3953
4025
  };
3954
4026
  },
3955
- poll(stream, timeout, notifyCallback) {
4027
+ poll(stream) {
3956
4028
  var pipe = stream.node.pipe;
3957
4029
 
3958
4030
  if ((stream.flags & 2097155) === 1) {
3959
- return (256 | 4);
4031
+ // Linux keeps the write end writable (the write itself fails with
4032
+ // EPIPE) while also signalling POLLERR once every read end is closed.
4033
+ var mask = 256 | 4;
4034
+ if (pipe.readClosed) {
4035
+ mask |= 8;
4036
+ }
4037
+ return mask;
3960
4038
  }
4039
+ var mask = 0;
3961
4040
  for (var bucket of pipe.buckets) {
3962
4041
  if (bucket.offset - bucket.roffset > 0) {
3963
- return (64 | 1);
4042
+ mask = 64 | 1;
4043
+ break;
3964
4044
  }
3965
4045
  }
3966
-
3967
- return 0;
4046
+ // With every write end closed the read end is at EOF: readable (read
4047
+ // returns 0) and hung up.
4048
+ if (pipe.writeClosed) {
4049
+ mask |= 16 | 1;
4050
+ }
4051
+ return mask;
3968
4052
  },
3969
4053
  dup(stream) {
3970
- stream.node.pipe.refcnt++;
4054
+ var pipe = stream.node.pipe;
4055
+ if ((stream.flags & 2097155) === 1) {
4056
+ pipe.writerCount++;
4057
+ } else {
4058
+ pipe.readerCount++;
4059
+ }
3971
4060
  },
3972
- ioctl(stream, request, varargs) {
4061
+ ioctl(stream, request, argp) {
4062
+ if (request == 21531) {
4063
+ var pipe = stream.node.pipe;
4064
+ var currentLength = 0;
4065
+ for (var bucket of pipe.buckets) {
4066
+ currentLength += bucket.offset - bucket.roffset;
4067
+ }
4068
+ HEAP32[((argp)>>2)] = currentLength;
4069
+ return 0;
4070
+ }
3973
4071
  return 28;
3974
4072
  },
3975
4073
  fsync(stream) {
@@ -4062,6 +4160,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4062
4160
  if (freeBytesInCurrBuffer >= dataLen) {
4063
4161
  currBucket.buffer.set(data, currBucket.offset);
4064
4162
  currBucket.offset += dataLen;
4163
+ pipe.readNode.notifyListeners(64 | 1);
4065
4164
  return dataLen;
4066
4165
  } else if (freeBytesInCurrBuffer > 0) {
4067
4166
  currBucket.buffer.set(data.subarray(0, freeBytesInCurrBuffer), currBucket.offset);
@@ -4093,12 +4192,25 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4093
4192
  newBucket.buffer.set(data);
4094
4193
  }
4095
4194
 
4195
+ pipe.readNode.notifyListeners(64 | 1);
4096
4196
  return dataLen;
4097
4197
  },
4098
4198
  close(stream) {
4099
4199
  var pipe = stream.node.pipe;
4100
- pipe.refcnt--;
4101
- if (pipe.refcnt === 0) {
4200
+ // When the last write end closes, wake any poll/epoll waiter on the read
4201
+ // end with POLLHUP so a reader blocked on the writer dropping unblocks.
4202
+ if ((stream.flags & 2097155) === 1) {
4203
+ if (!--pipe.writerCount) {
4204
+ pipe.writeClosed = true;
4205
+ pipe.readNode.notifyListeners(16 | 64 | 1);
4206
+ }
4207
+ } else if (!--pipe.readerCount) {
4208
+ // Mirror: when the last read end closes, wake any poll/epoll waiter on
4209
+ // the write end with POLLERR (a further write would get EPIPE).
4210
+ pipe.readClosed = true;
4211
+ pipe.writeNode.notifyListeners(8 | 256 | 4);
4212
+ }
4213
+ if (!pipe.readerCount && !pipe.writerCount) {
4102
4214
  pipe.buckets = null;
4103
4215
  }
4104
4216
  },
@@ -4110,15 +4222,25 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4110
4222
  return 'pipe[' + (PIPEFS.nextname.current++) + ']';
4111
4223
  },
4112
4224
  };
4113
- function ___syscall_pipe(fdPtr) {
4225
+
4226
+ function ___syscall_pipe2(fdPtr, flags) {
4114
4227
  try {
4115
4228
 
4116
4229
  if (fdPtr == 0) {
4117
4230
  throw new FS.ErrnoError(21);
4118
4231
  }
4232
+ var validFlags = 524288 | 2048;
4233
+ if (flags & ~validFlags) {
4234
+ throw new FS.ErrnoError(138);
4235
+ }
4119
4236
 
4120
4237
  var res = PIPEFS.createPipe();
4121
4238
 
4239
+ if (flags & 2048) {
4240
+ FS.getStream(res.readable_fd).flags |= 2048;
4241
+ FS.getStream(res.writable_fd).flags |= 2048;
4242
+ }
4243
+
4122
4244
  HEAP32[((fdPtr)>>2)] = res.readable_fd;
4123
4245
  HEAP32[(((fdPtr)+(4))>>2)] = res.writable_fd;
4124
4246
 
@@ -4128,30 +4250,35 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4128
4250
  return -e.errno;
4129
4251
  }
4130
4252
  }
4253
+
4131
4254
 
4132
- function ___syscall_poll(fds, nfds, timeout) {
4133
- try {
4255
+ var pollOne = (fd, events) => {
4256
+ var stream = FS.getStream(fd);
4257
+ if (!stream) return 32;
4258
+ // Streams without a poll handler (regular files, incl. NODERAWFS/NODEFS
4259
+ // which leave stream_ops unset) are treated as always readable+writable.
4260
+ var flags = stream.stream_ops?.poll
4261
+ ? stream.stream_ops.poll(stream)
4262
+ : 5;
4263
+ return flags & (events | 8 | 16 | 32);
4264
+ };
4134
4265
 
4135
4266
 
4267
+ var doPollSync = (fds, nfds) => {
4136
4268
  var count = 0;
4137
- for (var i = 0; i < nfds; i++) {
4138
- var pollfd = fds + 8 * i;
4139
- var fd = HEAP32[((pollfd)>>2)];
4140
- var events = HEAP16[(((pollfd)+(4))>>1)];
4141
- var flags = 32;
4142
- var stream = FS.getStream(fd);
4143
- if (stream) {
4144
- if (stream.stream_ops.poll) {
4145
- flags = stream.stream_ops.poll(stream, -1);
4146
- } else {
4147
- flags = 5;
4148
- }
4149
- }
4150
- flags &= events | 8 | 16;
4151
- if (flags) count++;
4152
- HEAP16[(((pollfd)+(6))>>1)] = flags;
4269
+ for (var i = 0, pollfd = fds; i < nfds; i++, pollfd += 8) {
4270
+ var revents = pollOne(
4271
+ HEAP32[((pollfd)>>2)],
4272
+ HEAP16[(((pollfd)+(4))>>1)]);
4273
+ if (revents) count++;
4274
+ HEAP16[(((pollfd)+(6))>>1)] = revents;
4153
4275
  }
4276
+ return count;
4277
+ };
4278
+ function ___syscall_poll(fds, nfds, timeout) {
4279
+ try {
4154
4280
 
4281
+ var count = doPollSync(fds, nfds);
4155
4282
  if (!count && timeout != 0) warnOnce('non-zero poll() timeout not supported: ' + timeout)
4156
4283
  return count;
4157
4284
  } catch (e) {
@@ -4159,7 +4286,20 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4159
4286
  return -e.errno;
4160
4287
  }
4161
4288
  }
4289
+
4162
4290
 
4291
+ function ___syscall_poll_nonblocking(fds, nfds) {
4292
+ try {
4293
+
4294
+ return doPollSync(fds, nfds);
4295
+ } catch (e) {
4296
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
4297
+ return -e.errno;
4298
+ }
4299
+ }
4300
+
4301
+
4302
+
4163
4303
 
4164
4304
 
4165
4305
  function ___syscall_readlinkat(dirfd, path, buf, bufsize) {
@@ -4182,6 +4322,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4182
4322
  return -e.errno;
4183
4323
  }
4184
4324
  }
4325
+
4185
4326
 
4186
4327
  function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) {
4187
4328
  try {
@@ -4197,6 +4338,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4197
4338
  return -e.errno;
4198
4339
  }
4199
4340
  }
4341
+
4200
4342
 
4201
4343
  function ___syscall_rmdir(path) {
4202
4344
  try {
@@ -4209,6 +4351,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4209
4351
  return -e.errno;
4210
4352
  }
4211
4353
  }
4354
+
4212
4355
 
4213
4356
  function ___syscall_stat64(path, buf) {
4214
4357
  try {
@@ -4220,6 +4363,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4220
4363
  return -e.errno;
4221
4364
  }
4222
4365
  }
4366
+
4223
4367
 
4224
4368
  function ___syscall_symlinkat(target, dirfd, linkpath) {
4225
4369
  try {
@@ -4234,6 +4378,20 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4234
4378
  return -e.errno;
4235
4379
  }
4236
4380
  }
4381
+
4382
+
4383
+ function ___syscall_umask(mask) {
4384
+ try {
4385
+
4386
+ var old = SYSCALLS.currentUmask;
4387
+ SYSCALLS.currentUmask = mask;
4388
+ return old;
4389
+ } catch (e) {
4390
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
4391
+ return -e.errno;
4392
+ }
4393
+ }
4394
+
4237
4395
 
4238
4396
  function ___syscall_unlinkat(dirfd, path, flags) {
4239
4397
  try {
@@ -4253,6 +4411,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4253
4411
  return -e.errno;
4254
4412
  }
4255
4413
  }
4414
+
4256
4415
 
4257
4416
  var __abort_js = () =>
4258
4417
  abort('native code called abort()');
@@ -4264,7 +4423,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4264
4423
  };
4265
4424
 
4266
4425
  var __emscripten_throw_longjmp = () => {
4267
- throw Infinity;
4426
+ throw new EmscriptenSjLj;
4268
4427
  };
4269
4428
 
4270
4429
  var isLeapYear = (year) => year%4 === 0 && (year%100 !== 0 || year%400 === 0);
@@ -4280,11 +4439,15 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4280
4439
  return yday;
4281
4440
  };
4282
4441
 
4442
+
4283
4443
  function __localtime_js(time, tmPtr) {
4284
4444
  time = bigintToI53Checked(time);
4285
4445
 
4286
4446
 
4287
4447
  var date = new Date(time*1000);
4448
+ if (isNaN(date.getTime())) {
4449
+ return 1;
4450
+ }
4288
4451
  HEAP32[((tmPtr)>>2)] = date.getSeconds();
4289
4452
  HEAP32[(((tmPtr)+(4))>>2)] = date.getMinutes();
4290
4453
  HEAP32[(((tmPtr)+(8))>>2)] = date.getHours();
@@ -4303,10 +4466,12 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4303
4466
  var winterOffset = start.getTimezoneOffset();
4304
4467
  var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset))|0;
4305
4468
  HEAP32[(((tmPtr)+(32))>>2)] = dst;
4469
+ return 0;
4306
4470
  ;
4307
4471
  }
4308
4472
 
4309
4473
 
4474
+
4310
4475
  var __mktime_js = function(tmPtr) {
4311
4476
 
4312
4477
  var ret = (() => {
@@ -4317,6 +4482,9 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4317
4482
  HEAP32[(((tmPtr)+(4))>>2)],
4318
4483
  HEAP32[((tmPtr)>>2)],
4319
4484
  0);
4485
+ if (isNaN(date.getTime())) {
4486
+ return -1;
4487
+ }
4320
4488
 
4321
4489
  // There's an ambiguous hour when the time goes back; the tm_isdst field is
4322
4490
  // used to disambiguate it. Date() basically guesses, so we fix it up if it
@@ -4329,14 +4497,18 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4329
4497
  var dstOffset = Math.min(winterOffset, summerOffset); // DST is in December in South
4330
4498
  if (dst < 0) {
4331
4499
  // Attention: some regions don't have DST at all.
4332
- HEAP32[(((tmPtr)+(32))>>2)] = Number(summerOffset != winterOffset && dstOffset == guessedOffset);
4500
+ dst = Number(summerOffset != winterOffset && dstOffset == guessedOffset);
4333
4501
  } else if ((dst > 0) != (dstOffset == guessedOffset)) {
4334
4502
  var nonDstOffset = Math.max(winterOffset, summerOffset);
4335
4503
  var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
4336
4504
  // Don't try setMinutes(date.getMinutes() + ...) -- it's messed up.
4337
4505
  date.setTime(date.getTime() + (trueOffset - guessedOffset)*60000);
4506
+ if (isNaN(date.getTime())) {
4507
+ return -1;
4508
+ }
4338
4509
  }
4339
4510
 
4511
+ HEAP32[(((tmPtr)+(32))>>2)] = dst;
4340
4512
  HEAP32[(((tmPtr)+(24))>>2)] = date.getDay();
4341
4513
  var yday = ydayFromDate(date)|0;
4342
4514
  HEAP32[(((tmPtr)+(28))>>2)] = yday;
@@ -4348,12 +4520,8 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4348
4520
  HEAP32[(((tmPtr)+(16))>>2)] = date.getMonth();
4349
4521
  HEAP32[(((tmPtr)+(20))>>2)] = date.getYear();
4350
4522
 
4351
- var timeMs = date.getTime();
4352
- if (isNaN(timeMs)) {
4353
- return -1;
4354
- }
4355
- // Return time in microseconds
4356
- return timeMs / 1000;
4523
+ // Return time in seconds
4524
+ return date.getTime() / 1000;
4357
4525
  })();
4358
4526
  return BigInt(ret);
4359
4527
  };
@@ -4377,6 +4545,8 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4377
4545
  }
4378
4546
 
4379
4547
 
4548
+
4549
+
4380
4550
  var __tzset_js = (timezone, daylight, std_name, dst_name) => {
4381
4551
  // TODO: Use (malleable) environment variables instead of system settings.
4382
4552
  var currentYear = new Date().getFullYear();
@@ -4405,11 +4575,11 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4405
4575
  var extractZone = (timezoneOffset) => {
4406
4576
  // Why inverse sign?
4407
4577
  // Read here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
4408
- var sign = timezoneOffset >= 0 ? "-" : "+";
4578
+ var sign = timezoneOffset >= 0 ? '-' : '+';
4409
4579
 
4410
4580
  var absOffset = Math.abs(timezoneOffset)
4411
- var hours = String(Math.floor(absOffset / 60)).padStart(2, "0");
4412
- var minutes = String(absOffset % 60).padStart(2, "0");
4581
+ var hours = String(Math.floor(absOffset / 60)).padStart(2, '0');
4582
+ var minutes = String(absOffset % 60).padStart(2, '0');
4413
4583
 
4414
4584
  return `UTC${sign}${hours}${minutes}`;
4415
4585
  }
@@ -4437,6 +4607,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4437
4607
 
4438
4608
  var checkWasiClock = (clock_id) => clock_id >= 0 && clock_id <= 3;
4439
4609
 
4610
+
4440
4611
  function _clock_time_get(clk_id, ignored_precision, ptime) {
4441
4612
  ignored_precision = bigintToI53Checked(ignored_precision);
4442
4613
 
@@ -4461,6 +4632,13 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4461
4632
  }
4462
4633
 
4463
4634
  var readEmAsmArgsArray = [];
4635
+
4636
+
4637
+
4638
+
4639
+ /** @type {!Float64Array} */
4640
+ var HEAPF64;
4641
+
4464
4642
  var readEmAsmArgs = (sigPtr, buf) => {
4465
4643
  // Nobody should have mutated _readEmAsmArgsArray underneath us to be something else than an array.
4466
4644
  assert(Array.isArray(readEmAsmArgsArray));
@@ -4526,9 +4704,10 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4526
4704
  } catch(e) {
4527
4705
  err(`growMemory: Attempted to grow heap from ${oldHeapSize} bytes to ${size} bytes, but got error: ${e}`);
4528
4706
  }
4529
- // implicit 0 return to save code size (caller will cast "undefined" into 0
4707
+ // implicit 0 return to save code size (caller will cast 'undefined' into 0
4530
4708
  // anyhow)
4531
4709
  };
4710
+
4532
4711
  var _emscripten_resize_heap = (requestedSize) => {
4533
4712
  var oldSize = HEAPU8.length;
4534
4713
  // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
@@ -4585,11 +4764,10 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4585
4764
  var ENV = {
4586
4765
  };
4587
4766
 
4588
- var getExecutableName = () => thisProgram || './this.program';
4767
+ var getExecutableName = () => thisProgram;
4589
4768
  var getEnvStrings = () => {
4590
4769
  if (!getEnvStrings.strings) {
4591
4770
  // Default values.
4592
- // Browser language detection #8751
4593
4771
  var lang = (globalThis.navigator?.language ?? 'C').replace('-', '_') + '.UTF-8';
4594
4772
  var env = {
4595
4773
  'USER': 'web_user',
@@ -4617,6 +4795,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4617
4795
  return getEnvStrings.strings;
4618
4796
  };
4619
4797
 
4798
+
4620
4799
  var _environ_get = (__environ, environ_buf) => {
4621
4800
  var bufSize = 0;
4622
4801
  var envp = 0;
@@ -4630,6 +4809,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4630
4809
  };
4631
4810
 
4632
4811
 
4812
+
4633
4813
  var _environ_sizes_get = (penviron_count, penviron_buf_size) => {
4634
4814
  var strings = getEnvStrings();
4635
4815
  HEAPU32[((penviron_count)>>2)] = strings.length;
@@ -4662,7 +4842,6 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4662
4842
  // if exit() was called explicitly, warn the user if the runtime isn't actually being shut down
4663
4843
  if (keepRuntimeAlive() && !implicit) {
4664
4844
  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)`;
4665
- readyPromiseReject?.(msg);
4666
4845
  err(msg);
4667
4846
  }
4668
4847
 
@@ -4681,7 +4860,11 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4681
4860
  return e.errno;
4682
4861
  }
4683
4862
  }
4863
+
4684
4864
 
4865
+
4866
+
4867
+
4685
4868
  function _fd_fdstat_get(fd, pbuf) {
4686
4869
  try {
4687
4870
 
@@ -4707,7 +4890,9 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4707
4890
  return e.errno;
4708
4891
  }
4709
4892
  }
4893
+
4710
4894
 
4895
+
4711
4896
  /** @param {number=} offset */
4712
4897
  var doReadv = (stream, iov, iovcnt, offset) => {
4713
4898
  var ret = 0;
@@ -4715,7 +4900,18 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4715
4900
  var ptr = HEAPU32[((iov)>>2)];
4716
4901
  var len = HEAPU32[(((iov)+(4))>>2)];
4717
4902
  iov += 8;
4718
- var curr = FS.read(stream, HEAP8, ptr, len, offset);
4903
+ try {
4904
+ var curr = FS.read(stream, HEAP8, ptr, len, offset);
4905
+ } catch (e) {
4906
+ // On a non-blocking stream a subsequent read may would-block after we
4907
+ // already gathered data. POSIX readv is a single gather-read: return
4908
+ // what we have rather than failing the whole call.
4909
+ if (ret > 0 && e instanceof FS.ErrnoError &&
4910
+ (e.errno == 6 || e.errno == 6)) {
4911
+ break;
4912
+ }
4913
+ throw e;
4914
+ }
4719
4915
  if (curr < 0) return -1;
4720
4916
  ret += curr;
4721
4917
  if (curr < len) break; // nothing more to read
@@ -4727,13 +4923,14 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4727
4923
  };
4728
4924
 
4729
4925
 
4926
+
4730
4927
  function _fd_pread(fd, iov, iovcnt, offset, pnum) {
4731
4928
  offset = bigintToI53Checked(offset);
4732
4929
 
4733
4930
 
4734
4931
  try {
4735
4932
 
4736
- if (isNaN(offset)) return 61;
4933
+ if (isNaN(offset)) return 22;
4737
4934
  var stream = SYSCALLS.getStreamFromFD(fd)
4738
4935
  var num = doReadv(stream, iov, iovcnt, offset);
4739
4936
  HEAPU32[((pnum)>>2)] = num;
@@ -4745,35 +4942,42 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4745
4942
  ;
4746
4943
  }
4747
4944
 
4945
+
4946
+
4748
4947
  /** @param {number=} offset */
4749
4948
  var doWritev = (stream, iov, iovcnt, offset) => {
4750
- var ret = 0;
4751
- for (var i = 0; i < iovcnt; i++) {
4949
+ // Gather all iovecs into one contiguous buffer and issue a single
4950
+ // FS.write, matching POSIX writev's single gather-write semantics (as
4951
+ // __syscall_sendmsg already does). Per-iovec writes fragment a stream
4952
+ // socket send into multiple segments, breaking stream byte semantics.
4953
+ if (iovcnt == 1) {
4954
+ // Single iovec: write directly from HEAP8, no gather buffer needed.
4955
+ return FS.write(stream, HEAP8, HEAPU32[((iov)>>2)], HEAPU32[(((iov)+(4))>>2)], offset);
4956
+ }
4957
+ var total = 0;
4958
+ for (var i = 0, p = iov; i < iovcnt; i++, p += 8) {
4959
+ total += HEAPU32[(((p)+(4))>>2)];
4960
+ }
4961
+ var view = new Uint8Array(total);
4962
+ var voff = 0;
4963
+ for (var i = 0; i < iovcnt; i++, iov += 8) {
4752
4964
  var ptr = HEAPU32[((iov)>>2)];
4753
4965
  var len = HEAPU32[(((iov)+(4))>>2)];
4754
- iov += 8;
4755
- var curr = FS.write(stream, HEAP8, ptr, len, offset);
4756
- if (curr < 0) return -1;
4757
- ret += curr;
4758
- if (curr < len) {
4759
- // No more space to write.
4760
- break;
4761
- }
4762
- if (typeof offset != 'undefined') {
4763
- offset += curr;
4764
- }
4966
+ view.set(HEAPU8.subarray(ptr, ptr + len), voff);
4967
+ voff += len;
4765
4968
  }
4766
- return ret;
4969
+ return FS.write(stream, view, 0, total, offset);
4767
4970
  };
4768
4971
 
4769
4972
 
4973
+
4770
4974
  function _fd_pwrite(fd, iov, iovcnt, offset, pnum) {
4771
4975
  offset = bigintToI53Checked(offset);
4772
4976
 
4773
4977
 
4774
4978
  try {
4775
4979
 
4776
- if (isNaN(offset)) return 61;
4980
+ if (isNaN(offset)) return 22;
4777
4981
  var stream = SYSCALLS.getStreamFromFD(fd)
4778
4982
  var num = doWritev(stream, iov, iovcnt, offset);
4779
4983
  HEAPU32[((pnum)>>2)] = num;
@@ -4786,6 +4990,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4786
4990
  }
4787
4991
 
4788
4992
 
4993
+
4789
4994
  function _fd_read(fd, iov, iovcnt, pnum) {
4790
4995
  try {
4791
4996
 
@@ -4798,19 +5003,21 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4798
5003
  return e.errno;
4799
5004
  }
4800
5005
  }
5006
+
4801
5007
 
4802
5008
 
5009
+
4803
5010
  function _fd_seek(fd, offset, whence, newOffset) {
4804
5011
  offset = bigintToI53Checked(offset);
4805
5012
 
4806
5013
 
4807
5014
  try {
4808
5015
 
4809
- if (isNaN(offset)) return 61;
5016
+ if (isNaN(offset)) return 22;
4810
5017
  var stream = SYSCALLS.getStreamFromFD(fd);
4811
5018
  FS.llseek(stream, offset, whence);
4812
5019
  HEAP64[((newOffset)>>3)] = BigInt(stream.position);
4813
- if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state
5020
+ if (stream.getdents && !offset && whence === 0) stream.getdents = null; // reset readdir state
4814
5021
  return 0;
4815
5022
  } catch (e) {
4816
5023
  if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
@@ -4830,8 +5037,10 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4830
5037
  return e.errno;
4831
5038
  }
4832
5039
  }
5040
+
4833
5041
 
4834
5042
 
5043
+
4835
5044
  function _fd_write(fd, iov, iovcnt, pnum) {
4836
5045
  try {
4837
5046
 
@@ -4844,12 +5053,81 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4844
5053
  return e.errno;
4845
5054
  }
4846
5055
  }
5056
+
5057
+
5058
+
5059
+
5060
+
5061
+
5062
+
5063
+
5064
+
5065
+
5066
+
5067
+
5068
+
5069
+
5070
+
5071
+
5072
+
5073
+
5074
+
5075
+
5076
+
5077
+
5078
+
5079
+
5080
+
5081
+
5082
+
5083
+
5084
+
5085
+
5086
+
5087
+
5088
+
5089
+
5090
+
5091
+
5092
+
5093
+
5094
+
5095
+
5096
+
5097
+
5098
+
5099
+ /** @type {!Uint16Array} */
5100
+ var HEAPU16;
5101
+
5102
+
5103
+
5104
+ /** @type {!Float32Array} */
5105
+ var HEAPF32;
5106
+
5107
+
5108
+
5109
+ /** not-@type {!BigUint64Array} */
5110
+ var HEAPU64;
5111
+
5112
+
5113
+
5114
+
5115
+
5116
+
5117
+
5118
+
5119
+
5120
+
5121
+
5122
+
5123
+
5124
+
4847
5125
 
4848
5126
 
4849
5127
 
4850
5128
  var getCFunc = (ident) => {
4851
5129
  var func = Module['_' + ident]; // closure exported function
4852
- assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported');
5130
+ assert(func, `Cannot call unknown function ${ident}, make sure it is exported`);
4853
5131
  return func;
4854
5132
  };
4855
5133
 
@@ -4906,12 +5184,12 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4906
5184
  var func = getCFunc(ident);
4907
5185
  var cArgs = [];
4908
5186
  var stack = 0;
4909
- assert(returnType !== 'array', 'Return type should not be "array".');
5187
+ assert(returnType !== 'array', 'return type should not be "array"');
4910
5188
  if (args) {
4911
5189
  for (var i = 0; i < args.length; i++) {
4912
5190
  var converter = toC[argTypes[i]];
4913
5191
  if (converter) {
4914
- if (stack === 0) stack = stackSave();
5192
+ if (!stack) stack = stackSave();
4915
5193
  cArgs[i] = converter(args[i]);
4916
5194
  } else {
4917
5195
  cArgs[i] = args[i];
@@ -4920,7 +5198,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4920
5198
  }
4921
5199
  var ret = func(...cArgs);
4922
5200
  function onDone(ret) {
4923
- if (stack !== 0) stackRestore(stack);
5201
+ if (stack) stackRestore(stack);
4924
5202
  return convertReturnValue(ret);
4925
5203
  }
4926
5204
 
@@ -4943,6 +5221,7 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4943
5221
 
4944
5222
 
4945
5223
 
5224
+
4946
5225
  FS.createPreloadedFile = FS_createPreloadedFile;
4947
5226
  FS.preloadFile = FS_preloadFile;
4948
5227
  FS.staticInit();;
@@ -4956,15 +5235,14 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4956
5235
 
4957
5236
  // Begin ATMODULES hooks
4958
5237
  if (Module['noExitRuntime']) noExitRuntime = Module['noExitRuntime'];
4959
- if (Module['preloadPlugins']) preloadPlugins = Module['preloadPlugins'];
5238
+
4960
5239
  if (Module['print']) out = Module['print'];
4961
5240
  if (Module['printErr']) err = Module['printErr'];
4962
- if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
4963
5241
  // End ATMODULES hooks
4964
5242
 
4965
5243
  checkIncomingModuleAPI();
4966
5244
 
4967
- if (Module['arguments']) arguments_ = Module['arguments'];
5245
+ if (Module['arguments']) programArgs = Module['arguments'];
4968
5246
  if (Module['thisProgram']) thisProgram = Module['thisProgram'];
4969
5247
 
4970
5248
  // Assertions on removed incoming Module JS APIs.
@@ -4983,10 +5261,13 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
4983
5261
  assert(typeof Module['wasmMemory'] == 'undefined', 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally');
4984
5262
  assert(typeof Module['INITIAL_MEMORY'] == 'undefined', 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically');
4985
5263
 
4986
- if (Module['preInit']) {
4987
- if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
4988
- while (Module['preInit'].length > 0) {
4989
- Module['preInit'].shift()();
5264
+ var preInit = Module['preInit'];
5265
+ if (preInit) {
5266
+ if (typeof preInit == 'function') Module['preInit'] = preInit = [preInit];
5267
+ // Written as a loop so that preInit functions that themselves add more
5268
+ // preInit functions. Is this actually needed?
5269
+ while (preInit.length > 0) {
5270
+ preInit.shift()();
4990
5271
  }
4991
5272
  }
4992
5273
  consumedModuleProp('preInit');
@@ -5046,6 +5327,8 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5046
5327
  'getFunctionAddress',
5047
5328
  'addFunction',
5048
5329
  'removeFunction',
5330
+ 'setValue',
5331
+ 'getValue',
5049
5332
  'intArrayToString',
5050
5333
  'AsciiToString',
5051
5334
  'stringToAscii',
@@ -5074,12 +5357,14 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5074
5357
  'registerOrientationChangeEventCallback',
5075
5358
  'fillFullscreenChangeEventData',
5076
5359
  'registerFullscreenChangeEventCallback',
5360
+ 'callCanvasResizedCallback',
5077
5361
  'JSEvents_requestFullscreen',
5078
5362
  'JSEvents_resizeCanvasForFullscreen',
5079
5363
  'registerRestoreOldStyle',
5080
5364
  'hideEverythingExceptGivenElement',
5081
5365
  'restoreHiddenElements',
5082
5366
  'setLetterbox',
5367
+ 'currentFullscreenStrategy',
5083
5368
  'softFullscreenResizeWebGLRenderTarget',
5084
5369
  'doRequestFullscreen',
5085
5370
  'fillPointerlockChangeEventData',
@@ -5109,10 +5394,9 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5109
5394
  'registerPreMainLoop',
5110
5395
  'getPromise',
5111
5396
  'makePromise',
5397
+ 'addPromise',
5112
5398
  'idsToPromises',
5113
5399
  'makePromiseCallback',
5114
- 'ExceptionInfo',
5115
- 'findMatchingCatch',
5116
5400
  'Browser_asyncPrepareDataCounter',
5117
5401
  'arraySum',
5118
5402
  'addDays',
@@ -5134,6 +5418,7 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5134
5418
  'colorChannelsInGlTextureFormat',
5135
5419
  'emscriptenWebGLGetTexPixelData',
5136
5420
  'emscriptenWebGLGetUniform',
5421
+ 'webglGetProgramUniformLocation',
5137
5422
  'webglGetUniformLocation',
5138
5423
  'webglPrepareUniformLocationsBeforeFirstUse',
5139
5424
  'webglGetLeftBracePos',
@@ -5142,14 +5427,10 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5142
5427
  'writeGLArray',
5143
5428
  'registerWebGlEventCallback',
5144
5429
  'runAndAbortIfError',
5145
- 'ALLOC_NORMAL',
5146
- 'ALLOC_STACK',
5147
- 'allocate',
5148
5430
  'writeStringToMemory',
5149
5431
  'writeAsciiToMemory',
5150
5432
  'allocateUTF8',
5151
5433
  'allocateUTF8OnStack',
5152
- 'demangle',
5153
5434
  'stackTrace',
5154
5435
  'getNativeTypeSize',
5155
5436
  ];
@@ -5162,20 +5443,20 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5162
5443
  'callMain',
5163
5444
  'abort',
5164
5445
  'wasmExports',
5165
- 'HEAPF32',
5166
- 'HEAPF64',
5446
+ 'writeStackCookie',
5447
+ 'checkStackCookie',
5448
+ 'INT53_MAX',
5449
+ 'INT53_MIN',
5450
+ 'bigintToI53Checked',
5167
5451
  'HEAP8',
5168
5452
  'HEAP16',
5169
5453
  'HEAPU16',
5170
5454
  'HEAP32',
5171
5455
  'HEAPU32',
5456
+ 'HEAPF32',
5457
+ 'HEAPF64',
5172
5458
  'HEAP64',
5173
5459
  'HEAPU64',
5174
- 'writeStackCookie',
5175
- 'checkStackCookie',
5176
- 'INT53_MAX',
5177
- 'INT53_MIN',
5178
- 'bigintToI53Checked',
5179
5460
  'stackSave',
5180
5461
  'stackRestore',
5181
5462
  'stackAlloc',
@@ -5210,8 +5491,6 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5210
5491
  'addOnPostRun',
5211
5492
  'freeTableIndexes',
5212
5493
  'functionsInTableMap',
5213
- 'setValue',
5214
- 'getValue',
5215
5494
  'PATH',
5216
5495
  'PATH_FS',
5217
5496
  'UTF8Decoder',
@@ -5224,7 +5503,6 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5224
5503
  'JSEvents',
5225
5504
  'specialHTMLTargets',
5226
5505
  'findCanvasEventTarget',
5227
- 'currentFullscreenStrategy',
5228
5506
  'restoreOldWindowedStyle',
5229
5507
  'UNWIND_CACHE',
5230
5508
  'ExitStatus',
@@ -5238,12 +5516,8 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5238
5516
  'emClearImmediate_deps',
5239
5517
  'emClearImmediate',
5240
5518
  'promiseMap',
5241
- 'uncaughtExceptionCount',
5242
- 'exceptionLast',
5243
- 'exceptionCaught',
5244
5519
  'Browser',
5245
5520
  'requestFullscreen',
5246
- 'requestFullScreen',
5247
5521
  'setCanvasSize',
5248
5522
  'getUserMedia',
5249
5523
  'createContext',
@@ -5261,6 +5535,7 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5261
5535
  'FS_preloadFile',
5262
5536
  'FS_modeStringToFlags',
5263
5537
  'FS_getMode',
5538
+ 'FS_fileDataToTypedArray',
5264
5539
  'FS_stdin_getChar_buffer',
5265
5540
  'FS_stdin_getChar',
5266
5541
  'FS_unlink',
@@ -5328,6 +5603,7 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5328
5603
  'FS_mkdir',
5329
5604
  'FS_mkdev',
5330
5605
  'FS_symlink',
5606
+ 'FS_link',
5331
5607
  'FS_rename',
5332
5608
  'FS_rmdir',
5333
5609
  'FS_readdir',
@@ -5372,12 +5648,6 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5372
5648
  'FS_createDataFile',
5373
5649
  'FS_forceLoadFile',
5374
5650
  'FS_createLazyFile',
5375
- 'FS_absolutePath',
5376
- 'FS_createFolder',
5377
- 'FS_createLink',
5378
- 'FS_joinPath',
5379
- 'FS_mmapAlloc',
5380
- 'FS_standardizePath',
5381
5651
  'MEMFS',
5382
5652
  'TTY',
5383
5653
  'PIPEFS',
@@ -5409,22 +5679,46 @@ function checkIncomingModuleAPI() {
5409
5679
  ignoredModuleProp('fetchSettings');
5410
5680
  ignoredModuleProp('logReadFiles');
5411
5681
  ignoredModuleProp('loadSplitModule');
5682
+ ignoredModuleProp('onMalloc');
5683
+ ignoredModuleProp('onRealloc');
5684
+ ignoredModuleProp('onFree');
5685
+ ignoredModuleProp('onSbrkGrow');
5686
+ ignoredModuleProp('onCOSCacheHit');
5687
+ ignoredModuleProp('onCOSCacheMiss');
5688
+ ignoredModuleProp('onCOSStore');
5689
+ ignoredModuleProp('GL_MAX_TEXTURE_IMAGE_UNITS');
5690
+ ignoredModuleProp('SDL_canPlayWithWebAudio');
5691
+ ignoredModuleProp('SDL_numSimultaneouslyQueuedBuffers');
5692
+ ignoredModuleProp('freePreloadedMediaOnUse');
5693
+ ignoredModuleProp('preinitializedWebGLContext');
5694
+ ignoredModuleProp('keyboardListeningElement');
5695
+ ignoredModuleProp('doNotCaptureKeyboard');
5696
+ ignoredModuleProp('extraStackTrace');
5697
+ ignoredModuleProp('preloadPlugins');
5698
+ ignoredModuleProp('preMainLoop');
5699
+ ignoredModuleProp('postMainLoop');
5700
+ ignoredModuleProp('forcedAspectRatio');
5701
+ ignoredModuleProp('mainScriptUrlOrBlob');
5702
+ ignoredModuleProp('onFullScreen');
5703
+ ignoredModuleProp('INITIAL_MEMORY');
5704
+ ignoredModuleProp('wasmMemory');
5705
+ ignoredModuleProp('wasmBinary');
5412
5706
  }
5413
5707
  var ASM_CONSTS = {
5414
- 2652134: ($0) => { globalThis.picorubyRefs[$0] = null; },
5415
- 2652174: ($0) => { globalThis.picorubyRefs[$0] = true; },
5416
- 2652214: ($0) => { globalThis.picorubyRefs[$0] = false; },
5417
- 2652255: ($0, $1) => { globalThis.picorubyRefs[$0] = $1; },
5418
- 2652293: ($0, $1) => { globalThis.picorubyRefs[$0] = $1; },
5419
- 2652331: ($0, $1, $2) => { const str = UTF8ToString($1, $2); globalThis.picorubyRefs[$0] = str; },
5420
- 2652404: ($0, $1) => { const arr = globalThis.picorubyRefs[$0]; const elem = globalThis.picorubyRefs[$1]; arr.push(elem); delete globalThis.picorubyRefs[$1]; },
5421
- 2652543: ($0, $1, $2) => { const obj = globalThis.picorubyRefs[$0]; const key = UTF8ToString($1); const val = globalThis.picorubyRefs[$2]; obj[key] = val; delete globalThis.picorubyRefs[$2]; }
5708
+ 2823398: ($0) => { globalThis.picorubyRefs[$0] = null; },
5709
+ 2823438: ($0) => { globalThis.picorubyRefs[$0] = true; },
5710
+ 2823478: ($0) => { globalThis.picorubyRefs[$0] = false; },
5711
+ 2823519: ($0, $1) => { globalThis.picorubyRefs[$0] = $1; },
5712
+ 2823557: ($0, $1) => { globalThis.picorubyRefs[$0] = $1; },
5713
+ 2823595: ($0, $1, $2) => { const str = UTF8ToString($1, $2); globalThis.picorubyRefs[$0] = str; },
5714
+ 2823668: ($0, $1) => { const arr = globalThis.picorubyRefs[$0]; const elem = globalThis.picorubyRefs[$1]; arr.push(elem); delete globalThis.picorubyRefs[$1]; },
5715
+ 2823807: ($0, $1, $2) => { const obj = globalThis.picorubyRefs[$0]; const key = UTF8ToString($1); const val = globalThis.picorubyRefs[$2]; obj[key] = val; delete globalThis.picorubyRefs[$2]; }
5422
5716
  };
5423
5717
  function ble_dataview_length(ref_id) { try { const dv = globalThis.picorubyRefs[ref_id]; if (dv && dv.byteLength !== undefined) { return dv.byteLength; } return 0; } catch(e) { console.error('ble_dataview_length failed:', e); return 0; } }
5424
5718
  function ble_dataview_read(ref_id,out_buf,max_len) { try { const dv = globalThis.picorubyRefs[ref_id]; if (!dv) return 0; const len = Math.min(dv.byteLength, max_len); for (let i = 0; i < len; i++) { HEAPU8[out_buf + i] = dv.getUint8(i); } return len; } catch(e) { console.error('ble_dataview_read failed:', e); return 0; } }
5425
5719
  function ble_create_uint8array(data,length) { try { const buffer = new Uint8Array(HEAPU8.buffer, data, length); const copy = new Uint8Array(buffer); const refId = globalThis.picorubyRefs.push(copy) - 1; return refId; } catch(e) { console.error('ble_create_uint8array failed:', e); return -1; } }
5426
- function ble_set_notify_handler(char_ref_id,callback_id) { try { const char_obj = globalThis.picorubyRefs[char_ref_id]; char_obj.addEventListener('characteristicvaluechanged', (event) => { const dataview = event.target.value; const len = dataview.byteLength; const ptr = _malloc(len); for (let i = 0; i < len; i++) { HEAPU8[ptr + i] = dataview.getUint8(i); } ccall( 'ble_notify_callback', 'void', ['number', 'number', 'number'], [callback_id, ptr, len] ); _free(ptr); }); } catch(e) { console.error('ble_set_notify_handler failed:', e); } }
5427
- function init_js_refs() { if (typeof globalThis.picorubyRefs === 'undefined') { globalThis.picorubyRefs = []; const rootObject = typeof window !== 'undefined' ? window : globalThis; globalThis.picorubyRefs.push(rootObject); } if (typeof window !== 'undefined' && typeof window._js_remove_event_listener_wrapper === 'undefined') { window._js_remove_event_listener_wrapper = function(callback_id) { if (!globalThis.picorubyEventHandlers) return false; const info = globalThis.picorubyEventHandlers[callback_id]; if (!info) return false; info.target.removeEventListener(info.type, info.handler); delete globalThis.picorubyEventHandlers[callback_id]; return true; }; } }
5720
+ function ble_set_notify_handler(char_ref_id,callback_id) { try { const char_obj = globalThis.picorubyRefs[char_ref_id]; if (char_obj.__picorbNotifyListener) { char_obj.removeEventListener('characteristicvaluechanged', char_obj.__picorbNotifyListener); } const listener = (event) => { const dataview = event.target.value; const len = dataview.byteLength; const ptr = _malloc(len); for (let i = 0; i < len; i++) { HEAPU8[ptr + i] = dataview.getUint8(i); } ccall( 'ble_notify_callback', 'void', ['number', 'number', 'number'], [callback_id, ptr, len] ); _free(ptr); }; char_obj.__picorbNotifyListener = listener; char_obj.addEventListener('characteristicvaluechanged', listener); } catch(e) { console.error('ble_set_notify_handler failed:', e); } }
5721
+ function init_js_refs() { if (typeof globalThis.picorubyRefs === 'undefined') { globalThis.picorubyRefs = []; const rootObject = typeof window !== 'undefined' ? window : globalThis; globalThis.picorubyRefs.push(rootObject); } if (typeof window !== 'undefined' && typeof window._js_remove_event_listener_wrapper === 'undefined') { window._js_remove_event_listener_wrapper = function(callback_id) { if (!globalThis.picorubyEventHandlers) return false; const info = globalThis.picorubyEventHandlers[callback_id]; if (!info) return false; info.target.removeEventListener(info.type, info.handler, !!info.capture); delete globalThis.picorubyEventHandlers[callback_id]; return true; }; } }
5428
5722
  function js_last_error_length() { const message = globalThis.picorubyLastError; return message ? lengthBytesUTF8(message) : 0; }
5429
5723
  function js_copy_last_error(buffer,buffer_size) { const message = globalThis.picorubyLastError; if (!message) { globalThis.picorubyLastError = null; return; } stringToUTF8(message, buffer, buffer_size); globalThis.picorubyLastError = null; }
5430
5724
  function is_array_like(ref_id) { const obj = globalThis.picorubyRefs[ref_id]; const isNodeList = typeof NodeList !== 'undefined' && obj instanceof NodeList; const isHTMLCollection = typeof HTMLCollection !== 'undefined' && obj instanceof HTMLCollection; return isNodeList || isHTMLCollection || (typeof obj === 'object' && obj !== null && 'length' in obj && typeof obj.length === 'number'); }
@@ -5458,12 +5752,12 @@ function call_constructor_with_args(ref_id,args_json,args_json_len) { globalThis
5458
5752
  function js_function_apply_args(func_ref_id,args_json,args_json_len) { globalThis.picorubyLastError = null; try { const fn = globalThis.picorubyRefs[func_ref_id]; if (typeof fn !== 'function') { console.error('js_function_apply_args: not a function'); return -1; } const argsData = JSON.parse(UTF8ToString(args_json, args_json_len)); if (!Array.isArray(argsData)) { console.error('js_function_apply_args: args_json must be a JSON array'); return -1; } const args = argsData.map(arg => { switch (arg.type) { case 'string': case 'integer': case 'float': case 'boolean': return arg.value; case 'ref': return globalThis.picorubyRefs[arg.value]; case 'nil': return null; default: return null; } }); const result = fn(...args); const newRefId = globalThis.picorubyRefs.length; globalThis.picorubyRefs.push(result); return newRefId; } catch(e) { globalThis.picorubyLastError = e && typeof e.message === 'string' ? e.message : String(e); return -1; } }
5459
5753
  function call_fetch_with_json_options(ref_id,url,options_json) { globalThis.picorubyLastError = null; try { const obj = globalThis.picorubyRefs[ref_id]; const urlStr = UTF8ToString(url); const optionsStr = UTF8ToString(options_json); const options = JSON.parse(optionsStr); const result = obj.fetch(urlStr, options); const newRefId = globalThis.picorubyRefs.length; globalThis.picorubyRefs.push(result); return newRefId; } catch(e) { globalThis.picorubyLastError = e && typeof e.message === 'string' ? e.message : String(e); return -1; } }
5460
5754
  function setup_promise_handler(promise_id,callback_id,mrb_ptr,task_ptr) { const promise = globalThis.picorubyRefs[promise_id]; promise.then( (result) => { const resultId = globalThis.picorubyRefs.length; globalThis.picorubyRefs.push(result); ccall( 'resume_promise_task', 'void', ['number', 'number', 'number', 'number'], [mrb_ptr, task_ptr, callback_id, resultId] ); } ).catch( (error) => { const message = error && typeof error.message === 'string' ? error.message : String(error); const size = lengthBytesUTF8(message) + 1; const errorPtr = _malloc(size); stringToUTF8(message, errorPtr, size); ccall( 'resume_promise_error_task', 'void', ['number', 'number', 'number', 'number'], [mrb_ptr, task_ptr, callback_id, errorPtr] ); } ); }
5461
- function js_add_event_listener(ref_id,callback_id,event_type) { const target = globalThis.picorubyRefs[ref_id]; const type = UTF8ToString(event_type); const handler = (event) => { if (!globalThis.picorubyEventHandlers || !globalThis.picorubyEventHandlers[callback_id]) { return; } if (type === 'submit' || (type === 'click' && target.tagName === 'A')) { event.preventDefault(); } const eventRefId = globalThis.picorubyRefs.push(event) - 1; ccall( 'call_ruby_callback', 'void', ['number', 'number'], [callback_id, eventRefId] ); }; target.addEventListener(type, handler); if (!globalThis.picorubyEventHandlers) { globalThis.picorubyEventHandlers = {}; } globalThis.picorubyEventHandlers[callback_id] = { target, type, handler }; }
5755
+ function js_add_event_listener(ref_id,callback_id,event_type,sync,capture,once,passive) { const target = globalThis.picorubyRefs[ref_id]; const type = UTF8ToString(event_type); const isSync = !!sync; const isOnce = !!once; const isCapture = !!capture; let options = undefined; if (isCapture || isOnce || passive >= 0) { options = { capture: isCapture, once: isOnce }; if (passive >= 0) options.passive = (passive === 1); } const handler = (event) => { if (!globalThis.picorubyEventHandlers || !globalThis.picorubyEventHandlers[callback_id]) { return; } if (isOnce) { delete globalThis.picorubyEventHandlers[callback_id]; } if (!isSync && passive !== 1 && (type === 'submit' || (type === 'click' && target.tagName === 'A'))) { event.preventDefault(); } const eventRefId = globalThis.picorubyRefs.push(event) - 1; if (isSync) { try { ccall( 'call_ruby_callback_sync_event', 'void', ['number', 'number', 'number'], [callback_id, eventRefId, isOnce ? 1 : 0] ); } finally { delete globalThis.picorubyRefs[eventRefId]; } } else { ccall( isOnce ? 'call_ruby_callback_oneshot' : 'call_ruby_callback', 'void', ['number', 'number'], [callback_id, eventRefId] ); } }; if (options) { target.addEventListener(type, handler, options); } else { target.addEventListener(type, handler); } if (!globalThis.picorubyEventHandlers) { globalThis.picorubyEventHandlers = {}; } globalThis.picorubyEventHandlers[callback_id] = { target, type, handler, capture: isCapture }; }
5462
5756
  function js_register_generic_callback(callback_id,callback_name) { const name = UTF8ToString(callback_name); if (!globalThis.picorubyGenericCallbacks) { globalThis.picorubyGenericCallbacks = {}; } globalThis.picorubyGenericCallbacks[name] = function(...args) { const argRefIds = args.map(arg => { const refId = globalThis.picorubyRefs.push(arg) - 1; return refId; }); const argRefIdsPtr = _malloc(argRefIds.length * 4); for (let i = 0; i < argRefIds.length; i++) { HEAP32[(argRefIdsPtr >> 2) + i] = argRefIds[i]; } const resultRefId = ccall( 'call_ruby_callback_sync_generic', 'number', ['number', 'number', 'number'], [callback_id, argRefIdsPtr, argRefIds.length] ); _free(argRefIdsPtr); if (resultRefId >= 0 && resultRefId < globalThis.picorubyRefs.length) { return globalThis.picorubyRefs[resultRefId]; } return undefined; }; }
5463
5757
  function js_create_callback_function(callback_id) { try { const fn = function(...args) { const argRefIds = args.map(arg => globalThis.picorubyRefs.push(arg) - 1); const argRefIdsPtr = _malloc(argRefIds.length * 4); for (let i = 0; i < argRefIds.length; i++) { HEAP32[(argRefIdsPtr >> 2) + i] = argRefIds[i]; } const resultRefId = ccall( 'call_ruby_callback_sync_generic', 'number', ['number', 'number', 'number'], [callback_id, argRefIdsPtr, argRefIds.length] ); _free(argRefIdsPtr); if (resultRefId >= 0 && resultRefId < globalThis.picorubyRefs.length) { return globalThis.picorubyRefs[resultRefId]; } return undefined; }; return globalThis.picorubyRefs.push(fn) - 1; } catch (e) { console.error('js_create_callback_function failed:', e); return -1; } }
5464
5758
  function js_set_timeout(callback_id,delay_ms) { const timerId = setTimeout(function() { if (!globalThis.picorubyTimeoutHandlers || !globalThis.picorubyTimeoutHandlers[callback_id]) { return; } ccall( 'call_ruby_callback_oneshot', 'void', ['number', 'number'], [callback_id, -1] ); delete globalThis.picorubyTimeoutHandlers[callback_id]; }, delay_ms); if (!globalThis.picorubyTimeoutHandlers) { globalThis.picorubyTimeoutHandlers = {}; } globalThis.picorubyTimeoutHandlers[callback_id] = timerId; return timerId; }
5465
5759
  function js_clear_timeout(callback_id) { try { if (!globalThis.picorubyTimeoutHandlers) return false; const timerId = globalThis.picorubyTimeoutHandlers[callback_id]; if (timerId === undefined) return false; clearTimeout(timerId); delete globalThis.picorubyTimeoutHandlers[callback_id]; return true; } catch(e) { console.error('Error in js_clear_timeout:', e); return false; } }
5466
- function js_remove_event_listener(callback_id) { try { if (!globalThis.picorubyEventHandlers) return false; const info = globalThis.picorubyEventHandlers[callback_id]; if (!info) return false; info.target.removeEventListener(info.type, info.handler); delete globalThis.picorubyEventHandlers[callback_id]; return true; } catch(e) { console.error('Error in js_remove_event_listener:', e); return false; } }
5760
+ function js_remove_event_listener(callback_id) { try { if (!globalThis.picorubyEventHandlers) return false; const info = globalThis.picorubyEventHandlers[callback_id]; if (!info) return false; info.target.removeEventListener(info.type, info.handler, !!info.capture); delete globalThis.picorubyEventHandlers[callback_id]; return true; } catch(e) { console.error('Error in js_remove_event_listener:', e); return false; } }
5467
5761
  function js_create_element(tag_name) { try { const element = document.createElement(UTF8ToString(tag_name)); const refId = globalThis.picorubyRefs.push(element) - 1; return refId; } catch(e) { console.error('Error in js_create_element:', e); return -1; } }
5468
5762
  function js_create_text_node(text) { try { const node = document.createTextNode(UTF8ToString(text)); const refId = globalThis.picorubyRefs.push(node) - 1; return refId; } catch(e) { console.error('Error in js_create_text_node:', e); return -1; } }
5469
5763
  function js_create_object() { try { const obj = {}; const refId = globalThis.picorubyRefs.push(obj) - 1; return refId; } catch(e) { console.error('Error in js_create_object:', e); return -1; } }
@@ -5519,9 +5813,9 @@ function ws_set_onopen(ref_id,callback_id) { const ws = globalThis.picorubyRefs[
5519
5813
  function ws_set_onmessage(ref_id,callback_id) { const ws = globalThis.picorubyRefs[ref_id]; ws.onmessage = (event) => { let data = event.data; if (data instanceof ArrayBuffer) { const uint8Array = new Uint8Array(data); const length = uint8Array.length; const ptr = _malloc(length); HEAPU8.set(uint8Array, ptr); ccall( 'call_ruby_callback_with_binary_data', 'void', ['number', 'number', 'number'], [callback_id, ptr, length] ); } else { const eventRefId = globalThis.picorubyRefs.push(event) - 1; ccall( 'call_ruby_callback', 'void', ['number', 'number'], [callback_id, eventRefId] ); } }; }
5520
5814
  function ws_set_onerror(ref_id,callback_id) { const ws = globalThis.picorubyRefs[ref_id]; ws.onerror = (event) => { const eventRefId = globalThis.picorubyRefs.push(event) - 1; ccall( 'call_ruby_callback_oneshot', 'void', ['number', 'number'], [callback_id, eventRefId] ); }; }
5521
5815
  function ws_set_onclose(ref_id,callback_id) { const ws = globalThis.picorubyRefs[ref_id]; ws.onclose = (event) => { const eventRefId = globalThis.picorubyRefs.push(event) - 1; ccall( 'call_ruby_callback_oneshot', 'void', ['number', 'number'], [callback_id, eventRefId] ); }; }
5522
- function idb_request_to_promise(req_ref_id) { try { const req = globalThis.picorubyRefs[req_ref_id]; if (!req) { console.error('idb_request_to_promise: invalid ref_id', req_ref_id); return -1; } const promise = new Promise((resolve, reject) => { req.onsuccess = () => { resolve(req.result); }; req.onerror = () => { const msg = (req.error && req.error.message) || 'IDB request failed'; reject(new Error(msg)); }; }); return globalThis.picorubyRefs.push(promise) - 1; } catch (e) { console.error('idb_request_to_promise failed:', e); return -1; } }
5523
- function idb_open_with_upgrade(name_ptr,version,callback_id) { try { const name = UTF8ToString(name_ptr); const idb = globalThis.indexedDB; if (!idb) { console.error('idb_open_with_upgrade: indexedDB unavailable'); return -1; } const req = (version > 0) ? idb.open(name, version) : idb.open(name); req.onupgradeneeded = (event) => { if (callback_id === 0) return; const db = req.result; const oldV = event.oldVersion; const newV = event.newVersion; const dbRef = globalThis.picorubyRefs.push(db) - 1; const oldRef = globalThis.picorubyRefs.push(oldV) - 1; const newRef = globalThis.picorubyRefs.push(newV) - 1; const argRefIds = [dbRef, oldRef, newRef]; const argRefIdsPtr = _malloc(argRefIds.length * 4); for (let i = 0; i < argRefIds.length; i++) { HEAP32[(argRefIdsPtr >> 2) + i] = argRefIds[i]; } try { ccall( 'call_ruby_callback_sync_generic', 'number', ['number', 'number', 'number'], [callback_id, argRefIdsPtr, argRefIds.length] ); } catch (e) { console.error('idb upgrade callback threw:', e); } finally { _free(argRefIdsPtr); } }; const promise = new Promise((resolve, reject) => { req.onsuccess = () => { resolve(req.result); }; req.onerror = () => { const msg = (req.error && req.error.message) || 'IDB open failed'; reject(new Error(msg)); }; req.onblocked = () => { reject(new Error('IDB open blocked: another connection holds an older version')); }; }); return globalThis.picorubyRefs.push(promise) - 1; } catch (e) { console.error('idb_open_with_upgrade failed:', e); return -1; } }
5524
- function idb_transaction_to_promise(tx_ref_id) { try { const tx = globalThis.picorubyRefs[tx_ref_id]; if (!tx) { console.error('idb_transaction_to_promise: invalid ref_id', tx_ref_id); return -1; } const promise = new Promise((resolve, reject) => { tx.oncomplete = () => { resolve(true); }; tx.onerror = () => { const msg = (tx.error && tx.error.message) || 'IDB transaction error'; reject(new Error(msg)); }; tx.onabort = () => { const msg = (tx.error && tx.error.message) || 'IDB transaction aborted'; reject(new Error(msg)); }; }); return globalThis.picorubyRefs.push(promise) - 1; } catch (e) { console.error('idb_transaction_to_promise failed:', e); return -1; } }
5816
+ function idb_request_to_promise(req_ref_id) { try { const req = globalThis.picorubyRefs[req_ref_id]; if (!req) { console.error('idb_request_to_promise: invalid ref_id', req_ref_id); return -1; } const promise = new Promise((resolve) => { req.onsuccess = () => { resolve({ ok: true, value: req.result }); }; req.onerror = () => { resolve({ ok: false, name: (req.error && req.error.name) || 'UnknownError', message: (req.error && req.error.message) || 'IDB request failed' }); }; }); return globalThis.picorubyRefs.push(promise) - 1; } catch (e) { console.error('idb_request_to_promise failed:', e); return -1; } }
5817
+ function idb_open_with_upgrade(name_ptr,version,callback_id,blocked_timeout_ms) { try { const name = UTF8ToString(name_ptr); const idb = globalThis.indexedDB; if (!idb) { console.error('idb_open_with_upgrade: indexedDB unavailable'); return -1; } let req; try { req = (version > 0) ? idb.open(name, version) : idb.open(name); } catch (e) { const promise = Promise.resolve({ ok: false, name: (e && e.name) || 'UnknownError', message: (e && e.message) || 'IDB open failed' }); return globalThis.picorubyRefs.push(promise) - 1; } let settled = false; let timedOut = false; let blockedTimer = null; req.onupgradeneeded = (event) => { if (timedOut) { try { if (req.transaction) req.transaction.abort(); } catch (e) { console.error('failed to abort late IDB upgrade:', e); } return; } if (callback_id === 0) return; const db = req.result; const oldV = event.oldVersion; const newV = event.newVersion; const dbRef = globalThis.picorubyRefs.push(db) - 1; const oldRef = globalThis.picorubyRefs.push(oldV) - 1; const newRef = globalThis.picorubyRefs.push(newV) - 1; const argRefIds = [dbRef, oldRef, newRef]; const argRefIdsPtr = _malloc(argRefIds.length * 4); for (let i = 0; i < argRefIds.length; i++) { HEAP32[(argRefIdsPtr >> 2) + i] = argRefIds[i]; } try { ccall( 'call_ruby_callback_sync_generic', 'number', ['number', 'number', 'number'], [callback_id, argRefIdsPtr, argRefIds.length] ); } catch (e) { console.error('idb upgrade callback threw:', e); } finally { _free(argRefIdsPtr); } }; const promise = new Promise((resolve) => { const settle = (result) => { if (settled) return; settled = true; if (blockedTimer) { clearTimeout(blockedTimer); blockedTimer = null; } resolve(result); }; req.onsuccess = () => { if (settled) { try { req.result.close(); } catch (e) {} return; } settle({ ok: true, value: req.result }); }; req.onerror = () => { settle({ ok: false, name: (req.error && req.error.name) || 'UnknownError', message: (req.error && req.error.message) || 'IDB open failed' }); }; req.onblocked = () => { if (settled || blockedTimer) return; blockedTimer = setTimeout(() => { timedOut = true; settle({ ok: false, name: 'PicoRubyBlockedTimeout', message: 'IDB open blocked: another connection held an older version past the timeout' }); }, blocked_timeout_ms); }; }); return globalThis.picorubyRefs.push(promise) - 1; } catch (e) { console.error('idb_open_with_upgrade failed:', e); return -1; } }
5818
+ function idb_transaction_to_promise(tx_ref_id) { try { const tx = globalThis.picorubyRefs[tx_ref_id]; if (!tx) { console.error('idb_transaction_to_promise: invalid ref_id', tx_ref_id); return -1; } const promise = new Promise((resolve) => { tx.oncomplete = () => { resolve({ ok: true, value: true }); }; tx.onerror = () => { resolve({ ok: false, name: (tx.error && tx.error.name) || 'UnknownError', message: (tx.error && tx.error.message) || 'IDB transaction error' }); }; tx.onabort = () => { resolve({ ok: false, name: (tx.error && tx.error.name) || 'AbortError', message: (tx.error && tx.error.message) || 'IDB transaction aborted' }); }; }); return globalThis.picorubyRefs.push(promise) - 1; } catch (e) { console.error('idb_transaction_to_promise failed:', e); return -1; } }
5525
5819
  function emscripten_date_now() { return Date.now(); }
5526
5820
 
5527
5821
  // Imports from the Wasm binary.
@@ -5539,6 +5833,7 @@ var _mrb_debug_next = Module['_mrb_debug_next'] = makeInvalidEarlyAccess('_mrb_d
5539
5833
  var _mrb_debug_get_callstack = Module['_mrb_debug_get_callstack'] = makeInvalidEarlyAccess('_mrb_debug_get_callstack');
5540
5834
  var _call_ruby_callback = Module['_call_ruby_callback'] = makeInvalidEarlyAccess('_call_ruby_callback');
5541
5835
  var _call_ruby_callback_oneshot = Module['_call_ruby_callback_oneshot'] = makeInvalidEarlyAccess('_call_ruby_callback_oneshot');
5836
+ var _call_ruby_callback_sync_event = Module['_call_ruby_callback_sync_event'] = makeInvalidEarlyAccess('_call_ruby_callback_sync_event');
5542
5837
  var _resume_promise_task = Module['_resume_promise_task'] = makeInvalidEarlyAccess('_resume_promise_task');
5543
5838
  var _resume_promise_error_task = Module['_resume_promise_error_task'] = makeInvalidEarlyAccess('_resume_promise_error_task');
5544
5839
  var _resume_binary_task = Module['_resume_binary_task'] = makeInvalidEarlyAccess('_resume_binary_task');
@@ -5587,6 +5882,7 @@ function assignWasmExports(wasmExports) {
5587
5882
  assert(typeof wasmExports['mrb_debug_get_callstack'] != 'undefined', 'missing Wasm export: mrb_debug_get_callstack');
5588
5883
  assert(typeof wasmExports['call_ruby_callback'] != 'undefined', 'missing Wasm export: call_ruby_callback');
5589
5884
  assert(typeof wasmExports['call_ruby_callback_oneshot'] != 'undefined', 'missing Wasm export: call_ruby_callback_oneshot');
5885
+ assert(typeof wasmExports['call_ruby_callback_sync_event'] != 'undefined', 'missing Wasm export: call_ruby_callback_sync_event');
5590
5886
  assert(typeof wasmExports['resume_promise_task'] != 'undefined', 'missing Wasm export: resume_promise_task');
5591
5887
  assert(typeof wasmExports['resume_promise_error_task'] != 'undefined', 'missing Wasm export: resume_promise_error_task');
5592
5888
  assert(typeof wasmExports['resume_binary_task'] != 'undefined', 'missing Wasm export: resume_binary_task');
@@ -5617,41 +5913,42 @@ function assignWasmExports(wasmExports) {
5617
5913
  assert(typeof wasmExports['emscripten_stack_get_current'] != 'undefined', 'missing Wasm export: emscripten_stack_get_current');
5618
5914
  assert(typeof wasmExports['memory'] != 'undefined', 'missing Wasm export: memory');
5619
5915
  assert(typeof wasmExports['__indirect_function_table'] != 'undefined', 'missing Wasm export: __indirect_function_table');
5620
- _ble_notify_callback = Module['_ble_notify_callback'] = createExportWrapper('ble_notify_callback', 3);
5621
- _mrb_get_globals_json = Module['_mrb_get_globals_json'] = createExportWrapper('mrb_get_globals_json', 0);
5622
- _mrb_get_component_debug_info = Module['_mrb_get_component_debug_info'] = createExportWrapper('mrb_get_component_debug_info', 1);
5623
- _mrb_get_component_state_by_id = Module['_mrb_get_component_state_by_id'] = createExportWrapper('mrb_get_component_state_by_id', 1);
5624
- _mrb_eval_string = Module['_mrb_eval_string'] = createExportWrapper('mrb_eval_string', 1);
5625
- _mrb_debug_get_status = Module['_mrb_debug_get_status'] = createExportWrapper('mrb_debug_get_status', 0);
5626
- _mrb_debug_continue = Module['_mrb_debug_continue'] = createExportWrapper('mrb_debug_continue', 0);
5627
- _mrb_debug_get_locals = Module['_mrb_debug_get_locals'] = createExportWrapper('mrb_debug_get_locals', 0);
5628
- _mrb_debug_eval_in_binding = Module['_mrb_debug_eval_in_binding'] = createExportWrapper('mrb_debug_eval_in_binding', 1);
5629
- _mrb_debug_step = Module['_mrb_debug_step'] = createExportWrapper('mrb_debug_step', 0);
5630
- _mrb_debug_next = Module['_mrb_debug_next'] = createExportWrapper('mrb_debug_next', 0);
5631
- _mrb_debug_get_callstack = Module['_mrb_debug_get_callstack'] = createExportWrapper('mrb_debug_get_callstack', 0);
5632
- _call_ruby_callback = Module['_call_ruby_callback'] = createExportWrapper('call_ruby_callback', 2);
5633
- _call_ruby_callback_oneshot = Module['_call_ruby_callback_oneshot'] = createExportWrapper('call_ruby_callback_oneshot', 2);
5634
- _resume_promise_task = Module['_resume_promise_task'] = createExportWrapper('resume_promise_task', 4);
5635
- _resume_promise_error_task = Module['_resume_promise_error_task'] = createExportWrapper('resume_promise_error_task', 4);
5636
- _resume_binary_task = Module['_resume_binary_task'] = createExportWrapper('resume_binary_task', 5);
5637
- _call_ruby_callback_sync_generic = Module['_call_ruby_callback_sync_generic'] = createExportWrapper('call_ruby_callback_sync_generic', 3);
5638
- _mrb_tick_wasm = Module['_mrb_tick_wasm'] = createExportWrapper('mrb_tick_wasm', 0);
5639
- _mrb_run_step = Module['_mrb_run_step'] = createExportWrapper('mrb_run_step', 0);
5640
- _mrb_run_step_status = Module['_mrb_run_step_status'] = createExportWrapper('mrb_run_step_status', 0);
5641
- _mrb_gc_scheduler_pending_wasm = Module['_mrb_gc_scheduler_pending_wasm'] = createExportWrapper('mrb_gc_scheduler_pending_wasm', 0);
5642
- _picorb_init = Module['_picorb_init'] = createExportWrapper('picorb_init', 0);
5643
- _picorb_create_task = Module['_picorb_create_task'] = createExportWrapper('picorb_create_task', 1);
5644
- _picorb_create_task_with_filename = Module['_picorb_create_task_with_filename'] = createExportWrapper('picorb_create_task_with_filename', 2);
5645
- _picorb_create_task_from_mrb = Module['_picorb_create_task_from_mrb'] = createExportWrapper('picorb_create_task_from_mrb', 2);
5646
- _serial_data_received = Module['_serial_data_received'] = createExportWrapper('serial_data_received', 3);
5647
- _serial_disconnect_callback = Module['_serial_disconnect_callback'] = createExportWrapper('serial_disconnect_callback', 1);
5648
- _call_ruby_callback_with_binary_data = Module['_call_ruby_callback_with_binary_data'] = createExportWrapper('call_ruby_callback_with_binary_data', 3);
5649
- _fflush = createExportWrapper('fflush', 1);
5650
- _strerror = createExportWrapper('strerror', 1);
5651
- _emscripten_builtin_memalign = createExportWrapper('emscripten_builtin_memalign', 2);
5652
- _malloc = Module['_malloc'] = createExportWrapper('malloc', 1);
5653
- _free = Module['_free'] = createExportWrapper('free', 1);
5654
- _setThrew = createExportWrapper('setThrew', 2);
5916
+ _ble_notify_callback = Module['_ble_notify_callback'] = createExportWrapper('ble_notify_callback', wasmExports['ble_notify_callback'], 3);
5917
+ _mrb_get_globals_json = Module['_mrb_get_globals_json'] = createExportWrapper('mrb_get_globals_json', wasmExports['mrb_get_globals_json'], 0);
5918
+ _mrb_get_component_debug_info = Module['_mrb_get_component_debug_info'] = createExportWrapper('mrb_get_component_debug_info', wasmExports['mrb_get_component_debug_info'], 1);
5919
+ _mrb_get_component_state_by_id = Module['_mrb_get_component_state_by_id'] = createExportWrapper('mrb_get_component_state_by_id', wasmExports['mrb_get_component_state_by_id'], 1);
5920
+ _mrb_eval_string = Module['_mrb_eval_string'] = createExportWrapper('mrb_eval_string', wasmExports['mrb_eval_string'], 1);
5921
+ _mrb_debug_get_status = Module['_mrb_debug_get_status'] = createExportWrapper('mrb_debug_get_status', wasmExports['mrb_debug_get_status'], 0);
5922
+ _mrb_debug_continue = Module['_mrb_debug_continue'] = createExportWrapper('mrb_debug_continue', wasmExports['mrb_debug_continue'], 0);
5923
+ _mrb_debug_get_locals = Module['_mrb_debug_get_locals'] = createExportWrapper('mrb_debug_get_locals', wasmExports['mrb_debug_get_locals'], 0);
5924
+ _mrb_debug_eval_in_binding = Module['_mrb_debug_eval_in_binding'] = createExportWrapper('mrb_debug_eval_in_binding', wasmExports['mrb_debug_eval_in_binding'], 1);
5925
+ _mrb_debug_step = Module['_mrb_debug_step'] = createExportWrapper('mrb_debug_step', wasmExports['mrb_debug_step'], 0);
5926
+ _mrb_debug_next = Module['_mrb_debug_next'] = createExportWrapper('mrb_debug_next', wasmExports['mrb_debug_next'], 0);
5927
+ _mrb_debug_get_callstack = Module['_mrb_debug_get_callstack'] = createExportWrapper('mrb_debug_get_callstack', wasmExports['mrb_debug_get_callstack'], 0);
5928
+ _call_ruby_callback = Module['_call_ruby_callback'] = createExportWrapper('call_ruby_callback', wasmExports['call_ruby_callback'], 2);
5929
+ _call_ruby_callback_oneshot = Module['_call_ruby_callback_oneshot'] = createExportWrapper('call_ruby_callback_oneshot', wasmExports['call_ruby_callback_oneshot'], 2);
5930
+ _call_ruby_callback_sync_event = Module['_call_ruby_callback_sync_event'] = createExportWrapper('call_ruby_callback_sync_event', wasmExports['call_ruby_callback_sync_event'], 3);
5931
+ _resume_promise_task = Module['_resume_promise_task'] = createExportWrapper('resume_promise_task', wasmExports['resume_promise_task'], 4);
5932
+ _resume_promise_error_task = Module['_resume_promise_error_task'] = createExportWrapper('resume_promise_error_task', wasmExports['resume_promise_error_task'], 4);
5933
+ _resume_binary_task = Module['_resume_binary_task'] = createExportWrapper('resume_binary_task', wasmExports['resume_binary_task'], 5);
5934
+ _call_ruby_callback_sync_generic = Module['_call_ruby_callback_sync_generic'] = createExportWrapper('call_ruby_callback_sync_generic', wasmExports['call_ruby_callback_sync_generic'], 3);
5935
+ _mrb_tick_wasm = Module['_mrb_tick_wasm'] = createExportWrapper('mrb_tick_wasm', wasmExports['mrb_tick_wasm'], 0);
5936
+ _mrb_run_step = Module['_mrb_run_step'] = createExportWrapper('mrb_run_step', wasmExports['mrb_run_step'], 0);
5937
+ _mrb_run_step_status = Module['_mrb_run_step_status'] = createExportWrapper('mrb_run_step_status', wasmExports['mrb_run_step_status'], 0);
5938
+ _mrb_gc_scheduler_pending_wasm = Module['_mrb_gc_scheduler_pending_wasm'] = createExportWrapper('mrb_gc_scheduler_pending_wasm', wasmExports['mrb_gc_scheduler_pending_wasm'], 0);
5939
+ _picorb_init = Module['_picorb_init'] = createExportWrapper('picorb_init', wasmExports['picorb_init'], 0);
5940
+ _picorb_create_task = Module['_picorb_create_task'] = createExportWrapper('picorb_create_task', wasmExports['picorb_create_task'], 1);
5941
+ _picorb_create_task_with_filename = Module['_picorb_create_task_with_filename'] = createExportWrapper('picorb_create_task_with_filename', wasmExports['picorb_create_task_with_filename'], 2);
5942
+ _picorb_create_task_from_mrb = Module['_picorb_create_task_from_mrb'] = createExportWrapper('picorb_create_task_from_mrb', wasmExports['picorb_create_task_from_mrb'], 2);
5943
+ _serial_data_received = Module['_serial_data_received'] = createExportWrapper('serial_data_received', wasmExports['serial_data_received'], 3);
5944
+ _serial_disconnect_callback = Module['_serial_disconnect_callback'] = createExportWrapper('serial_disconnect_callback', wasmExports['serial_disconnect_callback'], 1);
5945
+ _call_ruby_callback_with_binary_data = Module['_call_ruby_callback_with_binary_data'] = createExportWrapper('call_ruby_callback_with_binary_data', wasmExports['call_ruby_callback_with_binary_data'], 3);
5946
+ _fflush = createExportWrapper('fflush', wasmExports['fflush'], 1);
5947
+ _strerror = createExportWrapper('strerror', wasmExports['strerror'], 1);
5948
+ _emscripten_builtin_memalign = createExportWrapper('emscripten_builtin_memalign', wasmExports['emscripten_builtin_memalign'], 2);
5949
+ _malloc = Module['_malloc'] = createExportWrapper('malloc', wasmExports['malloc'], 1);
5950
+ _free = Module['_free'] = createExportWrapper('free', wasmExports['free'], 1);
5951
+ _setThrew = createExportWrapper('setThrew', wasmExports['setThrew'], 2);
5655
5952
  _emscripten_stack_init = wasmExports['emscripten_stack_init'];
5656
5953
  _emscripten_stack_get_free = wasmExports['emscripten_stack_get_free'];
5657
5954
  _emscripten_stack_get_base = wasmExports['emscripten_stack_get_base'];
@@ -5697,10 +5994,12 @@ var wasmImports = {
5697
5994
  /** @export */
5698
5995
  __syscall_openat: ___syscall_openat,
5699
5996
  /** @export */
5700
- __syscall_pipe: ___syscall_pipe,
5997
+ __syscall_pipe2: ___syscall_pipe2,
5701
5998
  /** @export */
5702
5999
  __syscall_poll: ___syscall_poll,
5703
6000
  /** @export */
6001
+ __syscall_poll_nonblocking: ___syscall_poll_nonblocking,
6002
+ /** @export */
5704
6003
  __syscall_readlinkat: ___syscall_readlinkat,
5705
6004
  /** @export */
5706
6005
  __syscall_renameat: ___syscall_renameat,
@@ -5711,6 +6010,8 @@ var wasmImports = {
5711
6010
  /** @export */
5712
6011
  __syscall_symlinkat: ___syscall_symlinkat,
5713
6012
  /** @export */
6013
+ __syscall_umask: ___syscall_umask,
6014
+ /** @export */
5714
6015
  __syscall_unlinkat: ___syscall_unlinkat,
5715
6016
  /** @export */
5716
6017
  _abort_js: __abort_js,
@@ -6020,7 +6321,7 @@ function invoke_viii(index,a1,a2,a3) {
6020
6321
  getWasmTableEntry(index)(a1,a2,a3);
6021
6322
  } catch(e) {
6022
6323
  stackRestore(sp);
6023
- if (e !== e+0) throw e;
6324
+ if (!(e instanceof EmscriptenEH)) throw e;
6024
6325
  _setThrew(1, 0);
6025
6326
  }
6026
6327
  }
@@ -6031,7 +6332,7 @@ function invoke_vii(index,a1,a2) {
6031
6332
  getWasmTableEntry(index)(a1,a2);
6032
6333
  } catch(e) {
6033
6334
  stackRestore(sp);
6034
- if (e !== e+0) throw e;
6335
+ if (!(e instanceof EmscriptenEH)) throw e;
6035
6336
  _setThrew(1, 0);
6036
6337
  }
6037
6338
  }
@@ -6042,7 +6343,7 @@ function invoke_ii(index,a1) {
6042
6343
  return getWasmTableEntry(index)(a1);
6043
6344
  } catch(e) {
6044
6345
  stackRestore(sp);
6045
- if (e !== e+0) throw e;
6346
+ if (!(e instanceof EmscriptenEH)) throw e;
6046
6347
  _setThrew(1, 0);
6047
6348
  }
6048
6349
  }
@@ -6053,7 +6354,7 @@ function invoke_ji(index,a1) {
6053
6354
  return getWasmTableEntry(index)(a1);
6054
6355
  } catch(e) {
6055
6356
  stackRestore(sp);
6056
- if (e !== e+0) throw e;
6357
+ if (!(e instanceof EmscriptenEH)) throw e;
6057
6358
  _setThrew(1, 0);
6058
6359
  return 0n;
6059
6360
  }
@@ -6065,7 +6366,7 @@ function invoke_vi(index,a1) {
6065
6366
  getWasmTableEntry(index)(a1);
6066
6367
  } catch(e) {
6067
6368
  stackRestore(sp);
6068
- if (e !== e+0) throw e;
6369
+ if (!(e instanceof EmscriptenEH)) throw e;
6069
6370
  _setThrew(1, 0);
6070
6371
  }
6071
6372
  }
@@ -6076,7 +6377,7 @@ function invoke_iijiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8) {
6076
6377
  return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8);
6077
6378
  } catch(e) {
6078
6379
  stackRestore(sp);
6079
- if (e !== e+0) throw e;
6380
+ if (!(e instanceof EmscriptenEH)) throw e;
6080
6381
  _setThrew(1, 0);
6081
6382
  }
6082
6383
  }
@@ -6087,7 +6388,7 @@ function invoke_viijiii(index,a1,a2,a3,a4,a5,a6) {
6087
6388
  getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6);
6088
6389
  } catch(e) {
6089
6390
  stackRestore(sp);
6090
- if (e !== e+0) throw e;
6391
+ if (!(e instanceof EmscriptenEH)) throw e;
6091
6392
  _setThrew(1, 0);
6092
6393
  }
6093
6394
  }
@@ -6098,7 +6399,7 @@ function invoke_iii(index,a1,a2) {
6098
6399
  return getWasmTableEntry(index)(a1,a2);
6099
6400
  } catch(e) {
6100
6401
  stackRestore(sp);
6101
- if (e !== e+0) throw e;
6402
+ if (!(e instanceof EmscriptenEH)) throw e;
6102
6403
  _setThrew(1, 0);
6103
6404
  }
6104
6405
  }
@@ -6109,7 +6410,7 @@ function invoke_viiiii(index,a1,a2,a3,a4,a5) {
6109
6410
  getWasmTableEntry(index)(a1,a2,a3,a4,a5);
6110
6411
  } catch(e) {
6111
6412
  stackRestore(sp);
6112
- if (e !== e+0) throw e;
6413
+ if (!(e instanceof EmscriptenEH)) throw e;
6113
6414
  _setThrew(1, 0);
6114
6415
  }
6115
6416
  }
@@ -6120,7 +6421,7 @@ function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7) {
6120
6421
  getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7);
6121
6422
  } catch(e) {
6122
6423
  stackRestore(sp);
6123
- if (e !== e+0) throw e;
6424
+ if (!(e instanceof EmscriptenEH)) throw e;
6124
6425
  _setThrew(1, 0);
6125
6426
  }
6126
6427
  }
@@ -6131,7 +6432,7 @@ function invoke_viiii(index,a1,a2,a3,a4) {
6131
6432
  getWasmTableEntry(index)(a1,a2,a3,a4);
6132
6433
  } catch(e) {
6133
6434
  stackRestore(sp);
6134
- if (e !== e+0) throw e;
6435
+ if (!(e instanceof EmscriptenEH)) throw e;
6135
6436
  _setThrew(1, 0);
6136
6437
  }
6137
6438
  }
@@ -6142,7 +6443,7 @@ function invoke_viiiijii(index,a1,a2,a3,a4,a5,a6,a7) {
6142
6443
  getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7);
6143
6444
  } catch(e) {
6144
6445
  stackRestore(sp);
6145
- if (e !== e+0) throw e;
6446
+ if (!(e instanceof EmscriptenEH)) throw e;
6146
6447
  _setThrew(1, 0);
6147
6448
  }
6148
6449
  }
@@ -6153,7 +6454,7 @@ function invoke_iiii(index,a1,a2,a3) {
6153
6454
  return getWasmTableEntry(index)(a1,a2,a3);
6154
6455
  } catch(e) {
6155
6456
  stackRestore(sp);
6156
- if (e !== e+0) throw e;
6457
+ if (!(e instanceof EmscriptenEH)) throw e;
6157
6458
  _setThrew(1, 0);
6158
6459
  }
6159
6460
  }
@@ -6164,7 +6465,7 @@ function invoke_iiiii(index,a1,a2,a3,a4) {
6164
6465
  return getWasmTableEntry(index)(a1,a2,a3,a4);
6165
6466
  } catch(e) {
6166
6467
  stackRestore(sp);
6167
- if (e !== e+0) throw e;
6468
+ if (!(e instanceof EmscriptenEH)) throw e;
6168
6469
  _setThrew(1, 0);
6169
6470
  }
6170
6471
  }
@@ -6175,7 +6476,7 @@ function invoke_viiiij(index,a1,a2,a3,a4,a5) {
6175
6476
  getWasmTableEntry(index)(a1,a2,a3,a4,a5);
6176
6477
  } catch(e) {
6177
6478
  stackRestore(sp);
6178
- if (e !== e+0) throw e;
6479
+ if (!(e instanceof EmscriptenEH)) throw e;
6179
6480
  _setThrew(1, 0);
6180
6481
  }
6181
6482
  }
@@ -6186,7 +6487,7 @@ function invoke_vij(index,a1,a2) {
6186
6487
  getWasmTableEntry(index)(a1,a2);
6187
6488
  } catch(e) {
6188
6489
  stackRestore(sp);
6189
- if (e !== e+0) throw e;
6490
+ if (!(e instanceof EmscriptenEH)) throw e;
6190
6491
  _setThrew(1, 0);
6191
6492
  }
6192
6493
  }
@@ -6197,7 +6498,7 @@ function invoke_viij(index,a1,a2,a3) {
6197
6498
  getWasmTableEntry(index)(a1,a2,a3);
6198
6499
  } catch(e) {
6199
6500
  stackRestore(sp);
6200
- if (e !== e+0) throw e;
6501
+ if (!(e instanceof EmscriptenEH)) throw e;
6201
6502
  _setThrew(1, 0);
6202
6503
  }
6203
6504
  }
@@ -6208,7 +6509,7 @@ function invoke_viiij(index,a1,a2,a3,a4) {
6208
6509
  getWasmTableEntry(index)(a1,a2,a3,a4);
6209
6510
  } catch(e) {
6210
6511
  stackRestore(sp);
6211
- if (e !== e+0) throw e;
6512
+ if (!(e instanceof EmscriptenEH)) throw e;
6212
6513
  _setThrew(1, 0);
6213
6514
  }
6214
6515
  }
@@ -6219,7 +6520,7 @@ function invoke_viiji(index,a1,a2,a3,a4) {
6219
6520
  getWasmTableEntry(index)(a1,a2,a3,a4);
6220
6521
  } catch(e) {
6221
6522
  stackRestore(sp);
6222
- if (e !== e+0) throw e;
6523
+ if (!(e instanceof EmscriptenEH)) throw e;
6223
6524
  _setThrew(1, 0);
6224
6525
  }
6225
6526
  }
@@ -6230,7 +6531,7 @@ function invoke_viijj(index,a1,a2,a3,a4) {
6230
6531
  getWasmTableEntry(index)(a1,a2,a3,a4);
6231
6532
  } catch(e) {
6232
6533
  stackRestore(sp);
6233
- if (e !== e+0) throw e;
6534
+ if (!(e instanceof EmscriptenEH)) throw e;
6234
6535
  _setThrew(1, 0);
6235
6536
  }
6236
6537
  }
@@ -6241,7 +6542,7 @@ function invoke_ddd(index,a1,a2) {
6241
6542
  return getWasmTableEntry(index)(a1,a2);
6242
6543
  } catch(e) {
6243
6544
  stackRestore(sp);
6244
- if (e !== e+0) throw e;
6545
+ if (!(e instanceof EmscriptenEH)) throw e;
6245
6546
  _setThrew(1, 0);
6246
6547
  }
6247
6548
  }
@@ -6252,7 +6553,7 @@ function invoke_iij(index,a1,a2) {
6252
6553
  return getWasmTableEntry(index)(a1,a2);
6253
6554
  } catch(e) {
6254
6555
  stackRestore(sp);
6255
- if (e !== e+0) throw e;
6556
+ if (!(e instanceof EmscriptenEH)) throw e;
6256
6557
  _setThrew(1, 0);
6257
6558
  }
6258
6559
  }
@@ -6263,7 +6564,7 @@ function invoke_jii(index,a1,a2) {
6263
6564
  return getWasmTableEntry(index)(a1,a2);
6264
6565
  } catch(e) {
6265
6566
  stackRestore(sp);
6266
- if (e !== e+0) throw e;
6567
+ if (!(e instanceof EmscriptenEH)) throw e;
6267
6568
  _setThrew(1, 0);
6268
6569
  return 0n;
6269
6570
  }
@@ -6275,7 +6576,7 @@ function invoke_vijii(index,a1,a2,a3,a4) {
6275
6576
  getWasmTableEntry(index)(a1,a2,a3,a4);
6276
6577
  } catch(e) {
6277
6578
  stackRestore(sp);
6278
- if (e !== e+0) throw e;
6579
+ if (!(e instanceof EmscriptenEH)) throw e;
6279
6580
  _setThrew(1, 0);
6280
6581
  }
6281
6582
  }
@@ -6295,54 +6596,37 @@ function stackCheckInit() {
6295
6596
  writeStackCookie();
6296
6597
  }
6297
6598
 
6298
- function run() {
6299
-
6300
- if (runDependencies > 0) {
6301
- dependenciesFulfilled = run;
6302
- return;
6303
- }
6599
+ async function run() {
6600
+ assert(!calledRun);
6601
+ calledRun = true;
6304
6602
 
6305
6603
  stackCheckInit();
6306
6604
 
6307
6605
  preRun();
6308
6606
 
6309
- // a preRun added a dependency, run will be called later
6310
- if (runDependencies > 0) {
6311
- dependenciesFulfilled = run;
6312
- return;
6607
+ if (runDependencies) {
6608
+ await resolveRunDependencies();
6313
6609
  }
6314
6610
 
6315
- function doRun() {
6316
- // run may have just been called through dependencies being fulfilled just in this very frame,
6317
- // or while the async setStatus time below was happening
6318
- assert(!calledRun);
6319
- calledRun = true;
6320
- Module['calledRun'] = true;
6321
-
6322
- if (ABORT) return;
6611
+ var setStatus = Module['setStatus'];
6612
+ if (setStatus) {
6613
+ setStatus('Running...');
6614
+ // Yield to the event loop to allow the browser to paint "Running..."
6615
+ await new Promise((resolve) => setTimeout(resolve, 1));
6616
+ // Then we want to clear the status text, but only after the rest of this function runs.
6617
+ setTimeout(setStatus, 1, '');
6618
+ }
6323
6619
 
6324
- initRuntime();
6620
+ if (ABORT) return;
6325
6621
 
6326
- readyPromiseResolve?.(Module);
6327
- Module['onRuntimeInitialized']?.();
6328
- consumedModuleProp('onRuntimeInitialized');
6622
+ initRuntime();
6329
6623
 
6330
- assert(!Module['_main'], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');
6624
+ Module['onRuntimeInitialized']?.();
6625
+ consumedModuleProp('onRuntimeInitialized');
6331
6626
 
6332
- postRun();
6333
- }
6627
+ assert(!Module['_main'], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');
6334
6628
 
6335
- if (Module['setStatus']) {
6336
- Module['setStatus']('Running...');
6337
- setTimeout(() => {
6338
- setTimeout(() => Module['setStatus'](''), 1);
6339
- doRun();
6340
- }, 1);
6341
- } else
6342
- {
6343
- doRun();
6344
- }
6345
- checkStackCookie();
6629
+ postRun();
6346
6630
  }
6347
6631
 
6348
6632
  function checkUnflushedContent() {
@@ -6388,28 +6672,14 @@ var wasmExports;
6388
6672
 
6389
6673
  // In modularize mode the generated code is within a factory function so we
6390
6674
  // can use await here (since it's not top-level-await).
6391
- wasmExports = await (createWasm());
6392
-
6393
- run();
6675
+ wasmExports = await createWasm();
6676
+ await run();
6394
6677
 
6395
6678
  // end include: postamble.js
6396
6679
 
6397
6680
  // include: postamble_modularize.js
6398
6681
  // In MODULARIZE mode we wrap the generated code in a factory function
6399
6682
  // and return either the Module itself, or a promise of the module.
6400
- //
6401
- // We assign to the `moduleRtn` global here and configure closure to see
6402
- // this as an extern so it won't get minified.
6403
-
6404
- if (runtimeInitialized) {
6405
- moduleRtn = Module;
6406
- } else {
6407
- // Set up the promise that indicates the Module is initialized
6408
- moduleRtn = new Promise((resolve, reject) => {
6409
- readyPromiseResolve = resolve;
6410
- readyPromiseReject = reject;
6411
- });
6412
- }
6413
6683
 
6414
6684
  // Assertion for attempting to access module properties on the incoming
6415
6685
  // moduleArg. In the past we used this object as the prototype of the module
@@ -6430,7 +6700,7 @@ for (const prop of Object.keys(Module)) {
6430
6700
 
6431
6701
 
6432
6702
 
6433
- return moduleRtn;
6703
+ return Module;
6434
6704
  }
6435
6705
 
6436
6706
  // Export using a UMD style export, or ES6 exports if selected