beam.com 0.1.0-rc.3 → 0.1.0-rc.4
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/README.md +2 -2
- package/package.json +1 -1
- package/runtime/cloudflare/worker.js +27 -10
- package/runtime/deno/worker.js +27 -10
- package/runtime/page/runtime-id.js +1 -1
- package/runtime/page/worker.js +27 -10
- package/runtime/release.json +1 -1
- package/runtime/runtime-id.js +1 -1
- package/runtime/worker.js +27 -10
package/README.md
CHANGED
|
@@ -219,7 +219,7 @@ jobs:
|
|
|
219
219
|
|
|
220
220
|
Then turn on Pages one time: Settings, Pages, Source "GitHub Actions". The
|
|
221
221
|
`GITHUB_TOKEN` cannot do this step. Until the release `v0.1.0`, use the
|
|
222
|
-
release candidate `@v0.1.0-rc.
|
|
222
|
+
release candidate `@v0.1.0-rc.4` in place of `@v0.1.0`. With `@main`, the
|
|
223
223
|
workflow uses the `edge` build of `beam.com`.
|
|
224
224
|
|
|
225
225
|
The workflow ([`pages-app.yml`](.github/workflows/pages-app.yml)) builds
|
|
@@ -286,7 +286,7 @@ Each GitHub release from 0.1.0-rc.2 also holds the package, the same
|
|
|
286
286
|
file as on npm. npm installs it with no registry:
|
|
287
287
|
|
|
288
288
|
```sh
|
|
289
|
-
npm install https://github.com/sntran/BEAM.com/releases/download/v0.1.0-rc.
|
|
289
|
+
npm install https://github.com/sntran/BEAM.com/releases/download/v0.1.0-rc.4/beam.com-0.1.0-rc.4.tgz
|
|
290
290
|
```
|
|
291
291
|
|
|
292
292
|
- `BEAM_COM`: the path of a `beam.com` to use. Then nothing is
|
package/package.json
CHANGED
|
@@ -1972,8 +1972,10 @@ export class Vm {
|
|
|
1972
1972
|
// body of the request, and the messages of a WebSocket. sent: the
|
|
1973
1973
|
// host tells wasm_tcp what the client took (tcp_sent).
|
|
1974
1974
|
this.event({ t: 'tcp_accept', id: this.listeners.get(port), conn: id, host: request.headers.get('cf-connecting-ip') ?? '0.0.0.0', port: 0, ack: !!body || upgrade, sent: true });
|
|
1975
|
-
|
|
1976
|
-
|
|
1975
|
+
// With a body, the head goes in the event of the first part of the
|
|
1976
|
+
// body (bridgeUpload): a small body is one event, as before the parts.
|
|
1977
|
+
if (body) this.bridgeUpload(c, body, declared === null, maxBody, bytes);
|
|
1978
|
+
else this.bridgeSend(c, bytes);
|
|
1977
1979
|
});
|
|
1978
1980
|
}
|
|
1979
1981
|
|
|
@@ -1987,8 +1989,10 @@ export class Vm {
|
|
|
1987
1989
|
// (or the rest of the body): one event for each part, not for each small
|
|
1988
1990
|
// chunk of the client. A part goes when less than UPLOAD_WINDOW bytes are
|
|
1989
1991
|
// unread in the VM (tcp_read of wasm_tcp): so a large body does not fill
|
|
1990
|
-
// the memory of the VM, and a slow app slows the client.
|
|
1991
|
-
|
|
1992
|
+
// the memory of the VM, and a slow app slows the client. The head of the
|
|
1993
|
+
// request goes with the bytes of the first read of the client, with no
|
|
1994
|
+
// wait for UPLOAD_PART bytes.
|
|
1995
|
+
async bridgeUpload(c, body, chunked, max, head) {
|
|
1992
1996
|
// workerd has readAtLeast. The option min of the standard BYOB read is
|
|
1993
1997
|
// not safe: when the stream closes with fewer bytes than min, the read
|
|
1994
1998
|
// errors the stream (Node.js 26, Chromium). So the other hosts use the
|
|
@@ -1997,7 +2001,7 @@ export class Vm {
|
|
|
1997
2001
|
try { byob = body.getReader({ mode: 'byob' }); } catch {}
|
|
1998
2002
|
if (byob && !byob.readAtLeast) { byob.releaseLock(); byob = null; }
|
|
1999
2003
|
const reader = byob ?? body.getReader();
|
|
2000
|
-
const read = byob ? () => byob.readAtLeast(
|
|
2004
|
+
const read = byob ? (min) => byob.readAtLeast(min, new Uint8Array(UPLOAD_READ)) : () => reader.read();
|
|
2001
2005
|
let total = 0;
|
|
2002
2006
|
let part = [];
|
|
2003
2007
|
let size = 0;
|
|
@@ -2011,13 +2015,22 @@ export class Vm {
|
|
|
2011
2015
|
const bytes = part.length === 1 ? part[0] : join(part, size);
|
|
2012
2016
|
part = [];
|
|
2013
2017
|
size = 0;
|
|
2014
|
-
|
|
2018
|
+
out(chunked ? chunk(bytes) : bytes);
|
|
2015
2019
|
return true;
|
|
2016
2020
|
};
|
|
2021
|
+
// Bytes to the app, after the head when it did not go yet.
|
|
2022
|
+
const out = (bytes) => {
|
|
2023
|
+
clearTimeout(alone);
|
|
2024
|
+
this.bridgeSend(c, head ? join([head, bytes], head.length + bytes.length) : bytes);
|
|
2025
|
+
head = null;
|
|
2026
|
+
};
|
|
2027
|
+
// A client that sends no body yet: the head goes alone after HEAD_WAIT
|
|
2028
|
+
// ms, so the app sees the request (and its own time limits run).
|
|
2029
|
+
const alone = setTimeout(() => { if (head && !c.done && !this.dead) out(new Uint8Array(0)); }, HEAD_WAIT);
|
|
2017
2030
|
try {
|
|
2018
2031
|
for (;;) {
|
|
2019
2032
|
// A read can end the stream with its last bytes (done and a value).
|
|
2020
|
-
const { value, done } = await read();
|
|
2033
|
+
const { value, done } = await read(head ? 1 : UPLOAD_PART);
|
|
2021
2034
|
if (c.done || this.dead) break;
|
|
2022
2035
|
if (value?.length) {
|
|
2023
2036
|
total += value.length;
|
|
@@ -2035,10 +2048,11 @@ export class Vm {
|
|
|
2035
2048
|
size += piece.length;
|
|
2036
2049
|
if (size >= UPLOAD_PART) ok = await flush();
|
|
2037
2050
|
}
|
|
2038
|
-
if (ok && done && size) ok = await flush();
|
|
2051
|
+
if (ok && (done || head) && size) ok = await flush();
|
|
2039
2052
|
if (!ok) break;
|
|
2040
2053
|
if (done) {
|
|
2041
|
-
if (chunked)
|
|
2054
|
+
if (chunked) out(CHUNKS_END);
|
|
2055
|
+
else if (head) out(new Uint8Array(0));
|
|
2042
2056
|
this.bridgeClock(c, c.timeout * 1000);
|
|
2043
2057
|
return;
|
|
2044
2058
|
}
|
|
@@ -2759,7 +2773,10 @@ const LATE = Symbol('late');
|
|
|
2759
2773
|
// read in workerd and of the largest piece of a client chunk. A client chunk can be 2 KB (workerd), and each event
|
|
2760
2774
|
// costs a turn of the VM.
|
|
2761
2775
|
const UPLOAD_WINDOW = 256 * 1024;
|
|
2762
|
-
const UPLOAD_PART =
|
|
2776
|
+
const UPLOAD_PART = 32 * 1024;
|
|
2777
|
+
// The time that the head of a request waits for the first bytes of its
|
|
2778
|
+
// body (bridgeUpload), in ms.
|
|
2779
|
+
const HEAD_WAIT = 20;
|
|
2763
2780
|
const UPLOAD_READ = 64 * 1024;
|
|
2764
2781
|
|
|
2765
2782
|
// The size bytes of the list parts, as one array.
|
package/runtime/deno/worker.js
CHANGED
|
@@ -1972,8 +1972,10 @@ export class Vm {
|
|
|
1972
1972
|
// body of the request, and the messages of a WebSocket. sent: the
|
|
1973
1973
|
// host tells wasm_tcp what the client took (tcp_sent).
|
|
1974
1974
|
this.event({ t: 'tcp_accept', id: this.listeners.get(port), conn: id, host: request.headers.get('cf-connecting-ip') ?? '0.0.0.0', port: 0, ack: !!body || upgrade, sent: true });
|
|
1975
|
-
|
|
1976
|
-
|
|
1975
|
+
// With a body, the head goes in the event of the first part of the
|
|
1976
|
+
// body (bridgeUpload): a small body is one event, as before the parts.
|
|
1977
|
+
if (body) this.bridgeUpload(c, body, declared === null, maxBody, bytes);
|
|
1978
|
+
else this.bridgeSend(c, bytes);
|
|
1977
1979
|
});
|
|
1978
1980
|
}
|
|
1979
1981
|
|
|
@@ -1987,8 +1989,10 @@ export class Vm {
|
|
|
1987
1989
|
// (or the rest of the body): one event for each part, not for each small
|
|
1988
1990
|
// chunk of the client. A part goes when less than UPLOAD_WINDOW bytes are
|
|
1989
1991
|
// unread in the VM (tcp_read of wasm_tcp): so a large body does not fill
|
|
1990
|
-
// the memory of the VM, and a slow app slows the client.
|
|
1991
|
-
|
|
1992
|
+
// the memory of the VM, and a slow app slows the client. The head of the
|
|
1993
|
+
// request goes with the bytes of the first read of the client, with no
|
|
1994
|
+
// wait for UPLOAD_PART bytes.
|
|
1995
|
+
async bridgeUpload(c, body, chunked, max, head) {
|
|
1992
1996
|
// workerd has readAtLeast. The option min of the standard BYOB read is
|
|
1993
1997
|
// not safe: when the stream closes with fewer bytes than min, the read
|
|
1994
1998
|
// errors the stream (Node.js 26, Chromium). So the other hosts use the
|
|
@@ -1997,7 +2001,7 @@ export class Vm {
|
|
|
1997
2001
|
try { byob = body.getReader({ mode: 'byob' }); } catch {}
|
|
1998
2002
|
if (byob && !byob.readAtLeast) { byob.releaseLock(); byob = null; }
|
|
1999
2003
|
const reader = byob ?? body.getReader();
|
|
2000
|
-
const read = byob ? () => byob.readAtLeast(
|
|
2004
|
+
const read = byob ? (min) => byob.readAtLeast(min, new Uint8Array(UPLOAD_READ)) : () => reader.read();
|
|
2001
2005
|
let total = 0;
|
|
2002
2006
|
let part = [];
|
|
2003
2007
|
let size = 0;
|
|
@@ -2011,13 +2015,22 @@ export class Vm {
|
|
|
2011
2015
|
const bytes = part.length === 1 ? part[0] : join(part, size);
|
|
2012
2016
|
part = [];
|
|
2013
2017
|
size = 0;
|
|
2014
|
-
|
|
2018
|
+
out(chunked ? chunk(bytes) : bytes);
|
|
2015
2019
|
return true;
|
|
2016
2020
|
};
|
|
2021
|
+
// Bytes to the app, after the head when it did not go yet.
|
|
2022
|
+
const out = (bytes) => {
|
|
2023
|
+
clearTimeout(alone);
|
|
2024
|
+
this.bridgeSend(c, head ? join([head, bytes], head.length + bytes.length) : bytes);
|
|
2025
|
+
head = null;
|
|
2026
|
+
};
|
|
2027
|
+
// A client that sends no body yet: the head goes alone after HEAD_WAIT
|
|
2028
|
+
// ms, so the app sees the request (and its own time limits run).
|
|
2029
|
+
const alone = setTimeout(() => { if (head && !c.done && !this.dead) out(new Uint8Array(0)); }, HEAD_WAIT);
|
|
2017
2030
|
try {
|
|
2018
2031
|
for (;;) {
|
|
2019
2032
|
// A read can end the stream with its last bytes (done and a value).
|
|
2020
|
-
const { value, done } = await read();
|
|
2033
|
+
const { value, done } = await read(head ? 1 : UPLOAD_PART);
|
|
2021
2034
|
if (c.done || this.dead) break;
|
|
2022
2035
|
if (value?.length) {
|
|
2023
2036
|
total += value.length;
|
|
@@ -2035,10 +2048,11 @@ export class Vm {
|
|
|
2035
2048
|
size += piece.length;
|
|
2036
2049
|
if (size >= UPLOAD_PART) ok = await flush();
|
|
2037
2050
|
}
|
|
2038
|
-
if (ok && done && size) ok = await flush();
|
|
2051
|
+
if (ok && (done || head) && size) ok = await flush();
|
|
2039
2052
|
if (!ok) break;
|
|
2040
2053
|
if (done) {
|
|
2041
|
-
if (chunked)
|
|
2054
|
+
if (chunked) out(CHUNKS_END);
|
|
2055
|
+
else if (head) out(new Uint8Array(0));
|
|
2042
2056
|
this.bridgeClock(c, c.timeout * 1000);
|
|
2043
2057
|
return;
|
|
2044
2058
|
}
|
|
@@ -2759,7 +2773,10 @@ const LATE = Symbol('late');
|
|
|
2759
2773
|
// read in workerd and of the largest piece of a client chunk. A client chunk can be 2 KB (workerd), and each event
|
|
2760
2774
|
// costs a turn of the VM.
|
|
2761
2775
|
const UPLOAD_WINDOW = 256 * 1024;
|
|
2762
|
-
const UPLOAD_PART =
|
|
2776
|
+
const UPLOAD_PART = 32 * 1024;
|
|
2777
|
+
// The time that the head of a request waits for the first bytes of its
|
|
2778
|
+
// body (bridgeUpload), in ms.
|
|
2779
|
+
const HEAD_WAIT = 20;
|
|
2763
2780
|
const UPLOAD_READ = 64 * 1024;
|
|
2764
2781
|
|
|
2765
2782
|
// The size bytes of the list parts, as one array.
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// The identity of this runtime (beam_com_wasm:runtime_id/1): the SHA-256 of
|
|
2
2
|
// the output of "sha256sum app-com.js beam.mjs beam.wasm worker.js".
|
|
3
|
-
export default '
|
|
3
|
+
export default '3ef0d2bdd150e2ab64517e29e6e85fbf70382d878b9ccbca998a22f15b566dc0';
|
package/runtime/page/worker.js
CHANGED
|
@@ -1972,8 +1972,10 @@ export class Vm {
|
|
|
1972
1972
|
// body of the request, and the messages of a WebSocket. sent: the
|
|
1973
1973
|
// host tells wasm_tcp what the client took (tcp_sent).
|
|
1974
1974
|
this.event({ t: 'tcp_accept', id: this.listeners.get(port), conn: id, host: request.headers.get('cf-connecting-ip') ?? '0.0.0.0', port: 0, ack: !!body || upgrade, sent: true });
|
|
1975
|
-
|
|
1976
|
-
|
|
1975
|
+
// With a body, the head goes in the event of the first part of the
|
|
1976
|
+
// body (bridgeUpload): a small body is one event, as before the parts.
|
|
1977
|
+
if (body) this.bridgeUpload(c, body, declared === null, maxBody, bytes);
|
|
1978
|
+
else this.bridgeSend(c, bytes);
|
|
1977
1979
|
});
|
|
1978
1980
|
}
|
|
1979
1981
|
|
|
@@ -1987,8 +1989,10 @@ export class Vm {
|
|
|
1987
1989
|
// (or the rest of the body): one event for each part, not for each small
|
|
1988
1990
|
// chunk of the client. A part goes when less than UPLOAD_WINDOW bytes are
|
|
1989
1991
|
// unread in the VM (tcp_read of wasm_tcp): so a large body does not fill
|
|
1990
|
-
// the memory of the VM, and a slow app slows the client.
|
|
1991
|
-
|
|
1992
|
+
// the memory of the VM, and a slow app slows the client. The head of the
|
|
1993
|
+
// request goes with the bytes of the first read of the client, with no
|
|
1994
|
+
// wait for UPLOAD_PART bytes.
|
|
1995
|
+
async bridgeUpload(c, body, chunked, max, head) {
|
|
1992
1996
|
// workerd has readAtLeast. The option min of the standard BYOB read is
|
|
1993
1997
|
// not safe: when the stream closes with fewer bytes than min, the read
|
|
1994
1998
|
// errors the stream (Node.js 26, Chromium). So the other hosts use the
|
|
@@ -1997,7 +2001,7 @@ export class Vm {
|
|
|
1997
2001
|
try { byob = body.getReader({ mode: 'byob' }); } catch {}
|
|
1998
2002
|
if (byob && !byob.readAtLeast) { byob.releaseLock(); byob = null; }
|
|
1999
2003
|
const reader = byob ?? body.getReader();
|
|
2000
|
-
const read = byob ? () => byob.readAtLeast(
|
|
2004
|
+
const read = byob ? (min) => byob.readAtLeast(min, new Uint8Array(UPLOAD_READ)) : () => reader.read();
|
|
2001
2005
|
let total = 0;
|
|
2002
2006
|
let part = [];
|
|
2003
2007
|
let size = 0;
|
|
@@ -2011,13 +2015,22 @@ export class Vm {
|
|
|
2011
2015
|
const bytes = part.length === 1 ? part[0] : join(part, size);
|
|
2012
2016
|
part = [];
|
|
2013
2017
|
size = 0;
|
|
2014
|
-
|
|
2018
|
+
out(chunked ? chunk(bytes) : bytes);
|
|
2015
2019
|
return true;
|
|
2016
2020
|
};
|
|
2021
|
+
// Bytes to the app, after the head when it did not go yet.
|
|
2022
|
+
const out = (bytes) => {
|
|
2023
|
+
clearTimeout(alone);
|
|
2024
|
+
this.bridgeSend(c, head ? join([head, bytes], head.length + bytes.length) : bytes);
|
|
2025
|
+
head = null;
|
|
2026
|
+
};
|
|
2027
|
+
// A client that sends no body yet: the head goes alone after HEAD_WAIT
|
|
2028
|
+
// ms, so the app sees the request (and its own time limits run).
|
|
2029
|
+
const alone = setTimeout(() => { if (head && !c.done && !this.dead) out(new Uint8Array(0)); }, HEAD_WAIT);
|
|
2017
2030
|
try {
|
|
2018
2031
|
for (;;) {
|
|
2019
2032
|
// A read can end the stream with its last bytes (done and a value).
|
|
2020
|
-
const { value, done } = await read();
|
|
2033
|
+
const { value, done } = await read(head ? 1 : UPLOAD_PART);
|
|
2021
2034
|
if (c.done || this.dead) break;
|
|
2022
2035
|
if (value?.length) {
|
|
2023
2036
|
total += value.length;
|
|
@@ -2035,10 +2048,11 @@ export class Vm {
|
|
|
2035
2048
|
size += piece.length;
|
|
2036
2049
|
if (size >= UPLOAD_PART) ok = await flush();
|
|
2037
2050
|
}
|
|
2038
|
-
if (ok && done && size) ok = await flush();
|
|
2051
|
+
if (ok && (done || head) && size) ok = await flush();
|
|
2039
2052
|
if (!ok) break;
|
|
2040
2053
|
if (done) {
|
|
2041
|
-
if (chunked)
|
|
2054
|
+
if (chunked) out(CHUNKS_END);
|
|
2055
|
+
else if (head) out(new Uint8Array(0));
|
|
2042
2056
|
this.bridgeClock(c, c.timeout * 1000);
|
|
2043
2057
|
return;
|
|
2044
2058
|
}
|
|
@@ -2759,7 +2773,10 @@ const LATE = Symbol('late');
|
|
|
2759
2773
|
// read in workerd and of the largest piece of a client chunk. A client chunk can be 2 KB (workerd), and each event
|
|
2760
2774
|
// costs a turn of the VM.
|
|
2761
2775
|
const UPLOAD_WINDOW = 256 * 1024;
|
|
2762
|
-
const UPLOAD_PART =
|
|
2776
|
+
const UPLOAD_PART = 32 * 1024;
|
|
2777
|
+
// The time that the head of a request waits for the first bytes of its
|
|
2778
|
+
// body (bridgeUpload), in ms.
|
|
2779
|
+
const HEAD_WAIT = 20;
|
|
2763
2780
|
const UPLOAD_READ = 64 * 1024;
|
|
2764
2781
|
|
|
2765
2782
|
// The size bytes of the list parts, as one array.
|
package/runtime/release.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version": "0.1.0-rc.
|
|
1
|
+
{"version": "0.1.0-rc.4", "sha256": "686c7f660def2d824d0580717d02736b2add06db7f06becbd3d6ff66cd5d2711"}
|
package/runtime/runtime-id.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// The identity of this runtime (beam_com_wasm:runtime_id/1): the SHA-256 of
|
|
2
2
|
// the output of "sha256sum app-com.js beam.mjs beam.wasm worker.js".
|
|
3
|
-
export default '
|
|
3
|
+
export default '3ef0d2bdd150e2ab64517e29e6e85fbf70382d878b9ccbca998a22f15b566dc0';
|
package/runtime/worker.js
CHANGED
|
@@ -1972,8 +1972,10 @@ export class Vm {
|
|
|
1972
1972
|
// body of the request, and the messages of a WebSocket. sent: the
|
|
1973
1973
|
// host tells wasm_tcp what the client took (tcp_sent).
|
|
1974
1974
|
this.event({ t: 'tcp_accept', id: this.listeners.get(port), conn: id, host: request.headers.get('cf-connecting-ip') ?? '0.0.0.0', port: 0, ack: !!body || upgrade, sent: true });
|
|
1975
|
-
|
|
1976
|
-
|
|
1975
|
+
// With a body, the head goes in the event of the first part of the
|
|
1976
|
+
// body (bridgeUpload): a small body is one event, as before the parts.
|
|
1977
|
+
if (body) this.bridgeUpload(c, body, declared === null, maxBody, bytes);
|
|
1978
|
+
else this.bridgeSend(c, bytes);
|
|
1977
1979
|
});
|
|
1978
1980
|
}
|
|
1979
1981
|
|
|
@@ -1987,8 +1989,10 @@ export class Vm {
|
|
|
1987
1989
|
// (or the rest of the body): one event for each part, not for each small
|
|
1988
1990
|
// chunk of the client. A part goes when less than UPLOAD_WINDOW bytes are
|
|
1989
1991
|
// unread in the VM (tcp_read of wasm_tcp): so a large body does not fill
|
|
1990
|
-
// the memory of the VM, and a slow app slows the client.
|
|
1991
|
-
|
|
1992
|
+
// the memory of the VM, and a slow app slows the client. The head of the
|
|
1993
|
+
// request goes with the bytes of the first read of the client, with no
|
|
1994
|
+
// wait for UPLOAD_PART bytes.
|
|
1995
|
+
async bridgeUpload(c, body, chunked, max, head) {
|
|
1992
1996
|
// workerd has readAtLeast. The option min of the standard BYOB read is
|
|
1993
1997
|
// not safe: when the stream closes with fewer bytes than min, the read
|
|
1994
1998
|
// errors the stream (Node.js 26, Chromium). So the other hosts use the
|
|
@@ -1997,7 +2001,7 @@ export class Vm {
|
|
|
1997
2001
|
try { byob = body.getReader({ mode: 'byob' }); } catch {}
|
|
1998
2002
|
if (byob && !byob.readAtLeast) { byob.releaseLock(); byob = null; }
|
|
1999
2003
|
const reader = byob ?? body.getReader();
|
|
2000
|
-
const read = byob ? () => byob.readAtLeast(
|
|
2004
|
+
const read = byob ? (min) => byob.readAtLeast(min, new Uint8Array(UPLOAD_READ)) : () => reader.read();
|
|
2001
2005
|
let total = 0;
|
|
2002
2006
|
let part = [];
|
|
2003
2007
|
let size = 0;
|
|
@@ -2011,13 +2015,22 @@ export class Vm {
|
|
|
2011
2015
|
const bytes = part.length === 1 ? part[0] : join(part, size);
|
|
2012
2016
|
part = [];
|
|
2013
2017
|
size = 0;
|
|
2014
|
-
|
|
2018
|
+
out(chunked ? chunk(bytes) : bytes);
|
|
2015
2019
|
return true;
|
|
2016
2020
|
};
|
|
2021
|
+
// Bytes to the app, after the head when it did not go yet.
|
|
2022
|
+
const out = (bytes) => {
|
|
2023
|
+
clearTimeout(alone);
|
|
2024
|
+
this.bridgeSend(c, head ? join([head, bytes], head.length + bytes.length) : bytes);
|
|
2025
|
+
head = null;
|
|
2026
|
+
};
|
|
2027
|
+
// A client that sends no body yet: the head goes alone after HEAD_WAIT
|
|
2028
|
+
// ms, so the app sees the request (and its own time limits run).
|
|
2029
|
+
const alone = setTimeout(() => { if (head && !c.done && !this.dead) out(new Uint8Array(0)); }, HEAD_WAIT);
|
|
2017
2030
|
try {
|
|
2018
2031
|
for (;;) {
|
|
2019
2032
|
// A read can end the stream with its last bytes (done and a value).
|
|
2020
|
-
const { value, done } = await read();
|
|
2033
|
+
const { value, done } = await read(head ? 1 : UPLOAD_PART);
|
|
2021
2034
|
if (c.done || this.dead) break;
|
|
2022
2035
|
if (value?.length) {
|
|
2023
2036
|
total += value.length;
|
|
@@ -2035,10 +2048,11 @@ export class Vm {
|
|
|
2035
2048
|
size += piece.length;
|
|
2036
2049
|
if (size >= UPLOAD_PART) ok = await flush();
|
|
2037
2050
|
}
|
|
2038
|
-
if (ok && done && size) ok = await flush();
|
|
2051
|
+
if (ok && (done || head) && size) ok = await flush();
|
|
2039
2052
|
if (!ok) break;
|
|
2040
2053
|
if (done) {
|
|
2041
|
-
if (chunked)
|
|
2054
|
+
if (chunked) out(CHUNKS_END);
|
|
2055
|
+
else if (head) out(new Uint8Array(0));
|
|
2042
2056
|
this.bridgeClock(c, c.timeout * 1000);
|
|
2043
2057
|
return;
|
|
2044
2058
|
}
|
|
@@ -2759,7 +2773,10 @@ const LATE = Symbol('late');
|
|
|
2759
2773
|
// read in workerd and of the largest piece of a client chunk. A client chunk can be 2 KB (workerd), and each event
|
|
2760
2774
|
// costs a turn of the VM.
|
|
2761
2775
|
const UPLOAD_WINDOW = 256 * 1024;
|
|
2762
|
-
const UPLOAD_PART =
|
|
2776
|
+
const UPLOAD_PART = 32 * 1024;
|
|
2777
|
+
// The time that the head of a request waits for the first bytes of its
|
|
2778
|
+
// body (bridgeUpload), in ms.
|
|
2779
|
+
const HEAD_WAIT = 20;
|
|
2763
2780
|
const UPLOAD_READ = 64 * 1024;
|
|
2764
2781
|
|
|
2765
2782
|
// The size bytes of the list parts, as one array.
|