@cloudflare/sandbox 1.0.1 → 1.0.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/README.md +1 -1
- package/dist/index.mjs +64 -11
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -99,7 +99,7 @@ npm run check
|
|
|
99
99
|
npm test
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
[Testing](docs/testing.md) explains what these commands check, how to build behind a TLS-inspecting proxy, and how to test in production. [Releasing](docs/releasing.md) explains how maintainers publish the package and its image.
|
|
102
|
+
[Testing](docs/testing.md) explains what these commands check, how to build behind a TLS-inspecting proxy, and how to test in production. [Releasing](docs/releasing.md) explains how to describe a change for the release notes, and how maintainers publish the package and its image.
|
|
103
103
|
|
|
104
104
|
## License
|
|
105
105
|
|
package/dist/index.mjs
CHANGED
|
@@ -985,11 +985,12 @@ async function readFile(container, path, options) {
|
|
|
985
985
|
stderr: "pipe"
|
|
986
986
|
});
|
|
987
987
|
let control;
|
|
988
|
-
let
|
|
988
|
+
let stdout;
|
|
989
989
|
try {
|
|
990
990
|
control = session.openStderrControl();
|
|
991
|
-
|
|
991
|
+
stdout = new StdoutReader(session.openStdoutReader());
|
|
992
992
|
const opening = await control.readFrame();
|
|
993
|
+
stdout.stopReadingAhead();
|
|
993
994
|
if (opening.kind === "fileError") {
|
|
994
995
|
await control.expectEnd();
|
|
995
996
|
await session.settle();
|
|
@@ -1001,17 +1002,69 @@ async function readFile(container, path, options) {
|
|
|
1001
1002
|
if (opening.kind !== "success") throw protocolError("sandbox-shim returned data before file bytes");
|
|
1002
1003
|
const terminal = readTerminalControl(control);
|
|
1003
1004
|
terminal.catch(() => void 0);
|
|
1004
|
-
return new Response(responseBody(session, control,
|
|
1005
|
+
return new Response(responseBody(session, control, stdout, terminal, path));
|
|
1005
1006
|
} catch (error) {
|
|
1006
|
-
terminateRead(session, control,
|
|
1007
|
+
terminateRead(session, control, stdout, error);
|
|
1007
1008
|
throw error;
|
|
1008
1009
|
}
|
|
1009
1010
|
}
|
|
1010
|
-
|
|
1011
|
+
/**
|
|
1012
|
+
* Reads the shim's stdout, reading ahead until `readFile` has the opening frame from stderr.
|
|
1013
|
+
*
|
|
1014
|
+
* A container transport can carry stdout and stderr over one connection with shared backpressure,
|
|
1015
|
+
* and can deliver file bytes before the opening frame, or between its fragments. The rest of the
|
|
1016
|
+
* frame then arrives only after something reads stdout. The shim writes the whole opening frame
|
|
1017
|
+
* before any file byte, so the read-ahead stops once that frame is complete. After that, the
|
|
1018
|
+
* response body reads stdout on demand, so the caller's pace applies backpressure again.
|
|
1019
|
+
*
|
|
1020
|
+
* The read-ahead has no size limit, because stopping before the frame is complete would bring the
|
|
1021
|
+
* hang back. How much it holds depends on how far the transport lets stdout run ahead of stderr.
|
|
1022
|
+
*/
|
|
1023
|
+
var StdoutReader = class {
|
|
1024
|
+
#reader;
|
|
1025
|
+
#chunks = [];
|
|
1026
|
+
#pending;
|
|
1027
|
+
#readingAhead = true;
|
|
1028
|
+
constructor(reader) {
|
|
1029
|
+
this.#reader = reader;
|
|
1030
|
+
this.#readNext();
|
|
1031
|
+
}
|
|
1032
|
+
/** Stops reading ahead. Chunks already read stay queued for `read()`. */
|
|
1033
|
+
stopReadingAhead() {
|
|
1034
|
+
this.#readingAhead = false;
|
|
1035
|
+
}
|
|
1036
|
+
read() {
|
|
1037
|
+
const chunk = this.#chunks.shift();
|
|
1038
|
+
if (chunk !== void 0) return Promise.resolve({
|
|
1039
|
+
done: false,
|
|
1040
|
+
value: chunk
|
|
1041
|
+
});
|
|
1042
|
+
const pending = this.#pending ?? this.#reader.read();
|
|
1043
|
+
this.#pending = void 0;
|
|
1044
|
+
return pending;
|
|
1045
|
+
}
|
|
1046
|
+
discard(reason) {
|
|
1047
|
+
this.#reader.cancel(reason).then(() => this.#reader.releaseLock(), () => this.#reader.releaseLock());
|
|
1048
|
+
}
|
|
1049
|
+
releaseLock() {
|
|
1050
|
+
this.#reader.releaseLock();
|
|
1051
|
+
}
|
|
1052
|
+
#readNext() {
|
|
1053
|
+
const read = this.#reader.read();
|
|
1054
|
+
this.#pending = read;
|
|
1055
|
+
read.then((result) => {
|
|
1056
|
+
if (this.#pending !== read || result.done) return;
|
|
1057
|
+
this.#pending = void 0;
|
|
1058
|
+
this.#chunks.push(result.value);
|
|
1059
|
+
if (this.#readingAhead) this.#readNext();
|
|
1060
|
+
}, () => void 0);
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
1063
|
+
function responseBody(session, control, stdout, terminalFrame, path) {
|
|
1011
1064
|
return new ReadableStream({
|
|
1012
1065
|
pull: async (controller) => {
|
|
1013
1066
|
try {
|
|
1014
|
-
const next = await session.waitFor(
|
|
1067
|
+
const next = await session.waitFor(stdout.read());
|
|
1015
1068
|
if (!next.done) {
|
|
1016
1069
|
controller.enqueue(next.value);
|
|
1017
1070
|
return;
|
|
@@ -1025,16 +1078,16 @@ function responseBody(session, control, output, terminalFrame, path) {
|
|
|
1025
1078
|
}, terminal.errno, terminal.detail);
|
|
1026
1079
|
}
|
|
1027
1080
|
if (terminal.kind !== "success") throw protocolError("sandbox-shim returned data after file bytes");
|
|
1028
|
-
|
|
1081
|
+
stdout.releaseLock();
|
|
1029
1082
|
control.releaseLock();
|
|
1030
1083
|
session.finish();
|
|
1031
1084
|
controller.close();
|
|
1032
1085
|
} catch (error) {
|
|
1033
|
-
terminateRead(session, control,
|
|
1086
|
+
terminateRead(session, control, stdout, error);
|
|
1034
1087
|
controller.error(error);
|
|
1035
1088
|
}
|
|
1036
1089
|
},
|
|
1037
|
-
cancel: (reason) => terminateRead(session, control,
|
|
1090
|
+
cancel: (reason) => terminateRead(session, control, stdout, reason)
|
|
1038
1091
|
});
|
|
1039
1092
|
}
|
|
1040
1093
|
async function readTerminalControl(control) {
|
|
@@ -1042,10 +1095,10 @@ async function readTerminalControl(control) {
|
|
|
1042
1095
|
await control.expectEnd();
|
|
1043
1096
|
return frame;
|
|
1044
1097
|
}
|
|
1045
|
-
function terminateRead(session, control,
|
|
1098
|
+
function terminateRead(session, control, stdout, reason) {
|
|
1046
1099
|
session.terminate();
|
|
1047
1100
|
control?.discard(reason);
|
|
1048
|
-
|
|
1101
|
+
stdout?.discard(reason);
|
|
1049
1102
|
}
|
|
1050
1103
|
//#endregion
|
|
1051
1104
|
//#region src/files/stat-file.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudflare/sandbox",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Structured workspace file operations for Cloudflare sandboxes",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -23,6 +23,6 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"aws4fetch": "1.0.20",
|
|
26
|
-
"zod": "4.6.
|
|
26
|
+
"zod": "4.6.7"
|
|
27
27
|
}
|
|
28
28
|
}
|