@bytecodealliance/preview2-shim 0.17.8 → 0.17.9

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.
@@ -1,11 +1,11 @@
1
- import { streams, poll } from './io.js';
1
+ import { streams, poll } from "./io.js";
2
2
 
3
3
  const { InputStream, OutputStream } = streams;
4
4
  const { Pollable } = poll;
5
5
 
6
- const symbolDispose = Symbol.dispose || Symbol.for('dispose');
6
+ const symbolDispose = Symbol.dispose || Symbol.for("dispose");
7
7
  const utf8Decoder = new TextDecoder();
8
- const forbiddenHeaders = new Set(['connection', 'keep-alive', 'host']);
8
+ const forbiddenHeaders = new Set(["connection", "keep-alive", "host"]);
9
9
  const DEFAULT_HTTP_TIMEOUT_NS = 600_000_000_000n;
10
10
 
11
11
  // RFC 9110 compliant header validation
@@ -13,133 +13,129 @@ const TOKEN_RE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
13
13
  const FIELD_VALUE_RE = /^[\t\x20-\x7E\x80-\xFF]*$/;
14
14
 
15
15
  function validateHeaderName(name) {
16
- if (!TOKEN_RE.test(name)) {
17
- throw { tag: 'invalid-syntax' };
18
- }
16
+ if (!TOKEN_RE.test(name)) {
17
+ throw { tag: "invalid-syntax" };
18
+ }
19
19
  }
20
20
 
21
21
  function validateHeaderValue(value) {
22
- const str = typeof value === 'string' ? value : utf8Decoder.decode(value);
23
- if (!FIELD_VALUE_RE.test(str)) {
24
- throw { tag: 'invalid-syntax' };
25
- }
22
+ const str = typeof value === "string" ? value : utf8Decoder.decode(value);
23
+ if (!FIELD_VALUE_RE.test(str)) {
24
+ throw { tag: "invalid-syntax" };
25
+ }
26
26
  }
27
27
 
