@php-wasm/node-5-2 3.1.34 → 3.1.36

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.
@@ -6145,6 +6145,7 @@ export function init(RuntimeName, PHPLoader) {
6145
6145
  O_NONBLOCK: 2048,
6146
6146
  POLLHUP: 16,
6147
6147
  SETFL_MASK: 3072,
6148
+ socketTimeouts: new Map,
6148
6149
  init: function () {
6149
6150
  // TODO: Move this to a library function that is made an onInit callback by the `__postset` suffix.
6150
6151
  if (PHPLoader.bindUserSpace) {
@@ -6574,6 +6575,29 @@ export function init(RuntimeName, PHPLoader) {
6574
6575
  return [promise, cancel];
6575
6576
  },
6576
6577
  noop: function () {},
6578
+ parseSocketTimeout: function (optionValuePtr, optionLen) {
6579
+ if (!optionValuePtr || optionLen < 8) {
6580
+ return null;
6581
+ }
6582
+ let seconds;
6583
+ let microseconds;
6584
+ if (optionLen >= 16) {
6585
+ seconds = Number(HEAP64[optionValuePtr >> 3]);
6586
+ microseconds = Number(HEAP64[(optionValuePtr + 8) >> 3]);
6587
+ } else {
6588
+ seconds = HEAP32[optionValuePtr >> 2];
6589
+ microseconds = HEAP32[(optionValuePtr + 4) >> 2];
6590
+ }
6591
+ if (
6592
+ !Number.isFinite(seconds) ||
6593
+ !Number.isFinite(microseconds) ||
6594
+ seconds < 0 ||
6595
+ microseconds < 0
6596
+ ) {
6597
+ return null;
6598
+ }
6599
+ return seconds * 1e3 + Math.ceil(microseconds / 1e3);
6600
+ },
6577
6601
  spawnProcess: function (command, args, options) {
6578
6602
  if (Module['spawnProcess']) {
6579
6603
  const spawned = Module['spawnProcess'](
@@ -6622,6 +6646,7 @@ export function init(RuntimeName, PHPLoader) {
6622
6646
  throw e;
6623
6647
  },
6624
6648
  shutdownSocket: function (socketd, how) {
6649
+ PHPWASM.socketTimeouts.delete(socketd);
6625
6650
  // This implementation only supports websockets at the moment
6626
6651
  const sock = getSocketFromFD(socketd);
6627
6652
  const peer = Object.values(sock.peers)[0];
@@ -6706,43 +6731,74 @@ export function init(RuntimeName, PHPLoader) {
6706
6731
  wakeUp(-ERRNO_CODES.ECONNREFUSED);
6707
6732
  return;
6708
6733
  }
6709
- // Wait for the connection to be established
6710
- const timeout = 3e4;
6711
- // 30 second timeout
6734
+ // Wait for the connection to be established. A zero timeval
6735
+ // disables the timeout, matching SO_SNDTIMEO semantics.
6736
+ const sendTimeout = PHPWASM.socketTimeouts.get(sockfd)?.send;
6737
+ const timeout = sendTimeout ?? 3e4;
6712
6738
  let resolved = false;
6713
- const timeoutId = setTimeout(() => {
6714
- if (!resolved) {
6715
- resolved = true;
6716
- wakeUp(-ERRNO_CODES.ETIMEDOUT);
6717
- }
6718
- }, timeout);
6719
- const handleOpen = () => {
6720
- if (!resolved) {
6721
- resolved = true;
6739
+ let timeoutId;
6740
+ let handleOpen;
6741
+ let handleError;
6742
+ let handleClose;
6743
+ const peer = PHPWASM.getAllPeers(sock).find(
6744
+ (candidate) => candidate.socket === ws
6745
+ );
6746
+
6747
+ const cleanupConnectListeners = () => {
6748
+ if (typeof timeoutId !== 'undefined') {
6722
6749
  clearTimeout(timeoutId);
6723
- ws.removeEventListener('error', handleError);
6724
- ws.removeEventListener('close', handleClose);
6725
- wakeUp(0);
6726
6750
  }
6751
+ ws.removeEventListener('open', handleOpen);
6752
+ ws.removeEventListener('error', handleError);
6753
+ ws.removeEventListener('close', handleClose);
6727
6754
  };
6728
- const handleError = () => {
6729
- if (!resolved) {
6730
- resolved = true;
6731
- clearTimeout(timeoutId);
6732
- ws.removeEventListener('open', handleOpen);
6733
- ws.removeEventListener('close', handleClose);
6734
- wakeUp(-ERRNO_CODES.ECONNREFUSED);
6755
+
6756
+ const cleanupFailedConnect = (errno) => {
6757
+ try {
6758
+ if (
6759
+ ws.readyState !== ws.CLOSING &&
6760
+ ws.readyState !== ws.CLOSED
6761
+ ) {
6762
+ ws.close();
6763
+ }
6764
+ } catch (e) {
6765
+ // Ignore close errors on an already-failed connect.
6735
6766
  }
6767
+ if (peer) {
6768
+ SOCKFS.websocket_sock_ops.removePeer(sock, peer);
6769
+ }
6770
+ sock.connecting = false;
6771
+ sock.error = errno;
6736
6772
  };
6737
- const handleClose = () => {
6773
+
6774
+ const finishConnect = (result) => {
6738
6775
  if (!resolved) {
6739
6776
  resolved = true;
6740
- clearTimeout(timeoutId);
6741
- ws.removeEventListener('open', handleOpen);
6742
- ws.removeEventListener('error', handleError);
6743
- wakeUp(-ERRNO_CODES.ECONNREFUSED);
6777
+ cleanupConnectListeners();
6778
+ if (result < 0) {
6779
+ cleanupFailedConnect(-result);
6780
+ }
6781
+ wakeUp(result);
6744
6782
  }
6745
6783
  };
6784
+
6785
+ if (timeout > 0) {
6786
+ timeoutId = setTimeout(() => {
6787
+ finishConnect(-ERRNO_CODES.ETIMEDOUT);
6788
+ }, timeout);
6789
+ }
6790
+
6791
+ handleOpen = () => {
6792
+ finishConnect(0);
6793
+ };
6794
+
6795
+ handleError = () => {
6796
+ finishConnect(-ERRNO_CODES.ECONNREFUSED);
6797
+ };
6798
+
6799
+ handleClose = () => {
6800
+ finishConnect(-ERRNO_CODES.ECONNREFUSED);
6801
+ };
6746
6802
  ws.addEventListener('open', handleOpen);
6747
6803
  ws.addEventListener('error', handleError);
6748
6804
  ws.addEventListener('close', handleClose);
@@ -9515,25 +9571,35 @@ export function init(RuntimeName, PHPLoader) {
9515
9571
  const SO_SNDTIMEO = 67;
9516
9572
  const IPPROTO_TCP = 6;
9517
9573
  const TCP_NODELAY = 1;
9518
- // Options that we can forward to the WebSocket proxy
9574
+ if (
9575
+ level === SOL_SOCKET &&
9576
+ (optionName === SO_RCVTIMEO || optionName === SO_SNDTIMEO)
9577
+ ) {
9578
+ const timeoutMs = PHPWASM.parseSocketTimeout(
9579
+ optionValuePtr,
9580
+ optionLen
9581
+ );
9582
+ if (timeoutMs === null) {
9583
+ return -1;
9584
+ }
9585
+ const timeouts = PHPWASM.socketTimeouts.get(socketd) || {};
9586
+ if (optionName === SO_RCVTIMEO) {
9587
+ timeouts.receive = timeoutMs;
9588
+ } else {
9589
+ timeouts.send = timeoutMs;
9590
+ }
9591
+ PHPWASM.socketTimeouts.set(socketd, timeouts);
9592
+ return 0;
9593
+ }
9519
9594
  const isForwardable =
9520
9595
  (level === SOL_SOCKET && optionName === SO_KEEPALIVE) ||
9521
9596
  (level === IPPROTO_TCP && optionName === TCP_NODELAY);
9522
- // Options that we acknowledge but don't actually implement
9523
- // (WebSocket connections handle timeouts differently)
9524
- const isIgnorable =
9525
- level === SOL_SOCKET &&
9526
- (optionName === SO_RCVTIMEO || optionName === SO_SNDTIMEO);
9527
- if (!isForwardable && !isIgnorable) {
9597
+ if (!isForwardable) {
9528
9598
  console.warn(
9529
9599
  `Unsupported socket option: ${level}, ${optionName}, ${optionValue}`
9530
9600
  );
9531
9601
  return -1;
9532
9602
  }
9533
- // For ignorable options, just return success
9534
- if (isIgnorable) {
9535
- return 0;
9536
- }
9537
9603
  const ws = PHPWASM.getAllWebSockets(socketd)[0];
9538
9604
  if (!ws) {
9539
9605
  return -1;
package/jspi/php_5_2.js CHANGED
@@ -6086,6 +6086,7 @@ export function init(RuntimeName, PHPLoader) {
6086
6086
  O_NONBLOCK: 2048,
6087
6087
  POLLHUP: 16,
6088
6088
  SETFL_MASK: 3072,
6089
+ socketTimeouts: new Map,
6089
6090
  init: function () {
6090
6091
  // TODO: Move this to a library function that is made an onInit callback by the `__postset` suffix.
6091
6092
  if (PHPLoader.bindUserSpace) {
@@ -6515,6 +6516,29 @@ export function init(RuntimeName, PHPLoader) {
6515
6516
  return [promise, cancel];
6516
6517
  },
6517
6518
  noop: function () {},
6519
+ parseSocketTimeout: function (optionValuePtr, optionLen) {
6520
+ if (!optionValuePtr || optionLen < 8) {
6521
+ return null;
6522
+ }
6523
+ let seconds;
6524
+ let microseconds;
6525
+ if (optionLen >= 16) {
6526
+ seconds = Number(HEAP64[optionValuePtr >> 3]);
6527
+ microseconds = Number(HEAP64[(optionValuePtr + 8) >> 3]);
6528
+ } else {
6529
+ seconds = HEAP32[optionValuePtr >> 2];
6530
+ microseconds = HEAP32[(optionValuePtr + 4) >> 2];
6531
+ }
6532
+ if (
6533
+ !Number.isFinite(seconds) ||
6534
+ !Number.isFinite(microseconds) ||
6535
+ seconds < 0 ||
6536
+ microseconds < 0
6537
+ ) {
6538
+ return null;
6539
+ }
6540
+ return seconds * 1e3 + Math.ceil(microseconds / 1e3);
6541
+ },
6518
6542
  spawnProcess: function (command, args, options) {
6519
6543
  if (Module['spawnProcess']) {
6520
6544
  const spawned = Module['spawnProcess'](
@@ -6563,6 +6587,7 @@ export function init(RuntimeName, PHPLoader) {
6563
6587
  throw e;
6564
6588
  },
6565
6589
  shutdownSocket: function (socketd, how) {
6590
+ PHPWASM.socketTimeouts.delete(socketd);
6566
6591
  // This implementation only supports websockets at the moment
6567
6592
  const sock = getSocketFromFD(socketd);
6568
6593
  const peer = Object.values(sock.peers)[0];
@@ -6647,43 +6672,74 @@ export function init(RuntimeName, PHPLoader) {
6647
6672
  wakeUp(-ERRNO_CODES.ECONNREFUSED);
6648
6673
  return;
6649
6674
  }
6650
- // Wait for the connection to be established
6651
- const timeout = 3e4;
6652
- // 30 second timeout
6675
+ // Wait for the connection to be established. A zero timeval
6676
+ // disables the timeout, matching SO_SNDTIMEO semantics.
6677
+ const sendTimeout = PHPWASM.socketTimeouts.get(sockfd)?.send;
6678
+ const timeout = sendTimeout ?? 3e4;
6653
6679
  let resolved = false;
6654
- const timeoutId = setTimeout(() => {
6655
- if (!resolved) {
6656
- resolved = true;
6657
- wakeUp(-ERRNO_CODES.ETIMEDOUT);
6658
- }
6659
- }, timeout);
6660
- const handleOpen = () => {
6661
- if (!resolved) {
6662
- resolved = true;
6680
+ let timeoutId;
6681
+ let handleOpen;
6682
+ let handleError;
6683
+ let handleClose;
6684
+ const peer = PHPWASM.getAllPeers(sock).find(
6685
+ (candidate) => candidate.socket === ws
6686
+ );
6687
+
6688
+ const cleanupConnectListeners = () => {
6689
+ if (typeof timeoutId !== 'undefined') {
6663
6690
  clearTimeout(timeoutId);
6664
- ws.removeEventListener('error', handleError);
6665
- ws.removeEventListener('close', handleClose);
6666
- wakeUp(0);
6667
6691
  }
6692
+ ws.removeEventListener('open', handleOpen);
6693
+ ws.removeEventListener('error', handleError);
6694
+ ws.removeEventListener('close', handleClose);
6668
6695
  };
6669
- const handleError = () => {
6670
- if (!resolved) {
6671
- resolved = true;
6672
- clearTimeout(timeoutId);
6673
- ws.removeEventListener('open', handleOpen);
6674
- ws.removeEventListener('close', handleClose);
6675
- wakeUp(-ERRNO_CODES.ECONNREFUSED);
6696
+
6697
+ const cleanupFailedConnect = (errno) => {
6698
+ try {
6699
+ if (
6700
+ ws.readyState !== ws.CLOSING &&
6701
+ ws.readyState !== ws.CLOSED
6702
+ ) {
6703
+ ws.close();
6704
+ }
6705
+ } catch (e) {
6706
+ // Ignore close errors on an already-failed connect.
6676
6707
  }
6708
+ if (peer) {
6709
+ SOCKFS.websocket_sock_ops.removePeer(sock, peer);
6710
+ }
6711
+ sock.connecting = false;
6712
+ sock.error = errno;
6677
6713
  };
6678
- const handleClose = () => {
6714
+
6715
+ const finishConnect = (result) => {
6679
6716
  if (!resolved) {
6680
6717
  resolved = true;
6681
- clearTimeout(timeoutId);
6682
- ws.removeEventListener('open', handleOpen);
6683
- ws.removeEventListener('error', handleError);
6684
- wakeUp(-ERRNO_CODES.ECONNREFUSED);
6718
+ cleanupConnectListeners();
6719
+ if (result < 0) {
6720
+ cleanupFailedConnect(-result);
6721
+ }
6722
+ wakeUp(result);
6685
6723
  }
6686
6724
  };
6725
+
6726
+ if (timeout > 0) {
6727
+ timeoutId = setTimeout(() => {
6728
+ finishConnect(-ERRNO_CODES.ETIMEDOUT);
6729
+ }, timeout);
6730
+ }
6731
+
6732
+ handleOpen = () => {
6733
+ finishConnect(0);
6734
+ };
6735
+
6736
+ handleError = () => {
6737
+ finishConnect(-ERRNO_CODES.ECONNREFUSED);
6738
+ };
6739
+
6740
+ handleClose = () => {
6741
+ finishConnect(-ERRNO_CODES.ECONNREFUSED);
6742
+ };
6687
6743
  ws.addEventListener('open', handleOpen);
6688
6744
  ws.addEventListener('error', handleError);
6689
6745
  ws.addEventListener('close', handleClose);
@@ -9450,25 +9506,35 @@ export function init(RuntimeName, PHPLoader) {
9450
9506
  const SO_SNDTIMEO = 67;
9451
9507
  const IPPROTO_TCP = 6;
9452
9508
  const TCP_NODELAY = 1;
9453
- // Options that we can forward to the WebSocket proxy
9509
+ if (
9510
+ level === SOL_SOCKET &&
9511
+ (optionName === SO_RCVTIMEO || optionName === SO_SNDTIMEO)
9512
+ ) {
9513
+ const timeoutMs = PHPWASM.parseSocketTimeout(
9514
+ optionValuePtr,
9515
+ optionLen
9516
+ );
9517
+ if (timeoutMs === null) {
9518
+ return -1;
9519
+ }
9520
+ const timeouts = PHPWASM.socketTimeouts.get(socketd) || {};
9521
+ if (optionName === SO_RCVTIMEO) {
9522
+ timeouts.receive = timeoutMs;
9523
+ } else {
9524
+ timeouts.send = timeoutMs;
9525
+ }
9526
+ PHPWASM.socketTimeouts.set(socketd, timeouts);
9527
+ return 0;
9528
+ }
9454
9529
  const isForwardable =
9455
9530
  (level === SOL_SOCKET && optionName === SO_KEEPALIVE) ||
9456
9531
  (level === IPPROTO_TCP && optionName === TCP_NODELAY);
9457
- // Options that we acknowledge but don't actually implement
9458
- // (WebSocket connections handle timeouts differently)
9459
- const isIgnorable =
9460
- level === SOL_SOCKET &&
9461
- (optionName === SO_RCVTIMEO || optionName === SO_SNDTIMEO);
9462
- if (!isForwardable && !isIgnorable) {
9532
+ if (!isForwardable) {
9463
9533
  console.warn(
9464
9534
  `Unsupported socket option: ${level}, ${optionName}, ${optionValue}`
9465
9535
  );
9466
9536
  return -1;
9467
9537
  }
9468
- // For ignorable options, just return success
9469
- if (isIgnorable) {
9470
- return 0;
9471
- }
9472
9538
  const ws = PHPWASM.getAllWebSockets(socketd)[0];
9473
9539
  if (!ws) {
9474
9540
  return -1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@php-wasm/node-5-2",
3
- "version": "3.1.34",
3
+ "version": "3.1.36",
4
4
  "description": "PHP 5.2 WebAssembly binaries for node (legacy)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -35,10 +35,10 @@
35
35
  "node": ">=20.10.0",
36
36
  "npm": ">=10.2.3"
37
37
  },
38
- "gitHead": "86daccc84fe31900eb57c4c8e1c3ba21a7ae8d13",
38
+ "gitHead": "371f4fd6f9d56af6fb35b6c2cf0267edaea83755",
39
39
  "dependencies": {
40
40
  "wasm-feature-detect": "1.8.0",
41
- "@php-wasm/universal": "3.1.34"
41
+ "@php-wasm/universal": "3.1.36"
42
42
  },
43
43
  "packageManager": "npm@10.9.2",
44
44
  "overrides": {