@sproutboat/toolchain 0.9.0 → 0.10.0
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/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/src/fetch-classes.ts +25 -6
- package/src/fingerprint.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @sproutboat/toolchain
|
|
2
2
|
|
|
3
|
+
## 0.10.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 4274bef: `Response.body` and `Request.body` are `ReadableStream`s for every body type, as in the Fetch spec and workerd. Before, they held the value given (a string, bytes or a `Blob`). `res.body.getReader()`, `res.body.pipeThrough(...)` and `new Response(other.body)` now work on any response, including the incoming request. The value as given stays internal, so responses are still written with a fixed length unless the body really is a stream. A body whose stream has been locked can no longer be read with `text()` and the other readers, which throw a `TypeError`.
|
|
8
|
+
|
|
3
9
|
## 0.9.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
package/package.json
CHANGED
package/src/fetch-classes.ts
CHANGED
|
@@ -65,7 +65,22 @@ export const REQUEST_CLASS_SOURCE = String.raw`class Request {
|
|
|
65
65
|
static _consume(message) {
|
|
66
66
|
if (message._bodyUsed === true) throw new TypeError('Body has already been used');
|
|
67
67
|
message._bodyUsed = true;
|
|
68
|
-
|
|
68
|
+
// A stream the body getter handed out is what the reader reads: a locked one throws.
|
|
69
|
+
return message._bodyStream != null ? message._bodyStream : message._bodyInit;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// body is a ReadableStream, as in Fetch: a stream body itself, else a stream made once over
|
|
73
|
+
// the bytes. The value as given stays in _bodyInit, which the native writer, streaming and
|
|
74
|
+
// the prelude read; assigning body (the native ingress does) sets it.
|
|
75
|
+
static _bodyAsStream(message) {
|
|
76
|
+
const init = message._bodyInit;
|
|
77
|
+
if (init == null) return null;
|
|
78
|
+
if (Request._isStream(init)) return init;
|
|
79
|
+
if (message._bodyStream == null) {
|
|
80
|
+
const bytes = Request._bodyBytes(init);
|
|
81
|
+
message._bodyStream = new globalThis.ReadableStream({ start(c) { if (bytes.length) c.enqueue(bytes); c.close(); } });
|
|
82
|
+
}
|
|
83
|
+
return message._bodyStream;
|
|
69
84
|
}
|
|
70
85
|
|
|
71
86
|
static _bodyText(body) {
|
|
@@ -119,7 +134,7 @@ export const REQUEST_CLASS_SOURCE = String.raw`class Request {
|
|
|
119
134
|
url = input.url;
|
|
120
135
|
method = input.method;
|
|
121
136
|
headers = input.headers;
|
|
122
|
-
body = input.
|
|
137
|
+
body = input._bodyStream != null ? input._bodyStream : input._bodyInit;
|
|
123
138
|
redirect = input.redirect;
|
|
124
139
|
} else if (input != null && Porffor.type(input) == Porffor.TYPES.object && input.href != null) url = input.href;
|
|
125
140
|
|
|
@@ -142,11 +157,13 @@ export const REQUEST_CLASS_SOURCE = String.raw`class Request {
|
|
|
142
157
|
if (init != null && init.body != null && init.body !== '' && (this.method == 'GET' || this.method == 'HEAD'))
|
|
143
158
|
throw new TypeError('Request with GET/HEAD method cannot have body.');
|
|
144
159
|
this.headers = new Headers(headers);
|
|
145
|
-
this.
|
|
160
|
+
this._bodyInit = Request._extractBody(body, this.headers);
|
|
146
161
|
if (redirect != null) this._redirect = String(redirect);
|
|
147
162
|
}
|
|
148
163
|
|
|
149
164
|
get redirect() { return this._redirect ?? 'follow'; }
|
|
165
|
+
get body() { return Request._bodyAsStream(this); }
|
|
166
|
+
set body(value) { this._bodyInit = value; this._bodyStream = null; }
|
|
150
167
|
get bodyUsed() { return this._bodyUsed === true; }
|
|
151
168
|
|
|
152
169
|
arrayBuffer() { return Request._read(this, (bytes) => bytes.buffer); }
|
|
@@ -179,7 +196,7 @@ export const RESPONSE_CLASS_SOURCE = String.raw`class Response {
|
|
|
179
196
|
throw new TypeError('Response with null body status cannot have body');
|
|
180
197
|
if (init?.statusText != null) this._statusText = String(init.statusText);
|
|
181
198
|
this.headers = new Headers(init?.headers);
|
|
182
|
-
this.
|
|
199
|
+
this._bodyInit = Request._extractBody(body, this.headers);
|
|
183
200
|
}
|
|
184
201
|
|
|
185
202
|
static error() {
|
|
@@ -192,6 +209,8 @@ export const RESPONSE_CLASS_SOURCE = String.raw`class Response {
|
|
|
192
209
|
get statusText() { return this._statusText ?? ''; }
|
|
193
210
|
get type() { return this._type ?? 'default'; }
|
|
194
211
|
get ok() { return this.status >= 200 && this.status < 300; }
|
|
212
|
+
get body() { return Request._bodyAsStream(this); }
|
|
213
|
+
set body(value) { this._bodyInit = value; this._bodyStream = null; }
|
|
195
214
|
get bodyUsed() { return this._bodyUsed === true; }
|
|
196
215
|
|
|
197
216
|
arrayBuffer() { return Request._read(this, (bytes) => bytes.buffer); }
|
|
@@ -199,7 +218,7 @@ export const RESPONSE_CLASS_SOURCE = String.raw`class Response {
|
|
|
199
218
|
clone() {
|
|
200
219
|
if (this._bodyUsed === true) throw new TypeError('Body has already been used');
|
|
201
220
|
const copy = new Response(null, { status: this.status == 0 ? 200 : this.status, statusText: this._statusText, headers: this.headers });
|
|
202
|
-
copy.
|
|
221
|
+
copy._bodyInit = this._bodyInit;
|
|
203
222
|
copy.status = this.status;
|
|
204
223
|
if (this._type != null) copy._type = this._type;
|
|
205
224
|
return copy;
|
|
@@ -223,7 +242,7 @@ export const RESPONSE_BYTES_ANCHOR =
|
|
|
223
242
|
export const RESPONSE_BYTES_INJECT =
|
|
224
243
|
" // sproutboat: byte bodies go out as their bytes. A Latin-1 string, one character per byte,\n" +
|
|
225
244
|
" // built in windows (concatenating one long string is quadratic), sent raw by the writer.\n" +
|
|
226
|
-
" let body = response.body;\n" +
|
|
245
|
+
" let body = response._bodyInit !== undefined ? response._bodyInit : response.body;\n" +
|
|
227
246
|
" let headersEntries = response.headers._entries;\n" +
|
|
228
247
|
" if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n" +
|
|
229
248
|
" const view = body instanceof ArrayBuffer ? new Uint8Array(body) : new Uint8Array(body.buffer, body.byteOffset, body.byteLength);\n" +
|
package/src/fingerprint.ts
CHANGED
|
@@ -21,7 +21,7 @@ export const PATCH_SOURCES = [
|
|
|
21
21
|
* patch.ts as the module patch.ts is everywhere else. Kept current by fingerprint.test.ts
|
|
22
22
|
* (UPDATE_FINGERPRINT=1 bun test packages/toolchain/src/fingerprint.test.ts).
|
|
23
23
|
*/
|
|
24
|
-
export const RELEASED_FINGERPRINT = "
|
|
24
|
+
export const RELEASED_FINGERPRINT = "405c8f04fb7d";
|
|
25
25
|
|
|
26
26
|
/** The fingerprint of the sources in dir, or null where they are not on disk. */
|
|
27
27
|
export function sourceFingerprint(dir: string): string | null {
|