@ricsam/isolate-fetch 0.1.23 → 0.1.24

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.
@@ -187,6 +187,21 @@ async function createConsistencyTestContext() {
187
187
  }
188
188
  }
189
189
  });
190
+ await runtime.eval(`
191
+ globalThis.__consistencyPendingTasks = new Set();
192
+ globalThis.__consistencyCleanupFns = [];
193
+ globalThis.__consistencyTrackTask = function(task) {
194
+ globalThis.__consistencyPendingTasks.add(task);
195
+ task.finally(() => {
196
+ globalThis.__consistencyPendingTasks.delete(task);
197
+ });
198
+ return task;
199
+ };
200
+ globalThis.__consistencyRegisterCleanup = function(cleanup) {
201
+ globalThis.__consistencyCleanupFns.push(cleanup);
202
+ return cleanup;
203
+ };
204
+ `);
190
205
  return {
191
206
  runtime,
192
207
  eval: runtime.eval.bind(runtime),
@@ -201,6 +216,27 @@ async function createConsistencyTestContext() {
201
216
  storedResult = undefined;
202
217
  },
203
218
  async dispose() {
219
+ try {
220
+ await runtime.eval(`
221
+ const cleanupFns = globalThis.__consistencyCleanupFns ?? [];
222
+ while (cleanupFns.length > 0) {
223
+ const cleanup = cleanupFns.pop();
224
+ if (!cleanup) continue;
225
+ try {
226
+ await cleanup();
227
+ } catch {
228
+ // Ignore cleanup races during test teardown.
229
+ }
230
+ }
231
+
232
+ const pendingTasks = globalThis.__consistencyPendingTasks
233
+ ? Array.from(globalThis.__consistencyPendingTasks)
234
+ : [];
235
+ if (pendingTasks.length > 0) {
236
+ await Promise.allSettled(pendingTasks);
237
+ }
238
+ `);
239
+ } catch {}
204
240
  await runtime.dispose();
205
241
  }
206
242
  };
@@ -401,15 +437,32 @@ async function getReadableStreamFromOrigin(ctx, origin, chunks = ["chunk1", "chu
401
437
  await ctx.eval(`
402
438
  const transform = new TransformStream();
403
439
  globalThis.__testReadableStream = transform.readable;
404
- // Write chunks to writable side and close it
405
440
  const writer = transform.writable.getWriter();
441
+ __consistencyRegisterCleanup(async () => {
442
+ try {
443
+ await writer.abort();
444
+ } catch {
445
+ // Ignore duplicate cleanup races.
446
+ }
447
+ try {
448
+ writer.releaseLock();
449
+ } catch {
450
+ // Ignore release races during teardown.
451
+ }
452
+ });
406
453
  const chunks = ${chunksJson};
407
- (async () => {
454
+ __consistencyTrackTask((async () => {
408
455
  for (const chunk of chunks) {
409
456
  await writer.write(new TextEncoder().encode(chunk));
410
457
  }
411
458
  await writer.close();
412
- })();
459
+ })().finally(() => {
460
+ try {
461
+ writer.releaseLock();
462
+ } catch {
463
+ // Ignore release races after the task settles.
464
+ }
465
+ }));
413
466
  `);
414
467
  break;
415
468
  }
@@ -436,14 +489,31 @@ async function getWritableStreamFromOrigin(ctx, origin) {
436
489
  }
437
490
  });
438
491
  globalThis.__testWritableStream = transform.writable;
439
- // Start reading to allow writes to complete
440
492
  const reader = transform.readable.getReader();
441
- (async () => {
493
+ __consistencyRegisterCleanup(async () => {
494
+ try {
495
+ await reader.cancel();
496
+ } catch {
497
+ // Ignore duplicate cleanup races.
498
+ }
499
+ try {
500
+ reader.releaseLock();
501
+ } catch {
502
+ // Ignore release races during teardown.
503
+ }
504
+ });
505
+ __consistencyTrackTask((async () => {
442
506
  while (true) {
443
507
  const { done } = await reader.read();
444
508
  if (done) break;
445
509
  }
446
- })();
510
+ })().finally(() => {
511
+ try {
512
+ reader.releaseLock();
513
+ } catch {
514
+ // Ignore release races after the task settles.
515
+ }
516
+ }));
447
517
  `);
448
518
  break;
449
519
  }
@@ -525,4 +595,4 @@ async function getAbortSignalFromOrigin(ctx, _origin) {
525
595
  `);
526
596
  }
527
597
 