28
28
  class Fields {
29
- #immutable = false;
30
- /** @type {[string, Uint8Array][]} */ #entries = [];
31
- /** @type {Map<string, [string, Uint8Array][]>} */ #table = new Map();
32
-
33
- static fromList(entries) {
34
- const fields = new Fields();
35
- for (const [key, value] of entries) {
36
- fields.append(key, value);
37
- }
38
- return fields;
39
- }
40
-
41
- get(name) {
42
- const tableEntries = this.#table.get(name.toLowerCase());
43
- if (!tableEntries) {
44
- return [];
45
- }
46
- return tableEntries.map(([, v]) => v);
47
- }
48
-
49
- set(name, values) {
50
- if (this.#immutable) {
51
- throw { tag: 'immutable' };
52
- }
53
- validateHeaderName(name);
54
- for (const value of values) {
55
- validateHeaderValue(value);
56
- }
57
- const lowercased = name.toLowerCase();
58
- if (forbiddenHeaders.has(lowercased)) {
59
- throw { tag: 'forbidden' };
60
- }
61
- const tableEntries = this.#table.get(lowercased);
62
- if (tableEntries) {
63
- this.#entries = this.#entries.filter(
64
- (entry) => !tableEntries.includes(entry)
65
- );
66
- tableEntries.splice(0, tableEntries.length);
67
- } else {
68
- this.#table.set(lowercased, []);
69
- }
70
- const newTableEntries = this.#table.get(lowercased);
71
- for (const value of values) {
72
- const entry = [name, value];
73
- this.#entries.push(entry);
74
- newTableEntries.push(entry);
75
- }
76
- }
77
-
78
- has(name) {
79
- return this.#table.has(name.toLowerCase());
80
- }
81
-
82
- delete(name) {
83
- if (this.#immutable) {
84
- throw { tag: 'immutable' };
85
- }
86
- const lowercased = name.toLowerCase();
87
- const tableEntries = this.#table.get(lowercased);
88
- if (tableEntries) {
89
- this.#entries = this.#entries.filter(
90
- (entry) => !tableEntries.includes(entry)
91
- );
92
- this.#table.delete(lowercased);
93
- }
94
- }
95
-
96
- append(name, value) {
97
- if (this.#immutable) {
98
- throw { tag: 'immutable' };
99
- }
100
- validateHeaderName(name);
101
- validateHeaderValue(value);
102
- const lowercased = name.toLowerCase();
103
- if (forbiddenHeaders.has(lowercased)) {
104
- throw { tag: 'forbidden' };
105
- }
106
- const entry = [name, value];
107
- this.#entries.push(entry);
108
- const tableEntries = this.#table.get(lowercased);
109
- if (tableEntries) {
110
- tableEntries.push(entry);
111
- } else {
112
- this.#table.set(lowercased, [entry]);
113
- }
114
- }
115
-
116
- entries() {
117
- return this.#entries;
118
- }
119
-
120
- clone() {
121
- return fieldsFromEntriesChecked(this.#entries);
122
- }
123
-
124
- static _lock(fields) {
125
- fields.#immutable = true;
126
- return fields;
127
- }
128
-
129
- static _fromEntriesChecked(entries) {
130
- const fields = new Fields();
131
- fields.#entries = entries;
132
- for (const entry of entries) {
133
- const lowercase = entry[0].toLowerCase();
134
- const existing = fields.#table.get(lowercase);
135
- if (existing) {
136
- existing.push(entry);
137
- } else {
138
- fields.#table.set(lowercase, [entry]);
139
- }
140
- }
141
- return fields;
142
- }
29
+ #immutable = false;
30
+ /** @type {[string, Uint8Array][]} */ #entries = [];
31
+ /** @type {Map<string, [string, Uint8Array][]>} */ #table = new Map();
32
+
33
+ static fromList(entries) {
34
+ const fields = new Fields();
35
+ for (const [key, value] of entries) {
36
+ fields.append(key, value);
37
+ }
38
+ return fields;
39
+ }
40
+
41
+ get(name) {
42
+ const tableEntries = this.#table.get(name.toLowerCase());
43
+ if (!tableEntries) {
44
+ return [];
45
+ }
46
+ return tableEntries.map(([, v]) => v);
47
+ }
48
+
49
+ set(name, values) {
50
+ if (this.#immutable) {
51
+ throw { tag: "immutable" };
52
+ }
53
+ validateHeaderName(name);
54
+ for (const value of values) {
55
+ validateHeaderValue(value);
56
+ }
57
+ const lowercased = name.toLowerCase();
58
+ if (forbiddenHeaders.has(lowercased)) {
59
+ throw { tag: "forbidden" };
60
+ }
61
+ const tableEntries = this.#table.get(lowercased);
62
+ if (tableEntries) {
63
+ this.#entries = this.#entries.filter((entry) => !tableEntries.includes(entry));
64
+ tableEntries.splice(0, tableEntries.length);
65
+ } else {
66
+ this.#table.set(lowercased, []);
67
+ }
68
+ const newTableEntries = this.#table.get(lowercased);
69
+ for (const value of values) {
70
+ const entry = [name, value];
71
+ this.#entries.push(entry);
72
+ newTableEntries.push(entry);
73
+ }
74
+ }
75
+
76
+ has(name) {
77
+ return this.#table.has(name.toLowerCase());
78
+ }
79
+
80
+ delete(name) {
81
+ if (this.#immutable) {
82
+ throw { tag: "immutable" };
83
+ }
84
+ const lowercased = name.toLowerCase();
85
+ const tableEntries = this.#table.get(lowercased);
86
+ if (tableEntries) {
87
+ this.#entries = this.#entries.filter((entry) => !tableEntries.includes(entry));
88
+ this.#table.delete(lowercased);
89
+ }
90
+ }
91
+
92
+ append(name, value) {
93
+ if (this.#immutable) {
94
+ throw { tag: "immutable" };
95
+ }
96
+ validateHeaderName(name);
97
+ validateHeaderValue(value);
98
+ const lowercased = name.toLowerCase();
99
+ if (forbiddenHeaders.has(lowercased)) {
100
+ throw { tag: "forbidden" };
101
+ }
102
+ const entry = [name, value];
103
+ this.#entries.push(entry);
104
+ const tableEntries = this.#table.get(lowercased);
105
+ if (tableEntries) {
106
+ tableEntries.push(entry);
107
+ } else {
108
+ this.#table.set(lowercased, [entry]);
109
+ }
110
+ }
111
+
112
+ entries() {
113
+ return this.#entries;
114
+ }
115
+
116
+ clone() {
117
+ return fieldsFromEntriesChecked(this.#entries);
118
+ }
119
+
120
+ static _lock(fields) {
121
+ fields.#immutable = true;
122
+ return fields;
123
+ }
124
+
125
+ static _fromEntriesChecked(entries) {
126
+ const fields = new Fields();
127
+ fields.#entries = entries;
128
+ for (const entry of entries) {
129
+ const lowercase = entry[0].toLowerCase();
130
+ const existing = fields.#table.get(lowercase);
131
+ if (existing) {
132
+ existing.push(entry);
133
+ } else {
134
+ fields.#table.set(lowercase, [entry]);
135
+ }
136
+ }
137
+ return fields;
138
+ }
143
139
  }
144
140
  const fieldsLock = Fields._lock;
145
141
  delete Fields._lock;
@@ -147,96 +143,96 @@ const fieldsFromEntriesChecked = Fields._fromEntriesChecked;
147
143
  delete Fields._fromEntriesChecked;
148
144
 
149
145
  class RequestOptions {
150
- #connectTimeout = DEFAULT_HTTP_TIMEOUT_NS;
151
- #firstByteTimeout = DEFAULT_HTTP_TIMEOUT_NS;
152
- #betweenBytesTimeout = DEFAULT_HTTP_TIMEOUT_NS;
153
- connectTimeout() {
154
- return this.#connectTimeout;
155
- }
156
- setConnectTimeout(duration) {
157
- if (duration < 0n) {
158
- throw new Error('duration must not be negative');
159
- }
160
- this.#connectTimeout = duration;
161
- }
162
- firstByteTimeout() {
163
- return this.#firstByteTimeout;
164
- }
165
- setFirstByteTimeout(duration) {
166
- if (duration < 0n) {
167
- throw new Error('duration must not be negative');
168
- }
169
- this.#firstByteTimeout = duration;
170
- }
171
- betweenBytesTimeout() {
172
- return this.#betweenBytesTimeout;
173
- }
174
- setBetweenBytesTimeout(duration) {
175
- if (duration < 0n) {
176
- throw new Error('duration must not be negative');
177
- }
178
- this.#betweenBytesTimeout = duration;
179
- }
146
+ #connectTimeout = DEFAULT_HTTP_TIMEOUT_NS;
147
+ #firstByteTimeout = DEFAULT_HTTP_TIMEOUT_NS;
148
+ #betweenBytesTimeout = DEFAULT_HTTP_TIMEOUT_NS;
149
+ connectTimeout() {
150
+ return this.#connectTimeout;
151
+ }
152
+ setConnectTimeout(duration) {
153
+ if (duration < 0n) {
154
+ throw new Error("duration must not be negative");
155
+ }
156
+ this.#connectTimeout = duration;
157
+ }
158
+ firstByteTimeout() {
159
+ return this.#firstByteTimeout;
160
+ }
161
+ setFirstByteTimeout(duration) {
162
+ if (duration < 0n) {
163
+ throw new Error("duration must not be negative");
164
+ }
165
+ this.#firstByteTimeout = duration;
166
+ }
167
+ betweenBytesTimeout() {
168
+ return this.#betweenBytesTimeout;
169
+ }
170
+ setBetweenBytesTimeout(duration) {
171
+ if (duration < 0n) {
172
+ throw new Error("duration must not be negative");
173
+ }
174
+ this.#betweenBytesTimeout = duration;
175
+ }
180
176
  }
181
177
 
182
178
  class OutgoingBody {
183
- #outputStream = null;
184
- #chunks = [];
185
- #finished = false;
186
-
187
- write() {
188
- const outputStream = this.#outputStream;
189
- if (outputStream === null) {
190
- throw undefined;
191
- }
192
- this.#outputStream = null;
193
- return outputStream;
194
- }
195
-
196
- static finish(body, trailers) {
197
- if (trailers) {
198
- throw { tag: 'internal-error', val: 'trailers unsupported' };
199
- }
200
- if (body.#finished) {
201
- throw { tag: 'internal-error', val: 'body already finished' };
202
- }
203
- body.#finished = true;
204
- }
205
-
206
- static _bodyData(outgoingBody) {
207
- if (outgoingBody.#chunks.length === 0) {
208
- return null;
209
- }
210
- let totalLen = 0;
211
- for (const chunk of outgoingBody.#chunks) {
212
- totalLen += chunk.byteLength;
213
- }
214
- const result = new Uint8Array(totalLen);
215
- let offset = 0;
216
- for (const chunk of outgoingBody.#chunks) {
217
- result.set(chunk, offset);
218
- offset += chunk.byteLength;
219
- }
220
- return result;
221
- }
222
-
223
- static _create() {
224
- const outgoingBody = new OutgoingBody();
225
- const chunks = outgoingBody.#chunks;
226
- outgoingBody.#outputStream = new OutputStream({
227
- write(buf) {
228
- chunks.push(new Uint8Array(buf));
229
- },
230
- flush() {},
231
- blockingFlush() {},
232
- subscribe() {
233
- return new Pollable();
234
- },
235
- });
236
- return outgoingBody;
237
- }
179
+ #outputStream = null;
180
+ #chunks = [];
181
+ #finished = false;
182
+
183
+ write() {
184
+ const outputStream = this.#outputStream;
185
+ if (outputStream === null) {
186
+ throw undefined;
187
+ }
188
+ this.#outputStream = null;
189
+ return outputStream;
190
+ }
191
+
192
+ static finish(body, trailers) {
193
+ if (trailers) {
194
+ throw { tag: "internal-error", val: "trailers unsupported" };
195
+ }
196
+ if (body.#finished) {
197
+ throw { tag: "internal-error", val: "body already finished" };
198
+ }
199
+ body.#finished = true;
200
+ }
201
+
202
+ static _bodyData(outgoingBody) {
203
+ if (outgoingBody.#chunks.length === 0) {
204
+ return null;
205
+ }
206
+ let totalLen = 0;
207
+ for (const chunk of outgoingBody.#chunks) {
208
+ totalLen += chunk.byteLength;
209
+ }
210
+ const result = new Uint8Array(totalLen);
211
+ let offset = 0;
212
+ for (const chunk of outgoingBody.#chunks) {
213
+ result.set(chunk, offset);
214
+ offset += chunk.byteLength;
215
+ }
216
+ return result;
217
+ }
218
+
219
+ static _create() {
220
+ const outgoingBody = new OutgoingBody();
221
+ const chunks = outgoingBody.#chunks;
222
+ outgoingBody.#outputStream = new OutputStream({
223
+ write(buf) {
224
+ chunks.push(new Uint8Array(buf));
225
+ },
226
+ flush() {},
227
+ blockingFlush() {},
228
+ subscribe() {
229
+ return new Pollable();
230
+ },
231
+ });
232
+ return outgoingBody;
233
+ }
238
234
 
