@php-wasm/node 1.1.3 → 1.1.5

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 (40) hide show
  1. package/asyncify/7_2_34/php_7_2.wasm +0 -0
  2. package/asyncify/7_3_33/php_7_3.wasm +0 -0
  3. package/asyncify/7_4_33/php_7_4.wasm +0 -0
  4. package/asyncify/8_0_30/php_8_0.wasm +0 -0
  5. package/asyncify/8_1_23/php_8_1.wasm +0 -0
  6. package/asyncify/8_2_10/php_8_2.wasm +0 -0
  7. package/asyncify/8_3_0/php_8_3.wasm +0 -0
  8. package/asyncify/8_4_0/php_8_4.wasm +0 -0
  9. package/asyncify/php_7_2.js +201 -138
  10. package/asyncify/php_7_3.js +200 -137
  11. package/asyncify/php_7_4.js +199 -136
  12. package/asyncify/php_8_0.js +203 -140
  13. package/asyncify/php_8_1.js +202 -139
  14. package/asyncify/php_8_2.js +203 -140
  15. package/asyncify/php_8_3.js +203 -140
  16. package/asyncify/php_8_4.js +202 -139
  17. package/fs_ext.node +0 -0
  18. package/index.cjs +9466 -3617
  19. package/index.js +9350 -3617
  20. package/jspi/7_2_34/php_7_2.wasm +0 -0
  21. package/jspi/7_3_33/php_7_3.wasm +0 -0
  22. package/jspi/7_4_33/php_7_4.wasm +0 -0
  23. package/jspi/8_0_30/php_8_0.wasm +0 -0
  24. package/jspi/8_1_23/php_8_1.wasm +0 -0
  25. package/jspi/8_2_10/php_8_2.wasm +0 -0
  26. package/jspi/8_3_0/php_8_3.wasm +0 -0
  27. package/jspi/8_4_0/php_8_4.wasm +0 -0
  28. package/jspi/php_7_2.js +2196 -1523
  29. package/jspi/php_7_3.js +2196 -1523
  30. package/jspi/php_7_4.js +9299 -7705
  31. package/jspi/php_8_0.js +2196 -1523
  32. package/jspi/php_8_1.js +2470 -1797
  33. package/jspi/php_8_2.js +2450 -1777
  34. package/jspi/php_8_3.js +2450 -1777
  35. package/jspi/php_8_4.js +2450 -1777
  36. package/lib/file-lock-manager-for-node.d.ts +149 -0
  37. package/lib/file-lock-manager.d.ts +96 -0
  38. package/lib/index.d.ts +2 -0
  39. package/lib/load-runtime.d.ts +31 -2
  40. package/package.json +10 -9
package/jspi/php_8_0.js CHANGED
@@ -8,7 +8,7 @@ import path from 'path';
8
8
 
9
9
  const dependencyFilename = path.join(__dirname, '8_0_30', 'php_8_0.wasm');
10
10
  export { dependencyFilename };
