funicular 0.3.0 → 0.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +57 -0
- data/demo/test_chartjs.html +9 -9
- data/demo/test_component.html +8 -8
- data/demo/test_error_boundary.html +44 -41
- data/demo/test_router.html +48 -48
- data/demo/tic-tac-toe.html +25 -25
- data/docs/architecture.md +46 -9
- data/lib/funicular/ssr/runtime.rb +1 -0
- data/lib/funicular/vendor/mrbc/VERSION +1 -1
- data/lib/funicular/vendor/mrbc/mrbc.js +613 -486
- data/lib/funicular/vendor/mrbc/mrbc.wasm +0 -0
- data/lib/funicular/vendor/picoruby/VERSION +1 -1
- data/lib/funicular/vendor/picoruby/debug/picoruby.js +669 -449
- data/lib/funicular/vendor/picoruby/debug/picoruby.wasm +0 -0
- data/lib/funicular/vendor/picoruby/dist/picoruby.js +2 -2
- data/lib/funicular/vendor/picoruby/dist/picoruby.wasm +0 -0
- data/lib/funicular/vendor/picoruby-test-node/VERSION +1 -1
- data/lib/funicular/vendor/picoruby-test-node/picoruby.js +921 -629
- data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm +0 -0
- data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm.map +1 -1
- data/lib/funicular/version.rb +1 -1
- data/lib/generators/funicular/chat/templates/funicular_chat_component.rb.tt +37 -38
- data/minitest/dsl_test.rb +237 -0
- data/minitest/fixtures/funicular_app/components/greeting_component.rb +5 -5
- data/minitest/form_for_test.rb +2 -2
- data/minitest/hydration_test.rb +2 -2
- data/minitest/sig_tags_test.rb +30 -0
- data/minitest/view_context_test.rb +15 -15
- data/mrblib/0_tags.rb +62 -0
- data/mrblib/component.rb +113 -23
- data/mrblib/error_boundary.rb +25 -19
- data/mrblib/form_builder.rb +10 -10
- data/mrblib/funicular.rb +1 -1
- data/mrblib/styles.rb +102 -12
- data/mrblib/view_context.rb +3 -32
- data/sig/component.rbs +18 -4
- data/sig/error_boundary.rbs +4 -4
- data/sig/styles.rbs +18 -5
- data/sig/tags.rbs +54 -0
- data/sig/view_context.rbs +47 -34
- metadata +5 -1
|
@@ -17,9 +17,14 @@
|
|
|
17
17
|
|
|
18
18
|
// Note: We use a typeof check here instead of optional chaining using
|
|
19
19
|
// globalThis because older browsers might not have globalThis defined.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
|
|
21
|
+
// We skip the node version checking when running on Bun/Deno since the node
|
|
22
|
+
// version they report doesn't seem to be useful.
|
|
23
|
+
if (typeof process !== 'undefined' && !process.versions?.bun && typeof Deno == "undefined") {
|
|
24
|
+
var currentNodeVersion = process.versions?.node ? humanReadableVersionToPacked(process.versions.node) : TARGET_NOT_SUPPORTED;
|
|
25
|
+
if (currentNodeVersion < 180300) {
|
|
26
|
+
throw new Error(`This emscripten-generated code requires node v${ packedVersionToHumanReadable(180300) } (detected v${packedVersionToHumanReadable(currentNodeVersion)})`);
|
|
27
|
+
}
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
var userAgent = typeof navigator !== 'undefined' && navigator.userAgent;
|
|
@@ -74,7 +79,7 @@ var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIR
|
|
|
74
79
|
// refer to Module (if they choose; they can also define Module)
|
|
75
80
|
|
|
76
81
|
|
|
77
|
-
var
|
|
82
|
+
var programArgs = [];
|
|
78
83
|
var thisProgram = './this.program';
|
|
79
84
|
var quit_ = (status, toThrow) => {
|
|
80
85
|
throw toThrow;
|
|
@@ -134,7 +139,7 @@ readAsync = async (filename, binary = true) => {
|
|
|
134
139
|
thisProgram = process.argv[1].replace(/\\/g, '/');
|
|
135
140
|
}
|
|
136
141
|
|
|
137
|
-
|
|
142
|
+
programArgs = process.argv.slice(2);
|
|
138
143
|
|
|
139
144
|
// MODULARIZE will export the module in the proper place outside, we don't need to export here
|
|
140
145
|
if (typeof module != 'undefined') {
|
|
@@ -224,7 +229,7 @@ var OPFS = 'OPFS is no longer included by default; build with -lopfs.js';
|
|
|
224
229
|
// perform assertions in shell.js after we set up out() and err(), as otherwise
|
|
225
230
|
// if an assertion fails it cannot print the message
|
|
226
231
|
|
|
227
|
-
assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time
|
|
232
|
+
assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time (add `shell` to `-sENVIRONMENT` to enable)');
|
|
228
233
|
|
|
229
234
|
// end include: shell.js
|
|
230
235
|
|
|
@@ -288,45 +293,12 @@ function _free() {
|
|
|
288
293
|
var isFileURI = (filename) => filename.startsWith('file://');
|
|
289
294
|
|
|
290
295
|
// include: runtime_common.js
|
|
291
|
-
// include: runtime_stack_check.js
|
|
292
|
-
// Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
|
|
293
|
-
function writeStackCookie() {
|
|
294
|
-
var max = _emscripten_stack_get_end();
|
|
295
|
-
assert((max & 3) == 0);
|
|
296
|
-
// If the stack ends at address zero we write our cookies 4 bytes into the
|
|
297
|
-
// stack. This prevents interference with SAFE_HEAP and ASAN which also
|
|
298
|
-
// monitor writes to address zero.
|
|
299
|
-
if (max == 0) {
|
|
300
|
-
max += 4;
|
|
301
|
-
}
|
|
302
|
-
// The stack grow downwards towards _emscripten_stack_get_end.
|
|
303
|
-
// We write cookies to the final two words in the stack and detect if they are
|
|
304
|
-
// ever overwritten.
|
|
305
|
-
HEAPU32[((max)>>2)] = 0x02135467;
|
|
306
|
-
HEAPU32[(((max)+(4))>>2)] = 0x89BACDFE;
|
|
307
|
-
// Also test the global address 0 for integrity.
|
|
308
|
-
HEAPU32[((0)>>2)] = 1668509029;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
function checkStackCookie() {
|
|
312
|
-
if (ABORT) return;
|
|
313
|
-
var max = _emscripten_stack_get_end();
|
|
314
|
-
// See writeStackCookie().
|
|
315
|
-
if (max == 0) {
|
|
316
|
-
max += 4;
|
|
317
|
-
}
|
|
318
|
-
var cookie1 = HEAPU32[((max)>>2)];
|
|
319
|
-
var cookie2 = HEAPU32[(((max)+(4))>>2)];
|
|
320
|
-
if (cookie1 != 0x02135467 || cookie2 != 0x89BACDFE) {
|
|
321
|
-
abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`);
|
|
322
|
-
}
|
|
323
|
-
// Also test the global address 0 for integrity.
|
|
324
|
-
if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) {
|
|
325
|
-
abort('Runtime error: The application has corrupted its heap memory area (address zero)!');
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
// end include: runtime_stack_check.js
|
|
329
296
|
// include: runtime_exceptions.js
|
|
297
|
+
// Base Emscripten EH error class
|
|
298
|
+
class EmscriptenEH {}
|
|
299
|
+
|
|
300
|
+
class EmscriptenSjLj extends EmscriptenEH {}
|
|
301
|
+
|
|
330
302
|
// end include: runtime_exceptions.js
|
|
331
303
|
// include: runtime_debug.js
|
|
332
304
|
var runtimeDebug = true; // Switch to false at runtime to disable logging at the right times
|
|
@@ -348,15 +320,31 @@ function dbg(...args) {
|
|
|
348
320
|
})();
|
|
349
321
|
|
|
350
322
|
function consumedModuleProp(prop) {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
323
|
+
var value = Module[prop];
|
|
324
|
+
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'`;
|
|
325
|
+
if (Array.isArray(value)) {
|
|
326
|
+
value = new Proxy(value, {
|
|
327
|
+
set(target, key, val) {
|
|
328
|
+
abort(msg);
|
|
329
|
+
return false;
|
|
330
|
+
},
|
|
331
|
+
defineProperty(target, key, descriptor) {
|
|
332
|
+
abort(msg);
|
|
333
|
+
return false;
|
|
334
|
+
},
|
|
335
|
+
deleteProperty(target, key) {
|
|
336
|
+
abort(msg);
|
|
337
|
+
return false;
|
|
357
338
|
}
|
|
358
339
|
});
|
|
359
340
|
}
|
|
341
|
+
Object.defineProperty(Module, prop, {
|
|
342
|
+
configurable: true,
|
|
343
|
+
get() { return value; },
|
|
344
|
+
set() {
|
|
345
|
+
abort(msg);
|
|
346
|
+
}
|
|
347
|
+
});
|
|
360
348
|
}
|
|
361
349
|
|
|
362
350
|
function makeInvalidEarlyAccess(name) {
|
|
@@ -453,32 +441,52 @@ function unexportedRuntimeSymbol(sym) {
|
|
|
453
441
|
}
|
|
454
442
|
|
|
455
443
|
// end include: runtime_debug.js
|
|
444
|
+
// include: runtime_stack_check.js
|
|
445
|
+
const stackCookie1 = 0x02135467;
|
|
446
|
+
const stackCookie2 = 0x89BACDFE;
|
|
447
|
+
|
|
448
|
+
// Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
|
|
449
|
+
function writeStackCookie() {
|
|
450
|
+
var max = _emscripten_stack_get_end();
|
|
451
|
+
assert((max & 3) == 0);
|
|
452
|
+
// If the stack ends at address zero we write our cookies 4 bytes into the
|
|
453
|
+
// stack. This prevents interference with SAFE_HEAP and ASAN which also
|
|
454
|
+
// monitor writes to address zero.
|
|
455
|
+
if (max == 0) {
|
|
456
|
+
max += 4;
|
|
457
|
+
}
|
|
458
|
+
// The stack grow downwards towards _emscripten_stack_get_end.
|
|
459
|
+
// We write cookies to the final two words in the stack and detect if they are
|
|
460
|
+
// ever overwritten.
|
|
461
|
+
HEAPU32[((max)>>2)] = stackCookie1;
|
|
462
|
+
HEAPU32[(((max)+(4))>>2)] = stackCookie2;
|
|
463
|
+
// Also test the global address 0 for integrity.
|
|
464
|
+
HEAPU32[((0)>>2)] = 1668509029;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function u32ToHexString(num) {
|
|
468
|
+
return '0x' + (num >>> 0).toString(16).padStart(8, '0');
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
function checkStackCookie() {
|
|
472
|
+
if (ABORT) return;
|
|
473
|
+
var max = _emscripten_stack_get_end();
|
|
474
|
+
// See writeStackCookie().
|
|
475
|
+
if (max == 0) {
|
|
476
|
+
max += 4;
|
|
477
|
+
}
|
|
478
|
+
var val1 = HEAPU32[((max)>>2)];
|
|
479
|
+
var val2 = HEAPU32[(((max)+(4))>>2)];
|
|
480
|
+
if (val1 != stackCookie1 || val2 != stackCookie2) {
|
|
481
|
+
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)}`);
|
|
482
|
+
}
|
|
483
|
+
// Also test the global address 0 for integrity.
|
|
484
|
+
if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) {
|
|
485
|
+
abort('Runtime error: The application has corrupted its heap memory area (address zero)!');
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
// end include: runtime_stack_check.js
|
|
456
489
|
// Memory management
|
|
457
|
-
var
|
|
458
|
-
/** @type {!Int8Array} */
|
|
459
|
-
HEAP8,
|
|
460
|
-
/** @type {!Uint8Array} */
|
|
461
|
-
HEAPU8,
|
|
462
|
-
/** @type {!Int16Array} */
|
|
463
|
-
HEAP16,
|
|
464
|
-
/** @type {!Uint16Array} */
|
|
465
|
-
HEAPU16,
|
|
466
|
-
/** @type {!Int32Array} */
|
|
467
|
-
HEAP32,
|
|
468
|
-
/** @type {!Uint32Array} */
|
|
469
|
-
HEAPU32,
|
|
470
|
-
/** @type {!Float32Array} */
|
|
471
|
-
HEAPF32,
|
|
472
|
-
/** @type {!Float64Array} */
|
|
473
|
-
HEAPF64;
|
|
474
|
-
|
|
475
|
-
// BigInt64Array type is not correctly defined in closure
|
|
476
|
-
var
|
|
477
|
-
/** not-@type {!BigInt64Array} */
|
|
478
|
-
HEAP64,
|
|
479
|
-
/* BigUint64Array type is not correctly defined in closure
|
|
480
|
-
/** not-@type {!BigUint64Array} */
|
|
481
|
-
HEAPU64;
|
|
482
490
|
|
|
483
491
|
var runtimeInitialized = false;
|
|
484
492
|
|
|
@@ -486,8 +494,17 @@ var runtimeExited = false;
|
|
|
486
494
|
|
|
487
495
|
|
|
488
496
|
|
|
497
|
+
// When ALLOW_MEMORY_GROWTH is enabled, the conversion from Wasm
|
|
498
|
+
// memory to ArrayBuffer requires some additional logic.
|
|
499
|
+
function getMemoryBuffer() {
|
|
500
|
+
return wasmMemory.buffer;
|
|
501
|
+
}
|
|
502
|
+
|
|
489
503
|
function updateMemoryViews() {
|
|
490
|
-
|
|
504
|
+
// If we already have a heap that is resizeable/growable buffer we don't
|
|
505
|
+
// need to do anything in updateMemoryViews.
|
|
506
|
+
if (HEAP8?.buffer?.resizable) return;
|
|
507
|
+
var b = getMemoryBuffer();
|
|
491
508
|
HEAP8 = new Int8Array(b);
|
|
492
509
|
HEAP16 = new Int16Array(b);
|
|
493
510
|
HEAPU8 = new Uint8Array(b);
|
|
@@ -507,11 +524,10 @@ assert(globalThis.Int32Array && globalThis.Float64Array && Int32Array.prototype.
|
|
|
507
524
|
'JS engine does not provide full typed array support');
|
|
508
525
|
|
|
509
526
|
function preRun() {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
}
|
|
527
|
+
var preRun = Module['preRun'];
|
|
528
|
+
if (preRun) {
|
|
529
|
+
if (typeof preRun == 'function') preRun = [preRun];
|
|
530
|
+
onPreRuns.push(...preRun);
|
|
515
531
|
}
|
|
516
532
|
consumedModuleProp('preRun');
|
|
517
533
|
// Begin ATPRERUNS hooks
|
|
@@ -535,17 +551,17 @@ TTY.init();
|
|
|
535
551
|
// Begin ATPOSTCTORS hooks
|
|
536
552
|
FS.ignorePermissions = false;
|
|
537
553
|
// End ATPOSTCTORS hooks
|
|
538
|
-
}
|
|
539
554
|
|
|
540
|
-
function preMain() {
|
|
541
555
|
checkStackCookie();
|
|
542
|
-
// No ATMAINS hooks
|
|
543
556
|
}
|
|
544
557
|
|
|
558
|
+
var runtimeExiting = false;
|
|
559
|
+
|
|
545
560
|
function exitRuntime() {
|
|
546
561
|
assert(!runtimeExited);
|
|
562
|
+
assert(!runtimeExiting, 'Re-entrant call to exitRuntime()! This can happen if an atexit() registered callback throws an exception.');
|
|
563
|
+
runtimeExiting = true;
|
|
547
564
|
checkStackCookie();
|
|
548
|
-
// PThreads reuse the runtime from the main thread.
|
|
549
565
|
___funcs_on_exit(); // Native atexit() functions
|
|
550
566
|
// Begin ATEXITS hooks
|
|
551
567
|
FS.quit();
|
|
@@ -556,13 +572,11 @@ TTY.shutdown();
|
|
|
556
572
|
|
|
557
573
|
function postRun() {
|
|
558
574
|
checkStackCookie();
|
|
559
|
-
// PThreads reuse the runtime from the main thread.
|
|
560
575
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
}
|
|
576
|
+
var postRun = Module['postRun'];
|
|
577
|
+
if (postRun) {
|
|
578
|
+
if (typeof postRun == 'function') postRun = [postRun];
|
|
579
|
+
onPostRuns.push(...postRun);
|
|
566
580
|
}
|
|
567
581
|
consumedModuleProp('postRun');
|
|
568
582
|
|
|
@@ -571,11 +585,13 @@ function postRun() {
|
|
|
571
585
|
// End ATPOSTRUNS hooks
|
|
572
586
|
}
|
|
573
587
|
|
|
574
|
-
/**
|
|
588
|
+
/**
|
|
589
|
+
* @param {string|number=} what
|
|
590
|
+
*/
|
|
575
591
|
function abort(what) {
|
|
576
592
|
Module['onAbort']?.(what);
|
|
577
593
|
|
|
578
|
-
what =
|
|
594
|
+
what = `Aborted(${what})`;
|
|
579
595
|
// TODO(sbc): Should we remove printing and leave it up to whoever
|
|
580
596
|
// catches the exception?
|
|
581
597
|
err(what);
|
|
@@ -604,15 +620,14 @@ function abort(what) {
|
|
|
604
620
|
throw e;
|
|
605
621
|
}
|
|
606
622
|
|
|
607
|
-
function createExportWrapper(name, nargs) {
|
|
623
|
+
function createExportWrapper(name, func, nargs) {
|
|
624
|
+
assert(func);
|
|
608
625
|
return (...args) => {
|
|
609
626
|
assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`);
|
|
610
627
|
assert(!runtimeExited, `native function \`${name}\` called after runtime exit (use NO_EXIT_RUNTIME to keep it alive after main() exits)`);
|
|
611
|
-
var f = wasmExports[name];
|
|
612
|
-
assert(f, `exported native function \`${name}\` not found`);
|
|
613
628
|
// Only assert for too many arguments. Too few can be valid since the missing arguments will be zero filled.
|
|
614
629
|
assert(args.length <= nargs, `native function \`${name}\` called with ${args.length} args but expects ${nargs}`);
|
|
615
|
-
return
|
|
630
|
+
return func(...args);
|
|
616
631
|
};
|
|
617
632
|
}
|
|
618
633
|
|
|
@@ -623,9 +638,6 @@ function findWasmBinary() {
|
|
|
623
638
|
}
|
|
624
639
|
|
|
625
640
|
function getBinarySync(file) {
|
|
626
|
-
if (file == wasmBinaryFile && wasmBinary) {
|
|
627
|
-
return new Uint8Array(wasmBinary);
|
|
628
|
-
}
|
|
629
641
|
if (readBinary) {
|
|
630
642
|
return readBinary(file);
|
|
631
643
|
}
|
|
@@ -708,18 +720,15 @@ async function createWasm() {
|
|
|
708
720
|
// Load the wasm module and create an instance of using native support in the JS engine.
|
|
709
721
|
// handle a generated wasm instance, receiving its exports and
|
|
710
722
|
// performing other necessary setup
|
|
711
|
-
|
|
712
|
-
function receiveInstance(instance, module) {
|
|
723
|
+
function receiveInstance(instance) {
|
|
713
724
|
wasmExports = instance.exports;
|
|
714
725
|
|
|
715
726
|
assignWasmExports(wasmExports);
|
|
716
727
|
|
|
717
728
|
updateMemoryViews();
|
|
718
729
|
|
|
719
|
-
removeRunDependency('wasm-instantiate');
|
|
720
730
|
return wasmExports;
|
|
721
731
|
}
|
|
722
|
-
addRunDependency('wasm-instantiate');
|
|
723
732
|
|
|
724
733
|
// Prefer streaming instantiation if available.
|
|
725
734
|
// Async compilation can be confusing when an error on the page overwrites Module
|
|
@@ -744,15 +753,14 @@ async function createWasm() {
|
|
|
744
753
|
// performing.
|
|
745
754
|
// Also pthreads and wasm workers initialize the wasm instance through this
|
|
746
755
|
// path.
|
|
747
|
-
|
|
748
|
-
|
|
756
|
+
var instantiateWasm = Module['instantiateWasm'];
|
|
757
|
+
if (instantiateWasm) {
|
|
758
|
+
return new Promise((resolve) => {
|
|
749
759
|
try {
|
|
750
|
-
|
|
751
|
-
resolve(receiveInstance(inst, mod));
|
|
752
|
-
});
|
|
760
|
+
instantiateWasm(info, (inst) => resolve(receiveInstance(inst)));
|
|
753
761
|
} catch(e) {
|
|
754
762
|
err(`Module.instantiateWasm callback failed with error: ${e}`);
|
|
755
|
-
|
|
763
|
+
throw e;
|
|
756
764
|
}
|
|
757
765
|
});
|
|
758
766
|
}
|
|
@@ -776,6 +784,36 @@ async function createWasm() {
|
|
|
776
784
|
}
|
|
777
785
|
}
|
|
778
786
|
|
|
787
|
+
/** @type {!Int16Array} */
|
|
788
|
+
var HEAP16;
|
|
789
|
+
|
|
790
|
+
/** @type {!Int32Array} */
|
|
791
|
+
var HEAP32;
|
|
792
|
+
|
|
793
|
+
/** not-@type {!BigInt64Array} */
|
|
794
|
+
var HEAP64;
|
|
795
|
+
|
|
796
|
+
/** @type {!Int8Array} */
|
|
797
|
+
var HEAP8;
|
|
798
|
+
|
|
799
|
+
/** @type {!Float32Array} */
|
|
800
|
+
var HEAPF32;
|
|
801
|
+
|
|
802
|
+
/** @type {!Float64Array} */
|
|
803
|
+
var HEAPF64;
|
|
804
|
+
|
|
805
|
+
/** @type {!Uint16Array} */
|
|
806
|
+
var HEAPU16;
|
|
807
|
+
|
|
808
|
+
/** @type {!Uint32Array} */
|
|
809
|
+
var HEAPU32;
|
|
810
|
+
|
|
811
|
+
/** not-@type {!BigUint64Array} */
|
|
812
|
+
var HEAPU64;
|
|
813
|
+
|
|
814
|
+
/** @type {!Uint8Array} */
|
|
815
|
+
var HEAPU8;
|
|
816
|
+
|
|
779
817
|
var callRuntimeCallbacks = (callbacks) => {
|
|
780
818
|
while (callbacks.length > 0) {
|
|
781
819
|
// Pass the module as the first argument.
|
|
@@ -788,71 +826,6 @@ async function createWasm() {
|
|
|
788
826
|
var onPreRuns = [];
|
|
789
827
|
var addOnPreRun = (cb) => onPreRuns.push(cb);
|
|
790
828
|
|
|
791
|
-
var runDependencies = 0;
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
var dependenciesFulfilled = null;
|
|
795
|
-
|
|
796
|
-
var runDependencyTracking = {
|
|
797
|
-
};
|
|
798
|
-
|
|
799
|
-
var runDependencyWatcher = null;
|
|
800
|
-
var removeRunDependency = (id) => {
|
|
801
|
-
runDependencies--;
|
|
802
|
-
|
|
803
|
-
Module['monitorRunDependencies']?.(runDependencies);
|
|
804
|
-
|
|
805
|
-
assert(id, 'removeRunDependency requires an ID');
|
|
806
|
-
assert(runDependencyTracking[id]);
|
|
807
|
-
delete runDependencyTracking[id];
|
|
808
|
-
if (runDependencies == 0) {
|
|
809
|
-
if (runDependencyWatcher !== null) {
|
|
810
|
-
clearInterval(runDependencyWatcher);
|
|
811
|
-
runDependencyWatcher = null;
|
|
812
|
-
}
|
|
813
|
-
if (dependenciesFulfilled) {
|
|
814
|
-
var callback = dependenciesFulfilled;
|
|
815
|
-
dependenciesFulfilled = null;
|
|
816
|
-
callback(); // can add another dependenciesFulfilled
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
};
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
var addRunDependency = (id) => {
|
|
823
|
-
runDependencies++;
|
|
824
|
-
|
|
825
|
-
Module['monitorRunDependencies']?.(runDependencies);
|
|
826
|
-
|
|
827
|
-
assert(id, 'addRunDependency requires an ID')
|
|
828
|
-
assert(!runDependencyTracking[id]);
|
|
829
|
-
runDependencyTracking[id] = 1;
|
|
830
|
-
if (runDependencyWatcher === null && globalThis.setInterval) {
|
|
831
|
-
// Check for missing dependencies every few seconds
|
|
832
|
-
runDependencyWatcher = setInterval(() => {
|
|
833
|
-
if (ABORT) {
|
|
834
|
-
clearInterval(runDependencyWatcher);
|
|
835
|
-
runDependencyWatcher = null;
|
|
836
|
-
return;
|
|
837
|
-
}
|
|
838
|
-
var shown = false;
|
|
839
|
-
for (var dep in runDependencyTracking) {
|
|
840
|
-
if (!shown) {
|
|
841
|
-
shown = true;
|
|
842
|
-
err('still waiting on run dependencies:');
|
|
843
|
-
}
|
|
844
|
-
err(`dependency: ${dep}`);
|
|
845
|
-
}
|
|
846
|
-
if (shown) {
|
|
847
|
-
err('(end of list)');
|
|
848
|
-
}
|
|
849
|
-
}, 10000);
|
|
850
|
-
// Prevent this timer from keeping the runtime alive if nothing
|
|
851
|
-
// else is.
|
|
852
|
-
runDependencyWatcher.unref?.()
|
|
853
|
-
}
|
|
854
|
-
};
|
|
855
|
-
|
|
856
829
|
|
|
857
830
|
|
|
858
831
|
/**
|
|
@@ -876,13 +849,12 @@ async function createWasm() {
|
|
|
876
849
|
|
|
877
850
|
var noExitRuntime = false;
|
|
878
851
|
|
|
879
|
-
|
|
852
|
+
function ptrToString(ptr) {
|
|
880
853
|
assert(typeof ptr === 'number', `ptrToString expects a number, got ${typeof ptr}`);
|
|
881
854
|
// Convert to 32-bit unsigned value
|
|
882
855
|
ptr >>>= 0;
|
|
883
856
|
return '0x' + ptr.toString(16).padStart(8, '0');
|
|
884
|
-
}
|
|
885
|
-
|
|
857
|
+
}
|
|
886
858
|
|
|
887
859
|
|
|
888
860
|
/**
|
|
@@ -922,6 +894,14 @@ async function createWasm() {
|
|
|
922
894
|
|
|
923
895
|
var UTF8Decoder = globalThis.TextDecoder && new TextDecoder();
|
|
924
896
|
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
* heapOrArray is either a regular array, or a JavaScript typed array view.
|
|
900
|
+
* @param {number} idx
|
|
901
|
+
* @param {number=} maxBytesToRead
|
|
902
|
+
* @param {boolean=} ignoreNul
|
|
903
|
+
* @return {number}
|
|
904
|
+
*/
|
|
925
905
|
var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => {
|
|
926
906
|
var maxIdx = idx + maxBytesToRead;
|
|
927
907
|
if (ignoreNul) return maxIdx;
|
|
@@ -966,7 +946,7 @@ async function createWasm() {
|
|
|
966
946
|
if ((u0 & 0xF0) == 0xE0) {
|
|
967
947
|
u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
|
|
968
948
|
} else {
|
|
969
|
-
if ((u0 & 0xF8) != 0xF0) warnOnce(
|
|
949
|
+
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!`);
|
|
970
950
|
u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
|
|
971
951
|
}
|
|
972
952
|
|
|
@@ -1024,15 +1004,12 @@ async function createWasm() {
|
|
|
1024
1004
|
// This block is not needed on v19+ since crypto.getRandomValues is builtin
|
|
1025
1005
|
if (ENVIRONMENT_IS_NODE) {
|
|
1026
1006
|
var nodeCrypto = require('node:crypto');
|
|
1027
|
-
return (view) => nodeCrypto.randomFillSync(view);
|
|
1007
|
+
return (view) => (nodeCrypto.randomFillSync(view), 0);
|
|
1028
1008
|
}
|
|
1029
1009
|
|
|
1030
|
-
return (view) => crypto.getRandomValues(view);
|
|
1031
|
-
};
|
|
1032
|
-
var randomFill = (view) => {
|
|
1033
|
-
// Lazily init on the first invocation.
|
|
1034
|
-
(randomFill = initRandomFill())(view);
|
|
1010
|
+
return (view) => (crypto.getRandomValues(view), 0);
|
|
1035
1011
|
};
|
|
1012
|
+
var randomFill = (view) => (randomFill = initRandomFill())(view);
|
|
1036
1013
|
|
|
1037
1014
|
|
|
1038
1015
|
|
|
@@ -1098,7 +1075,7 @@ async function createWasm() {
|
|
|
1098
1075
|
heap[outIdx++] = 0x80 | (u & 63);
|
|
1099
1076
|
} else {
|
|
1100
1077
|
if (outIdx + 3 >= endIdx) break;
|
|
1101
|
-
if (u > 0x10FFFF) warnOnce(
|
|
1078
|
+
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).`);
|
|
1102
1079
|
heap[outIdx++] = 0xF0 | (u >> 18);
|
|
1103
1080
|
heap[outIdx++] = 0x80 | ((u >> 12) & 63);
|
|
1104
1081
|
heap[outIdx++] = 0x80 | ((u >> 6) & 63);
|
|
@@ -1313,7 +1290,7 @@ async function createWasm() {
|
|
|
1313
1290
|
var zeroMemory = (ptr, size) => HEAPU8.fill(0, ptr, ptr + size);
|
|
1314
1291
|
|
|
1315
1292
|
var alignMemory = (size, alignment) => {
|
|
1316
|
-
assert(alignment,
|
|
1293
|
+
assert(alignment, 'alignment argument is required');
|
|
1317
1294
|
return Math.ceil(size / alignment) * alignment;
|
|
1318
1295
|
};
|
|
1319
1296
|
var mmapAlloc = (size) => {
|
|
@@ -1386,11 +1363,14 @@ async function createWasm() {
|
|
|
1386
1363
|
} else if (FS.isFile(node.mode)) {
|
|
1387
1364
|
node.node_ops = MEMFS.ops_table.file.node;
|
|
1388
1365
|
node.stream_ops = MEMFS.ops_table.file.stream;
|
|
1389
|
-
|
|
1390
|
-
//
|
|
1391
|
-
|
|
1392
|
-
//
|
|
1393
|
-
|
|
1366
|
+
// The actual number of bytes used in the typed array, as opposed to
|
|
1367
|
+
// contents.length which gives the whole capacity.
|
|
1368
|
+
node.usedBytes = 0;
|
|
1369
|
+
// The byte data of the file is stored in a typed array.
|
|
1370
|
+
// Note: typed arrays are not resizable like normal JS arrays are, so
|
|
1371
|
+
// there is a small penalty involved for appending file writes that
|
|
1372
|
+
// continuously grow a file similar to std::vector capacity vs used.
|
|
1373
|
+
node.contents = MEMFS.emptyFileContents ??= new Uint8Array(0);
|
|
1394
1374
|
} else if (FS.isLink(node.mode)) {
|
|
1395
1375
|
node.node_ops = MEMFS.ops_table.link.node;
|
|
1396
1376
|
node.stream_ops = MEMFS.ops_table.link.stream;
|
|
@@ -1407,36 +1387,30 @@ async function createWasm() {
|
|
|
1407
1387
|
return node;
|
|
1408
1388
|
},
|
|
1409
1389
|
getFileDataAsTypedArray(node) {
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
return new Uint8Array(node.contents);
|
|
1390
|
+
assert(FS.isFile(node.mode), 'getFileDataAsTypedArray called on non-file');
|
|
1391
|
+
return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes.
|
|
1413
1392
|
},
|
|
1414
1393
|
expandFileStorage(node, newCapacity) {
|
|
1415
|
-
var prevCapacity = node.contents
|
|
1394
|
+
var prevCapacity = node.contents.length;
|
|
1416
1395
|
if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough.
|
|
1417
|
-
// Don't expand strictly to the given requested limit if it's only a very
|
|
1418
|
-
//
|
|
1419
|
-
//
|
|
1396
|
+
// Don't expand strictly to the given requested limit if it's only a very
|
|
1397
|
+
// small increase, but instead geometrically grow capacity.
|
|
1398
|
+
// For small filesizes (<1MB), perform size*2 geometric increase, but for
|
|
1399
|
+
// large sizes, do a much more conservative size*1.125 increase to avoid
|
|
1400
|
+
// overshooting the allocation cap by a very large margin.
|
|
1420
1401
|
var CAPACITY_DOUBLING_MAX = 1024 * 1024;
|
|
1421
1402
|
newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0);
|
|
1422
|
-
if (prevCapacity
|
|
1423
|
-
var oldContents = node
|
|
1403
|
+
if (prevCapacity) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.
|
|
1404
|
+
var oldContents = MEMFS.getFileDataAsTypedArray(node);
|
|
1424
1405
|
node.contents = new Uint8Array(newCapacity); // Allocate new storage.
|
|
1425
|
-
|
|
1406
|
+
node.contents.set(oldContents);
|
|
1426
1407
|
},
|
|
1427
1408
|
resizeFileStorage(node, newSize) {
|
|
1428
1409
|
if (node.usedBytes == newSize) return;
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
var oldContents = node.contents;
|
|
1434
|
-
node.contents = new Uint8Array(newSize); // Allocate new storage.
|
|
1435
|
-
if (oldContents) {
|
|
1436
|
-
node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage.
|
|
1437
|
-
}
|
|
1438
|
-
node.usedBytes = newSize;
|
|
1439
|
-
}
|
|
1410
|
+
var oldContents = node.contents;
|
|
1411
|
+
node.contents = new Uint8Array(newSize); // Allocate new storage.
|
|
1412
|
+
node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage.
|
|
1413
|
+
node.usedBytes = newSize;
|
|
1440
1414
|
},
|
|
1441
1415
|
node_ops:{
|
|
1442
1416
|
getattr(node) {
|
|
@@ -1536,16 +1510,11 @@ async function createWasm() {
|
|
|
1536
1510
|
if (position >= stream.node.usedBytes) return 0;
|
|
1537
1511
|
var size = Math.min(stream.node.usedBytes - position, length);
|
|
1538
1512
|
assert(size >= 0);
|
|
1539
|
-
|
|
1540
|
-
buffer.set(contents.subarray(position, position + size), offset);
|
|
1541
|
-
} else {
|
|
1542
|
-
for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
|
|
1543
|
-
}
|
|
1513
|
+
buffer.set(contents.subarray(position, position + size), offset);
|
|
1544
1514
|
return size;
|
|
1545
1515
|
},
|
|
1546
1516
|
write(stream, buffer, offset, length, position, canOwn) {
|
|
1547
|
-
|
|
1548
|
-
assert(!(buffer instanceof ArrayBuffer));
|
|
1517
|
+
assert(buffer.subarray, 'FS.write expects a TypedArray');
|
|
1549
1518
|
// If the buffer is located in main memory (HEAP), and if
|
|
1550
1519
|
// memory can grow, we can't hold on to references of the
|
|
1551
1520
|
// memory buffer, as they may get invalidated. That means we
|
|
@@ -1558,33 +1527,19 @@ async function createWasm() {
|
|
|
1558
1527
|
var node = stream.node;
|
|
1559
1528
|
node.mtime = node.ctime = Date.now();
|
|
1560
1529
|
|
|
1561
|
-
if (
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
return length;
|
|
1571
|
-
} else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file?
|
|
1572
|
-
node.contents.set(buffer.subarray(offset, offset + length), position);
|
|
1573
|
-
return length;
|
|
1574
|
-
}
|
|
1575
|
-
}
|
|
1576
|
-
|
|
1577
|
-
// Appending to an existing file and we need to reallocate, or source data did not come as a typed array.
|
|
1578
|
-
MEMFS.expandFileStorage(node, position+length);
|
|
1579
|
-
if (node.contents.subarray && buffer.subarray) {
|
|
1530
|
+
if (canOwn) {
|
|
1531
|
+
assert(position === 0, 'canOwn must imply no weird position inside the file');
|
|
1532
|
+
node.contents = buffer.subarray(offset, offset + length);
|
|
1533
|
+
node.usedBytes = length;
|
|
1534
|
+
} 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.
|
|
1535
|
+
node.contents = buffer.slice(offset, offset + length);
|
|
1536
|
+
node.usedBytes = length;
|
|
1537
|
+
} else {
|
|
1538
|
+
MEMFS.expandFileStorage(node, position+length);
|
|
1580
1539
|
// Use typed array write which is available.
|
|
1581
1540
|
node.contents.set(buffer.subarray(offset, offset + length), position);
|
|
1582
|
-
|
|
1583
|
-
for (var i = 0; i < length; i++) {
|
|
1584
|
-
node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not.
|
|
1585
|
-
}
|
|
1541
|
+
node.usedBytes = Math.max(node.usedBytes, position + length);
|
|
1586
1542
|
}
|
|
1587
|
-
node.usedBytes = Math.max(node.usedBytes, position + length);
|
|
1588
1543
|
return length;
|
|
1589
1544
|
},
|
|
1590
1545
|
llseek(stream, offset, whence) {
|
|
@@ -1609,7 +1564,7 @@ async function createWasm() {
|
|
|
1609
1564
|
var allocated;
|
|
1610
1565
|
var contents = stream.node.contents;
|
|
1611
1566
|
// Only make a new copy when MAP_PRIVATE is specified.
|
|
1612
|
-
if (!(flags & 2) && contents
|
|
1567
|
+
if (!(flags & 2) && contents.buffer === HEAP8.buffer) {
|
|
1613
1568
|
// We can't emulate MAP_SHARED when the file is not backed by the
|
|
1614
1569
|
// buffer we're mapping to (e.g. the HEAP buffer).
|
|
1615
1570
|
allocated = false;
|
|
@@ -1643,6 +1598,7 @@ async function createWasm() {
|
|
|
1643
1598
|
};
|
|
1644
1599
|
|
|
1645
1600
|
var FS_modeStringToFlags = (str) => {
|
|
1601
|
+
if (typeof str != 'string') return str;
|
|
1646
1602
|
var flagModes = {
|
|
1647
1603
|
'r': 0,
|
|
1648
1604
|
'r+': 2,
|
|
@@ -1658,6 +1614,16 @@ async function createWasm() {
|
|
|
1658
1614
|
return flags;
|
|
1659
1615
|
};
|
|
1660
1616
|
|
|
1617
|
+
var FS_fileDataToTypedArray = (data) => {
|
|
1618
|
+
if (typeof data == 'string') {
|
|
1619
|
+
data = intArrayFromString(data, true);
|
|
1620
|
+
}
|
|
1621
|
+
if (!data.subarray) {
|
|
1622
|
+
data = new Uint8Array(data);
|
|
1623
|
+
}
|
|
1624
|
+
return data;
|
|
1625
|
+
};
|
|
1626
|
+
|
|
1661
1627
|
var FS_getMode = (canRead, canWrite) => {
|
|
1662
1628
|
var mode = 0;
|
|
1663
1629
|
if (canRead) mode |= 292 | 73;
|
|
@@ -1951,7 +1917,11 @@ async function createWasm() {
|
|
|
1951
1917
|
if (attr.mode != null && attr.dontFollow) {
|
|
1952
1918
|
throw new FS.ErrnoError(52);
|
|
1953
1919
|
}
|
|
1954
|
-
|
|
1920
|
+
// `dontFollow` (AT_SYMLINK_NOFOLLOW): use lutimes so the symlink's own
|
|
1921
|
+
// timestamps are set without the host resolving it, which would
|
|
1922
|
+
// otherwise escape the NODEFS mount root.
|
|
1923
|
+
var utimes = attr.dontFollow ? fs.lutimesSync : fs.utimesSync;
|
|
1924
|
+
NODEFS.setattr(path, node, attr, fs.chmodSync, utimes, fs.truncateSync, fs.lstatSync);
|
|
1955
1925
|
},
|
|
1956
1926
|
lookup(parent, name) {
|
|
1957
1927
|
var path = PATH.join2(NODEFS.realPath(parent), name);
|
|
@@ -2083,6 +2053,70 @@ async function createWasm() {
|
|
|
2083
2053
|
|
|
2084
2054
|
|
|
2085
2055
|
|
|
2056
|
+
|
|
2057
|
+
var NODERAWFS_stream_funcs = {
|
|
2058
|
+
close(stream) {
|
|
2059
|
+
VFS.closeStream(stream.fd);
|
|
2060
|
+
// Don't close stdin/stdout/stderr since they are used by node itself.
|
|
2061
|
+
if (--stream.shared.refcnt <= 0 && stream.nfd > 2) {
|
|
2062
|
+
// This stream is created by our Node.js filesystem, close the
|
|
2063
|
+
// native file descriptor when its reference count drops to 0.
|
|
2064
|
+
fs.closeSync(stream.nfd);
|
|
2065
|
+
}
|
|
2066
|
+
},
|
|
2067
|
+
llseek(stream, offset, whence) {
|
|
2068
|
+
var position = offset;
|
|
2069
|
+
if (whence === 1) {
|
|
2070
|
+
position += stream.position;
|
|
2071
|
+
} else if (whence === 2) {
|
|
2072
|
+
position += fs.fstatSync(stream.nfd).size;
|
|
2073
|
+
} else if (whence !== 0) {
|
|
2074
|
+
throw new FS.ErrnoError(28);
|
|
2075
|
+
}
|
|
2076
|
+
|
|
2077
|
+
if (position < 0) {
|
|
2078
|
+
throw new FS.ErrnoError(28);
|
|
2079
|
+
}
|
|
2080
|
+
stream.position = position;
|
|
2081
|
+
return position;
|
|
2082
|
+
},
|
|
2083
|
+
read(stream, buffer, offset, length, position) {
|
|
2084
|
+
var seeking = typeof position != 'undefined';
|
|
2085
|
+
if (!seeking && stream.seekable) position = stream.position;
|
|
2086
|
+
var bytesRead = fs.readSync(stream.nfd, buffer, offset, length, position);
|
|
2087
|
+
// update position marker when non-seeking
|
|
2088
|
+
if (!seeking) stream.position += bytesRead;
|
|
2089
|
+
return bytesRead;
|
|
2090
|
+
},
|
|
2091
|
+
write(stream, buffer, offset, length, position) {
|
|
2092
|
+
if (stream.flags & 1024) {
|
|
2093
|
+
// seek to the end before writing in append mode
|
|
2094
|
+
FS.llseek(stream, 0, 2);
|
|
2095
|
+
}
|
|
2096
|
+
var seeking = typeof position != 'undefined';
|
|
2097
|
+
if (!seeking && stream.seekable) position = stream.position;
|
|
2098
|
+
var bytesWritten = fs.writeSync(stream.nfd, buffer, offset, length, position);
|
|
2099
|
+
// update position marker when non-seeking
|
|
2100
|
+
if (!seeking) stream.position += bytesWritten;
|
|
2101
|
+
return bytesWritten;
|
|
2102
|
+
},
|
|
2103
|
+
mmap(stream, length, position, prot, flags) {
|
|
2104
|
+
if (!length) {
|
|
2105
|
+
throw new FS.ErrnoError(28);
|
|
2106
|
+
}
|
|
2107
|
+
var ptr = mmapAlloc(length);
|
|
2108
|
+
FS.read(stream, HEAP8, ptr, length, position);
|
|
2109
|
+
return { ptr, allocated: true };
|
|
2110
|
+
},
|
|
2111
|
+
msync(stream, buffer, offset, length, mmapFlags) {
|
|
2112
|
+
FS.write(stream, buffer, 0, length, offset);
|
|
2113
|
+
// should we check if bytesWritten and length are the same?
|
|
2114
|
+
return 0;
|
|
2115
|
+
},
|
|
2116
|
+
ioctl(stream, cmd, arg) {
|
|
2117
|
+
throw new FS.ErrnoError(59);
|
|
2118
|
+
},
|
|
2119
|
+
};
|
|
2086
2120
|
var NODERAWFS = {
|
|
2087
2121
|
lookup(parent, name) {
|
|
2088
2122
|
assert(parent)
|
|
@@ -2098,11 +2132,10 @@ async function createWasm() {
|
|
|
2098
2132
|
return { path, node: { id: st.ino, mode, node_ops: NODERAWFS, path }};
|
|
2099
2133
|
},
|
|
2100
2134
|
createStandardStreams() {
|
|
2101
|
-
|
|
2102
|
-
FS.createStream({ nfd: 0, position: 0, path: '/dev/stdin', flags: 0, tty: true, seekable: false }, 0);
|
|
2135
|
+
FS.createStream({ nfd: 0, position: 0, path: '/dev/stdin', flags: 0, seekable: false }, 0);
|
|
2103
2136
|
var paths = [,'/dev/stdout', '/dev/stderr'];
|
|
2104
2137
|
for (var i = 1; i < 3; i++) {
|
|
2105
|
-
FS.createStream({ nfd: i, position: 0, path: paths[i], flags: 577,
|
|
2138
|
+
FS.createStream({ nfd: i, position: 0, path: paths[i], flags: 577, seekable: false }, i);
|
|
2106
2139
|
}
|
|
2107
2140
|
},
|
|
2108
2141
|
cwd() { return process.cwd(); },
|
|
@@ -2116,6 +2149,14 @@ async function createWasm() {
|
|
|
2116
2149
|
},
|
|
2117
2150
|
mkdir(...args) { fs.mkdirSync(...args); },
|
|
2118
2151
|
symlink(...args) { fs.symlinkSync(...args); },
|
|
2152
|
+
link(oldpath, newpath, flags) {
|
|
2153
|
+
// AT_SYMLINK_FOLLOW (0x400): dereference oldpath if it is a symlink,
|
|
2154
|
+
// since node's link(2) links to the symlink itself by default.
|
|
2155
|
+
if (flags & 0x400) {
|
|
2156
|
+
oldpath = fs.realpathSync(oldpath);
|
|
2157
|
+
}
|
|
2158
|
+
fs.linkSync(oldpath, newpath);
|
|
2159
|
+
},
|
|
2119
2160
|
rename(...args) { fs.renameSync(...args); },
|
|
2120
2161
|
rmdir(...args) { fs.rmdirSync(...args); },
|
|
2121
2162
|
readdir(...args) { return ['.', '..'].concat(fs.readdirSync(...args)); },
|
|
@@ -2132,6 +2173,12 @@ async function createWasm() {
|
|
|
2132
2173
|
},
|
|
2133
2174
|
fstat(fd) {
|
|
2134
2175
|
var stream = FS.getStreamChecked(fd);
|
|
2176
|
+
// Virtual streams (pipes, sockets) have no backing node fd; defer to their
|
|
2177
|
+
// own getattr rather than node's fs.fstatSync.
|
|
2178
|
+
var getattr = stream.stream_ops?.getattr ?? stream.node.node_ops?.getattr;
|
|
2179
|
+
if (getattr) {
|
|
2180
|
+
return getattr(stream.stream_ops?.getattr ? stream : stream.node);
|
|
2181
|
+
}
|
|
2135
2182
|
return fs.fstatSync(stream.nfd);
|
|
2136
2183
|
},
|
|
2137
2184
|
statfs(path) {
|
|
@@ -2185,21 +2232,23 @@ async function createWasm() {
|
|
|
2185
2232
|
var stream = FS.getStreamChecked(fd);
|
|
2186
2233
|
fs.ftruncateSync(stream.nfd, len);
|
|
2187
2234
|
},
|
|
2188
|
-
utime(path, atime, mtime) {
|
|
2235
|
+
utime(path, atime, mtime, dontFollow) {
|
|
2189
2236
|
// null here for atime or mtime means UTIME_OMIT was passed. Since node
|
|
2190
2237
|
// doesn't support this concept we need to first find the existing
|
|
2191
2238
|
// timestamps in order to preserve them.
|
|
2192
2239
|
if ((atime === null) || (mtime === null)) {
|
|
2193
|
-
var st = fs.statSync(path);
|
|
2240
|
+
var st = dontFollow ? fs.lstatSync(path) : fs.statSync(path);
|
|
2194
2241
|
atime ||= st.atimeMs;
|
|
2195
2242
|
mtime ||= st.mtimeMs;
|
|
2196
2243
|
}
|
|
2197
|
-
|
|
2244
|
+
if (dontFollow) {
|
|
2245
|
+
fs.lutimesSync(path, atime/1000, mtime/1000);
|
|
2246
|
+
} else {
|
|
2247
|
+
fs.utimesSync(path, atime/1000, mtime/1000);
|
|
2248
|
+
}
|
|
2198
2249
|
},
|
|
2199
2250
|
open(path, flags, mode) {
|
|
2200
|
-
|
|
2201
|
-
flags = FS_modeStringToFlags(flags)
|
|
2202
|
-
}
|
|
2251
|
+
flags = FS_modeStringToFlags(flags);
|
|
2203
2252
|
var pathTruncated = path.split('/').map((s) => s.slice(0, 255)).join('/');
|
|
2204
2253
|
var nfd = fs.openSync(pathTruncated, NODEFS.flagsForNode(flags), mode);
|
|
2205
2254
|
var st = fs.fstatSync(nfd);
|
|
@@ -2214,96 +2263,14 @@ async function createWasm() {
|
|
|
2214
2263
|
createStream(stream, fd) {
|
|
2215
2264
|
// Call the original FS.createStream
|
|
2216
2265
|
var rtn = VFS.createStream(stream, fd);
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2266
|
+
// Detect PIPEFS streams and skip the refcnt/tty initialization in that case.
|
|
2267
|
+
if (!stream.stream_ops) {
|
|
2268
|
+
rtn.shared.refcnt ??= 0;
|
|
2220
2269
|
rtn.shared.refcnt++;
|
|
2270
|
+
rtn.tty = nodeTTY.isatty(rtn.nfd);
|
|
2221
2271
|
}
|
|
2222
2272
|
return rtn;
|
|
2223
2273
|
},
|
|
2224
|
-
close(stream) {
|
|
2225
|
-
VFS.closeStream(stream.fd);
|
|
2226
|
-
// Don't close stdin/stdout/stderr since they are used by node itself.
|
|
2227
|
-
if (!stream.stream_ops && --stream.shared.refcnt <= 0 && stream.nfd > 2) {
|
|
2228
|
-
// This stream is created by our Node.js filesystem, close the
|
|
2229
|
-
// native file descriptor when its reference count drops to 0.
|
|
2230
|
-
fs.closeSync(stream.nfd);
|
|
2231
|
-
}
|
|
2232
|
-
},
|
|
2233
|
-
llseek(stream, offset, whence) {
|
|
2234
|
-
if (stream.stream_ops) {
|
|
2235
|
-
// this stream is created by in-memory filesystem
|
|
2236
|
-
return VFS.llseek(stream, offset, whence);
|
|
2237
|
-
}
|
|
2238
|
-
var position = offset;
|
|
2239
|
-
if (whence === 1) {
|
|
2240
|
-
position += stream.position;
|
|
2241
|
-
} else if (whence === 2) {
|
|
2242
|
-
position += fs.fstatSync(stream.nfd).size;
|
|
2243
|
-
} else if (whence !== 0) {
|
|
2244
|
-
throw new FS.ErrnoError(28);
|
|
2245
|
-
}
|
|
2246
|
-
|
|
2247
|
-
if (position < 0) {
|
|
2248
|
-
throw new FS.ErrnoError(28);
|
|
2249
|
-
}
|
|
2250
|
-
stream.position = position;
|
|
2251
|
-
return position;
|
|
2252
|
-
},
|
|
2253
|
-
read(stream, buffer, offset, length, position) {
|
|
2254
|
-
if (stream.stream_ops) {
|
|
2255
|
-
// this stream is created by in-memory filesystem
|
|
2256
|
-
return VFS.read(stream, buffer, offset, length, position);
|
|
2257
|
-
}
|
|
2258
|
-
var seeking = typeof position != 'undefined';
|
|
2259
|
-
if (!seeking && stream.seekable) position = stream.position;
|
|
2260
|
-
var bytesRead = fs.readSync(stream.nfd, buffer, offset, length, position);
|
|
2261
|
-
// update position marker when non-seeking
|
|
2262
|
-
if (!seeking) stream.position += bytesRead;
|
|
2263
|
-
return bytesRead;
|
|
2264
|
-
},
|
|
2265
|
-
write(stream, buffer, offset, length, position) {
|
|
2266
|
-
if (stream.stream_ops) {
|
|
2267
|
-
// this stream is created by in-memory filesystem
|
|
2268
|
-
return VFS.write(stream, buffer, offset, length, position);
|
|
2269
|
-
}
|
|
2270
|
-
if (stream.flags & +"1024") {
|
|
2271
|
-
// seek to the end before writing in append mode
|
|
2272
|
-
FS.llseek(stream, 0, +"2");
|
|
2273
|
-
}
|
|
2274
|
-
var seeking = typeof position != 'undefined';
|
|
2275
|
-
if (!seeking && stream.seekable) position = stream.position;
|
|
2276
|
-
var bytesWritten = fs.writeSync(stream.nfd, buffer, offset, length, position);
|
|
2277
|
-
// update position marker when non-seeking
|
|
2278
|
-
if (!seeking) stream.position += bytesWritten;
|
|
2279
|
-
return bytesWritten;
|
|
2280
|
-
},
|
|
2281
|
-
mmap(stream, length, position, prot, flags) {
|
|
2282
|
-
if (!length) {
|
|
2283
|
-
throw new FS.ErrnoError(28);
|
|
2284
|
-
}
|
|
2285
|
-
if (stream.stream_ops) {
|
|
2286
|
-
// this stream is created by in-memory filesystem
|
|
2287
|
-
return VFS.mmap(stream, length, position, prot, flags);
|
|
2288
|
-
}
|
|
2289
|
-
|
|
2290
|
-
var ptr = mmapAlloc(length);
|
|
2291
|
-
FS.read(stream, HEAP8, ptr, length, position);
|
|
2292
|
-
return { ptr, allocated: true };
|
|
2293
|
-
},
|
|
2294
|
-
msync(stream, buffer, offset, length, mmapFlags) {
|
|
2295
|
-
if (stream.stream_ops) {
|
|
2296
|
-
// this stream is created by in-memory filesystem
|
|
2297
|
-
return VFS.msync(stream, buffer, offset, length, mmapFlags);
|
|
2298
|
-
}
|
|
2299
|
-
|
|
2300
|
-
FS.write(stream, buffer, 0, length, offset);
|
|
2301
|
-
// should we check if bytesWritten and length are the same?
|
|
2302
|
-
return 0;
|
|
2303
|
-
},
|
|
2304
|
-
ioctl() {
|
|
2305
|
-
throw new FS.ErrnoError(59);
|
|
2306
|
-
},
|
|
2307
2274
|
};
|
|
2308
2275
|
|
|
2309
2276
|
|
|
@@ -2328,6 +2295,73 @@ async function createWasm() {
|
|
|
2328
2295
|
}
|
|
2329
2296
|
};
|
|
2330
2297
|
|
|
2298
|
+
var dependenciesPromise = null;
|
|
2299
|
+
var resolveRunDependencies = async () => dependenciesPromise;
|
|
2300
|
+
var runDependencies = 0;
|
|
2301
|
+
|
|
2302
|
+
|
|
2303
|
+
var dependenciesPromiseResolve = null;
|
|
2304
|
+
|
|
2305
|
+
var runDependencyTracking = {
|
|
2306
|
+
};
|
|
2307
|
+
|
|
2308
|
+
var runDependencyWatcher = null;
|
|
2309
|
+
var removeRunDependency = (id) => {
|
|
2310
|
+
runDependencies--;
|
|
2311
|
+
|
|
2312
|
+
Module['monitorRunDependencies']?.(runDependencies);
|
|
2313
|
+
|
|
2314
|
+
assert(id, 'removeRunDependency requires an ID');
|
|
2315
|
+
assert(runDependencyTracking[id]);
|
|
2316
|
+
delete runDependencyTracking[id];
|
|
2317
|
+
if (!runDependencies) {
|
|
2318
|
+
if (runDependencyWatcher !== null) {
|
|
2319
|
+
clearInterval(runDependencyWatcher);
|
|
2320
|
+
runDependencyWatcher = null;
|
|
2321
|
+
}
|
|
2322
|
+
dependenciesPromiseResolve();
|
|
2323
|
+
}
|
|
2324
|
+
};
|
|
2325
|
+
|
|
2326
|
+
|
|
2327
|
+
|
|
2328
|
+
|
|
2329
|
+
var addRunDependency = (id) => {
|
|
2330
|
+
if (!runDependencies) {
|
|
2331
|
+
dependenciesPromise = new Promise((resolve) => dependenciesPromiseResolve = resolve);
|
|
2332
|
+
}
|
|
2333
|
+
runDependencies++;
|
|
2334
|
+
|
|
2335
|
+
Module['monitorRunDependencies']?.(runDependencies);
|
|
2336
|
+
|
|
2337
|
+
assert(id, 'addRunDependency requires an ID')
|
|
2338
|
+
assert(!runDependencyTracking[id]);
|
|
2339
|
+
runDependencyTracking[id] = 1;
|
|
2340
|
+
if (runDependencyWatcher === null && globalThis.setInterval) {
|
|
2341
|
+
// Check for missing dependencies every few seconds
|
|
2342
|
+
runDependencyWatcher = setInterval(() => {
|
|
2343
|
+
if (ABORT) {
|
|
2344
|
+
clearInterval(runDependencyWatcher);
|
|
2345
|
+
runDependencyWatcher = null;
|
|
2346
|
+
return;
|
|
2347
|
+
}
|
|
2348
|
+
var shown = false;
|
|
2349
|
+
for (var dep in runDependencyTracking) {
|
|
2350
|
+
if (!shown) {
|
|
2351
|
+
shown = true;
|
|
2352
|
+
err('still waiting on run dependencies:');
|
|
2353
|
+
}
|
|
2354
|
+
err(`dependency: ${dep}`);
|
|
2355
|
+
}
|
|
2356
|
+
if (shown) {
|
|
2357
|
+
err('(end of list)');
|
|
2358
|
+
}
|
|
2359
|
+
}, 10000);
|
|
2360
|
+
// Prevent this timer from keeping the runtime alive if nothing
|
|
2361
|
+
// else is.
|
|
2362
|
+
runDependencyWatcher.unref?.()
|
|
2363
|
+
}
|
|
2364
|
+
};
|
|
2331
2365
|
|
|
2332
2366
|
|
|
2333
2367
|
var preloadPlugins = [];
|
|
@@ -2468,6 +2502,48 @@ async function createWasm() {
|
|
|
2468
2502
|
get isDevice() {
|
|
2469
2503
|
return FS.isChrdev(this.mode);
|
|
2470
2504
|
}
|
|
2505
|
+
// The per-inode readiness wait-queue. The node carries a Set of listener
|
|
2506
|
+
// entries {cb}; producers (SOCKFS, PIPEFS) call notifyListeners on a
|
|
2507
|
+
// readiness transition, and poll()/epoll consume it. It lives on the node
|
|
2508
|
+
// (not the fd) so dup'd fds share one queue. Only nodes that derive real
|
|
2509
|
+
// readiness (sockets, pipes, and an epoll's own node) ever use this -
|
|
2510
|
+
// always-ready types (regular files, ttys) never register or notify.
|
|
2511
|
+
addListener(cb, exclusive = false) {
|
|
2512
|
+
var entry = {cb, exclusive};
|
|
2513
|
+
var listeners = (this.listeners ??= new Set());
|
|
2514
|
+
listeners.add(entry);
|
|
2515
|
+
return {listeners, entry};
|
|
2516
|
+
}
|
|
2517
|
+
notifyListeners(flags) {
|
|
2518
|
+
// Iterates the set without copying, which is safe ONLY under a
|
|
2519
|
+
// load-bearing contract that every internal listener must honour:
|
|
2520
|
+
// 1. A listener must not run user code synchronously (a poll waiter only
|
|
2521
|
+
// resolves a Promise; an epoll registration only re-lists +
|
|
2522
|
+
// re-notifies; the epoll callback only schedules a tick). User code
|
|
2523
|
+
// runs on a later tick, never inside this loop.
|
|
2524
|
+
// 2. A listener may delete entries only from ITS OWN waiter, never from
|
|
2525
|
+
// a sibling node's set that may be mid-iteration. (Deleting an entry
|
|
2526
|
+
// of the set being iterated here is fine - a Set tolerates removal of
|
|
2527
|
+
// a not-yet-visited entry mid-iteration; mutating a *different* node's
|
|
2528
|
+
// set is fine because that set is not being iterated.)
|
|
2529
|
+
// Violating either gives silently skipped wakeups that are near-impossible
|
|
2530
|
+
// to reproduce. Any new producer/listener must preserve it.
|
|
2531
|
+
if (!this.listeners) return;
|
|
2532
|
+
// Fire every non-exclusive listener. Among EPOLLEXCLUSIVE registrations
|
|
2533
|
+
// (one fd watched by several epolls) wake only one, rotating round-robin
|
|
2534
|
+
// per node, to avoid a thundering herd. (Only epoll registrations are ever
|
|
2535
|
+
// exclusive; poll waiters and a node's own consumers are not.)
|
|
2536
|
+
var excl;
|
|
2537
|
+
for (var entry of this.listeners) {
|
|
2538
|
+
if (entry.exclusive) (excl ||= []).push(entry);
|
|
2539
|
+
else entry.cb(flags);
|
|
2540
|
+
}
|
|
2541
|
+
if (excl) {
|
|
2542
|
+
var i = (this.exclTurn || 0) % excl.length;
|
|
2543
|
+
this.exclTurn = i + 1;
|
|
2544
|
+
excl[i].cb(flags);
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2471
2547
|
},
|
|
2472
2548
|
lookupPath(path, opts = {}) {
|
|
2473
2549
|
if (!path) {
|
|
@@ -2479,7 +2555,7 @@ async function createWasm() {
|
|
|
2479
2555
|
path = FS.cwd() + '/' + path;
|
|
2480
2556
|
}
|
|
2481
2557
|
|
|
2482
|
-
// limit max consecutive symlinks to
|
|
2558
|
+
// limit max consecutive symlinks to SYMLOOP_MAX.
|
|
2483
2559
|
linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) {
|
|
2484
2560
|
// split the absolute path
|
|
2485
2561
|
var parts = path.split('/').filter((p) => !!p);
|
|
@@ -2771,7 +2847,14 @@ async function createWasm() {
|
|
|
2771
2847
|
var arg = setattr ? stream : node;
|
|
2772
2848
|
setattr ??= node.node_ops.setattr;
|
|
2773
2849
|
FS.checkOpExists(setattr, 63)
|
|
2774
|
-
|
|
2850
|
+
try {
|
|
2851
|
+
setattr(arg, attr);
|
|
2852
|
+
} catch (e) {
|
|
2853
|
+
if (e instanceof RangeError) {
|
|
2854
|
+
throw new FS.ErrnoError(22);
|
|
2855
|
+
}
|
|
2856
|
+
throw e;
|
|
2857
|
+
}
|
|
2775
2858
|
},
|
|
2776
2859
|
chrdev_stream_ops:{
|
|
2777
2860
|
open(stream) {
|
|
@@ -3038,6 +3121,25 @@ async function createWasm() {
|
|
|
3038
3121
|
}
|
|
3039
3122
|
return parent.node_ops.symlink(parent, newname, oldpath);
|
|
3040
3123
|
},
|
|
3124
|
+
link(oldpath, newpath, flags) {
|
|
3125
|
+
var lookup = FS.lookupPath(newpath, { parent: true });
|
|
3126
|
+
var parent = lookup.node;
|
|
3127
|
+
if (!parent) {
|
|
3128
|
+
throw new FS.ErrnoError(44);
|
|
3129
|
+
}
|
|
3130
|
+
var newname = PATH.basename(newpath);
|
|
3131
|
+
var errCode = FS.mayCreate(parent, newname);
|
|
3132
|
+
if (errCode) {
|
|
3133
|
+
throw new FS.ErrnoError(errCode);
|
|
3134
|
+
}
|
|
3135
|
+
// Hardlinks are only supported by filesystem backends that provide a
|
|
3136
|
+
// `link` node op (e.g. NODERAWFS backed by the host). NODEFS omits it:
|
|
3137
|
+
// a host hardlink cannot be confined to the mount root.
|
|
3138
|
+
if (!parent.node_ops.link) {
|
|
3139
|
+
throw new FS.ErrnoError(34);
|
|
3140
|
+
}
|
|
3141
|
+
return parent.node_ops.link(parent, newname, oldpath, flags);
|
|
3142
|
+
},
|
|
3041
3143
|
rename(old_path, new_path) {
|
|
3042
3144
|
var old_dirname = PATH.dirname(old_path);
|
|
3043
3145
|
var new_dirname = PATH.dirname(new_path);
|
|
@@ -3284,20 +3386,19 @@ async function createWasm() {
|
|
|
3284
3386
|
}
|
|
3285
3387
|
FS.doTruncate(stream, stream.node, len);
|
|
3286
3388
|
},
|
|
3287
|
-
utime(path, atime, mtime) {
|
|
3288
|
-
var lookup = FS.lookupPath(path, { follow:
|
|
3289
|
-
|
|
3290
|
-
var setattr = FS.checkOpExists(node.node_ops.setattr, 63);
|
|
3291
|
-
setattr(node, {
|
|
3389
|
+
utime(path, atime, mtime, dontFollow) {
|
|
3390
|
+
var lookup = FS.lookupPath(path, { follow: !dontFollow });
|
|
3391
|
+
FS.doSetAttr(null, lookup.node, {
|
|
3292
3392
|
atime: atime,
|
|
3293
|
-
mtime: mtime
|
|
3393
|
+
mtime: mtime,
|
|
3394
|
+
dontFollow
|
|
3294
3395
|
});
|
|
3295
3396
|
},
|
|
3296
3397
|
open(path, flags, mode = 0o666) {
|
|
3297
3398
|
if (path === "") {
|
|
3298
3399
|
throw new FS.ErrnoError(44);
|
|
3299
3400
|
}
|
|
3300
|
-
flags =
|
|
3401
|
+
flags = FS_modeStringToFlags(flags);
|
|
3301
3402
|
if ((flags & 64)) {
|
|
3302
3403
|
mode = (mode & 4095) | 32768;
|
|
3303
3404
|
} else {
|
|
@@ -3391,6 +3492,11 @@ async function createWasm() {
|
|
|
3391
3492
|
throw new FS.ErrnoError(8);
|
|
3392
3493
|
}
|
|
3393
3494
|
if (stream.getdents) stream.getdents = null; // free readdir state
|
|
3495
|
+
// The fd is going away: wake anything waiting on it (poll/epoll) with
|
|
3496
|
+
// POLLNVAL so a blocking wait unblocks and an epoll registration is evicted
|
|
3497
|
+
// on its next derive. Only sockets/pipes/epoll ever carry a wait-queue, so
|
|
3498
|
+
// for every other stream (incl. nodeless noderawfs stdio) this is a no-op.
|
|
3499
|
+
stream.node?.notifyListeners(32);
|
|
3394
3500
|
try {
|
|
3395
3501
|
if (stream.stream_ops.close) {
|
|
3396
3502
|
stream.stream_ops.close(stream);
|
|
@@ -3448,6 +3554,7 @@ async function createWasm() {
|
|
|
3448
3554
|
},
|
|
3449
3555
|
write(stream, buffer, offset, length, position, canOwn) {
|
|
3450
3556
|
assert(offset >= 0);
|
|
3557
|
+
assert(buffer.subarray, 'FS.write expects a TypedArray');
|
|
3451
3558
|
if (length < 0 || position < 0) {
|
|
3452
3559
|
throw new FS.ErrnoError(28);
|
|
3453
3560
|
}
|
|
@@ -3514,8 +3621,8 @@ async function createWasm() {
|
|
|
3514
3621
|
return stream.stream_ops.ioctl(stream, cmd, arg);
|
|
3515
3622
|
},
|
|
3516
3623
|
readFile(path, opts = {}) {
|
|
3517
|
-
opts.flags = opts.flags
|
|
3518
|
-
opts.encoding = opts.encoding
|
|
3624
|
+
opts.flags = opts.flags ?? 0;
|
|
3625
|
+
opts.encoding = opts.encoding ?? 'binary';
|
|
3519
3626
|
if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') {
|
|
3520
3627
|
abort(`Invalid encoding type "${opts.encoding}"`);
|
|
3521
3628
|
}
|
|
@@ -3531,16 +3638,10 @@ async function createWasm() {
|
|
|
3531
3638
|
return buf;
|
|
3532
3639
|
},
|
|
3533
3640
|
writeFile(path, data, opts = {}) {
|
|
3534
|
-
opts.flags = opts.flags
|
|
3641
|
+
opts.flags = opts.flags ?? 577;
|
|
3535
3642
|
var stream = FS.open(path, opts.flags, opts.mode);
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
}
|
|
3539
|
-
if (ArrayBuffer.isView(data)) {
|
|
3540
|
-
FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
|
|
3541
|
-
} else {
|
|
3542
|
-
abort('Unsupported data type');
|
|
3543
|
-
}
|
|
3643
|
+
data = FS_fileDataToTypedArray(data);
|
|
3644
|
+
FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
|
|
3544
3645
|
FS.close(stream);
|
|
3545
3646
|
},
|
|
3546
3647
|
cwd:() => FS.currentPath,
|
|
@@ -3766,11 +3867,7 @@ async function createWasm() {
|
|
|
3766
3867
|
var mode = FS_getMode(canRead, canWrite);
|
|
3767
3868
|
var node = FS.create(path, mode);
|
|
3768
3869
|
if (data) {
|
|
3769
|
-
|
|
3770
|
-
var arr = new Array(data.length);
|
|
3771
|
-
for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
|
|
3772
|
-
data = arr;
|
|
3773
|
-
}
|
|
3870
|
+
data = FS_fileDataToTypedArray(data);
|
|
3774
3871
|
// make sure we can write to the file
|
|
3775
3872
|
FS.chmod(node, mode | 146);
|
|
3776
3873
|
var stream = FS.open(node, 577);
|
|
@@ -3879,8 +3976,8 @@ async function createWasm() {
|
|
|
3879
3976
|
|
|
3880
3977
|
// Function to get a range from the remote URL.
|
|
3881
3978
|
var doXHR = (from, to) => {
|
|
3882
|
-
if (from > to) abort(
|
|
3883
|
-
if (to > datalength-1) abort(
|
|
3979
|
+
if (from > to) abort(`invalid range (${from}, ${to}) or no bytes requested!`);
|
|
3980
|
+
if (to > datalength-1) abort(`only ${datalength} bytes available! programmer error!`);
|
|
3884
3981
|
|
|
3885
3982
|
// TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
|
|
3886
3983
|
var xhr = new XMLHttpRequest();
|
|
@@ -3898,7 +3995,7 @@ async function createWasm() {
|
|
|
3898
3995
|
if (xhr.response !== undefined) {
|
|
3899
3996
|
return new Uint8Array(/** @type{Array<number>} */(xhr.response || []));
|
|
3900
3997
|
}
|
|
3901
|
-
return intArrayFromString(xhr.responseText
|
|
3998
|
+
return intArrayFromString(xhr.responseText ?? '', true);
|
|
3902
3999
|
};
|
|
3903
4000
|
var lazyArray = this;
|
|
3904
4001
|
lazyArray.setDataGetter((chunkNum) => {
|
|
@@ -4005,27 +4102,10 @@ async function createWasm() {
|
|
|
4005
4102
|
node.stream_ops = stream_ops;
|
|
4006
4103
|
return node;
|
|
4007
4104
|
},
|
|
4008
|
-
absolutePath() {
|
|
4009
|
-
abort('FS.absolutePath has been removed; use PATH_FS.resolve instead');
|
|
4010
|
-
},
|
|
4011
|
-
createFolder() {
|
|
4012
|
-
abort('FS.createFolder has been removed; use FS.mkdir instead');
|
|
4013
|
-
},
|
|
4014
|
-
createLink() {
|
|
4015
|
-
abort('FS.createLink has been removed; use FS.symlink instead');
|
|
4016
|
-
},
|
|
4017
|
-
joinPath() {
|
|
4018
|
-
abort('FS.joinPath has been removed; use PATH.join instead');
|
|
4019
|
-
},
|
|
4020
|
-
mmapAlloc() {
|
|
4021
|
-
abort('FS.mmapAlloc has been replaced by the top level function mmapAlloc');
|
|
4022
|
-
},
|
|
4023
|
-
standardizePath() {
|
|
4024
|
-
abort('FS.standardizePath has been removed; use PATH.normalize instead');
|
|
4025
|
-
},
|
|
4026
4105
|
};
|
|
4027
4106
|
|
|
4028
4107
|
var SYSCALLS = {
|
|
4108
|
+
currentUmask:18,
|
|
4029
4109
|
calculateAt(dirfd, path, allowEmpty) {
|
|
4030
4110
|
if (PATH.isAbs(path)) {
|
|
4031
4111
|
return path;
|
|
@@ -4088,7 +4168,7 @@ async function createWasm() {
|
|
|
4088
4168
|
// MAP_PRIVATE calls need not to be synced back to underlying fs
|
|
4089
4169
|
return 0;
|
|
4090
4170
|
}
|
|
4091
|
-
var buffer = HEAPU8.
|
|
4171
|
+
var buffer = HEAPU8.subarray(addr, addr + len);
|
|
4092
4172
|
FS.msync(stream, buffer, offset, len, flags);
|
|
4093
4173
|
},
|
|
4094
4174
|
getStreamFromFD(fd) {
|
|
@@ -4126,7 +4206,8 @@ async function createWasm() {
|
|
|
4126
4206
|
return stream.flags;
|
|
4127
4207
|
case 4: {
|
|
4128
4208
|
var arg = syscallGetVarargI();
|
|
4129
|
-
|
|
4209
|
+
var mask = 289792;
|
|
4210
|
+
stream.flags = (stream.flags & ~mask) | (arg & mask);
|
|
4130
4211
|
return 0;
|
|
4131
4212
|
}
|
|
4132
4213
|
case 12: {
|
|
@@ -4150,6 +4231,7 @@ async function createWasm() {
|
|
|
4150
4231
|
return -e.errno;
|
|
4151
4232
|
}
|
|
4152
4233
|
}
|
|
4234
|
+
|
|
4153
4235
|
|
|
4154
4236
|
|
|
4155
4237
|
function ___syscall_ioctl(fd, op, varargs) {
|
|
@@ -4247,6 +4329,7 @@ async function createWasm() {
|
|
|
4247
4329
|
return -e.errno;
|
|
4248
4330
|
}
|
|
4249
4331
|
}
|
|
4332
|
+
|
|
4250
4333
|
|
|
4251
4334
|
|
|
4252
4335
|
function ___syscall_openat(dirfd, path, flags, varargs) {
|
|
@@ -4256,18 +4339,22 @@ async function createWasm() {
|
|
|
4256
4339
|
path = SYSCALLS.getStr(path);
|
|
4257
4340
|
path = SYSCALLS.calculateAt(dirfd, path);
|
|
4258
4341
|
var mode = varargs ? syscallGetVarargI() : 0;
|
|
4342
|
+
if (flags & 64) {
|
|
4343
|
+
mode &= ~SYSCALLS.currentUmask;
|
|
4344
|
+
}
|
|
4259
4345
|
return FS.open(path, flags, mode).fd;
|
|
4260
4346
|
} catch (e) {
|
|
4261
4347
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
4262
4348
|
return -e.errno;
|
|
4263
4349
|
}
|
|
4264
4350
|
}
|
|
4351
|
+
|
|
4265
4352
|
|
|
4266
4353
|
var __abort_js = () =>
|
|
4267
4354
|
abort('native code called abort()');
|
|
4268
4355
|
|
|
4269
4356
|
var __emscripten_throw_longjmp = () => {
|
|
4270
|
-
throw
|
|
4357
|
+
throw new EmscriptenSjLj;
|
|
4271
4358
|
};
|
|
4272
4359
|
|
|
4273
4360
|
|
|
@@ -4409,6 +4496,7 @@ async function createWasm() {
|
|
|
4409
4496
|
return e.errno;
|
|
4410
4497
|
}
|
|
4411
4498
|
}
|
|
4499
|
+
|
|
4412
4500
|
|
|
4413
4501
|
/** @param {number=} offset */
|
|
4414
4502
|
var doReadv = (stream, iov, iovcnt, offset) => {
|
|
@@ -4417,7 +4505,18 @@ async function createWasm() {
|
|
|
4417
4505
|
var ptr = HEAPU32[((iov)>>2)];
|
|
4418
4506
|
var len = HEAPU32[(((iov)+(4))>>2)];
|
|
4419
4507
|
iov += 8;
|
|
4420
|
-
|
|
4508
|
+
try {
|
|
4509
|
+
var curr = FS.read(stream, HEAP8, ptr, len, offset);
|
|
4510
|
+
} catch (e) {
|
|
4511
|
+
// On a non-blocking stream a subsequent read may would-block after we
|
|
4512
|
+
// already gathered data. POSIX readv is a single gather-read: return
|
|
4513
|
+
// what we have rather than failing the whole call.
|
|
4514
|
+
if (ret > 0 && e instanceof FS.ErrnoError &&
|
|
4515
|
+
(e.errno == 6 || e.errno == 6)) {
|
|
4516
|
+
break;
|
|
4517
|
+
}
|
|
4518
|
+
throw e;
|
|
4519
|
+
}
|
|
4421
4520
|
if (curr < 0) return -1;
|
|
4422
4521
|
ret += curr;
|
|
4423
4522
|
if (curr < len) break; // nothing more to read
|
|
@@ -4440,6 +4539,7 @@ async function createWasm() {
|
|
|
4440
4539
|
return e.errno;
|
|
4441
4540
|
}
|
|
4442
4541
|
}
|
|
4542
|
+
|
|
4443
4543
|
|
|
4444
4544
|
|
|
4445
4545
|
function _fd_seek(fd, offset, whence, newOffset) {
|
|
@@ -4448,7 +4548,7 @@ async function createWasm() {
|
|
|
4448
4548
|
|
|
4449
4549
|
try {
|
|
4450
4550
|
|
|
4451
|
-
if (isNaN(offset)) return
|
|
4551
|
+
if (isNaN(offset)) return 22;
|
|
4452
4552
|
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
4453
4553
|
FS.llseek(stream, offset, whence);
|
|
4454
4554
|
HEAP64[((newOffset)>>3)] = BigInt(stream.position);
|
|
@@ -4463,23 +4563,27 @@ async function createWasm() {
|
|
|
4463
4563
|
|
|
4464
4564
|
/** @param {number=} offset */
|
|
4465
4565
|
var doWritev = (stream, iov, iovcnt, offset) => {
|
|
4466
|
-
|
|
4467
|
-
|
|
4566
|
+
// Gather all iovecs into one contiguous buffer and issue a single
|
|
4567
|
+
// FS.write, matching POSIX writev's single gather-write semantics (as
|
|
4568
|
+
// __syscall_sendmsg already does). Per-iovec writes fragment a stream
|
|
4569
|
+
// socket send into multiple segments, breaking stream byte semantics.
|
|
4570
|
+
if (iovcnt == 1) {
|
|
4571
|
+
// Single iovec: write directly from HEAP8, no gather buffer needed.
|
|
4572
|
+
return FS.write(stream, HEAP8, HEAPU32[((iov)>>2)], HEAPU32[(((iov)+(4))>>2)], offset);
|
|
4573
|
+
}
|
|
4574
|
+
var total = 0;
|
|
4575
|
+
for (var i = 0, p = iov; i < iovcnt; i++, p += 8) {
|
|
4576
|
+
total += HEAPU32[(((p)+(4))>>2)];
|
|
4577
|
+
}
|
|
4578
|
+
var view = new Uint8Array(total);
|
|
4579
|
+
var voff = 0;
|
|
4580
|
+
for (var i = 0; i < iovcnt; i++, iov += 8) {
|
|
4468
4581
|
var ptr = HEAPU32[((iov)>>2)];
|
|
4469
4582
|
var len = HEAPU32[(((iov)+(4))>>2)];
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
if (curr < 0) return -1;
|
|
4473
|
-
ret += curr;
|
|
4474
|
-
if (curr < len) {
|
|
4475
|
-
// No more space to write.
|
|
4476
|
-
break;
|
|
4477
|
-
}
|
|
4478
|
-
if (typeof offset != 'undefined') {
|
|
4479
|
-
offset += curr;
|
|
4480
|
-
}
|
|
4583
|
+
view.set(HEAPU8.subarray(ptr, ptr + len), voff);
|
|
4584
|
+
voff += len;
|
|
4481
4585
|
}
|
|
4482
|
-
return
|
|
4586
|
+
return FS.write(stream, view, 0, total, offset);
|
|
4483
4587
|
};
|
|
4484
4588
|
|
|
4485
4589
|
function _fd_write(fd, iov, iovcnt, pnum) {
|
|
@@ -4494,6 +4598,7 @@ async function createWasm() {
|
|
|
4494
4598
|
return e.errno;
|
|
4495
4599
|
}
|
|
4496
4600
|
}
|
|
4601
|
+
|
|
4497
4602
|
|
|
4498
4603
|
|
|
4499
4604
|
var handleException = (e) => {
|
|
@@ -4516,7 +4621,7 @@ async function createWasm() {
|
|
|
4516
4621
|
|
|
4517
4622
|
|
|
4518
4623
|
var stringToUTF8 = (str, outPtr, maxBytesToWrite) => {
|
|
4519
|
-
assert(typeof maxBytesToWrite == 'number', 'stringToUTF8
|
|
4624
|
+
assert(typeof maxBytesToWrite == 'number', 'stringToUTF8 requires a third parameter that specifies the length of the output buffer');
|
|
4520
4625
|
return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
|
|
4521
4626
|
};
|
|
4522
4627
|
|
|
@@ -4538,7 +4643,7 @@ async function createWasm() {
|
|
|
4538
4643
|
wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
|
|
4539
4644
|
}
|
|
4540
4645
|
/** @suppress {checkTypes} */
|
|
4541
|
-
assert(wasmTable.get(funcPtr) == func, '
|
|
4646
|
+
assert(wasmTable.get(funcPtr) == func, 'table mirror is out of date');
|
|
4542
4647
|
return func;
|
|
4543
4648
|
};
|
|
4544
4649
|
|
|
@@ -4550,8 +4655,9 @@ if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); };
|
|
|
4550
4655
|
if (!ENVIRONMENT_IS_NODE) {
|
|
4551
4656
|
throw new Error("NODERAWFS is currently only supported on Node.js environment.")
|
|
4552
4657
|
}
|
|
4553
|
-
var
|
|
4554
|
-
|
|
4658
|
+
var nodeTTY = require('node:tty');
|
|
4659
|
+
function _wrapNodeError(func) {
|
|
4660
|
+
return (...args) => {
|
|
4555
4661
|
try {
|
|
4556
4662
|
return func(...args)
|
|
4557
4663
|
} catch (e) {
|
|
@@ -4566,14 +4672,26 @@ if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); };
|
|
|
4566
4672
|
throw e;
|
|
4567
4673
|
}
|
|
4568
4674
|
}
|
|
4569
|
-
}
|
|
4675
|
+
}
|
|
4676
|
+
function _wrapNodeStreamFunc(func, vfs_func) {
|
|
4677
|
+
return _wrapNodeError((stream, ...args) => {
|
|
4678
|
+
if (stream.stream_ops) {
|
|
4679
|
+
// this stream was created by some other FS. e.g: PIPEFS.
|
|
4680
|
+
return vfs_func(stream, ...args);
|
|
4681
|
+
}
|
|
4682
|
+
return func(stream, ...args);
|
|
4683
|
+
});
|
|
4684
|
+
}
|
|
4570
4685
|
// Use this to reference our in-memory filesystem
|
|
4571
4686
|
/** @suppress {partialAlias} */
|
|
4572
4687
|
var VFS = {...FS};
|
|
4573
4688
|
// Wrap the whole in-memory filesystem API with
|
|
4574
4689
|
// our Node.js based functions
|
|
4575
|
-
for (
|
|
4576
|
-
FS[
|
|
4690
|
+
for (const [key, value] of Object.entries(NODERAWFS)) {
|
|
4691
|
+
FS[key] = _wrapNodeError(value);
|
|
4692
|
+
}
|
|
4693
|
+
for (const [key, value] of Object.entries(NODERAWFS_stream_funcs)) {
|
|
4694
|
+
FS[key] = _wrapNodeStreamFunc(value, FS[key]);
|
|
4577
4695
|
};
|
|
4578
4696
|
// End JS library code
|
|
4579
4697
|
|
|
@@ -4585,15 +4703,14 @@ if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); };
|
|
|
4585
4703
|
|
|
4586
4704
|
// Begin ATMODULES hooks
|
|
4587
4705
|
if (Module['noExitRuntime']) noExitRuntime = Module['noExitRuntime'];
|
|
4588
|
-
|
|
4706
|
+
|
|
4589
4707
|
if (Module['print']) out = Module['print'];
|
|
4590
4708
|
if (Module['printErr']) err = Module['printErr'];
|
|
4591
|
-
if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
|
|
4592
4709
|
// End ATMODULES hooks
|
|
4593
4710
|
|
|
4594
4711
|
checkIncomingModuleAPI();
|
|
4595
4712
|
|
|
4596
|
-
if (Module['arguments'])
|
|
4713
|
+
if (Module['arguments']) programArgs = Module['arguments'];
|
|
4597
4714
|
if (Module['thisProgram']) thisProgram = Module['thisProgram'];
|
|
4598
4715
|
|
|
4599
4716
|
// Assertions on removed incoming Module JS APIs.
|
|
@@ -4612,10 +4729,13 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
|
|
|
4612
4729
|
assert(typeof Module['wasmMemory'] == 'undefined', 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally');
|
|
4613
4730
|
assert(typeof Module['INITIAL_MEMORY'] == 'undefined', 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically');
|
|
4614
4731
|
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4732
|
+
var preInit = Module['preInit'];
|
|
4733
|
+
if (preInit) {
|
|
4734
|
+
if (typeof preInit == 'function') Module['preInit'] = preInit = [preInit];
|
|
4735
|
+
// Written as a loop so that preInit functions that themselves add more
|
|
4736
|
+
// preInit functions. Is this actually needed?
|
|
4737
|
+
while (preInit.length > 0) {
|
|
4738
|
+
preInit.shift()();
|
|
4619
4739
|
}
|
|
4620
4740
|
}
|
|
4621
4741
|
consumedModuleProp('preInit');
|
|
@@ -4701,12 +4821,14 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
|
|
|
4701
4821
|
'registerOrientationChangeEventCallback',
|
|
4702
4822
|
'fillFullscreenChangeEventData',
|
|
4703
4823
|
'registerFullscreenChangeEventCallback',
|
|
4824
|
+
'callCanvasResizedCallback',
|
|
4704
4825
|
'JSEvents_requestFullscreen',
|
|
4705
4826
|
'JSEvents_resizeCanvasForFullscreen',
|
|
4706
4827
|
'registerRestoreOldStyle',
|
|
4707
4828
|
'hideEverythingExceptGivenElement',
|
|
4708
4829
|
'restoreHiddenElements',
|
|
4709
4830
|
'setLetterbox',
|
|
4831
|
+
'currentFullscreenStrategy',
|
|
4710
4832
|
'softFullscreenResizeWebGLRenderTarget',
|
|
4711
4833
|
'doRequestFullscreen',
|
|
4712
4834
|
'fillPointerlockChangeEventData',
|
|
@@ -4738,10 +4860,13 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
|
|
|
4738
4860
|
'registerPreMainLoop',
|
|
4739
4861
|
'getPromise',
|
|
4740
4862
|
'makePromise',
|
|
4863
|
+
'addPromise',
|
|
4741
4864
|
'idsToPromises',
|
|
4742
4865
|
'makePromiseCallback',
|
|
4743
4866
|
'ExceptionInfo',
|
|
4744
4867
|
'findMatchingCatch',
|
|
4868
|
+
'incrementUncaughtExceptionCount',
|
|
4869
|
+
'decrementUncaughtExceptionCount',
|
|
4745
4870
|
'Browser_asyncPrepareDataCounter',
|
|
4746
4871
|
'isLeapYear',
|
|
4747
4872
|
'ydayFromDate',
|
|
@@ -4765,6 +4890,7 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
|
|
|
4765
4890
|
'colorChannelsInGlTextureFormat',
|
|
4766
4891
|
'emscriptenWebGLGetTexPixelData',
|
|
4767
4892
|
'emscriptenWebGLGetUniform',
|
|
4893
|
+
'webglGetProgramUniformLocation',
|
|
4768
4894
|
'webglGetUniformLocation',
|
|
4769
4895
|
'webglPrepareUniformLocationsBeforeFirstUse',
|
|
4770
4896
|
'webglGetLeftBracePos',
|
|
@@ -4792,21 +4918,21 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
|
|
|
4792
4918
|
'err',
|
|
4793
4919
|
'abort',
|
|
4794
4920
|
'wasmExports',
|
|
4795
|
-
'
|
|
4796
|
-
'
|
|
4921
|
+
'writeStackCookie',
|
|
4922
|
+
'checkStackCookie',
|
|
4923
|
+
'INT53_MAX',
|
|
4924
|
+
'INT53_MIN',
|
|
4925
|
+
'bigintToI53Checked',
|
|
4797
4926
|
'HEAP8',
|
|
4798
4927
|
'HEAPU8',
|
|
4799
4928
|
'HEAP16',
|
|
4800
4929
|
'HEAPU16',
|
|
4801
4930
|
'HEAP32',
|
|
4802
4931
|
'HEAPU32',
|
|
4932
|
+
'HEAPF32',
|
|
4933
|
+
'HEAPF64',
|
|
4803
4934
|
'HEAP64',
|
|
4804
4935
|
'HEAPU64',
|
|
4805
|
-
'writeStackCookie',
|
|
4806
|
-
'checkStackCookie',
|
|
4807
|
-
'INT53_MAX',
|
|
4808
|
-
'INT53_MIN',
|
|
4809
|
-
'bigintToI53Checked',
|
|
4810
4936
|
'stackSave',
|
|
4811
4937
|
'stackRestore',
|
|
4812
4938
|
'stackAlloc',
|
|
@@ -4855,7 +4981,6 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
|
|
|
4855
4981
|
'JSEvents',
|
|
4856
4982
|
'specialHTMLTargets',
|
|
4857
4983
|
'findCanvasEventTarget',
|
|
4858
|
-
'currentFullscreenStrategy',
|
|
4859
4984
|
'restoreOldWindowedStyle',
|
|
4860
4985
|
'UNWIND_CACHE',
|
|
4861
4986
|
'ExitStatus',
|
|
@@ -4868,7 +4993,6 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
|
|
|
4868
4993
|
'emClearImmediate',
|
|
4869
4994
|
'promiseMap',
|
|
4870
4995
|
'uncaughtExceptionCount',
|
|
4871
|
-
'exceptionLast',
|
|
4872
4996
|
'exceptionCaught',
|
|
4873
4997
|
'Browser',
|
|
4874
4998
|
'requestFullscreen',
|
|
@@ -4888,6 +5012,7 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
|
|
|
4888
5012
|
'FS_preloadFile',
|
|
4889
5013
|
'FS_modeStringToFlags',
|
|
4890
5014
|
'FS_getMode',
|
|
5015
|
+
'FS_fileDataToTypedArray',
|
|
4891
5016
|
'FS_stdin_getChar_buffer',
|
|
4892
5017
|
'FS_stdin_getChar',
|
|
4893
5018
|
'FS_unlink',
|
|
@@ -4956,6 +5081,7 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
|
|
|
4956
5081
|
'FS_mkdir',
|
|
4957
5082
|
'FS_mkdev',
|
|
4958
5083
|
'FS_symlink',
|
|
5084
|
+
'FS_link',
|
|
4959
5085
|
'FS_rename',
|
|
4960
5086
|
'FS_rmdir',
|
|
4961
5087
|
'FS_readdir',
|
|
@@ -5000,18 +5126,13 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
|
|
|
5000
5126
|
'FS_createDataFile',
|
|
5001
5127
|
'FS_forceLoadFile',
|
|
5002
5128
|
'FS_createLazyFile',
|
|
5003
|
-
'FS_absolutePath',
|
|
5004
|
-
'FS_createFolder',
|
|
5005
|
-
'FS_createLink',
|
|
5006
|
-
'FS_joinPath',
|
|
5007
|
-
'FS_mmapAlloc',
|
|
5008
|
-
'FS_standardizePath',
|
|
5009
5129
|
'MEMFS',
|
|
5010
5130
|
'TTY',
|
|
5011
5131
|
'PIPEFS',
|
|
5012
5132
|
'SOCKFS',
|
|
5013
5133
|
'NODEFS',
|
|
5014
5134
|
'NODERAWFS',
|
|
5135
|
+
'NODERAWFS_stream_funcs',
|
|
5015
5136
|
'nodePath',
|
|
5016
5137
|
'tempFixedLengthArray',
|
|
5017
5138
|
'miniTempWebGLFloatBuffers',
|
|
@@ -5040,6 +5161,30 @@ function checkIncomingModuleAPI() {
|
|
|
5040
5161
|
ignoredModuleProp('fetchSettings');
|
|
5041
5162
|
ignoredModuleProp('logReadFiles');
|
|
5042
5163
|
ignoredModuleProp('loadSplitModule');
|
|
5164
|
+
ignoredModuleProp('onMalloc');
|
|
5165
|
+
ignoredModuleProp('onRealloc');
|
|
5166
|
+
ignoredModuleProp('onFree');
|
|
5167
|
+
ignoredModuleProp('onSbrkGrow');
|
|
5168
|
+
ignoredModuleProp('onCOSCacheHit');
|
|
5169
|
+
ignoredModuleProp('onCOSCacheMiss');
|
|
5170
|
+
ignoredModuleProp('onCOSStore');
|
|
5171
|
+
ignoredModuleProp('GL_MAX_TEXTURE_IMAGE_UNITS');
|
|
5172
|
+
ignoredModuleProp('SDL_canPlayWithWebAudio');
|
|
5173
|
+
ignoredModuleProp('SDL_numSimultaneouslyQueuedBuffers');
|
|
5174
|
+
ignoredModuleProp('freePreloadedMediaOnUse');
|
|
5175
|
+
ignoredModuleProp('preinitializedWebGLContext');
|
|
5176
|
+
ignoredModuleProp('keyboardListeningElement');
|
|
5177
|
+
ignoredModuleProp('doNotCaptureKeyboard');
|
|
5178
|
+
ignoredModuleProp('extraStackTrace');
|
|
5179
|
+
ignoredModuleProp('preloadPlugins');
|
|
5180
|
+
ignoredModuleProp('preMainLoop');
|
|
5181
|
+
ignoredModuleProp('postMainLoop');
|
|
5182
|
+
ignoredModuleProp('forcedAspectRatio');
|
|
5183
|
+
ignoredModuleProp('mainScriptUrlOrBlob');
|
|
5184
|
+
ignoredModuleProp('onFullScreen');
|
|
5185
|
+
ignoredModuleProp('INITIAL_MEMORY');
|
|
5186
|
+
ignoredModuleProp('wasmMemory');
|
|
5187
|
+
ignoredModuleProp('wasmBinary');
|
|
5043
5188
|
}
|
|
5044
5189
|
|
|
5045
5190
|
// Imports from the Wasm binary.
|
|
@@ -5077,14 +5222,14 @@ function assignWasmExports(wasmExports) {
|
|
|
5077
5222
|
assert(typeof wasmExports['emscripten_stack_get_current'] != 'undefined', 'missing Wasm export: emscripten_stack_get_current');
|
|
5078
5223
|
assert(typeof wasmExports['memory'] != 'undefined', 'missing Wasm export: memory');
|
|
5079
5224
|
assert(typeof wasmExports['__indirect_function_table'] != 'undefined', 'missing Wasm export: __indirect_function_table');
|
|
5080
|
-
_main = Module['_main'] = createExportWrapper('__main_argc_argv', 2);
|
|
5081
|
-
_fflush = createExportWrapper('fflush', 1);
|
|
5082
|
-
___funcs_on_exit = createExportWrapper('__funcs_on_exit', 0);
|
|
5083
|
-
_emscripten_builtin_memalign = createExportWrapper('emscripten_builtin_memalign', 2);
|
|
5225
|
+
_main = Module['_main'] = createExportWrapper('__main_argc_argv', wasmExports['__main_argc_argv'], 2);
|
|
5226
|
+
_fflush = createExportWrapper('fflush', wasmExports['fflush'], 1);
|
|
5227
|
+
___funcs_on_exit = createExportWrapper('__funcs_on_exit', wasmExports['__funcs_on_exit'], 0);
|
|
5228
|
+
_emscripten_builtin_memalign = createExportWrapper('emscripten_builtin_memalign', wasmExports['emscripten_builtin_memalign'], 2);
|
|
5084
5229
|
_emscripten_stack_get_end = wasmExports['emscripten_stack_get_end'];
|
|
5085
5230
|
_emscripten_stack_get_base = wasmExports['emscripten_stack_get_base'];
|
|
5086
|
-
_strerror = createExportWrapper('strerror', 1);
|
|
5087
|
-
_setThrew = createExportWrapper('setThrew', 2);
|
|
5231
|
+
_strerror = createExportWrapper('strerror', wasmExports['strerror'], 1);
|
|
5232
|
+
_setThrew = createExportWrapper('setThrew', wasmExports['setThrew'], 2);
|
|
5088
5233
|
_emscripten_stack_init = wasmExports['emscripten_stack_init'];
|
|
5089
5234
|
_emscripten_stack_get_free = wasmExports['emscripten_stack_get_free'];
|
|
5090
5235
|
__emscripten_stack_restore = wasmExports['_emscripten_stack_restore'];
|
|
@@ -5139,7 +5284,7 @@ function invoke_ii(index,a1) {
|
|
|
5139
5284
|
return getWasmTableEntry(index)(a1);
|
|
5140
5285
|
} catch(e) {
|
|
5141
5286
|
stackRestore(sp);
|
|
5142
|
-
if (e
|
|
5287
|
+
if (!(e instanceof EmscriptenEH)) throw e;
|
|
5143
5288
|
_setThrew(1, 0);
|
|
5144
5289
|
}
|
|
5145
5290
|
}
|
|
@@ -5150,7 +5295,7 @@ function invoke_iii(index,a1,a2) {
|
|
|
5150
5295
|
return getWasmTableEntry(index)(a1,a2);
|
|
5151
5296
|
} catch(e) {
|
|
5152
5297
|
stackRestore(sp);
|
|
5153
|
-
if (e
|
|
5298
|
+
if (!(e instanceof EmscriptenEH)) throw e;
|
|
5154
5299
|
_setThrew(1, 0);
|
|
5155
5300
|
}
|
|
5156
5301
|
}
|
|
@@ -5161,7 +5306,7 @@ function invoke_viii(index,a1,a2,a3) {
|
|
|
5161
5306
|
getWasmTableEntry(index)(a1,a2,a3);
|
|
5162
5307
|
} catch(e) {
|
|
5163
5308
|
stackRestore(sp);
|
|
5164
|
-
if (e
|
|
5309
|
+
if (!(e instanceof EmscriptenEH)) throw e;
|
|
5165
5310
|
_setThrew(1, 0);
|
|
5166
5311
|
}
|
|
5167
5312
|
}
|
|
@@ -5172,7 +5317,7 @@ function invoke_vii(index,a1,a2) {
|
|
|
5172
5317
|
getWasmTableEntry(index)(a1,a2);
|
|
5173
5318
|
} catch(e) {
|
|
5174
5319
|
stackRestore(sp);
|
|
5175
|
-
if (e
|
|
5320
|
+
if (!(e instanceof EmscriptenEH)) throw e;
|
|
5176
5321
|
_setThrew(1, 0);
|
|
5177
5322
|
}
|
|
5178
5323
|
}
|
|
@@ -5183,7 +5328,7 @@ function invoke_vi(index,a1) {
|
|
|
5183
5328
|
getWasmTableEntry(index)(a1);
|
|
5184
5329
|
} catch(e) {
|
|
5185
5330
|
stackRestore(sp);
|
|
5186
|
-
if (e
|
|
5331
|
+
if (!(e instanceof EmscriptenEH)) throw e;
|
|
5187
5332
|
_setThrew(1, 0);
|
|
5188
5333
|
}
|
|
5189
5334
|
}
|
|
@@ -5232,65 +5377,47 @@ function stackCheckInit() {
|
|
|
5232
5377
|
writeStackCookie();
|
|
5233
5378
|
}
|
|
5234
5379
|
|
|
5235
|
-
function run(args =
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
dependenciesFulfilled = run;
|
|
5239
|
-
return;
|
|
5240
|
-
}
|
|
5380
|
+
async function run(args = programArgs) {
|
|
5381
|
+
assert(!calledRun);
|
|
5382
|
+
calledRun = true;
|
|
5241
5383
|
|
|
5242
5384
|
stackCheckInit();
|
|
5243
5385
|
|
|
5244
5386
|
preRun();
|
|
5245
5387
|
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
dependenciesFulfilled = run;
|
|
5249
|
-
return;
|
|
5388
|
+
if (runDependencies) {
|
|
5389
|
+
await resolveRunDependencies();
|
|
5250
5390
|
}
|
|
5251
5391
|
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5392
|
+
var setStatus = Module['setStatus'];
|
|
5393
|
+
if (setStatus) {
|
|
5394
|
+
setStatus('Running...');
|
|
5395
|
+
// Yield to the event loop to allow the browser to paint "Running..."
|
|
5396
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
5397
|
+
// Then we want to clear the status text, but only after the rest of this function runs.
|
|
5398
|
+
setTimeout(setStatus, 1, '');
|
|
5399
|
+
}
|
|
5260
5400
|
|
|
5261
|
-
|
|
5401
|
+
if (ABORT) return;
|
|
5262
5402
|
|
|
5263
|
-
|
|
5403
|
+
initRuntime();
|
|
5264
5404
|
|
|
5265
|
-
|
|
5266
|
-
consumedModuleProp('onRuntimeInitialized');
|
|
5405
|
+
// No ATMAINS hooks
|
|
5267
5406
|
|
|
5268
|
-
|
|
5269
|
-
|
|
5407
|
+
Module['onRuntimeInitialized']?.();
|
|
5408
|
+
consumedModuleProp('onRuntimeInitialized');
|
|
5270
5409
|
|
|
5271
|
-
|
|
5272
|
-
|
|
5410
|
+
var noInitialRun = Module['noInitialRun'] || false;
|
|
5411
|
+
if (!noInitialRun) callMain(args);
|
|
5273
5412
|
|
|
5274
|
-
|
|
5275
|
-
Module['setStatus']('Running...');
|
|
5276
|
-
setTimeout(() => {
|
|
5277
|
-
setTimeout(() => Module['setStatus'](''), 1);
|
|
5278
|
-
doRun();
|
|
5279
|
-
}, 1);
|
|
5280
|
-
} else
|
|
5281
|
-
{
|
|
5282
|
-
doRun();
|
|
5283
|
-
}
|
|
5284
|
-
checkStackCookie();
|
|
5413
|
+
postRun();
|
|
5285
5414
|
}
|
|
5286
5415
|
|
|
5287
5416
|
var wasmExports;
|
|
5288
5417
|
|
|
5289
5418
|
// With async instantation wasmExports is assigned asynchronously when the
|
|
5290
5419
|
// instance is received.
|
|
5291
|
-
createWasm();
|
|
5292
|
-
|
|
5293
|
-
run();
|
|
5420
|
+
createWasm().then(() => run());
|
|
5294
5421
|
|
|
5295
5422
|
// end include: postamble.js
|
|
5296
5423
|
|