@bytecodealliance/preview3-shim 0.1.2 → 0.2.1

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.
Files changed (112) hide show
  1. package/dist/nodejs/cli.d.ts +51 -0
  2. package/dist/nodejs/cli.js +106 -0
  3. package/dist/nodejs/clocks.d.ts +55 -0
  4. package/dist/nodejs/clocks.js +83 -0
  5. package/dist/nodejs/filesystem/descriptor.d.ts +443 -0
  6. package/dist/nodejs/filesystem/descriptor.js +1010 -0
  7. package/dist/nodejs/filesystem/error.d.ts +61 -0
  8. package/dist/nodejs/filesystem/error.js +86 -0
  9. package/dist/nodejs/filesystem/utils.d.ts +8 -0
  10. package/dist/nodejs/filesystem/utils.js +25 -0
  11. package/dist/nodejs/filesystem.js +2 -0
  12. package/dist/nodejs/finalization.d.ts +2 -0
  13. package/{lib → dist}/nodejs/finalization.js +15 -21
  14. package/dist/nodejs/future.d.ts +98 -0
  15. package/dist/nodejs/future.js +176 -0
  16. package/dist/nodejs/http/client.d.ts +22 -0
  17. package/dist/nodejs/http/client.js +138 -0
  18. package/dist/nodejs/http/error.d.ts +18 -0
  19. package/dist/nodejs/http/error.js +62 -0
  20. package/dist/nodejs/http/fields.d.ts +144 -0
  21. package/dist/nodejs/http/fields.js +332 -0
  22. package/dist/nodejs/http/request.d.ts +256 -0
  23. package/dist/nodejs/http/request.js +606 -0
  24. package/dist/nodejs/http/response.d.ts +82 -0
  25. package/dist/nodejs/http/response.js +202 -0
  26. package/dist/nodejs/http/server.d.ts +13 -0
  27. package/dist/nodejs/http/server.js +127 -0
  28. package/dist/nodejs/http.d.ts +19 -0
  29. package/{lib → dist}/nodejs/http.js +13 -18
  30. package/dist/nodejs/index.js +8 -0
  31. package/dist/nodejs/random.d.ts +5 -0
  32. package/{lib → dist}/nodejs/random.js +2 -8
  33. package/dist/nodejs/sockets/address.d.ts +78 -0
  34. package/dist/nodejs/sockets/address.js +120 -0
  35. package/dist/nodejs/sockets/error.d.ts +83 -0
  36. package/dist/nodejs/sockets/error.js +120 -0
  37. package/dist/nodejs/sockets/ip-name-lookup.d.ts +18 -0
  38. package/dist/nodejs/sockets/ip-name-lookup.js +84 -0
  39. package/dist/nodejs/sockets/tcp.d.ts +333 -0
  40. package/dist/nodejs/sockets/tcp.js +723 -0
  41. package/dist/nodejs/sockets/udp.d.ts +224 -0
  42. package/dist/nodejs/sockets/udp.js +475 -0
  43. package/dist/nodejs/sockets.d.ts +11 -0
  44. package/{lib → dist}/nodejs/sockets.js +2 -5
  45. package/dist/nodejs/stream.d.ts +161 -0
  46. package/dist/nodejs/stream.js +388 -0
  47. package/dist/nodejs/workers/cli-worker.d.ts +1 -0
  48. package/dist/nodejs/workers/cli-worker.js +41 -0
  49. package/dist/nodejs/workers/filesystem-worker.d.ts +1 -0
  50. package/dist/nodejs/workers/filesystem-worker.js +109 -0
  51. package/dist/nodejs/workers/http-worker.d.ts +1 -0
  52. package/dist/nodejs/workers/http-worker.js +355 -0
  53. package/dist/nodejs/workers/resource-worker.d.ts +13 -0
  54. package/dist/nodejs/workers/resource-worker.js +152 -0
  55. package/dist/nodejs/workers/tcp-worker.d.ts +2 -0
  56. package/dist/nodejs/workers/tcp-worker.js +318 -0
  57. package/dist/nodejs/workers/udp-worker.d.ts +1 -0
  58. package/dist/nodejs/workers/udp-worker.js +156 -0
  59. package/package.json +20 -12
  60. package/types/interfaces/wasi-cli-environment.d.ts +3 -3
  61. package/types/interfaces/wasi-cli-exit.d.ts +12 -1
  62. package/types/interfaces/wasi-cli-run.d.ts +1 -1
  63. package/types/interfaces/wasi-cli-stderr.d.ts +3 -3
  64. package/types/interfaces/wasi-cli-stdin.d.ts +5 -5
  65. package/types/interfaces/wasi-cli-stdout.d.ts +3 -3
  66. package/types/interfaces/wasi-cli-terminal-input.d.ts +1 -1
  67. package/types/interfaces/wasi-cli-terminal-output.d.ts +1 -1
  68. package/types/interfaces/wasi-cli-terminal-stderr.d.ts +1 -1
  69. package/types/interfaces/wasi-cli-terminal-stdin.d.ts +1 -1
  70. package/types/interfaces/wasi-cli-terminal-stdout.d.ts +1 -1
  71. package/types/interfaces/wasi-cli-types.d.ts +5 -5
  72. package/types/interfaces/wasi-clocks-monotonic-clock.d.ts +3 -3
  73. package/types/interfaces/wasi-clocks-system-clock.d.ts +6 -6
  74. package/types/interfaces/wasi-clocks-types.d.ts +1 -1
  75. package/types/interfaces/wasi-filesystem-preopens.d.ts +1 -1
  76. package/types/interfaces/wasi-filesystem-types.d.ts +74 -74
  77. package/types/interfaces/wasi-http-client.d.ts +1 -1
  78. package/types/interfaces/wasi-http-handler.d.ts +1 -1
  79. package/types/interfaces/wasi-http-types.d.ts +34 -34
  80. package/types/interfaces/wasi-random-insecure-seed.d.ts +5 -5
  81. package/types/interfaces/wasi-random-insecure.d.ts +5 -5
  82. package/types/interfaces/wasi-random-random.d.ts +5 -5
  83. package/types/interfaces/wasi-sockets-ip-name-lookup.d.ts +11 -11
  84. package/types/interfaces/wasi-sockets-types.d.ts +121 -121
  85. package/types/wasi-cli-command.d.ts +23 -23
  86. package/types/wasi-http-service.d.ts +14 -14
  87. package/lib/nodejs/cli.js +0 -127
  88. package/lib/nodejs/clocks.js +0 -98
  89. package/lib/nodejs/filesystem/descriptor.js +0 -1093
  90. package/lib/nodejs/filesystem/error.js +0 -92
  91. package/lib/nodejs/filesystem/utils.js +0 -19
  92. package/lib/nodejs/future.js +0 -190
  93. package/lib/nodejs/http/client.js +0 -161
  94. package/lib/nodejs/http/error.js +0 -71
  95. package/lib/nodejs/http/fields.js +0 -373
  96. package/lib/nodejs/http/request.js +0 -691
  97. package/lib/nodejs/http/response.js +0 -227
  98. package/lib/nodejs/http/server.js +0 -157
  99. package/lib/nodejs/sockets/address.js +0 -146
  100. package/lib/nodejs/sockets/error.js +0 -123
  101. package/lib/nodejs/sockets/ip-name-lookup.js +0 -93
  102. package/lib/nodejs/sockets/tcp.js +0 -801
  103. package/lib/nodejs/sockets/udp.js +0 -516
  104. package/lib/nodejs/stream.js +0 -437
  105. package/lib/nodejs/workers/cli-worker.js +0 -49
  106. package/lib/nodejs/workers/filesystem-worker.js +0 -119
  107. package/lib/nodejs/workers/http-worker.js +0 -417
  108. package/lib/nodejs/workers/resource-worker.js +0 -195
  109. package/lib/nodejs/workers/tcp-worker.js +0 -370
  110. package/lib/nodejs/workers/udp-worker.js +0 -194
  111. /package/{lib/nodejs/filesystem.js → dist/nodejs/filesystem.d.ts} +0 -0
  112. /package/{lib/nodejs/index.js → dist/nodejs/index.d.ts} +0 -0