239
- [symbolDispose]() {}
235
+ [symbolDispose]() {}
240
236
  }
241
237
  const outgoingBodyCreate = OutgoingBody._create;
242
238
  delete OutgoingBody._create;
@@ -244,449 +240,455 @@ const outgoingBodyData = OutgoingBody._bodyData;
244
240
  delete OutgoingBody._bodyData;
245
241
 
246
242
  class OutgoingRequest {
247
- /** @type {{ tag: string, val?: string }} */ #method = { tag: 'get' };
248
- /** @type {{ tag: string, val?: string } | undefined} */ #scheme = undefined;
249
- /** @type {string | undefined} */ #pathWithQuery = undefined;
250
- /** @type {string | undefined} */ #authority = undefined;
251
- /** @type {Fields} */ #headers;
252
- /** @type {OutgoingBody} */ #body;
253
- #bodyRequested = false;
254
-
255
- constructor(headers) {
256
- fieldsLock(headers);
257
- this.#headers = headers;
258
- this.#body = outgoingBodyCreate();
259
- }
260
-
261
- body() {
262
- if (this.#bodyRequested) {
263
- throw new Error('Body already requested');
264
- }
265
- this.#bodyRequested = true;
266
- return this.#body;
267
- }
243
+ /** @type {{ tag: string, val?: string }} */ #method = { tag: "get" };
244
+ /** @type {{ tag: string, val?: string } | undefined} */ #scheme = undefined;
245
+ /** @type {string | undefined} */ #pathWithQuery = undefined;
246
+ /** @type {string | undefined} */ #authority = undefined;
247
+ /** @type {Fields} */ #headers;
248
+ /** @type {OutgoingBody} */ #body;
249
+ #bodyRequested = false;
268
250
 
269
- method() {
270
- return this.#method;
271
- }
251
+ constructor(headers) {
252
+ fieldsLock(headers);
253
+ this.#headers = headers;
254
+ this.#body = outgoingBodyCreate();
255
+ }
272
256
 
273
- setMethod(method) {
274
- if (method.tag === 'other' && !method.val.match(/^[a-zA-Z-]+$/)) {
275
- throw undefined;
276
- }
277
- this.#method = method;
257
+ body() {
258
+ if (this.#bodyRequested) {
259
+ throw new Error("Body already requested");
278
260
  }
261
+ this.#bodyRequested = true;
262
+ return this.#body;
263
+ }
279
264
 
280
- pathWithQuery() {
281
- return this.#pathWithQuery;
282
- }
265
+ method() {
266
+ return this.#method;
267
+ }
283
268
 
284
- setPathWithQuery(pathWithQuery) {
285
- if (
286
- pathWithQuery &&
287
- !pathWithQuery.match(/^[a-zA-Z0-9.\-_~!$&'()*+,;=:@%?/]+$/)
288
- ) {
289
- throw undefined;
290
- }
291
- this.#pathWithQuery = pathWithQuery;
269
+ setMethod(method) {
270
+ if (method.tag === "other" && !method.val.match(/^[a-zA-Z-]+$/)) {
271
+ throw undefined;
292
272
  }
273
+ this.#method = method;
274
+ }
293
275
 
294
- scheme() {
295
- return this.#scheme;
296
- }
276
+ pathWithQuery() {
277
+ return this.#pathWithQuery;
278
+ }
297
279
 
298
- setScheme(scheme) {
299
- if (scheme?.tag === 'other' && !scheme.val.match(/^[a-zA-Z]+$/)) {
300
- throw undefined;
301
- }
302
- this.#scheme = scheme;
280
+ setPathWithQuery(pathWithQuery) {
281
+ if (pathWithQuery && !pathWithQuery.match(/^[a-zA-Z0-9.\-_~!$&'()*+,;=:@%?/]+$/)) {
282
+ throw undefined;
303
283
  }
284
+ this.#pathWithQuery = pathWithQuery;
285
+ }
304
286
 
305
- authority() {
306
- return this.#authority;
307
- }
287
+ scheme() {
288
+ return this.#scheme;
289
+ }
308
290
 
309
- setAuthority(authority) {
310
- if (authority) {
311
- const [host, port, ...extra] = authority.split(':');
312
- const portNum = Number(port);
313
- if (
314
- extra.length ||
315
- (port !== undefined &&
316
- (portNum.toString() !== port || portNum > 65535)) ||
317
- !host.match(/^[a-zA-Z0-9-.]+$/)
318
- ) {
319
- throw undefined;
320
- }
321
- }
322
- this.#authority = authority;
291
+ setScheme(scheme) {
292
+ if (scheme?.tag === "other" && !scheme.val.match(/^[a-zA-Z]+$/)) {
293
+ throw undefined;
323
294
  }
295
+ this.#scheme = scheme;
296
+ }
297
+
298
+ authority() {
299
+ return this.#authority;
300
+ }
324
301
 
325
- headers() {
326
- return this.#headers;
302
+ setAuthority(authority) {
303
+ if (authority) {
304
+ const [host, port, ...extra] = authority.split(":");
305
+ const portNum = Number(port);
306
+ if (
307
+ extra.length ||
308
+ (port !== undefined && (portNum.toString() !== port || portNum > 65535)) ||
309
+ !host.match(/^[a-zA-Z0-9-.]+$/)
310
+ ) {
311
+ throw undefined;
312
+ }
327
313
  }
314
+ this.#authority = authority;
315
+ }
328
316
 
329
- [symbolDispose]() {}
317
+ headers() {
318
+ return this.#headers;
319
+ }
330
320
 
331
- static _handle(request, options) {
332
- const scheme = schemeString(request.#scheme);
333
- const method = request.#method.val || request.#method.tag;
321
+ [symbolDispose]() {}
334
322
 
335
- if (!request.#pathWithQuery) {
336
- throw { tag: 'HTTP-request-URI-invalid' };
337
- }
323
+ static _handle(request, options) {
324
+ const scheme = schemeString(request.#scheme);
325
+ const method = request.#method.val || request.#method.tag;
338
326
 
339
- const url = `${scheme}//${request.#authority || ''}${request.#pathWithQuery}`;
327
+ if (!request.#pathWithQuery) {
328
+ throw { tag: "HTTP-request-URI-invalid" };
329
+ }
340
330
 
341
- const headers = new Headers();
342
- for (const [key, value] of request.#headers.entries()) {
343
- const lowerKey = key.toLowerCase();
344
- if (!forbiddenHeaders.has(lowerKey)) {
345
- headers.set(key, utf8Decoder.decode(value));
346
- }
347
- }
331
+ const url = `${scheme}//${request.#authority || ""}${request.#pathWithQuery}`;
348
332
 
349
- const bodyData = outgoingBodyData(request.#body);
333
+ const headers = new Headers();
334
+ for (const [key, value] of request.#headers.entries()) {
335
+ const lowerKey = key.toLowerCase();
336
+ if (!forbiddenHeaders.has(lowerKey)) {
337
+ headers.set(key, utf8Decoder.decode(value));
338
+ }
339
+ }
350
340
 
351
- let timeoutMs = Number(DEFAULT_HTTP_TIMEOUT_NS / 1_000_000n);
352
- if (options) {
353
- const ct = options.connectTimeout?.() ?? DEFAULT_HTTP_TIMEOUT_NS;
354
- const fbt = options.firstByteTimeout?.() ?? DEFAULT_HTTP_TIMEOUT_NS;
355
- const minTimeout = ct < fbt ? ct : fbt;
356
- timeoutMs = Number(minTimeout / 1_000_000n);
357
- }
341
+ const bodyData = outgoingBodyData(request.#body);
358
342
 
359
- return futureIncomingResponseCreate(
360
- url, method.toUpperCase(), headers, bodyData, timeoutMs
361
- );
343
+ let timeoutMs = Number(DEFAULT_HTTP_TIMEOUT_NS / 1_000_000n);
344
+ if (options) {
345
+ const ct = options.connectTimeout?.() ?? DEFAULT_HTTP_TIMEOUT_NS;
346
+ const fbt = options.firstByteTimeout?.() ?? DEFAULT_HTTP_TIMEOUT_NS;
347
+ const minTimeout = ct < fbt ? ct : fbt;
348
+ timeoutMs = Number(minTimeout / 1_000_000n);
362
349
  }
350
+
351
+ return futureIncomingResponseCreate(url, method.toUpperCase(), headers, bodyData, timeoutMs);
352
+ }
363
353
  }
364
354
  const outgoingRequestHandle = OutgoingRequest._handle;
365
355
  delete OutgoingRequest._handle;
366
356
 
367
357
  class IncomingBody {
368
- #finished = false;
369
- #stream = undefined;
370
-
371
- stream() {
372
- if (!this.#stream) {
373
- throw undefined;
374
- }
375
- const stream = this.#stream;
376
- this.#stream = null;
377
- return stream;
378
- }
379
-
380
- static finish(incomingBody) {
381
- if (incomingBody.#finished) {
382
- throw new Error('incoming body already finished');
383
- }
384
- incomingBody.#finished = true;
385
- return futureTrailersCreate();
386
- }
387
-
388
- [symbolDispose]() {}
389
-
390
- static _create(fetchResponse) {
391
- const incomingBody = new IncomingBody();
392
- let buffer = null;
393
- let bufferOffset = 0;
394
- let done = false;
395
- let reader = null;
396
- let readPromise = null;
397
-
398
- function ensureReader() {
399
- if (!reader && fetchResponse.body) {
400
- reader = fetchResponse.body.getReader();
358
+ #finished = false;
359
+ #stream = undefined;
360
+
361
+ stream() {
362
+ if (!this.#stream) {
363
+ throw undefined;
364
+ }
365
+ const stream = this.#stream;
366
+ this.#stream = null;
367
+ return stream;
368
+ }
369
+
370
+ static finish(incomingBody) {
371
+ if (incomingBody.#finished) {
372
+ throw new Error("incoming body already finished");
373
+ }
374
+ incomingBody.#finished = true;
375
+ return futureTrailersCreate();
376
+ }
377
+
378
+ [symbolDispose]() {}
379
+
380
+ static _create(fetchResponse) {
381
+ const incomingBody = new IncomingBody();
382
+ let buffer = null;
383
+ let bufferOffset = 0;
384
+ let done = false;
385
+ let reader = null;
386
+ let readPromise = null;
387
+
388
+ function ensureReader() {
389
+ if (!reader && fetchResponse.body) {
390
+ reader = fetchResponse.body.getReader();
391
+ }
392
+ }
393
+
394
+ function startRead() {
395
+ if (readPromise || done) {
396
+ return;
397
+ }
398
+ ensureReader();
399
+ if (!reader) {
400
+ done = true;
401
+ return;
402
+ }
403
+ readPromise = reader.read().then(
404
+ (result) => {
405
+ readPromise = null;
406
+ if (result.done) {
407
+ done = true;
408
+ } else {
409
+ buffer = result.value;
410
+ bufferOffset = 0;
411
+ }
412
+ },
413
+ () => {
414
+ readPromise = null;
415
+ done = true;
416
+ },
417
+ );
418
+ }
419
+
420
+ incomingBody.#stream = new InputStream({
421
+ read(len) {
422
+ if (done && (buffer === null || bufferOffset >= buffer.byteLength)) {
423
+ throw { tag: "closed" };
424
+ }
425
+ if (buffer !== null && bufferOffset < buffer.byteLength) {
426
+ const available = buffer.byteLength - bufferOffset;
427
+ const toRead = Math.min(Number(len), available);
428
+ const slice = buffer.slice(bufferOffset, bufferOffset + toRead);
429
+ bufferOffset += toRead;
430
+ if (bufferOffset >= buffer.byteLength) {
431
+ buffer = null;
432
+ bufferOffset = 0;
433
+ if (!done) {
434
+ startRead();
401
435
  }
402
- }
403
-
404
- function startRead() {
405
- if (readPromise || done) { return; }
406
- ensureReader();
407
- if (!reader) {
408
- done = true;
409
- return;
436
+ }
437
+ return slice;
438
+ }
439
+ throw { tag: "would-block" };
440
+ },
441
+ blockingRead(len) {
442
+ if (done && (buffer === null || bufferOffset >= buffer.byteLength)) {
443
+ throw { tag: "closed" };
444
+ }
445
+ if (buffer !== null && bufferOffset < buffer.byteLength) {
446
+ const available = buffer.byteLength - bufferOffset;
447
+ const toRead = Math.min(Number(len), available);
448
+ const slice = buffer.slice(bufferOffset, bufferOffset + toRead);
449
+ bufferOffset += toRead;
450
+ if (bufferOffset >= buffer.byteLength) {
451
+ buffer = null;
452
+ bufferOffset = 0;
453
+ if (!done) {
454
+ startRead();
410
455
  }
411
- readPromise = reader.read().then(
412
- (result) => {
413
- readPromise = null;
414
- if (result.done) {
415
- done = true;
416
- } else {
417
- buffer = result.value;
418
- bufferOffset = 0;
419
- }
420
- },
421
- () => {
422
- readPromise = null;
423
- done = true;
424
- }
425
- );
456
+ }
457
+ return slice;
426
458
  }
427
-
428
- incomingBody.#stream = new InputStream({
429
- read(len) {
430
- if (done && (buffer === null || bufferOffset >= buffer.byteLength)) {
431
- throw { tag: 'closed' };
432
- }
433
- if (buffer !== null && bufferOffset < buffer.byteLength) {
434
- const available = buffer.byteLength - bufferOffset;
435
- const toRead = Math.min(Number(len), available);
436
- const slice = buffer.slice(bufferOffset, bufferOffset + toRead);
437
- bufferOffset += toRead;
438
- if (bufferOffset >= buffer.byteLength) {
439
- buffer = null;
440
- bufferOffset = 0;
441
- if (!done) { startRead(); }
442
- }
443
- return slice;
444
- }
445
- throw { tag: 'would-block' };
446
- },
447
- blockingRead(len) {
448
- if (done && (buffer === null || bufferOffset >= buffer.byteLength)) {
449
- throw { tag: 'closed' };
450
- }
451
- if (buffer !== null && bufferOffset < buffer.byteLength) {
452
- const available = buffer.byteLength - bufferOffset;
453
- const toRead = Math.min(Number(len), available);
454
- const slice = buffer.slice(bufferOffset, bufferOffset + toRead);
455
- bufferOffset += toRead;
456
- if (bufferOffset >= buffer.byteLength) {
457
- buffer = null;
458
- bufferOffset = 0;
459
- if (!done) { startRead(); }
460
- }
461
- return slice;
462
- }
463
- startRead();
464
- const waitFor = readPromise || Promise.resolve();
465
- return waitFor.then(() => {
466
- if (done && (buffer === null || bufferOffset >= buffer.byteLength)) {
467
- throw { tag: 'closed' };
468
- }
469
- if (buffer !== null && bufferOffset < buffer.byteLength) {
470
- const available = buffer.byteLength - bufferOffset;
471
- const toRead = Math.min(Number(len), available);
472
- const slice = buffer.slice(bufferOffset, bufferOffset + toRead);
473
- bufferOffset += toRead;
474
- if (bufferOffset >= buffer.byteLength) {
475
- buffer = null;
476
- bufferOffset = 0;
477
- if (!done) { startRead(); }
478
- }
479
- return slice;
480
- }
481
- throw { tag: 'closed' };
482
- });
483
- },
484
- subscribe() {
485
- if (done || (buffer !== null && bufferOffset < buffer.byteLength)) {
486
- return new Pollable();
487
- }
459
+ startRead();
460
+ const waitFor = readPromise || Promise.resolve();
461
+ return waitFor.then(() => {
462
+ if (done && (buffer === null || bufferOffset >= buffer.byteLength)) {
463
+ throw { tag: "closed" };
464
+ }
465
+ if (buffer !== null && bufferOffset < buffer.byteLength) {
466
+ const available = buffer.byteLength - bufferOffset;
467
+ const toRead = Math.min(Number(len), available);
468
+ const slice = buffer.slice(bufferOffset, bufferOffset + toRead);
469
+ bufferOffset += toRead;
470
+ if (bufferOffset >= buffer.byteLength) {
471
+ buffer = null;
472
+ bufferOffset = 0;
473
+ if (!done) {
488
474
  startRead();
489
- if (readPromise) {
490
- return new Pollable(readPromise);
491
- }
492
- return new Pollable();
493
- },
475
+ }
476
+ }
477
+ return slice;
478
+ }
479
+ throw { tag: "closed" };
494
480
  });
495
-
481
+ },
482
+ subscribe() {
483
+ if (done || (buffer !== null && bufferOffset < buffer.byteLength)) {
484
+ return new Pollable();
485
+ }
496
486
  startRead();
497
- return incomingBody;
498
- }
487
+ if (readPromise) {
488
+ return new Pollable(readPromise);
489
+ }
490
+ return new Pollable();
491
+ },
492
+ });
493
+
494
+ startRead();
495
+ return incomingBody;
496
+ }
499
497
  }
500
498
  const incomingBodyCreate = IncomingBody._create;
501
499
  delete IncomingBody._create;
502
500
 
503
501
  class IncomingResponse {
504
- /** @type {Fields} */ #headers = undefined;
505
- #status = 0;
506
- /** @type {IncomingBody} */ #body;
507
-
508
- status() {
509
- return this.#status;
510
- }
511
-
512
- headers() {
513
- return this.#headers;
514
- }
515
-
516
- consume() {
517
- if (this.#body === undefined) {
518
- throw undefined;
519
- }
520
- const body = this.#body;
521
- this.#body = undefined;
522
- return body;
523
- }
524
-
525
- [symbolDispose]() {}
526
-
527
- static _create(fetchResponse) {
528
- const res = new IncomingResponse();
529
- res.#status = fetchResponse.status;
530
-
531
- const headerEntries = [];
532
- const encoder = new TextEncoder();
533
- fetchResponse.headers.forEach((value, key) => {
534
- headerEntries.push([key, encoder.encode(value)]);
535
- });
536
- res.#headers = fieldsLock(fieldsFromEntriesChecked(headerEntries));
537
- res.#body = incomingBodyCreate(fetchResponse);
538
- return res;
539
- }
502
+ /** @type {Fields} */ #headers = undefined;
503
+ #status = 0;
504
+ /** @type {IncomingBody} */ #body;
505
+
506
+ status() {
507
+ return this.#status;
508
+ }
509
+
510
+ headers() {
511
+ return this.#headers;
512
+ }
513
+
514
+ consume() {
515
+ if (this.#body === undefined) {
516
+ throw undefined;
517
+ }
518
+ const body = this.#body;
519
+ this.#body = undefined;
520
+ return body;
521
+ }
522
+
523
+ [symbolDispose]() {}
524
+
525
+ static _create(fetchResponse) {
526
+ const res = new IncomingResponse();
527
+ res.#status = fetchResponse.status;
528
+
529
+ const headerEntries = [];
530
+ const encoder = new TextEncoder();
531
+ fetchResponse.headers.forEach((value, key) => {
532
+ headerEntries.push([key, encoder.encode(value)]);
533
+ });
534
+ res.#headers = fieldsLock(fieldsFromEntriesChecked(headerEntries));
535
+ res.#body = incomingBodyCreate(fetchResponse);
536
+ return res;
537
+ }
540
538
  }
541
539
  const incomingResponseCreate = IncomingResponse._create;
542
540
  delete IncomingResponse._create;
543
541
 
544
542
  class FutureTrailers {
545
- #requested = false;
546
- subscribe() {
547
- return new Pollable();
548
- }
549
- get() {
550
- if (this.#requested) {
551
- return { tag: 'err' };
552
- }
553
- this.#requested = true;
554
- return {
555
- tag: 'ok',
556
- val: {
557
- tag: 'ok',
558
- val: undefined,
559
- },
560
- };
561
- }
562
- static _create() {
563
- return new FutureTrailers();
564
- }
543
+ #requested = false;
544
+ subscribe() {
545
+ return new Pollable();
546
+ }
547
+ get() {
548
+ if (this.#requested) {
549
+ return { tag: "err" };
550
+ }
551
+ this.#requested = true;
552
+ return {
553
+ tag: "ok",
554
+ val: {
555
+ tag: "ok",
556
+ val: undefined,
557
+ },
558
+ };
559
+ }
560
+ static _create() {
561
+ return new FutureTrailers();
562
+ }
565
563
  }
566
564
  const futureTrailersCreate = FutureTrailers._create;
567
565
  delete FutureTrailers._create;
568
566
 
569
567
  function mapFetchError(err) {
570
- if (err.name === 'AbortError') {
571
- return { tag: 'connection-timeout' };
572
- }
573
- if (err.name === 'TypeError') {
574
- return { tag: 'connection-refused' };
575
- }
576
- return { tag: 'internal-error', val: err.message };
568
+ if (err.name === "AbortError") {
569
+ return { tag: "connection-timeout" };
570
+ }
571
+ if (err.name === "TypeError") {
572
+ return { tag: "connection-refused" };
573
+ }
574
+ return { tag: "internal-error", val: err.message };
577
575
  }
578
576
 
579
577
  class FutureIncomingResponse {
580
- #result = undefined;
581
- #promise = null;
578
+ #result = undefined;
579
+ #promise = null;
582
580
 
583
- subscribe() {
584
- return new Pollable(this.#promise);
585
- }
581
+ subscribe() {
582
+ return new Pollable(this.#promise);
583
+ }
586
584
 
587
- get() {
588
- if (this.#result === undefined) {
589
- return undefined;
590
- }
591
- const result = this.#result;
592
- this.#result = { tag: 'err' };
593
- return result;
585
+ get() {
586
+ if (this.#result === undefined) {
587
+ return undefined;
594
588
  }
589
+ const result = this.#result;
590
+ this.#result = { tag: "err" };
591
+ return result;
592
+ }
593
+
594
+ [symbolDispose]() {
595
+ this.#promise = null;
596
+ }
595
597
 
596
- [symbolDispose]() {
597
- this.#promise = null;
598
+ static _create(url, method, headers, bodyData, timeoutMs) {
599
+ const future = new FutureIncomingResponse();
600
+
601
+ const controller = new AbortController();
602
+ let timer;
603
+ if (timeoutMs < Infinity) {
604
+ timer = setTimeout(() => controller.abort(), timeoutMs);
598
605
  }
599
606
 
600
- static _create(url, method, headers, bodyData, timeoutMs) {
601
- const future = new FutureIncomingResponse();
607
+ const init = {
608
+ method,
609
+ headers,
610
+ signal: controller.signal,
611
+ };
612
+ if (bodyData && method !== "GET" && method !== "HEAD") {
613
+ init.body = bodyData;
614
+ }
602
615
 
603
- const controller = new AbortController();
604
- let timer;
605
- if (timeoutMs < Infinity) {
606
- timer = setTimeout(() => controller.abort(), timeoutMs);
616
+ future.#promise = fetch(url, init).then(
617
+ (response) => {
618
+ if (timer) {
619
+ clearTimeout(timer);
607
620
  }
608
-
609
- const init = {
610
- method,
611
- headers,
612
- signal: controller.signal,
621
+ future.#result = {
622
+ tag: "ok",
623
+ val: {
624
+ tag: "ok",
625
+ val: incomingResponseCreate(response),
626
+ },
613
627
  };
614
- if (bodyData && method !== 'GET' && method !== 'HEAD') {
615
- init.body = bodyData;
616
- }
617
-
618
- future.#promise = fetch(url, init).then(
619
- (response) => {
620
- if (timer) { clearTimeout(timer); }
621
- future.#result = {
622
- tag: 'ok',
623
- val: {
624
- tag: 'ok',
625
- val: incomingResponseCreate(response),
626
- },
627
- };
628
- },
629
- (err) => {
630
- if (timer) { clearTimeout(timer); }
631
- future.#result = {
632
- tag: 'ok',
633
- val: {
634
- tag: 'err',
635
- val: mapFetchError(err),
636
- },
637
- };
638
- }
639
- );
628
+ },
629
+ (err) => {
630
+ if (timer) {
631
+ clearTimeout(timer);
632
+ }
633
+ future.#result = {
634
+ tag: "ok",
635
+ val: {
636
+ tag: "err",
637
+ val: mapFetchError(err),
638
+ },
639
+ };
640
+ },
641
+ );
640
642
 
641
- return future;
642
- }
643
+ return future;
644
+ }
643
645
  }
644
646
  const futureIncomingResponseCreate = FutureIncomingResponse._create;
645
647
  delete FutureIncomingResponse._create;
646
648
 
647
649
  function schemeString(scheme) {
648
- if (!scheme) {
649
- return 'https:';
650
- }
651
- switch (scheme.tag) {
652
- case 'HTTP':
653
- return 'http:';
654
- case 'HTTPS':
655
- return 'https:';
656
- case 'other':
657
- return scheme.val.toLowerCase() + ':';
658
- }
650
+ if (!scheme) {
651
+ return "https:";
652
+ }
653
+ switch (scheme.tag) {
654
+ case "HTTP":
655
+ return "http:";
656
+ case "HTTPS":
657
+ return "https:";
658
+ case "other":
659
+ return scheme.val.toLowerCase() + ":";
660
+ }
659
661
  }
660
662
 
661
663
  function httpErrorCode(err) {
662
- if (err.payload) {
663
- return err.payload;
664
- }
665
- return {
666
- tag: 'internal-error',
667
- val: err.message,
668
- };
664
+ if (err.payload) {
665
+ return err.payload;
666
+ }
667
+ return {
668
+ tag: "internal-error",
669
+ val: err.message,
670
+ };
669
671
  }
670
672
 
671
673
  export const outgoingHandler = {
672
- handle: outgoingRequestHandle,
674
+ handle: outgoingRequestHandle,
673
675
  };
674
676
 
675
677
  export const incomingHandler = {
676
- handle() {},
678
+ handle() {},
677
679
  };
678
680
 
679
681
  export const types = {
680
- Fields,
681
- FutureIncomingResponse,
682
- FutureTrailers,
683
- IncomingBody,
684
- IncomingRequest: class IncomingRequest {},
685
- IncomingResponse,
686
- OutgoingBody,
687
- OutgoingRequest,
688
- OutgoingResponse: class OutgoingResponse {},
689
- ResponseOutparam: class ResponseOutparam {},
690
- RequestOptions,
691
- httpErrorCode,
682
+ Fields,
683
+ FutureIncomingResponse,
684
+ FutureTrailers,
685
+ IncomingBody,
686
+ IncomingRequest: class IncomingRequest {},
687
+ IncomingResponse,
688
+ OutgoingBody,
689
+ OutgoingRequest,
690
+ OutgoingResponse: class OutgoingResponse {},
691
+ ResponseOutparam: class ResponseOutparam {},
692
+ RequestOptions,
693
+ httpErrorCode,
692
694
  };