@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.
- package/dist/cjs/consistency/origins.cjs +77 -7
- package/dist/cjs/consistency/origins.cjs.map +3 -3
- package/dist/cjs/index.cjs +28 -1
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/stream-state.cjs +6 -1
- package/dist/cjs/stream-state.cjs.map +3 -3
- package/dist/mjs/consistency/origins.mjs +77 -7
- package/dist/mjs/consistency/origins.mjs.map +3 -3
- package/dist/mjs/index.mjs +30 -2
- package/dist/mjs/index.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/stream-state.mjs +6 -1
- package/dist/mjs/stream-state.mjs.map +3 -3
- package/package.json +1 -1
|
@@ -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=
|
|
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": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASkD,IAAlD;AACsC,IAAtC;AAgDO,IAAM,mBAAqC;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,kBAAmC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,kBAAmC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,eAA6B,CAAC,QAAQ;AAE5C,IAAM,eAA6B,CAAC,QAAQ;AAE5C,IAAM,cAA2B,CAAC,UAAU,gBAAgB;AAE5D,IAAM,0BAAmD;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,mBAAqC;AAAA,EAChD;AAAA,EACA;AACF;AAEO,IAAM,0BAAkD;AAAA,EAC7D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,0BAAkD;AAAA,EAC7D;AAAA,EACA;AACF;AAEO,IAAM,2BAAoD,CAAC,QAAQ;AACnE,IAAM,8BAAyD,CAAC,QAAQ;AACxE,IAAM,8BAAyD,CAAC,QAAQ;AACxE,IAAM,2BAAoD,CAAC,QAAQ;AAOnE,IAAM,2BAAoD,CAAC,QAAQ;AACnE,IAAM,uBAA4C,CAAC,QAAQ;AAkClE,eAAsB,4BAA4B,GAAoC;AAAA,EAEpF,0CAAsB;AAAA,EAEtB,IAAI,eAA6B,EAAE,QAAQ,KAAK,MAAM,GAAG;AAAA,EACzD,IAAI,eAAwB;AAAA,EAI5B,IAAI,wBAAqE;AAAA,EACzE,IAAI,uBAAkE;AAAA,EACtE,IAAI,aAAyB;AAAA,EAE7B,MAAM,UAAU,MAAM,qCAAc;AAAA,IAClC,OAAO,YAAY;AAAA,MAEjB,OAAO,IAAI,SAAS,aAAa,QAAQ,IAAI;AAAA,QAC3C,QAAQ,aAAa,UAAU;AAAA,QAC/B,YAAY,aAAa,cAAc;AAAA,QACvC,SAAS,aAAa;AAAA,MACxB,CAAC;AAAA;AAAA,IAEH,iBAAiB;AAAA,MACf,WAAW;AAAA,QACT,IAAI,CAAC,UAAmB;AAAA,UACtB,eAAe;AAAA;AAAA,QAEjB,MAAM;AAAA,MACR;AAAA,MAEA,qBAAqB;AAAA,QACnB,IAAI,CAAC,MAAc,SAAuB;AAAA,UACxC,wBAAwB,EAAE,MAAM,KAAK;AAAA;AAAA,QAEvC,MAAM;AAAA,MACR;AAAA,MACA,qBAAqB;AAAA,QACnB,IAAI,MAAM;AAAA,UACR,MAAM,SAAS;AAAA,UACf,wBAAwB;AAAA,UACxB,OAAO;AAAA;AAAA,QAET,MAAM;AAAA,MACR;AAAA,MAEA,oBAAoB;AAAA,QAClB,IAAI,CAAC,KAAa,SAAsB;AAAA,UACtC,uBAAuB,EAAE,KAAK,KAAK;AAAA;AAAA,QAErC,MAAM;AAAA,MACR;AAAA,MACA,oBAAoB;AAAA,QAClB,IAAI,MAAM;AAAA,UACR,MAAM,SAAS;AAAA,UACf,uBAAuB;AAAA,UACvB,OAAO;AAAA;AAAA,QAET,MAAM;AAAA,MACR;AAAA,MAEA,UAAU;AAAA,QACR,IAAI,CAAC,QAAa;AAAA,UAChB,aAAa;AAAA;AAAA,QAEf,MAAM;AAAA,MACR;AAAA,MACA,UAAU;AAAA,QACR,IAAI,MAAM;AAAA,UACR,MAAM,MAAM;AAAA,UACZ,aAAa;AAAA,UACb,OAAO;AAAA;AAAA,QAET,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF,CAAC;AAAA,EAED,OAAO;AAAA,IACL;AAAA,IACA,MAAM,QAAQ,KAAK,KAAK,OAAO;AAAA,IAC/B,iBAAiB,QAAQ,MAAM,gBAAgB,KAAK,QAAQ,KAAK;AAAA,IACjE,eAAe,CAAC,UAAwB;AAAA,MACtC,eAAe;AAAA;AAAA,IAEjB,SAAsB,GAAkB;AAAA,MACtC,OAAO;AAAA;AAAA,IAET,WAAW,GAAG;AAAA,MACZ,eAAe;AAAA;AAAA,SAEX,QAAO,GAAG;AAAA,MACd,MAAM,QAAQ,QAAQ;AAAA;AAAA,EAE1B;AAAA;AAiBF,eAAsB,qBAAqB,CACzC,KACA,QACA,MACA,SACe;AAAA,EACf,MAAM,OAAO;AAAA,IACX,QAAQ,SAAS,UAAU;AAAA,IAC3B,YAAY,SAAS,cAAc;AAAA,IACnC,SAAS,SAAS,WAAW,CAAC;AAAA,EAChC;AAAA,EACA,MAAM,WAAW,KAAK,UAAU,IAAI;AAAA,EAEpC,QAAQ;AAAA,SACD;AAAA,MACH,MAAM,IAAI,KAAK;AAAA,mDAC8B,KAAK,UAAU,IAAI,MAAM;AAAA,OACrE;AAAA,MACD;AAAA,SAEG;AAAA,MAGH,MAAM,IAAI,KAAK;AAAA,8BACS,KAAK,UAAU,IAAI,MAAM;AAAA;AAAA;AAAA,OAGhD;AAAA,MACD;AAAA,SAEG;AAAA,MACH,IAAI,gBAAgB;AAAA,QAClB,QAAQ,KAAK;AAAA,QACb,YAAY,KAAK;AAAA,QACjB;AAAA,QACA,SAAS,KAAK;AAAA,MAChB,CAAC;AAAA,MACD,MAAM,IAAI,KAAK;AAAA;AAAA,OAEd;AAAA,MACD;AAAA;AAAA;AAkBN,eAAsB,oBAAoB,CACxC,KACA,QACA,KACA,SACe;AAAA,EACf,MAAM,OAAoB;AAAA,IACxB,QAAQ,SAAS,UAAU;AAAA,IAC3B,SAAS,SAAS,WAAW,CAAC;AAAA,EAChC;AAAA,EAGA,IAAI,SAAS,QAAQ,KAAK,WAAW,SAAS,KAAK,WAAW,QAAQ;AAAA,IACpE,KAAK,OAAO,QAAQ;AAAA,EACtB;AAAA,EAEA,MAAM,WAAW,KAAK,UAAU,IAAI;AAAA,EAEpC,QAAQ;AAAA,SACD;AAAA,MACH,MAAM,IAAI,KAAK;AAAA,iDAC4B,KAAK,UAAU,GAAG,MAAM;AAAA,OAClE;AAAA,MACD;AAAA,SAEG;AAAA,MAGH,MAAM,IAAI,KAAK;AAAA,6BACQ,KAAK,UAAU,GAAG,MAAM;AAAA;AAAA;AAAA,OAG9C;AAAA,MACD;AAAA,SAEG;AAAA,MAEH,MAAM,IAAI,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAOd;AAAA,MAGD,MAAM,UAAU,IAAI,QAAQ,KAAK,IAAmB;AAAA,MACpD,MAAM,IAAI,gBAAgB,OAAO;AAAA,MACjC;AAAA;AAAA;AAYN,eAAsB,oBAAoB,CACxC,KACA,QACA,MACe;AAAA,EACf,MAAM,WAAW,KAAK,UAAU,IAAI;AAAA,EAEpC,QAAQ;AAAA,SACD;AAAA,MACH,MAAM,IAAI,KAAK;AAAA,iDAC4B;AAAA,OAC1C;AAAA,MACD;AAAA,SAEG;AAAA,MACH,MAAM,IAAI,KAAK;AAAA,yDACoC;AAAA;AAAA,OAElD;AAAA,MACD;AAAA,SAEG;AAAA,MACH,MAAM,IAAI,KAAK;AAAA,wEACmD;AAAA;AAAA,OAEjE;AAAA,MACD;AAAA;AAAA;AAgBN,eAAsB,iBAAiB,CACrC,KACA,QACA,SACA,SACe;AAAA,EACf,MAAM,cAAc,EAAE,MAAM,SAAS,QAAQ,GAAG;AAAA,EAChD,MAAM,cAAc,KAAK,UAAU,WAAW;AAAA,EAE9C,QAAQ;AAAA,SACD;AAAA,MACH,MAAM,IAAI,KAAK;AAAA,4CACuB,KAAK,UAAU,OAAO,OAAO;AAAA,OAClE;AAAA,MACD;AAAA;AAAA;AAiBN,eAAsB,iBAAiB,CACrC,KACA,QACA,SACA,UACA,SACe;AAAA,EACf,MAAM,cAAc;AAAA,IAClB,MAAM,SAAS,QAAQ;AAAA,IACvB,cAAc,SAAS,gBAAgB,KAAK,IAAI;AAAA,EAClD;AAAA,EACA,MAAM,cAAc,KAAK,UAAU,WAAW;AAAA,EAE9C,QAAQ;AAAA,SACD;AAAA,MACH,MAAM,IAAI,KAAK;AAAA,4CACuB,KAAK,UAAU,OAAO,OAAO,KAAK,UAAU,QAAQ,MAAM;AAAA,OAC/F;AAAA,MACD;AAAA;AAAA;AAYN,eAAsB,qBAAqB,CACzC,KACA,QACA,SACe;AAAA,EACf,MAAM,cAAc,KAAK,UAAU,OAAO;AAAA,EAE1C,QAAQ;AAAA,SACD;AAAA,MACH,MAAM,IAAI,KAAK;AAAA;AAAA,qCAEgB;AAAA;AAAA;AAAA,OAG9B;AAAA,MACD;AAAA,SAEG;AAAA,MAEH,MAAM,SAAS,QAAQ,IAAI,EAAE,GAAG,OAAO,GAAG,mBAAmB,CAAC,KAAK,mBAAmB,CAAC,GAAG,EAAE,KAAK,GAAG;AAAA,MACpG,MAAM,IAAI,KAAK;AAAA,wCACmB,KAAK,UAAU,MAAM;AAAA;AAAA;AAAA;AAAA,OAItD;AAAA,MACD;AAAA;AAAA;AAWN,eAAsB,iBAAiB,CACrC,KACA,MACA,SACe;AAAA,EACf,MAAM,OAAO;AAAA,IACX,QAAQ,SAAS,UAAU;AAAA,IAC3B,YAAY,SAAS,cAAc;AAAA,IACnC,SAAS,SAAS,WAAW,CAAC;AAAA,EAChC;AAAA,EACA,MAAM,WAAW,KAAK,UAAU,IAAI;AAAA,EAEpC,MAAM,IAAI,KAAK;AAAA;AAAA;AAAA,8BAGa,KAAK,UAAU,IAAI,MAAM;AAAA;AAAA;AAAA,GAGpD;AAAA;AAOH,eAAsB,mBAAmB,CACvC,KACA,MACA,SACmB;AAAA,EACnB,MAAM,kBAAkB,KAAK,MAAM,OAAO;AAAA,EAC1C,OAAO,IAAI,gBAAgB,IAAI,QAAQ,0BAA0B,CAAC;AAAA;AAWpE,eAAsB,2BAA2B,CAC/C,KACA,QACA,SAAmB,CAAC,UAAU,QAAQ,GACvB;AAAA,EACf,MAAM,aAAa,KAAK,UAAU,MAAM;AAAA,EAExC,QAAQ;AAAA,SACD;AAAA,MACH,MAAM,IAAI,KAAK;AAAA,yBACI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAWlB;AAAA,MACD;AAAA,SAEG;AAAA,MACH,IAAI,gBAAgB;AAAA,QAClB,QAAQ;AAAA,QACR,MAAM,OAAO,KAAK,EAAE;AAAA,MACtB,CAAC;AAAA,MACD,MAAM,IAAI,KAAK;AAAA;AAAA;AAAA,OAGd;AAAA,MACD;AAAA,SAEG;AAAA,MACH,MAAM,IAAI,KAAK;AAAA,yBACI;AAAA;AAAA;AAAA,OAGlB;AAAA,MACD;AAAA,SAEG;AAAA,MACH,MAAM,IAAI,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "5F9068869222631564756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -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=
|
|
2640
|
+
//# debugId=F5F300B6CCB64E6864756E2164756E21
|