528
- //# debugId=274AB1900A4AAC4364756E2164756E21
598
+ //# debugId=5F9068869222631564756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../src/consistency/origins.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * Helper functions for creating web objects from different origins.\n * Used to test that objects behave identically regardless of how they were created.\n *\n * Note: The `customFunction` origin is tested where supported. For Response and Request,\n * this requires constructing the object in the isolate using parameters passed from\n * a host custom function, since native objects cannot be serialized across the boundary.\n */\n\nimport { createRuntime, type RuntimeHandle } from \"@ricsam/isolate-runtime\";\nimport { clearAllInstanceState } from \"@ricsam/isolate-core\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ResponseOrigin =\n | \"direct\"\n | \"customFunction\"\n | \"fetchCallback\";\n\nexport type RequestOrigin =\n | \"direct\"\n | \"customFunction\"\n | \"serveRequest\";\n\nexport type HeadersOrigin = \"direct\" | \"fromResponse\" | \"fromRequest\";\n\n// Blob and File don't have special marshalling support for custom functions\nexport type BlobOrigin = \"direct\";\n\nexport type FileOrigin = \"direct\";\n\n// URL has special marshalling via URLRef (only href stored)\nexport type URLOrigin = \"direct\" | \"customFunction\";\n\n// URLSearchParams can come from direct construction or from URL.searchParams\nexport type URLSearchParamsOrigin = \"direct\" | \"fromURL\" | \"fromCustomFunctionURL\";\n\n// FormData doesn't have special marshalling support for custom functions\nexport type FormDataOrigin = \"direct\" | \"fromResponse\";\n\n// Stream origins\nexport type ReadableStreamOrigin =\n | \"direct\" // new ReadableStream() in isolate\n | \"responseBody\" // response.body from fetch callback\n | \"blobStream\" // blob.stream()\n | \"transformReadable\"; // transformStream.readable\n\nexport type WritableStreamOrigin =\n | \"direct\" // new WritableStream() in isolate\n | \"transformWritable\"; // transformStream.writable\n\nexport type TransformStreamOrigin = \"direct\";\nexport type TextEncoderStreamOrigin = \"direct\";\nexport type TextDecoderStreamOrigin = \"direct\";\nexport type QueuingStrategyOrigin = \"direct\";\n\nexport const RESPONSE_ORIGINS: ResponseOrigin[] = [\n \"direct\",\n \"customFunction\",\n \"fetchCallback\",\n];\n\nexport const REQUEST_ORIGINS: RequestOrigin[] = [\n \"direct\",\n \"customFunction\",\n \"serveRequest\",\n];\n\nexport const HEADERS_ORIGINS: HeadersOrigin[] = [\n \"direct\",\n \"fromResponse\",\n \"fromRequest\",\n];\n\nexport const BLOB_ORIGINS: BlobOrigin[] = [\"direct\"];\n\nexport const FILE_ORIGINS: FileOrigin[] = [\"direct\"];\n\nexport const URL_ORIGINS: URLOrigin[] = [\"direct\", \"customFunction\"];\n\nexport const URLSEARCHPARAMS_ORIGINS: URLSearchParamsOrigin[] = [\n \"direct\",\n \"fromURL\",\n \"fromCustomFunctionURL\",\n];\n\nexport const FORMDATA_ORIGINS: FormDataOrigin[] = [\n \"direct\",\n \"fromResponse\",\n];\n\nexport const READABLE_STREAM_ORIGINS: ReadableStreamOrigin[] = [\n \"direct\",\n \"responseBody\",\n \"blobStream\",\n \"transformReadable\",\n];\n\nexport const WRITABLE_STREAM_ORIGINS: WritableStreamOrigin[] = [\n \"direct\",\n \"transformWritable\",\n];\n\nexport const TRANSFORM_STREAM_ORIGINS: TransformStreamOrigin[] = [\"direct\"];\nexport const TEXT_ENCODER_STREAM_ORIGINS: TextEncoderStreamOrigin[] = [\"direct\"];\nexport const TEXT_DECODER_STREAM_ORIGINS: TextDecoderStreamOrigin[] = [\"direct\"];\nexport const QUEUING_STRATEGY_ORIGINS: QueuingStrategyOrigin[] = [\"direct\"];\n\n// AbortController/AbortSignal have NO marshalling support (no AbortRef type in codec)\n// They cannot be passed through custom functions - only direct instantiation in isolate\nexport type AbortControllerOrigin = \"direct\";\nexport type AbortSignalOrigin = \"direct\";\n\nexport const ABORT_CONTROLLER_ORIGINS: AbortControllerOrigin[] = [\"direct\"];\nexport const ABORT_SIGNAL_ORIGINS: AbortSignalOrigin[] = [\"direct\"];\n\n// ============================================================================\n// Test Context\n// ============================================================================\n\nexport interface ConsistencyTestContext {\n /** The runtime handle */\n runtime: RuntimeHandle;\n /** Execute code in the runtime */\n eval(code: string): Promise<void>;\n /** Dispatch an HTTP request to the serve() handler */\n dispatchRequest(request: Request): Promise<Response>;\n /** Set the mock response for the next fetch call */\n setMockResponse(response: MockResponse): void;\n /** Get a result from the isolate via setResult() */\n getResult<T = unknown>(): T | undefined;\n /** Clear the stored result */\n clearResult(): void;\n /** Dispose all resources */\n dispose(): Promise<void>;\n}\n\nexport interface MockResponse {\n status?: number;\n statusText?: string;\n body?: string;\n headers?: Record<string, string>;\n}\n\n/**\n * Create a test context for consistency tests.\n * Provides helpers for creating objects from different origins.\n */\nexport async function createConsistencyTestContext(): Promise<ConsistencyTestContext> {\n // Clear any previous instance state\n clearAllInstanceState();\n\n let mockResponse: MockResponse = { status: 200, body: \"\" };\n let storedResult: unknown = undefined;\n\n // Pending parameters for custom function origins\n // These are stored on the host and retrieved by the isolate to construct objects\n let pendingResponseParams: { body: string; init: ResponseInit } | null = null;\n let pendingRequestParams: { url: string; init: RequestInit } | null = null;\n let pendingURL: URL | null = null;\n\n const runtime = await createRuntime({\n fetch: async () => {\n // Return mock response\n return new Response(mockResponse.body ?? \"\", {\n status: mockResponse.status ?? 200,\n statusText: mockResponse.statusText ?? \"\",\n headers: mockResponse.headers,\n });\n },\n customFunctions: {\n setResult: {\n fn: (value: unknown) => {\n storedResult = value;\n },\n type: \"sync\",\n },\n // For Response customFunction origin: store params, return them for isolate to construct\n __setResponseParams: {\n fn: (body: string, init: ResponseInit) => {\n pendingResponseParams = { body, init };\n },\n type: \"sync\",\n },\n __getResponseParams: {\n fn: () => {\n const params = pendingResponseParams;\n pendingResponseParams = null;\n return params;\n },\n type: \"sync\",\n },\n // For Request customFunction origin: store params, return them for isolate to construct\n __setRequestParams: {\n fn: (url: string, init: RequestInit) => {\n pendingRequestParams = { url, init };\n },\n type: \"sync\",\n },\n __getRequestParams: {\n fn: () => {\n const params = pendingRequestParams;\n pendingRequestParams = null;\n return params;\n },\n type: \"sync\",\n },\n // For URL customFunction origin: URL goes through marshal/unmarshal (URLRef)\n __setURL: {\n fn: (url: URL) => {\n pendingURL = url;\n },\n type: \"sync\",\n },\n __getURL: {\n fn: () => {\n const url = pendingURL;\n pendingURL = null;\n return url;\n },\n type: \"sync\",\n },\n },\n });\n\n return {\n runtime,\n eval: runtime.eval.bind(runtime),\n dispatchRequest: runtime.fetch.dispatchRequest.bind(runtime.fetch),\n setMockResponse(response: MockResponse) {\n mockResponse = response;\n },\n getResult<T = unknown>(): T | undefined {\n return storedResult as T | undefined;\n },\n clearResult() {\n storedResult = undefined;\n },\n async dispose() {\n await runtime.dispose();\n },\n };\n}\n\n// ============================================================================\n// Response Helpers\n// ============================================================================\n\nexport interface ResponseOptions {\n status?: number;\n statusText?: string;\n headers?: Record<string, string>;\n}\n\n/**\n * Create a Response in the isolate from the specified origin.\n * The Response is stored at globalThis.__testResponse.\n */\nexport async function getResponseFromOrigin(\n ctx: ConsistencyTestContext,\n origin: ResponseOrigin,\n body: string,\n options?: ResponseOptions\n): Promise<void> {\n const init = {\n status: options?.status ?? 200,\n statusText: options?.statusText ?? \"\",\n headers: options?.headers ?? {},\n };\n const initJson = JSON.stringify(init);\n\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testResponse = new Response(${JSON.stringify(body)}, ${initJson});\n `);\n break;\n\n case \"customFunction\":\n // Store params on host, then retrieve and construct in isolate\n // This simulates getting data from a custom function and constructing a Response\n await ctx.eval(`\n __setResponseParams(${JSON.stringify(body)}, ${initJson});\n const params = __getResponseParams();\n globalThis.__testResponse = new Response(params.body, params.init);\n `);\n break;\n\n case \"fetchCallback\":\n ctx.setMockResponse({\n status: init.status,\n statusText: init.statusText,\n body,\n headers: init.headers,\n });\n await ctx.eval(`\n globalThis.__testResponse = await fetch(\"https://example.com/test\");\n `);\n break;\n }\n}\n\n// ============================================================================\n// Request Helpers\n// ============================================================================\n\nexport interface RequestOptions {\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n}\n\n/**\n * Create a Request in the isolate from the specified origin.\n * The Request is stored at globalThis.__testRequest.\n */\nexport async function getRequestFromOrigin(\n ctx: ConsistencyTestContext,\n origin: RequestOrigin,\n url: string,\n options?: RequestOptions\n): Promise<void> {\n const init: RequestInit = {\n method: options?.method ?? \"GET\",\n headers: options?.headers ?? {},\n };\n\n // Only add body for non-GET/HEAD requests\n if (options?.body && init.method !== \"GET\" && init.method !== \"HEAD\") {\n init.body = options.body;\n }\n\n const initJson = JSON.stringify(init);\n\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testRequest = new Request(${JSON.stringify(url)}, ${initJson});\n `);\n break;\n\n case \"customFunction\":\n // Store params on host, then retrieve and construct in isolate\n // This simulates getting data from a custom function and constructing a Request\n await ctx.eval(`\n __setRequestParams(${JSON.stringify(url)}, ${initJson});\n const params = __getRequestParams();\n globalThis.__testRequest = new Request(params.url, params.init);\n `);\n break;\n\n case \"serveRequest\":\n // Setup serve handler that captures the request\n await ctx.eval(`\n serve({\n fetch(request) {\n globalThis.__testRequest = request;\n return new Response(\"ok\");\n }\n });\n `);\n\n // Dispatch a request from the host\n const request = new Request(url, init as RequestInit);\n await ctx.dispatchRequest(request);\n break;\n }\n}\n\n// ============================================================================\n// Headers Helpers\n// ============================================================================\n\n/**\n * Create Headers in the isolate from the specified origin.\n * The Headers is stored at globalThis.__testHeaders.\n */\nexport async function getHeadersFromOrigin(\n ctx: ConsistencyTestContext,\n origin: HeadersOrigin,\n init: Record<string, string>\n): Promise<void> {\n const initJson = JSON.stringify(init);\n\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testHeaders = new Headers(${initJson});\n `);\n break;\n\n case \"fromResponse\":\n await ctx.eval(`\n const response = new Response(null, { headers: ${initJson} });\n globalThis.__testHeaders = response.headers;\n `);\n break;\n\n case \"fromRequest\":\n await ctx.eval(`\n const request = new Request(\"https://example.com\", { headers: ${initJson} });\n globalThis.__testHeaders = request.headers;\n `);\n break;\n }\n}\n\n// ============================================================================\n// Blob Helpers\n// ============================================================================\n\nexport interface BlobOptions {\n type?: string;\n}\n\n/**\n * Create a Blob in the isolate from the specified origin.\n * The Blob is stored at globalThis.__testBlob.\n */\nexport async function getBlobFromOrigin(\n ctx: ConsistencyTestContext,\n origin: BlobOrigin,\n content: string,\n options?: BlobOptions\n): Promise<void> {\n const blobOptions = { type: options?.type ?? \"\" };\n const optionsJson = JSON.stringify(blobOptions);\n\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testBlob = new Blob([${JSON.stringify(content)}], ${optionsJson});\n `);\n break;\n }\n}\n\n// ============================================================================\n// File Helpers\n// ============================================================================\n\nexport interface FileOptions {\n type?: string;\n lastModified?: number;\n}\n\n/**\n * Create a File in the isolate from the specified origin.\n * The File is stored at globalThis.__testFile.\n */\nexport async function getFileFromOrigin(\n ctx: ConsistencyTestContext,\n origin: FileOrigin,\n content: string,\n filename: string,\n options?: FileOptions\n): Promise<void> {\n const fileOptions = {\n type: options?.type ?? \"\",\n lastModified: options?.lastModified ?? Date.now(),\n };\n const optionsJson = JSON.stringify(fileOptions);\n\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testFile = new File([${JSON.stringify(content)}], ${JSON.stringify(filename)}, ${optionsJson});\n `);\n break;\n }\n}\n\n// ============================================================================\n// FormData Helpers\n// ============================================================================\n\n/**\n * Create FormData in the isolate from the specified origin.\n * The FormData is stored at globalThis.__testFormData.\n */\nexport async function getFormDataFromOrigin(\n ctx: ConsistencyTestContext,\n origin: FormDataOrigin,\n entries: Array<[string, string]>\n): Promise<void> {\n const entriesJson = JSON.stringify(entries);\n\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testFormData = new FormData();\n for (const [key, value] of ${entriesJson}) {\n globalThis.__testFormData.append(key, value);\n }\n `);\n break;\n\n case \"fromResponse\":\n // Create a response with urlencoded body and parse it\n const params = entries.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join(\"&\");\n await ctx.eval(`\n const response = new Response(${JSON.stringify(params)}, {\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" }\n });\n globalThis.__testFormData = await response.formData();\n `);\n break;\n }\n}\n\n// ============================================================================\n// Host-side helpers for dispatchResponse origin\n// ============================================================================\n\n/**\n * Setup a serve handler that returns the specified response.\n */\nexport async function setupServeHandler(\n ctx: ConsistencyTestContext,\n body: string,\n options?: ResponseOptions\n): Promise<void> {\n const init = {\n status: options?.status ?? 200,\n statusText: options?.statusText ?? \"\",\n headers: options?.headers ?? {},\n };\n const initJson = JSON.stringify(init);\n\n await ctx.eval(`\n serve({\n fetch(request) {\n return new Response(${JSON.stringify(body)}, ${initJson});\n }\n });\n `);\n}\n\n/**\n * Dispatch a request and get the Response on the host side.\n * This tests the host-side conversion of Response from isolate.\n */\nexport async function getDispatchResponse(\n ctx: ConsistencyTestContext,\n body: string,\n options?: ResponseOptions\n): Promise<Response> {\n await setupServeHandler(ctx, body, options);\n return ctx.dispatchRequest(new Request(\"https://example.com/test\"));\n}\n\n// ============================================================================\n// ReadableStream Helpers\n// ============================================================================\n\n/**\n * Create a ReadableStream in the isolate from the specified origin.\n * The ReadableStream is stored at globalThis.__testReadableStream.\n */\nexport async function getReadableStreamFromOrigin(\n ctx: ConsistencyTestContext,\n origin: ReadableStreamOrigin,\n chunks: string[] = [\"chunk1\", \"chunk2\"]\n): Promise<void> {\n const chunksJson = JSON.stringify(chunks);\n\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n const chunks = ${chunksJson};\n let index = 0;\n globalThis.__testReadableStream = new ReadableStream({\n pull(controller) {\n if (index < chunks.length) {\n controller.enqueue(new TextEncoder().encode(chunks[index++]));\n } else {\n controller.close();\n }\n }\n });\n `);\n break;\n\n case \"responseBody\":\n ctx.setMockResponse({\n status: 200,\n body: chunks.join(\"\"),\n });\n await ctx.eval(`\n const response = await fetch(\"https://example.com/test\");\n globalThis.__testReadableStream = response.body;\n `);\n break;\n\n case \"blobStream\":\n await ctx.eval(`\n const chunks = ${chunksJson};\n const blob = new Blob(chunks);\n globalThis.__testReadableStream = blob.stream();\n `);\n break;\n\n case \"transformReadable\":\n await ctx.eval(`\n const transform = new TransformStream();\n globalThis.__testReadableStream = transform.readable;\n // Write chunks to writable side and close it\n const writer = transform.writable.getWriter();\n const chunks = ${chunksJson};\n (async () => {\n for (const chunk of chunks) {\n await writer.write(new TextEncoder().encode(chunk));\n }\n await writer.close();\n })();\n `);\n break;\n }\n}\n\n// ============================================================================\n// WritableStream Helpers\n// ============================================================================\n\n/**\n * Create a WritableStream in the isolate from the specified origin.\n * The WritableStream is stored at globalThis.__testWritableStream.\n * Also stores written chunks at globalThis.__testWrittenChunks.\n */\nexport async function getWritableStreamFromOrigin(\n ctx: ConsistencyTestContext,\n origin: WritableStreamOrigin\n): Promise<void> {\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testWrittenChunks = [];\n globalThis.__testWritableStream = new WritableStream({\n write(chunk) {\n globalThis.__testWrittenChunks.push(chunk);\n }\n });\n `);\n break;\n\n case \"transformWritable\":\n await ctx.eval(`\n globalThis.__testWrittenChunks = [];\n const transform = new TransformStream({\n transform(chunk, controller) {\n globalThis.__testWrittenChunks.push(chunk);\n controller.enqueue(chunk);\n }\n });\n globalThis.__testWritableStream = transform.writable;\n // Start reading to allow writes to complete\n const reader = transform.readable.getReader();\n (async () => {\n while (true) {\n const { done } = await reader.read();\n if (done) break;\n }\n })();\n `);\n break;\n }\n}\n\n// ============================================================================\n// TransformStream Helpers\n// ============================================================================\n\n/**\n * Create a TransformStream in the isolate from the specified origin.\n * The TransformStream is stored at globalThis.__testTransformStream.\n */\nexport async function getTransformStreamFromOrigin(\n ctx: ConsistencyTestContext,\n _origin: TransformStreamOrigin\n): Promise<void> {\n await ctx.eval(`\n globalThis.__testTransformStream = new TransformStream();\n `);\n}\n\n// ============================================================================\n// TextEncoderStream Helpers\n// ============================================================================\n\n/**\n * Create a TextEncoderStream in the isolate from the specified origin.\n * The TextEncoderStream is stored at globalThis.__testTextEncoderStream.\n */\nexport async function getTextEncoderStreamFromOrigin(\n ctx: ConsistencyTestContext,\n _origin: TextEncoderStreamOrigin\n): Promise<void> {\n await ctx.eval(`\n globalThis.__testTextEncoderStream = new TextEncoderStream();\n `);\n}\n\n// ============================================================================\n// TextDecoderStream Helpers\n// ============================================================================\n\nexport interface TextDecoderStreamOptions {\n fatal?: boolean;\n ignoreBOM?: boolean;\n}\n\n/**\n * Create a TextDecoderStream in the isolate from the specified origin.\n * The TextDecoderStream is stored at globalThis.__testTextDecoderStream.\n */\nexport async function getTextDecoderStreamFromOrigin(\n ctx: ConsistencyTestContext,\n _origin: TextDecoderStreamOrigin,\n options?: TextDecoderStreamOptions\n): Promise<void> {\n const optionsJson = JSON.stringify(options ?? {});\n await ctx.eval(`\n globalThis.__testTextDecoderStream = new TextDecoderStream(\"utf-8\", ${optionsJson});\n `);\n}\n\n// ============================================================================\n// QueuingStrategy Helpers\n// ============================================================================\n\n/**\n * Create a ByteLengthQueuingStrategy or CountQueuingStrategy in the isolate.\n * The strategy is stored at globalThis.__testQueuingStrategy.\n */\nexport async function getQueuingStrategyFromOrigin(\n ctx: ConsistencyTestContext,\n strategyType: \"ByteLength\" | \"Count\",\n highWaterMark: number = 1\n): Promise<void> {\n if (strategyType === \"ByteLength\") {\n await ctx.eval(`\n globalThis.__testQueuingStrategy = new ByteLengthQueuingStrategy({ highWaterMark: ${highWaterMark} });\n `);\n } else {\n await ctx.eval(`\n globalThis.__testQueuingStrategy = new CountQueuingStrategy({ highWaterMark: ${highWaterMark} });\n `);\n }\n}\n\n// ============================================================================\n// URL Helpers\n// ============================================================================\n\n/**\n * Create a URL in the isolate from the specified origin.\n * The URL is stored at globalThis.__testURL.\n */\nexport async function getURLFromOrigin(\n ctx: ConsistencyTestContext,\n origin: URLOrigin,\n urlString: string\n): Promise<void> {\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testURL = new URL(${JSON.stringify(urlString)});\n `);\n break;\n\n case \"customFunction\":\n // URL goes through marshal/unmarshal (URLRef)\n await ctx.eval(`\n __setURL(new URL(${JSON.stringify(urlString)}));\n globalThis.__testURL = __getURL();\n `);\n break;\n }\n}\n\n// ============================================================================\n// URLSearchParams Helpers\n// ============================================================================\n\n/**\n * Create URLSearchParams in the isolate from the specified origin.\n * The URLSearchParams is stored at globalThis.__testURLSearchParams.\n */\nexport async function getURLSearchParamsFromOrigin(\n ctx: ConsistencyTestContext,\n origin: URLSearchParamsOrigin,\n init: string = \"\"\n): Promise<void> {\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testURLSearchParams = new URLSearchParams(${JSON.stringify(init)});\n `);\n break;\n\n case \"fromURL\":\n await ctx.eval(`\n const url = new URL(\"https://example.com?\" + ${JSON.stringify(init)});\n globalThis.__testURLSearchParams = url.searchParams;\n `);\n break;\n\n case \"fromCustomFunctionURL\":\n // URL comes through boundary, then get searchParams\n await ctx.eval(`\n __setURL(new URL(\"https://example.com?\" + ${JSON.stringify(init)}));\n const url = __getURL();\n globalThis.__testURLSearchParams = url.searchParams;\n `);\n break;\n }\n}\n\n// ============================================================================\n// AbortController Helpers\n// ============================================================================\n\n/**\n * Create an AbortController in the isolate from the specified origin.\n * The AbortController is stored at globalThis.__testAbortController.\n */\nexport async function getAbortControllerFromOrigin(\n ctx: ConsistencyTestContext,\n _origin: AbortControllerOrigin\n): Promise<void> {\n await ctx.eval(`\n globalThis.__testAbortController = new AbortController();\n `);\n}\n\n// ============================================================================\n// AbortSignal Helpers\n// ============================================================================\n\n/**\n * Create an AbortSignal in the isolate from the specified origin.\n * The AbortSignal is stored at globalThis.__testAbortSignal.\n */\nexport async function getAbortSignalFromOrigin(\n ctx: ConsistencyTestContext,\n _origin: AbortSignalOrigin\n): Promise<void> {\n // AbortSignal is obtained from AbortController.signal\n await ctx.eval(`\n const controller = new AbortController();\n globalThis.__testAbortSignal = controller.signal;\n globalThis.__testAbortController = controller;\n `);\n}\n"
5
+ "/**\n * Helper functions for creating web objects from different origins.\n * Used to test that objects behave identically regardless of how they were created.\n *\n * Note: The `customFunction` origin is tested where supported. For Response and Request,\n * this requires constructing the object in the isolate using parameters passed from\n * a host custom function, since native objects cannot be serialized across the boundary.\n */\n\nimport { createRuntime, type RuntimeHandle } from \"@ricsam/isolate-runtime\";\nimport { clearAllInstanceState } from \"@ricsam/isolate-core\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ResponseOrigin =\n | \"direct\"\n | \"customFunction\"\n | \"fetchCallback\";\n\nexport type RequestOrigin =\n | \"direct\"\n | \"customFunction\"\n | \"serveRequest\";\n\nexport type HeadersOrigin = \"direct\" | \"fromResponse\" | \"fromRequest\";\n\n// Blob and File don't have special marshalling support for custom functions\nexport type BlobOrigin = \"direct\";\n\nexport type FileOrigin = \"direct\";\n\n// URL has special marshalling via URLRef (only href stored)\nexport type URLOrigin = \"direct\" | \"customFunction\";\n\n// URLSearchParams can come from direct construction or from URL.searchParams\nexport type URLSearchParamsOrigin = \"direct\" | \"fromURL\" | \"fromCustomFunctionURL\";\n\n// FormData doesn't have special marshalling support for custom functions\nexport type FormDataOrigin = \"direct\" | \"fromResponse\";\n\n// Stream origins\nexport type ReadableStreamOrigin =\n | \"direct\" // new ReadableStream() in isolate\n | \"responseBody\" // response.body from fetch callback\n | \"blobStream\" // blob.stream()\n | \"transformReadable\"; // transformStream.readable\n\nexport type WritableStreamOrigin =\n | \"direct\" // new WritableStream() in isolate\n | \"transformWritable\"; // transformStream.writable\n\nexport type TransformStreamOrigin = \"direct\";\nexport type TextEncoderStreamOrigin = \"direct\";\nexport type TextDecoderStreamOrigin = \"direct\";\nexport type QueuingStrategyOrigin = \"direct\";\n\nexport const RESPONSE_ORIGINS: ResponseOrigin[] = [\n \"direct\",\n \"customFunction\",\n \"fetchCallback\",\n];\n\nexport const REQUEST_ORIGINS: RequestOrigin[] = [\n \"direct\",\n \"customFunction\",\n \"serveRequest\",\n];\n\nexport const HEADERS_ORIGINS: HeadersOrigin[] = [\n \"direct\",\n \"fromResponse\",\n \"fromRequest\",\n];\n\nexport const BLOB_ORIGINS: BlobOrigin[] = [\"direct\"];\n\nexport const FILE_ORIGINS: FileOrigin[] = [\"direct\"];\n\nexport const URL_ORIGINS: URLOrigin[] = [\"direct\", \"customFunction\"];\n\nexport const URLSEARCHPARAMS_ORIGINS: URLSearchParamsOrigin[] = [\n \"direct\",\n \"fromURL\",\n \"fromCustomFunctionURL\",\n];\n\nexport const FORMDATA_ORIGINS: FormDataOrigin[] = [\n \"direct\",\n \"fromResponse\",\n];\n\nexport const READABLE_STREAM_ORIGINS: ReadableStreamOrigin[] = [\n \"direct\",\n \"responseBody\",\n \"blobStream\",\n \"transformReadable\",\n];\n\nexport const WRITABLE_STREAM_ORIGINS: WritableStreamOrigin[] = [\n \"direct\",\n \"transformWritable\",\n];\n\nexport const TRANSFORM_STREAM_ORIGINS: TransformStreamOrigin[] = [\"direct\"];\nexport const TEXT_ENCODER_STREAM_ORIGINS: TextEncoderStreamOrigin[] = [\"direct\"];\nexport const TEXT_DECODER_STREAM_ORIGINS: TextDecoderStreamOrigin[] = [\"direct\"];\nexport const QUEUING_STRATEGY_ORIGINS: QueuingStrategyOrigin[] = [\"direct\"];\n\n// AbortController/AbortSignal have NO marshalling support (no AbortRef type in codec)\n// They cannot be passed through custom functions - only direct instantiation in isolate\nexport type AbortControllerOrigin = \"direct\";\nexport type AbortSignalOrigin = \"direct\";\n\nexport const ABORT_CONTROLLER_ORIGINS: AbortControllerOrigin[] = [\"direct\"];\nexport const ABORT_SIGNAL_ORIGINS: AbortSignalOrigin[] = [\"direct\"];\n\n// ============================================================================\n// Test Context\n// ============================================================================\n\nexport interface ConsistencyTestContext {\n /** The runtime handle */\n runtime: RuntimeHandle;\n /** Execute code in the runtime */\n eval(code: string): Promise<void>;\n /** Dispatch an HTTP request to the serve() handler */\n dispatchRequest(request: Request): Promise<Response>;\n /** Set the mock response for the next fetch call */\n setMockResponse(response: MockResponse): void;\n /** Get a result from the isolate via setResult() */\n getResult<T = unknown>(): T | undefined;\n /** Clear the stored result */\n clearResult(): void;\n /** Dispose all resources */\n dispose(): Promise<void>;\n}\n\nexport interface MockResponse {\n status?: number;\n statusText?: string;\n body?: string;\n headers?: Record<string, string>;\n}\n\n/**\n * Create a test context for consistency tests.\n * Provides helpers for creating objects from different origins.\n */\nexport async function createConsistencyTestContext(): Promise<ConsistencyTestContext> {\n // Clear any previous instance state\n clearAllInstanceState();\n\n let mockResponse: MockResponse = { status: 200, body: \"\" };\n let storedResult: unknown = undefined;\n\n // Pending parameters for custom function origins\n // These are stored on the host and retrieved by the isolate to construct objects\n let pendingResponseParams: { body: string; init: ResponseInit } | null = null;\n let pendingRequestParams: { url: string; init: RequestInit } | null = null;\n let pendingURL: URL | null = null;\n\n const runtime = await createRuntime({\n fetch: async () => {\n // Return mock response\n return new Response(mockResponse.body ?? \"\", {\n status: mockResponse.status ?? 200,\n statusText: mockResponse.statusText ?? \"\",\n headers: mockResponse.headers,\n });\n },\n customFunctions: {\n setResult: {\n fn: (value: unknown) => {\n storedResult = value;\n },\n type: \"sync\",\n },\n // For Response customFunction origin: store params, return them for isolate to construct\n __setResponseParams: {\n fn: (body: string, init: ResponseInit) => {\n pendingResponseParams = { body, init };\n },\n type: \"sync\",\n },\n __getResponseParams: {\n fn: () => {\n const params = pendingResponseParams;\n pendingResponseParams = null;\n return params;\n },\n type: \"sync\",\n },\n // For Request customFunction origin: store params, return them for isolate to construct\n __setRequestParams: {\n fn: (url: string, init: RequestInit) => {\n pendingRequestParams = { url, init };\n },\n type: \"sync\",\n },\n __getRequestParams: {\n fn: () => {\n const params = pendingRequestParams;\n pendingRequestParams = null;\n return params;\n },\n type: \"sync\",\n },\n // For URL customFunction origin: URL goes through marshal/unmarshal (URLRef)\n __setURL: {\n fn: (url: URL) => {\n pendingURL = url;\n },\n type: \"sync\",\n },\n __getURL: {\n fn: () => {\n const url = pendingURL;\n pendingURL = null;\n return url;\n },\n type: \"sync\",\n },\n },\n });\n\n await runtime.eval(`\n globalThis.__consistencyPendingTasks = new Set();\n globalThis.__consistencyCleanupFns = [];\n globalThis.__consistencyTrackTask = function(task) {\n globalThis.__consistencyPendingTasks.add(task);\n task.finally(() => {\n globalThis.__consistencyPendingTasks.delete(task);\n });\n return task;\n };\n globalThis.__consistencyRegisterCleanup = function(cleanup) {\n globalThis.__consistencyCleanupFns.push(cleanup);\n return cleanup;\n };\n `);\n\n return {\n runtime,\n eval: runtime.eval.bind(runtime),\n dispatchRequest: runtime.fetch.dispatchRequest.bind(runtime.fetch),\n setMockResponse(response: MockResponse) {\n mockResponse = response;\n },\n getResult<T = unknown>(): T | undefined {\n return storedResult as T | undefined;\n },\n clearResult() {\n storedResult = undefined;\n },\n async dispose() {\n try {\n await runtime.eval(`\n const cleanupFns = globalThis.__consistencyCleanupFns ?? [];\n while (cleanupFns.length > 0) {\n const cleanup = cleanupFns.pop();\n if (!cleanup) continue;\n try {\n await cleanup();\n } catch {\n // Ignore cleanup races during test teardown.\n }\n }\n\n const pendingTasks = globalThis.__consistencyPendingTasks\n ? Array.from(globalThis.__consistencyPendingTasks)\n : [];\n if (pendingTasks.length > 0) {\n await Promise.allSettled(pendingTasks);\n }\n `);\n } catch {\n // The runtime may already be tearing down; ignore cleanup races.\n }\n await runtime.dispose();\n },\n };\n}\n\n// ============================================================================\n// Response Helpers\n// ============================================================================\n\nexport interface ResponseOptions {\n status?: number;\n statusText?: string;\n headers?: Record<string, string>;\n}\n\n/**\n * Create a Response in the isolate from the specified origin.\n * The Response is stored at globalThis.__testResponse.\n */\nexport async function getResponseFromOrigin(\n ctx: ConsistencyTestContext,\n origin: ResponseOrigin,\n body: string,\n options?: ResponseOptions\n): Promise<void> {\n const init = {\n status: options?.status ?? 200,\n statusText: options?.statusText ?? \"\",\n headers: options?.headers ?? {},\n };\n const initJson = JSON.stringify(init);\n\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testResponse = new Response(${JSON.stringify(body)}, ${initJson});\n `);\n break;\n\n case \"customFunction\":\n // Store params on host, then retrieve and construct in isolate\n // This simulates getting data from a custom function and constructing a Response\n await ctx.eval(`\n __setResponseParams(${JSON.stringify(body)}, ${initJson});\n const params = __getResponseParams();\n globalThis.__testResponse = new Response(params.body, params.init);\n `);\n break;\n\n case \"fetchCallback\":\n ctx.setMockResponse({\n status: init.status,\n statusText: init.statusText,\n body,\n headers: init.headers,\n });\n await ctx.eval(`\n globalThis.__testResponse = await fetch(\"https://example.com/test\");\n `);\n break;\n }\n}\n\n// ============================================================================\n// Request Helpers\n// ============================================================================\n\nexport interface RequestOptions {\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n}\n\n/**\n * Create a Request in the isolate from the specified origin.\n * The Request is stored at globalThis.__testRequest.\n */\nexport async function getRequestFromOrigin(\n ctx: ConsistencyTestContext,\n origin: RequestOrigin,\n url: string,\n options?: RequestOptions\n): Promise<void> {\n const init: RequestInit = {\n method: options?.method ?? \"GET\",\n headers: options?.headers ?? {},\n };\n\n // Only add body for non-GET/HEAD requests\n if (options?.body && init.method !== \"GET\" && init.method !== \"HEAD\") {\n init.body = options.body;\n }\n\n const initJson = JSON.stringify(init);\n\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testRequest = new Request(${JSON.stringify(url)}, ${initJson});\n `);\n break;\n\n case \"customFunction\":\n // Store params on host, then retrieve and construct in isolate\n // This simulates getting data from a custom function and constructing a Request\n await ctx.eval(`\n __setRequestParams(${JSON.stringify(url)}, ${initJson});\n const params = __getRequestParams();\n globalThis.__testRequest = new Request(params.url, params.init);\n `);\n break;\n\n case \"serveRequest\":\n // Setup serve handler that captures the request\n await ctx.eval(`\n serve({\n fetch(request) {\n globalThis.__testRequest = request;\n return new Response(\"ok\");\n }\n });\n `);\n\n // Dispatch a request from the host\n const request = new Request(url, init as RequestInit);\n await ctx.dispatchRequest(request);\n break;\n }\n}\n\n// ============================================================================\n// Headers Helpers\n// ============================================================================\n\n/**\n * Create Headers in the isolate from the specified origin.\n * The Headers is stored at globalThis.__testHeaders.\n */\nexport async function getHeadersFromOrigin(\n ctx: ConsistencyTestContext,\n origin: HeadersOrigin,\n init: Record<string, string>\n): Promise<void> {\n const initJson = JSON.stringify(init);\n\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testHeaders = new Headers(${initJson});\n `);\n break;\n\n case \"fromResponse\":\n await ctx.eval(`\n const response = new Response(null, { headers: ${initJson} });\n globalThis.__testHeaders = response.headers;\n `);\n break;\n\n case \"fromRequest\":\n await ctx.eval(`\n const request = new Request(\"https://example.com\", { headers: ${initJson} });\n globalThis.__testHeaders = request.headers;\n `);\n break;\n }\n}\n\n// ============================================================================\n// Blob Helpers\n// ============================================================================\n\nexport interface BlobOptions {\n type?: string;\n}\n\n/**\n * Create a Blob in the isolate from the specified origin.\n * The Blob is stored at globalThis.__testBlob.\n */\nexport async function getBlobFromOrigin(\n ctx: ConsistencyTestContext,\n origin: BlobOrigin,\n content: string,\n options?: BlobOptions\n): Promise<void> {\n const blobOptions = { type: options?.type ?? \"\" };\n const optionsJson = JSON.stringify(blobOptions);\n\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testBlob = new Blob([${JSON.stringify(content)}], ${optionsJson});\n `);\n break;\n }\n}\n\n// ============================================================================\n// File Helpers\n// ============================================================================\n\nexport interface FileOptions {\n type?: string;\n lastModified?: number;\n}\n\n/**\n * Create a File in the isolate from the specified origin.\n * The File is stored at globalThis.__testFile.\n */\nexport async function getFileFromOrigin(\n ctx: ConsistencyTestContext,\n origin: FileOrigin,\n content: string,\n filename: string,\n options?: FileOptions\n): Promise<void> {\n const fileOptions = {\n type: options?.type ?? \"\",\n lastModified: options?.lastModified ?? Date.now(),\n };\n const optionsJson = JSON.stringify(fileOptions);\n\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testFile = new File([${JSON.stringify(content)}], ${JSON.stringify(filename)}, ${optionsJson});\n `);\n break;\n }\n}\n\n// ============================================================================\n// FormData Helpers\n// ============================================================================\n\n/**\n * Create FormData in the isolate from the specified origin.\n * The FormData is stored at globalThis.__testFormData.\n */\nexport async function getFormDataFromOrigin(\n ctx: ConsistencyTestContext,\n origin: FormDataOrigin,\n entries: Array<[string, string]>\n): Promise<void> {\n const entriesJson = JSON.stringify(entries);\n\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testFormData = new FormData();\n for (const [key, value] of ${entriesJson}) {\n globalThis.__testFormData.append(key, value);\n }\n `);\n break;\n\n case \"fromResponse\":\n // Create a response with urlencoded body and parse it\n const params = entries.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join(\"&\");\n await ctx.eval(`\n const response = new Response(${JSON.stringify(params)}, {\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" }\n });\n globalThis.__testFormData = await response.formData();\n `);\n break;\n }\n}\n\n// ============================================================================\n// Host-side helpers for dispatchResponse origin\n// ============================================================================\n\n/**\n * Setup a serve handler that returns the specified response.\n */\nexport async function setupServeHandler(\n ctx: ConsistencyTestContext,\n body: string,\n options?: ResponseOptions\n): Promise<void> {\n const init = {\n status: options?.status ?? 200,\n statusText: options?.statusText ?? \"\",\n headers: options?.headers ?? {},\n };\n const initJson = JSON.stringify(init);\n\n await ctx.eval(`\n serve({\n fetch(request) {\n return new Response(${JSON.stringify(body)}, ${initJson});\n }\n });\n `);\n}\n\n/**\n * Dispatch a request and get the Response on the host side.\n * This tests the host-side conversion of Response from isolate.\n */\nexport async function getDispatchResponse(\n ctx: ConsistencyTestContext,\n body: string,\n options?: ResponseOptions\n): Promise<Response> {\n await setupServeHandler(ctx, body, options);\n return ctx.dispatchRequest(new Request(\"https://example.com/test\"));\n}\n\n// ============================================================================\n// ReadableStream Helpers\n// ============================================================================\n\n/**\n * Create a ReadableStream in the isolate from the specified origin.\n * The ReadableStream is stored at globalThis.__testReadableStream.\n */\nexport async function getReadableStreamFromOrigin(\n ctx: ConsistencyTestContext,\n origin: ReadableStreamOrigin,\n chunks: string[] = [\"chunk1\", \"chunk2\"]\n): Promise<void> {\n const chunksJson = JSON.stringify(chunks);\n\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n const chunks = ${chunksJson};\n let index = 0;\n globalThis.__testReadableStream = new ReadableStream({\n pull(controller) {\n if (index < chunks.length) {\n controller.enqueue(new TextEncoder().encode(chunks[index++]));\n } else {\n controller.close();\n }\n }\n });\n `);\n break;\n\n case \"responseBody\":\n ctx.setMockResponse({\n status: 200,\n body: chunks.join(\"\"),\n });\n await ctx.eval(`\n const response = await fetch(\"https://example.com/test\");\n globalThis.__testReadableStream = response.body;\n `);\n break;\n\n case \"blobStream\":\n await ctx.eval(`\n const chunks = ${chunksJson};\n const blob = new Blob(chunks);\n globalThis.__testReadableStream = blob.stream();\n `);\n break;\n\n case \"transformReadable\":\n await ctx.eval(`\n const transform = new TransformStream();\n globalThis.__testReadableStream = transform.readable;\n const writer = transform.writable.getWriter();\n __consistencyRegisterCleanup(async () => {\n try {\n await writer.abort();\n } catch {\n // Ignore duplicate cleanup races.\n }\n try {\n writer.releaseLock();\n } catch {\n // Ignore release races during teardown.\n }\n });\n const chunks = ${chunksJson};\n __consistencyTrackTask((async () => {\n for (const chunk of chunks) {\n await writer.write(new TextEncoder().encode(chunk));\n }\n await writer.close();\n })().finally(() => {\n try {\n writer.releaseLock();\n } catch {\n // Ignore release races after the task settles.\n }\n }));\n `);\n break;\n }\n}\n\n// ============================================================================\n// WritableStream Helpers\n// ============================================================================\n\n/**\n * Create a WritableStream in the isolate from the specified origin.\n * The WritableStream is stored at globalThis.__testWritableStream.\n * Also stores written chunks at globalThis.__testWrittenChunks.\n */\nexport async function getWritableStreamFromOrigin(\n ctx: ConsistencyTestContext,\n origin: WritableStreamOrigin\n): Promise<void> {\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testWrittenChunks = [];\n globalThis.__testWritableStream = new WritableStream({\n write(chunk) {\n globalThis.__testWrittenChunks.push(chunk);\n }\n });\n `);\n break;\n\n case \"transformWritable\":\n await ctx.eval(`\n globalThis.__testWrittenChunks = [];\n const transform = new TransformStream({\n transform(chunk, controller) {\n globalThis.__testWrittenChunks.push(chunk);\n controller.enqueue(chunk);\n }\n });\n globalThis.__testWritableStream = transform.writable;\n const reader = transform.readable.getReader();\n __consistencyRegisterCleanup(async () => {\n try {\n await reader.cancel();\n } catch {\n // Ignore duplicate cleanup races.\n }\n try {\n reader.releaseLock();\n } catch {\n // Ignore release races during teardown.\n }\n });\n __consistencyTrackTask((async () => {\n while (true) {\n const { done } = await reader.read();\n if (done) break;\n }\n })().finally(() => {\n try {\n reader.releaseLock();\n } catch {\n // Ignore release races after the task settles.\n }\n }));\n `);\n break;\n }\n}\n\n// ============================================================================\n// TransformStream Helpers\n// ============================================================================\n\n/**\n * Create a TransformStream in the isolate from the specified origin.\n * The TransformStream is stored at globalThis.__testTransformStream.\n */\nexport async function getTransformStreamFromOrigin(\n ctx: ConsistencyTestContext,\n _origin: TransformStreamOrigin\n): Promise<void> {\n await ctx.eval(`\n globalThis.__testTransformStream = new TransformStream();\n `);\n}\n\n// ============================================================================\n// TextEncoderStream Helpers\n// ============================================================================\n\n/**\n * Create a TextEncoderStream in the isolate from the specified origin.\n * The TextEncoderStream is stored at globalThis.__testTextEncoderStream.\n */\nexport async function getTextEncoderStreamFromOrigin(\n ctx: ConsistencyTestContext,\n _origin: TextEncoderStreamOrigin\n): Promise<void> {\n await ctx.eval(`\n globalThis.__testTextEncoderStream = new TextEncoderStream();\n `);\n}\n\n// ============================================================================\n// TextDecoderStream Helpers\n// ============================================================================\n\nexport interface TextDecoderStreamOptions {\n fatal?: boolean;\n ignoreBOM?: boolean;\n}\n\n/**\n * Create a TextDecoderStream in the isolate from the specified origin.\n * The TextDecoderStream is stored at globalThis.__testTextDecoderStream.\n */\nexport async function getTextDecoderStreamFromOrigin(\n ctx: ConsistencyTestContext,\n _origin: TextDecoderStreamOrigin,\n options?: TextDecoderStreamOptions\n): Promise<void> {\n const optionsJson = JSON.stringify(options ?? {});\n await ctx.eval(`\n globalThis.__testTextDecoderStream = new TextDecoderStream(\"utf-8\", ${optionsJson});\n `);\n}\n\n// ============================================================================\n// QueuingStrategy Helpers\n// ============================================================================\n\n/**\n * Create a ByteLengthQueuingStrategy or CountQueuingStrategy in the isolate.\n * The strategy is stored at globalThis.__testQueuingStrategy.\n */\nexport async function getQueuingStrategyFromOrigin(\n ctx: ConsistencyTestContext,\n strategyType: \"ByteLength\" | \"Count\",\n highWaterMark: number = 1\n): Promise<void> {\n if (strategyType === \"ByteLength\") {\n await ctx.eval(`\n globalThis.__testQueuingStrategy = new ByteLengthQueuingStrategy({ highWaterMark: ${highWaterMark} });\n `);\n } else {\n await ctx.eval(`\n globalThis.__testQueuingStrategy = new CountQueuingStrategy({ highWaterMark: ${highWaterMark} });\n `);\n }\n}\n\n// ============================================================================\n// URL Helpers\n// ============================================================================\n\n/**\n * Create a URL in the isolate from the specified origin.\n * The URL is stored at globalThis.__testURL.\n */\nexport async function getURLFromOrigin(\n ctx: ConsistencyTestContext,\n origin: URLOrigin,\n urlString: string\n): Promise<void> {\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testURL = new URL(${JSON.stringify(urlString)});\n `);\n break;\n\n case \"customFunction\":\n // URL goes through marshal/unmarshal (URLRef)\n await ctx.eval(`\n __setURL(new URL(${JSON.stringify(urlString)}));\n globalThis.__testURL = __getURL();\n `);\n break;\n }\n}\n\n// ============================================================================\n// URLSearchParams Helpers\n// ============================================================================\n\n/**\n * Create URLSearchParams in the isolate from the specified origin.\n * The URLSearchParams is stored at globalThis.__testURLSearchParams.\n */\nexport async function getURLSearchParamsFromOrigin(\n ctx: ConsistencyTestContext,\n origin: URLSearchParamsOrigin,\n init: string = \"\"\n): Promise<void> {\n switch (origin) {\n case \"direct\":\n await ctx.eval(`\n globalThis.__testURLSearchParams = new URLSearchParams(${JSON.stringify(init)});\n `);\n break;\n\n case \"fromURL\":\n await ctx.eval(`\n const url = new URL(\"https://example.com?\" + ${JSON.stringify(init)});\n globalThis.__testURLSearchParams = url.searchParams;\n `);\n break;\n\n case \"fromCustomFunctionURL\":\n // URL comes through boundary, then get searchParams\n await ctx.eval(`\n __setURL(new URL(\"https://example.com?\" + ${JSON.stringify(init)}));\n const url = __getURL();\n globalThis.__testURLSearchParams = url.searchParams;\n `);\n break;\n }\n}\n\n// ============================================================================\n// AbortController Helpers\n// ============================================================================\n\n/**\n * Create an AbortController in the isolate from the specified origin.\n * The AbortController is stored at globalThis.__testAbortController.\n */\nexport async function getAbortControllerFromOrigin(\n ctx: ConsistencyTestContext,\n _origin: AbortControllerOrigin\n): Promise<void> {\n await ctx.eval(`\n globalThis.__testAbortController = new AbortController();\n `);\n}\n\n// ============================================================================\n// AbortSignal Helpers\n// ============================================================================\n\n/**\n * Create an AbortSignal in the isolate from the specified origin.\n * The AbortSignal is stored at globalThis.__testAbortSignal.\n */\nexport async function getAbortSignalFromOrigin(\n ctx: ConsistencyTestContext,\n _origin: AbortSignalOrigin\n): Promise<void> {\n // AbortSignal is obtained from AbortController.signal\n await ctx.eval(`\n const controller = new AbortController();\n globalThis.__testAbortSignal = controller.signal;\n globalThis.__testAbortController = controller;\n `);\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "274AB1900A4AAC4364756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "5F9068869222631564756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -121,6 +121,13 @@ function releaseTrackedGlobalHandles(context) {
121
121
  }
