@statewalker/webrun-http-browser 0.12.1 → 0.12.2
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.
- package/dist/index.js +22 -18
- package/dist/sw.js +22 -18
- package/dist/worker.js +22 -18
- package/dist/ws/frames.d.ts +6 -1
- package/dist/ws/frames.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/ws/frames.ts +18 -12
package/dist/index.js
CHANGED
|
@@ -1747,7 +1747,7 @@ const LAST_CHUNK = /* @__PURE__ */ new Uint8Array([
|
|
|
1747
1747
|
13,
|
|
1748
1748
|
10
|
|
1749
1749
|
]);
|
|
1750
|
-
const encoder = /* @__PURE__ */ new TextEncoder();
|
|
1750
|
+
const encoder$2 = /* @__PURE__ */ new TextEncoder();
|
|
1751
1751
|
/**
|
|
1752
1752
|
* Chunk sizes are written in HEXADECIMAL — a 21-byte chunk is `15`. Writing
|
|
1753
1753
|
* them in decimal is the defect note 15 found in @libp2p/http, and it is the
|
|
@@ -1760,7 +1760,7 @@ const encoder = /* @__PURE__ */ new TextEncoder();
|
|
|
1760
1760
|
async function* encodeChunked(body) {
|
|
1761
1761
|
for await (const chunk of body) {
|
|
1762
1762
|
if (chunk.byteLength === 0) continue;
|
|
1763
|
-
yield encoder.encode(`${chunk.byteLength.toString(16)}\r\n`);
|
|
1763
|
+
yield encoder$2.encode(`${chunk.byteLength.toString(16)}\r\n`);
|
|
1764
1764
|
yield chunk;
|
|
1765
1765
|
yield CRLF;
|
|
1766
1766
|
}
|
|
@@ -3331,7 +3331,7 @@ const STREAM_ABORT = "webrun-rpc:stream-abort";
|
|
|
3331
3331
|
* request, sent only on a port where both ends agreed `pipeline`. The window's
|
|
3332
3332
|
* credit is its confirmation.
|
|
3333
3333
|
*/
|
|
3334
|
-
const CHUNK = "webrun-rpc:chunk";
|
|
3334
|
+
const CHUNK$1 = "webrun-rpc:chunk";
|
|
3335
3335
|
/**
|
|
3336
3336
|
* What a pipelined chunk counts beyond its bytes, against the window, on the
|
|
3337
3337
|
* receiving side. Both codecs' windows count more for the chunk's envelope
|
|
@@ -3662,7 +3662,7 @@ function receiveChunks(port, channelName, controller, touch, notice) {
|
|
|
3662
3662
|
const watcher = (event) => {
|
|
3663
3663
|
const data = event.data;
|
|
3664
3664
|
if (data?.channelName !== channelName) return;
|
|
3665
|
-
const chunk = data.type === CHUNK ? data.chunk : data.type === "request" ? data.params : void 0;
|
|
3665
|
+
const chunk = data.type === CHUNK$1 ? data.chunk : data.type === "request" ? data.params : void 0;
|
|
3666
3666
|
if (!chunk) return;
|
|
3667
3667
|
if (!watchPeerEnd()) {
|
|
3668
3668
|
port.removeEventListener("message", watcher);
|
|
@@ -3697,7 +3697,7 @@ function receiveChunks(port, channelName, controller, touch, notice) {
|
|
|
3697
3697
|
}, { channelName });
|
|
3698
3698
|
const onChunk = (event) => {
|
|
3699
3699
|
const data = event.data;
|
|
3700
|
-
if (data?.type !== CHUNK || data.channelName !== channelName || !data.chunk) return;
|
|
3700
|
+
if (data?.type !== CHUNK$1 || data.channelName !== channelName || !data.chunk) return;
|
|
3701
3701
|
if (poison) return;
|
|
3702
3702
|
const agreement = portAgreement(port);
|
|
3703
3703
|
if (!agreement?.caps.has("pipeline")) {
|
|
@@ -3810,7 +3810,7 @@ async function sendChunks(port, channelName, output, { maxMessageSize, log }, si
|
|
|
3810
3810
|
});
|
|
3811
3811
|
if (mayPipeline(port)) {
|
|
3812
3812
|
port.postMessage({
|
|
3813
|
-
type: CHUNK,
|
|
3813
|
+
type: CHUNK$1,
|
|
3814
3814
|
channelName,
|
|
3815
3815
|
chunk
|
|
3816
3816
|
});
|
|
@@ -5104,20 +5104,24 @@ function postFrame(port, frame) {
|
|
|
5104
5104
|
function messageSize(data) {
|
|
5105
5105
|
return typeof data === "string" ? utf8Length(data) : data.byteLength;
|
|
5106
5106
|
}
|
|
5107
|
-
|
|
5107
|
+
const encoder = new TextEncoder();
|
|
5108
|
+
/** Characters encoded per `encodeInto` call: at most 3 bytes each, so the scratch stays at 96 KiB. */
|
|
5109
|
+
const CHUNK = 32768;
|
|
5110
|
+
const scratch = new Uint8Array(CHUNK * 3);
|
|
5111
|
+
/**
|
|
5112
|
+
* The UTF-8 length of `text`, as `TextEncoder` would encode it (a lone surrogate counts as the 3
|
|
5113
|
+
* bytes of U+FFFD). Every message is measured on both ends (`bufferedAmount` and the byte acks), so
|
|
5114
|
+
* this runs natively: `encodeInto` a reused buffer, a chunk at a time, never splitting a surrogate
|
|
5115
|
+
* pair across two chunks. A loop over the characters in JavaScript took about 30 times as long.
|
|
5116
|
+
*/
|
|
5108
5117
|
function utf8Length(text) {
|
|
5109
5118
|
let length = 0;
|
|
5110
|
-
for (let
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
if (next >= 56320 && next <= 57343) {
|
|
5117
|
-
length += 4;
|
|
5118
|
-
i++;
|
|
5119
|
-
} else length += 3;
|
|
5120
|
-
} else length += 3;
|
|
5119
|
+
for (let start = 0; start < text.length;) {
|
|
5120
|
+
let end = Math.min(start + CHUNK, text.length);
|
|
5121
|
+
const last = text.charCodeAt(end - 1);
|
|
5122
|
+
if (end < text.length && last >= 55296 && last <= 56319) end--;
|
|
5123
|
+
length += encoder.encodeInto(text.slice(start, end), scratch).written;
|
|
5124
|
+
start = end;
|
|
5121
5125
|
}
|
|
5122
5126
|
return length;
|
|
5123
5127
|
}
|
package/dist/sw.js
CHANGED
|
@@ -706,7 +706,7 @@ const LAST_CHUNK = /* @__PURE__ */ new Uint8Array([
|
|
|
706
706
|
13,
|
|
707
707
|
10
|
|
708
708
|
]);
|
|
709
|
-
const encoder = /* @__PURE__ */ new TextEncoder();
|
|
709
|
+
const encoder$2 = /* @__PURE__ */ new TextEncoder();
|
|
710
710
|
/**
|
|
711
711
|
* Chunk sizes are written in HEXADECIMAL — a 21-byte chunk is `15`. Writing
|
|
712
712
|
* them in decimal is the defect note 15 found in @libp2p/http, and it is the
|
|
@@ -719,7 +719,7 @@ const encoder = /* @__PURE__ */ new TextEncoder();
|
|
|
719
719
|
async function* encodeChunked(body) {
|
|
720
720
|
for await (const chunk of body) {
|
|
721
721
|
if (chunk.byteLength === 0) continue;
|
|
722
|
-
yield encoder.encode(`${chunk.byteLength.toString(16)}\r\n`);
|
|
722
|
+
yield encoder$2.encode(`${chunk.byteLength.toString(16)}\r\n`);
|
|
723
723
|
yield chunk;
|
|
724
724
|
yield CRLF;
|
|
725
725
|
}
|
|
@@ -2089,7 +2089,7 @@ const STREAM_ABORT = "webrun-rpc:stream-abort";
|
|
|
2089
2089
|
* request, sent only on a port where both ends agreed `pipeline`. The window's
|
|
2090
2090
|
* credit is its confirmation.
|
|
2091
2091
|
*/
|
|
2092
|
-
const CHUNK = "webrun-rpc:chunk";
|
|
2092
|
+
const CHUNK$1 = "webrun-rpc:chunk";
|
|
2093
2093
|
/**
|
|
2094
2094
|
* What a pipelined chunk counts beyond its bytes, against the window, on the
|
|
2095
2095
|
* receiving side. Both codecs' windows count more for the chunk's envelope
|
|
@@ -2420,7 +2420,7 @@ function receiveChunks(port, channelName, controller, touch, notice) {
|
|
|
2420
2420
|
const watcher = (event) => {
|
|
2421
2421
|
const data = event.data;
|
|
2422
2422
|
if (data?.channelName !== channelName) return;
|
|
2423
|
-
const chunk = data.type === CHUNK ? data.chunk : data.type === "request" ? data.params : void 0;
|
|
2423
|
+
const chunk = data.type === CHUNK$1 ? data.chunk : data.type === "request" ? data.params : void 0;
|
|
2424
2424
|
if (!chunk) return;
|
|
2425
2425
|
if (!watchPeerEnd()) {
|
|
2426
2426
|
port.removeEventListener("message", watcher);
|
|
@@ -2455,7 +2455,7 @@ function receiveChunks(port, channelName, controller, touch, notice) {
|
|
|
2455
2455
|
}, { channelName });
|
|
2456
2456
|
const onChunk = (event) => {
|
|
2457
2457
|
const data = event.data;
|
|
2458
|
-
if (data?.type !== CHUNK || data.channelName !== channelName || !data.chunk) return;
|
|
2458
|
+
if (data?.type !== CHUNK$1 || data.channelName !== channelName || !data.chunk) return;
|
|
2459
2459
|
if (poison) return;
|
|
2460
2460
|
const agreement = portAgreement(port);
|
|
2461
2461
|
if (!agreement?.caps.has("pipeline")) {
|
|
@@ -2568,7 +2568,7 @@ async function sendChunks(port, channelName, output, { maxMessageSize, log }, si
|
|
|
2568
2568
|
});
|
|
2569
2569
|
if (mayPipeline(port)) {
|
|
2570
2570
|
port.postMessage({
|
|
2571
|
-
type: CHUNK,
|
|
2571
|
+
type: CHUNK$1,
|
|
2572
2572
|
channelName,
|
|
2573
2573
|
chunk
|
|
2574
2574
|
});
|
|
@@ -3867,20 +3867,24 @@ function postFrame(port, frame) {
|
|
|
3867
3867
|
function messageSize(data) {
|
|
3868
3868
|
return typeof data === "string" ? utf8Length(data) : data.byteLength;
|
|
3869
3869
|
}
|
|
3870
|
-
|
|
3870
|
+
const encoder = new TextEncoder();
|
|
3871
|
+
/** Characters encoded per `encodeInto` call: at most 3 bytes each, so the scratch stays at 96 KiB. */
|
|
3872
|
+
const CHUNK = 32768;
|
|
3873
|
+
const scratch = new Uint8Array(CHUNK * 3);
|
|
3874
|
+
/**
|
|
3875
|
+
* The UTF-8 length of `text`, as `TextEncoder` would encode it (a lone surrogate counts as the 3
|
|
3876
|
+
* bytes of U+FFFD). Every message is measured on both ends (`bufferedAmount` and the byte acks), so
|
|
3877
|
+
* this runs natively: `encodeInto` a reused buffer, a chunk at a time, never splitting a surrogate
|
|
3878
|
+
* pair across two chunks. A loop over the characters in JavaScript took about 30 times as long.
|
|
3879
|
+
*/
|
|
3871
3880
|
function utf8Length(text) {
|
|
3872
3881
|
let length = 0;
|
|
3873
|
-
for (let
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
if (next >= 56320 && next <= 57343) {
|
|
3880
|
-
length += 4;
|
|
3881
|
-
i++;
|
|
3882
|
-
} else length += 3;
|
|
3883
|
-
} else length += 3;
|
|
3882
|
+
for (let start = 0; start < text.length;) {
|
|
3883
|
+
let end = Math.min(start + CHUNK, text.length);
|
|
3884
|
+
const last = text.charCodeAt(end - 1);
|
|
3885
|
+
if (end < text.length && last >= 55296 && last <= 56319) end--;
|
|
3886
|
+
length += encoder.encodeInto(text.slice(start, end), scratch).written;
|
|
3887
|
+
start = end;
|
|
3884
3888
|
}
|
|
3885
3889
|
return length;
|
|
3886
3890
|
}
|
package/dist/worker.js
CHANGED
|
@@ -647,7 +647,7 @@ const LAST_CHUNK = /* @__PURE__ */ new Uint8Array([
|
|
|
647
647
|
13,
|
|
648
648
|
10
|
|
649
649
|
]);
|
|
650
|
-
const encoder = /* @__PURE__ */ new TextEncoder();
|
|
650
|
+
const encoder$2 = /* @__PURE__ */ new TextEncoder();
|
|
651
651
|
/**
|
|
652
652
|
* Chunk sizes are written in HEXADECIMAL — a 21-byte chunk is `15`. Writing
|
|
653
653
|
* them in decimal is the defect note 15 found in @libp2p/http, and it is the
|
|
@@ -660,7 +660,7 @@ const encoder = /* @__PURE__ */ new TextEncoder();
|
|
|
660
660
|
async function* encodeChunked(body) {
|
|
661
661
|
for await (const chunk of body) {
|
|
662
662
|
if (chunk.byteLength === 0) continue;
|
|
663
|
-
yield encoder.encode(`${chunk.byteLength.toString(16)}\r\n`);
|
|
663
|
+
yield encoder$2.encode(`${chunk.byteLength.toString(16)}\r\n`);
|
|
664
664
|
yield chunk;
|
|
665
665
|
yield CRLF;
|
|
666
666
|
}
|
|
@@ -1975,7 +1975,7 @@ const STREAM_ABORT = "webrun-rpc:stream-abort";
|
|
|
1975
1975
|
* request, sent only on a port where both ends agreed `pipeline`. The window's
|
|
1976
1976
|
* credit is its confirmation.
|
|
1977
1977
|
*/
|
|
1978
|
-
const CHUNK = "webrun-rpc:chunk";
|
|
1978
|
+
const CHUNK$1 = "webrun-rpc:chunk";
|
|
1979
1979
|
/**
|
|
1980
1980
|
* What a pipelined chunk counts beyond its bytes, against the window, on the
|
|
1981
1981
|
* receiving side. Both codecs' windows count more for the chunk's envelope
|
|
@@ -2306,7 +2306,7 @@ function receiveChunks(port, channelName, controller, touch, notice) {
|
|
|
2306
2306
|
const watcher = (event) => {
|
|
2307
2307
|
const data = event.data;
|
|
2308
2308
|
if (data?.channelName !== channelName) return;
|
|
2309
|
-
const chunk = data.type === CHUNK ? data.chunk : data.type === "request" ? data.params : void 0;
|
|
2309
|
+
const chunk = data.type === CHUNK$1 ? data.chunk : data.type === "request" ? data.params : void 0;
|
|
2310
2310
|
if (!chunk) return;
|
|
2311
2311
|
if (!watchPeerEnd()) {
|
|
2312
2312
|
port.removeEventListener("message", watcher);
|
|
@@ -2341,7 +2341,7 @@ function receiveChunks(port, channelName, controller, touch, notice) {
|
|
|
2341
2341
|
}, { channelName });
|
|
2342
2342
|
const onChunk = (event) => {
|
|
2343
2343
|
const data = event.data;
|
|
2344
|
-
if (data?.type !== CHUNK || data.channelName !== channelName || !data.chunk) return;
|
|
2344
|
+
if (data?.type !== CHUNK$1 || data.channelName !== channelName || !data.chunk) return;
|
|
2345
2345
|
if (poison) return;
|
|
2346
2346
|
const agreement = portAgreement(port);
|
|
2347
2347
|
if (!agreement?.caps.has("pipeline")) {
|
|
@@ -2454,7 +2454,7 @@ async function sendChunks(port, channelName, output, { maxMessageSize, log }, si
|
|
|
2454
2454
|
});
|
|
2455
2455
|
if (mayPipeline(port)) {
|
|
2456
2456
|
port.postMessage({
|
|
2457
|
-
type: CHUNK,
|
|
2457
|
+
type: CHUNK$1,
|
|
2458
2458
|
channelName,
|
|
2459
2459
|
chunk
|
|
2460
2460
|
});
|
|
@@ -3678,20 +3678,24 @@ function postFrame(port, frame) {
|
|
|
3678
3678
|
function messageSize(data) {
|
|
3679
3679
|
return typeof data === "string" ? utf8Length(data) : data.byteLength;
|
|
3680
3680
|
}
|
|
3681
|
-
|
|
3681
|
+
const encoder = new TextEncoder();
|
|
3682
|
+
/** Characters encoded per `encodeInto` call: at most 3 bytes each, so the scratch stays at 96 KiB. */
|
|
3683
|
+
const CHUNK = 32768;
|
|
3684
|
+
const scratch = new Uint8Array(CHUNK * 3);
|
|
3685
|
+
/**
|
|
3686
|
+
* The UTF-8 length of `text`, as `TextEncoder` would encode it (a lone surrogate counts as the 3
|
|
3687
|
+
* bytes of U+FFFD). Every message is measured on both ends (`bufferedAmount` and the byte acks), so
|
|
3688
|
+
* this runs natively: `encodeInto` a reused buffer, a chunk at a time, never splitting a surrogate
|
|
3689
|
+
* pair across two chunks. A loop over the characters in JavaScript took about 30 times as long.
|
|
3690
|
+
*/
|
|
3682
3691
|
function utf8Length(text) {
|
|
3683
3692
|
let length = 0;
|
|
3684
|
-
for (let
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
if (next >= 56320 && next <= 57343) {
|
|
3691
|
-
length += 4;
|
|
3692
|
-
i++;
|
|
3693
|
-
} else length += 3;
|
|
3694
|
-
} else length += 3;
|
|
3693
|
+
for (let start = 0; start < text.length;) {
|
|
3694
|
+
let end = Math.min(start + CHUNK, text.length);
|
|
3695
|
+
const last = text.charCodeAt(end - 1);
|
|
3696
|
+
if (end < text.length && last >= 55296 && last <= 56319) end--;
|
|
3697
|
+
length += encoder.encodeInto(text.slice(start, end), scratch).written;
|
|
3698
|
+
start = end;
|
|
3695
3699
|
}
|
|
3696
3700
|
return length;
|
|
3697
3701
|
}
|
package/dist/ws/frames.d.ts
CHANGED
|
@@ -63,6 +63,11 @@ export declare function readFrame(data: unknown): WsFrame | undefined;
|
|
|
63
63
|
export declare function postFrame(port: MessagePort, frame: WsFrame): void;
|
|
64
64
|
/** The size a message counts for in `bufferedAmount`: UTF-8 bytes, or the buffer's length. */
|
|
65
65
|
export declare function messageSize(data: string | ArrayBuffer): number;
|
|
66
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* The UTF-8 length of `text`, as `TextEncoder` would encode it (a lone surrogate counts as the 3
|
|
68
|
+
* bytes of U+FFFD). Every message is measured on both ends (`bufferedAmount` and the byte acks), so
|
|
69
|
+
* this runs natively: `encodeInto` a reused buffer, a chunk at a time, never splitting a surrogate
|
|
70
|
+
* pair across two chunks. A loop over the characters in JavaScript took about 30 times as long.
|
|
71
|
+
*/
|
|
67
72
|
export declare function utf8Length(text: string): number;
|
|
68
73
|
//# sourceMappingURL=frames.d.ts.map
|
package/dist/ws/frames.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../../src/ws/frames.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,0EAA0E;AAC1E,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAE3C,oEAAoE;AACpE,eAAO,MAAM,wBAAwB,OAAQ,CAAC;AAE9C,MAAM,MAAM,OAAO,GACf;IAAE,CAAC,EAAE,GAAG,CAAC;IAAC,CAAC,EAAE,MAAM,GAAG,WAAW,CAAA;CAAE,GACnC;IAAE,CAAC,EAAE,GAAG,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,CAAC,EAAE,GAAG,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GACtB;IAAE,CAAC,EAAE,GAAG,CAAA;CAAE,GACV;IAAE,CAAC,EAAE,GAAG,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1B;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,UAAU,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAChD,YAAY,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACjD,aAAa,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;CAClC;AAED,eAAO,MAAM,aAAa,EAAE,QAK3B,CAAC;AAEF,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CA2B5D;AAED,6DAA6D;AAC7D,wBAAgB,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAGjE;AAED,8FAA8F;AAC9F,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAE9D;
|
|
1
|
+
{"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../../src/ws/frames.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,0EAA0E;AAC1E,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAE3C,oEAAoE;AACpE,eAAO,MAAM,wBAAwB,OAAQ,CAAC;AAE9C,MAAM,MAAM,OAAO,GACf;IAAE,CAAC,EAAE,GAAG,CAAC;IAAC,CAAC,EAAE,MAAM,GAAG,WAAW,CAAA;CAAE,GACnC;IAAE,CAAC,EAAE,GAAG,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,CAAC,EAAE,GAAG,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GACtB;IAAE,CAAC,EAAE,GAAG,CAAA;CAAE,GACV;IAAE,CAAC,EAAE,GAAG,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1B;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,UAAU,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAChD,YAAY,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACjD,aAAa,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;CAClC;AAED,eAAO,MAAM,aAAa,EAAE,QAK3B,CAAC;AAEF,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CA2B5D;AAED,6DAA6D;AAC7D,wBAAgB,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAGjE;AAED,8FAA8F;AAC9F,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAE9D;AAOD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAW/C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statewalker/webrun-http-browser",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "ServiceWorker-based HTTP and WebSocket server for browsers: handlers in pages and Dedicated Workers, same-origin and relay modes, streams with backpressure",
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
],
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"idb-keyval": "^6.3.0",
|
|
61
|
-
"@statewalker/webrun-streams": "^0.
|
|
61
|
+
"@statewalker/webrun-http-streams": "^0.4.0",
|
|
62
62
|
"@statewalker/webrun-rpc": "^0.10.0",
|
|
63
|
-
"@statewalker/webrun-
|
|
63
|
+
"@statewalker/webrun-streams": "^0.2.3"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@biomejs/biome": "^2.5.15",
|
package/src/ws/frames.ts
CHANGED
|
@@ -100,20 +100,26 @@ export function messageSize(data: string | ArrayBuffer): number {
|
|
|
100
100
|
return typeof data === "string" ? utf8Length(data) : data.byteLength;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
const encoder = new TextEncoder();
|
|
104
|
+
/** Characters encoded per `encodeInto` call: at most 3 bytes each, so the scratch stays at 96 KiB. */
|
|
105
|
+
const CHUNK = 32_768;
|
|
106
|
+
const scratch = new Uint8Array(CHUNK * 3);
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The UTF-8 length of `text`, as `TextEncoder` would encode it (a lone surrogate counts as the 3
|
|
110
|
+
* bytes of U+FFFD). Every message is measured on both ends (`bufferedAmount` and the byte acks), so
|
|
111
|
+
* this runs natively: `encodeInto` a reused buffer, a chunk at a time, never splitting a surrogate
|
|
112
|
+
* pair across two chunks. A loop over the characters in JavaScript took about 30 times as long.
|
|
113
|
+
*/
|
|
104
114
|
export function utf8Length(text: string): number {
|
|
105
115
|
let length = 0;
|
|
106
|
-
for (let
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
length += 4;
|
|
114
|
-
i++;
|
|
115
|
-
} else length += 3;
|
|
116
|
-
} else length += 3;
|
|
116
|
+
for (let start = 0; start < text.length; ) {
|
|
117
|
+
let end = Math.min(start + CHUNK, text.length);
|
|
118
|
+
// A high surrogate ending the chunk goes with its low surrogate into the next one.
|
|
119
|
+
const last = text.charCodeAt(end - 1);
|
|
120
|
+
if (end < text.length && last >= 0xd800 && last <= 0xdbff) end--;
|
|
121
|
+
length += encoder.encodeInto(text.slice(start, end), scratch).written;
|
|
122
|
+
start = end;
|
|
117
123
|
}
|
|
118
124
|
return length;
|
|
119
125
|
}
|