@@ -1,691 +0,0 @@
1
- import { HttpError } from "./error.js";
2
- import { _fieldsLock, Fields } from "./fields.js";
3
-
4
- import { FutureReader, future } from "../future.js";
5
- import {
6
- DEFAULT_BYTE_STREAM_CHUNK_SIZE,
7
- StreamReader,
8
- _byteChunk,
9
- readableByteStreamFromReader,
10
- } from "../stream.js";
11
-
12
- const symbolDispose = Symbol.dispose || Symbol.for("dispose");
13
-
14
- const SUPPORTED_METHODS = [
15
- "get",
16
- "head",
17
- "post",
18
- "put",
19
- "delete",
20
- "connect",
21
- "options",
22
- "trace",
23
- "patch",
24
- ];
25
-
26
- let REQUEST_CREATE_TOKEN = null;
27
- function token() {
28
- return (REQUEST_CREATE_TOKEN ??= Symbol("RequestCreateToken"));
29
- }
30
-
31
- export class RequestOptions {
32
- #connectTimeoutNs = undefined;
33
- #firstByteTimeoutNs = undefined;
34
- #betweenBytesTimeoutNs = undefined;
35
- #immutable = false;
36
-
37
- /**
38
- * Construct a default ~RequestOptions~ value.
39
- * WIT:
40
- * ```
41
- * constructor()
42
- * ```
43
- */
44
- constructor() {}
45
-
46
- /**
47
- * The timeout for the initial connect to the HTTP Server.
48
- * WIT:
49
- * ```
50
- * connect-timeout: func() -> option<duration>
51
- * ```
52
- *
53
- * @returns {?number} Duration in milliseconds, or `null` if not set
54
- */
55
- getConnectTimeout() {
56
- return this.#connectTimeoutNs;
57
- }
58
-
59
- /**
60
- * Set the timeout for the initial connect to the HTTP Server.
61
- * WIT:
62
- * ```
63
- * set-connect-timeout: func(duration: option<duration>) -> result<_, request-options-error>
64
- * ```
65
- *
66
- * @param {?bigint} duration Duration in nanoseconds, or `null` to clear
67
- * @throws {HttpError} with payload.tag 'immutable' if this handle is immutable
68
- */
69
- setConnectTimeout(duration) {
70
- this._ensureMutable();
71
- this.#connectTimeoutNs = duration ?? undefined;
72
- }
73
-
74
- /**
75
- * The timeout for receiving the first byte of the Response body.
76
- * WIT:
77
- * ```
78
- * first-byte-timeout: func() -> option<duration>
79
- * ```
80
- *
81
- * @returns {?bigint} Duration in nanoseconds, or `null` if not set
82
- */
83
- getFirstByteTimeout() {
84
- return this.#firstByteTimeoutNs;
85
- }
86
-
87
- /**
88
- * Set the timeout for receiving the first byte of the Response body.
89
- * WIT:
90
- * ```
91
- * set-first-byte-timeout: func(duration: option<duration>) -> result<_, request-options-error>
92
- * ```
93
- *
94
- * @param {?bigint} duration Duration in nanoseconds, or `null` to clear
95
- * @throws {HttpError} with payload.tag 'immutable' if this handle is immutable
96
- */
97
- setFirstByteTimeout(duration) {
98
- this._ensureMutable();
99
- this.#firstByteTimeoutNs = duration ?? undefined;
100
- }
101
-
102
- /**
103
- * The timeout for receiving subsequent chunks of bytes in the Response body.
104
- * WIT:
105
- * ```
106
- * between-bytes-timeout: func() -> option<duration>
107
- * ```
108
- *
109
- * @returns {?bigint} Duration in nanoseconds, or `null` if not set
110
- */
111
- getBetweenBytesTimeout() {
112
- return this.#betweenBytesTimeoutNs;
113
- }
114
-
115
- /**
116
- * Set the timeout for receiving subsequent chunks of bytes in the Response body.
117
- * WIT:
118
- * ```
119
- * set-between-bytes-timeout: func(duration: option<duration>) -> result<_, request-options-error>
120
- * ```
121
- *
122
- * @param {?bigint} duration Duration in nanoseconds, or `null` to clear
123
- * @throws {HttpError} with payload.tag 'immutable' if this handle is immutable
124
- */
125
- setBetweenBytesTimeout(duration) {
126
- this._ensureMutable();
127
- this.#betweenBytesTimeoutNs = duration ?? undefined;
128
- }
129
-
130
- /**
131
- * Make a deep copy of the ~RequestOptions~.
132
- * WIT:
133
- * ```
134
- * clone: func() -> request-options
135
- * ```
136
- *
137
- * @returns {RequestOptions} A new mutable copy
138
- */
139
- clone() {
140
- const cloned = new RequestOptions();
141
- cloned.#connectTimeoutNs = this.#connectTimeoutNs;
142
- cloned.#firstByteTimeoutNs = this.#firstByteTimeoutNs;
143
- cloned.#betweenBytesTimeoutNs = this.#betweenBytesTimeoutNs;
144
- return cloned;
145
- }
146
-
147
- /**
148
- * Mark options as immutable
149
- *
150
- * @param {RequestOptions} opts - The RequestOptions instance to mark as immutable
151
- * @returns {RequestOptions} The same instance, now immutable
152
- */
153
- static _lock(fields) {
154
- if (fields) {
155
- fields.#immutable = true;
156
- }
157
- return fields;
158
- }
159
-
160
- _ensureMutable() {
161
- if (this.#immutable) {
162
- throw new HttpError("immutable", "Cannot modify immutable RequestOptions");
163
- }
164
- }
165
- }
166
-
167
- export function _optionsLock(fields) {
168
- return RequestOptions._lock(fields);
169
- }
170
-
171
- export class Request {
172
- #method = { tag: "get" };
173
- #headers = null;
174
- #contents = null;
175
- #options = null;
176
- #scheme = undefined;
177
- #authority = undefined;
178
- #pathWithQuery = undefined;
179
- #trailersFuture = null;
180
- #requestFuture = null;
181
- #contentsDispose = null;
182
- #bodyOpen = false;
183
- #bodyEnded = false;
184
-
185
- constructor(t) {
186
- if (t !== token()) {
187
- throw new Error("Use Request.new(...) to create a Request");
188
- }
189
- }
190
-
191
- /**
192
- * Construct a new Request with default values.
193
- *
194
- * WIT:
195
- * ```
196
- * new: static func(
197
- * headers: headers,
198
- * contents: option<stream<u8>>,
199
- * trailers: future<result<option<trailers>, error-code>>,
200
- * options: option<request-options>
201
- * ) -> tuple<request, future<result<_, error-code>>>;
202
- * ```
203
- *
204
- * @param {Fields} headers immutable headers resource
205
- * @param {?StreamReader|object} contents optional body stream
206
- * @param {FutureReader|Promise} trailers future for trailers
207
- * @param {?RequestOptions} options optional RequestOptions
208
- * @returns {[Request, FutureReader]}
209
- * @throws {HttpError} with payload.tag 'invalid-argument' for invalid arguments
210
- *
211
- */
212
- static new(headers, contents, trailers, options) {
213
- if (options != null && !(options instanceof RequestOptions)) {
214
- throw new HttpError("invalid-argument", "options must be RequestOptions");
215
- }
216
-
217
- if (!(headers instanceof Fields)) {
218
- throw new HttpError("invalid-argument", "headers must be Fields");
219
- }
220
-
221
- if (!(trailers instanceof FutureReader) && (!trailers || typeof trailers.then !== "function")) {
222
- throw new HttpError("invalid-argument", "trailers must be FutureReader or Promise");
223
- }
224
-
225
- let dispose = null;
226
- if (contents != null && !(contents instanceof StreamReader)) {
227
- try {
228
- dispose = contents[symbolDispose]?.bind(contents);
229
- const inner = readableContentsStream(contents, headers);
230
- contents = new StreamReader(inner);
231
- } catch (err) {
232
- throw new HttpError("invalid-argument", err.message);
233
- }
234
- }
235
-
236
- // Generated P3 futures are lazy thenables so we want to observe them now so early error paths don't hang.
237
- if (!(trailers instanceof FutureReader)) {
238
- const promise = Promise.resolve(trailers);
239
- trailers = new FutureReader(promise);
240
- }
241
-
242
- let request = new Request(token());
243
- request.#headers = headers;
244
- request.#contents = contents;
245
- request.#contentsDispose = dispose;
246
- request.#options = options;
247
- request.#trailersFuture = trailers;
248
- request.#pathWithQuery = undefined;
249
- request.#scheme = undefined;
250
- request.#authority = undefined;
251
-
252
- _fieldsLock(request.#headers);
253
- _optionsLock(request.#options);
254
-
255
- const { tx, rx } = future();
256
- request.#requestFuture = tx;
257
-
258
- return [request, rx];
259
- }
260
-
261
- [symbolDispose]() {
262
- if (this.#contents && !this.#bodyOpen && !this.#bodyEnded) {
263
- this.#contentsDispose?.();
264
- this.#contents.close();
265
- }
266
- this.#contents = null;
267
- this.#contentsDispose = null;
268
- this.#bodyOpen = false;
269
- this.#bodyEnded = true;
270
- }
271
-
272
- /**
273
- * Get the Method for the Request.
274
- *
275
- * WIT:
276
- * ```
277
- * method: func() -> method;
278
- * ```
279
- *
280
- * @returns {method}
281
- */
282
- getMethod() {
283
- return this.#method;
284
- }
285
-
286
- /**
287
- * Set the Method for the Request.
288
- *
289
- * WIT:
290
- * ```
291
- * set-method: func(method: method) -> result;
292
- * ```
293
- *
294
- * @param {method} method
295
- * @throws {HttpError} with payload.tag 'invalid-syntax' if method is invalid
296
- */
297
- setMethod(method) {
298
- this.#method = normalizeMethod(method);
299
- }
300
-
301
- /**
302
- * Get the HTTP Path and Query.
303
- *
304
- * WIT:
305
- * ```
306
- * path-with-query: func() -> option<string>;
307
- * ```
308
- *
309
- * @returns {?string}
310
- */
311
- getPathWithQuery() {
312
- return this.#pathWithQuery;
313
- }
314
-
315
- /**
316
- * Set the HTTP Path and Query.
317
- *
318
- * WIT:
319
- * ```
320
- * set-path-with-query: func(path-with-query: option<string>) -> result;
321
- * ```
322
- *
323
- * @param {?string} pathWithQuery
324
- * @throws {HttpError} with payload.tag 'invalid-syntax' if invalid URI component
325
- */
326
- setPathWithQuery(pathWithQuery) {
327
- validateUrlPart(pathWithQuery, UrlPart.PATH_WITH_QUERY);
328
- this.#pathWithQuery = pathWithQuery === "" ? "/" : (pathWithQuery ?? undefined);
329
- }
330
-
331
- /**
332
- * Get the HTTP Scheme.
333
- *
334
- * WIT:
335
- * ```
336
- * scheme: func() -> option<scheme>;
337
- * ```
338
- *
339
- * @returns {?scheme}
340
- */
341
- getScheme() {
342
- return this.#scheme;
343
- }
344
-
345
- /**
346
- * Set the HTTP Scheme.
347
- *
348
- * WIT:
349
- * ```
350
- * set-scheme: func(scheme: option<scheme>) -> result;
351
- * ```
352
- *
353
- * @param {?scheme} scheme
354
- * @throws {HttpError} with payload.tag 'invalid-syntax' if invalid scheme
355
- */
356
- setScheme(scheme) {
357
- this.#scheme = normalizeScheme(scheme);
358
- }
359
-
360
- /**
361
- * Get the authority for the target URI.
362
- *
363
- * WIT:
364
- * ```
365
- * authority: func() -> option<string>;
366
- * ```
367
- *
368
- * @returns {?string}
369
- */
370
- getAuthority() {
371
- return this.#authority;
372
- }
373
-
374
- /**
375
- * Set the authority for the target URI.
376
- *
377
- * WIT:
378
- * ```
379
- * set-authority: func(authority: option<string>) -> result;
380
- * ```
381
- *
382
- * @param {?string} authority
383
- * @throws {HttpError} with payload.tag 'invalid-syntax' if invalid authority
384
- */
385
- setAuthority(authority) {
386
- validateUrlPart(authority, UrlPart.AUTHORITY);
387
- this.#authority = authority ?? undefined;
388
- }
389
-
390
- /**
391
- * Get the associated request-options resource.
392
- *
393
- * WIT:
394
- * ```
395
- * options: func() -> option<request-options>;
396
- * ```
397
- *
398
- * @returns {?RequestOptions}
399
- */
400
- getOptions() {
401
- return this.#options;
402
- }
403
-
404
- /**
405
- * Get the headers resource (immutable).
406
- *
407
- * WIT:
408
- * ```
409
- * headers: func() -> headers;
410
- * ```
411
- *
412
- * @returns {Fields}
413
- */
414
- getHeaders() {
415
- return this.#headers;
416
- }
417
-
418
- /**
419
- * Get body stream and trailers future, consuming the resource.
420
- *
421
- * WIT:
422
- * ```
423
- * consume-body: static func(this: request, res: future<result<_, error-code>>)
424
- * -> tuple<stream<u8>, future<result<option<trailers>, error-code>>>;
425
- * ```
426
- *
427
- * @param {Request} request - The request to consume.
428
- * @param {FutureReader} res - A future for communicating errors.
429
- * @returns {[StreamReader, FutureReader]} A tuple of [body stream, trailers future].
430
- * @throws {HttpError} with payload.tag 'invalid-state' if body already open or consumed.
431
- */
432
- static consumeBody(request, res) {
433
- if (res && typeof res.then === "function") {
434
- // TODO: Use res to abort/close the body transport on errors.
435
- void Promise.resolve(res).catch(() => {});
436
- }
437
-
438
- if (request.#bodyOpen) {
439
- throw new HttpError("invalid-state", "body already called and not yet closed");
440
- }
441
-
442
- if (request.#bodyEnded) {
443
- throw new HttpError("invalid-state", "body has already been consumed");
444
- }
445
-
446
- if (!request.#contents) {
447
- request.#bodyEnded = true;
448
- return [request.#contents, request.#trailersFuture];
449
- }
450
-
451
- const reader = request.#contents;
452
- request.#bodyOpen = true;
453
-
454
- const readFn = reader.read.bind(reader);
455
- reader.read = async (...args) => {
456
- const chunk = await readFn(...args);
457
- if (chunk === null) {
458
- request.#bodyEnded = true;
459
- request.#bodyOpen = false;
460
- }
461
-
462
- return chunk;
463
- };
464
-
465
- const closedFn = reader.close.bind(reader);
466
- reader.close = () => {
467
- closedFn();
468
- request.#bodyEnded = true;
469
- request.#bodyOpen = false;
470
- };
471
-
472
- return [request.#contents, request.#trailersFuture];
473
- }
474
-
475
- // TODO: placeholder
476
- _resolve(result) {
477
- if (this.#requestFuture) {
478
- this.#requestFuture.write(result);
479
- this.#requestFuture = null;
480
- }
481
- }
482
- }
483
-
484
- function readableContentsStream(reader, headers) {
485
- const expectedLength = contentLength(headers.copyAll());
486
- if (expectedLength === null) {
487
- return readableByteStreamFromReader(reader, { name: "contents" });
488
- }
489
-
490
- const source =
491
- typeof reader?.read === "function"
492
- ? reader
493
- : new StreamReader(readableByteStreamFromReader(reader, { name: "contents" }));
494
- return readableByteStreamFromReader(contentLengthReader(source, expectedLength), {
495
- name: "contents",
496
- });
497
- }
498
-
499
- function contentLengthReader(reader, expectedLength) {
500
- let sent = 0n;
501
- return {
502
- async read() {
503
- const result = await reader.read(readOpts(expectedLength - sent));
504
- if (isIteratorResult(result) && result.rejectedLength !== undefined) {
505
- throw requestBodySizeError(sent + BigInt(result.rejectedLength));
506
- }
507
- if (isIteratorResult(result) && result.done) {
508
- if (sent < expectedLength) {
509
- throw requestBodySizeError(sent);
510
- }
511
- return result;
512
- }
513
-
514
- const value = isIteratorResult(result) ? result.value : result;
515
- const chunk = _byteChunk(value);
516
- sent += BigInt(chunk.byteLength);
517
- if (sent > expectedLength) {
518
- throw requestBodySizeError(sent);
519
- }
520
- return { value: chunk, done: false };
521
- },
522
- cancel(reason) {
523
- if (typeof reader.cancel === "function") {
524
- return reader.cancel(reason);
525
- }
526
- if (typeof reader.close === "function") {
527
- return reader.close();
528
- }
529
- return reader[symbolDispose]?.();
530
- },
531
- };
532
- }
533
-
534
- function readOpts(remaining) {
535
- if (remaining <= 0n) {
536
- return { count: 0, rejectLength: 0 };
537
- }
538
-
539
- const count = Number(
540
- remaining <= BigInt(DEFAULT_BYTE_STREAM_CHUNK_SIZE)
541
- ? remaining
542
- : BigInt(DEFAULT_BYTE_STREAM_CHUNK_SIZE),
543
- );
544
- const opts = { count };
545
- if (remaining <= BigInt(Number.MAX_SAFE_INTEGER)) {
546
- opts.rejectLength = Number(remaining);
547
- }
548
- return opts;
549
- }
550
-
551
- function requestBodySizeError(bytes) {
552
- return { tag: "HTTP-request-body-size", val: bytes };
553
- }
554
-
555
- function isIteratorResult(value) {
556
- return value != null && typeof value === "object" && typeof value.done === "boolean";
557
- }
558
-
559
- const decoder = new TextDecoder();
560
-
561
- const contentLength = (entries) => {
562
- const entry = entries.findLast(([name]) => name.toLowerCase() === "content-length");
563
- if (!entry) {
564
- return null;
565
- }
566
-
567
- const value = decoder.decode(entry[1]);
568
- return /^\d+$/.test(value) ? BigInt(value) : null;
569
- };
570
-
571
- const UrlPart = {
572
- PATH_WITH_QUERY: "pathWithQuery",
573
- SCHEME: "scheme",
574
- AUTHORITY: "authority",
575
- };
576
-
577
- function normalizeMethod(method) {
578
- const VALUE_TOKEN_RE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
579
-
580
- if (typeof method === "string") {
581
- if (!VALUE_TOKEN_RE.test(method)) {
582
- throw new HttpError("invalid-syntax");
583
- }
584
-
585
- const lowercase = method.toLowerCase();
586
- return SUPPORTED_METHODS.includes(lowercase)
587
- ? { tag: lowercase }
588
- : { tag: "other", val: lowercase };
589
- }
590
-
591
- if (!method || typeof method !== "object" || typeof method.tag !== "string") {
592
- throw new HttpError("invalid-syntax");
593
- }
594
-
595
- if (SUPPORTED_METHODS.includes(method.tag)) {
596
- return { tag: method.tag };
597
- }
598
-
599
- if (method.tag === "other" && typeof method.val === "string" && VALUE_TOKEN_RE.test(method.val)) {
600
- const standard = method.val.toLowerCase();
601
- return SUPPORTED_METHODS.includes(standard) && method.val === method.val.toUpperCase()
602
- ? { tag: standard }
603
- : { tag: "other", val: method.val };
604
- }
605
-
606
- throw new HttpError("invalid-syntax");
607
- }
608
-
609
- function normalizeScheme(scheme) {
610
- if (scheme == null) {
611
- return undefined;
612
- }
613
-
614
- if (typeof scheme === "string") {
615
- validateUrlPart(scheme, UrlPart.SCHEME);
616
- const uppercase = scheme.toUpperCase();
617
- if (uppercase === "HTTP" || uppercase === "HTTPS") {
618
- return { tag: uppercase };
619
- }
620
- return { tag: "other", val: scheme };
621
- }
622
-
623
- if (typeof scheme !== "object" || typeof scheme.tag !== "string") {
624
- throw new HttpError("invalid-syntax");
625
- }
626
-
627
- if (scheme.tag === "HTTP" || scheme.tag === "HTTPS") {
628
- return { tag: scheme.tag };
629
- }
630
-
631
- if (scheme.tag === "other" && typeof scheme.val === "string") {
632
- validateUrlPart(scheme.val, UrlPart.SCHEME);
633
- const uppercase = scheme.val.toUpperCase();
634
- if (uppercase === "HTTP" || uppercase === "HTTPS") {
635
- return { tag: uppercase };
636
- }
637
- return { tag: "other", val: scheme.val };
638
- }
639
-
640
- throw new HttpError("invalid-syntax");
641
- }
642
-
643
- export function _schemeToString(scheme) {
644
- if (scheme === undefined) {
645
- return undefined;
646
- }
647
-
648
- switch (scheme.tag) {
649
- case "HTTP":
650
- return "http";
651
- case "HTTPS":
652
- return "https";
653
- case "other":
654
- return scheme.val;
655
- default:
656
- throw new HttpError("invalid-syntax", `Invalid scheme: ${scheme.tag}`);
657
- }
658
- }
659
-
660
- function validateUrlPart(value, part) {
661
- if (value == null) {
662
- return;
663
- }
664
-
665
- // URL parsing may normalize some raw control characters but wasi treats them as invalid syntax.
666
- if (/[\u0000-\u001f\u007f]/.test(value)) {
667
- throw new HttpError("invalid-syntax", `Invalid ${part}: ${value}`);
668
- }
669
-
670
- if (part === UrlPart.PATH_WITH_QUERY && /[ <>`]/.test(value)) {
671
- throw new HttpError("invalid-syntax", `Invalid ${part}: ${value}`);
672
- }
673
-
674
- try {
675
- switch (part) {
676
- case UrlPart.PATH_WITH_QUERY:
677
- new URL(value, "http://example");
678
- break;
679
- case UrlPart.SCHEME:
680
- new URL(`${value}://example`);
681
- break;
682
- case UrlPart.AUTHORITY:
683
- new URL(`http://${value}`);
684
- break;
685
- default:
686
- throw new Error(`Unknown URL part: ${part}`);
687
- }
688
- } catch {
689
- throw new HttpError("invalid-syntax", `Invalid ${part}: ${value}`);
690
- }
691
- }