122
122
  handles.clear();
123
123
  }
124
+ function clearPassthruBodiesForContext(context) {
125
+ const map = passthruBodies.get(context);
126
+ if (!map)
127
+ return;
128
+ map.clear();
129
+ passthruBodies.delete(context);
130
+ }
124
131
  var headersCode = `
125
132
  (function() {
126
133
  class Headers {
@@ -180,6 +187,12 @@ var headersCode = `
180
187
  const sortedKeys = [...this.#headers.keys()].sort();
181
188
  for (const key of sortedKeys) {
182
189
  const [, values] = this.#headers.get(key);
190
+ if (key === 'set-cookie') {
191
+ for (const value of values) {
192
+ callback.call(thisArg, value, key, this);
193
+ }
194
+ continue;
195
+ }
183
196
  callback.call(thisArg, values.join(', '), key, this);
184
197
  }
185
198
  }
@@ -188,6 +201,12 @@ var headersCode = `
188
201
  const sortedKeys = [...this.#headers.keys()].sort();
189
202
  for (const key of sortedKeys) {
190
203
  const [, values] = this.#headers.get(key);
204
+ if (key === 'set-cookie') {
205
+ for (const value of values) {
206
+ yield [key, value];
207
+ }
208
+ continue;
209
+ }
191
210
  yield [key, values.join(', ')];
192
211
  }
193
212
  }
@@ -203,6 +222,12 @@ var headersCode = `
203
222
  const sortedKeys = [...this.#headers.keys()].sort();
204
223
  for (const key of sortedKeys) {
205
224
  const [, values] = this.#headers.get(key);
225
+ if (key === 'set-cookie') {
226
+ for (const value of values) {
227
+ yield value;
228
+ }
229
+ continue;
230
+ }
206
231
  yield values.join(', ');
207
232
  }
208
233
  }
@@ -2256,6 +2281,8 @@ async function setupFetch(context, options) {
2256
2281
  return {
2257
2282
  dispose() {
2258
2283
  stateMap.clear();
2284
+ clearPassthruBodiesForContext(context);
2285
+ import_stream_state.clearStreamRegistryForContext(context);
2259
2286
  context.evalSync(`globalThis.__upgradeRegistry__.clear()`);
2260
2287
  serveState.activeConnections.clear();
2261
2288
  serveState.pendingUpgrade = null;
@@ -2610,4 +2637,4 @@ async function setupFetch(context, options) {
2610
2637
  };
2611
2638
  }
2612
2639
 
2613
- //# debugId=515350DA36E4FB2764756E2164756E21
2640
+ //# debugId=F5F300B6CCB64E6864756E2164756E21