11
- export const dependenciesTotalSize = 17167885;
11
+ export const dependenciesTotalSize = 17169869;
12
12
  export function init(RuntimeName, PHPLoader) {
13
13
  // The rest of the code comes from the built php.js file and esm-suffix.js
14
14
  // include: shell.js
@@ -5227,262 +5227,1080 @@ export function init(RuntimeName, PHPLoader) {
5227
5227
 
5228
5228
  var syscallGetVarargP = syscallGetVarargI;
5229
5229
 
5230
- function ___syscall_fcntl64(fd, cmd, varargs) {
5231
- SYSCALLS.varargs = varargs;
5232
- try {
5233
- var stream = SYSCALLS.getStreamFromFD(fd);
5234
- switch (cmd) {
5235
- case 0: {
5236
- var arg = syscallGetVarargI();
5237
- if (arg < 0) {
5238
- return -28;
5239
- }
5240
- while (FS.streams[arg]) {
5241
- arg++;
5242
- }
5243
- var newStream;
5244
- newStream = FS.dupStream(stream, arg);
5245
- return newStream.fd;
5246
- }
5247
-
5248
- case 1:
5249
- case 2:
5250
- return 0;
5251
-
5252
- // FD_CLOEXEC makes no sense for a single process.
5253
- case 3:
5254
- return stream.flags;
5255
-
5256
- case 4: {
5257
- var arg = syscallGetVarargI();
5258
- stream.flags |= arg;
5259
- return 0;
5260
- }
5261
-
5262
- case 12: {
5263
- var arg = syscallGetVarargP();
5264
- var offset = 0;
5265
- // We're always unlocked.
5266
- HEAP16[(arg + offset) >> 1] = 2;
5267
- return 0;
5268
- }
5269
-
5270
- case 13:
5271
- case 14:
5272
- // Pretend that the locking is successful. These are process-level locks,
5273
- // and Emscripten programs are a single process. If we supported linking a
5274
- // filesystem between programs, we'd need to do more here.
5275
- // See https://github.com/emscripten-core/emscripten/issues/23697
5276
- return 0;
5277
- }
5278
- return -28;
5279
- } catch (e) {
5280
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5281
- return -e.errno;
5282
- }
5283
- }
5284
-
5285
- function ___syscall_fdatasync(fd) {
5286
- try {
5287
- var stream = SYSCALLS.getStreamFromFD(fd);
5288
- return 0;
5289
- } catch (e) {
5290
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5291
- return -e.errno;
5292
- }
5293
- }
5294
-
5295
- function ___syscall_fstat64(fd, buf) {
5296
- try {
5297
- return SYSCALLS.writeStat(buf, FS.fstat(fd));
5298
- } catch (e) {
5299
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5300
- return -e.errno;
5301
- }
5302
- }
5303
-
5304
- function ___syscall_ftruncate64(fd, length) {
5305
- length = bigintToI53Checked(length);
5306
- try {
5307
- if (isNaN(length)) return 61;
5308
- FS.ftruncate(fd, length);
5309
- return 0;
5310
- } catch (e) {
5311
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5312
- return -e.errno;
5313
- }
5314
- }
5315
-
5316
5230
  var stringToUTF8 = (str, outPtr, maxBytesToWrite) =>
5317
5231
  stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
5318
5232
 
5319
5233
  Module['stringToUTF8'] = stringToUTF8;
5320
5234
 
5321
- function ___syscall_getcwd(buf, size) {
5322
- try {
5323
- if (size === 0) return -28;
5324
- var cwd = FS.cwd();
5325
- var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1;
5326
- if (size < cwdLengthInBytes) return -68;
5327
- stringToUTF8(cwd, buf, size);
5328
- return cwdLengthInBytes;
5329
- } catch (e) {
5330
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5331
- return -e.errno;
5332
- }
5333
- }
5334
-
5335
- function ___syscall_getdents64(fd, dirp, count) {
5336
- try {
5337
- var stream = SYSCALLS.getStreamFromFD(fd);
5338
- stream.getdents ||= FS.readdir(stream.path);
5339
- var struct_size = 280;
5340
- var pos = 0;
5341
- var off = FS.llseek(stream, 0, 1);
5342
- var startIdx = Math.floor(off / struct_size);
5343
- var endIdx = Math.min(
5344
- stream.getdents.length,
5345
- startIdx + Math.floor(count / struct_size)
5346
- );
5347
- for (var idx = startIdx; idx < endIdx; idx++) {
5348
- var id;
5349
- var type;
5350
- var name = stream.getdents[idx];
5351
- if (name === '.') {
5352
- id = stream.node.id;
5353
- type = 4;
5354
- } else if (name === '..') {
5355
- var lookup = FS.lookupPath(stream.path, {
5356
- parent: true,
5357
- });
5358
- id = lookup.node.id;
5359
- type = 4;
5360
- } else {
5361
- var child;
5362
- try {
5363
- child = FS.lookupNode(stream.node, name);
5364
- } catch (e) {
5365
- // If the entry is not a directory, file, or symlink, nodefs
5366
- // lookupNode will raise EINVAL. Skip these and continue.
5367
- if (e?.errno === 28) {
5368
- continue;
5369
- }
5370
- throw e;
5371
- }
5372
- id = child.id;
5373
- type = FS.isChrdev(child.mode)
5374
- ? 2 // DT_CHR, character device.
5375
- : FS.isDir(child.mode)
5376
- ? 4 // DT_DIR, directory.
5377
- : FS.isLink(child.mode)
5378
- ? 10 // DT_LNK, symbolic link.
5379
- : 8;
5380
- }
5381
- HEAP64[(dirp + pos) >> 3] = BigInt(id);
5382
- HEAP64[(dirp + pos + 8) >> 3] = BigInt((idx + 1) * struct_size);
5383
- HEAP16[(dirp + pos + 16) >> 1] = 280;
5384
- HEAP8[dirp + pos + 18] = type;
5385
- stringToUTF8(name, dirp + pos + 19, 256);
5386
- pos += struct_size;
5387
- }
5388
- FS.llseek(stream, idx * struct_size, 0);
5389
- return pos;
5390
- } catch (e) {
5391
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5392
- return -e.errno;
5393
- }
5394
- }
5395
-
5396
- function ___syscall_getpeername(fd, addr, addrlen, d1, d2, d3) {
5397
- try {
5398
- var sock = getSocketFromFD(fd);
5399
- if (!sock.daddr) {
5400
- return -53;
5401
- }
5402
- var errno = writeSockaddr(
5403
- addr,
5404
- sock.family,
5405
- DNS.lookup_name(sock.daddr),
5406
- sock.dport,
5407
- addrlen
5408
- );
5409
- return 0;
5410
- } catch (e) {
5411
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5412
- return -e.errno;
5413
- }
5414
- }
5415
-
5416
- function ___syscall_getsockname(fd, addr, addrlen, d1, d2, d3) {
5417
- try {
5418
- var sock = getSocketFromFD(fd);
5419
- // TODO: sock.saddr should never be undefined, see TODO in websocket_sock_ops.getname
5420
- var errno = writeSockaddr(
5421
- addr,
5422
- sock.family,
5423
- DNS.lookup_name(sock.saddr || '0.0.0.0'),
5424
- sock.sport,
5425
- addrlen
5426
- );
5427
- return 0;
5428
- } catch (e) {
5429
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5430
- return -e.errno;
5431
- }
5432
- }
5235
+ var stackAlloc = (sz) => __emscripten_stack_alloc(sz);
5433
5236
 
5434
- function ___syscall_getsockopt(fd, level, optname, optval, optlen, d1) {
5435
- try {
5436
- var sock = getSocketFromFD(fd);
5437
- // Minimal getsockopt aimed at resolving https://github.com/emscripten-core/emscripten/issues/2211
5438
- // so only supports SOL_SOCKET with SO_ERROR.
5439
- if (level === 1) {
5440
- if (optname === 4) {
5441
- HEAP32[optval >> 2] = sock.error;
5442
- HEAP32[optlen >> 2] = 4;
5443
- sock.error = null;
5444
- // Clear the error (The SO_ERROR option obtains and then clears this field).
5445
- return 0;
5446
- }
5447
- }
5448
- return -50;
5449
- } catch (e) {
5450
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5451
- return -e.errno;
5452
- }
5453
- }
5237
+ /** @suppress {duplicate } */ var stringToUTF8OnStack = (str) => {
5238
+ var size = lengthBytesUTF8(str) + 1;
5239
+ var ret = stackAlloc(size);
5240
+ stringToUTF8(str, ret, size);
5241
+ return ret;
5242
+ };
5454
5243
 
5455
- function ___syscall_ioctl(fd, op, varargs) {
5456
- SYSCALLS.varargs = varargs;
5457
- try {
5458
- var stream = SYSCALLS.getStreamFromFD(fd);
5459
- switch (op) {
5460
- case 21509: {
5461
- if (!stream.tty) return -59;
5462
- return 0;
5463
- }
5244
+ var allocateUTF8OnStack = stringToUTF8OnStack;
5464
5245
 
5465
- case 21505: {
5466
- if (!stream.tty) return -59;
5467
- if (stream.tty.ops.ioctl_tcgets) {
5468
- var termios = stream.tty.ops.ioctl_tcgets(stream);
5469
- var argp = syscallGetVarargP();
5470
- HEAP32[argp >> 2] = termios.c_iflag || 0;
5471
- HEAP32[(argp + 4) >> 2] = termios.c_oflag || 0;
5472
- HEAP32[(argp + 8) >> 2] = termios.c_cflag || 0;
5473
- HEAP32[(argp + 12) >> 2] = termios.c_lflag || 0;
5474
- for (var i = 0; i < 32; i++) {
5475
- HEAP8[argp + i + 17] = termios.c_cc[i] || 0;
5476
- }
5477
- return 0;
5478
- }
5479
- return 0;
5480
- }
5246
+ var PHPWASM = {
5247
+ init: function () {
5248
+ Module['ENV'] = Module['ENV'] || {};
5249
+ // Ensure a platform-level bin directory for a fallback `php` binary.
5250
+ Module['ENV']['PATH'] = [
5251
+ Module['ENV']['PATH'],
5252
+ '/internal/shared/bin',
5253
+ ]
5254
+ .filter(Boolean)
5255
+ .join(':');
5481
5256
 
5482
- case 21510:
5483
- case 21511:
5484
- case 21512: {
5485
- if (!stream.tty) return -59;
5257
+ // The /internal directory is required by the C module. It's where the
5258
+ // stdout, stderr, and headers information are written for the JavaScript
5259
+ // code to read later on.
5260
+ FS.mkdir('/internal');
5261
+ // The files from the shared directory are shared between all the
5262
+ // PHP processes managed by PHPProcessManager.
5263
+ FS.mkdir('/internal/shared');
5264
+ // The files from the preload directory are preloaded using the
5265
+ // auto_prepend_file php.ini directive.
5266
+ FS.mkdir('/internal/shared/preload');
5267
+ // Platform-level bin directory for a fallback `php` binary. Without it,
5268
+ // PHP may not populate the PHP_BINARY constant.
5269
+ FS.mkdir('/internal/shared/bin');
5270
+ const originalOnRuntimeInitialized = Module['onRuntimeInitialized'];
5271
+ Module['onRuntimeInitialized'] = () => {
5272
+ // Dummy PHP binary for PHP to populate the PHP_BINARY constant.
5273
+ FS.writeFile(
5274
+ '/internal/shared/bin/php',
5275
+ new TextEncoder().encode('#!/bin/sh\nphp "$@"')
5276
+ );
5277
+ // It must be executable to be used by PHP.
5278
+ FS.chmod('/internal/shared/bin/php', 0o755);
5279
+ originalOnRuntimeInitialized();
5280
+ };
5281
+ // Create stdout and stderr devices. We can't just use Emscripten's
5282
+ // default stdout and stderr devices because they stop processing data
5283
+ // on the first null byte. However, when dealing with binary data,
5284
+ // null bytes are valid and common.
5285
+ FS.registerDevice(FS.makedev(64, 0), {
5286
+ open: () => {},
5287
+ close: () => {},
5288
+ read: () => 0,
5289
+ write: (stream, buffer, offset, length, pos) => {
5290
+ const chunk = buffer.subarray(offset, offset + length);
5291
+ PHPWASM.onStdout(chunk);
5292
+ return length;
5293
+ },
5294
+ });
5295
+ FS.mkdev('/internal/stdout', FS.makedev(64, 0));
5296
+ FS.registerDevice(FS.makedev(63, 0), {
5297
+ open: () => {},
5298
+ close: () => {},
5299
+ read: () => 0,
5300
+ write: (stream, buffer, offset, length, pos) => {
5301
+ const chunk = buffer.subarray(offset, offset + length);
5302
+ PHPWASM.onStderr(chunk);
5303
+ return length;
5304
+ },
5305
+ });
5306
+ FS.mkdev('/internal/stderr', FS.makedev(63, 0));
5307
+ FS.registerDevice(FS.makedev(62, 0), {
5308
+ open: () => {},
5309
+ close: () => {},
5310
+ read: () => 0,
5311
+ write: (stream, buffer, offset, length, pos) => {
5312
+ const chunk = buffer.subarray(offset, offset + length);
5313
+ PHPWASM.onHeaders(chunk);
5314
+ return length;
5315
+ },
5316
+ });
5317
+ FS.mkdev('/internal/headers', FS.makedev(62, 0));
5318
+ // Handle events.
5319
+ PHPWASM.EventEmitter = ENVIRONMENT_IS_NODE
5320
+ ? require('events').EventEmitter
5321
+ : class EventEmitter {
5322
+ constructor() {
5323
+ this.listeners = {};
5324
+ }
5325
+ emit(eventName, data) {
5326
+ if (this.listeners[eventName]) {
5327
+ this.listeners[eventName].forEach(
5328
+ (callback) => {
5329
+ callback(data);
5330
+ }
5331
+ );
5332
+ }
5333
+ }
5334
+ once(eventName, callback) {
5335
+ const self = this;
5336
+ function removedCallback() {
5337
+ callback(...arguments);
5338
+ self.removeListener(eventName, removedCallback);
5339
+ }
5340
+ this.on(eventName, removedCallback);
5341
+ }
5342
+ removeAllListeners(eventName) {
5343
+ if (eventName) {
5344
+ delete this.listeners[eventName];
5345
+ } else {
5346
+ this.listeners = {};
5347
+ }
5348
+ }
5349
+ removeListener(eventName, callback) {
5350
+ if (this.listeners[eventName]) {
5351
+ const idx =
5352
+ this.listeners[eventName].indexOf(callback);
5353
+ if (idx !== -1) {
5354
+ this.listeners[eventName].splice(idx, 1);
5355
+ }
5356
+ }
5357
+ }
5358
+ };
5359
+ // Clean up the fd -> childProcess mapping when the fd is closed:
5360
+ const originalClose = FS.close;
5361
+ FS.close = function (stream) {
5362
+ originalClose(stream);
5363
+ delete PHPWASM.child_proc_by_fd[stream.fd];
5364
+ };
5365
+ PHPWASM.child_proc_by_fd = {};
5366
+ PHPWASM.child_proc_by_pid = {};
5367
+ PHPWASM.input_devices = {};
5368
+ const originalWrite = TTY.stream_ops.write;
5369
+ TTY.stream_ops.write = function (stream, ...rest) {
5370
+ const retval = originalWrite(stream, ...rest);
5371
+ // Implicit flush since PHP's fflush() doesn't seem to trigger the fsync event
5372
+ // @TODO: Fix this at the wasm level
5373
+ stream.tty.ops.fsync(stream.tty);
5374
+ return retval;
5375
+ };
5376
+ const originalPutChar = TTY.stream_ops.put_char;
5377
+ TTY.stream_ops.put_char = function (tty, val) {
5378
+ /**
5379
+ * Buffer newlines that Emscripten normally ignores.
5380
+ *
5381
+ * Emscripten doesn't do it by default because its default
5382
+ * print function is console.log that implicitly adds a newline. We are overwriting
5383
+ * it with an environment-specific function that outputs exaclty what it was given,
5384
+ * e.g. in Node.js it's process.stdout.write(). Therefore, we need to mak sure
5385
+ * all the newlines make it to the output buffer.
5386
+ */ if (val === 10) tty.output.push(val);
5387
+ return originalPutChar(tty, val);
5388
+ };
5389
+ },
5390
+ onHeaders: function (chunk) {
5391
+ if (Module['onHeaders']) {
5392
+ Module['onHeaders'](chunk);
5393
+ return;
5394
+ }
5395
+ console.log('headers', {
5396
+ chunk,
5397
+ });
5398
+ },
5399
+ onStdout: function (chunk) {
5400
+ if (Module['onStdout']) {
5401
+ Module['onStdout'](chunk);
5402
+ return;
5403
+ }
5404
+ if (ENVIRONMENT_IS_NODE) {
5405
+ process.stdout.write(chunk);
5406
+ } else {
5407
+ console.log('stdout', {
5408
+ chunk,
5409
+ });
5410
+ }
5411
+ },
5412
+ onStderr: function (chunk) {
5413
+ if (Module['onStderr']) {
5414
+ Module['onStderr'](chunk);
5415
+ return;
5416
+ }
5417
+ if (ENVIRONMENT_IS_NODE) {
5418
+ process.stderr.write(chunk);
5419
+ } else {
5420
+ console.warn('stderr', {
5421
+ chunk,
5422
+ });
5423
+ }
5424
+ },
5425
+ getAllWebSockets: function (sock) {
5426
+ const webSockets = new Set();
5427
+ if (sock.server) {
5428
+ sock.server.clients.forEach((ws) => {
5429
+ webSockets.add(ws);
5430
+ });
5431
+ }
5432
+ for (const peer of PHPWASM.getAllPeers(sock)) {
5433
+ webSockets.add(peer.socket);
5434
+ }
5435
+ return Array.from(webSockets);
5436
+ },
5437
+ getAllPeers: function (sock) {
5438
+ const peers = new Set();
5439
+ if (sock.server) {
5440
+ sock.pending
5441
+ .filter((pending) => pending.peers)
5442
+ .forEach((pending) => {
5443
+ for (const peer of Object.values(pending.peers)) {
5444
+ peers.add(peer);
5445
+ }
5446
+ });
5447
+ }
5448
+ if (sock.peers) {
5449
+ for (const peer of Object.values(sock.peers)) {
5450
+ peers.add(peer);
5451
+ }
5452
+ }
5453
+ return Array.from(peers);
5454
+ },
5455
+ awaitData: function (ws) {
5456
+ return PHPWASM.awaitEvent(ws, 'message');
5457
+ },
5458
+ awaitConnection: function (ws) {
5459
+ if (ws.OPEN === ws.readyState) {
5460
+ return [Promise.resolve(), PHPWASM.noop];
5461
+ }
5462
+ return PHPWASM.awaitEvent(ws, 'open');
5463
+ },
5464
+ awaitClose: function (ws) {
5465
+ if ([ws.CLOSING, ws.CLOSED].includes(ws.readyState)) {
5466
+ return [Promise.resolve(), PHPWASM.noop];
5467
+ }
5468
+ return PHPWASM.awaitEvent(ws, 'close');
5469
+ },
5470
+ awaitError: function (ws) {
5471
+ if ([ws.CLOSING, ws.CLOSED].includes(ws.readyState)) {
5472
+ return [Promise.resolve(), PHPWASM.noop];
5473
+ }
5474
+ return PHPWASM.awaitEvent(ws, 'error');
5475
+ },
5476
+ awaitEvent: function (ws, event) {
5477
+ let resolve;
5478
+ const listener = () => {
5479
+ resolve();
5480
+ };
5481
+ const promise = new Promise(function (_resolve) {
5482
+ resolve = _resolve;
5483
+ ws.once(event, listener);
5484
+ });
5485
+ const cancel = () => {
5486
+ ws.removeListener(event, listener);
5487
+ // Rejecting the promises bubbles up and kills the entire
5488
+ // node process. Let's resolve them on the next tick instead
5489
+ // to give the caller some space to unbind any handlers.
5490
+ setTimeout(resolve);
5491
+ };
5492
+ return [promise, cancel];
5493
+ },
5494
+ noop: function () {},
5495
+ spawnProcess: function (command, args, options) {
5496
+ if (Module['spawnProcess']) {
5497
+ const spawnedPromise = Module['spawnProcess'](
5498
+ command,
5499
+ args,
5500
+ options
5501
+ );
5502
+ return Promise.resolve(spawnedPromise).then(function (spawned) {
5503
+ if (!spawned || !spawned.on) {
5504
+ throw new Error(
5505
+ 'spawnProcess() must return an EventEmitter but returned a different type.'
5506
+ );
5507
+ }
5508
+ return spawned;
5509
+ });
5510
+ }
5511
+ if (ENVIRONMENT_IS_NODE) {
5512
+ return require('child_process').spawn(command, args, {
5513
+ ...options,
5514
+ shell: true,
5515
+ stdio: ['pipe', 'pipe', 'pipe'],
5516
+ timeout: 100,
5517
+ });
5518
+ }
5519
+ const e = new Error(
5520
+ 'popen(), proc_open() etc. are unsupported in the browser. Call php.setSpawnHandler() ' +
5521
+ 'and provide a callback to handle spawning processes, or disable a popen(), proc_open() ' +
5522
+ 'and similar functions via php.ini.'
5523
+ );
5524
+ e.code = 'SPAWN_UNSUPPORTED';
5525
+ throw e;
5526
+ },
5527
+ shutdownSocket: function (socketd, how) {
5528
+ // This implementation only supports websockets at the moment
5529
+ const sock = getSocketFromFD(socketd);
5530
+ const peer = Object.values(sock.peers)[0];
5531
+ if (!peer) {
5532
+ return -1;
5533
+ }
5534
+ try {
5535
+ peer.socket.close();
5536
+ SOCKFS.websocket_sock_ops.removePeer(sock, peer);
5537
+ return 0;
5538
+ } catch (e) {
5539
+ console.log('Socket shutdown error', e);
5540
+ return -1;
5541
+ }
5542
+ },
5543
+ };
5544
+
5545
+ function _js_getpid() {
5546
+ return PHPLoader.processId ?? 42;
5547
+ }
5548
+
5549
+ function _js_wasm_trace(format, ...args) {
5550
+ if (PHPLoader.trace instanceof Function) {
5551
+ PHPLoader.trace(_js_getpid(), format, ...args);
5552
+ }
5553
+ }
5554
+
5555
+ function _fd_close(fd) {
5556
+ _js_wasm_trace('fd_close(%d)', fd);
5557
+ const [vfsPath, pathResolutionErrno] = locking.get_vfs_path_from_fd(fd);
5558
+ if (pathResolutionErrno !== 0) {
5559
+ _js_wasm_trace(
5560
+ 'fd_close(%d) get_vfs_path_from_fd error %d',
5561
+ fd,
5562
+ pathResolutionErrno
5563
+ );
5564
+ return -ERRNO_CODES.EBADF;
5565
+ }
5566
+ const result = _builtin_fd_close(fd);
5567
+ if (result === 0 && locking.maybeLockedFds.has(fd)) {
5568
+ const nativeFilePath =
5569
+ locking.get_native_path_from_vfs_path(vfsPath);
5570
+ return PHPLoader.fileLockManager
5571
+ .releaseLocksForProcessFd(
5572
+ PHPLoader.processId,
5573
+ fd,
5574
+ nativeFilePath
5575
+ )
5576
+ .then(() => {
5577
+ _js_wasm_trace('fd_close(%d) release locks success', fd);
5578
+ })
5579
+ .catch((e) => {
5580
+ _js_wasm_trace("fd_close(%d) error '%s'", fd, e);
5581
+ })
5582
+ .then(() => {
5583
+ _js_wasm_trace('fd_close(%d) result %d', fd, result);
5584
+ return result;
5585
+ })
5586
+ .finally(() => {
5587
+ locking.maybeLockedFds.delete(fd);
5588
+ });
5589
+ } else {
5590
+ _js_wasm_trace('fd_close(%d) result %d', fd, result);
5591
+ return result;
5592
+ }
5593
+ }
5594
+
5595
+ function _builtin_fd_close(fd) {
5596
+ try {
5597
+ var stream = SYSCALLS.getStreamFromFD(fd);
5598
+ FS.close(stream);
5599
+ return 0;
5600
+ } catch (e) {
5601
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5602
+ return e.errno;
5603
+ }
5604
+ }
5605
+
5606
+ function _builtin_fcntl64(fd, cmd, varargs) {
5607
+ SYSCALLS.varargs = varargs;
5608
+ try {
5609
+ var stream = SYSCALLS.getStreamFromFD(fd);
5610
+ switch (cmd) {
5611
+ case 0: {
5612
+ var arg = syscallGetVarargI();
5613
+ if (arg < 0) {
5614
+ return -28;
5615
+ }
5616
+ while (FS.streams[arg]) {
5617
+ arg++;
5618
+ }
5619
+ var newStream;
5620
+ newStream = FS.dupStream(stream, arg);
5621
+ return newStream.fd;
5622
+ }
5623
+
5624
+ case 1:
5625
+ case 2:
5626
+ return 0;
5627
+
5628
+ // FD_CLOEXEC makes no sense for a single process.
5629
+ case 3:
5630
+ return stream.flags;
5631
+
5632
+ case 4: {
5633
+ var arg = syscallGetVarargI();
5634
+ stream.flags |= arg;
5635
+ return 0;
5636
+ }
5637
+
5638
+ case 12: {
5639
+ var arg = syscallGetVarargP();
5640
+ var offset = 0;
5641
+ // We're always unlocked.
5642
+ HEAP16[(arg + offset) >> 1] = 2;
5643
+ return 0;
5644
+ }
5645
+
5646
+ case 13:
5647
+ case 14:
5648
+ // Pretend that the locking is successful. These are process-level locks,
5649
+ // and Emscripten programs are a single process. If we supported linking a
5650
+ // filesystem between programs, we'd need to do more here.
5651
+ // See https://github.com/emscripten-core/emscripten/issues/23697
5652
+ return 0;
5653
+ }
5654
+ return -28;
5655
+ } catch (e) {
5656
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5657
+ return -e.errno;
5658
+ }
5659
+ }
5660
+
5661
+ var locking = {
5662
+ maybeLockedFds: new Set(),
5663
+ F_RDLCK: 0,
5664
+ F_WRLCK: 1,
5665
+ F_UNLCK: 2,
5666
+ lockStateToFcntl: {
5667
+ shared: 0,
5668
+ exclusive: 1,
5669
+ unlocked: 2,
5670
+ },
5671
+ fcntlToLockState: {
5672
+ 0: 'shared',
5673
+ 1: 'exclusive',
5674
+ 2: 'unlocked',
5675
+ },
5676
+ is_shared_fs_node(node) {
5677
+ if (node?.isSharedFS) {
5678
+ return true;
5679
+ }
5680
+
5681
+ // Handle PROXYFS nodes which wrap other nodes.
5682
+ if (
5683
+ !node?.mount?.opts?.fs?.lookupPath ||
5684
+ !node?.mount?.type?.realPath
5685
+ ) {
5686
+ return false;
5687
+ }
5688
+
5689
+ // Only NODEFS can be shared between workers at the moment.
5690
+ if (node.mount.type !== NODEFS) {
5691
+ return false;
5692
+ }
5693
+ const vfsPath = node.mount.type.realPath(node);
5694
+ try {
5695
+ const underlyingNode =
5696
+ node.mount.opts.fs.lookupPath(vfsPath)?.node;
5697
+ return !!underlyingNode?.isSharedFS;
5698
+ } catch (e) {
5699
+ return false;
5700
+ }
5701
+ },
5702
+ is_path_to_shared_fs(path) {
5703
+ const { node } = FS.lookupPath(path);
5704
+ return locking.is_shared_fs_node(node);
5705
+ },
5706
+ get_fd_access_mode(fd) {
5707
+ const emscripten_F_GETFL = Number('3');
5708
+ const emscripten_O_ACCMODE = Number('2097155');
5709
+ return (
5710
+ _builtin_fcntl64(fd, emscripten_F_GETFL) & emscripten_O_ACCMODE
5711
+ );
5712
+ },
5713
+ get_vfs_path_from_fd(fd) {
5714
+ try {
5715
+ return [FS.readlink(`/proc/self/fd/${fd}`), 0];
5716
+ } catch (error) {
5717
+ return [null, ERRNO_CODES.EBADF];
5718
+ }
5719
+ },
5720
+ get_native_path_from_vfs_path(vfsPath) {
5721
+ const { node } = FS.lookupPath(vfsPath);
5722
+ return NODEFS.realPath(node);
5723
+ },
5724
+ check_lock_params(fd, l_type) {
5725
+ const emscripten_O_RDONLY = Number('0');
5726
+ const emscripten_O_WRONLY = Number('1');
5727
+ const accessMode = locking.get_fd_access_mode(fd);
5728
+ if (
5729
+ (l_type === locking.F_WRLCK &&
5730
+ accessMode === emscripten_O_RDONLY) ||
5731
+ (l_type === locking.F_RDLCK &&
5732
+ accessMode === emscripten_O_WRONLY)
5733
+ ) {
5734
+ return ERRNO_CODES.EBADF;
5735
+ }
5736
+ return 0;
5737
+ },
5738
+ };
5739
+
5740
+ async function ___syscall_fcntl64(fd, cmd, varargs) {
5741
+ // Necessary to use varargs accessor
5742
+ SYSCALLS.varargs = varargs;
5743
+ // These constants are replaced by Emscripten during the build process
5744
+ const emscripten_F_GETLK = Number('12');
5745
+ const emscripten_F_SETLK = Number('13');
5746
+ const emscripten_F_SETLKW = Number('14');
5747
+ const emscripten_SEEK_SET = Number('0');
5748
+ // NOTE: With the exception of l_type, these offsets are not exposed to
5749
+ // JS by Emscripten, so we hardcode them here.
5750
+ const emscripten_flock_l_type_offset = 0;
5751
+ const emscripten_flock_l_whence_offset = 2;
5752
+ const emscripten_flock_l_start_offset = 8;
5753
+ const emscripten_flock_l_len_offset = 16;
5754
+ const emscripten_flock_l_pid_offset = 24;
5755
+ /**
5756
+ * Read the flock struct at the given address.
5757
+ *
5758
+ * @param {bigint} flockStructAddress - the address of the flock struct
5759
+ * @returns the flock struct
5760
+ */ function read_flock_struct(flockStructAddress) {
5761
+ /*
5762
+ * NOTE: Since we are using HEAP<WORD_SIZE> vars like HEAP16 and HEAP64,
5763
+ * we need to adjust offsets to address the word size of each HEAP.
5764
+ *
5765
+ * For example, an offset of 64 bytes is the following for each HEAP:
5766
+ * - HEAP8: 64 (the 64th byte)
5767
+ * - HEAP16: 32 (the 32nd 16-bit word)
5768
+ * - HEAP32: 16 (the 16th 32-bit word)
5769
+ * - HEAP64: 8 (the 8th 64-bit word)
5770
+ *
5771
+ * We get a word offset by dividing the byte offset by the word size.
5772
+ */ return {
5773
+ l_type: HEAP16[ // Shift right by 1 to divide by 2^1.
5774
+ (flockStructAddress + emscripten_flock_l_type_offset) >> 1
5775
+ ],
5776
+ l_whence:
5777
+ HEAP16[ // Shift right by 1 to divide by 2^1.
5778
+ (flockStructAddress +
5779
+ emscripten_flock_l_whence_offset) >>
5780
+ 1
5781
+ ],
5782
+ l_start:
5783
+ HEAP64[ // Shift right by 3 to divide by 2^3.
5784
+ (flockStructAddress +
5785
+ emscripten_flock_l_start_offset) >>
5786
+ 3
5787
+ ],
5788
+ l_len: HEAP64[ // Shift right by 3 to divide by 2^3.
5789
+ (flockStructAddress + emscripten_flock_l_len_offset) >> 3
5790
+ ],
5791
+ l_pid: HEAP32[ // Shift right by 2 to divide by 2^2.
5792
+ (flockStructAddress + emscripten_flock_l_pid_offset) >> 2
5793
+ ],
5794
+ };
5795
+ }
5796
+ /**
5797
+ * Update the flock struct at the given address with the given fields.
5798
+ *
5799
+ * @param {bigint} flockStructAddress - the address of the flock struct
5800
+ * @param {object} fields - the fields to update
5801
+ */ function update_flock_struct(flockStructAddress, fields) {
5802
+ /*
5803
+ * NOTE: Since we are using HEAP<WORD_SIZE> vars like HEAP16 and HEAP64,
5804
+ * we need to adjust offsets to address the word size of each HEAP.
5805
+ *
5806
+ * For example, an offset of 64 bytes is the following for each HEAP:
5807
+ * - HEAP8: 64 (the 64th byte)
5808
+ * - HEAP16: 32 (the 32nd 16-bit word)
5809
+ * - HEAP32: 16 (the 16th 32-bit word)
5810
+ * - HEAP64: 8 (the 8th 64-bit word)
5811
+ *
5812
+ * We get a word offset by dividing the byte offset by the word size.
5813
+ */ if (fields.l_type !== undefined) {
5814
+ HEAP16[ // Shift right by 1 to divide by 2^1.
5815
+ (flockStructAddress + emscripten_flock_l_type_offset) >> 1
5816
+ ] = fields.l_type;
5817
+ }
5818
+ if (fields.l_whence !== undefined) {
5819
+ HEAP16[ // Shift right by 1 to divide by 2^1.
5820
+ (flockStructAddress + emscripten_flock_l_whence_offset) >> 1
5821
+ ] = fields.l_whence;
5822
+ }
5823
+ if (fields.l_start !== undefined) {
5824
+ HEAP64[ // Shift right by 3 to divide by 2^3.
5825
+ (flockStructAddress + emscripten_flock_l_start_offset) >> 3
5826
+ ] = fields.l_start;
5827
+ }
5828
+ if (fields.l_len !== undefined) {
5829
+ HEAP64[ // Shift right by 3 to divide by 2^3.
5830
+ (flockStructAddress + emscripten_flock_l_len_offset) >> 3
5831
+ ] = fields.l_len;
5832
+ }
5833
+ if (fields.l_pid !== undefined) {
5834
+ HEAP32[ // Shift right by 2 to divide by 2^2.
5835
+ (flockStructAddress + emscripten_flock_l_pid_offset) >> 2
5836
+ ] = fields.l_pid;
5837
+ }
5838
+ }
5839
+ /**
5840
+ * Resolve the base address of the range depending on the whence and start offset.
5841
+ *
5842
+ * @param {number} fd - the file descriptor
5843
+ * @param {number} whence - what the start offset is relative to
5844
+ * @param {bigint} startOffset - the offset from the whence
5845
+ * @returns The resolved offset and the errno. If there is an error,
5846
+ * the resolved offset is null, and the errno is non-zero.
5847
+ */ function get_base_address(fd, whence, startOffset) {
5848
+ let baseAddress;
5849
+ switch (whence) {
5850
+ case emscripten_SEEK_SET:
5851
+ baseAddress = 0n;
5852
+ break;
5853
+
5854
+ case emscripten_SEEK_CUR:
5855
+ baseAddress = FS.lseek(fd, 0, whence);
5856
+ break;
5857
+
5858
+ case emscripten_SEEK_END:
5859
+ baseAddress = _wasm_get_end_offset(fd);
5860
+ break;
5861
+
5862
+ default:
5863
+ return [null, ERRNO_CODES.EINVAL];
5864
+ }
5865
+ if (baseAddress == -1) {
5866
+ // We cannot resolve the offset within the file.
5867
+ // Let's treat this as a problem with the file descriptor.
5868
+ return [null, ERRNO_CODES.EBADF];
5869
+ }
5870
+ const resolvedOffset = baseAddress + startOffset;
5871
+ if (resolvedOffset < 0) {
5872
+ // This is not a valid offset. Report args as invalid.
5873
+ return [null, ERRNO_CODES.EINVAL];
5874
+ }
5875
+ return [resolvedOffset, 0];
5876
+ }
5877
+ const pid = PHPLoader.processId;
5878
+ switch (cmd) {
5879
+ case emscripten_F_GETLK: {
5880
+ _js_wasm_trace('fcntl(%d, F_GETLK)', fd);
5881
+ let vfsPath;
5882
+ let errno;
5883
+ [vfsPath, errno] = locking.get_vfs_path_from_fd(fd);
5884
+ if (errno !== 0) {
5885
+ _js_wasm_trace(
5886
+ 'fcntl(%d, F_GETLK) %s get_vfs_path_from_fd errno %d',
5887
+ fd,
5888
+ vfsPath,
5889
+ errno
5890
+ );
5891
+ return -ERRNO_CODES.EBADF;
5892
+ }
5893
+ if (!locking.is_path_to_shared_fs(vfsPath)) {
5894
+ _js_wasm_trace(
5895
+ "fcntl(%d, F_GETLK) locking is not implemented for non-NodeFS path '%s'",
5896
+ fd,
5897
+ vfsPath
5898
+ );
5899
+ // If not a NodeFS path, we can't lock it.
5900
+ // Default to succeeding as Emscripten does.
5901
+ update_flock_struct(flockStructAddr, {
5902
+ l_type: F_UNLCK,
5903
+ });
5904
+ return 0;
5905
+ }
5906
+ const flockStructAddr = syscallGetVarargP();
5907
+ const flockStruct = read_flock_struct(flockStructAddr);
5908
+ if (!(flockStruct.l_type in locking.fcntlToLockState)) {
5909
+ return -ERRNO_CODES.EINVAL;
5910
+ }
5911
+ errno = locking.check_lock_params(fd, flockStruct.l_type);
5912
+ if (errno !== 0) {
5913
+ _js_wasm_trace(
5914
+ 'fcntl(%d, F_GETLK) %s check_lock_params errno %d',
5915
+ fd,
5916
+ vfsPath,
5917
+ errno
5918
+ );
5919
+ return -ERRNO_CODES.EINVAL;
5920
+ }
5921
+ const requestedLockType =
5922
+ locking.fcntlToLockState[flockStruct.l_type];
5923
+ let absoluteStartOffset;
5924
+ [absoluteStartOffset, errno] = get_base_address(
5925
+ fd,
5926
+ flockStruct.l_whence,
5927
+ flockStruct.l_start
5928
+ );
5929
+ if (errno !== 0) {
5930
+ _js_wasm_trace(
5931
+ 'fcntl(%d, F_GETLK) %s get_base_address errno %d',
5932
+ fd,
5933
+ vfsPath,
5934
+ errno
5935
+ );
5936
+ return -ERRNO_CODES.EINVAL;
5937
+ }
5938
+ const nativeFilePath =
5939
+ locking.get_native_path_from_vfs_path(vfsPath);
5940
+ return PHPLoader.fileLockManager
5941
+ .findFirstConflictingByteRangeLock(nativeFilePath, {
5942
+ type: requestedLockType,
5943
+ start: absoluteStartOffset,
5944
+ end: absoluteStartOffset + flockStruct.l_len,
5945
+ pid,
5946
+ })
5947
+ .then((conflictingLock) => {
5948
+ if (conflictingLock === undefined) {
5949
+ _js_wasm_trace(
5950
+ 'fcntl(%d, F_GETLK) %s findFirstConflictingByteRangeLock type=unlocked start=0x%x end=0x%x',
5951
+ fd,
5952
+ vfsPath,
5953
+ absoluteStartOffset,
5954
+ absoluteStartOffset + flockStruct.l_len
5955
+ );
5956
+ update_flock_struct(flockStructAddr, {
5957
+ l_type: F_UNLCK,
5958
+ });
5959
+ return 0;
5960
+ }
5961
+ _js_wasm_trace(
5962
+ 'fcntl(%d, F_GETLK) %s findFirstConflictingByteRangeLock type=%s start=0x%x end=0x%x conflictingLock %d',
5963
+ fd,
5964
+ vfsPath,
5965
+ conflictingLock.type,
5966
+ conflictingLock.start,
5967
+ conflictingLock.end,
5968
+ conflictingLock.pid
5969
+ );
5970
+ const fcntlLockState =
5971
+ locking.lockStateToFcntl[conflictingLock.type];
5972
+ update_flock_struct(flockStructAddr, {
5973
+ l_type: fcntlLockState,
5974
+ l_whence: emscripten_SEEK_SET,
5975
+ l_start: conflictingLock.start,
5976
+ l_len: conflictingLock.end - conflictingLock.start,
5977
+ l_pid: conflictingLock.pid,
5978
+ });
5979
+ return 0;
5980
+ })
5981
+ .catch((e) => {
5982
+ _js_wasm_trace(
5983
+ 'fcntl(%d, F_GETLK) %s findFirstConflictingByteRangeLock error %s',
5984
+ fd,
5985
+ vfsPath,
5986
+ e
5987
+ );
5988
+ return -ERRNO_CODES.EINVAL;
5989
+ });
5990
+ }
5991
+
5992
+ case emscripten_F_SETLK: {
5993
+ _js_wasm_trace('fcntl(%d, F_SETLK)', fd);
5994
+ let vfsPath;
5995
+ let errno;
5996
+ [vfsPath, errno] = locking.get_vfs_path_from_fd(fd);
5997
+ if (errno !== 0) {
5998
+ _js_wasm_trace(
5999
+ 'fcntl(%d, F_SETLK) %s get_vfs_path_from_fd errno %d',
6000
+ fd,
6001
+ vfsPath,
6002
+ errno
6003
+ );
6004
+ return -errno;
6005
+ }
6006
+ if (!locking.is_path_to_shared_fs(vfsPath)) {
6007
+ _js_wasm_trace(
6008
+ 'fcntl(%d, F_SETLK) locking is not implemented for non-NodeFS path %s',
6009
+ fd,
6010
+ vfsPath
6011
+ );
6012
+ // If not a NodeFS path, we can't lock it.
6013
+ // Default to succeeding as Emscripten does.
6014
+ return 0;
6015
+ }
6016
+ var flockStructAddr = syscallGetVarargP();
6017
+ const flockStruct = read_flock_struct(flockStructAddr);
6018
+ let absoluteStartOffset;
6019
+ [absoluteStartOffset, errno] = get_base_address(
6020
+ fd,
6021
+ flockStruct.l_whence,
6022
+ flockStruct.l_start
6023
+ );
6024
+ if (errno !== 0) {
6025
+ _js_wasm_trace(
6026
+ 'fcntl(%d, F_SETLK) %s get_base_address errno %d',
6027
+ fd,
6028
+ vfsPath,
6029
+ errno
6030
+ );
6031
+ return -errno;
6032
+ }
6033
+ if (!(flockStruct.l_type in locking.fcntlToLockState)) {
6034
+ _js_wasm_trace(
6035
+ 'fcntl(%d, F_SETLK) %s invalid lock type %d',
6036
+ fd,
6037
+ vfsPath,
6038
+ flockStruct.l_type
6039
+ );
6040
+ return -ERRNO_CODES.EINVAL;
6041
+ }
6042
+ errno = locking.check_lock_params(fd, flockStruct.l_type);
6043
+ if (errno !== 0) {
6044
+ _js_wasm_trace(
6045
+ 'fcntl(%d, F_SETLK) %s check_lock_params errno %d',
6046
+ fd,
6047
+ vfsPath,
6048
+ errno
6049
+ );
6050
+ return -errno;
6051
+ }
6052
+ locking.maybeLockedFds.add(fd);
6053
+ const requestedLockType =
6054
+ locking.fcntlToLockState[flockStruct.l_type];
6055
+ const rangeLock = {
6056
+ type: requestedLockType,
6057
+ start: absoluteStartOffset,
6058
+ end: absoluteStartOffset + flockStruct.l_len,
6059
+ pid,
6060
+ };
6061
+ const nativeFilePath =
6062
+ locking.get_native_path_from_vfs_path(vfsPath);
6063
+ _js_wasm_trace(
6064
+ 'fcntl(%d, F_SETLK) %s calling lockFileByteRange for range lock %s',
6065
+ fd,
6066
+ vfsPath,
6067
+ rangeLock
6068
+ );
6069
+ return PHPLoader.fileLockManager
6070
+ .lockFileByteRange(nativeFilePath, rangeLock)
6071
+ .then((succeeded) => {
6072
+ _js_wasm_trace(
6073
+ 'fcntl(%d, F_SETLK) %s lockFileByteRange returned %d for range lock %s',
6074
+ fd,
6075
+ vfsPath,
6076
+ succeeded,
6077
+ rangeLock
6078
+ );
6079
+ return succeeded ? 0 : -ERRNO_CODES.EAGAIN;
6080
+ })
6081
+ .catch((e) => {
6082
+ _js_wasm_trace(
6083
+ 'fcntl(%d, F_SETLK) %s lockFileByteRange error %s for range lock %s',
6084
+ fd,
6085
+ vfsPath,
6086
+ e,
6087
+ rangeLock
6088
+ );
6089
+ return -ERRNO_CODES.EINVAL;
6090
+ });
6091
+ }
6092
+
6093
+ // @TODO: Implement waiting for lock
6094
+ case emscripten_F_SETLKW: {
6095
+ // We do not yet support the blocking form of flock().
6096
+ // We respond with EDEADLK to indicate failure
6097
+ // because it is a known errno for a failed F_SETLKW command.
6098
+ return -ERRNO_CODES.EDEADLK;
6099
+ }
6100
+
6101
+ default:
6102
+ return _builtin_fcntl64(fd, cmd, varargs);
6103
+ }
6104
+ }
6105
+
6106
+ ___syscall_fcntl64.isAsync = true;
6107
+
6108
+ function ___syscall_fdatasync(fd) {
6109
+ try {
6110
+ var stream = SYSCALLS.getStreamFromFD(fd);
6111
+ return 0;
6112
+ } catch (e) {
6113
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6114
+ return -e.errno;
6115
+ }
6116
+ }
6117
+
6118
+ function ___syscall_fstat64(fd, buf) {
6119
+ try {
6120
+ return SYSCALLS.writeStat(buf, FS.fstat(fd));
6121
+ } catch (e) {
6122
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6123
+ return -e.errno;
6124
+ }
6125
+ }
6126
+
6127
+ function ___syscall_ftruncate64(fd, length) {
6128
+ length = bigintToI53Checked(length);
6129
+ try {
6130
+ if (isNaN(length)) return 61;
6131
+ FS.ftruncate(fd, length);
6132
+ return 0;
6133
+ } catch (e) {
6134
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6135
+ return -e.errno;
6136
+ }
6137
+ }
6138
+
6139
+ function ___syscall_getcwd(buf, size) {
6140
+ try {
6141
+ if (size === 0) return -28;
6142
+ var cwd = FS.cwd();
6143
+ var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1;
6144
+ if (size < cwdLengthInBytes) return -68;
6145
+ stringToUTF8(cwd, buf, size);
6146
+ return cwdLengthInBytes;
6147
+ } catch (e) {
6148
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6149
+ return -e.errno;
6150
+ }
6151
+ }
6152
+
6153
+ function ___syscall_getdents64(fd, dirp, count) {
6154
+ try {
6155
+ var stream = SYSCALLS.getStreamFromFD(fd);
6156
+ stream.getdents ||= FS.readdir(stream.path);
6157
+ var struct_size = 280;
6158
+ var pos = 0;
6159
+ var off = FS.llseek(stream, 0, 1);
6160
+ var startIdx = Math.floor(off / struct_size);
6161
+ var endIdx = Math.min(
6162
+ stream.getdents.length,
6163
+ startIdx + Math.floor(count / struct_size)
6164
+ );
6165
+ for (var idx = startIdx; idx < endIdx; idx++) {
6166
+ var id;
6167
+ var type;
6168
+ var name = stream.getdents[idx];
6169
+ if (name === '.') {
6170
+ id = stream.node.id;
6171
+ type = 4;
6172
+ } else if (name === '..') {
6173
+ var lookup = FS.lookupPath(stream.path, {
6174
+ parent: true,
6175
+ });
6176
+ id = lookup.node.id;
6177
+ type = 4;
6178
+ } else {
6179
+ var child;
6180
+ try {
6181
+ child = FS.lookupNode(stream.node, name);
6182
+ } catch (e) {
6183
+ // If the entry is not a directory, file, or symlink, nodefs
6184
+ // lookupNode will raise EINVAL. Skip these and continue.
6185
+ if (e?.errno === 28) {
6186
+ continue;
6187
+ }
6188
+ throw e;
6189
+ }
6190
+ id = child.id;
6191
+ type = FS.isChrdev(child.mode)
6192
+ ? 2 // DT_CHR, character device.
6193
+ : FS.isDir(child.mode)
6194
+ ? 4 // DT_DIR, directory.
6195
+ : FS.isLink(child.mode)
6196
+ ? 10 // DT_LNK, symbolic link.
6197
+ : 8;
6198
+ }
6199
+ HEAP64[(dirp + pos) >> 3] = BigInt(id);
6200
+ HEAP64[(dirp + pos + 8) >> 3] = BigInt((idx + 1) * struct_size);
6201
+ HEAP16[(dirp + pos + 16) >> 1] = 280;
6202
+ HEAP8[dirp + pos + 18] = type;
6203
+ stringToUTF8(name, dirp + pos + 19, 256);
6204
+ pos += struct_size;
6205
+ }
6206
+ FS.llseek(stream, idx * struct_size, 0);
6207
+ return pos;
6208
+ } catch (e) {
6209
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6210
+ return -e.errno;
6211
+ }
6212
+ }
6213
+
6214
+ function ___syscall_getpeername(fd, addr, addrlen, d1, d2, d3) {
6215
+ try {
6216
+ var sock = getSocketFromFD(fd);
6217
+ if (!sock.daddr) {
6218
+ return -53;
6219
+ }
6220
+ var errno = writeSockaddr(
6221
+ addr,
6222
+ sock.family,
6223
+ DNS.lookup_name(sock.daddr),
6224
+ sock.dport,
6225
+ addrlen
6226
+ );
6227
+ return 0;
6228
+ } catch (e) {
6229
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6230
+ return -e.errno;
6231
+ }
6232
+ }
6233
+
6234
+ function ___syscall_getsockname(fd, addr, addrlen, d1, d2, d3) {
6235
+ try {
6236
+ var sock = getSocketFromFD(fd);
6237
+ // TODO: sock.saddr should never be undefined, see TODO in websocket_sock_ops.getname
6238
+ var errno = writeSockaddr(
6239
+ addr,
6240
+ sock.family,
6241
+ DNS.lookup_name(sock.saddr || '0.0.0.0'),
6242
+ sock.sport,
6243
+ addrlen
6244
+ );
6245
+ return 0;
6246
+ } catch (e) {
6247
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6248
+ return -e.errno;
6249
+ }
6250
+ }
6251
+
6252
+ function ___syscall_getsockopt(fd, level, optname, optval, optlen, d1) {
6253
+ try {
6254
+ var sock = getSocketFromFD(fd);
6255
+ // Minimal getsockopt aimed at resolving https://github.com/emscripten-core/emscripten/issues/2211
6256
+ // so only supports SOL_SOCKET with SO_ERROR.
6257
+ if (level === 1) {
6258
+ if (optname === 4) {
6259
+ HEAP32[optval >> 2] = sock.error;
6260
+ HEAP32[optlen >> 2] = 4;
6261
+ sock.error = null;
6262
+ // Clear the error (The SO_ERROR option obtains and then clears this field).
6263
+ return 0;
6264
+ }
6265
+ }
6266
+ return -50;
6267
+ } catch (e) {
6268
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6269
+ return -e.errno;
6270
+ }
6271
+ }
6272
+
6273
+ function ___syscall_ioctl(fd, op, varargs) {
6274
+ SYSCALLS.varargs = varargs;
6275
+ try {
6276
+ var stream = SYSCALLS.getStreamFromFD(fd);
6277
+ switch (op) {
6278
+ case 21509: {
6279
+ if (!stream.tty) return -59;
6280
+ return 0;
6281
+ }
6282
+
6283
+ case 21505: {
6284
+ if (!stream.tty) return -59;
6285
+ if (stream.tty.ops.ioctl_tcgets) {
6286
+ var termios = stream.tty.ops.ioctl_tcgets(stream);
6287
+ var argp = syscallGetVarargP();
6288
+ HEAP32[argp >> 2] = termios.c_iflag || 0;
6289
+ HEAP32[(argp + 4) >> 2] = termios.c_oflag || 0;
6290
+ HEAP32[(argp + 8) >> 2] = termios.c_cflag || 0;
6291
+ HEAP32[(argp + 12) >> 2] = termios.c_lflag || 0;
6292
+ for (var i = 0; i < 32; i++) {
6293
+ HEAP8[argp + i + 17] = termios.c_cc[i] || 0;
6294
+ }
6295
+ return 0;
6296
+ }
6297
+ return 0;
6298
+ }
6299
+
6300
+ case 21510:
6301
+ case 21511:
6302
+ case 21512: {
6303
+ if (!stream.tty) return -59;
5486
6304
  return 0;
5487
6305
  }
5488
6306
 
@@ -5836,408 +6654,28 @@ export function init(RuntimeName, PHPLoader) {
5836
6654
  },
5837
6655
  close(stream) {
5838
6656
  var pipe = stream.node.pipe;
5839
- pipe.refcnt--;
5840
- if (pipe.refcnt === 0) {
5841
- pipe.buckets = null;
5842
- }
5843
- },
5844
- },
5845
- nextname() {
5846
- if (!PIPEFS.nextname.current) {
5847
- PIPEFS.nextname.current = 0;
5848
- }
5849
- return 'pipe[' + PIPEFS.nextname.current++ + ']';
5850
- },
5851
- };
5852
-
5853
- function ___syscall_pipe(fdPtr) {
5854
- try {
5855
- if (fdPtr == 0) {
5856
- throw new FS.ErrnoError(21);
5857
- }
5858
- var res = PIPEFS.createPipe();
5859
- HEAP32[fdPtr >> 2] = res.readable_fd;
5860
- HEAP32[(fdPtr + 4) >> 2] = res.writable_fd;
5861
- return 0;
5862
- } catch (e) {
5863
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5864
- return -e.errno;
5865
- }
5866
- }
5867
-
5868
- function ___syscall_poll(fds, nfds, timeout) {
5869
- try {
5870
- var nonzero = 0;
5871
- for (var i = 0; i < nfds; i++) {
5872
- var pollfd = fds + 8 * i;
5873
- var fd = HEAP32[pollfd >> 2];
5874
- var events = HEAP16[(pollfd + 4) >> 1];
5875
- var mask = 32;
5876
- var stream = FS.getStream(fd);
5877
- if (stream) {
5878
- mask = SYSCALLS.DEFAULT_POLLMASK;
5879
- if (stream.stream_ops?.poll) {
5880
- mask = stream.stream_ops.poll(stream, -1);
5881
- }
5882
- }
5883
- mask &= events | 8 | 16;
5884
- if (mask) nonzero++;
5885
- HEAP16[(pollfd + 6) >> 1] = mask;
5886
- }
5887
- return nonzero;
5888
- } catch (e) {
5889
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5890
- return -e.errno;
5891
- }
5892
- }
5893
-
5894
- function ___syscall_readlinkat(dirfd, path, buf, bufsize) {
5895
- try {
5896
- path = SYSCALLS.getStr(path);
5897
- path = SYSCALLS.calculateAt(dirfd, path);
5898
- if (bufsize <= 0) return -28;
5899
- var ret = FS.readlink(path);
5900
- var len = Math.min(bufsize, lengthBytesUTF8(ret));
5901
- var endChar = HEAP8[buf + len];
5902
- stringToUTF8(ret, buf, bufsize + 1);
5903
- // readlink is one of the rare functions that write out a C string, but does never append a null to the output buffer(!)
5904
- // stringToUTF8() always appends a null byte, so restore the character under the null byte after the write.
5905
- HEAP8[buf + len] = endChar;
5906
- return len;
5907
- } catch (e) {
5908
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5909
- return -e.errno;
5910
- }
5911
- }
5912
-
5913
- function ___syscall_recvfrom(fd, buf, len, flags, addr, addrlen) {
5914
- try {
5915
- var sock = getSocketFromFD(fd);
5916
- var msg = sock.sock_ops.recvmsg(
5917
- sock,
5918
- len,
5919
- typeof flags !== 'undefined' ? flags : 0
5920
- );
5921
- if (!msg) return 0;
5922
- // socket is closed
5923
- if (addr) {
5924
- var errno = writeSockaddr(
5925
- addr,
5926
- sock.family,
5927
- DNS.lookup_name(msg.addr),
5928
- msg.port,
5929
- addrlen
5930
- );
5931
- }
5932
- HEAPU8.set(msg.buffer, buf);
5933
- return msg.buffer.byteLength;
5934
- } catch (e) {
5935
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5936
- return -e.errno;
5937
- }
5938
- }
5939
-
5940
- function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) {
5941
- try {
5942
- oldpath = SYSCALLS.getStr(oldpath);
5943
- newpath = SYSCALLS.getStr(newpath);
5944
- oldpath = SYSCALLS.calculateAt(olddirfd, oldpath);
5945
- newpath = SYSCALLS.calculateAt(newdirfd, newpath);
5946
- FS.rename(oldpath, newpath);
5947
- return 0;
5948
- } catch (e) {
5949
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5950
- return -e.errno;
5951
- }
5952
- }
5953
-
5954
- function ___syscall_rmdir(path) {
5955
- try {
5956
- path = SYSCALLS.getStr(path);
5957
- FS.rmdir(path);
5958
- return 0;
5959
- } catch (e) {
5960
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5961
- return -e.errno;
5962
- }
5963
- }
5964
-
5965
- function ___syscall_sendto(fd, message, length, flags, addr, addr_len) {
5966
- try {
5967
- var sock = getSocketFromFD(fd);
5968
- if (!addr) {
5969
- // send, no address provided
5970
- return FS.write(sock.stream, HEAP8, message, length);
5971
- }
5972
- var dest = getSocketAddress(addr, addr_len);
5973
- // sendto an address
5974
- return sock.sock_ops.sendmsg(
5975
- sock,
5976
- HEAP8,
5977
- message,
5978
- length,
5979
- dest.addr,
5980
- dest.port
5981
- );
5982
- } catch (e) {
5983
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5984
- return -e.errno;
5985
- }
5986
- }
5987
-
5988
- function ___syscall_socket(domain, type, protocol) {
5989
- try {
5990
- var sock = SOCKFS.createSocket(domain, type, protocol);
5991
- return sock.stream.fd;
5992
- } catch (e) {
5993
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
5994
- return -e.errno;
5995
- }
5996
- }
5997
-
5998
- function ___syscall_stat64(path, buf) {
5999
- try {
6000
- path = SYSCALLS.getStr(path);
6001
- return SYSCALLS.writeStat(buf, FS.stat(path));
6002
- } catch (e) {
6003
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6004
- return -e.errno;
6005
- }
6006
- }
6007
-
6008
- function ___syscall_statfs64(path, size, buf) {
6009
- try {
6010
- SYSCALLS.writeStatFs(buf, FS.statfs(SYSCALLS.getStr(path)));
6011
- return 0;
6012
- } catch (e) {
6013
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6014
- return -e.errno;
6015
- }
6016
- }
6017
-
6018
- function ___syscall_symlinkat(target, dirfd, linkpath) {
6019
- try {
6020
- target = SYSCALLS.getStr(target);
6021
- linkpath = SYSCALLS.getStr(linkpath);
6022
- linkpath = SYSCALLS.calculateAt(dirfd, linkpath);
6023
- FS.symlink(target, linkpath);
6024
- return 0;
6025
- } catch (e) {
6026
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6027
- return -e.errno;
6028
- }
6029
- }
6030
-
6031
- function ___syscall_unlinkat(dirfd, path, flags) {
6032
- try {
6033
- path = SYSCALLS.getStr(path);
6034
- path = SYSCALLS.calculateAt(dirfd, path);
6035
- if (flags === 0) {
6036
- FS.unlink(path);
6037
- } else if (flags === 512) {
6038
- FS.rmdir(path);
6039
- } else {
6040
- abort('Invalid flags passed to unlinkat');
6041
- }
6042
- return 0;
6043
- } catch (e) {
6044
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6045
- return -e.errno;
6046
- }
6047
- }
6048
-
6049
- var readI53FromI64 = (ptr) =>
6050
- HEAPU32[ptr >> 2] + HEAP32[(ptr + 4) >> 2] * 4294967296;
6051
-
6052
- function ___syscall_utimensat(dirfd, path, times, flags) {
6053
- try {
6054
- path = SYSCALLS.getStr(path);
6055
- path = SYSCALLS.calculateAt(dirfd, path, true);
6056
- var now = Date.now(),
6057
- atime,
6058
- mtime;
6059
- if (!times) {
6060
- atime = now;
6061
- mtime = now;
6062
- } else {
6063
- var seconds = readI53FromI64(times);
6064
- var nanoseconds = HEAP32[(times + 8) >> 2];
6065
- if (nanoseconds == 1073741823) {
6066
- atime = now;
6067
- } else if (nanoseconds == 1073741822) {
6068
- atime = null;
6069
- } else {
6070
- atime = seconds * 1e3 + nanoseconds / (1e3 * 1e3);
6071
- }
6072
- times += 16;
6073
- seconds = readI53FromI64(times);
6074
- nanoseconds = HEAP32[(times + 8) >> 2];
6075
- if (nanoseconds == 1073741823) {
6076
- mtime = now;
6077
- } else if (nanoseconds == 1073741822) {
6078
- mtime = null;
6079
- } else {
6080
- mtime = seconds * 1e3 + nanoseconds / (1e3 * 1e3);
6657
+ pipe.refcnt--;
6658
+ if (pipe.refcnt === 0) {
6659
+ pipe.buckets = null;
6081
6660
  }
6661
+ },
6662
+ },
6663
+ nextname() {
6664
+ if (!PIPEFS.nextname.current) {
6665
+ PIPEFS.nextname.current = 0;
6082
6666
  }
6083
- // null here means UTIME_OMIT was passed. If both were set to UTIME_OMIT then
6084
- // we can skip the call completely.
6085
- if ((mtime ?? atime) !== null) {
6086
- FS.utime(path, atime, mtime);
6087
- }
6088
- return 0;
6089
- } catch (e) {
6090
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6091
- return -e.errno;
6092
- }
6093
- }
6094
-
6095
- var __abort_js = () => abort('');
6096
-
6097
- var __emscripten_lookup_name = (name) => {
6098
- // uint32_t _emscripten_lookup_name(const char *name);
6099
- var nameString = UTF8ToString(name);
6100
- return inetPton4(DNS.lookup_name(nameString));
6101
- };
6102
-
6103
- var runtimeKeepaliveCounter = 0;
6104
-
6105
- var __emscripten_runtime_keepalive_clear = () => {
6106
- noExitRuntime = false;
6107
- runtimeKeepaliveCounter = 0;
6108
- };
6109
-
6110
- function __gmtime_js(time, tmPtr) {
6111
- time = bigintToI53Checked(time);
6112
- var date = new Date(time * 1e3);
6113
- HEAP32[tmPtr >> 2] = date.getUTCSeconds();
6114
- HEAP32[(tmPtr + 4) >> 2] = date.getUTCMinutes();
6115
- HEAP32[(tmPtr + 8) >> 2] = date.getUTCHours();
6116
- HEAP32[(tmPtr + 12) >> 2] = date.getUTCDate();
6117
- HEAP32[(tmPtr + 16) >> 2] = date.getUTCMonth();
6118
- HEAP32[(tmPtr + 20) >> 2] = date.getUTCFullYear() - 1900;
6119
- HEAP32[(tmPtr + 24) >> 2] = date.getUTCDay();
6120
- var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0);
6121
- var yday = ((date.getTime() - start) / (1e3 * 60 * 60 * 24)) | 0;
6122
- HEAP32[(tmPtr + 28) >> 2] = yday;
6123
- }
6124
-
6125
- var isLeapYear = (year) =>
6126
- year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
6127
-
6128
- var MONTH_DAYS_LEAP_CUMULATIVE = [
6129
- 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
6130
- ];
6131
-
6132
- var MONTH_DAYS_REGULAR_CUMULATIVE = [
6133
- 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
6134
- ];
6135
-
6136
- var ydayFromDate = (date) => {
6137
- var leap = isLeapYear(date.getFullYear());
6138
- var monthDaysCumulative = leap
6139
- ? MONTH_DAYS_LEAP_CUMULATIVE
6140
- : MONTH_DAYS_REGULAR_CUMULATIVE;
6141
- var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1;
6142
- // -1 since it's days since Jan 1
6143
- return yday;
6144
- };
6145
-
6146
- function __localtime_js(time, tmPtr) {
6147
- time = bigintToI53Checked(time);
6148
- var date = new Date(time * 1e3);
6149
- HEAP32[tmPtr >> 2] = date.getSeconds();
6150
- HEAP32[(tmPtr + 4) >> 2] = date.getMinutes();
6151
- HEAP32[(tmPtr + 8) >> 2] = date.getHours();
6152
- HEAP32[(tmPtr + 12) >> 2] = date.getDate();
6153
- HEAP32[(tmPtr + 16) >> 2] = date.getMonth();
6154
- HEAP32[(tmPtr + 20) >> 2] = date.getFullYear() - 1900;
6155
- HEAP32[(tmPtr + 24) >> 2] = date.getDay();
6156
- var yday = ydayFromDate(date) | 0;
6157
- HEAP32[(tmPtr + 28) >> 2] = yday;
6158
- HEAP32[(tmPtr + 36) >> 2] = -(date.getTimezoneOffset() * 60);
6159
- // Attention: DST is in December in South, and some regions don't have DST at all.
6160
- var start = new Date(date.getFullYear(), 0, 1);
6161
- var summerOffset = new Date(
6162
- date.getFullYear(),
6163
- 6,
6164
- 1
6165
- ).getTimezoneOffset();
6166
- var winterOffset = start.getTimezoneOffset();
6167
- var dst =
6168
- (summerOffset != winterOffset &&
6169
- date.getTimezoneOffset() ==
6170
- Math.min(winterOffset, summerOffset)) | 0;
6171
- HEAP32[(tmPtr + 32) >> 2] = dst;
6172
- }
6173
-
6174
- var __mktime_js = function (tmPtr) {
6175
- var ret = (() => {
6176
- var date = new Date(
6177
- HEAP32[(tmPtr + 20) >> 2] + 1900,
6178
- HEAP32[(tmPtr + 16) >> 2],
6179
- HEAP32[(tmPtr + 12) >> 2],
6180
- HEAP32[(tmPtr + 8) >> 2],
6181
- HEAP32[(tmPtr + 4) >> 2],
6182
- HEAP32[tmPtr >> 2],
6183
- 0
6184
- );
6185
- // There's an ambiguous hour when the time goes back; the tm_isdst field is
6186
- // used to disambiguate it. Date() basically guesses, so we fix it up if it
6187
- // guessed wrong, or fill in tm_isdst with the guess if it's -1.
6188
- var dst = HEAP32[(tmPtr + 32) >> 2];
6189
- var guessedOffset = date.getTimezoneOffset();
6190
- var start = new Date(date.getFullYear(), 0, 1);
6191
- var summerOffset = new Date(
6192
- date.getFullYear(),
6193
- 6,
6194
- 1
6195
- ).getTimezoneOffset();
6196
- var winterOffset = start.getTimezoneOffset();
6197
- var dstOffset = Math.min(winterOffset, summerOffset);
6198
- // DST is in December in South
6199
- if (dst < 0) {
6200
- // Attention: some regions don't have DST at all.
6201
- HEAP32[(tmPtr + 32) >> 2] = Number(
6202
- summerOffset != winterOffset && dstOffset == guessedOffset
6203
- );
6204
- } else if (dst > 0 != (dstOffset == guessedOffset)) {
6205
- var nonDstOffset = Math.max(winterOffset, summerOffset);
6206
- var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
6207
- // Don't try setMinutes(date.getMinutes() + ...) -- it's messed up.
6208
- date.setTime(
6209
- date.getTime() + (trueOffset - guessedOffset) * 6e4
6210
- );
6211
- }
6212
- HEAP32[(tmPtr + 24) >> 2] = date.getDay();
6213
- var yday = ydayFromDate(date) | 0;
6214
- HEAP32[(tmPtr + 28) >> 2] = yday;
6215
- // To match expected behavior, update fields from date
6216
- HEAP32[tmPtr >> 2] = date.getSeconds();
6217
- HEAP32[(tmPtr + 4) >> 2] = date.getMinutes();
6218
- HEAP32[(tmPtr + 8) >> 2] = date.getHours();
6219
- HEAP32[(tmPtr + 12) >> 2] = date.getDate();
6220
- HEAP32[(tmPtr + 16) >> 2] = date.getMonth();
6221
- HEAP32[(tmPtr + 20) >> 2] = date.getYear();
6222
- var timeMs = date.getTime();
6223
- if (isNaN(timeMs)) {
6224
- return -1;
6225
- }
6226
- // Return time in microseconds
6227
- return timeMs / 1e3;
6228
- })();
6229
- return BigInt(ret);
6667
+ return 'pipe[' + PIPEFS.nextname.current++ + ']';
6668
+ },
6230
6669
  };
6231
6670
 
6232
- function __mmap_js(len, prot, flags, fd, offset, allocated, addr) {
6233
- offset = bigintToI53Checked(offset);
6671
+ function ___syscall_pipe(fdPtr) {
6234
6672
  try {
6235
- if (isNaN(offset)) return 61;
6236
- var stream = SYSCALLS.getStreamFromFD(fd);
6237
- var res = FS.mmap(stream, len, offset, prot, flags);
6238
- var ptr = res.ptr;
6239
- HEAP32[allocated >> 2] = res.allocated;
6240
- HEAPU32[addr >> 2] = ptr;
6673
+ if (fdPtr == 0) {
6674
+ throw new FS.ErrnoError(21);
6675
+ }
6676
+ var res = PIPEFS.createPipe();
6677
+ HEAP32[fdPtr >> 2] = res.readable_fd;
6678
+ HEAP32[(fdPtr + 4) >> 2] = res.writable_fd;
6241
6679
  return 0;
6242
6680
  } catch (e) {
6243
6681
  if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
@@ -6245,991 +6683,1073 @@ export function init(RuntimeName, PHPLoader) {
6245
6683
  }
6246
6684
  }
6247
6685
 
6248
- function __munmap_js(addr, len, prot, flags, fd, offset) {
6249
- offset = bigintToI53Checked(offset);
6686
+ function ___syscall_poll(fds, nfds, timeout) {
6250
6687
  try {
6251
- var stream = SYSCALLS.getStreamFromFD(fd);
6252
- if (prot & 2) {
6253
- SYSCALLS.doMsync(addr, stream, len, flags, offset);
6688
+ var nonzero = 0;
6689
+ for (var i = 0; i < nfds; i++) {
6690
+ var pollfd = fds + 8 * i;
6691
+ var fd = HEAP32[pollfd >> 2];
6692
+ var events = HEAP16[(pollfd + 4) >> 1];
6693
+ var mask = 32;
6694
+ var stream = FS.getStream(fd);
6695
+ if (stream) {
6696
+ mask = SYSCALLS.DEFAULT_POLLMASK;
6697
+ if (stream.stream_ops?.poll) {
6698
+ mask = stream.stream_ops.poll(stream, -1);
6699
+ }
6700
+ }
6701
+ mask &= events | 8 | 16;
6702
+ if (mask) nonzero++;
6703
+ HEAP16[(pollfd + 6) >> 1] = mask;
6254
6704
  }
6705
+ return nonzero;
6255
6706
  } catch (e) {
6256
6707
  if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6257
6708
  return -e.errno;
6258
6709
  }
6259
6710
  }
6260
6711
 
6261
- var timers = {};
6262
-
6263
- var handleException = (e) => {
6264
- // Certain exception types we do not treat as errors since they are used for
6265
- // internal control flow.
6266
- // 1. ExitStatus, which is thrown by exit()
6267
- // 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others
6268
- // that wish to return to JS event loop.
6269
- if (e instanceof ExitStatus || e == 'unwind') {
6270
- return EXITSTATUS;
6271
- }
6272
- quit_(1, e);
6273
- };
6274
-
6275
- var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
6276
-
6277
- var _proc_exit = (code) => {
6278
- EXITSTATUS = code;
6279
- if (!keepRuntimeAlive()) {
6280
- Module['onExit']?.(code);
6281
- ABORT = true;
6282
- }
6283
- quit_(code, new ExitStatus(code));
6284
- };
6285
-
6286
- /** @suppress {duplicate } */ /** @param {boolean|number=} implicit */ var exitJS =
6287
- (status, implicit) => {
6288
- EXITSTATUS = status;
6289
- if (!keepRuntimeAlive()) {
6290
- exitRuntime();
6291
- }
6292
- _proc_exit(status);
6293
- };
6294
-
6295
- var _exit = exitJS;
6296
-
6297
- Module['_exit'] = _exit;
6298
-
6299
- var maybeExit = () => {
6300
- if (runtimeExited) {
6301
- return;
6302
- }
6303
- if (!keepRuntimeAlive()) {
6304
- try {
6305
- _exit(EXITSTATUS);
6306
- } catch (e) {
6307
- handleException(e);
6308
- }
6712
+ function ___syscall_readlinkat(dirfd, path, buf, bufsize) {
6713
+ try {
6714
+ path = SYSCALLS.getStr(path);
6715
+ path = SYSCALLS.calculateAt(dirfd, path);
6716
+ if (bufsize <= 0) return -28;
6717
+ var ret = FS.readlink(path);
6718
+ var len = Math.min(bufsize, lengthBytesUTF8(ret));
6719
+ var endChar = HEAP8[buf + len];
6720
+ stringToUTF8(ret, buf, bufsize + 1);
6721
+ // readlink is one of the rare functions that write out a C string, but does never append a null to the output buffer(!)
6722
+ // stringToUTF8() always appends a null byte, so restore the character under the null byte after the write.
6723
+ HEAP8[buf + len] = endChar;
6724
+ return len;
6725
+ } catch (e) {
6726
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6727
+ return -e.errno;
6309
6728
  }
6310
- };
6729
+ }
6311
6730
 
6312
- var callUserCallback = (func) => {
6313
- if (runtimeExited || ABORT) {
6314
- return;
6315
- }
6731
+ function ___syscall_recvfrom(fd, buf, len, flags, addr, addrlen) {
6316
6732
  try {
6317
- func();
6318
- maybeExit();
6733
+ var sock = getSocketFromFD(fd);
6734
+ var msg = sock.sock_ops.recvmsg(
6735
+ sock,
6736
+ len,
6737
+ typeof flags !== 'undefined' ? flags : 0
6738
+ );
6739
+ if (!msg) return 0;
6740
+ // socket is closed
6741
+ if (addr) {
6742
+ var errno = writeSockaddr(
6743
+ addr,
6744
+ sock.family,
6745
+ DNS.lookup_name(msg.addr),
6746
+ msg.port,
6747
+ addrlen
6748
+ );
6749
+ }
6750
+ HEAPU8.set(msg.buffer, buf);
6751
+ return msg.buffer.byteLength;
6319
6752
  } catch (e) {
6320
- handleException(e);
6321
- }
6322
- };
6323
-
6324
- var _emscripten_get_now = () => performance.now();
6325
-
6326
- var __setitimer_js = (which, timeout_ms) => {
6327
- // First, clear any existing timer.
6328
- if (timers[which]) {
6329
- clearTimeout(timers[which].id);
6330
- delete timers[which];
6753
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6754
+ return -e.errno;
6331
6755
  }
6332
- // A timeout of zero simply cancels the current timeout so we have nothing
6333
- // more to do.
6334
- if (!timeout_ms) return 0;
6335
- var id = setTimeout(() => {
6336
- delete timers[which];
6337
- callUserCallback(() =>
6338
- __emscripten_timeout(which, _emscripten_get_now())
6339
- );
6340
- }, timeout_ms);
6341
- timers[which] = {
6342
- id,
6343
- timeout_ms,
6344
- };
6345
- return 0;
6346
- };
6756
+ }
6347
6757
 
6348
- var __tzset_js = (timezone, daylight, std_name, dst_name) => {
6349
- // TODO: Use (malleable) environment variables instead of system settings.
6350
- var currentYear = new Date().getFullYear();
6351
- var winter = new Date(currentYear, 0, 1);
6352
- var summer = new Date(currentYear, 6, 1);
6353
- var winterOffset = winter.getTimezoneOffset();
6354
- var summerOffset = summer.getTimezoneOffset();
6355
- // Local standard timezone offset. Local standard time is not adjusted for
6356
- // daylight savings. This code uses the fact that getTimezoneOffset returns
6357
- // a greater value during Standard Time versus Daylight Saving Time (DST).
6358
- // Thus it determines the expected output during Standard Time, and it
6359
- // compares whether the output of the given date the same (Standard) or less
6360
- // (DST).
6361
- var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
6362
- // timezone is specified as seconds west of UTC ("The external variable
6363
- // `timezone` shall be set to the difference, in seconds, between
6364
- // Coordinated Universal Time (UTC) and local standard time."), the same
6365
- // as returned by stdTimezoneOffset.
6366
- // See http://pubs.opengroup.org/onlinepubs/009695399/functions/tzset.html
6367
- HEAPU32[timezone >> 2] = stdTimezoneOffset * 60;
6368
- HEAP32[daylight >> 2] = Number(winterOffset != summerOffset);
6369
- var extractZone = (timezoneOffset) => {
6370
- // Why inverse sign?
6371
- // Read here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
6372
- var sign = timezoneOffset >= 0 ? '-' : '+';
6373
- var absOffset = Math.abs(timezoneOffset);
6374
- var hours = String(Math.floor(absOffset / 60)).padStart(2, '0');
6375
- var minutes = String(absOffset % 60).padStart(2, '0');
6376
- return `UTC${sign}${hours}${minutes}`;
6377
- };
6378
- var winterName = extractZone(winterOffset);
6379
- var summerName = extractZone(summerOffset);
6380
- if (summerOffset < winterOffset) {
6381
- // Northern hemisphere
6382
- stringToUTF8(winterName, std_name, 17);
6383
- stringToUTF8(summerName, dst_name, 17);
6384
- } else {
6385
- stringToUTF8(winterName, dst_name, 17);
6386
- stringToUTF8(summerName, std_name, 17);
6758
+ function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) {
6759
+ try {
6760
+ oldpath = SYSCALLS.getStr(oldpath);
6761
+ newpath = SYSCALLS.getStr(newpath);
6762
+ oldpath = SYSCALLS.calculateAt(olddirfd, oldpath);
6763
+ newpath = SYSCALLS.calculateAt(newdirfd, newpath);
6764
+ FS.rename(oldpath, newpath);
6765
+ return 0;
6766
+ } catch (e) {
6767
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6768
+ return -e.errno;
6387
6769
  }
6388
- };
6389
-
6390
- var _emscripten_date_now = () => Date.now();
6391
-
6392
- var nowIsMonotonic = 1;
6393
-
6394
- var checkWasiClock = (clock_id) => clock_id >= 0 && clock_id <= 3;
6770
+ }
6395
6771
 
6396
- function _clock_time_get(clk_id, ignored_precision, ptime) {
6397
- ignored_precision = bigintToI53Checked(ignored_precision);
6398
- if (!checkWasiClock(clk_id)) {
6399
- return 28;
6400
- }
6401
- var now;
6402
- // all wasi clocks but realtime are monotonic
6403
- if (clk_id === 0) {
6404
- now = _emscripten_date_now();
6405
- } else if (nowIsMonotonic) {
6406
- now = _emscripten_get_now();
6407
- } else {
6408
- return 52;
6772
+ function ___syscall_rmdir(path) {
6773
+ try {
6774
+ path = SYSCALLS.getStr(path);
6775
+ FS.rmdir(path);
6776
+ return 0;
6777
+ } catch (e) {
6778
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6779
+ return -e.errno;
6409
6780
  }
6410
- // "now" is in ms, and wasi times are in ns.
6411
- var nsec = Math.round(now * 1e3 * 1e3);
6412
- HEAP64[ptime >> 3] = BigInt(nsec);
6413
- return 0;
6414
6781
  }
6415
6782
 
6416
- var getHeapMax = () =>
6417
- // Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate
6418
- // full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side
6419
- // for any code that deals with heap sizes, which would require special
6420
- // casing all heap size related code to treat 0 specially.
6421
- 2147483648;
6422
-
6423
- var _emscripten_get_heap_max = () => getHeapMax();
6424
-
6425
- var growMemory = (size) => {
6426
- var b = wasmMemory.buffer;
6427
- var pages = ((size - b.byteLength + 65535) / 65536) | 0;
6783
+ function ___syscall_sendto(fd, message, length, flags, addr, addr_len) {
6428
6784
  try {
6429
- // round size grow request up to wasm page size (fixed 64KB per spec)
6430
- wasmMemory.grow(pages);
6431
- // .grow() takes a delta compared to the previous size
6432
- updateMemoryViews();
6433
- return 1;
6434
- } catch (e) {}
6435
- };
6436
-
6437
- var _emscripten_resize_heap = (requestedSize) => {
6438
- var oldSize = HEAPU8.length;
6439
- // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
6440
- requestedSize >>>= 0;
6441
- // With multithreaded builds, races can happen (another thread might increase the size
6442
- // in between), so return a failure, and let the caller retry.
6443
- // Memory resize rules:
6444
- // 1. Always increase heap size to at least the requested size, rounded up
6445
- // to next page multiple.
6446
- // 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap
6447
- // geometrically: increase the heap size according to
6448
- // MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most
6449
- // overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB).
6450
- // 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap
6451
- // linearly: increase the heap size by at least
6452
- // MEMORY_GROWTH_LINEAR_STEP bytes.
6453
- // 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by
6454
- // MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest
6455
- // 4. If we were unable to allocate as much memory, it may be due to
6456
- // over-eager decision to excessively reserve due to (3) above.
6457
- // Hence if an allocation fails, cut down on the amount of excess
6458
- // growth, in an attempt to succeed to perform a smaller allocation.
6459
- // A limit is set for how much we can grow. We should not exceed that
6460
- // (the wasm binary specifies it, so if we tried, we'd fail anyhow).
6461
- var maxHeapSize = getHeapMax();
6462
- if (requestedSize > maxHeapSize) {
6463
- return false;
6464
- }
6465
- // Loop through potential heap size increases. If we attempt a too eager
6466
- // reservation that fails, cut down on the attempted size and reserve a
6467
- // smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
6468
- for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
6469
- var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown);
6470
- // ensure geometric growth
6471
- // but limit overreserving (default to capping at +96MB overgrowth at most)
6472
- overGrownHeapSize = Math.min(
6473
- overGrownHeapSize,
6474
- requestedSize + 100663296
6475
- );
6476
- var newSize = Math.min(
6477
- maxHeapSize,
6478
- alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536)
6479
- );
6480
- var replacement = growMemory(newSize);
6481
- if (replacement) {
6482
- return true;
6785
+ var sock = getSocketFromFD(fd);
6786
+ if (!addr) {
6787
+ // send, no address provided
6788
+ return FS.write(sock.stream, HEAP8, message, length);
6483
6789
  }
6790
+ var dest = getSocketAddress(addr, addr_len);
6791
+ // sendto an address
6792
+ return sock.sock_ops.sendmsg(
6793
+ sock,
6794
+ HEAP8,
6795
+ message,
6796
+ length,
6797
+ dest.addr,
6798
+ dest.port
6799
+ );
6800
+ } catch (e) {
6801
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6802
+ return -e.errno;
6484
6803
  }
6485
- return false;
6486
- };
6487
-
6488
- var runtimeKeepalivePush = () => {
6489
- runtimeKeepaliveCounter += 1;
6490
- };
6491
-
6492
- var runtimeKeepalivePop = () => {
6493
- runtimeKeepaliveCounter -= 1;
6494
- };
6804
+ }
6495
6805
 
6496
- /** @param {number=} timeout */ var safeSetTimeout = (func, timeout) => {
6497
- runtimeKeepalivePush();
6498
- return setTimeout(() => {
6499
- runtimeKeepalivePop();
6500
- callUserCallback(func);
6501
- }, timeout);
6502
- };
6806
+ function ___syscall_socket(domain, type, protocol) {
6807
+ try {
6808
+ var sock = SOCKFS.createSocket(domain, type, protocol);
6809
+ return sock.stream.fd;
6810
+ } catch (e) {
6811
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6812
+ return -e.errno;
6813
+ }
6814
+ }
6503
6815
 
6504
- var _emscripten_sleep = (ms) =>
6505
- Asyncify.handleSleep((wakeUp) => safeSetTimeout(wakeUp, ms));
6816
+ function ___syscall_stat64(path, buf) {
6817
+ try {
6818
+ path = SYSCALLS.getStr(path);
6819
+ return SYSCALLS.writeStat(buf, FS.stat(path));
6820
+ } catch (e) {
6821
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6822
+ return -e.errno;
6823
+ }
6824
+ }
6506
6825
 
6507
- Module['_emscripten_sleep'] = _emscripten_sleep;
6826
+ function ___syscall_statfs64(path, size, buf) {
6827
+ try {
6828
+ SYSCALLS.writeStatFs(buf, FS.statfs(SYSCALLS.getStr(path)));
6829
+ return 0;
6830
+ } catch (e) {
6831
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6832
+ return -e.errno;
6833
+ }
6834
+ }
6508
6835
 
6509
- _emscripten_sleep.isAsync = true;
6836
+ function ___syscall_symlinkat(target, dirfd, linkpath) {
6837
+ try {
6838
+ target = SYSCALLS.getStr(target);
6839
+ linkpath = SYSCALLS.getStr(linkpath);
6840
+ linkpath = SYSCALLS.calculateAt(dirfd, linkpath);
6841
+ FS.symlink(target, linkpath);
6842
+ return 0;
6843
+ } catch (e) {
6844
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6845
+ return -e.errno;
6846
+ }
6847
+ }
6510
6848
 
6511
- var ENV = PHPLoader.ENV || {};
6849
+ function ___syscall_unlinkat(dirfd, path, flags) {
6850
+ try {
6851
+ path = SYSCALLS.getStr(path);
6852
+ path = SYSCALLS.calculateAt(dirfd, path);
6853
+ if (flags === 0) {
6854
+ FS.unlink(path);
6855
+ } else if (flags === 512) {
6856
+ FS.rmdir(path);
6857
+ } else {
6858
+ abort('Invalid flags passed to unlinkat');
6859
+ }
6860
+ return 0;
6861
+ } catch (e) {
6862
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6863
+ return -e.errno;
6864
+ }
6865
+ }
6512
6866
 
6513
- var getExecutableName = () => thisProgram || './this.program';
6867
+ var readI53FromI64 = (ptr) =>
6868
+ HEAPU32[ptr >> 2] + HEAP32[(ptr + 4) >> 2] * 4294967296;
6514
6869
 
6515
- var getEnvStrings = () => {
6516
- if (!getEnvStrings.strings) {
6517
- // Default values.
6518
- // Browser language detection #8751
6519
- var lang =
6520
- (
6521
- (typeof navigator == 'object' &&
6522
- navigator.languages &&
6523
- navigator.languages[0]) ||
6524
- 'C'
6525
- ).replace('-', '_') + '.UTF-8';
6526
- var env = {
6527
- USER: 'web_user',
6528
- LOGNAME: 'web_user',
6529
- PATH: '/',
6530
- PWD: '/',
6531
- HOME: '/home/web_user',
6532
- LANG: lang,
6533
- _: getExecutableName(),
6534
- };
6535
- // Apply the user-provided values, if any.
6536
- for (var x in ENV) {
6537
- // x is a key in ENV; if ENV[x] is undefined, that means it was
6538
- // explicitly set to be so. We allow user code to do that to
6539
- // force variables with default values to remain unset.
6540
- if (ENV[x] === undefined) delete env[x];
6541
- else env[x] = ENV[x];
6870
+ function ___syscall_utimensat(dirfd, path, times, flags) {
6871
+ try {
6872
+ path = SYSCALLS.getStr(path);
6873
+ path = SYSCALLS.calculateAt(dirfd, path, true);
6874
+ var now = Date.now(),
6875
+ atime,
6876
+ mtime;
6877
+ if (!times) {
6878
+ atime = now;
6879
+ mtime = now;
6880
+ } else {
6881
+ var seconds = readI53FromI64(times);
6882
+ var nanoseconds = HEAP32[(times + 8) >> 2];
6883
+ if (nanoseconds == 1073741823) {
6884
+ atime = now;
6885
+ } else if (nanoseconds == 1073741822) {
6886
+ atime = null;
6887
+ } else {
6888
+ atime = seconds * 1e3 + nanoseconds / (1e3 * 1e3);
6889
+ }
6890
+ times += 16;
6891
+ seconds = readI53FromI64(times);
6892
+ nanoseconds = HEAP32[(times + 8) >> 2];
6893
+ if (nanoseconds == 1073741823) {
6894
+ mtime = now;
6895
+ } else if (nanoseconds == 1073741822) {
6896
+ mtime = null;
6897
+ } else {
6898
+ mtime = seconds * 1e3 + nanoseconds / (1e3 * 1e3);
6899
+ }
6542
6900
  }
6543
- var strings = [];
6544
- for (var x in env) {
6545
- strings.push(`${x}=${env[x]}`);
6901
+ // null here means UTIME_OMIT was passed. If both were set to UTIME_OMIT then
6902
+ // we can skip the call completely.
6903
+ if ((mtime ?? atime) !== null) {
6904
+ FS.utime(path, atime, mtime);
6546
6905
  }
6547
- getEnvStrings.strings = strings;
6906
+ return 0;
6907
+ } catch (e) {
6908
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6909
+ return -e.errno;
6548
6910
  }
6549
- return getEnvStrings.strings;
6550
- };
6911
+ }
6551
6912
 
6552
- var stringToAscii = (str, buffer) => {
6553
- for (var i = 0; i < str.length; ++i) {
6554
- HEAP8[buffer++] = str.charCodeAt(i);
6555
- }
6556
- // Null-terminate the string
6557
- HEAP8[buffer] = 0;
6913
+ var __abort_js = () => abort('');
6914
+
6915
+ var __emscripten_lookup_name = (name) => {
6916
+ // uint32_t _emscripten_lookup_name(const char *name);
6917
+ var nameString = UTF8ToString(name);
6918
+ return inetPton4(DNS.lookup_name(nameString));
6558
6919
  };
6559
6920
 
6560
- var _environ_get = (__environ, environ_buf) => {
6561
- var bufSize = 0;
6562
- getEnvStrings().forEach((string, i) => {
6563
- var ptr = environ_buf + bufSize;
6564
- HEAPU32[(__environ + i * 4) >> 2] = ptr;
6565
- stringToAscii(string, ptr);
6566
- bufSize += string.length + 1;
6567
- });
6568
- return 0;
6921
+ var runtimeKeepaliveCounter = 0;
6922
+
6923
+ var __emscripten_runtime_keepalive_clear = () => {
6924
+ noExitRuntime = false;
6925
+ runtimeKeepaliveCounter = 0;
6569
6926
  };
6570
6927
 
6571
- var _environ_sizes_get = (penviron_count, penviron_buf_size) => {
6572
- var strings = getEnvStrings();
6573
- HEAPU32[penviron_count >> 2] = strings.length;
6574
- var bufSize = 0;
6575
- strings.forEach((string) => (bufSize += string.length + 1));
6576
- HEAPU32[penviron_buf_size >> 2] = bufSize;
6577
- return 0;
6928
+ function __gmtime_js(time, tmPtr) {
6929
+ time = bigintToI53Checked(time);
6930
+ var date = new Date(time * 1e3);
6931
+ HEAP32[tmPtr >> 2] = date.getUTCSeconds();
6932
+ HEAP32[(tmPtr + 4) >> 2] = date.getUTCMinutes();
6933
+ HEAP32[(tmPtr + 8) >> 2] = date.getUTCHours();
6934
+ HEAP32[(tmPtr + 12) >> 2] = date.getUTCDate();
6935
+ HEAP32[(tmPtr + 16) >> 2] = date.getUTCMonth();
6936
+ HEAP32[(tmPtr + 20) >> 2] = date.getUTCFullYear() - 1900;
6937
+ HEAP32[(tmPtr + 24) >> 2] = date.getUTCDay();
6938
+ var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0);
6939
+ var yday = ((date.getTime() - start) / (1e3 * 60 * 60 * 24)) | 0;
6940
+ HEAP32[(tmPtr + 28) >> 2] = yday;
6941
+ }
6942
+
6943
+ var isLeapYear = (year) =>
6944
+ year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
6945
+
6946
+ var MONTH_DAYS_LEAP_CUMULATIVE = [
6947
+ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
6948
+ ];
6949
+
6950
+ var MONTH_DAYS_REGULAR_CUMULATIVE = [
6951
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
6952
+ ];
6953
+
6954
+ var ydayFromDate = (date) => {
6955
+ var leap = isLeapYear(date.getFullYear());
6956
+ var monthDaysCumulative = leap
6957
+ ? MONTH_DAYS_LEAP_CUMULATIVE
6958
+ : MONTH_DAYS_REGULAR_CUMULATIVE;
6959
+ var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1;
6960
+ // -1 since it's days since Jan 1
6961
+ return yday;
6578
6962
  };
6579
6963
 
6580
- function _fd_close(fd) {
6581
- try {
6582
- var stream = SYSCALLS.getStreamFromFD(fd);
6583
- FS.close(stream);
6584
- return 0;
6585
- } catch (e) {
6586
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6587
- return e.errno;
6588
- }
6964
+ function __localtime_js(time, tmPtr) {
6965
+ time = bigintToI53Checked(time);
6966
+ var date = new Date(time * 1e3);
6967
+ HEAP32[tmPtr >> 2] = date.getSeconds();
6968
+ HEAP32[(tmPtr + 4) >> 2] = date.getMinutes();
6969
+ HEAP32[(tmPtr + 8) >> 2] = date.getHours();
6970
+ HEAP32[(tmPtr + 12) >> 2] = date.getDate();
6971
+ HEAP32[(tmPtr + 16) >> 2] = date.getMonth();
6972
+ HEAP32[(tmPtr + 20) >> 2] = date.getFullYear() - 1900;
6973
+ HEAP32[(tmPtr + 24) >> 2] = date.getDay();
6974
+ var yday = ydayFromDate(date) | 0;
6975
+ HEAP32[(tmPtr + 28) >> 2] = yday;
6976
+ HEAP32[(tmPtr + 36) >> 2] = -(date.getTimezoneOffset() * 60);
6977
+ // Attention: DST is in December in South, and some regions don't have DST at all.
6978
+ var start = new Date(date.getFullYear(), 0, 1);
6979
+ var summerOffset = new Date(
6980
+ date.getFullYear(),
6981
+ 6,
6982
+ 1
6983
+ ).getTimezoneOffset();
6984
+ var winterOffset = start.getTimezoneOffset();
6985
+ var dst =
6986
+ (summerOffset != winterOffset &&
6987
+ date.getTimezoneOffset() ==
6988
+ Math.min(winterOffset, summerOffset)) | 0;
6989
+ HEAP32[(tmPtr + 32) >> 2] = dst;
6589
6990
  }
6590
6991
 
6591
- function _fd_fdstat_get(fd, pbuf) {
6592
- try {
6593
- var rightsBase = 0;
6594
- var rightsInheriting = 0;
6595
- var flags = 0;
6596
- {
6597
- var stream = SYSCALLS.getStreamFromFD(fd);
6598
- // All character devices are terminals (other things a Linux system would
6599
- // assume is a character device, like the mouse, we have special APIs for).
6600
- var type = stream.tty
6601
- ? 2
6602
- : FS.isDir(stream.mode)
6603
- ? 3
6604
- : FS.isLink(stream.mode)
6605
- ? 7
6606
- : 4;
6992
+ var __mktime_js = function (tmPtr) {
6993
+ var ret = (() => {
6994
+ var date = new Date(
6995
+ HEAP32[(tmPtr + 20) >> 2] + 1900,
6996
+ HEAP32[(tmPtr + 16) >> 2],
6997
+ HEAP32[(tmPtr + 12) >> 2],
6998
+ HEAP32[(tmPtr + 8) >> 2],
6999
+ HEAP32[(tmPtr + 4) >> 2],
7000
+ HEAP32[tmPtr >> 2],
7001
+ 0
7002
+ );
7003
+ // There's an ambiguous hour when the time goes back; the tm_isdst field is
7004
+ // used to disambiguate it. Date() basically guesses, so we fix it up if it
7005
+ // guessed wrong, or fill in tm_isdst with the guess if it's -1.
7006
+ var dst = HEAP32[(tmPtr + 32) >> 2];
7007
+ var guessedOffset = date.getTimezoneOffset();
7008
+ var start = new Date(date.getFullYear(), 0, 1);
7009
+ var summerOffset = new Date(
7010
+ date.getFullYear(),
7011
+ 6,
7012
+ 1
7013
+ ).getTimezoneOffset();
7014
+ var winterOffset = start.getTimezoneOffset();
7015
+ var dstOffset = Math.min(winterOffset, summerOffset);
7016
+ // DST is in December in South
7017
+ if (dst < 0) {
7018
+ // Attention: some regions don't have DST at all.
7019
+ HEAP32[(tmPtr + 32) >> 2] = Number(
7020
+ summerOffset != winterOffset && dstOffset == guessedOffset
7021
+ );
7022
+ } else if (dst > 0 != (dstOffset == guessedOffset)) {
7023
+ var nonDstOffset = Math.max(winterOffset, summerOffset);
7024
+ var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
7025
+ // Don't try setMinutes(date.getMinutes() + ...) -- it's messed up.
7026
+ date.setTime(
7027
+ date.getTime() + (trueOffset - guessedOffset) * 6e4
7028
+ );
6607
7029
  }
6608
- HEAP8[pbuf] = type;
6609
- HEAP16[(pbuf + 2) >> 1] = flags;
6610
- HEAP64[(pbuf + 8) >> 3] = BigInt(rightsBase);
6611
- HEAP64[(pbuf + 16) >> 3] = BigInt(rightsInheriting);
6612
- return 0;
6613
- } catch (e) {
6614
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6615
- return e.errno;
6616
- }
6617
- }
6618
-
6619
- /** @param {number=} offset */ var doReadv = (
6620
- stream,
6621
- iov,
6622
- iovcnt,
6623
- offset
6624
- ) => {
6625
- var ret = 0;
6626
- for (var i = 0; i < iovcnt; i++) {
6627
- var ptr = HEAPU32[iov >> 2];
6628
- var len = HEAPU32[(iov + 4) >> 2];
6629
- iov += 8;
6630
- var curr = FS.read(stream, HEAP8, ptr, len, offset);
6631
- if (curr < 0) return -1;
6632
- ret += curr;
6633
- if (curr < len) break;
6634
- // nothing more to read
6635
- if (typeof offset != 'undefined') {
6636
- offset += curr;
7030
+ HEAP32[(tmPtr + 24) >> 2] = date.getDay();
7031
+ var yday = ydayFromDate(date) | 0;
7032
+ HEAP32[(tmPtr + 28) >> 2] = yday;
7033
+ // To match expected behavior, update fields from date
7034
+ HEAP32[tmPtr >> 2] = date.getSeconds();
7035
+ HEAP32[(tmPtr + 4) >> 2] = date.getMinutes();
7036
+ HEAP32[(tmPtr + 8) >> 2] = date.getHours();
7037
+ HEAP32[(tmPtr + 12) >> 2] = date.getDate();
7038
+ HEAP32[(tmPtr + 16) >> 2] = date.getMonth();
7039
+ HEAP32[(tmPtr + 20) >> 2] = date.getYear();
7040
+ var timeMs = date.getTime();
7041
+ if (isNaN(timeMs)) {
7042
+ return -1;
6637
7043
  }
6638
- }
6639
- return ret;
7044
+ // Return time in microseconds
7045
+ return timeMs / 1e3;
7046
+ })();
7047
+ return BigInt(ret);
6640
7048
  };
6641
7049
 
6642
- function _fd_read(fd, iov, iovcnt, pnum) {
7050
+ function __mmap_js(len, prot, flags, fd, offset, allocated, addr) {
7051
+ offset = bigintToI53Checked(offset);
6643
7052
  try {
7053
+ if (isNaN(offset)) return 61;
6644
7054
  var stream = SYSCALLS.getStreamFromFD(fd);
6645
- var num = doReadv(stream, iov, iovcnt);
6646
- HEAPU32[pnum >> 2] = num;
7055
+ var res = FS.mmap(stream, len, offset, prot, flags);
7056
+ var ptr = res.ptr;
7057
+ HEAP32[allocated >> 2] = res.allocated;
7058
+ HEAPU32[addr >> 2] = ptr;
6647
7059
  return 0;
6648
7060
  } catch (e) {
6649
7061
  if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6650
- return e.errno;
7062
+ return -e.errno;
6651
7063
  }
6652
7064
  }
6653
7065
 
6654
- function _fd_seek(fd, offset, whence, newOffset) {
7066
+ function __munmap_js(addr, len, prot, flags, fd, offset) {
6655
7067
  offset = bigintToI53Checked(offset);
6656
7068
  try {
6657
- if (isNaN(offset)) return 61;
6658
7069
  var stream = SYSCALLS.getStreamFromFD(fd);
6659
- FS.llseek(stream, offset, whence);
6660
- HEAP64[newOffset >> 3] = BigInt(stream.position);
6661
- if (stream.getdents && offset === 0 && whence === 0)
6662
- stream.getdents = null;
6663
- // reset readdir state
6664
- return 0;
7070
+ if (prot & 2) {
7071
+ SYSCALLS.doMsync(addr, stream, len, flags, offset);
7072
+ }
6665
7073
  } catch (e) {
6666
7074
  if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6667
- return e.errno;
7075
+ return -e.errno;
6668
7076
  }
6669
7077
  }
6670
7078
 
6671
- /** @param {number=} offset */ var doWritev = (
6672
- stream,
6673
- iov,
6674
- iovcnt,
6675
- offset
6676
- ) => {
6677
- var ret = 0;
6678
- for (var i = 0; i < iovcnt; i++) {
6679
- var ptr = HEAPU32[iov >> 2];
6680
- var len = HEAPU32[(iov + 4) >> 2];
6681
- iov += 8;
6682
- var curr = FS.write(stream, HEAP8, ptr, len, offset);
6683
- if (curr < 0) return -1;
6684
- ret += curr;
6685
- if (curr < len) {
6686
- // No more space to write.
6687
- break;
6688
- }
6689
- if (typeof offset != 'undefined') {
6690
- offset += curr;
6691
- }
7079
+ var timers = {};
7080
+
7081
+ var handleException = (e) => {
7082
+ // Certain exception types we do not treat as errors since they are used for
7083
+ // internal control flow.
7084
+ // 1. ExitStatus, which is thrown by exit()
7085
+ // 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others
7086
+ // that wish to return to JS event loop.
7087
+ if (e instanceof ExitStatus || e == 'unwind') {
7088
+ return EXITSTATUS;
6692
7089
  }
6693
- return ret;
7090
+ quit_(1, e);
6694
7091
  };
6695
7092
 
6696
- function _fd_write(fd, iov, iovcnt, pnum) {
6697
- try {
6698
- var stream = SYSCALLS.getStreamFromFD(fd);
6699
- var num = doWritev(stream, iov, iovcnt);
6700
- HEAPU32[pnum >> 2] = num;
6701
- return 0;
6702
- } catch (e) {
6703
- if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
6704
- return e.errno;
6705
- }
6706
- }
7093
+ var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
6707
7094
 
6708
- var _getaddrinfo = (node, service, hint, out) => {
6709
- var addr = 0;
6710
- var port = 0;
6711
- var flags = 0;
6712
- var family = 0;
6713
- var type = 0;
6714
- var proto = 0;
6715
- var ai;
6716
- function allocaddrinfo(family, type, proto, canon, addr, port) {
6717
- var sa, salen, ai;
6718
- var errno;
6719
- salen = family === 10 ? 28 : 16;
6720
- addr = family === 10 ? inetNtop6(addr) : inetNtop4(addr);
6721
- sa = _malloc(salen);
6722
- errno = writeSockaddr(sa, family, addr, port);
6723
- assert(!errno);
6724
- ai = _malloc(32);
6725
- HEAP32[(ai + 4) >> 2] = family;
6726
- HEAP32[(ai + 8) >> 2] = type;
6727
- HEAP32[(ai + 12) >> 2] = proto;
6728
- HEAPU32[(ai + 24) >> 2] = canon;
6729
- HEAPU32[(ai + 20) >> 2] = sa;
6730
- if (family === 10) {
6731
- HEAP32[(ai + 16) >> 2] = 28;
6732
- } else {
6733
- HEAP32[(ai + 16) >> 2] = 16;
6734
- }
6735
- HEAP32[(ai + 28) >> 2] = 0;
6736
- return ai;
6737
- }
6738
- if (hint) {
6739
- flags = HEAP32[hint >> 2];
6740
- family = HEAP32[(hint + 4) >> 2];
6741
- type = HEAP32[(hint + 8) >> 2];
6742
- proto = HEAP32[(hint + 12) >> 2];
6743
- }
6744
- if (type && !proto) {
6745
- proto = type === 2 ? 17 : 6;
6746
- }
6747
- if (!type && proto) {
6748
- type = proto === 17 ? 2 : 1;
6749
- }
6750
- // If type or proto are set to zero in hints we should really be returning multiple addrinfo values, but for
6751
- // now default to a TCP STREAM socket so we can at least return a sensible addrinfo given NULL hints.
6752
- if (proto === 0) {
6753
- proto = 6;
6754
- }
6755
- if (type === 0) {
6756
- type = 1;
6757
- }
6758
- if (!node && !service) {
6759
- return -2;
6760
- }
6761
- if (flags & ~(1 | 2 | 4 | 1024 | 8 | 16 | 32)) {
6762
- return -1;
6763
- }
6764
- if (hint !== 0 && HEAP32[hint >> 2] & 2 && !node) {
6765
- return -1;
6766
- }
6767
- if (flags & 32) {
6768
- // TODO
6769
- return -2;
6770
- }
6771
- if (type !== 0 && type !== 1 && type !== 2) {
6772
- return -7;
6773
- }
6774
- if (family !== 0 && family !== 2 && family !== 10) {
6775
- return -6;
6776
- }
6777
- if (service) {
6778
- service = UTF8ToString(service);
6779
- port = parseInt(service, 10);
6780
- if (isNaN(port)) {
6781
- if (flags & 1024) {
6782
- return -2;
6783
- }
6784
- // TODO support resolving well-known service names from:
6785
- // http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt
6786
- return -8;
6787
- }
6788
- }
6789
- if (!node) {
6790
- if (family === 0) {
6791
- family = 2;
6792
- }
6793
- if ((flags & 1) === 0) {
6794
- if (family === 2) {
6795
- addr = _htonl(2130706433);
6796
- } else {
6797
- addr = [0, 0, 0, _htonl(1)];
6798
- }
6799
- }
6800
- ai = allocaddrinfo(family, type, proto, null, addr, port);
6801
- HEAPU32[out >> 2] = ai;
6802
- return 0;
7095
+ var _proc_exit = (code) => {
7096
+ EXITSTATUS = code;
7097
+ if (!keepRuntimeAlive()) {
7098
+ Module['onExit']?.(code);
7099
+ ABORT = true;
6803
7100
  }
6804
- // try as a numeric address
6805
- node = UTF8ToString(node);
6806
- addr = inetPton4(node);
6807
- if (addr !== null) {
6808
- // incoming node is a valid ipv4 address
6809
- if (family === 0 || family === 2) {
6810
- family = 2;
6811
- } else if (family === 10 && flags & 8) {
6812
- addr = [0, 0, _htonl(65535), addr];
6813
- family = 10;
6814
- } else {
6815
- return -2;
7101
+ quit_(code, new ExitStatus(code));
7102
+ };
7103
+
7104
+ /** @suppress {duplicate } */ /** @param {boolean|number=} implicit */ var exitJS =
7105
+ (status, implicit) => {
7106
+ EXITSTATUS = status;
7107
+ if (!keepRuntimeAlive()) {
7108
+ exitRuntime();
6816
7109
  }
6817
- } else {
6818
- addr = inetPton6(node);
6819
- if (addr !== null) {
6820
- // incoming node is a valid ipv6 address
6821
- if (family === 0 || family === 10) {
6822
- family = 10;
6823
- } else {
6824
- return -2;
6825
- }
7110
+ _proc_exit(status);
7111
+ };
7112
+
7113
+ var _exit = exitJS;
7114
+
7115
+ Module['_exit'] = _exit;
7116
+
7117
+ var maybeExit = () => {
7118
+ if (runtimeExited) {
7119
+ return;
7120
+ }
7121
+ if (!keepRuntimeAlive()) {
7122
+ try {
7123
+ _exit(EXITSTATUS);
7124
+ } catch (e) {
7125
+ handleException(e);
6826
7126
  }
6827
7127
  }
6828
- if (addr != null) {
6829
- ai = allocaddrinfo(family, type, proto, node, addr, port);
6830
- HEAPU32[out >> 2] = ai;
6831
- return 0;
7128
+ };
7129
+
7130
+ var callUserCallback = (func) => {
7131
+ if (runtimeExited || ABORT) {
7132
+ return;
6832
7133
  }
6833
- if (flags & 4) {
6834
- return -2;
7134
+ try {
7135
+ func();
7136
+ maybeExit();
7137
+ } catch (e) {
7138
+ handleException(e);
6835
7139
  }
6836
- // try as a hostname
6837
- // resolve the hostname to a temporary fake address
6838
- node = DNS.lookup_name(node);
6839
- addr = inetPton4(node);
6840
- if (family === 0) {
6841
- family = 2;
6842
- } else if (family === 10) {
6843
- addr = [0, 0, _htonl(65535), addr];
7140
+ };
7141
+
7142
+ var _emscripten_get_now = () => performance.now();
7143
+
7144
+ var __setitimer_js = (which, timeout_ms) => {
7145
+ // First, clear any existing timer.
7146
+ if (timers[which]) {
7147
+ clearTimeout(timers[which].id);
7148
+ delete timers[which];
6844
7149
  }
6845
- ai = allocaddrinfo(family, type, proto, null, addr, port);
6846
- HEAPU32[out >> 2] = ai;
7150
+ // A timeout of zero simply cancels the current timeout so we have nothing
7151
+ // more to do.
7152
+ if (!timeout_ms) return 0;
7153
+ var id = setTimeout(() => {
7154
+ delete timers[which];
7155
+ callUserCallback(() =>
7156
+ __emscripten_timeout(which, _emscripten_get_now())
7157
+ );
7158
+ }, timeout_ms);
7159
+ timers[which] = {
7160
+ id,
7161
+ timeout_ms,
7162
+ };
6847
7163
  return 0;
6848
7164
  };
6849
7165
 
6850
- var _getnameinfo = (sa, salen, node, nodelen, serv, servlen, flags) => {
6851
- var info = readSockaddr(sa, salen);
6852
- if (info.errno) {
6853
- return -6;
6854
- }
6855
- var port = info.port;
6856
- var addr = info.addr;
6857
- var overflowed = false;
6858
- if (node && nodelen) {
6859
- var lookup;
6860
- if (flags & 1 || !(lookup = DNS.lookup_addr(addr))) {
6861
- if (flags & 8) {
6862
- return -2;
6863
- }
6864
- } else {
6865
- addr = lookup;
6866
- }
6867
- var numBytesWrittenExclNull = stringToUTF8(addr, node, nodelen);
6868
- if (numBytesWrittenExclNull + 1 >= nodelen) {
6869
- overflowed = true;
6870
- }
7166
+ var __tzset_js = (timezone, daylight, std_name, dst_name) => {
7167
+ // TODO: Use (malleable) environment variables instead of system settings.
7168
+ var currentYear = new Date().getFullYear();
7169
+ var winter = new Date(currentYear, 0, 1);
7170
+ var summer = new Date(currentYear, 6, 1);
7171
+ var winterOffset = winter.getTimezoneOffset();
7172
+ var summerOffset = summer.getTimezoneOffset();
7173
+ // Local standard timezone offset. Local standard time is not adjusted for
7174
+ // daylight savings. This code uses the fact that getTimezoneOffset returns
7175
+ // a greater value during Standard Time versus Daylight Saving Time (DST).
7176
+ // Thus it determines the expected output during Standard Time, and it
7177
+ // compares whether the output of the given date the same (Standard) or less
7178
+ // (DST).
7179
+ var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
7180
+ // timezone is specified as seconds west of UTC ("The external variable
7181
+ // `timezone` shall be set to the difference, in seconds, between
7182
+ // Coordinated Universal Time (UTC) and local standard time."), the same
7183
+ // as returned by stdTimezoneOffset.
7184
+ // See http://pubs.opengroup.org/onlinepubs/009695399/functions/tzset.html
7185
+ HEAPU32[timezone >> 2] = stdTimezoneOffset * 60;
7186
+ HEAP32[daylight >> 2] = Number(winterOffset != summerOffset);
7187
+ var extractZone = (timezoneOffset) => {
7188
+ // Why inverse sign?
7189
+ // Read here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
7190
+ var sign = timezoneOffset >= 0 ? '-' : '+';
7191
+ var absOffset = Math.abs(timezoneOffset);
7192
+ var hours = String(Math.floor(absOffset / 60)).padStart(2, '0');
7193
+ var minutes = String(absOffset % 60).padStart(2, '0');
7194
+ return `UTC${sign}${hours}${minutes}`;
7195
+ };
7196
+ var winterName = extractZone(winterOffset);
7197
+ var summerName = extractZone(summerOffset);
7198
+ if (summerOffset < winterOffset) {
7199
+ // Northern hemisphere
7200
+ stringToUTF8(winterName, std_name, 17);
7201
+ stringToUTF8(summerName, dst_name, 17);
7202
+ } else {
7203
+ stringToUTF8(winterName, dst_name, 17);
7204
+ stringToUTF8(summerName, std_name, 17);
6871
7205
  }
6872
- if (serv && servlen) {
6873
- port = '' + port;
6874
- var numBytesWrittenExclNull = stringToUTF8(port, serv, servlen);
6875
- if (numBytesWrittenExclNull + 1 >= servlen) {
6876
- overflowed = true;
6877
- }
7206
+ };
7207
+
7208
+ var _emscripten_date_now = () => Date.now();
7209
+
7210
+ var nowIsMonotonic = 1;
7211
+
7212
+ var checkWasiClock = (clock_id) => clock_id >= 0 && clock_id <= 3;
7213
+
7214
+ function _clock_time_get(clk_id, ignored_precision, ptime) {
7215
+ ignored_precision = bigintToI53Checked(ignored_precision);
7216
+ if (!checkWasiClock(clk_id)) {
7217
+ return 28;
6878
7218
  }
6879
- if (overflowed) {
6880
- // Note: even when we overflow, getnameinfo() is specced to write out the truncated results.
6881
- return -12;
7219
+ var now;
7220
+ // all wasi clocks but realtime are monotonic
7221
+ if (clk_id === 0) {
7222
+ now = _emscripten_date_now();
7223
+ } else if (nowIsMonotonic) {
7224
+ now = _emscripten_get_now();
7225
+ } else {
7226
+ return 52;
6882
7227
  }
7228
+ // "now" is in ms, and wasi times are in ns.
7229
+ var nsec = Math.round(now * 1e3 * 1e3);
7230
+ HEAP64[ptime >> 3] = BigInt(nsec);
6883
7231
  return 0;
7232
+ }
7233
+
7234
+ var getHeapMax = () =>
7235
+ // Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate
7236
+ // full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side
7237
+ // for any code that deals with heap sizes, which would require special
7238
+ // casing all heap size related code to treat 0 specially.
7239
+ 2147483648;
7240
+
7241
+ var _emscripten_get_heap_max = () => getHeapMax();
7242
+
7243
+ var growMemory = (size) => {
7244
+ var b = wasmMemory.buffer;
7245
+ var pages = ((size - b.byteLength + 65535) / 65536) | 0;
7246
+ try {
7247
+ // round size grow request up to wasm page size (fixed 64KB per spec)
7248
+ wasmMemory.grow(pages);
7249
+ // .grow() takes a delta compared to the previous size
7250
+ updateMemoryViews();
7251
+ return 1;
7252
+ } catch (e) {}
7253
+ };
7254
+
7255
+ var _emscripten_resize_heap = (requestedSize) => {
7256
+ var oldSize = HEAPU8.length;
7257
+ // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
7258
+ requestedSize >>>= 0;
7259
+ // With multithreaded builds, races can happen (another thread might increase the size
7260
+ // in between), so return a failure, and let the caller retry.
7261
+ // Memory resize rules:
7262
+ // 1. Always increase heap size to at least the requested size, rounded up
7263
+ // to next page multiple.
7264
+ // 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap
7265
+ // geometrically: increase the heap size according to
7266
+ // MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most
7267
+ // overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB).
7268
+ // 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap
7269
+ // linearly: increase the heap size by at least
7270
+ // MEMORY_GROWTH_LINEAR_STEP bytes.
7271
+ // 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by
7272
+ // MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest
7273
+ // 4. If we were unable to allocate as much memory, it may be due to
7274
+ // over-eager decision to excessively reserve due to (3) above.
7275
+ // Hence if an allocation fails, cut down on the amount of excess
7276
+ // growth, in an attempt to succeed to perform a smaller allocation.
7277
+ // A limit is set for how much we can grow. We should not exceed that
7278
+ // (the wasm binary specifies it, so if we tried, we'd fail anyhow).
7279
+ var maxHeapSize = getHeapMax();
7280
+ if (requestedSize > maxHeapSize) {
7281
+ return false;
7282
+ }
7283
+ // Loop through potential heap size increases. If we attempt a too eager
7284
+ // reservation that fails, cut down on the attempted size and reserve a
7285
+ // smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
7286
+ for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
7287
+ var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown);
7288
+ // ensure geometric growth
7289
+ // but limit overreserving (default to capping at +96MB overgrowth at most)
7290
+ overGrownHeapSize = Math.min(
7291
+ overGrownHeapSize,
7292
+ requestedSize + 100663296
7293
+ );
7294
+ var newSize = Math.min(
7295
+ maxHeapSize,
7296
+ alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536)
7297
+ );
7298
+ var replacement = growMemory(newSize);
7299
+ if (replacement) {
7300
+ return true;
7301
+ }
7302
+ }
7303
+ return false;
7304
+ };
7305
+
7306
+ var runtimeKeepalivePush = () => {
7307
+ runtimeKeepaliveCounter += 1;
7308
+ };
7309
+
7310
+ var runtimeKeepalivePop = () => {
7311
+ runtimeKeepaliveCounter -= 1;
7312
+ };
7313
+
7314
+ /** @param {number=} timeout */ var safeSetTimeout = (func, timeout) => {
7315
+ runtimeKeepalivePush();
7316
+ return setTimeout(() => {
7317
+ runtimeKeepalivePop();
7318
+ callUserCallback(func);
7319
+ }, timeout);
6884
7320
  };
6885
7321
 
6886
- var Protocols = {
6887
- list: [],
6888
- map: {},
6889
- };
7322
+ var _emscripten_sleep = (ms) =>
7323
+ Asyncify.handleSleep((wakeUp) => safeSetTimeout(wakeUp, ms));
6890
7324
 
6891
- var _setprotoent = (stayopen) => {
6892
- // void setprotoent(int stayopen);
6893
- // Allocate and populate a protoent structure given a name, protocol number and array of aliases
6894
- function allocprotoent(name, proto, aliases) {
6895
- // write name into buffer
6896
- var nameBuf = _malloc(name.length + 1);
6897
- stringToAscii(name, nameBuf);
6898
- // write aliases into buffer
6899
- var j = 0;
6900
- var length = aliases.length;
6901
- var aliasListBuf = _malloc((length + 1) * 4);
6902
- // Use length + 1 so we have space for the terminating NULL ptr.
6903
- for (var i = 0; i < length; i++, j += 4) {
6904
- var alias = aliases[i];
6905
- var aliasBuf = _malloc(alias.length + 1);
6906
- stringToAscii(alias, aliasBuf);
6907
- HEAPU32[(aliasListBuf + j) >> 2] = aliasBuf;
7325
+ Module['_emscripten_sleep'] = _emscripten_sleep;
7326
+
7327
+ _emscripten_sleep.isAsync = true;
7328
+
7329
+ var ENV = PHPLoader.ENV || {};
7330
+
7331
+ var getExecutableName = () => thisProgram || './this.program';
7332
+
7333
+ var getEnvStrings = () => {
7334
+ if (!getEnvStrings.strings) {
7335
+ // Default values.
7336
+ // Browser language detection #8751
7337
+ var lang =
7338
+ (
7339
+ (typeof navigator == 'object' &&
7340
+ navigator.languages &&
7341
+ navigator.languages[0]) ||
7342
+ 'C'
7343
+ ).replace('-', '_') + '.UTF-8';
7344
+ var env = {
7345
+ USER: 'web_user',
7346
+ LOGNAME: 'web_user',
7347
+ PATH: '/',
7348
+ PWD: '/',
7349
+ HOME: '/home/web_user',
7350
+ LANG: lang,
7351
+ _: getExecutableName(),
7352
+ };
7353
+ // Apply the user-provided values, if any.
7354
+ for (var x in ENV) {
7355
+ // x is a key in ENV; if ENV[x] is undefined, that means it was
7356
+ // explicitly set to be so. We allow user code to do that to
7357
+ // force variables with default values to remain unset.
7358
+ if (ENV[x] === undefined) delete env[x];
7359
+ else env[x] = ENV[x];
6908
7360
  }
6909
- HEAPU32[(aliasListBuf + j) >> 2] = 0;
6910
- // Terminating NULL pointer.
6911
- // generate protoent
6912
- var pe = _malloc(12);
6913
- HEAPU32[pe >> 2] = nameBuf;
6914
- HEAPU32[(pe + 4) >> 2] = aliasListBuf;
6915
- HEAP32[(pe + 8) >> 2] = proto;
6916
- return pe;
6917
- }
6918
- // Populate the protocol 'database'. The entries are limited to tcp and udp, though it is fairly trivial
6919
- // to add extra entries from /etc/protocols if desired - though not sure if that'd actually be useful.
6920
- var list = Protocols.list;
6921
- var map = Protocols.map;
6922
- if (list.length === 0) {
6923
- var entry = allocprotoent('tcp', 6, ['TCP']);
6924
- list.push(entry);
6925
- map['tcp'] = map['6'] = entry;
6926
- entry = allocprotoent('udp', 17, ['UDP']);
6927
- list.push(entry);
6928
- map['udp'] = map['17'] = entry;
7361
+ var strings = [];
7362
+ for (var x in env) {
7363
+ strings.push(`${x}=${env[x]}`);
7364
+ }
7365
+ getEnvStrings.strings = strings;
6929
7366
  }
6930
- _setprotoent.index = 0;
7367
+ return getEnvStrings.strings;
6931
7368
  };
6932
7369
 
6933
- var _getprotobyname = (name) => {
6934
- // struct protoent *getprotobyname(const char *);
6935
- name = UTF8ToString(name);
6936
- _setprotoent(true);
6937
- var result = Protocols.map[name];
6938
- return result;
7370
+ var stringToAscii = (str, buffer) => {
7371
+ for (var i = 0; i < str.length; ++i) {
7372
+ HEAP8[buffer++] = str.charCodeAt(i);
7373
+ }
7374
+ // Null-terminate the string
7375
+ HEAP8[buffer] = 0;
6939
7376
  };
6940
7377
 
6941
- var _getprotobynumber = (number) => {
6942
- // struct protoent *getprotobynumber(int proto);
6943
- _setprotoent(true);
6944
- var result = Protocols.map[number];
6945
- return result;
7378
+ var _environ_get = (__environ, environ_buf) => {
7379
+ var bufSize = 0;
7380
+ getEnvStrings().forEach((string, i) => {
7381
+ var ptr = environ_buf + bufSize;
7382
+ HEAPU32[(__environ + i * 4) >> 2] = ptr;
7383
+ stringToAscii(string, ptr);
7384
+ bufSize += string.length + 1;
7385
+ });
7386
+ return 0;
6946
7387
  };
6947
7388
 
6948
- var stackAlloc = (sz) => __emscripten_stack_alloc(sz);
6949
-
6950
- /** @suppress {duplicate } */ var stringToUTF8OnStack = (str) => {
6951
- var size = lengthBytesUTF8(str) + 1;
6952
- var ret = stackAlloc(size);
6953
- stringToUTF8(str, ret, size);
6954
- return ret;
7389
+ var _environ_sizes_get = (penviron_count, penviron_buf_size) => {
7390
+ var strings = getEnvStrings();
7391
+ HEAPU32[penviron_count >> 2] = strings.length;
7392
+ var bufSize = 0;
7393
+ strings.forEach((string) => (bufSize += string.length + 1));
7394
+ HEAPU32[penviron_buf_size >> 2] = bufSize;
7395
+ return 0;
6955
7396
  };
6956
7397
 
6957
- var allocateUTF8OnStack = stringToUTF8OnStack;
6958
-
6959
- var PHPWASM = {
6960
- init: function () {
6961
- // The /internal directory is required by the C module. It's where the
6962
- // stdout, stderr, and headers information are written for the JavaScript
6963
- // code to read later on.
6964
- FS.mkdir('/internal');
6965
- // The files from the shared directory are shared between all the
6966
- // PHP processes managed by PHPProcessManager.
6967
- FS.mkdir('/internal/shared');
6968
- // The files from the preload directory are preloaded using the
6969
- // auto_prepend_file php.ini directive.
6970
- FS.mkdir('/internal/shared/preload');
6971
- // Create stdout and stderr devices. We can't just use Emscripten's
6972
- // default stdout and stderr devices because they stop processing data
6973
- // on the first null byte. However, when dealing with binary data,
6974
- // null bytes are valid and common.
6975
- FS.registerDevice(FS.makedev(64, 0), {
6976
- open: () => {},
6977
- close: () => {},
6978
- read: () => 0,
6979
- write: (stream, buffer, offset, length, pos) => {
6980
- const chunk = buffer.subarray(offset, offset + length);
6981
- PHPWASM.onStdout(chunk);
6982
- return length;
6983
- },
6984
- });
6985
- FS.mkdev('/internal/stdout', FS.makedev(64, 0));
6986
- FS.registerDevice(FS.makedev(63, 0), {
6987
- open: () => {},
6988
- close: () => {},
6989
- read: () => 0,
6990
- write: (stream, buffer, offset, length, pos) => {
6991
- const chunk = buffer.subarray(offset, offset + length);
6992
- PHPWASM.onStderr(chunk);
6993
- return length;
6994
- },
6995
- });
6996
- FS.mkdev('/internal/stderr', FS.makedev(63, 0));
6997
- FS.registerDevice(FS.makedev(62, 0), {
6998
- open: () => {},
6999
- close: () => {},
7000
- read: () => 0,
7001
- write: (stream, buffer, offset, length, pos) => {
7002
- const chunk = buffer.subarray(offset, offset + length);
7003
- PHPWASM.onHeaders(chunk);
7004
- return length;
7005
- },
7006
- });
7007
- FS.mkdev('/internal/headers', FS.makedev(62, 0));
7008
- // Handle events.
7009
- PHPWASM.EventEmitter = ENVIRONMENT_IS_NODE
7010
- ? require('events').EventEmitter
7011
- : class EventEmitter {
7012
- constructor() {
7013
- this.listeners = {};
7014
- }
7015
- emit(eventName, data) {
7016
- if (this.listeners[eventName]) {
7017
- this.listeners[eventName].forEach(
7018
- (callback) => {
7019
- callback(data);
7020
- }
7021
- );
7022
- }
7023
- }
7024
- once(eventName, callback) {
7025
- const self = this;
7026
- function removedCallback() {
7027
- callback(...arguments);
7028
- self.removeListener(eventName, removedCallback);
7029
- }
7030
- this.on(eventName, removedCallback);
7031
- }
7032
- removeAllListeners(eventName) {
7033
- if (eventName) {
7034
- delete this.listeners[eventName];
7035
- } else {
7036
- this.listeners = {};
7037
- }
7038
- }
7039
- removeListener(eventName, callback) {
7040
- if (this.listeners[eventName]) {
7041
- const idx =
7042
- this.listeners[eventName].indexOf(callback);
7043
- if (idx !== -1) {
7044
- this.listeners[eventName].splice(idx, 1);
7045
- }
7046
- }
7047
- }
7048
- };
7049
- // Clean up the fd -> childProcess mapping when the fd is closed:
7050
- const originalClose = FS.close;
7051
- FS.close = function (stream) {
7052
- originalClose(stream);
7053
- delete PHPWASM.child_proc_by_fd[stream.fd];
7054
- };
7055
- PHPWASM.child_proc_by_fd = {};
7056
- PHPWASM.child_proc_by_pid = {};
7057
- PHPWASM.input_devices = {};
7058
- const originalWrite = TTY.stream_ops.write;
7059
- TTY.stream_ops.write = function (stream, ...rest) {
7060
- const retval = originalWrite(stream, ...rest);
7061
- // Implicit flush since PHP's fflush() doesn't seem to trigger the fsync event
7062
- // @TODO: Fix this at the wasm level
7063
- stream.tty.ops.fsync(stream.tty);
7064
- return retval;
7065
- };
7066
- const originalPutChar = TTY.stream_ops.put_char;
7067
- TTY.stream_ops.put_char = function (tty, val) {
7068
- /**
7069
- * Buffer newlines that Emscripten normally ignores.
7070
- *
7071
- * Emscripten doesn't do it by default because its default
7072
- * print function is console.log that implicitly adds a newline. We are overwriting
7073
- * it with an environment-specific function that outputs exaclty what it was given,
7074
- * e.g. in Node.js it's process.stdout.write(). Therefore, we need to mak sure
7075
- * all the newlines make it to the output buffer.
7076
- */ if (val === 10) tty.output.push(val);
7077
- return originalPutChar(tty, val);
7078
- };
7079
- },
7080
- onHeaders: function (chunk) {
7081
- if (Module['onHeaders']) {
7082
- Module['onHeaders'](chunk);
7083
- return;
7398
+ function _fd_fdstat_get(fd, pbuf) {
7399
+ try {
7400
+ var rightsBase = 0;
7401
+ var rightsInheriting = 0;
7402
+ var flags = 0;
7403
+ {
7404
+ var stream = SYSCALLS.getStreamFromFD(fd);
7405
+ // All character devices are terminals (other things a Linux system would
7406
+ // assume is a character device, like the mouse, we have special APIs for).
7407
+ var type = stream.tty
7408
+ ? 2
7409
+ : FS.isDir(stream.mode)
7410
+ ? 3
7411
+ : FS.isLink(stream.mode)
7412
+ ? 7
7413
+ : 4;
7084
7414
  }
7085
- console.log('headers', {
7086
- chunk,
7087
- });
7088
- },
7089
- onStdout: function (chunk) {
7090
- if (Module['onStdout']) {
7091
- Module['onStdout'](chunk);
7092
- return;
7415
+ HEAP8[pbuf] = type;
7416
+ HEAP16[(pbuf + 2) >> 1] = flags;
7417
+ HEAP64[(pbuf + 8) >> 3] = BigInt(rightsBase);
7418
+ HEAP64[(pbuf + 16) >> 3] = BigInt(rightsInheriting);
7419
+ return 0;
7420
+ } catch (e) {
7421
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
7422
+ return e.errno;
7423
+ }
7424
+ }
7425
+
7426
+ /** @param {number=} offset */ var doReadv = (
7427
+ stream,
7428
+ iov,
7429
+ iovcnt,
7430
+ offset
7431
+ ) => {
7432
+ var ret = 0;
7433
+ for (var i = 0; i < iovcnt; i++) {
7434
+ var ptr = HEAPU32[iov >> 2];
7435
+ var len = HEAPU32[(iov + 4) >> 2];
7436
+ iov += 8;
7437
+ var curr = FS.read(stream, HEAP8, ptr, len, offset);
7438
+ if (curr < 0) return -1;
7439
+ ret += curr;
7440
+ if (curr < len) break;
7441
+ // nothing more to read
7442
+ if (typeof offset != 'undefined') {
7443
+ offset += curr;
7093
7444
  }
7094
- if (ENVIRONMENT_IS_NODE) {
7095
- process.stdout.write(chunk);
7096
- } else {
7097
- console.log('stdout', {
7098
- chunk,
7099
- });
7445
+ }
7446
+ return ret;
7447
+ };
7448
+
7449
+ function _fd_read(fd, iov, iovcnt, pnum) {
7450
+ try {
7451
+ var stream = SYSCALLS.getStreamFromFD(fd);
7452
+ var num = doReadv(stream, iov, iovcnt);
7453
+ HEAPU32[pnum >> 2] = num;
7454
+ return 0;
7455
+ } catch (e) {
7456
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
7457
+ return e.errno;
7458
+ }
7459
+ }
7460
+
7461
+ function _fd_seek(fd, offset, whence, newOffset) {
7462
+ offset = bigintToI53Checked(offset);
7463
+ try {
7464
+ if (isNaN(offset)) return 61;
7465
+ var stream = SYSCALLS.getStreamFromFD(fd);
7466
+ FS.llseek(stream, offset, whence);
7467
+ HEAP64[newOffset >> 3] = BigInt(stream.position);
7468
+ if (stream.getdents && offset === 0 && whence === 0)
7469
+ stream.getdents = null;
7470
+ // reset readdir state
7471
+ return 0;
7472
+ } catch (e) {
7473
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
7474
+ return e.errno;
7475
+ }
7476
+ }
7477
+
7478
+ /** @param {number=} offset */ var doWritev = (
7479
+ stream,
7480
+ iov,
7481
+ iovcnt,
7482
+ offset
7483
+ ) => {
7484
+ var ret = 0;
7485
+ for (var i = 0; i < iovcnt; i++) {
7486
+ var ptr = HEAPU32[iov >> 2];
7487
+ var len = HEAPU32[(iov + 4) >> 2];
7488
+ iov += 8;
7489
+ var curr = FS.write(stream, HEAP8, ptr, len, offset);
7490
+ if (curr < 0) return -1;
7491
+ ret += curr;
7492
+ if (curr < len) {
7493
+ // No more space to write.
7494
+ break;
7100
7495
  }
7101
- },
7102
- onStderr: function (chunk) {
7103
- if (Module['onStderr']) {
7104
- Module['onStderr'](chunk);
7105
- return;
7496
+ if (typeof offset != 'undefined') {
7497
+ offset += curr;
7106
7498
  }
7107
- if (ENVIRONMENT_IS_NODE) {
7108
- process.stderr.write(chunk);
7499
+ }
7500
+ return ret;
7501
+ };
7502
+
7503
+ function _fd_write(fd, iov, iovcnt, pnum) {
7504
+ try {
7505
+ var stream = SYSCALLS.getStreamFromFD(fd);
7506
+ var num = doWritev(stream, iov, iovcnt);
7507
+ HEAPU32[pnum >> 2] = num;
7508
+ return 0;
7509
+ } catch (e) {
7510
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
7511
+ return e.errno;
7512
+ }
7513
+ }
7514
+
7515
+ var _getaddrinfo = (node, service, hint, out) => {
7516
+ var addr = 0;
7517
+ var port = 0;
7518
+ var flags = 0;
7519
+ var family = 0;
7520
+ var type = 0;
7521
+ var proto = 0;
7522
+ var ai;
7523
+ function allocaddrinfo(family, type, proto, canon, addr, port) {
7524
+ var sa, salen, ai;
7525
+ var errno;
7526
+ salen = family === 10 ? 28 : 16;
7527
+ addr = family === 10 ? inetNtop6(addr) : inetNtop4(addr);
7528
+ sa = _malloc(salen);
7529
+ errno = writeSockaddr(sa, family, addr, port);
7530
+ assert(!errno);
7531
+ ai = _malloc(32);
7532
+ HEAP32[(ai + 4) >> 2] = family;
7533
+ HEAP32[(ai + 8) >> 2] = type;
7534
+ HEAP32[(ai + 12) >> 2] = proto;
7535
+ HEAPU32[(ai + 24) >> 2] = canon;
7536
+ HEAPU32[(ai + 20) >> 2] = sa;
7537
+ if (family === 10) {
7538
+ HEAP32[(ai + 16) >> 2] = 28;
7109
7539
  } else {
7110
- console.warn('stderr', {
7111
- chunk,
7112
- });
7113
- }
7114
- },
7115
- getAllWebSockets: function (sock) {
7116
- const webSockets = new Set();
7117
- if (sock.server) {
7118
- sock.server.clients.forEach((ws) => {
7119
- webSockets.add(ws);
7120
- });
7121
- }
7122
- for (const peer of PHPWASM.getAllPeers(sock)) {
7123
- webSockets.add(peer.socket);
7124
- }
7125
- return Array.from(webSockets);
7126
- },
7127
- getAllPeers: function (sock) {
7128
- const peers = new Set();
7129
- if (sock.server) {
7130
- sock.pending
7131
- .filter((pending) => pending.peers)
7132
- .forEach((pending) => {
7133
- for (const peer of Object.values(pending.peers)) {
7134
- peers.add(peer);
7135
- }
7136
- });
7540
+ HEAP32[(ai + 16) >> 2] = 16;
7137
7541
  }
7138
- if (sock.peers) {
7139
- for (const peer of Object.values(sock.peers)) {
7140
- peers.add(peer);
7542
+ HEAP32[(ai + 28) >> 2] = 0;
7543
+ return ai;
7544
+ }
7545
+ if (hint) {
7546
+ flags = HEAP32[hint >> 2];
7547
+ family = HEAP32[(hint + 4) >> 2];
7548
+ type = HEAP32[(hint + 8) >> 2];
7549
+ proto = HEAP32[(hint + 12) >> 2];
7550
+ }
7551
+ if (type && !proto) {
7552
+ proto = type === 2 ? 17 : 6;
7553
+ }
7554
+ if (!type && proto) {
7555
+ type = proto === 17 ? 2 : 1;
7556
+ }
7557
+ // If type or proto are set to zero in hints we should really be returning multiple addrinfo values, but for
7558
+ // now default to a TCP STREAM socket so we can at least return a sensible addrinfo given NULL hints.
7559
+ if (proto === 0) {
7560
+ proto = 6;
7561
+ }
7562
+ if (type === 0) {
7563
+ type = 1;
7564
+ }
7565
+ if (!node && !service) {
7566
+ return -2;
7567
+ }
7568
+ if (flags & ~(1 | 2 | 4 | 1024 | 8 | 16 | 32)) {
7569
+ return -1;
7570
+ }
7571
+ if (hint !== 0 && HEAP32[hint >> 2] & 2 && !node) {
7572
+ return -1;
7573
+ }
7574
+ if (flags & 32) {
7575
+ // TODO
7576
+ return -2;
7577
+ }
7578
+ if (type !== 0 && type !== 1 && type !== 2) {
7579
+ return -7;
7580
+ }
7581
+ if (family !== 0 && family !== 2 && family !== 10) {
7582
+ return -6;
7583
+ }
7584
+ if (service) {
7585
+ service = UTF8ToString(service);
7586
+ port = parseInt(service, 10);
7587
+ if (isNaN(port)) {
7588
+ if (flags & 1024) {
7589
+ return -2;
7141
7590
  }
7591
+ // TODO support resolving well-known service names from:
7592
+ // http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt
7593
+ return -8;
7142
7594
  }
7143
- return Array.from(peers);
7144
- },
7145
- awaitData: function (ws) {
7146
- return PHPWASM.awaitEvent(ws, 'message');
7147
- },
7148
- awaitConnection: function (ws) {
7149
- if (ws.OPEN === ws.readyState) {
7150
- return [Promise.resolve(), PHPWASM.noop];
7595
+ }
7596
+ if (!node) {
7597
+ if (family === 0) {
7598
+ family = 2;
7599
+ }
7600
+ if ((flags & 1) === 0) {
7601
+ if (family === 2) {
7602
+ addr = _htonl(2130706433);
7603
+ } else {
7604
+ addr = [0, 0, 0, _htonl(1)];
7605
+ }
7151
7606
  }
7152
- return PHPWASM.awaitEvent(ws, 'open');
7153
- },
7154
- awaitClose: function (ws) {
7155
- if ([ws.CLOSING, ws.CLOSED].includes(ws.readyState)) {
7156
- return [Promise.resolve(), PHPWASM.noop];
7607
+ ai = allocaddrinfo(family, type, proto, null, addr, port);
7608
+ HEAPU32[out >> 2] = ai;
7609
+ return 0;
7610
+ }
7611
+ // try as a numeric address
7612
+ node = UTF8ToString(node);
7613
+ addr = inetPton4(node);
7614
+ if (addr !== null) {
7615
+ // incoming node is a valid ipv4 address
7616
+ if (family === 0 || family === 2) {
7617
+ family = 2;
7618
+ } else if (family === 10 && flags & 8) {
7619
+ addr = [0, 0, _htonl(65535), addr];
7620
+ family = 10;
7621
+ } else {
7622
+ return -2;
7157
7623
  }
7158
- return PHPWASM.awaitEvent(ws, 'close');
7159
- },
7160
- awaitError: function (ws) {
7161
- if ([ws.CLOSING, ws.CLOSED].includes(ws.readyState)) {
7162
- return [Promise.resolve(), PHPWASM.noop];
7624
+ } else {
7625
+ addr = inetPton6(node);
7626
+ if (addr !== null) {
7627
+ // incoming node is a valid ipv6 address
7628
+ if (family === 0 || family === 10) {
7629
+ family = 10;
7630
+ } else {
7631
+ return -2;
7632
+ }
7163
7633
  }
7164
- return PHPWASM.awaitEvent(ws, 'error');
7165
- },
7166
- awaitEvent: function (ws, event) {
7167
- let resolve;
7168
- const listener = () => {
7169
- resolve();
7170
- };
7171
- const promise = new Promise(function (_resolve) {
7172
- resolve = _resolve;
7173
- ws.once(event, listener);
7174
- });
7175
- const cancel = () => {
7176
- ws.removeListener(event, listener);
7177
- // Rejecting the promises bubbles up and kills the entire
7178
- // node process. Let's resolve them on the next tick instead
7179
- // to give the caller some space to unbind any handlers.
7180
- setTimeout(resolve);
7181
- };
7182
- return [promise, cancel];
7183
- },
7184
- noop: function () {},
7185
- spawnProcess: function (command, args, options) {
7186
- if (Module['spawnProcess']) {
7187
- const spawnedPromise = Module['spawnProcess'](
7188
- command,
7189
- args,
7190
- options
7191
- );
7192
- return Promise.resolve(spawnedPromise).then(function (spawned) {
7193
- if (!spawned || !spawned.on) {
7194
- throw new Error(
7195
- 'spawnProcess() must return an EventEmitter but returned a different type.'
7196
- );
7197
- }
7198
- return spawned;
7199
- });
7634
+ }
7635
+ if (addr != null) {
7636
+ ai = allocaddrinfo(family, type, proto, node, addr, port);
7637
+ HEAPU32[out >> 2] = ai;
7638
+ return 0;
7639
+ }
7640
+ if (flags & 4) {
7641
+ return -2;
7642
+ }
7643
+ // try as a hostname
7644
+ // resolve the hostname to a temporary fake address
7645
+ node = DNS.lookup_name(node);
7646
+ addr = inetPton4(node);
7647
+ if (family === 0) {
7648
+ family = 2;
7649
+ } else if (family === 10) {
7650
+ addr = [0, 0, _htonl(65535), addr];
7651
+ }
7652
+ ai = allocaddrinfo(family, type, proto, null, addr, port);
7653
+ HEAPU32[out >> 2] = ai;
7654
+ return 0;
7655
+ };
7656
+
7657
+ var _getnameinfo = (sa, salen, node, nodelen, serv, servlen, flags) => {
7658
+ var info = readSockaddr(sa, salen);
7659
+ if (info.errno) {
7660
+ return -6;
7661
+ }
7662
+ var port = info.port;
7663
+ var addr = info.addr;
7664
+ var overflowed = false;
7665
+ if (node && nodelen) {
7666
+ var lookup;
7667
+ if (flags & 1 || !(lookup = DNS.lookup_addr(addr))) {
7668
+ if (flags & 8) {
7669
+ return -2;
7670
+ }
7671
+ } else {
7672
+ addr = lookup;
7200
7673
  }
7201
- if (ENVIRONMENT_IS_NODE) {
7202
- return require('child_process').spawn(command, args, {
7203
- ...options,
7204
- shell: true,
7205
- stdio: ['pipe', 'pipe', 'pipe'],
7206
- timeout: 100,
7207
- });
7674
+ var numBytesWrittenExclNull = stringToUTF8(addr, node, nodelen);
7675
+ if (numBytesWrittenExclNull + 1 >= nodelen) {
7676
+ overflowed = true;
7208
7677
  }
7209
- const e = new Error(
7210
- 'popen(), proc_open() etc. are unsupported in the browser. Call php.setSpawnHandler() ' +
7211
- 'and provide a callback to handle spawning processes, or disable a popen(), proc_open() ' +
7212
- 'and similar functions via php.ini.'
7213
- );
7214
- e.code = 'SPAWN_UNSUPPORTED';
7215
- throw e;
7216
- },
7217
- shutdownSocket: function (socketd, how) {
7218
- // This implementation only supports websockets at the moment
7219
- const sock = getSocketFromFD(socketd);
7220
- const peer = Object.values(sock.peers)[0];
7221
- if (!peer) {
7222
- return -1;
7678
+ }
7679
+ if (serv && servlen) {
7680
+ port = '' + port;
7681
+ var numBytesWrittenExclNull = stringToUTF8(port, serv, servlen);
7682
+ if (numBytesWrittenExclNull + 1 >= servlen) {
7683
+ overflowed = true;
7223
7684
  }
7224
- try {
7225
- peer.socket.close();
7226
- SOCKFS.websocket_sock_ops.removePeer(sock, peer);
7227
- return 0;
7228
- } catch (e) {
7229
- console.log('Socket shutdown error', e);
7230
- return -1;
7685
+ }
7686
+ if (overflowed) {
7687
+ // Note: even when we overflow, getnameinfo() is specced to write out the truncated results.
7688
+ return -12;
7689
+ }
7690
+ return 0;
7691
+ };
7692
+
7693
+ var Protocols = {
7694
+ list: [],
7695
+ map: {},
7696
+ };
7697
+
7698
+ var _setprotoent = (stayopen) => {
7699
+ // void setprotoent(int stayopen);
7700
+ // Allocate and populate a protoent structure given a name, protocol number and array of aliases
7701
+ function allocprotoent(name, proto, aliases) {
7702
+ // write name into buffer
7703
+ var nameBuf = _malloc(name.length + 1);
7704
+ stringToAscii(name, nameBuf);
7705
+ // write aliases into buffer
7706
+ var j = 0;
7707
+ var length = aliases.length;
7708
+ var aliasListBuf = _malloc((length + 1) * 4);
7709
+ // Use length + 1 so we have space for the terminating NULL ptr.
7710
+ for (var i = 0; i < length; i++, j += 4) {
7711
+ var alias = aliases[i];
7712
+ var aliasBuf = _malloc(alias.length + 1);
7713
+ stringToAscii(alias, aliasBuf);
7714
+ HEAPU32[(aliasListBuf + j) >> 2] = aliasBuf;
7231
7715
  }
7232
- },
7716
+ HEAPU32[(aliasListBuf + j) >> 2] = 0;
7717
+ // Terminating NULL pointer.
7718
+ // generate protoent
7719
+ var pe = _malloc(12);
7720
+ HEAPU32[pe >> 2] = nameBuf;
7721
+ HEAPU32[(pe + 4) >> 2] = aliasListBuf;
7722
+ HEAP32[(pe + 8) >> 2] = proto;
7723
+ return pe;
7724
+ }
7725
+ // Populate the protocol 'database'. The entries are limited to tcp and udp, though it is fairly trivial
7726
+ // to add extra entries from /etc/protocols if desired - though not sure if that'd actually be useful.
7727
+ var list = Protocols.list;
7728
+ var map = Protocols.map;
7729
+ if (list.length === 0) {
7730
+ var entry = allocprotoent('tcp', 6, ['TCP']);
7731
+ list.push(entry);
7732
+ map['tcp'] = map['6'] = entry;
7733
+ entry = allocprotoent('udp', 17, ['UDP']);
7734
+ list.push(entry);
7735
+ map['udp'] = map['17'] = entry;
7736
+ }
7737
+ _setprotoent.index = 0;
7738
+ };
7739
+
7740
+ var _getprotobyname = (name) => {
7741
+ // struct protoent *getprotobyname(const char *);
7742
+ name = UTF8ToString(name);
7743
+ _setprotoent(true);
7744
+ var result = Protocols.map[name];
7745
+ return result;
7746
+ };
7747
+
7748
+ var _getprotobynumber = (number) => {
7749
+ // struct protoent *getprotobynumber(int proto);
7750
+ _setprotoent(true);
7751
+ var result = Protocols.map[number];
7752
+ return result;
7233
7753
  };
7234
7754
 
7235
7755
  function _js_create_input_device(deviceId) {
@@ -7267,6 +7787,98 @@ export function init(RuntimeName, PHPLoader) {
7267
7787
  return allocateUTF8OnStack(devicePath);
7268
7788
  }
7269
7789
 
7790
+ async function _js_flock(fd, op) {
7791
+ _js_wasm_trace('js_flock(%d, %d)', fd, op);
7792
+ // Emscripten does not expose these constants to JS, so we hardcode them here.
7793
+ // Based on
7794
+ // https://github.com/emscripten-core/emscripten/blob/76860cc47cef67f5712a7a03a247bc1baabf7ba4/system/lib/libc/musl/include/sys/file.h#L7-L10
7795
+ const emscripten_LOCK_SH = 1;
7796
+ const emscripten_LOCK_EX = 2;
7797
+ const emscripten_LOCK_NB = 4;
7798
+ const emscripten_LOCK_UN = 8;
7799
+ const flockToLockOpType = {
7800
+ [emscripten_LOCK_SH]: 'shared',
7801
+ [emscripten_LOCK_EX]: 'exclusive',
7802
+ [emscripten_LOCK_UN]: 'unlocked',
7803
+ };
7804
+ let vfsPath;
7805
+ let errno;
7806
+ [vfsPath, errno] = locking.get_vfs_path_from_fd(fd);
7807
+ if (errno !== 0) {
7808
+ _js_wasm_trace(
7809
+ 'js_flock(%d, %d) get_vfs_path_from_fd errno %d',
7810
+ fd,
7811
+ op,
7812
+ vfsPath,
7813
+ errno
7814
+ );
7815
+ return -errno;
7816
+ }
7817
+ if (!locking.is_path_to_shared_fs(vfsPath)) {
7818
+ _js_wasm_trace(
7819
+ 'flock(%d, %d) locking is not implemented for non-NodeFS path %s',
7820
+ fd,
7821
+ op,
7822
+ vfsPath
7823
+ );
7824
+ // If not a NodeFS path, we can't lock it.
7825
+ // Default to succeeding as Emscripten does.
7826
+ return 0;
7827
+ }
7828
+ errno = locking.check_lock_params(fd, op);
7829
+ if (errno !== 0) {
7830
+ _js_wasm_trace(
7831
+ 'js_flock(%d, %d) check_lock_params errno %d',
7832
+ fd,
7833
+ op,
7834
+ errno
7835
+ );
7836
+ return -errno;
7837
+ }
7838
+ // @TODO: Consider supporting blocking mode of flock()
7839
+ if (op & (emscripten_LOCK_NB === 0)) {
7840
+ _js_wasm_trace(
7841
+ 'js_flock(%d, %d) blocking mode of flock() is not implemented',
7842
+ fd,
7843
+ op
7844
+ );
7845
+ // We do not yet support the blocking form of flock().
7846
+ // We respond with EINVAL to indicate failure
7847
+ // because it is a known errno for a failed blocking flock().
7848
+ return -ERRNO_CODES.EINVAL;
7849
+ }
7850
+ const maskedOp =
7851
+ op & (emscripten_LOCK_SH | emscripten_LOCK_EX | emscripten_LOCK_UN);
7852
+ const lockOpType = flockToLockOpType[maskedOp];
7853
+ if (lockOpType === undefined) {
7854
+ _js_wasm_trace(
7855
+ 'js_flock(%d, %d) invalid flock() operation',
7856
+ fd,
7857
+ op
7858
+ );
7859
+ return -ERRNO_CODES.EINVAL;
7860
+ }
7861
+ const nativeFilePath = locking.get_native_path_from_vfs_path(vfsPath);
7862
+ const obtainedLock = await PHPLoader.fileLockManager.lockWholeFile(
7863
+ nativeFilePath,
7864
+ {
7865
+ type: lockOpType,
7866
+ pid: PHPLoader.processId,
7867
+ fd,
7868
+ }
7869
+ );
7870
+ _js_wasm_trace(
7871
+ 'js_flock(%d, %d) lockWholeFile %s returned %d',
7872
+ fd,
7873
+ op,
7874
+ vfsPath,
7875
+ obtainedLock
7876
+ );
7877
+ return obtainedLock ? 0 : -ERRNO_CODES.EWOULDBLOCK;
7878
+ }
7879
+
7880
+ _js_flock.isAsync = true;
7881
+
7270
7882
  function _js_open_process(
7271
7883
  command,
7272
7884
  argsPtr,
@@ -7539,6 +8151,21 @@ export function init(RuntimeName, PHPLoader) {
7539
8151
  return 0;
7540
8152
  }
7541
8153
 
8154
+ var _js_release_file_locks = async function js_release_file_locks() {
8155
+ _js_wasm_trace('js_release_file_locks()');
8156
+ const pid = PHPLoader.processId;
8157
+ return await PHPLoader.fileLockManager
8158
+ .releaseLocksForProcess(pid)
8159
+ .then(() => {
8160
+ _js_wasm_trace('js_release_file_locks succeeded');
8161
+ })
8162
+ .catch((e) => {
8163
+ _js_wasm_trace('js_release_file_locks error %s', e);
8164
+ });
8165
+ };
8166
+
8167
+ _js_release_file_locks.isAsync = true;
8168
+
7542
8169
  function _js_waitpid(pid, exitCodePtr) {
7543
8170
  if (!PHPWASM.child_proc_by_pid[pid]) {
7544
8171
  return -1;
@@ -8465,9 +9092,13 @@ export function init(RuntimeName, PHPLoader) {
8465
9092
  /** @export */ getprotobyname: _getprotobyname,
8466
9093
  /** @export */ getprotobynumber: _getprotobynumber,
8467
9094
  /** @export */ js_create_input_device: _js_create_input_device,
9095
+ /** @export */ js_flock: _js_flock,
9096
+ /** @export */ js_getpid: _js_getpid,
8468
9097
  /** @export */ js_open_process: _js_open_process,
8469
9098
  /** @export */ js_process_status: _js_process_status,
9099
+ /** @export */ js_release_file_locks: _js_release_file_locks,
8470
9100
  /** @export */ js_waitpid: _js_waitpid,
9101
+ /** @export */ js_wasm_trace: _js_wasm_trace,
8471
9102
  /** @export */ proc_exit: _proc_exit,
8472
9103
  /** @export */ strptime: _strptime,
8473
9104
  /** @export */ wasm_close: _wasm_close,
@@ -8493,6 +9124,12 @@ export function init(RuntimeName, PHPLoader) {
8493
9124
 
8494
9125
  var _fflush = (a0) => (_fflush = wasmExports['fflush'])(a0);
8495
9126
 
9127
+ var _flock = (Module['_flock'] = (a0, a1) =>
9128
+ (_flock = Module['_flock'] = wasmExports['flock'])(a0, a1));
9129
+
9130
+ var _getpid = (Module['_getpid'] = () =>
9131
+ (_getpid = Module['_getpid'] = wasmExports['getpid'])());
9132
+
8496
9133
  var _wasm_popen = (Module['_wasm_popen'] = (a0, a1) =>
8497
9134
  (_wasm_popen = Module['_wasm_popen'] = wasmExports['wasm_popen'])(
8498
9135
  a0,
@@ -8607,6 +9244,16 @@ export function init(RuntimeName, PHPLoader) {
8607
9244
  var _wasm_free = (Module['_wasm_free'] = (a0) =>
8608
9245
  (_wasm_free = Module['_wasm_free'] = wasmExports['wasm_free'])(a0));
8609
9246
 
9247
+ var _wasm_get_end_offset = (Module['_wasm_get_end_offset'] = (a0) =>
9248
+ (_wasm_get_end_offset = Module['_wasm_get_end_offset'] =
9249
+ wasmExports['wasm_get_end_offset'])(a0));
9250
+
9251
+ var _wasm_trace = (Module['_wasm_trace'] = (a0, a1) =>
9252
+ (_wasm_trace = Module['_wasm_trace'] = wasmExports['wasm_trace'])(
9253
+ a0,
9254
+ a1
9255
+ ));
9256
+
8610
9257
  var ___funcs_on_exit = () =>
8611
9258
  (___funcs_on_exit = wasmExports['__funcs_on_exit'])();
8612
9259
 
@@ -8754,6 +9401,32 @@ export function init(RuntimeName, PHPLoader) {
8754
9401
  PHPLoader['free'] =
8755
9402
  typeof _free === 'function' ? _free : PHPLoader['_wasm_free'];
8756
9403
 
9404
+ if (typeof NODEFS === 'object') {
9405
+ // We override NODEFS.createNode() to add an `isSharedFS` flag to all NODEFS
9406
+ // nodes. This way we can tell whether file-locking is needed and possible
9407
+ // for an FS node, even if wrapped with PROXYFS.
9408
+ const originalCreateNode = NODEFS.createNode;
9409
+ NODEFS.createNode = function createNodeWithSharedFlag() {
9410
+ const node = originalCreateNode.apply(NODEFS, arguments);
9411
+ node.isSharedFS = true;
9412
+ return node;
9413
+ };
9414
+
9415
+ var originalHashAddNode = FS.hashAddNode;
9416
+ FS.hashAddNode = function hashAddNodeIfNotSharedFS(node) {
9417
+ if (
9418
+ typeof locking === 'object' &&
9419
+ locking?.is_shared_fs_node(node)
9420
+ ) {
9421
+ // Avoid caching shared VFS nodes so multiple instances
9422
+ // can access the same underlying filesystem without
9423
+ // conflicting caches.
9424
+ return;
9425
+ }
9426
+ return originalHashAddNode.apply(FS, arguments);
9427
+ };
9428
+ }
9429
+
8757
9430
  return PHPLoader;
8758
9431
 
8759
9432
  // Close the opening bracket from esm-prefix.js: