@ricsam/isolate-fetch 0.1.22 → 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 +2 -2
package/dist/cjs/package.json
CHANGED
|
@@ -160,6 +160,11 @@ function createStreamStateRegistry() {
|
|
|
160
160
|
},
|
|
161
161
|
clear() {
|
|
162
162
|
for (const [streamId] of streams) {
|
|
163
|
+
const cleanup = cleanups.get(streamId);
|
|
164
|
+
if (cleanup) {
|
|
165
|
+
cleanup().catch(() => {});
|
|
166
|
+
cleanups.delete(streamId);
|
|
167
|
+
}
|
|
163
168
|
this.delete(streamId);
|
|
164
169
|
}
|
|
165
170
|
},
|
|
@@ -248,4 +253,4 @@ function startNativeStreamReader(nativeStream, streamId, registry) {
|
|
|
248
253
|
};
|
|
249
254
|
}
|
|
250
255
|
|
|
251
|
-
//# debugId=
|
|
256
|
+
//# debugId=03C33CB0D90F624664756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/stream-state.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import ivm from \"isolated-vm\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface StreamState {\n /** Buffered chunks waiting to be read */\n queue: Uint8Array[];\n\n /** Total bytes in queue (for backpressure) */\n queueSize: number;\n\n /** Stream has been closed (no more data) */\n closed: boolean;\n\n /** Stream encountered an error */\n errored: boolean;\n\n /** The error value if errored */\n errorValue: unknown;\n\n /** A pull is waiting for data */\n pullWaiting: boolean;\n\n /** Resolve function for waiting pull */\n pullResolve: ((chunk: Uint8Array | null) => void) | null;\n\n /** Reject function for waiting pull */\n pullReject: ((error: unknown) => void) | null;\n}\n\nexport interface StreamStateRegistry {\n /** Create a new stream and return its ID */\n create(): number;\n\n /** Get stream state by ID */\n get(streamId: number): StreamState | undefined;\n\n /** Push a chunk to the stream's queue */\n push(streamId: number, chunk: Uint8Array): boolean;\n\n /** Pull a chunk from the stream (returns Promise that resolves when data available) */\n pull(\n streamId: number\n ): Promise<{ value: Uint8Array; done: false } | { done: true }>;\n\n /** Close the stream (no more data) */\n close(streamId: number): void;\n\n /** Error the stream */\n error(streamId: number, errorValue: unknown): void;\n\n /** Check if stream queue is above high-water mark */\n isQueueFull(streamId: number): boolean;\n\n /** Delete stream state (cleanup) */\n delete(streamId: number): void;\n\n /** Clear all streams (context cleanup) */\n clear(): void;\n\n /** Cancel a stream and call its cleanup function */\n cancel(streamId: number): void;\n\n /** Register a cleanup function for a stream */\n setCleanup(streamId: number, cleanup: () => Promise<void>): void;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** Maximum bytes to buffer before backpressure kicks in */\nexport const HIGH_WATER_MARK = 64 * 1024; // 64KB\n\n/** Maximum number of chunks in queue */\nexport const MAX_QUEUE_CHUNKS = 16;\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\nexport function createStreamStateRegistry(): StreamStateRegistry {\n const streams = new Map<number, StreamState>();\n const cleanups = new Map<number, () => Promise<void>>();\n let nextStreamId = 1;\n\n return {\n create(): number {\n const streamId = nextStreamId++;\n streams.set(streamId, {\n queue: [],\n queueSize: 0,\n closed: false,\n errored: false,\n errorValue: undefined,\n pullWaiting: false,\n pullResolve: null,\n pullReject: null,\n });\n return streamId;\n },\n\n get(streamId: number): StreamState | undefined {\n return streams.get(streamId);\n },\n\n push(streamId: number, chunk: Uint8Array): boolean {\n const state = streams.get(streamId);\n if (!state) return false;\n if (state.closed || state.errored) return false;\n\n // If a pull is waiting, deliver directly\n if (state.pullWaiting && state.pullResolve) {\n state.pullWaiting = false;\n const resolve = state.pullResolve;\n state.pullResolve = null;\n state.pullReject = null;\n resolve(chunk);\n return true;\n }\n\n // Otherwise queue the chunk\n state.queue.push(chunk);\n state.queueSize += chunk.length;\n return true;\n },\n\n async pull(\n streamId: number\n ): Promise<{ value: Uint8Array; done: false } | { done: true }> {\n const state = streams.get(streamId);\n if (!state) {\n return { done: true };\n }\n\n // If queue has data, return it first (even if stream is errored)\n if (state.queue.length > 0) {\n const chunk = state.queue.shift()!;\n state.queueSize -= chunk.length;\n return { value: chunk, done: false };\n }\n\n // If errored (and queue is empty), throw\n if (state.errored) {\n throw state.errorValue;\n }\n\n // If closed and queue empty, we're done\n if (state.closed) {\n return { done: true };\n }\n\n // Wait for data\n return new Promise((resolve, reject) => {\n state.pullWaiting = true;\n state.pullResolve = (chunk) => {\n if (chunk === null) {\n resolve({ done: true });\n } else {\n resolve({ value: chunk, done: false });\n }\n };\n state.pullReject = reject;\n });\n },\n\n close(streamId: number): void {\n const state = streams.get(streamId);\n if (!state) return;\n\n state.closed = true;\n\n // If a pull is waiting, resolve with done\n if (state.pullWaiting && state.pullResolve) {\n state.pullWaiting = false;\n const resolve = state.pullResolve;\n state.pullResolve = null;\n state.pullReject = null;\n resolve(null);\n }\n },\n\n error(streamId: number, errorValue: unknown): void {\n const state = streams.get(streamId);\n if (!state) return;\n\n state.errored = true;\n state.errorValue = errorValue;\n\n // If a pull is waiting, reject it\n if (state.pullWaiting && state.pullReject) {\n state.pullWaiting = false;\n const reject = state.pullReject;\n state.pullResolve = null;\n state.pullReject = null;\n reject(errorValue);\n }\n },\n\n isQueueFull(streamId: number): boolean {\n const state = streams.get(streamId);\n if (!state) return true;\n return (\n state.queueSize >= HIGH_WATER_MARK ||\n state.queue.length >= MAX_QUEUE_CHUNKS\n );\n },\n\n delete(streamId: number): void {\n const state = streams.get(streamId);\n if (state && state.pullWaiting && state.pullReject) {\n state.pullReject(new Error(\"Stream deleted\"));\n }\n streams.delete(streamId);\n cleanups.delete(streamId);\n },\n\n clear(): void {\n for (const [streamId] of streams) {\n this.delete(streamId);\n }\n },\n\n cancel(streamId: number): void {\n this.close(streamId);\n const cleanup = cleanups.get(streamId);\n if (cleanup) {\n cleanup().catch(() => {});\n cleanups.delete(streamId);\n }\n },\n\n setCleanup(streamId: number, cleanup: () => Promise<void>): void {\n cleanups.set(streamId, cleanup);\n },\n };\n}\n\n// ============================================================================\n// Context-Scoped Registry\n// ============================================================================\n\nconst contextRegistries = new WeakMap<ivm.Context, StreamStateRegistry>();\n\nexport function getStreamRegistryForContext(\n context: ivm.Context\n): StreamStateRegistry {\n let registry = contextRegistries.get(context);\n if (!registry) {\n registry = createStreamStateRegistry();\n contextRegistries.set(context, registry);\n }\n return registry;\n}\n\nexport function clearStreamRegistryForContext(context: ivm.Context): void {\n const registry = contextRegistries.get(context);\n if (registry) {\n registry.clear();\n contextRegistries.delete(context);\n }\n}\n\n// ============================================================================\n// Native Stream Reader\n// ============================================================================\n\n/**\n * Start reading from a native ReadableStream and push to host queue.\n * Respects backpressure by pausing when queue is full.\n *\n * @param nativeStream The native ReadableStream to read from\n * @param streamId The stream ID in the registry\n * @param registry The stream state registry\n * @returns Async cleanup function to cancel the reader\n */\nexport function startNativeStreamReader(\n nativeStream: ReadableStream<Uint8Array>,\n streamId: number,\n registry: StreamStateRegistry\n): () => Promise<void> {\n let cancelled = false;\n let reader: ReadableStreamDefaultReader<Uint8Array> | null = null;\n let readLoopPromise: Promise<void> | null = null;\n\n const CHUNK_SIZE = 64 * 1024; // 64KB max chunk size\n\n async function readLoop() {\n try {\n reader = nativeStream.getReader();\n\n while (!cancelled) {\n // Respect backpressure - wait if queue is full\n while (registry.isQueueFull(streamId) && !cancelled) {\n await new Promise((resolve) => setTimeout(resolve, 1));\n }\n if (cancelled) break;\n\n const { done, value } = await reader.read();\n\n if (done) {\n registry.close(streamId);\n break;\n }\n\n if (value) {\n // Split large chunks to maintain granularity\n if (value.length > CHUNK_SIZE) {\n for (let offset = 0; offset < value.length; offset += CHUNK_SIZE) {\n const chunk = value.slice(\n offset,\n Math.min(offset + CHUNK_SIZE, value.length)\n );\n registry.push(streamId, chunk);\n }\n } else {\n registry.push(streamId, value);\n }\n }\n }\n } catch (error) {\n registry.error(streamId, error);\n } finally {\n if (reader) {\n try {\n reader.releaseLock();\n } catch {\n // Ignore release errors\n }\n }\n }\n }\n\n // Start the read loop and save the promise\n readLoopPromise = readLoop();\n\n // Return async cleanup function\n return async () => {\n cancelled = true;\n if (reader) {\n try {\n await reader.cancel();\n } catch {\n // Ignore cancel errors\n }\n }\n // Wait for read loop to finish\n if (readLoopPromise) {\n try {\n await readLoopPromise;\n } catch {\n // Ignore read loop errors during cleanup\n }\n }\n };\n}\n"
|
|
5
|
+
"import ivm from \"isolated-vm\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface StreamState {\n /** Buffered chunks waiting to be read */\n queue: Uint8Array[];\n\n /** Total bytes in queue (for backpressure) */\n queueSize: number;\n\n /** Stream has been closed (no more data) */\n closed: boolean;\n\n /** Stream encountered an error */\n errored: boolean;\n\n /** The error value if errored */\n errorValue: unknown;\n\n /** A pull is waiting for data */\n pullWaiting: boolean;\n\n /** Resolve function for waiting pull */\n pullResolve: ((chunk: Uint8Array | null) => void) | null;\n\n /** Reject function for waiting pull */\n pullReject: ((error: unknown) => void) | null;\n}\n\nexport interface StreamStateRegistry {\n /** Create a new stream and return its ID */\n create(): number;\n\n /** Get stream state by ID */\n get(streamId: number): StreamState | undefined;\n\n /** Push a chunk to the stream's queue */\n push(streamId: number, chunk: Uint8Array): boolean;\n\n /** Pull a chunk from the stream (returns Promise that resolves when data available) */\n pull(\n streamId: number\n ): Promise<{ value: Uint8Array; done: false } | { done: true }>;\n\n /** Close the stream (no more data) */\n close(streamId: number): void;\n\n /** Error the stream */\n error(streamId: number, errorValue: unknown): void;\n\n /** Check if stream queue is above high-water mark */\n isQueueFull(streamId: number): boolean;\n\n /** Delete stream state (cleanup) */\n delete(streamId: number): void;\n\n /** Clear all streams (context cleanup) */\n clear(): void;\n\n /** Cancel a stream and call its cleanup function */\n cancel(streamId: number): void;\n\n /** Register a cleanup function for a stream */\n setCleanup(streamId: number, cleanup: () => Promise<void>): void;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** Maximum bytes to buffer before backpressure kicks in */\nexport const HIGH_WATER_MARK = 64 * 1024; // 64KB\n\n/** Maximum number of chunks in queue */\nexport const MAX_QUEUE_CHUNKS = 16;\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\nexport function createStreamStateRegistry(): StreamStateRegistry {\n const streams = new Map<number, StreamState>();\n const cleanups = new Map<number, () => Promise<void>>();\n let nextStreamId = 1;\n\n return {\n create(): number {\n const streamId = nextStreamId++;\n streams.set(streamId, {\n queue: [],\n queueSize: 0,\n closed: false,\n errored: false,\n errorValue: undefined,\n pullWaiting: false,\n pullResolve: null,\n pullReject: null,\n });\n return streamId;\n },\n\n get(streamId: number): StreamState | undefined {\n return streams.get(streamId);\n },\n\n push(streamId: number, chunk: Uint8Array): boolean {\n const state = streams.get(streamId);\n if (!state) return false;\n if (state.closed || state.errored) return false;\n\n // If a pull is waiting, deliver directly\n if (state.pullWaiting && state.pullResolve) {\n state.pullWaiting = false;\n const resolve = state.pullResolve;\n state.pullResolve = null;\n state.pullReject = null;\n resolve(chunk);\n return true;\n }\n\n // Otherwise queue the chunk\n state.queue.push(chunk);\n state.queueSize += chunk.length;\n return true;\n },\n\n async pull(\n streamId: number\n ): Promise<{ value: Uint8Array; done: false } | { done: true }> {\n const state = streams.get(streamId);\n if (!state) {\n return { done: true };\n }\n\n // If queue has data, return it first (even if stream is errored)\n if (state.queue.length > 0) {\n const chunk = state.queue.shift()!;\n state.queueSize -= chunk.length;\n return { value: chunk, done: false };\n }\n\n // If errored (and queue is empty), throw\n if (state.errored) {\n throw state.errorValue;\n }\n\n // If closed and queue empty, we're done\n if (state.closed) {\n return { done: true };\n }\n\n // Wait for data\n return new Promise((resolve, reject) => {\n state.pullWaiting = true;\n state.pullResolve = (chunk) => {\n if (chunk === null) {\n resolve({ done: true });\n } else {\n resolve({ value: chunk, done: false });\n }\n };\n state.pullReject = reject;\n });\n },\n\n close(streamId: number): void {\n const state = streams.get(streamId);\n if (!state) return;\n\n state.closed = true;\n\n // If a pull is waiting, resolve with done\n if (state.pullWaiting && state.pullResolve) {\n state.pullWaiting = false;\n const resolve = state.pullResolve;\n state.pullResolve = null;\n state.pullReject = null;\n resolve(null);\n }\n },\n\n error(streamId: number, errorValue: unknown): void {\n const state = streams.get(streamId);\n if (!state) return;\n\n state.errored = true;\n state.errorValue = errorValue;\n\n // If a pull is waiting, reject it\n if (state.pullWaiting && state.pullReject) {\n state.pullWaiting = false;\n const reject = state.pullReject;\n state.pullResolve = null;\n state.pullReject = null;\n reject(errorValue);\n }\n },\n\n isQueueFull(streamId: number): boolean {\n const state = streams.get(streamId);\n if (!state) return true;\n return (\n state.queueSize >= HIGH_WATER_MARK ||\n state.queue.length >= MAX_QUEUE_CHUNKS\n );\n },\n\n delete(streamId: number): void {\n const state = streams.get(streamId);\n if (state && state.pullWaiting && state.pullReject) {\n state.pullReject(new Error(\"Stream deleted\"));\n }\n streams.delete(streamId);\n cleanups.delete(streamId);\n },\n\n clear(): void {\n for (const [streamId] of streams) {\n const cleanup = cleanups.get(streamId);\n if (cleanup) {\n cleanup().catch(() => {});\n cleanups.delete(streamId);\n }\n this.delete(streamId);\n }\n },\n\n cancel(streamId: number): void {\n this.close(streamId);\n const cleanup = cleanups.get(streamId);\n if (cleanup) {\n cleanup().catch(() => {});\n cleanups.delete(streamId);\n }\n },\n\n setCleanup(streamId: number, cleanup: () => Promise<void>): void {\n cleanups.set(streamId, cleanup);\n },\n };\n}\n\n// ============================================================================\n// Context-Scoped Registry\n// ============================================================================\n\nconst contextRegistries = new WeakMap<ivm.Context, StreamStateRegistry>();\n\nexport function getStreamRegistryForContext(\n context: ivm.Context\n): StreamStateRegistry {\n let registry = contextRegistries.get(context);\n if (!registry) {\n registry = createStreamStateRegistry();\n contextRegistries.set(context, registry);\n }\n return registry;\n}\n\nexport function clearStreamRegistryForContext(context: ivm.Context): void {\n const registry = contextRegistries.get(context);\n if (registry) {\n registry.clear();\n contextRegistries.delete(context);\n }\n}\n\n// ============================================================================\n// Native Stream Reader\n// ============================================================================\n\n/**\n * Start reading from a native ReadableStream and push to host queue.\n * Respects backpressure by pausing when queue is full.\n *\n * @param nativeStream The native ReadableStream to read from\n * @param streamId The stream ID in the registry\n * @param registry The stream state registry\n * @returns Async cleanup function to cancel the reader\n */\nexport function startNativeStreamReader(\n nativeStream: ReadableStream<Uint8Array>,\n streamId: number,\n registry: StreamStateRegistry\n): () => Promise<void> {\n let cancelled = false;\n let reader: ReadableStreamDefaultReader<Uint8Array> | null = null;\n let readLoopPromise: Promise<void> | null = null;\n\n const CHUNK_SIZE = 64 * 1024; // 64KB max chunk size\n\n async function readLoop() {\n try {\n reader = nativeStream.getReader();\n\n while (!cancelled) {\n // Respect backpressure - wait if queue is full\n while (registry.isQueueFull(streamId) && !cancelled) {\n await new Promise((resolve) => setTimeout(resolve, 1));\n }\n if (cancelled) break;\n\n const { done, value } = await reader.read();\n\n if (done) {\n registry.close(streamId);\n break;\n }\n\n if (value) {\n // Split large chunks to maintain granularity\n if (value.length > CHUNK_SIZE) {\n for (let offset = 0; offset < value.length; offset += CHUNK_SIZE) {\n const chunk = value.slice(\n offset,\n Math.min(offset + CHUNK_SIZE, value.length)\n );\n registry.push(streamId, chunk);\n }\n } else {\n registry.push(streamId, value);\n }\n }\n }\n } catch (error) {\n registry.error(streamId, error);\n } finally {\n if (reader) {\n try {\n reader.releaseLock();\n } catch {\n // Ignore release errors\n }\n }\n }\n }\n\n // Start the read loop and save the promise\n readLoopPromise = readLoop();\n\n // Return async cleanup function\n return async () => {\n cancelled = true;\n if (reader) {\n try {\n await reader.cancel();\n } catch {\n // Ignore cancel errors\n }\n }\n // Wait for read loop to finish\n if (readLoopPromise) {\n try {\n await readLoopPromise;\n } catch {\n // Ignore read loop errors during cleanup\n }\n }\n };\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "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",
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "03C33CB0D90F624664756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -110,6 +110,21 @@ async function createConsistencyTestContext() {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
});
|
|
113
|
+
await runtime.eval(`
|
|
114
|
+
globalThis.__consistencyPendingTasks = new Set();
|
|
115
|
+
globalThis.__consistencyCleanupFns = [];
|
|
116
|
+
globalThis.__consistencyTrackTask = function(task) {
|
|
117
|
+
globalThis.__consistencyPendingTasks.add(task);
|
|
118
|
+
task.finally(() => {
|
|
119
|
+
globalThis.__consistencyPendingTasks.delete(task);
|
|
120
|
+
});
|
|
121
|
+
return task;
|
|
122
|
+
};
|
|
123
|
+
globalThis.__consistencyRegisterCleanup = function(cleanup) {
|
|
124
|
+
globalThis.__consistencyCleanupFns.push(cleanup);
|
|
125
|
+
return cleanup;
|
|
126
|
+
};
|
|
127
|
+
`);
|
|
113
128
|
return {
|
|
114
129
|
runtime,
|
|
115
130
|
eval: runtime.eval.bind(runtime),
|
|
@@ -124,6 +139,27 @@ async function createConsistencyTestContext() {
|
|
|
124
139
|
storedResult = undefined;
|
|
125
140
|
},
|
|
126
141
|
async dispose() {
|
|
142
|
+
try {
|
|
143
|
+
await runtime.eval(`
|
|
144
|
+
const cleanupFns = globalThis.__consistencyCleanupFns ?? [];
|
|
145
|
+
while (cleanupFns.length > 0) {
|
|
146
|
+
const cleanup = cleanupFns.pop();
|
|
147
|
+
if (!cleanup) continue;
|
|
148
|
+
try {
|
|
149
|
+
await cleanup();
|
|
150
|
+
} catch {
|
|
151
|
+
// Ignore cleanup races during test teardown.
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const pendingTasks = globalThis.__consistencyPendingTasks
|
|
156
|
+
? Array.from(globalThis.__consistencyPendingTasks)
|
|
157
|
+
: [];
|
|
158
|
+
if (pendingTasks.length > 0) {
|
|
159
|
+
await Promise.allSettled(pendingTasks);
|
|
160
|
+
}
|
|
161
|
+
`);
|
|
162
|
+
} catch {}
|
|
127
163
|
await runtime.dispose();
|
|
128
164
|
}
|
|
129
165
|
};
|
|
@@ -324,15 +360,32 @@ async function getReadableStreamFromOrigin(ctx, origin, chunks = ["chunk1", "chu
|
|
|
324
360
|
await ctx.eval(`
|
|
325
361
|
const transform = new TransformStream();
|
|
326
362
|
globalThis.__testReadableStream = transform.readable;
|
|
327
|
-
// Write chunks to writable side and close it
|
|
328
363
|
const writer = transform.writable.getWriter();
|
|
364
|
+
__consistencyRegisterCleanup(async () => {
|
|
365
|
+
try {
|
|
366
|
+
await writer.abort();
|
|
367
|
+
} catch {
|
|
368
|
+
// Ignore duplicate cleanup races.
|
|
369
|
+
}
|
|
370
|
+
try {
|
|
371
|
+
writer.releaseLock();
|
|
372
|
+
} catch {
|
|
373
|
+
// Ignore release races during teardown.
|
|
374
|
+
}
|
|
375
|
+
});
|
|
329
376
|
const chunks = ${chunksJson};
|
|
330
|
-
(async () => {
|
|
377
|
+
__consistencyTrackTask((async () => {
|
|
331
378
|
for (const chunk of chunks) {
|
|
332
379
|
await writer.write(new TextEncoder().encode(chunk));
|
|
333
380
|
}
|
|
334
381
|
await writer.close();
|
|
335
|
-
})()
|
|
382
|
+
})().finally(() => {
|
|
383
|
+
try {
|
|
384
|
+
writer.releaseLock();
|
|
385
|
+
} catch {
|
|
386
|
+
// Ignore release races after the task settles.
|
|
387
|
+
}
|
|
388
|
+
}));
|
|
336
389
|
`);
|
|
337
390
|
break;
|
|
338
391
|
}
|
|
@@ -359,14 +412,31 @@ async function getWritableStreamFromOrigin(ctx, origin) {
|
|
|
359
412
|
}
|
|
360
413
|
});
|
|
361
414
|
globalThis.__testWritableStream = transform.writable;
|
|
362
|
-
// Start reading to allow writes to complete
|
|
363
415
|
const reader = transform.readable.getReader();
|
|
364
|
-
(async () => {
|
|
416
|
+
__consistencyRegisterCleanup(async () => {
|
|
417
|
+
try {
|
|
418
|
+
await reader.cancel();
|
|
419
|
+
} catch {
|
|
420
|
+
// Ignore duplicate cleanup races.
|
|
421
|
+
}
|
|
422
|
+
try {
|
|
423
|
+
reader.releaseLock();
|
|
424
|
+
} catch {
|
|
425
|
+
// Ignore release races during teardown.
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
__consistencyTrackTask((async () => {
|
|
365
429
|
while (true) {
|
|
366
430
|
const { done } = await reader.read();
|
|
367
431
|
if (done) break;
|
|
368
432
|
}
|
|
369
|
-
})()
|
|
433
|
+
})().finally(() => {
|
|
434
|
+
try {
|
|
435
|
+
reader.releaseLock();
|
|
436
|
+
} catch {
|
|
437
|
+
// Ignore release races after the task settles.
|
|
438
|
+
}
|
|
439
|
+
}));
|
|
370
440
|
`);
|
|
371
441
|
break;
|
|
372
442
|
}
|
|
@@ -485,4 +555,4 @@ export {
|
|
|
485
555
|
ABORT_CONTROLLER_ORIGINS
|
|
486
556
|
};
|
|
487
557
|
|
|
488
|
-
//# debugId=
|
|
558
|
+
//# debugId=86244895EE82125C64756E2164756E21
|
|
@@ -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": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "86244895EE82125C64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/mjs/index.mjs
CHANGED
|
@@ -3,7 +3,8 @@ import ivm from "isolated-vm";
|
|
|
3
3
|
import { setupCore, clearAllInstanceState } from "@ricsam/isolate-core";
|
|
4
4
|
import {
|
|
5
5
|
getStreamRegistryForContext,
|
|
6
|
-
startNativeStreamReader
|
|
6
|
+
startNativeStreamReader,
|
|
7
|
+
clearStreamRegistryForContext
|
|
7
8
|
} from "./stream-state.mjs";
|
|
8
9
|
var instanceStateMap = new WeakMap;
|
|
9
10
|
var passthruBodies = new WeakMap;
|
|
@@ -56,6 +57,13 @@ function releaseTrackedGlobalHandles(context) {
|
|
|
56
57
|
}
|
|
57
58
|
handles.clear();
|
|
58
59
|
}
|
|
60
|
+
function clearPassthruBodiesForContext(context) {
|
|
61
|
+
const map = passthruBodies.get(context);
|
|
62
|
+
if (!map)
|
|
63
|
+
return;
|
|
64
|
+
map.clear();
|
|
65
|
+
passthruBodies.delete(context);
|
|
66
|
+
}
|
|
59
67
|
var headersCode = `
|
|
60
68
|
(function() {
|
|
61
69
|
class Headers {
|
|
@@ -115,6 +123,12 @@ var headersCode = `
|
|
|
115
123
|
const sortedKeys = [...this.#headers.keys()].sort();
|
|
116
124
|
for (const key of sortedKeys) {
|
|
117
125
|
const [, values] = this.#headers.get(key);
|
|
126
|
+
if (key === 'set-cookie') {
|
|
127
|
+
for (const value of values) {
|
|
128
|
+
callback.call(thisArg, value, key, this);
|
|
129
|
+
}
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
118
132
|
callback.call(thisArg, values.join(', '), key, this);
|
|
119
133
|
}
|
|
120
134
|
}
|
|
@@ -123,6 +137,12 @@ var headersCode = `
|
|
|
123
137
|
const sortedKeys = [...this.#headers.keys()].sort();
|
|
124
138
|
for (const key of sortedKeys) {
|
|
125
139
|
const [, values] = this.#headers.get(key);
|
|
140
|
+
if (key === 'set-cookie') {
|
|
141
|
+
for (const value of values) {
|
|
142
|
+
yield [key, value];
|
|
143
|
+
}
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
126
146
|
yield [key, values.join(', ')];
|
|
127
147
|
}
|
|
128
148
|
}
|
|
@@ -138,6 +158,12 @@ var headersCode = `
|
|
|
138
158
|
const sortedKeys = [...this.#headers.keys()].sort();
|
|
139
159
|
for (const key of sortedKeys) {
|
|
140
160
|
const [, values] = this.#headers.get(key);
|
|
161
|
+
if (key === 'set-cookie') {
|
|
162
|
+
for (const value of values) {
|
|
163
|
+
yield value;
|
|
164
|
+
}
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
141
167
|
yield values.join(', ');
|
|
142
168
|
}
|
|
143
169
|
}
|
|
@@ -2191,6 +2217,8 @@ async function setupFetch(context, options) {
|
|
|
2191
2217
|
return {
|
|
2192
2218
|
dispose() {
|
|
2193
2219
|
stateMap.clear();
|
|
2220
|
+
clearPassthruBodiesForContext(context);
|
|
2221
|
+
clearStreamRegistryForContext(context);
|
|
2194
2222
|
context.evalSync(`globalThis.__upgradeRegistry__.clear()`);
|
|
2195
2223
|
serveState.activeConnections.clear();
|
|
2196
2224
|
serveState.pendingUpgrade = null;
|
|
@@ -2549,4 +2577,4 @@ export {
|
|
|
2549
2577
|
clearAllInstanceState
|
|
2550
2578
|
};
|
|
2551
2579
|
|
|
2552
|
-
//# debugId=
|
|
2580
|
+
//# debugId=5A069524D0B6F93C64756E2164756E21
|