@driftengine/network 4.8.2 → 4.8.3

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.
@@ -68,3 +68,16 @@ export interface Transport {
68
68
  * shared memory, which a browser refuses to send, is copied off it.
69
69
  */
70
70
  export declare function sendable(message: Uint8Array): Uint8Array<ArrayBuffer>;
71
+ /**
72
+ * A received message's bytes, whatever the socket or channel handed over, or null where nothing
73
+ * can be read out of it — which the transport counts as dropped.
74
+ *
75
+ * Browsers deliver an `ArrayBuffer` once `binaryType` is set, `ws` under Node delivers a `Buffer`,
76
+ * and a **text frame** arrives as a string. A text frame is lossless UTF-8 by the protocol, so its
77
+ * bytes are exactly what the sender wrote, and it is read as them. It was discarded until 4.8.3,
78
+ * on the ground that a payload through UTF-8 loses every byte above 0x7f — which is true of binary
79
+ * data somebody sent as text, and not of a server that speaks text, whose every message then
80
+ * vanished without a count. **What this gives up** is nothing a sender can still lose: binary bytes
81
+ * sent as text were mangled before they reached this, by the sender.
82
+ */
83
+ export declare function receivedBytes(data: unknown): Uint8Array | null;
package/dist/transport.js CHANGED
@@ -49,3 +49,27 @@ export function sendable(message) {
49
49
  ? message
50
50
  : message.slice();
51
51
  }
52
+ const UTF8 = new TextEncoder();
53
+ /**
54
+ * A received message's bytes, whatever the socket or channel handed over, or null where nothing
55
+ * can be read out of it — which the transport counts as dropped.
56
+ *
57
+ * Browsers deliver an `ArrayBuffer` once `binaryType` is set, `ws` under Node delivers a `Buffer`,
58
+ * and a **text frame** arrives as a string. A text frame is lossless UTF-8 by the protocol, so its
59
+ * bytes are exactly what the sender wrote, and it is read as them. It was discarded until 4.8.3,
60
+ * on the ground that a payload through UTF-8 loses every byte above 0x7f — which is true of binary
61
+ * data somebody sent as text, and not of a server that speaks text, whose every message then
62
+ * vanished without a count. **What this gives up** is nothing a sender can still lose: binary bytes
63
+ * sent as text were mangled before they reached this, by the sender.
64
+ */
65
+ export function receivedBytes(data) {
66
+ if (data instanceof Uint8Array)
67
+ return data;
68
+ if (data instanceof ArrayBuffer)
69
+ return new Uint8Array(data);
70
+ if (ArrayBuffer.isView(data))
71
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
72
+ if (typeof data === 'string')
73
+ return UTF8.encode(data);
74
+ return null;
75
+ }
package/dist/webrtc.js CHANGED
@@ -30,7 +30,7 @@
30
30
  * That is a weaker guarantee than the loopback transport has, and it is why WebSocket is the
31
31
  * default rather than this.
32
32
  */
33
- import { BROADCAST, sendable, } from './transport.js';
33
+ import { BROADCAST, receivedBytes, sendable, } from './transport.js';
34
34
  /**
35
35
  * A channel configured the way a simulation wants one.
36
36
  *
@@ -57,9 +57,11 @@ export class WebRtcTransport {
57
57
  this.channel.binaryType = 'arraybuffer';
58
58
  this.channel.addEventListener('message', (event) => {
59
59
  const data = event.data;
60
- const bytes = toBytes(data);
61
- if (bytes === null)
60
+ const bytes = receivedBytes(data);
61
+ if (bytes === null) {
62
+ this.droppedCount += 1;
62
63
  return;
64
+ }
63
65
  if (this.arrived.length >= this.maxQueued) {
64
66
  this.arrived.shift();
65
67
  this.droppedCount += 1;
@@ -96,13 +98,3 @@ export class WebRtcTransport {
96
98
  this.channel.close();
97
99
  }
98
100
  }
99
- function toBytes(data) {
100
- if (data instanceof Uint8Array)
101
- return data;
102
- if (data instanceof ArrayBuffer)
103
- return new Uint8Array(data);
104
- if (ArrayBuffer.isView(data)) {
105
- return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
106
- }
107
- return null;
108
- }
@@ -60,7 +60,10 @@ export declare class WebSocketTransport implements Transport {
60
60
  private droppedCount;
61
61
  constructor(options: WebSocketTransportOptions);
62
62
  get state(): TransportState;
63
- /** Messages dropped because nothing drained. A consumer watching for a stalled tab reads this. */
63
+ /**
64
+ * Messages dropped: because nothing drained, which a consumer watching for a stalled tab reads,
65
+ * or because nothing could be read out of them.
66
+ */
64
67
  get dropped(): number;
65
68
  /**
66
69
  * Send, or do nothing if the socket is not open yet.
package/dist/websocket.js CHANGED
@@ -23,7 +23,7 @@
23
23
  * the credentials and the reconnection policy. A transport that opened its own connection would be
24
24
  * making four decisions that belong to whoever is paying for the server.
25
25
  */
26
- import { BROADCAST, sendable, } from './transport.js';
26
+ import { BROADCAST, receivedBytes, sendable, } from './transport.js';
27
27
  /** The `readyState` values, which are the same three numbers everywhere. */
28
28
  const OPEN = 1;
29
29
  const CLOSED = 3;
@@ -44,9 +44,11 @@ export class WebSocketTransport {
44
44
  this.socket.binaryType = 'arraybuffer';
45
45
  this.socket.addEventListener('message', (event) => {
46
46
  const data = event.data;
47
- const bytes = toBytes(data);
48
- if (bytes === null)
47
+ const bytes = receivedBytes(data);
48
+ if (bytes === null) {
49
+ this.droppedCount += 1;
49
50
  return;
51
+ }
50
52
  if (this.arrived.length >= this.maxQueued) {
51
53
  this.arrived.shift();
52
54
  this.droppedCount += 1;
@@ -59,7 +61,10 @@ export class WebSocketTransport {
59
61
  return 'closed';
60
62
  return this.socket.readyState === OPEN ? 'open' : 'connecting';
61
63
  }
62
- /** Messages dropped because nothing drained. A consumer watching for a stalled tab reads this. */
64
+ /**
65
+ * Messages dropped: because nothing drained, which a consumer watching for a stalled tab reads,
66
+ * or because nothing could be read out of them.
67
+ */
63
68
  get dropped() {
64
69
  return this.droppedCount;
65
70
  }
@@ -86,20 +91,3 @@ export class WebSocketTransport {
86
91
  this.socket.close();
87
92
  }
88
93
  }
89
- /**
90
- * A message's bytes, whatever the socket handed over, or null.
91
- *
92
- * Browsers deliver an `ArrayBuffer` when `binaryType` is set, `ws` under Node delivers a `Buffer`,
93
- * and a socket left on its default delivers a string. The first two are usable and the third is
94
- * not: a payload that has been through UTF-8 has had every byte above 0x7f replaced.
95
- */
96
- function toBytes(data) {
97
- if (data instanceof Uint8Array)
98
- return data;
99
- if (data instanceof ArrayBuffer)
100
- return new Uint8Array(data);
101
- if (ArrayBuffer.isView(data)) {
102
- return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
103
- }
104
- return null;
105
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@driftengine/network",
3
- "version": "4.8.2",
3
+ "version": "4.8.3",
4
4
  "description": "A transport seam, rewind and replay, lockstep and an authoritative host, on the fixed-step loop",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -27,10 +27,10 @@
27
27
  ],
28
28
  "sideEffects": false,
29
29
  "peerDependencies": {
30
- "@driftengine/entities": "4.8.2"
30
+ "@driftengine/entities": "4.8.3"
31
31
  },
32
32
  "devDependencies": {
33
- "@driftengine/core": "4.8.2"
33
+ "@driftengine/core": "4.8.3"
34
34
  },
35
35
  "author": "Drift Technologies",
36
36
  "repository": {
package/src/transport.ts CHANGED
@@ -79,3 +79,26 @@ export function sendable(message: Uint8Array): Uint8Array<ArrayBuffer> {
79
79
  ? (message as Uint8Array<ArrayBuffer>)
80
80
  : message.slice();
81
81
  }
82
+
83
+ const UTF8 = new TextEncoder();
84
+
85
+ /**
86
+ * A received message's bytes, whatever the socket or channel handed over, or null where nothing
87
+ * can be read out of it — which the transport counts as dropped.
88
+ *
89
+ * Browsers deliver an `ArrayBuffer` once `binaryType` is set, `ws` under Node delivers a `Buffer`,
90
+ * and a **text frame** arrives as a string. A text frame is lossless UTF-8 by the protocol, so its
91
+ * bytes are exactly what the sender wrote, and it is read as them. It was discarded until 4.8.3,
92
+ * on the ground that a payload through UTF-8 loses every byte above 0x7f — which is true of binary
93
+ * data somebody sent as text, and not of a server that speaks text, whose every message then
94
+ * vanished without a count. **What this gives up** is nothing a sender can still lose: binary bytes
95
+ * sent as text were mangled before they reached this, by the sender.
96
+ */
97
+ export function receivedBytes(data: unknown): Uint8Array | null {
98
+ if (data instanceof Uint8Array) return data;
99
+ if (data instanceof ArrayBuffer) return new Uint8Array(data);
100
+ if (ArrayBuffer.isView(data))
101
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
102
+ if (typeof data === 'string') return UTF8.encode(data);
103
+ return null;
104
+ }
package/src/webrtc.ts CHANGED
@@ -36,6 +36,7 @@ import {
36
36
  type PeerId,
37
37
  type Transport,
38
38
  type TransportState,
39
+ receivedBytes,
39
40
  sendable,
40
41
  } from './transport.ts';
41
42
 
@@ -94,8 +95,11 @@ export class WebRtcTransport implements Transport {
94
95
 
95
96
  this.channel.addEventListener('message', (event) => {
96
97
  const data = (event as { data?: unknown }).data;
97
- const bytes = toBytes(data);
98
- if (bytes === null) return;
98
+ const bytes = receivedBytes(data);
99
+ if (bytes === null) {
100
+ this.droppedCount += 1;
101
+ return;
102
+ }
99
103
  if (this.arrived.length >= this.maxQueued) {
100
104
  this.arrived.shift();
101
105
  this.droppedCount += 1;
@@ -132,12 +136,3 @@ export class WebRtcTransport implements Transport {
132
136
  this.channel.close();
133
137
  }
134
138
  }
135
-
136
- function toBytes(data: unknown): Uint8Array | null {
137
- if (data instanceof Uint8Array) return data;
138
- if (data instanceof ArrayBuffer) return new Uint8Array(data);
139
- if (ArrayBuffer.isView(data)) {
140
- return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
141
- }
142
- return null;
143
- }
package/src/websocket.ts CHANGED
@@ -29,6 +29,7 @@ import {
29
29
  type PeerId,
30
30
  type Transport,
31
31
  type TransportState,
32
+ receivedBytes,
32
33
  sendable,
33
34
  } from './transport.ts';
34
35
 
@@ -85,8 +86,11 @@ export class WebSocketTransport implements Transport {
85
86
 
86
87
  this.socket.addEventListener('message', (event) => {
87
88
  const data = (event as { data?: unknown }).data;
88
- const bytes = toBytes(data);
89
- if (bytes === null) return;
89
+ const bytes = receivedBytes(data);
90
+ if (bytes === null) {
91
+ this.droppedCount += 1;
92
+ return;
93
+ }
90
94
  if (this.arrived.length >= this.maxQueued) {
91
95
  this.arrived.shift();
92
96
  this.droppedCount += 1;
@@ -100,7 +104,10 @@ export class WebSocketTransport implements Transport {
100
104
  return this.socket.readyState === OPEN ? 'open' : 'connecting';
101
105
  }
102
106
 
103
- /** Messages dropped because nothing drained. A consumer watching for a stalled tab reads this. */
107
+ /**
108
+ * Messages dropped: because nothing drained, which a consumer watching for a stalled tab reads,
109
+ * or because nothing could be read out of them.
110
+ */
104
111
  get dropped(): number {
105
112
  return this.droppedCount;
106
113
  }
@@ -128,19 +135,3 @@ export class WebSocketTransport implements Transport {
128
135
  this.socket.close();
129
136
  }
130
137
  }
131
-
132
- /**
133
- * A message's bytes, whatever the socket handed over, or null.
134
- *
135
- * Browsers deliver an `ArrayBuffer` when `binaryType` is set, `ws` under Node delivers a `Buffer`,
136
- * and a socket left on its default delivers a string. The first two are usable and the third is
137
- * not: a payload that has been through UTF-8 has had every byte above 0x7f replaced.
138
- */
139
- function toBytes(data: unknown): Uint8Array | null {
140
- if (data instanceof Uint8Array) return data;
141
- if (data instanceof ArrayBuffer) return new Uint8Array(data);
142
- if (ArrayBuffer.isView(data)) {
143
- return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
144
- }
145
- return null;
146
- }