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