@ricsam/quickjs-fetch 0.2.15 → 0.2.17
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/globals/headers.cjs +8 -51
- package/dist/cjs/globals/headers.cjs.map +3 -3
- package/dist/cjs/globals/request.cjs +28 -6
- package/dist/cjs/globals/request.cjs.map +3 -3
- package/dist/cjs/globals/response.cjs +41 -6
- package/dist/cjs/globals/response.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/setup.cjs +3 -1
- package/dist/cjs/setup.cjs.map +3 -3
- package/dist/mjs/globals/headers.mjs +9 -52
- package/dist/mjs/globals/headers.mjs.map +3 -3
- package/dist/mjs/globals/request.mjs +29 -7
- package/dist/mjs/globals/request.mjs.map +3 -3
- package/dist/mjs/globals/response.mjs +43 -7
- package/dist/mjs/globals/response.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/setup.mjs +5 -3
- package/dist/mjs/setup.mjs.map +3 -3
- package/dist/types/globals/headers.d.ts +0 -21
- package/dist/types/globals/request.d.ts +9 -0
- package/dist/types/globals/response.d.ts +9 -0
- package/package.json +2 -2
package/dist/cjs/package.json
CHANGED
package/dist/cjs/setup.cjs
CHANGED
|
@@ -133,6 +133,8 @@ function setupFetch(context, options = {}) {
|
|
|
133
133
|
import_request.addRequestFormDataMethod(context);
|
|
134
134
|
import_request.addRequestCloneMethod(context);
|
|
135
135
|
import_response.addResponseCloneMethod(context);
|
|
136
|
+
import_request.addRequestHeadersGetter(context);
|
|
137
|
+
import_response.addResponseHeadersGetter(context);
|
|
136
138
|
import_form_data.addFormDataFileMethods(context);
|
|
137
139
|
const ServerWebSocketClass = import_serve.createServerWebSocketClass(context, stateMap, dispatchWsCommand);
|
|
138
140
|
context.setProp(context.global, "__ServerWebSocket__", ServerWebSocketClass);
|
|
@@ -200,4 +202,4 @@ function setupFetch(context, options = {}) {
|
|
|
200
202
|
}
|
|
201
203
|
})
|
|
202
204
|
|
|
203
|
-
//# debugId=
|
|
205
|
+
//# debugId=69084328C5578CAD64756E2164756E21
|
package/dist/cjs/setup.cjs.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/setup.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport { setupCore, createStateMap, createReadableStream } from \"@ricsam/quickjs-core\";\nimport type { SetupFetchOptions, FetchHandle, ServeState } from \"./types.cjs\";\nimport { createHeadersClass } from \"./globals/headers.cjs\";\nimport { createRequestClass, addRequestFormDataMethod, addRequestCloneMethod } from \"./globals/request.cjs\";\nimport { createResponseClass, addResponseStaticMethods, addResponseCloneMethod } from \"./globals/response.cjs\";\nimport { setupAbortControllerAndSignal } from \"./globals/abort-controller.cjs\";\nimport { createFormDataClass, addFormDataFileMethods } from \"./globals/form-data.cjs\";\nimport { createFetchFunction } from \"./globals/fetch.cjs\";\nimport {\n createServeFunction,\n createServerClass,\n createServerWebSocketClass,\n} from \"./globals/serve.cjs\";\nimport { createFetchHandle } from \"./handle.cjs\";\n\n/**\n * Setup Fetch API in a QuickJS context\n *\n * Injects the following globals:\n * - fetch\n * - Request\n * - Response\n * - Headers\n * - AbortController\n * - AbortSignal\n * - serve\n * - FormData\n *\n * Also sets up Core APIs (Streams, Blob, File) if not already present.\n *\n * **Private globals (internal use):**\n * - `__Server__` - Server class for serve() handler, instantiated via evalCode\n * - `__ServerWebSocket__` - WebSocket class for connection handling\n * - `__scheduleTimeout__` - Host function to schedule AbortSignal.timeout()\n * - `__checkTimeout__` - Host function to check if timeout elapsed\n *\n * These private globals follow the `__Name__` convention and are required for\n * JavaScript code in QuickJS to create class instances via evalCode.\n * See PATTERNS.md section 5 for details.\n *\n * @example\n * const handle = setupFetch(context, {\n * onFetch: async (request) => {\n * // Proxy to real fetch\n * return fetch(request);\n * }\n * });\n *\n * context.evalCode(`\n * serve({\n * fetch(request, server) {\n * return new Response(\"Hello!\");\n * }\n * });\n * `);\n *\n * const response = await handle.dispatchRequest(\n * new Request(\"http://localhost/\")\n * );\n */\nexport function setupFetch(\n context: QuickJSContext,\n options: SetupFetchOptions = {}\n): FetchHandle {\n // Setup core if not already done\n const coreHandle =\n options.coreHandle ??\n setupCore(context, {\n stateMap: options.stateMap,\n });\n\n const stateMap = options.stateMap ?? coreHandle.stateMap;\n\n // Create serve state\n const serveState: ServeState = {\n fetchHandler: null,\n websocketHandlers: {},\n pendingUpgrade: null,\n activeConnections: new Map(),\n };\n\n // WebSocket command dispatcher\n const wsCommandCallbacks = new Set<\n (cmd: import(\"./types.cjs\").WebSocketCommand) => void\n >();\n const dispatchWsCommand = (cmd: import(\"./types.cjs\").WebSocketCommand) => {\n for (const cb of wsCommandCallbacks) {\n cb(cmd);\n }\n };\n\n // Create stream factory for Request/Response body\n const streamFactory = (source: UnderlyingSource) =>\n createReadableStream(context, stateMap, source);\n\n // Create stream helpers for upload streaming\n const streamHelpers = {\n createStream: streamFactory,\n /**\n * Create an empty ReadableStream for upload streaming.\n *\n * IMPORTANT: We store the stream on a global variable and return the key.\n * This is necessary because __hostCall__ manages and disposes returned handles\n * in its scope. If we cached the handle and returned it multiple times,\n * subsequent calls would return a dead handle.\n *\n * The getter must call getStreamByKey() each time to get a fresh handle.\n */\n createEmptyStream: (): { instanceId: number; globalKey: string } => {\n const globalKey = `__uploadStream_${Date.now()}_${Math.random().toString(36).slice(2)}__`;\n const result = context.evalCode(`\n (function() {\n const stream = new ReadableStream();\n globalThis[\"${globalKey}\"] = stream;\n return stream.__instanceId__;\n })()\n `);\n if (result.error) {\n const error = context.dump(result.error);\n result.error.dispose();\n throw new Error(`Failed to create empty ReadableStream: ${JSON.stringify(error)}`);\n }\n const instanceId = context.getNumber(result.value);\n result.value.dispose();\n\n return { instanceId, globalKey };\n },\n /**\n * Get a fresh handle to the stream stored at globalKey.\n * This must be called each time the body getter is accessed to avoid\n * returning disposed handles.\n */\n getStreamByKey: (globalKey: string): import(\"quickjs-emscripten\").QuickJSHandle | null => {\n const result = context.evalCode(`globalThis[\"${globalKey}\"]`);\n if (result.error) {\n result.error.dispose();\n return null;\n }\n if (context.typeof(result.value) === \"undefined\") {\n result.value.dispose();\n return null;\n }\n return result.value;\n },\n pumpEventLoop: () => {\n context.runtime.executePendingJobs();\n },\n };\n\n // Create Headers class\n const HeadersClass = createHeadersClass(context, stateMap);\n context.setProp(context.global, \"Headers\", HeadersClass);\n HeadersClass.dispose();\n\n // Add Symbol.iterator support for Headers (for...of, Array.from, spread)\n const iteratorResult = context.evalCode(`\n Headers.prototype[Symbol.iterator] = function() {\n return this.entries()[Symbol.iterator]();\n };\n `);\n if (iteratorResult.error) {\n iteratorResult.error.dispose();\n } else {\n iteratorResult.value.dispose();\n }\n\n // Create Request class\n const RequestClass = createRequestClass(context, stateMap, streamHelpers);\n context.setProp(context.global, \"Request\", RequestClass);\n RequestClass.dispose();\n\n // Note: No body getter wrapper needed - handles are returned directly\n // through __hostCall__ because quickjs-emscripten properly duplicates\n // handles via QTS_DupValuePointer before returning to QuickJS.\n\n // Create Response class\n const ResponseClass = createResponseClass(context, stateMap, streamFactory);\n context.setProp(context.global, \"Response\", ResponseClass);\n ResponseClass.dispose();\n\n // Add Response static methods (must be after Response and Headers are on global)\n addResponseStaticMethods(context);\n\n // Create AbortSignal and AbortController classes (pure QuickJS implementation)\n setupAbortControllerAndSignal(context);\n\n // Create FormData class\n const FormDataClass = createFormDataClass(context, stateMap);\n context.setProp(context.global, \"FormData\", FormDataClass);\n FormDataClass.dispose();\n\n // Add Symbol.iterator support for FormData (for...of, Array.from, spread)\n const formDataIteratorResult = context.evalCode(`\n FormData.prototype[Symbol.iterator] = function() {\n return this.entries()[Symbol.iterator]();\n };\n `);\n if (formDataIteratorResult.error) {\n formDataIteratorResult.error.dispose();\n } else {\n formDataIteratorResult.value.dispose();\n }\n\n // Add Request.formData() method that returns a proper FormData instance\n // Must be after both Request and FormData are on global\n addRequestFormDataMethod(context);\n\n // Add Request.clone() method that returns a proper Request instance\n // Must be after Request and Headers are on global\n addRequestCloneMethod(context);\n\n // Add Response.clone() method that returns a proper Response instance\n // Must be after Response and Headers are on global\n addResponseCloneMethod(context);\n\n // Add FormData.get()/getAll() overrides to reconstruct File instances\n // Must be after both FormData and File are on global\n addFormDataFileMethods(context);\n\n // Create ServerWebSocket class (internal, for WebSocket handling)\n const ServerWebSocketClass = createServerWebSocketClass(\n context,\n stateMap,\n dispatchWsCommand\n );\n // Set on global with internal name so we can use evalCode to instantiate\n context.setProp(context.global, \"__ServerWebSocket__\", ServerWebSocketClass);\n ServerWebSocketClass.dispose();\n // Note: ServerWebSocketClass handle is now owned by global\n\n // Add pure-JS data getter to ServerWebSocket prototype\n // This getter reads from __upgradeRegistry__ using __connectionId__,\n // keeping complex data (like Zod schemas) entirely within QuickJS\n // to avoid marshalling depth limit issues\n const dataGetterResult = context.evalCode(`\n Object.defineProperty(__ServerWebSocket__.prototype, 'data', {\n get: function() {\n return __upgradeRegistry__.get(this.__connectionId__);\n },\n enumerable: true,\n configurable: true\n });\n `);\n if (dataGetterResult.error) {\n dataGetterResult.error.dispose();\n } else {\n dataGetterResult.value.dispose();\n }\n\n // Create Server class (internal, passed to fetch handler)\n const ServerClass = createServerClass(context, stateMap, serveState);\n // Set on global with internal name so we can use evalCode to instantiate\n context.setProp(context.global, \"__Server__\", ServerClass);\n ServerClass.dispose();\n // Note: ServerClass handle is now owned by global\n\n // Setup upgrade registry and helper function for WebSocket upgrades\n // The registry keeps data within QuickJS to avoid marshalling complex objects\n const registryResult = context.evalCode(`\n globalThis.__upgradeRegistry__ = new Map();\n globalThis.__upgradeIdCounter__ = 0;\n `);\n if (registryResult.error) {\n registryResult.error.dispose();\n } else {\n registryResult.value.dispose();\n }\n\n // Host function to set pendingUpgrade - only receives connectionId string\n const setPendingUpgradeFn = context.newFunction(\n \"__setPendingUpgrade__\",\n (connIdHandle) => {\n const connectionId = context.getString(connIdHandle);\n serveState.pendingUpgrade = { requested: true, connectionId };\n return context.undefined;\n }\n );\n context.setProp(context.global, \"__setPendingUpgrade__\", setPendingUpgradeFn);\n setPendingUpgradeFn.dispose();\n\n // Add upgrade method to Server prototype as pure JavaScript\n // This keeps the data within QuickJS and only passes connectionId to host\n const upgradeMethodResult = context.evalCode(`\n __Server__.prototype.upgrade = function(request, options) {\n const data = options && typeof options === 'object' ? options.data : undefined;\n const connectionId = String(++globalThis.__upgradeIdCounter__);\n globalThis.__upgradeRegistry__.set(connectionId, data);\n __setPendingUpgrade__(connectionId);\n return true;\n };\n `);\n if (upgradeMethodResult.error) {\n upgradeMethodResult.error.dispose();\n } else {\n upgradeMethodResult.value.dispose();\n }\n\n // Create fetch function\n const fetchFn = createFetchFunction(context, options.onFetch);\n context.setProp(context.global, \"fetch\", fetchFn);\n fetchFn.dispose();\n\n // Create serve function\n const serveFn = createServeFunction(context, stateMap, serveState);\n context.setProp(context.global, \"serve\", serveFn);\n serveFn.dispose();\n\n // Create and return the handle\n const fetchHandle = createFetchHandle(\n context,\n stateMap,\n serveState\n );\n\n // Wire up WebSocket command callbacks\n const originalOnWebSocketCommand = fetchHandle.onWebSocketCommand;\n fetchHandle.onWebSocketCommand = (callback) => {\n wsCommandCallbacks.add(callback);\n return () => wsCommandCallbacks.delete(callback);\n };\n\n return fetchHandle;\n}\n"
|
|
5
|
+
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport { setupCore, createStateMap, createReadableStream } from \"@ricsam/quickjs-core\";\nimport type { SetupFetchOptions, FetchHandle, ServeState } from \"./types.cjs\";\nimport { createHeadersClass } from \"./globals/headers.cjs\";\nimport { createRequestClass, addRequestFormDataMethod, addRequestCloneMethod, addRequestHeadersGetter } from \"./globals/request.cjs\";\nimport { createResponseClass, addResponseStaticMethods, addResponseCloneMethod, addResponseHeadersGetter } from \"./globals/response.cjs\";\nimport { setupAbortControllerAndSignal } from \"./globals/abort-controller.cjs\";\nimport { createFormDataClass, addFormDataFileMethods } from \"./globals/form-data.cjs\";\nimport { createFetchFunction } from \"./globals/fetch.cjs\";\nimport {\n createServeFunction,\n createServerClass,\n createServerWebSocketClass,\n} from \"./globals/serve.cjs\";\nimport { createFetchHandle } from \"./handle.cjs\";\n\n/**\n * Setup Fetch API in a QuickJS context\n *\n * Injects the following globals:\n * - fetch\n * - Request\n * - Response\n * - Headers\n * - AbortController\n * - AbortSignal\n * - serve\n * - FormData\n *\n * Also sets up Core APIs (Streams, Blob, File) if not already present.\n *\n * **Private globals (internal use):**\n * - `__Server__` - Server class for serve() handler, instantiated via evalCode\n * - `__ServerWebSocket__` - WebSocket class for connection handling\n * - `__scheduleTimeout__` - Host function to schedule AbortSignal.timeout()\n * - `__checkTimeout__` - Host function to check if timeout elapsed\n *\n * These private globals follow the `__Name__` convention and are required for\n * JavaScript code in QuickJS to create class instances via evalCode.\n * See PATTERNS.md section 5 for details.\n *\n * @example\n * const handle = setupFetch(context, {\n * onFetch: async (request) => {\n * // Proxy to real fetch\n * return fetch(request);\n * }\n * });\n *\n * context.evalCode(`\n * serve({\n * fetch(request, server) {\n * return new Response(\"Hello!\");\n * }\n * });\n * `);\n *\n * const response = await handle.dispatchRequest(\n * new Request(\"http://localhost/\")\n * );\n */\nexport function setupFetch(\n context: QuickJSContext,\n options: SetupFetchOptions = {}\n): FetchHandle {\n // Setup core if not already done\n const coreHandle =\n options.coreHandle ??\n setupCore(context, {\n stateMap: options.stateMap,\n });\n\n const stateMap = options.stateMap ?? coreHandle.stateMap;\n\n // Create serve state\n const serveState: ServeState = {\n fetchHandler: null,\n websocketHandlers: {},\n pendingUpgrade: null,\n activeConnections: new Map(),\n };\n\n // WebSocket command dispatcher\n const wsCommandCallbacks = new Set<\n (cmd: import(\"./types.cjs\").WebSocketCommand) => void\n >();\n const dispatchWsCommand = (cmd: import(\"./types.cjs\").WebSocketCommand) => {\n for (const cb of wsCommandCallbacks) {\n cb(cmd);\n }\n };\n\n // Create stream factory for Request/Response body\n const streamFactory = (source: UnderlyingSource) =>\n createReadableStream(context, stateMap, source);\n\n // Create stream helpers for upload streaming\n const streamHelpers = {\n createStream: streamFactory,\n /**\n * Create an empty ReadableStream for upload streaming.\n *\n * IMPORTANT: We store the stream on a global variable and return the key.\n * This is necessary because __hostCall__ manages and disposes returned handles\n * in its scope. If we cached the handle and returned it multiple times,\n * subsequent calls would return a dead handle.\n *\n * The getter must call getStreamByKey() each time to get a fresh handle.\n */\n createEmptyStream: (): { instanceId: number; globalKey: string } => {\n const globalKey = `__uploadStream_${Date.now()}_${Math.random().toString(36).slice(2)}__`;\n const result = context.evalCode(`\n (function() {\n const stream = new ReadableStream();\n globalThis[\"${globalKey}\"] = stream;\n return stream.__instanceId__;\n })()\n `);\n if (result.error) {\n const error = context.dump(result.error);\n result.error.dispose();\n throw new Error(`Failed to create empty ReadableStream: ${JSON.stringify(error)}`);\n }\n const instanceId = context.getNumber(result.value);\n result.value.dispose();\n\n return { instanceId, globalKey };\n },\n /**\n * Get a fresh handle to the stream stored at globalKey.\n * This must be called each time the body getter is accessed to avoid\n * returning disposed handles.\n */\n getStreamByKey: (globalKey: string): import(\"quickjs-emscripten\").QuickJSHandle | null => {\n const result = context.evalCode(`globalThis[\"${globalKey}\"]`);\n if (result.error) {\n result.error.dispose();\n return null;\n }\n if (context.typeof(result.value) === \"undefined\") {\n result.value.dispose();\n return null;\n }\n return result.value;\n },\n pumpEventLoop: () => {\n context.runtime.executePendingJobs();\n },\n };\n\n // Create Headers class\n const HeadersClass = createHeadersClass(context, stateMap);\n context.setProp(context.global, \"Headers\", HeadersClass);\n HeadersClass.dispose();\n\n // Add Symbol.iterator support for Headers (for...of, Array.from, spread)\n const iteratorResult = context.evalCode(`\n Headers.prototype[Symbol.iterator] = function() {\n return this.entries()[Symbol.iterator]();\n };\n `);\n if (iteratorResult.error) {\n iteratorResult.error.dispose();\n } else {\n iteratorResult.value.dispose();\n }\n\n // Create Request class\n const RequestClass = createRequestClass(context, stateMap, streamHelpers);\n context.setProp(context.global, \"Request\", RequestClass);\n RequestClass.dispose();\n\n // Note: No body getter wrapper needed - handles are returned directly\n // through __hostCall__ because quickjs-emscripten properly duplicates\n // handles via QTS_DupValuePointer before returning to QuickJS.\n\n // Create Response class\n const ResponseClass = createResponseClass(context, stateMap, streamFactory);\n context.setProp(context.global, \"Response\", ResponseClass);\n ResponseClass.dispose();\n\n // Add Response static methods (must be after Response and Headers are on global)\n addResponseStaticMethods(context);\n\n // Create AbortSignal and AbortController classes (pure QuickJS implementation)\n setupAbortControllerAndSignal(context);\n\n // Create FormData class\n const FormDataClass = createFormDataClass(context, stateMap);\n context.setProp(context.global, \"FormData\", FormDataClass);\n FormDataClass.dispose();\n\n // Add Symbol.iterator support for FormData (for...of, Array.from, spread)\n const formDataIteratorResult = context.evalCode(`\n FormData.prototype[Symbol.iterator] = function() {\n return this.entries()[Symbol.iterator]();\n };\n `);\n if (formDataIteratorResult.error) {\n formDataIteratorResult.error.dispose();\n } else {\n formDataIteratorResult.value.dispose();\n }\n\n // Add Request.formData() method that returns a proper FormData instance\n // Must be after both Request and FormData are on global\n addRequestFormDataMethod(context);\n\n // Add Request.clone() method that returns a proper Request instance\n // Must be after Request and Headers are on global\n addRequestCloneMethod(context);\n\n // Add Response.clone() method that returns a proper Response instance\n // Must be after Response and Headers are on global\n addResponseCloneMethod(context);\n\n // Add Request.headers getter that returns a proper Headers instance\n // Must be after both Request and Headers are on global\n addRequestHeadersGetter(context);\n\n // Add Response.headers getter that returns a proper Headers instance\n // Must be after both Response and Headers are on global\n addResponseHeadersGetter(context);\n\n // Add FormData.get()/getAll() overrides to reconstruct File instances\n // Must be after both FormData and File are on global\n addFormDataFileMethods(context);\n\n // Create ServerWebSocket class (internal, for WebSocket handling)\n const ServerWebSocketClass = createServerWebSocketClass(\n context,\n stateMap,\n dispatchWsCommand\n );\n // Set on global with internal name so we can use evalCode to instantiate\n context.setProp(context.global, \"__ServerWebSocket__\", ServerWebSocketClass);\n ServerWebSocketClass.dispose();\n // Note: ServerWebSocketClass handle is now owned by global\n\n // Add pure-JS data getter to ServerWebSocket prototype\n // This getter reads from __upgradeRegistry__ using __connectionId__,\n // keeping complex data (like Zod schemas) entirely within QuickJS\n // to avoid marshalling depth limit issues\n const dataGetterResult = context.evalCode(`\n Object.defineProperty(__ServerWebSocket__.prototype, 'data', {\n get: function() {\n return __upgradeRegistry__.get(this.__connectionId__);\n },\n enumerable: true,\n configurable: true\n });\n `);\n if (dataGetterResult.error) {\n dataGetterResult.error.dispose();\n } else {\n dataGetterResult.value.dispose();\n }\n\n // Create Server class (internal, passed to fetch handler)\n const ServerClass = createServerClass(context, stateMap, serveState);\n // Set on global with internal name so we can use evalCode to instantiate\n context.setProp(context.global, \"__Server__\", ServerClass);\n ServerClass.dispose();\n // Note: ServerClass handle is now owned by global\n\n // Setup upgrade registry and helper function for WebSocket upgrades\n // The registry keeps data within QuickJS to avoid marshalling complex objects\n const registryResult = context.evalCode(`\n globalThis.__upgradeRegistry__ = new Map();\n globalThis.__upgradeIdCounter__ = 0;\n `);\n if (registryResult.error) {\n registryResult.error.dispose();\n } else {\n registryResult.value.dispose();\n }\n\n // Host function to set pendingUpgrade - only receives connectionId string\n const setPendingUpgradeFn = context.newFunction(\n \"__setPendingUpgrade__\",\n (connIdHandle) => {\n const connectionId = context.getString(connIdHandle);\n serveState.pendingUpgrade = { requested: true, connectionId };\n return context.undefined;\n }\n );\n context.setProp(context.global, \"__setPendingUpgrade__\", setPendingUpgradeFn);\n setPendingUpgradeFn.dispose();\n\n // Add upgrade method to Server prototype as pure JavaScript\n // This keeps the data within QuickJS and only passes connectionId to host\n const upgradeMethodResult = context.evalCode(`\n __Server__.prototype.upgrade = function(request, options) {\n const data = options && typeof options === 'object' ? options.data : undefined;\n const connectionId = String(++globalThis.__upgradeIdCounter__);\n globalThis.__upgradeRegistry__.set(connectionId, data);\n __setPendingUpgrade__(connectionId);\n return true;\n };\n `);\n if (upgradeMethodResult.error) {\n upgradeMethodResult.error.dispose();\n } else {\n upgradeMethodResult.value.dispose();\n }\n\n // Create fetch function\n const fetchFn = createFetchFunction(context, options.onFetch);\n context.setProp(context.global, \"fetch\", fetchFn);\n fetchFn.dispose();\n\n // Create serve function\n const serveFn = createServeFunction(context, stateMap, serveState);\n context.setProp(context.global, \"serve\", serveFn);\n serveFn.dispose();\n\n // Create and return the handle\n const fetchHandle = createFetchHandle(\n context,\n stateMap,\n serveState\n );\n\n // Wire up WebSocket command callbacks\n const originalOnWebSocketCommand = fetchHandle.onWebSocketCommand;\n fetchHandle.onWebSocketCommand = (callback) => {\n wsCommandCallbacks.add(callback);\n return () => wsCommandCallbacks.delete(callback);\n };\n\n return fetchHandle;\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACgE,IAAhE;AAEmC,IAAnC;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "69084328C5578CAD64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/fetch/src/globals/headers.ts
|
|
3
|
-
import { defineClass, coerceHeaders } from "@ricsam/quickjs-core";
|
|
3
|
+
import { defineClass, coerceHeaders, getInstanceStateById } from "@ricsam/quickjs-core";
|
|
4
4
|
function createHeadersClass(context, stateMap) {
|
|
5
5
|
return defineClass(context, stateMap, {
|
|
6
6
|
name: "Headers",
|
|
@@ -59,6 +59,13 @@ function createHeadersClass(context, stateMap) {
|
|
|
59
59
|
},
|
|
60
60
|
getSetCookie() {
|
|
61
61
|
return this.headers.get("set-cookie") || [];
|
|
62
|
+
},
|
|
63
|
+
__linkToParent__(parentInstanceId) {
|
|
64
|
+
const id = typeof parentInstanceId === "number" ? parentInstanceId : 0;
|
|
65
|
+
const parentState = getInstanceStateById(id);
|
|
66
|
+
if (parentState?.headersState) {
|
|
67
|
+
this.headers = parentState.headersState.headers;
|
|
68
|
+
}
|
|
62
69
|
}
|
|
63
70
|
}
|
|
64
71
|
});
|
|
@@ -81,60 +88,10 @@ function headersStateToNative(state) {
|
|
|
81
88
|
}
|
|
82
89
|
return headers;
|
|
83
90
|
}
|
|
84
|
-
function createHeadersLike(state) {
|
|
85
|
-
return {
|
|
86
|
-
headers: state.headers,
|
|
87
|
-
append(name, value) {
|
|
88
|
-
const key = name.toLowerCase();
|
|
89
|
-
const existing = state.headers.get(key) || [];
|
|
90
|
-
existing.push(value);
|
|
91
|
-
state.headers.set(key, existing);
|
|
92
|
-
},
|
|
93
|
-
delete(name) {
|
|
94
|
-
state.headers.delete(name.toLowerCase());
|
|
95
|
-
},
|
|
96
|
-
get(name) {
|
|
97
|
-
const values = state.headers.get(name.toLowerCase());
|
|
98
|
-
return values ? values.join(", ") : null;
|
|
99
|
-
},
|
|
100
|
-
has(name) {
|
|
101
|
-
return state.headers.has(name.toLowerCase());
|
|
102
|
-
},
|
|
103
|
-
set(name, value) {
|
|
104
|
-
state.headers.set(name.toLowerCase(), [value]);
|
|
105
|
-
},
|
|
106
|
-
entries() {
|
|
107
|
-
const result = [];
|
|
108
|
-
for (const [key, values] of state.headers) {
|
|
109
|
-
result.push([key, values.join(", ")]);
|
|
110
|
-
}
|
|
111
|
-
return result;
|
|
112
|
-
},
|
|
113
|
-
keys() {
|
|
114
|
-
return Array.from(state.headers.keys());
|
|
115
|
-
},
|
|
116
|
-
values() {
|
|
117
|
-
const result = [];
|
|
118
|
-
for (const values of state.headers.values()) {
|
|
119
|
-
result.push(values.join(", "));
|
|
120
|
-
}
|
|
121
|
-
return result;
|
|
122
|
-
},
|
|
123
|
-
forEach(callback) {
|
|
124
|
-
for (const [key, values] of state.headers) {
|
|
125
|
-
callback(values.join(", "), key);
|
|
126
|
-
}
|
|
127
|
-
},
|
|
128
|
-
getSetCookie() {
|
|
129
|
-
return state.headers.get("set-cookie") || [];
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
91
|
export {
|
|
134
92
|
headersStateToNative,
|
|
135
93
|
createHeadersStateFromNative,
|
|
136
|
-
createHeadersLike,
|
|
137
94
|
createHeadersClass
|
|
138
95
|
};
|
|
139
96
|
|
|
140
|
-
//# debugId=
|
|
97
|
+
//# debugId=314BF006BE58B50F64756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/globals/headers.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { StateMap } from \"@ricsam/quickjs-core\";\nimport { defineClass, coerceHeaders } from \"@ricsam/quickjs-core\";\nimport type { HeadersState } from \"../types.mjs\";\n\n/**\n * Create the Headers class for QuickJS\n */\nexport function createHeadersClass(\n context: QuickJSContext,\n stateMap: StateMap\n): QuickJSHandle {\n return defineClass<HeadersState>(context, stateMap, {\n name: \"Headers\",\n construct: (args) => {\n const init = args[0];\n // Use coercion to handle all input types consistently\n const coerced = coerceHeaders.safeParse(init);\n if (coerced.success) {\n return coerced.value;\n }\n // Fallback to empty headers if coercion fails\n return { headers: new Map<string, string[]>() };\n },\n methods: {\n append(this: HeadersState, name: unknown, value: unknown) {\n const key = String(name).toLowerCase();\n const existing = this.headers.get(key) || [];\n existing.push(String(value));\n this.headers.set(key, existing);\n },\n delete(this: HeadersState, name: unknown) {\n this.headers.delete(String(name).toLowerCase());\n },\n get(this: HeadersState, name: unknown): string | null {\n const values = this.headers.get(String(name).toLowerCase());\n return values ? values.join(\", \") : null;\n },\n has(this: HeadersState, name: unknown): boolean {\n return this.headers.has(String(name).toLowerCase());\n },\n set(this: HeadersState, name: unknown, value: unknown) {\n this.headers.set(String(name).toLowerCase(), [String(value)]);\n },\n entries(this: HeadersState): Array<[string, string]> {\n const result: Array<[string, string]> = [];\n for (const [key, values] of this.headers) {\n result.push([key, values.join(\", \")]);\n }\n return result;\n },\n keys(this: HeadersState): string[] {\n return Array.from(this.headers.keys());\n },\n values(this: HeadersState): string[] {\n const result: string[] = [];\n for (const values of this.headers.values()) {\n result.push(values.join(\", \"));\n }\n return result;\n },\n forEach(this: HeadersState, callback: unknown) {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"callback must be a function\");\n }\n for (const [key, values] of this.headers) {\n (callback as (value: string, key: string, parent: HeadersState) => void)(\n values.join(\", \"),\n key,\n this\n );\n }\n },\n getSetCookie(this: HeadersState): string[] {\n return this.headers.get(\"set-cookie\") || [];\n },\n },\n });\n}\n\n/**\n * Create a HeadersState from a native Headers object\n */\nexport function createHeadersStateFromNative(headers: Headers): HeadersState {\n const map = new Map<string, string[]>();\n headers.forEach((value, key) => {\n const existing = map.get(key.toLowerCase()) || [];\n existing.push(value);\n map.set(key.toLowerCase(), existing);\n });\n return { headers: map };\n}\n\n/**\n * Convert HeadersState to native Headers\n */\nexport function headersStateToNative(state: HeadersState): Headers {\n const headers = new Headers();\n for (const [key, values] of state.headers) {\n for (const value of values) {\n headers.append(key, value);\n }\n }\n return headers;\n}\n\n
|
|
5
|
+
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { StateMap } from \"@ricsam/quickjs-core\";\nimport { defineClass, coerceHeaders, getInstanceStateById } from \"@ricsam/quickjs-core\";\nimport type { HeadersState } from \"../types.mjs\";\n\n/**\n * Create the Headers class for QuickJS\n */\nexport function createHeadersClass(\n context: QuickJSContext,\n stateMap: StateMap\n): QuickJSHandle {\n return defineClass<HeadersState>(context, stateMap, {\n name: \"Headers\",\n construct: (args) => {\n const init = args[0];\n // Use coercion to handle all input types consistently\n const coerced = coerceHeaders.safeParse(init);\n if (coerced.success) {\n return coerced.value;\n }\n // Fallback to empty headers if coercion fails\n return { headers: new Map<string, string[]>() };\n },\n methods: {\n append(this: HeadersState, name: unknown, value: unknown) {\n const key = String(name).toLowerCase();\n const existing = this.headers.get(key) || [];\n existing.push(String(value));\n this.headers.set(key, existing);\n },\n delete(this: HeadersState, name: unknown) {\n this.headers.delete(String(name).toLowerCase());\n },\n get(this: HeadersState, name: unknown): string | null {\n const values = this.headers.get(String(name).toLowerCase());\n return values ? values.join(\", \") : null;\n },\n has(this: HeadersState, name: unknown): boolean {\n return this.headers.has(String(name).toLowerCase());\n },\n set(this: HeadersState, name: unknown, value: unknown) {\n this.headers.set(String(name).toLowerCase(), [String(value)]);\n },\n entries(this: HeadersState): Array<[string, string]> {\n const result: Array<[string, string]> = [];\n for (const [key, values] of this.headers) {\n result.push([key, values.join(\", \")]);\n }\n return result;\n },\n keys(this: HeadersState): string[] {\n return Array.from(this.headers.keys());\n },\n values(this: HeadersState): string[] {\n const result: string[] = [];\n for (const values of this.headers.values()) {\n result.push(values.join(\", \"));\n }\n return result;\n },\n forEach(this: HeadersState, callback: unknown) {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"callback must be a function\");\n }\n for (const [key, values] of this.headers) {\n (callback as (value: string, key: string, parent: HeadersState) => void)(\n values.join(\", \"),\n key,\n this\n );\n }\n },\n getSetCookie(this: HeadersState): string[] {\n return this.headers.get(\"set-cookie\") || [];\n },\n /**\n * Private method to link this Headers instance to a parent Request/Response.\n * Called from the cached headers getter to share state.\n */\n __linkToParent__(this: HeadersState, parentInstanceId: unknown) {\n const id = typeof parentInstanceId === \"number\" ? parentInstanceId : 0;\n const parentState = getInstanceStateById<{ headersState: HeadersState }>(id);\n if (parentState?.headersState) {\n this.headers = parentState.headersState.headers;\n }\n },\n },\n });\n}\n\n/**\n * Create a HeadersState from a native Headers object\n */\nexport function createHeadersStateFromNative(headers: Headers): HeadersState {\n const map = new Map<string, string[]>();\n headers.forEach((value, key) => {\n const existing = map.get(key.toLowerCase()) || [];\n existing.push(value);\n map.set(key.toLowerCase(), existing);\n });\n return { headers: map };\n}\n\n/**\n * Convert HeadersState to native Headers\n */\nexport function headersStateToNative(state: HeadersState): Headers {\n const headers = new Headers();\n for (const [key, values] of state.headers) {\n for (const value of values) {\n headers.append(key, value);\n }\n }\n return headers;\n}\n\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;AAEA;AAMO,SAAS,kBAAkB,CAChC,SACA,UACe;AAAA,EACf,OAAO,YAA0B,SAAS,UAAU;AAAA,IAClD,MAAM;AAAA,IACN,WAAW,CAAC,SAAS;AAAA,MACnB,MAAM,OAAO,KAAK;AAAA,MAElB,MAAM,UAAU,cAAc,UAAU,IAAI;AAAA,MAC5C,IAAI,QAAQ,SAAS;AAAA,QACnB,OAAO,QAAQ;AAAA,MACjB;AAAA,MAEA,OAAO,EAAE,SAAS,IAAI,IAAwB;AAAA;AAAA,IAEhD,SAAS;AAAA,MACP,MAAM,CAAqB,MAAe,OAAgB;AAAA,QACxD,MAAM,MAAM,OAAO,IAAI,EAAE,YAAY;AAAA,QACrC,MAAM,WAAW,KAAK,QAAQ,IAAI,GAAG,KAAK,CAAC;AAAA,QAC3C,SAAS,KAAK,OAAO,KAAK,CAAC;AAAA,QAC3B,KAAK,QAAQ,IAAI,KAAK,QAAQ;AAAA;AAAA,MAEhC,MAAM,CAAqB,MAAe;AAAA,QACxC,KAAK,QAAQ,OAAO,OAAO,IAAI,EAAE,YAAY,CAAC;AAAA;AAAA,MAEhD,GAAG,CAAqB,MAA8B;AAAA,QACpD,MAAM,SAAS,KAAK,QAAQ,IAAI,OAAO,IAAI,EAAE,YAAY,CAAC;AAAA,QAC1D,OAAO,SAAS,OAAO,KAAK,IAAI,IAAI;AAAA;AAAA,MAEtC,GAAG,CAAqB,MAAwB;AAAA,QAC9C,OAAO,KAAK,QAAQ,IAAI,OAAO,IAAI,EAAE,YAAY,CAAC;AAAA;AAAA,MAEpD,GAAG,CAAqB,MAAe,OAAgB;AAAA,QACrD,KAAK,QAAQ,IAAI,OAAO,IAAI,EAAE,YAAY,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC;AAAA;AAAA,MAE9D,OAAO,GAA8C;AAAA,QACnD,MAAM,SAAkC,CAAC;AAAA,QACzC,YAAY,KAAK,WAAW,KAAK,SAAS;AAAA,UACxC,OAAO,KAAK,CAAC,KAAK,OAAO,KAAK,IAAI,CAAC,CAAC;AAAA,QACtC;AAAA,QACA,OAAO;AAAA;AAAA,MAET,IAAI,GAA+B;AAAA,QACjC,OAAO,MAAM,KAAK,KAAK,QAAQ,KAAK,CAAC;AAAA;AAAA,MAEvC,MAAM,GAA+B;AAAA,QACnC,MAAM,SAAmB,CAAC;AAAA,QAC1B,WAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAAA,UAC1C,OAAO,KAAK,OAAO,KAAK,IAAI,CAAC;AAAA,QAC/B;AAAA,QACA,OAAO;AAAA;AAAA,MAET,OAAO,CAAqB,UAAmB;AAAA,QAC7C,IAAI,OAAO,aAAa,YAAY;AAAA,UAClC,MAAM,IAAI,UAAU,6BAA6B;AAAA,QACnD;AAAA,QACA,YAAY,KAAK,WAAW,KAAK,SAAS;AAAA,UACvC,SACC,OAAO,KAAK,IAAI,GAChB,KACA,IACF;AAAA,QACF;AAAA;AAAA,MAEF,YAAY,GAA+B;AAAA,QACzC,OAAO,KAAK,QAAQ,IAAI,YAAY,KAAK,CAAC;AAAA;AAAA,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;AAEA;AAMO,SAAS,kBAAkB,CAChC,SACA,UACe;AAAA,EACf,OAAO,YAA0B,SAAS,UAAU;AAAA,IAClD,MAAM;AAAA,IACN,WAAW,CAAC,SAAS;AAAA,MACnB,MAAM,OAAO,KAAK;AAAA,MAElB,MAAM,UAAU,cAAc,UAAU,IAAI;AAAA,MAC5C,IAAI,QAAQ,SAAS;AAAA,QACnB,OAAO,QAAQ;AAAA,MACjB;AAAA,MAEA,OAAO,EAAE,SAAS,IAAI,IAAwB;AAAA;AAAA,IAEhD,SAAS;AAAA,MACP,MAAM,CAAqB,MAAe,OAAgB;AAAA,QACxD,MAAM,MAAM,OAAO,IAAI,EAAE,YAAY;AAAA,QACrC,MAAM,WAAW,KAAK,QAAQ,IAAI,GAAG,KAAK,CAAC;AAAA,QAC3C,SAAS,KAAK,OAAO,KAAK,CAAC;AAAA,QAC3B,KAAK,QAAQ,IAAI,KAAK,QAAQ;AAAA;AAAA,MAEhC,MAAM,CAAqB,MAAe;AAAA,QACxC,KAAK,QAAQ,OAAO,OAAO,IAAI,EAAE,YAAY,CAAC;AAAA;AAAA,MAEhD,GAAG,CAAqB,MAA8B;AAAA,QACpD,MAAM,SAAS,KAAK,QAAQ,IAAI,OAAO,IAAI,EAAE,YAAY,CAAC;AAAA,QAC1D,OAAO,SAAS,OAAO,KAAK,IAAI,IAAI;AAAA;AAAA,MAEtC,GAAG,CAAqB,MAAwB;AAAA,QAC9C,OAAO,KAAK,QAAQ,IAAI,OAAO,IAAI,EAAE,YAAY,CAAC;AAAA;AAAA,MAEpD,GAAG,CAAqB,MAAe,OAAgB;AAAA,QACrD,KAAK,QAAQ,IAAI,OAAO,IAAI,EAAE,YAAY,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC;AAAA;AAAA,MAE9D,OAAO,GAA8C;AAAA,QACnD,MAAM,SAAkC,CAAC;AAAA,QACzC,YAAY,KAAK,WAAW,KAAK,SAAS;AAAA,UACxC,OAAO,KAAK,CAAC,KAAK,OAAO,KAAK,IAAI,CAAC,CAAC;AAAA,QACtC;AAAA,QACA,OAAO;AAAA;AAAA,MAET,IAAI,GAA+B;AAAA,QACjC,OAAO,MAAM,KAAK,KAAK,QAAQ,KAAK,CAAC;AAAA;AAAA,MAEvC,MAAM,GAA+B;AAAA,QACnC,MAAM,SAAmB,CAAC;AAAA,QAC1B,WAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAAA,UAC1C,OAAO,KAAK,OAAO,KAAK,IAAI,CAAC;AAAA,QAC/B;AAAA,QACA,OAAO;AAAA;AAAA,MAET,OAAO,CAAqB,UAAmB;AAAA,QAC7C,IAAI,OAAO,aAAa,YAAY;AAAA,UAClC,MAAM,IAAI,UAAU,6BAA6B;AAAA,QACnD;AAAA,QACA,YAAY,KAAK,WAAW,KAAK,SAAS;AAAA,UACvC,SACC,OAAO,KAAK,IAAI,GAChB,KACA,IACF;AAAA,QACF;AAAA;AAAA,MAEF,YAAY,GAA+B;AAAA,QACzC,OAAO,KAAK,QAAQ,IAAI,YAAY,KAAK,CAAC;AAAA;AAAA,MAM5C,gBAAgB,CAAqB,kBAA2B;AAAA,QAC9D,MAAM,KAAK,OAAO,qBAAqB,WAAW,mBAAmB;AAAA,QACrE,MAAM,cAAc,qBAAqD,EAAE;AAAA,QAC3E,IAAI,aAAa,cAAc;AAAA,UAC7B,KAAK,UAAU,YAAY,aAAa;AAAA,QAC1C;AAAA;AAAA,IAEJ;AAAA,EACF,CAAC;AAAA;AAMI,SAAS,4BAA4B,CAAC,SAAgC;AAAA,EAC3E,MAAM,MAAM,IAAI;AAAA,EAChB,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AAAA,IAC9B,MAAM,WAAW,IAAI,IAAI,IAAI,YAAY,CAAC,KAAK,CAAC;AAAA,IAChD,SAAS,KAAK,KAAK;AAAA,IACnB,IAAI,IAAI,IAAI,YAAY,GAAG,QAAQ;AAAA,GACpC;AAAA,EACD,OAAO,EAAE,SAAS,IAAI;AAAA;AAMjB,SAAS,oBAAoB,CAAC,OAA8B;AAAA,EACjE,MAAM,UAAU,IAAI;AAAA,EACpB,YAAY,KAAK,WAAW,MAAM,SAAS;AAAA,IACzC,WAAW,SAAS,QAAQ;AAAA,MAC1B,QAAQ,OAAO,KAAK,KAAK;AAAA,IAC3B;AAAA,EACF;AAAA,EACA,OAAO;AAAA;",
|
|
8
|
+
"debugId": "314BF006BE58B50F64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
coerceBody
|
|
10
10
|
} from "@ricsam/quickjs-core";
|
|
11
11
|
import { isHeadersState, isAbortSignalState } from "../types.mjs";
|
|
12
|
-
import { createHeadersStateFromNative
|
|
12
|
+
import { createHeadersStateFromNative } from "./headers.mjs";
|
|
13
13
|
import { parseMultipartFormData, parseUrlEncodedFormData } from "./form-data.mjs";
|
|
14
14
|
import { startNativeStreamReader } from "../upload-stream-queue.mjs";
|
|
15
15
|
async function consumeNativeStream(stream) {
|
|
@@ -242,11 +242,6 @@ function createRequestClass(context, stateMap, streamHelpers) {
|
|
|
242
242
|
return this.url;
|
|
243
243
|
}
|
|
244
244
|
},
|
|
245
|
-
headers: {
|
|
246
|
-
get() {
|
|
247
|
-
return createHeadersLike(this.headersState);
|
|
248
|
-
}
|
|
249
|
-
},
|
|
250
245
|
body: {
|
|
251
246
|
get() {
|
|
252
247
|
if (!createStream) {
|
|
@@ -574,6 +569,32 @@ function addRequestCloneMethod(context) {
|
|
|
574
569
|
result.value.dispose();
|
|
575
570
|
}
|
|
576
571
|
}
|
|
572
|
+
function addRequestHeadersGetter(context) {
|
|
573
|
+
const result = context.evalCode(`
|
|
574
|
+
(function() {
|
|
575
|
+
const headersCache = new Map();
|
|
576
|
+
|
|
577
|
+
Object.defineProperty(Request.prototype, 'headers', {
|
|
578
|
+
get: function() {
|
|
579
|
+
const instanceId = this.__instanceId__;
|
|
580
|
+
if (!headersCache.has(instanceId)) {
|
|
581
|
+
const headers = new Headers();
|
|
582
|
+
headers.__linkToParent__(instanceId);
|
|
583
|
+
headersCache.set(instanceId, headers);
|
|
584
|
+
}
|
|
585
|
+
return headersCache.get(instanceId);
|
|
586
|
+
},
|
|
587
|
+
enumerable: true,
|
|
588
|
+
configurable: true
|
|
589
|
+
});
|
|
590
|
+
})();
|
|
591
|
+
`);
|
|
592
|
+
if (result.error) {
|
|
593
|
+
result.error.dispose();
|
|
594
|
+
} else {
|
|
595
|
+
result.value.dispose();
|
|
596
|
+
}
|
|
597
|
+
}
|
|
577
598
|
function createRequestStateFromNative(request) {
|
|
578
599
|
return {
|
|
579
600
|
method: request.method,
|
|
@@ -597,8 +618,9 @@ function createRequestStateFromNative(request) {
|
|
|
597
618
|
export {
|
|
598
619
|
createRequestStateFromNative,
|
|
599
620
|
createRequestClass,
|
|
621
|
+
addRequestHeadersGetter,
|
|
600
622
|
addRequestFormDataMethod,
|
|
601
623
|
addRequestCloneMethod
|
|
602
624
|
};
|
|
603
625
|
|
|
604
|
-
//# debugId=
|
|
626
|
+
//# debugId=373C320F0ED238CF64756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/globals/request.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { StateMap } from \"@ricsam/quickjs-core\";\nimport {\n defineClass,\n getInstanceStateById,\n isInstanceOf,\n getClassInstanceState,\n coerceToURLString,\n coerceHeaders,\n coerceBody,\n} from \"@ricsam/quickjs-core\";\nimport type { RequestState, HeadersState, AbortSignalState, FormDataState } from \"../types.mjs\";\nimport { isHeadersState, isAbortSignalState } from \"../types.mjs\";\nimport { createHeadersStateFromNative, createHeadersLike } from \"./headers.mjs\";\nimport { parseMultipartFormData, parseUrlEncodedFormData } from \"./form-data.mjs\";\nimport { startNativeStreamReader } from \"../upload-stream-queue.mjs\";\n\n/**\n * Type for the stream factory function\n */\ntype StreamFactory = (source: UnderlyingSource) => QuickJSHandle;\n\n/**\n * Stream helpers passed to the body getter for upload streaming\n */\ninterface StreamHelpers {\n createStream: StreamFactory;\n /** Creates an empty ReadableStream, stores on global, returns instanceId and globalKey */\n createEmptyStream: () => { instanceId: number; globalKey: string };\n /** Gets a fresh handle to the stream stored at globalKey */\n getStreamByKey: (globalKey: string) => QuickJSHandle | null;\n pumpEventLoop: () => void;\n}\n\n/**\n * Helper to consume a native ReadableStream into a Uint8Array.\n * Used by text(), json(), arrayBuffer(), blob() methods.\n */\nasync function consumeNativeStream(\n stream: ReadableStream<Uint8Array>\n): Promise<Uint8Array> {\n const chunks: Uint8Array[] = [];\n const reader = stream.getReader();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n }\n\n // Concatenate chunks into single Uint8Array\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const result = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n\n return result;\n}\n\n/**\n * Internal state of a QuickJS ReadableStream.\n * Mirrors structure in upload-stream-queue.ts and core/streams/readable-stream.ts.\n */\ninterface ReadableStreamInternalState {\n locked: boolean;\n queue: unknown[];\n closeRequested: boolean;\n closed: boolean;\n errored: boolean;\n errorValue: unknown;\n reader: {\n readRequests: Array<{\n resolve: (result: { value: unknown; done: boolean }) => void;\n reject: (e: unknown) => void;\n }>;\n closedPromiseResolvers: {\n resolve: () => void;\n reject: (e: unknown) => void;\n };\n } | null;\n}\n\n/**\n * Helper to consume a QuickJS ReadableStream by reading from its internal state.\n * Used when body getter was accessed before consumption methods (json(), text(), etc.).\n *\n * This reads directly from the stream's queue which is being populated by\n * startNativeStreamReader in the background.\n *\n * @param streamInstanceId The instance ID of the QuickJS ReadableStream\n * @param pumpEventLoop Function to pump the QuickJS event loop\n * @returns Promise that resolves to the concatenated body as Uint8Array\n */\nasync function consumeQuickJSStreamById(\n streamInstanceId: number,\n pumpEventLoop: () => void\n): Promise<Uint8Array> {\n const chunks: Uint8Array[] = [];\n\n while (true) {\n // Pump event loop to allow native stream reader to push more data\n pumpEventLoop();\n\n const state = getInstanceStateById<ReadableStreamInternalState>(streamInstanceId);\n if (!state) {\n // Stream was disposed or doesn't exist\n break;\n }\n\n // Drain all available chunks from the queue\n while (state.queue.length > 0) {\n const chunk = state.queue.shift();\n if (chunk instanceof Uint8Array) {\n chunks.push(chunk);\n }\n }\n\n // Check if stream is done (closed with empty queue)\n if (state.closed || (state.closeRequested && state.queue.length === 0)) {\n break;\n }\n\n // Check for errors\n if (state.errored) {\n throw state.errorValue instanceof Error\n ? state.errorValue\n : new Error(String(state.errorValue));\n }\n\n // Wait for more data via read request mechanism\n await new Promise<void>((resolve, reject) => {\n // Re-check state in case it changed during await\n const currentState = getInstanceStateById<ReadableStreamInternalState>(streamInstanceId);\n if (!currentState) {\n resolve();\n return;\n }\n\n // If there's data now or stream is done, resolve immediately\n if (currentState.queue.length > 0 || currentState.closed || currentState.closeRequested) {\n resolve();\n return;\n }\n\n // Ensure reader structure exists for read requests\n if (!currentState.reader) {\n currentState.reader = {\n readRequests: [],\n closedPromiseResolvers: {\n resolve: () => {},\n reject: () => {},\n },\n };\n }\n\n // Add a read request that will be fulfilled when data arrives\n currentState.reader.readRequests.push({\n resolve: (result) => {\n if (!result.done && result.value instanceof Uint8Array) {\n chunks.push(result.value);\n }\n resolve();\n },\n reject: (e) => reject(e),\n });\n\n // Pump event loop to process incoming data\n pumpEventLoop();\n });\n }\n\n // Concatenate all chunks into a single Uint8Array\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const result = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n\n return result;\n}\n\n/**\n * Create the Request class for QuickJS\n */\nexport function createRequestClass(\n context: QuickJSContext,\n stateMap: StateMap,\n streamHelpers?: StreamHelpers\n): QuickJSHandle {\n const createStream = streamHelpers?.createStream;\n return defineClass<RequestState>(context, stateMap, {\n name: \"Request\",\n construct: (args) => {\n const input = args[0];\n const init = args[1] as {\n method?: string;\n headers?: object;\n body?: unknown;\n cache?: string;\n credentials?: string;\n integrity?: string;\n keepalive?: boolean;\n mode?: string;\n redirect?: string;\n referrer?: string;\n referrerPolicy?: string;\n signal?: AbortSignalState;\n } | undefined;\n\n // Step 1: Extract URL from first argument (highest priority)\n // Per WHATWG Fetch spec, the first argument determines the URL\n let url = \"\";\n if (typeof input === \"string\") {\n url = input;\n } else if (input && typeof input === \"object\") {\n // Check for URL instance first (takes priority over Request.url)\n if (isInstanceOf(input, \"URL\")) {\n const urlState = getClassInstanceState<{ href: string }>(input);\n if (urlState && urlState.href) {\n url = urlState.href;\n }\n } else if (isInstanceOf(input, \"Request\")) {\n // Request instance - get URL from state\n const requestState = getClassInstanceState<RequestState>(input);\n if (requestState) {\n url = requestState.url;\n }\n } else if (\"href\" in input && typeof (input as { href: string }).href === \"string\") {\n // URL-like object with href property\n url = (input as { href: string }).href;\n } else if (\"url\" in input) {\n // Request-like object with url property\n url = String((input as { url: string }).url);\n }\n }\n\n // Step 2: Extract base properties from input if it's a Request\n let method = \"GET\";\n let headersState: HeadersState = { headers: new Map() };\n let body: Uint8Array | null = null;\n let signal: AbortSignalState | null = null;\n let cache = \"default\";\n let credentials = \"same-origin\";\n let integrity = \"\";\n let keepalive = false;\n let mode = \"cors\";\n let redirect = \"follow\";\n let referrer = \"about:client\";\n let referrerPolicy = \"\";\n\n if (input && typeof input === \"object\") {\n if (isInstanceOf(input, \"Request\")) {\n // Copy properties from Request instance\n const requestState = getClassInstanceState<RequestState>(input);\n if (requestState) {\n method = requestState.method;\n headersState = { headers: new Map(requestState.headersState.headers) };\n body = requestState.body;\n signal = requestState.signal;\n cache = requestState.cache;\n credentials = requestState.credentials;\n integrity = requestState.integrity;\n keepalive = requestState.keepalive;\n mode = requestState.mode;\n redirect = requestState.redirect;\n referrer = requestState.referrer;\n referrerPolicy = requestState.referrerPolicy;\n }\n } else if (!isInstanceOf(input, \"URL\")) {\n // Plain object with Request-like properties (not a URL)\n const inputObj = input as Record<string, unknown>;\n if (\"method\" in inputObj && typeof inputObj.method === \"string\") {\n method = inputObj.method;\n }\n if (\"headersState\" in inputObj && isHeadersState(inputObj.headersState)) {\n headersState = { headers: new Map(inputObj.headersState.headers) };\n }\n if (\"body\" in inputObj && inputObj.body) {\n body = coerceBody(inputObj.body);\n }\n if (\"signal\" in inputObj && isAbortSignalState(inputObj.signal)) {\n signal = inputObj.signal;\n }\n }\n }\n\n // Step 3: Apply init options (overrides from second argument)\n // Special case: if init is a Request instance, extract properties from it\n if (init && isInstanceOf(init, \"Request\")) {\n const initRequestState = getClassInstanceState<RequestState>(init);\n if (initRequestState) {\n // Copy properties from the Request instance\n // Only override if input wasn't also a Request (in which case we already copied)\n if (!isInstanceOf(input, \"Request\")) {\n method = initRequestState.method;\n headersState = { headers: new Map(initRequestState.headersState.headers) };\n body = initRequestState.body;\n signal = initRequestState.signal;\n cache = initRequestState.cache;\n credentials = initRequestState.credentials;\n integrity = initRequestState.integrity;\n keepalive = initRequestState.keepalive;\n mode = initRequestState.mode;\n redirect = initRequestState.redirect;\n referrer = initRequestState.referrer;\n referrerPolicy = initRequestState.referrerPolicy;\n }\n }\n } else if (init) {\n // Plain object init\n if (init.method) {\n method = init.method.toUpperCase();\n }\n if (init.headers !== undefined) {\n const coerced = coerceHeaders.safeParse(init.headers);\n if (coerced.success) {\n headersState = coerced.value;\n }\n }\n if (init.body !== undefined) {\n body = coerceBody(init.body);\n }\n if (init.signal) {\n signal = init.signal;\n }\n if (init.cache !== undefined) cache = init.cache;\n if (init.credentials !== undefined) credentials = init.credentials;\n if (init.integrity !== undefined) integrity = init.integrity;\n if (init.keepalive !== undefined) keepalive = init.keepalive;\n if (init.mode !== undefined) mode = init.mode;\n if (init.redirect !== undefined) redirect = init.redirect;\n if (init.referrer !== undefined) referrer = init.referrer;\n if (init.referrerPolicy !== undefined) referrerPolicy = init.referrerPolicy;\n }\n\n return {\n method,\n url,\n headersState,\n body,\n bodyUsed: false,\n cache,\n credentials,\n destination: \"\",\n integrity,\n keepalive,\n mode,\n redirect,\n referrer,\n referrerPolicy,\n signal,\n };\n },\n properties: {\n method: {\n get(this: RequestState) {\n return this.method;\n },\n },\n url: {\n get(this: RequestState) {\n return this.url;\n },\n },\n headers: {\n get(this: RequestState) {\n return createHeadersLike(this.headersState);\n },\n },\n body: {\n get(this: RequestState & { _uploadStreamGlobalKey?: string; _uploadStreamCleanup?: () => void; _cachedBodyStream?: object | null; _uploadStreamInstanceId?: number }) {\n if (!createStream) {\n // Fallback: return raw body if no stream factory\n return this.body;\n }\n\n // If we have an upload stream, get a fresh handle each time\n // (Can't cache handles because __hostCall__ disposes them after each call)\n if (this._uploadStreamGlobalKey) {\n return streamHelpers?.getStreamByKey(this._uploadStreamGlobalKey) || null;\n }\n\n // Return cached buffered body stream if already created\n if (this._cachedBodyStream !== undefined) {\n return this._cachedBodyStream;\n }\n\n // Streaming native body - create a QuickJS ReadableStream that bridges to the native stream\n // Uses the \"Inverted Direct State Access\" pattern: host pushes to QuickJS stream's queue\n if (this.nativeBodyStream) {\n if (!streamHelpers?.createEmptyStream || !streamHelpers?.getStreamByKey) {\n // No helpers available - fall back to null (legacy behavior)\n return null;\n }\n\n // Create a QuickJS ReadableStream with no source callbacks.\n // The stream is stored on a global because __hostCall__ disposes returned\n // handles after each call. We cache the globalKey and get a fresh handle\n // on each access via getStreamByKey().\n const { instanceId: streamInstanceId, globalKey } = streamHelpers.createEmptyStream();\n\n // Start background reader that pushes to the QuickJS stream\n // The onChunkPushed callback pumps the event loop to process pending reads\n const cleanup = startNativeStreamReader(\n this.nativeBodyStream,\n streamInstanceId,\n streamHelpers.pumpEventLoop\n );\n\n // Store cleanup function for potential cancellation\n this._uploadStreamCleanup = cleanup;\n // Cache the global key so subsequent calls can get the same stream\n this._uploadStreamGlobalKey = globalKey;\n // Store instance ID so consumption methods can read from this stream\n this._uploadStreamInstanceId = streamInstanceId;\n\n // Clear nativeBodyStream to prevent double-consumption\n // This ensures text()/json()/arrayBuffer() don't try to read from it\n this.nativeBodyStream = undefined;\n\n // Get fresh handle to return\n return streamHelpers.getStreamByKey(globalKey);\n }\n\n // Fallback: buffered body (backwards compatibility)\n if (!this.body) {\n this._cachedBodyStream = null;\n return null;\n }\n const bodyData = this.body;\n let offset = 0;\n const chunkSize = 65536; // 64KB chunks\n const stream = createStream({\n pull(controller) {\n if (offset >= bodyData.length) {\n controller.close();\n return;\n }\n const chunk = bodyData.slice(offset, Math.min(offset + chunkSize, bodyData.length));\n offset += chunk.length;\n controller.enqueue(chunk);\n },\n });\n this._cachedBodyStream = stream;\n return stream;\n },\n },\n bodyUsed: {\n get(this: RequestState) {\n return this.bodyUsed;\n },\n },\n cache: {\n get(this: RequestState) {\n return this.cache;\n },\n },\n credentials: {\n get(this: RequestState) {\n return this.credentials;\n },\n },\n destination: {\n get(this: RequestState) {\n return this.destination;\n },\n },\n integrity: {\n get(this: RequestState) {\n return this.integrity;\n },\n },\n keepalive: {\n get(this: RequestState) {\n return this.keepalive;\n },\n },\n mode: {\n get(this: RequestState) {\n return this.mode;\n },\n },\n redirect: {\n get(this: RequestState) {\n return this.redirect;\n },\n },\n referrer: {\n get(this: RequestState) {\n return this.referrer;\n },\n },\n referrerPolicy: {\n get(this: RequestState) {\n return this.referrerPolicy;\n },\n },\n signal: {\n get(this: RequestState) {\n return this.signal;\n },\n },\n },\n methods: {\n async arrayBuffer(this: RequestState & { _uploadStreamInstanceId?: number }): Promise<ArrayBuffer> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n\n // Check if QuickJS stream was created (body getter was accessed first)\n if (this._uploadStreamInstanceId !== undefined) {\n const buffer = await consumeQuickJSStreamById(\n this._uploadStreamInstanceId,\n streamHelpers?.pumpEventLoop ?? (() => {})\n );\n return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength) as ArrayBuffer;\n }\n\n // Consume native stream if present\n if (this.nativeBodyStream) {\n const buffer = await consumeNativeStream(this.nativeBodyStream);\n return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength) as ArrayBuffer;\n }\n\n // Fallback: buffered body\n if (!this.body) {\n return new ArrayBuffer(0);\n }\n return this.body.buffer.slice(\n this.body.byteOffset,\n this.body.byteOffset + this.body.byteLength\n ) as ArrayBuffer;\n },\n async blob(this: RequestState & { _uploadStreamInstanceId?: number }): Promise<object> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n const contentType = this.headersState.headers.get(\"content-type\")?.[0] || \"\";\n\n // Check if QuickJS stream was created (body getter was accessed first)\n if (this._uploadStreamInstanceId !== undefined) {\n const buffer = await consumeQuickJSStreamById(\n this._uploadStreamInstanceId,\n streamHelpers?.pumpEventLoop ?? (() => {})\n );\n return {\n parts: [buffer],\n type: contentType,\n size: buffer.length,\n };\n }\n\n // Consume native stream if present\n if (this.nativeBodyStream) {\n const buffer = await consumeNativeStream(this.nativeBodyStream);\n return {\n parts: [buffer],\n type: contentType,\n size: buffer.length,\n };\n }\n\n // Fallback: buffered body\n return {\n parts: this.body ? [this.body] : [],\n type: contentType,\n size: this.body?.length || 0,\n };\n },\n /**\n * Private method that returns the cloned state as a serializable object.\n * Used by the clone() method added via evalCode (see addRequestCloneMethod).\n */\n __getClonedState__(this: RequestState & { _uploadStreamInstanceId?: number }): {\n method: string;\n url: string;\n headers: Array<[string, string]>;\n body: number[] | null;\n cache: string;\n credentials: string;\n integrity: string;\n keepalive: boolean;\n mode: string;\n redirect: string;\n referrer: string;\n referrerPolicy: string;\n } {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n // Note: Cannot clone streaming body - would need to tee the stream\n if (this.nativeBodyStream) {\n throw new TypeError(\"Cannot clone Request with streaming body\");\n }\n // Also cannot clone if body getter created a QuickJS stream\n if (this._uploadStreamInstanceId !== undefined) {\n throw new TypeError(\"Cannot clone Request with streaming body\");\n }\n\n // Convert headers to array of pairs for safe marshalling\n const headersArray: Array<[string, string]> = [];\n for (const [key, values] of this.headersState.headers) {\n headersArray.push([key, values.join(\", \")]);\n }\n\n return {\n method: this.method,\n url: this.url,\n headers: headersArray,\n body: this.body ? Array.from(this.body) : null,\n cache: this.cache,\n credentials: this.credentials,\n integrity: this.integrity,\n keepalive: this.keepalive,\n mode: this.mode,\n redirect: this.redirect,\n referrer: this.referrer,\n referrerPolicy: this.referrerPolicy,\n };\n },\n async json(this: RequestState & { _uploadStreamInstanceId?: number }): Promise<unknown> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n\n // Check if QuickJS stream was created (body getter was accessed first)\n if (this._uploadStreamInstanceId !== undefined) {\n const buffer = await consumeQuickJSStreamById(\n this._uploadStreamInstanceId,\n streamHelpers?.pumpEventLoop ?? (() => {})\n );\n const text = new TextDecoder().decode(buffer);\n return JSON.parse(text);\n }\n\n // Consume native stream if present\n if (this.nativeBodyStream) {\n const buffer = await consumeNativeStream(this.nativeBodyStream);\n const text = new TextDecoder().decode(buffer);\n return JSON.parse(text);\n }\n\n // Fallback: buffered body\n if (!this.body) {\n return JSON.parse(\"\");\n }\n const text = new TextDecoder().decode(this.body);\n return JSON.parse(text);\n },\n async text(this: RequestState & { _uploadStreamInstanceId?: number }): Promise<string> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n\n // Check if QuickJS stream was created (body getter was accessed first)\n if (this._uploadStreamInstanceId !== undefined) {\n const buffer = await consumeQuickJSStreamById(\n this._uploadStreamInstanceId,\n streamHelpers?.pumpEventLoop ?? (() => {})\n );\n return new TextDecoder().decode(buffer);\n }\n\n // Consume native stream if present\n if (this.nativeBodyStream) {\n const buffer = await consumeNativeStream(this.nativeBodyStream);\n return new TextDecoder().decode(buffer);\n }\n\n // Fallback: buffered body\n if (!this.body) {\n return \"\";\n }\n return new TextDecoder().decode(this.body);\n },\n /**\n * Private method that returns raw FormData entries.\n * Used by the formData() method added via evalCode (see addRequestFormDataMethod).\n *\n * Note: File data is converted to plain number arrays to avoid memory issues\n * when marshalling Uint8Array between host and QuickJS contexts.\n */\n async __getFormDataEntries__(this: RequestState & { _uploadStreamInstanceId?: number }): Promise<{\n entries: Array<{\n name: string;\n value: string | { __formDataFile__: true; data: number[]; filename: string; type: string };\n }>;\n }> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n\n // Get body data from QuickJS stream, native stream, or buffered body\n let bodyData: Uint8Array | null = null;\n if (this._uploadStreamInstanceId !== undefined) {\n bodyData = await consumeQuickJSStreamById(\n this._uploadStreamInstanceId,\n streamHelpers?.pumpEventLoop ?? (() => {})\n );\n } else if (this.nativeBodyStream) {\n bodyData = await consumeNativeStream(this.nativeBodyStream);\n } else {\n bodyData = this.body;\n }\n\n if (!bodyData) {\n return { entries: [] };\n }\n\n const contentType = this.headersState.headers.get(\"content-type\")?.[0] || \"\";\n\n let formDataState: FormDataState;\n if (contentType.includes(\"multipart/form-data\")) {\n formDataState = parseMultipartFormData(bodyData, contentType);\n } else if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n formDataState = parseUrlEncodedFormData(bodyData);\n } else {\n throw new TypeError(\"Could not parse content as FormData\");\n }\n\n // Convert Uint8Array data to plain number arrays for safe marshalling\n // Include marker so FormData.get() can reconstruct File instances\n type SerializedFileValue = { __formDataFile__: true; data: number[]; filename: string; type: string };\n type SerializedEntry = { name: string; value: string | SerializedFileValue };\n return {\n entries: formDataState.entries.map((entry): SerializedEntry => {\n if (typeof entry.value === \"string\") {\n return { name: entry.name, value: entry.value };\n }\n // Convert Uint8Array to number array and include marker\n return {\n name: entry.name,\n value: {\n __formDataFile__: true,\n data: Array.from(entry.value.data),\n filename: entry.value.filename,\n type: entry.value.type,\n },\n };\n }),\n };\n },\n },\n });\n}\n\n/**\n * Add the formData() method to Request.prototype via evalCode.\n *\n * This must be called AFTER both Request and FormData classes are on global.\n * The method creates a proper FormData instance with all entries.\n *\n * @see PATTERNS.md section 2 (Class Methods That Return Instances)\n */\nexport function addRequestFormDataMethod(context: QuickJSContext): void {\n const result = context.evalCode(`\n Request.prototype.formData = async function() {\n // Get raw entries from private method\n // Note: File data comes as plain number arrays (converted in host side)\n const rawData = await this.__getFormDataEntries__();\n\n // Create a proper FormData instance\n const formData = new FormData();\n\n // Populate with entries\n // FormData.append handles both string values and file-like objects\n // with number arrays (converted to Uint8Array on the host side)\n for (const entry of rawData.entries) {\n formData.append(entry.name, entry.value);\n }\n\n return formData;\n };\n `);\n\n if (result.error) {\n result.error.dispose();\n } else {\n result.value.dispose();\n }\n}\n\n/**\n * Add the clone() method to Request.prototype via evalCode.\n *\n * This must be called AFTER Request class is on global.\n * The method creates a proper Request instance with cloned state.\n *\n * @see PATTERNS.md section 2 (Class Methods That Return Instances)\n */\nexport function addRequestCloneMethod(context: QuickJSContext): void {\n const result = context.evalCode(`\n Request.prototype.clone = function() {\n // Get cloned state from private method\n const state = this.__getClonedState__();\n\n // Create headers from the array of pairs\n const headers = new Headers();\n for (const [key, value] of state.headers) {\n headers.set(key, value);\n }\n\n // Convert body from number array back to Uint8Array if present\n let body = null;\n if (state.body) {\n body = new Uint8Array(state.body);\n }\n\n // Create a proper Request instance\n return new Request(state.url, {\n method: state.method,\n headers: headers,\n body: body,\n cache: state.cache,\n credentials: state.credentials,\n integrity: state.integrity,\n keepalive: state.keepalive,\n mode: state.mode,\n redirect: state.redirect,\n referrer: state.referrer,\n referrerPolicy: state.referrerPolicy,\n });\n };\n `);\n\n if (result.error) {\n result.error.dispose();\n } else {\n result.value.dispose();\n }\n}\n\n/**\n * Create a RequestState from a native Request object.\n *\n * This is now synchronous - we preserve the native ReadableStream instead of\n * buffering it. The stream is consumed lazily when QuickJS code accesses\n * request.body or calls request.text()/json()/arrayBuffer().\n *\n * This enables streaming large uploads (1GB+) without buffering.\n */\nexport function createRequestStateFromNative(\n request: Request\n): RequestState {\n return {\n method: request.method,\n url: request.url,\n headersState: createHeadersStateFromNative(request.headers),\n body: null, // Not buffered upfront - use nativeBodyStream instead\n bodyUsed: false,\n cache: request.cache,\n credentials: request.credentials,\n destination: request.destination,\n integrity: request.integrity,\n keepalive: request.keepalive,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n signal: null, // Signal handling is complex, simplified here\n nativeBodyStream: request.body ?? undefined,\n };\n}\n"
|
|
5
|
+
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { StateMap } from \"@ricsam/quickjs-core\";\nimport {\n defineClass,\n getInstanceStateById,\n isInstanceOf,\n getClassInstanceState,\n coerceToURLString,\n coerceHeaders,\n coerceBody,\n} from \"@ricsam/quickjs-core\";\nimport type { RequestState, HeadersState, AbortSignalState, FormDataState } from \"../types.mjs\";\nimport { isHeadersState, isAbortSignalState } from \"../types.mjs\";\nimport { createHeadersStateFromNative } from \"./headers.mjs\";\nimport { parseMultipartFormData, parseUrlEncodedFormData } from \"./form-data.mjs\";\nimport { startNativeStreamReader } from \"../upload-stream-queue.mjs\";\n\n/**\n * Type for the stream factory function\n */\ntype StreamFactory = (source: UnderlyingSource) => QuickJSHandle;\n\n/**\n * Stream helpers passed to the body getter for upload streaming\n */\ninterface StreamHelpers {\n createStream: StreamFactory;\n /** Creates an empty ReadableStream, stores on global, returns instanceId and globalKey */\n createEmptyStream: () => { instanceId: number; globalKey: string };\n /** Gets a fresh handle to the stream stored at globalKey */\n getStreamByKey: (globalKey: string) => QuickJSHandle | null;\n pumpEventLoop: () => void;\n}\n\n/**\n * Helper to consume a native ReadableStream into a Uint8Array.\n * Used by text(), json(), arrayBuffer(), blob() methods.\n */\nasync function consumeNativeStream(\n stream: ReadableStream<Uint8Array>\n): Promise<Uint8Array> {\n const chunks: Uint8Array[] = [];\n const reader = stream.getReader();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n }\n\n // Concatenate chunks into single Uint8Array\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const result = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n\n return result;\n}\n\n/**\n * Internal state of a QuickJS ReadableStream.\n * Mirrors structure in upload-stream-queue.ts and core/streams/readable-stream.ts.\n */\ninterface ReadableStreamInternalState {\n locked: boolean;\n queue: unknown[];\n closeRequested: boolean;\n closed: boolean;\n errored: boolean;\n errorValue: unknown;\n reader: {\n readRequests: Array<{\n resolve: (result: { value: unknown; done: boolean }) => void;\n reject: (e: unknown) => void;\n }>;\n closedPromiseResolvers: {\n resolve: () => void;\n reject: (e: unknown) => void;\n };\n } | null;\n}\n\n/**\n * Helper to consume a QuickJS ReadableStream by reading from its internal state.\n * Used when body getter was accessed before consumption methods (json(), text(), etc.).\n *\n * This reads directly from the stream's queue which is being populated by\n * startNativeStreamReader in the background.\n *\n * @param streamInstanceId The instance ID of the QuickJS ReadableStream\n * @param pumpEventLoop Function to pump the QuickJS event loop\n * @returns Promise that resolves to the concatenated body as Uint8Array\n */\nasync function consumeQuickJSStreamById(\n streamInstanceId: number,\n pumpEventLoop: () => void\n): Promise<Uint8Array> {\n const chunks: Uint8Array[] = [];\n\n while (true) {\n // Pump event loop to allow native stream reader to push more data\n pumpEventLoop();\n\n const state = getInstanceStateById<ReadableStreamInternalState>(streamInstanceId);\n if (!state) {\n // Stream was disposed or doesn't exist\n break;\n }\n\n // Drain all available chunks from the queue\n while (state.queue.length > 0) {\n const chunk = state.queue.shift();\n if (chunk instanceof Uint8Array) {\n chunks.push(chunk);\n }\n }\n\n // Check if stream is done (closed with empty queue)\n if (state.closed || (state.closeRequested && state.queue.length === 0)) {\n break;\n }\n\n // Check for errors\n if (state.errored) {\n throw state.errorValue instanceof Error\n ? state.errorValue\n : new Error(String(state.errorValue));\n }\n\n // Wait for more data via read request mechanism\n await new Promise<void>((resolve, reject) => {\n // Re-check state in case it changed during await\n const currentState = getInstanceStateById<ReadableStreamInternalState>(streamInstanceId);\n if (!currentState) {\n resolve();\n return;\n }\n\n // If there's data now or stream is done, resolve immediately\n if (currentState.queue.length > 0 || currentState.closed || currentState.closeRequested) {\n resolve();\n return;\n }\n\n // Ensure reader structure exists for read requests\n if (!currentState.reader) {\n currentState.reader = {\n readRequests: [],\n closedPromiseResolvers: {\n resolve: () => {},\n reject: () => {},\n },\n };\n }\n\n // Add a read request that will be fulfilled when data arrives\n currentState.reader.readRequests.push({\n resolve: (result) => {\n if (!result.done && result.value instanceof Uint8Array) {\n chunks.push(result.value);\n }\n resolve();\n },\n reject: (e) => reject(e),\n });\n\n // Pump event loop to process incoming data\n pumpEventLoop();\n });\n }\n\n // Concatenate all chunks into a single Uint8Array\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const result = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n\n return result;\n}\n\n/**\n * Create the Request class for QuickJS\n */\nexport function createRequestClass(\n context: QuickJSContext,\n stateMap: StateMap,\n streamHelpers?: StreamHelpers\n): QuickJSHandle {\n const createStream = streamHelpers?.createStream;\n return defineClass<RequestState>(context, stateMap, {\n name: \"Request\",\n construct: (args) => {\n const input = args[0];\n const init = args[1] as {\n method?: string;\n headers?: object;\n body?: unknown;\n cache?: string;\n credentials?: string;\n integrity?: string;\n keepalive?: boolean;\n mode?: string;\n redirect?: string;\n referrer?: string;\n referrerPolicy?: string;\n signal?: AbortSignalState;\n } | undefined;\n\n // Step 1: Extract URL from first argument (highest priority)\n // Per WHATWG Fetch spec, the first argument determines the URL\n let url = \"\";\n if (typeof input === \"string\") {\n url = input;\n } else if (input && typeof input === \"object\") {\n // Check for URL instance first (takes priority over Request.url)\n if (isInstanceOf(input, \"URL\")) {\n const urlState = getClassInstanceState<{ href: string }>(input);\n if (urlState && urlState.href) {\n url = urlState.href;\n }\n } else if (isInstanceOf(input, \"Request\")) {\n // Request instance - get URL from state\n const requestState = getClassInstanceState<RequestState>(input);\n if (requestState) {\n url = requestState.url;\n }\n } else if (\"href\" in input && typeof (input as { href: string }).href === \"string\") {\n // URL-like object with href property\n url = (input as { href: string }).href;\n } else if (\"url\" in input) {\n // Request-like object with url property\n url = String((input as { url: string }).url);\n }\n }\n\n // Step 2: Extract base properties from input if it's a Request\n let method = \"GET\";\n let headersState: HeadersState = { headers: new Map() };\n let body: Uint8Array | null = null;\n let signal: AbortSignalState | null = null;\n let cache = \"default\";\n let credentials = \"same-origin\";\n let integrity = \"\";\n let keepalive = false;\n let mode = \"cors\";\n let redirect = \"follow\";\n let referrer = \"about:client\";\n let referrerPolicy = \"\";\n\n if (input && typeof input === \"object\") {\n if (isInstanceOf(input, \"Request\")) {\n // Copy properties from Request instance\n const requestState = getClassInstanceState<RequestState>(input);\n if (requestState) {\n method = requestState.method;\n headersState = { headers: new Map(requestState.headersState.headers) };\n body = requestState.body;\n signal = requestState.signal;\n cache = requestState.cache;\n credentials = requestState.credentials;\n integrity = requestState.integrity;\n keepalive = requestState.keepalive;\n mode = requestState.mode;\n redirect = requestState.redirect;\n referrer = requestState.referrer;\n referrerPolicy = requestState.referrerPolicy;\n }\n } else if (!isInstanceOf(input, \"URL\")) {\n // Plain object with Request-like properties (not a URL)\n const inputObj = input as Record<string, unknown>;\n if (\"method\" in inputObj && typeof inputObj.method === \"string\") {\n method = inputObj.method;\n }\n if (\"headersState\" in inputObj && isHeadersState(inputObj.headersState)) {\n headersState = { headers: new Map(inputObj.headersState.headers) };\n }\n if (\"body\" in inputObj && inputObj.body) {\n body = coerceBody(inputObj.body);\n }\n if (\"signal\" in inputObj && isAbortSignalState(inputObj.signal)) {\n signal = inputObj.signal;\n }\n }\n }\n\n // Step 3: Apply init options (overrides from second argument)\n // Special case: if init is a Request instance, extract properties from it\n if (init && isInstanceOf(init, \"Request\")) {\n const initRequestState = getClassInstanceState<RequestState>(init);\n if (initRequestState) {\n // Copy properties from the Request instance\n // Only override if input wasn't also a Request (in which case we already copied)\n if (!isInstanceOf(input, \"Request\")) {\n method = initRequestState.method;\n headersState = { headers: new Map(initRequestState.headersState.headers) };\n body = initRequestState.body;\n signal = initRequestState.signal;\n cache = initRequestState.cache;\n credentials = initRequestState.credentials;\n integrity = initRequestState.integrity;\n keepalive = initRequestState.keepalive;\n mode = initRequestState.mode;\n redirect = initRequestState.redirect;\n referrer = initRequestState.referrer;\n referrerPolicy = initRequestState.referrerPolicy;\n }\n }\n } else if (init) {\n // Plain object init\n if (init.method) {\n method = init.method.toUpperCase();\n }\n if (init.headers !== undefined) {\n const coerced = coerceHeaders.safeParse(init.headers);\n if (coerced.success) {\n headersState = coerced.value;\n }\n }\n if (init.body !== undefined) {\n body = coerceBody(init.body);\n }\n if (init.signal) {\n signal = init.signal;\n }\n if (init.cache !== undefined) cache = init.cache;\n if (init.credentials !== undefined) credentials = init.credentials;\n if (init.integrity !== undefined) integrity = init.integrity;\n if (init.keepalive !== undefined) keepalive = init.keepalive;\n if (init.mode !== undefined) mode = init.mode;\n if (init.redirect !== undefined) redirect = init.redirect;\n if (init.referrer !== undefined) referrer = init.referrer;\n if (init.referrerPolicy !== undefined) referrerPolicy = init.referrerPolicy;\n }\n\n return {\n method,\n url,\n headersState,\n body,\n bodyUsed: false,\n cache,\n credentials,\n destination: \"\",\n integrity,\n keepalive,\n mode,\n redirect,\n referrer,\n referrerPolicy,\n signal,\n };\n },\n properties: {\n method: {\n get(this: RequestState) {\n return this.method;\n },\n },\n url: {\n get(this: RequestState) {\n return this.url;\n },\n },\n // Note: headers getter is added via addRequestHeadersGetter() in setup.ts\n // to return a proper Headers instance instead of a plain object\n body: {\n get(this: RequestState & { _uploadStreamGlobalKey?: string; _uploadStreamCleanup?: () => void; _cachedBodyStream?: object | null; _uploadStreamInstanceId?: number }) {\n if (!createStream) {\n // Fallback: return raw body if no stream factory\n return this.body;\n }\n\n // If we have an upload stream, get a fresh handle each time\n // (Can't cache handles because __hostCall__ disposes them after each call)\n if (this._uploadStreamGlobalKey) {\n return streamHelpers?.getStreamByKey(this._uploadStreamGlobalKey) || null;\n }\n\n // Return cached buffered body stream if already created\n if (this._cachedBodyStream !== undefined) {\n return this._cachedBodyStream;\n }\n\n // Streaming native body - create a QuickJS ReadableStream that bridges to the native stream\n // Uses the \"Inverted Direct State Access\" pattern: host pushes to QuickJS stream's queue\n if (this.nativeBodyStream) {\n if (!streamHelpers?.createEmptyStream || !streamHelpers?.getStreamByKey) {\n // No helpers available - fall back to null (legacy behavior)\n return null;\n }\n\n // Create a QuickJS ReadableStream with no source callbacks.\n // The stream is stored on a global because __hostCall__ disposes returned\n // handles after each call. We cache the globalKey and get a fresh handle\n // on each access via getStreamByKey().\n const { instanceId: streamInstanceId, globalKey } = streamHelpers.createEmptyStream();\n\n // Start background reader that pushes to the QuickJS stream\n // The onChunkPushed callback pumps the event loop to process pending reads\n const cleanup = startNativeStreamReader(\n this.nativeBodyStream,\n streamInstanceId,\n streamHelpers.pumpEventLoop\n );\n\n // Store cleanup function for potential cancellation\n this._uploadStreamCleanup = cleanup;\n // Cache the global key so subsequent calls can get the same stream\n this._uploadStreamGlobalKey = globalKey;\n // Store instance ID so consumption methods can read from this stream\n this._uploadStreamInstanceId = streamInstanceId;\n\n // Clear nativeBodyStream to prevent double-consumption\n // This ensures text()/json()/arrayBuffer() don't try to read from it\n this.nativeBodyStream = undefined;\n\n // Get fresh handle to return\n return streamHelpers.getStreamByKey(globalKey);\n }\n\n // Fallback: buffered body (backwards compatibility)\n if (!this.body) {\n this._cachedBodyStream = null;\n return null;\n }\n const bodyData = this.body;\n let offset = 0;\n const chunkSize = 65536; // 64KB chunks\n const stream = createStream({\n pull(controller) {\n if (offset >= bodyData.length) {\n controller.close();\n return;\n }\n const chunk = bodyData.slice(offset, Math.min(offset + chunkSize, bodyData.length));\n offset += chunk.length;\n controller.enqueue(chunk);\n },\n });\n this._cachedBodyStream = stream;\n return stream;\n },\n },\n bodyUsed: {\n get(this: RequestState) {\n return this.bodyUsed;\n },\n },\n cache: {\n get(this: RequestState) {\n return this.cache;\n },\n },\n credentials: {\n get(this: RequestState) {\n return this.credentials;\n },\n },\n destination: {\n get(this: RequestState) {\n return this.destination;\n },\n },\n integrity: {\n get(this: RequestState) {\n return this.integrity;\n },\n },\n keepalive: {\n get(this: RequestState) {\n return this.keepalive;\n },\n },\n mode: {\n get(this: RequestState) {\n return this.mode;\n },\n },\n redirect: {\n get(this: RequestState) {\n return this.redirect;\n },\n },\n referrer: {\n get(this: RequestState) {\n return this.referrer;\n },\n },\n referrerPolicy: {\n get(this: RequestState) {\n return this.referrerPolicy;\n },\n },\n signal: {\n get(this: RequestState) {\n return this.signal;\n },\n },\n },\n methods: {\n async arrayBuffer(this: RequestState & { _uploadStreamInstanceId?: number }): Promise<ArrayBuffer> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n\n // Check if QuickJS stream was created (body getter was accessed first)\n if (this._uploadStreamInstanceId !== undefined) {\n const buffer = await consumeQuickJSStreamById(\n this._uploadStreamInstanceId,\n streamHelpers?.pumpEventLoop ?? (() => {})\n );\n return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength) as ArrayBuffer;\n }\n\n // Consume native stream if present\n if (this.nativeBodyStream) {\n const buffer = await consumeNativeStream(this.nativeBodyStream);\n return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength) as ArrayBuffer;\n }\n\n // Fallback: buffered body\n if (!this.body) {\n return new ArrayBuffer(0);\n }\n return this.body.buffer.slice(\n this.body.byteOffset,\n this.body.byteOffset + this.body.byteLength\n ) as ArrayBuffer;\n },\n async blob(this: RequestState & { _uploadStreamInstanceId?: number }): Promise<object> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n const contentType = this.headersState.headers.get(\"content-type\")?.[0] || \"\";\n\n // Check if QuickJS stream was created (body getter was accessed first)\n if (this._uploadStreamInstanceId !== undefined) {\n const buffer = await consumeQuickJSStreamById(\n this._uploadStreamInstanceId,\n streamHelpers?.pumpEventLoop ?? (() => {})\n );\n return {\n parts: [buffer],\n type: contentType,\n size: buffer.length,\n };\n }\n\n // Consume native stream if present\n if (this.nativeBodyStream) {\n const buffer = await consumeNativeStream(this.nativeBodyStream);\n return {\n parts: [buffer],\n type: contentType,\n size: buffer.length,\n };\n }\n\n // Fallback: buffered body\n return {\n parts: this.body ? [this.body] : [],\n type: contentType,\n size: this.body?.length || 0,\n };\n },\n /**\n * Private method that returns the cloned state as a serializable object.\n * Used by the clone() method added via evalCode (see addRequestCloneMethod).\n */\n __getClonedState__(this: RequestState & { _uploadStreamInstanceId?: number }): {\n method: string;\n url: string;\n headers: Array<[string, string]>;\n body: number[] | null;\n cache: string;\n credentials: string;\n integrity: string;\n keepalive: boolean;\n mode: string;\n redirect: string;\n referrer: string;\n referrerPolicy: string;\n } {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n // Note: Cannot clone streaming body - would need to tee the stream\n if (this.nativeBodyStream) {\n throw new TypeError(\"Cannot clone Request with streaming body\");\n }\n // Also cannot clone if body getter created a QuickJS stream\n if (this._uploadStreamInstanceId !== undefined) {\n throw new TypeError(\"Cannot clone Request with streaming body\");\n }\n\n // Convert headers to array of pairs for safe marshalling\n const headersArray: Array<[string, string]> = [];\n for (const [key, values] of this.headersState.headers) {\n headersArray.push([key, values.join(\", \")]);\n }\n\n return {\n method: this.method,\n url: this.url,\n headers: headersArray,\n body: this.body ? Array.from(this.body) : null,\n cache: this.cache,\n credentials: this.credentials,\n integrity: this.integrity,\n keepalive: this.keepalive,\n mode: this.mode,\n redirect: this.redirect,\n referrer: this.referrer,\n referrerPolicy: this.referrerPolicy,\n };\n },\n async json(this: RequestState & { _uploadStreamInstanceId?: number }): Promise<unknown> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n\n // Check if QuickJS stream was created (body getter was accessed first)\n if (this._uploadStreamInstanceId !== undefined) {\n const buffer = await consumeQuickJSStreamById(\n this._uploadStreamInstanceId,\n streamHelpers?.pumpEventLoop ?? (() => {})\n );\n const text = new TextDecoder().decode(buffer);\n return JSON.parse(text);\n }\n\n // Consume native stream if present\n if (this.nativeBodyStream) {\n const buffer = await consumeNativeStream(this.nativeBodyStream);\n const text = new TextDecoder().decode(buffer);\n return JSON.parse(text);\n }\n\n // Fallback: buffered body\n if (!this.body) {\n return JSON.parse(\"\");\n }\n const text = new TextDecoder().decode(this.body);\n return JSON.parse(text);\n },\n async text(this: RequestState & { _uploadStreamInstanceId?: number }): Promise<string> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n\n // Check if QuickJS stream was created (body getter was accessed first)\n if (this._uploadStreamInstanceId !== undefined) {\n const buffer = await consumeQuickJSStreamById(\n this._uploadStreamInstanceId,\n streamHelpers?.pumpEventLoop ?? (() => {})\n );\n return new TextDecoder().decode(buffer);\n }\n\n // Consume native stream if present\n if (this.nativeBodyStream) {\n const buffer = await consumeNativeStream(this.nativeBodyStream);\n return new TextDecoder().decode(buffer);\n }\n\n // Fallback: buffered body\n if (!this.body) {\n return \"\";\n }\n return new TextDecoder().decode(this.body);\n },\n /**\n * Private method that returns raw FormData entries.\n * Used by the formData() method added via evalCode (see addRequestFormDataMethod).\n *\n * Note: File data is converted to plain number arrays to avoid memory issues\n * when marshalling Uint8Array between host and QuickJS contexts.\n */\n async __getFormDataEntries__(this: RequestState & { _uploadStreamInstanceId?: number }): Promise<{\n entries: Array<{\n name: string;\n value: string | { __formDataFile__: true; data: number[]; filename: string; type: string };\n }>;\n }> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n\n // Get body data from QuickJS stream, native stream, or buffered body\n let bodyData: Uint8Array | null = null;\n if (this._uploadStreamInstanceId !== undefined) {\n bodyData = await consumeQuickJSStreamById(\n this._uploadStreamInstanceId,\n streamHelpers?.pumpEventLoop ?? (() => {})\n );\n } else if (this.nativeBodyStream) {\n bodyData = await consumeNativeStream(this.nativeBodyStream);\n } else {\n bodyData = this.body;\n }\n\n if (!bodyData) {\n return { entries: [] };\n }\n\n const contentType = this.headersState.headers.get(\"content-type\")?.[0] || \"\";\n\n let formDataState: FormDataState;\n if (contentType.includes(\"multipart/form-data\")) {\n formDataState = parseMultipartFormData(bodyData, contentType);\n } else if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n formDataState = parseUrlEncodedFormData(bodyData);\n } else {\n throw new TypeError(\"Could not parse content as FormData\");\n }\n\n // Convert Uint8Array data to plain number arrays for safe marshalling\n // Include marker so FormData.get() can reconstruct File instances\n type SerializedFileValue = { __formDataFile__: true; data: number[]; filename: string; type: string };\n type SerializedEntry = { name: string; value: string | SerializedFileValue };\n return {\n entries: formDataState.entries.map((entry): SerializedEntry => {\n if (typeof entry.value === \"string\") {\n return { name: entry.name, value: entry.value };\n }\n // Convert Uint8Array to number array and include marker\n return {\n name: entry.name,\n value: {\n __formDataFile__: true,\n data: Array.from(entry.value.data),\n filename: entry.value.filename,\n type: entry.value.type,\n },\n };\n }),\n };\n },\n },\n });\n}\n\n/**\n * Add the formData() method to Request.prototype via evalCode.\n *\n * This must be called AFTER both Request and FormData classes are on global.\n * The method creates a proper FormData instance with all entries.\n *\n * @see PATTERNS.md section 2 (Class Methods That Return Instances)\n */\nexport function addRequestFormDataMethod(context: QuickJSContext): void {\n const result = context.evalCode(`\n Request.prototype.formData = async function() {\n // Get raw entries from private method\n // Note: File data comes as plain number arrays (converted in host side)\n const rawData = await this.__getFormDataEntries__();\n\n // Create a proper FormData instance\n const formData = new FormData();\n\n // Populate with entries\n // FormData.append handles both string values and file-like objects\n // with number arrays (converted to Uint8Array on the host side)\n for (const entry of rawData.entries) {\n formData.append(entry.name, entry.value);\n }\n\n return formData;\n };\n `);\n\n if (result.error) {\n result.error.dispose();\n } else {\n result.value.dispose();\n }\n}\n\n/**\n * Add the clone() method to Request.prototype via evalCode.\n *\n * This must be called AFTER Request class is on global.\n * The method creates a proper Request instance with cloned state.\n *\n * @see PATTERNS.md section 2 (Class Methods That Return Instances)\n */\nexport function addRequestCloneMethod(context: QuickJSContext): void {\n const result = context.evalCode(`\n Request.prototype.clone = function() {\n // Get cloned state from private method\n const state = this.__getClonedState__();\n\n // Create headers from the array of pairs\n const headers = new Headers();\n for (const [key, value] of state.headers) {\n headers.set(key, value);\n }\n\n // Convert body from number array back to Uint8Array if present\n let body = null;\n if (state.body) {\n body = new Uint8Array(state.body);\n }\n\n // Create a proper Request instance\n return new Request(state.url, {\n method: state.method,\n headers: headers,\n body: body,\n cache: state.cache,\n credentials: state.credentials,\n integrity: state.integrity,\n keepalive: state.keepalive,\n mode: state.mode,\n redirect: state.redirect,\n referrer: state.referrer,\n referrerPolicy: state.referrerPolicy,\n });\n };\n `);\n\n if (result.error) {\n result.error.dispose();\n } else {\n result.value.dispose();\n }\n}\n\n/**\n * Add the headers getter to Request.prototype via evalCode.\n *\n * This must be called AFTER both Request and Headers classes are on global.\n * Returns a cached Headers instance that shares state with the Request.\n *\n * @see PATTERNS.md section 9 (Instance-Cached Properties)\n */\nexport function addRequestHeadersGetter(context: QuickJSContext): void {\n const result = context.evalCode(`\n (function() {\n const headersCache = new Map();\n\n Object.defineProperty(Request.prototype, 'headers', {\n get: function() {\n const instanceId = this.__instanceId__;\n if (!headersCache.has(instanceId)) {\n const headers = new Headers();\n headers.__linkToParent__(instanceId);\n headersCache.set(instanceId, headers);\n }\n return headersCache.get(instanceId);\n },\n enumerable: true,\n configurable: true\n });\n })();\n `);\n\n if (result.error) {\n result.error.dispose();\n } else {\n result.value.dispose();\n }\n}\n\n/**\n * Create a RequestState from a native Request object.\n *\n * This is now synchronous - we preserve the native ReadableStream instead of\n * buffering it. The stream is consumed lazily when QuickJS code accesses\n * request.body or calls request.text()/json()/arrayBuffer().\n *\n * This enables streaming large uploads (1GB+) without buffering.\n */\nexport function createRequestStateFromNative(\n request: Request\n): RequestState {\n return {\n method: request.method,\n url: request.url,\n headersState: createHeadersStateFromNative(request.headers),\n body: null, // Not buffered upfront - use nativeBodyStream instead\n bodyUsed: false,\n cache: request.cache,\n credentials: request.credentials,\n destination: request.destination,\n integrity: request.integrity,\n keepalive: request.keepalive,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n signal: null, // Signal handling is complex, simplified here\n nativeBodyStream: request.body ?? undefined,\n };\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "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",
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "373C320F0ED238CF64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
import {
|
|
4
4
|
defineClass,
|
|
5
5
|
isDefineClassInstance,
|
|
6
|
+
getClassInstanceState,
|
|
6
7
|
coerceHeaders
|
|
7
8
|
} from "@ricsam/quickjs-core";
|
|
8
9
|
import { isResponseState, isHeadersState } from "../types.mjs";
|
|
9
|
-
import { headersStateToNative
|
|
10
|
+
import { headersStateToNative } from "./headers.mjs";
|
|
10
11
|
import { parseMultipartFormData, parseUrlEncodedFormData } from "./form-data.mjs";
|
|
11
12
|
function createResponseClass(context, stateMap, createStream) {
|
|
12
13
|
const classHandle = defineClass(context, stateMap, {
|
|
@@ -30,6 +31,19 @@ function createResponseClass(context, stateMap, createStream) {
|
|
|
30
31
|
} else if (bodyInit instanceof Uint8Array) {
|
|
31
32
|
body = bodyInit;
|
|
32
33
|
bodyType = "binary";
|
|
34
|
+
} else if (isDefineClassInstance(bodyInit) && (bodyInit.__className__ === "Blob" || bodyInit.__className__ === "File")) {
|
|
35
|
+
const blobState = getClassInstanceState(bodyInit);
|
|
36
|
+
if (blobState && blobState.parts) {
|
|
37
|
+
const parts = blobState.parts;
|
|
38
|
+
const totalLength = parts.reduce((sum, p) => sum + p.length, 0);
|
|
39
|
+
body = new Uint8Array(totalLength);
|
|
40
|
+
let offset = 0;
|
|
41
|
+
for (const part of parts) {
|
|
42
|
+
body.set(part, offset);
|
|
43
|
+
offset += part.length;
|
|
44
|
+
}
|
|
45
|
+
bodyType = "binary";
|
|
46
|
+
}
|
|
33
47
|
} else if (bodyInit && typeof bodyInit === "object" && "parts" in bodyInit) {
|
|
34
48
|
const parts = bodyInit.parts;
|
|
35
49
|
const totalLength = parts.reduce((sum, p) => sum + p.length, 0);
|
|
@@ -98,11 +112,6 @@ function createResponseClass(context, stateMap, createStream) {
|
|
|
98
112
|
return this.bodyUsed;
|
|
99
113
|
}
|
|
100
114
|
},
|
|
101
|
-
headers: {
|
|
102
|
-
get() {
|
|
103
|
-
return createHeadersLike(this.headersState);
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
115
|
ok: {
|
|
107
116
|
get() {
|
|
108
117
|
return this.ok;
|
|
@@ -305,6 +314,32 @@ function addResponseCloneMethod(context) {
|
|
|
305
314
|
result.value.dispose();
|
|
306
315
|
}
|
|
307
316
|
}
|
|
317
|
+
function addResponseHeadersGetter(context) {
|
|
318
|
+
const result = context.evalCode(`
|
|
319
|
+
(function() {
|
|
320
|
+
const headersCache = new Map();
|
|
321
|
+
|
|
322
|
+
Object.defineProperty(Response.prototype, 'headers', {
|
|
323
|
+
get: function() {
|
|
324
|
+
const instanceId = this.__instanceId__;
|
|
325
|
+
if (!headersCache.has(instanceId)) {
|
|
326
|
+
const headers = new Headers();
|
|
327
|
+
headers.__linkToParent__(instanceId);
|
|
328
|
+
headersCache.set(instanceId, headers);
|
|
329
|
+
}
|
|
330
|
+
return headersCache.get(instanceId);
|
|
331
|
+
},
|
|
332
|
+
enumerable: true,
|
|
333
|
+
configurable: true
|
|
334
|
+
});
|
|
335
|
+
})();
|
|
336
|
+
`);
|
|
337
|
+
if (result.error) {
|
|
338
|
+
result.error.dispose();
|
|
339
|
+
} else {
|
|
340
|
+
result.value.dispose();
|
|
341
|
+
}
|
|
342
|
+
}
|
|
308
343
|
function responseStateToNative(state) {
|
|
309
344
|
if (isResponseState(state)) {
|
|
310
345
|
if (state.bodyType === "stream") {
|
|
@@ -388,7 +423,8 @@ export {
|
|
|
388
423
|
createResponseStateFromNative,
|
|
389
424
|
createResponseClass,
|
|
390
425
|
addResponseStaticMethods,
|
|
426
|
+
addResponseHeadersGetter,
|
|
391
427
|
addResponseCloneMethod
|
|
392
428
|
};
|
|
393
429
|
|
|
394
|
-
//# debugId=
|
|
430
|
+
//# debugId=2C8015EA6BE1243864756E2164756E21
|