@ricsam/quickjs-fetch 0.2.5 → 0.2.7
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/request.cjs +9 -1
- package/dist/cjs/globals/request.cjs.map +3 -3
- package/dist/cjs/globals/response.cjs +38 -4
- package/dist/cjs/globals/response.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/globals/request.mjs +10 -2
- package/dist/mjs/globals/request.mjs.map +3 -3
- package/dist/mjs/globals/response.mjs +39 -5
- package/dist/mjs/globals/response.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/types/types.d.ts +2 -0
- package/package.json +2 -2
|
@@ -81,6 +81,14 @@ function createRequestClass(context, stateMap, createStream) {
|
|
|
81
81
|
headersState = {
|
|
82
82
|
headers: new Map(init.headers.headers)
|
|
83
83
|
};
|
|
84
|
+
} else if ("__isDefineClassInstance__" in init.headers && init.headers.__isDefineClassInstance__ === true && "__instanceId__" in init.headers) {
|
|
85
|
+
const instanceId = init.headers.__instanceId__;
|
|
86
|
+
const state = import_quickjs_core.getInstanceStateById(instanceId);
|
|
87
|
+
if (state && state.headers instanceof Map) {
|
|
88
|
+
headersState = {
|
|
89
|
+
headers: new Map(state.headers)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
84
92
|
} else {
|
|
85
93
|
headersState = { headers: new Map };
|
|
86
94
|
for (const [key, value] of Object.entries(init.headers)) {
|
|
@@ -357,4 +365,4 @@ async function createRequestStateFromNative(request) {
|
|
|
357
365
|
}
|
|
358
366
|
})
|
|
359
367
|
|
|
360
|
-
//# debugId=
|
|
368
|
+
//# debugId=CE847DBCB06DA09264756E2164756E21
|
|
@@ -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 { defineClass } from \"@ricsam/quickjs-core\";\nimport type { RequestState, HeadersState, AbortSignalState, FormDataState } from \"../types.cjs\";\nimport { createHeadersStateFromNative, createHeadersLike } from \"./headers.cjs\";\nimport { parseMultipartFormData, parseUrlEncodedFormData } from \"./form-data.cjs\";\n\n/**\n * Type for the stream factory function\n */\ntype StreamFactory = (source: UnderlyingSource) => QuickJSHandle;\n\n/**\n * Create the Request class for QuickJS\n */\nexport function createRequestClass(\n context: QuickJSContext,\n stateMap: StateMap,\n createStream?: StreamFactory\n): QuickJSHandle {\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 let url = \"\";\n let method = \"GET\";\n let headersState: HeadersState = { headers: new Map() };\n let body: Uint8Array | null = null;\n let signal: AbortSignalState | null = null;\n\n // Handle input\n if (typeof input === \"string\") {\n url = input;\n } else if (input && typeof input === \"object\") {\n // Could be URL or Request-like\n if (\"url\" in input) {\n url = String((input as { url: string }).url);\n }\n if (\"method\" in input) {\n method = String((input as { method: string }).method);\n }\n if (\"headersState\" in input) {\n const inputHeaders = (input as RequestState).headersState;\n headersState = {\n headers: new Map(inputHeaders.headers),\n };\n }\n if (\"body\" in input && (input as RequestState).body) {\n body = (input as RequestState).body;\n }\n if (\"signal\" in input) {\n signal = (input as RequestState).signal;\n }\n }\n\n // Apply init options\n if (init) {\n if (init.method) {\n method = init.method.toUpperCase();\n }\n if (init.headers) {\n if (init.headers && typeof init.headers === \"object\") {\n if (\"headers\" in init.headers && init.headers.headers instanceof Map) {\n headersState = {\n headers: new Map((init.headers as HeadersState).headers),\n };\n } else {\n headersState = { headers: new Map() };\n for (const [key, value] of Object.entries(init.headers)) {\n headersState.headers.set(key.toLowerCase(), [String(value)]);\n }\n }\n }\n }\n if (init.body !== undefined && init.body !== null) {\n if (typeof init.body === \"string\") {\n body = new TextEncoder().encode(init.body);\n } else if (init.body instanceof ArrayBuffer) {\n body = new Uint8Array(init.body);\n } else if (init.body instanceof Uint8Array) {\n body = init.body;\n }\n }\n if (init.signal) {\n signal = init.signal;\n }\n }\n\n return {\n method,\n url,\n headersState,\n body,\n bodyUsed: false,\n cache: init?.cache || \"default\",\n credentials: init?.credentials || \"same-origin\",\n destination: \"\",\n integrity: init?.integrity || \"\",\n keepalive: init?.keepalive || false,\n mode: init?.mode || \"cors\",\n redirect: init?.redirect || \"follow\",\n referrer: init?.referrer || \"about:client\",\n referrerPolicy: init?.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) {\n if (!this.body) return null;\n if (!createStream) {\n // Fallback: return raw body if no stream factory\n return this.body;\n }\n // Create a ReadableStream from the body data\n const bodyData = this.body;\n let offset = 0;\n const chunkSize = 65536; // 64KB chunks\n return 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 },\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): Promise<ArrayBuffer> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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): 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 return {\n parts: this.body ? [this.body] : [],\n type: contentType,\n size: this.body?.length || 0,\n };\n },\n clone(this: RequestState): RequestState {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n return {\n ...this,\n headersState: {\n headers: new Map(this.headersState.headers),\n },\n body: this.body ? new Uint8Array(this.body) : null,\n bodyUsed: false,\n };\n },\n async json(this: RequestState): Promise<unknown> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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): Promise<string> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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): 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 if (!this.body) {\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(this.body, contentType);\n } else if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n formDataState = parseUrlEncodedFormData(this.body);\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 * Create a RequestState from a native Request object\n */\nexport async function createRequestStateFromNative(\n request: Request\n): Promise<RequestState> {\n const body = request.body\n ? new Uint8Array(await request.arrayBuffer())\n : null;\n\n return {\n method: request.method,\n url: request.url,\n headersState: createHeadersStateFromNative(request.headers),\n body,\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 };\n}\n"
|
|
5
|
+
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { StateMap } from \"@ricsam/quickjs-core\";\nimport { defineClass, getInstanceStateById } from \"@ricsam/quickjs-core\";\nimport type { RequestState, HeadersState, AbortSignalState, FormDataState } from \"../types.cjs\";\nimport { createHeadersStateFromNative, createHeadersLike } from \"./headers.cjs\";\nimport { parseMultipartFormData, parseUrlEncodedFormData } from \"./form-data.cjs\";\n\n/**\n * Type for the stream factory function\n */\ntype StreamFactory = (source: UnderlyingSource) => QuickJSHandle;\n\n/**\n * Create the Request class for QuickJS\n */\nexport function createRequestClass(\n context: QuickJSContext,\n stateMap: StateMap,\n createStream?: StreamFactory\n): QuickJSHandle {\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 let url = \"\";\n let method = \"GET\";\n let headersState: HeadersState = { headers: new Map() };\n let body: Uint8Array | null = null;\n let signal: AbortSignalState | null = null;\n\n // Handle input\n if (typeof input === \"string\") {\n url = input;\n } else if (input && typeof input === \"object\") {\n // Could be URL or Request-like\n if (\"url\" in input) {\n url = String((input as { url: string }).url);\n }\n if (\"method\" in input) {\n method = String((input as { method: string }).method);\n }\n if (\"headersState\" in input) {\n const inputHeaders = (input as RequestState).headersState;\n headersState = {\n headers: new Map(inputHeaders.headers),\n };\n }\n if (\"body\" in input && (input as RequestState).body) {\n body = (input as RequestState).body;\n }\n if (\"signal\" in input) {\n signal = (input as RequestState).signal;\n }\n }\n\n // Apply init options\n if (init) {\n if (init.method) {\n method = init.method.toUpperCase();\n }\n if (init.headers) {\n if (init.headers && typeof init.headers === \"object\") {\n if (\"headers\" in init.headers && init.headers.headers instanceof Map) {\n headersState = {\n headers: new Map((init.headers as HeadersState).headers),\n };\n } else if (\n \"__isDefineClassInstance__\" in init.headers &&\n (init.headers as { __isDefineClassInstance__?: boolean }).__isDefineClassInstance__ === true &&\n \"__instanceId__\" in init.headers\n ) {\n // Unmarshalled Headers instance from defineClass\n const instanceId = (init.headers as { __instanceId__: number }).__instanceId__;\n const state = getInstanceStateById<HeadersState>(instanceId);\n if (state && state.headers instanceof Map) {\n headersState = {\n headers: new Map(state.headers),\n };\n }\n } else {\n headersState = { headers: new Map() };\n for (const [key, value] of Object.entries(init.headers)) {\n headersState.headers.set(key.toLowerCase(), [String(value)]);\n }\n }\n }\n }\n if (init.body !== undefined && init.body !== null) {\n if (typeof init.body === \"string\") {\n body = new TextEncoder().encode(init.body);\n } else if (init.body instanceof ArrayBuffer) {\n body = new Uint8Array(init.body);\n } else if (init.body instanceof Uint8Array) {\n body = init.body;\n }\n }\n if (init.signal) {\n signal = init.signal;\n }\n }\n\n return {\n method,\n url,\n headersState,\n body,\n bodyUsed: false,\n cache: init?.cache || \"default\",\n credentials: init?.credentials || \"same-origin\",\n destination: \"\",\n integrity: init?.integrity || \"\",\n keepalive: init?.keepalive || false,\n mode: init?.mode || \"cors\",\n redirect: init?.redirect || \"follow\",\n referrer: init?.referrer || \"about:client\",\n referrerPolicy: init?.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) {\n if (!this.body) return null;\n if (!createStream) {\n // Fallback: return raw body if no stream factory\n return this.body;\n }\n // Create a ReadableStream from the body data\n const bodyData = this.body;\n let offset = 0;\n const chunkSize = 65536; // 64KB chunks\n return 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 },\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): Promise<ArrayBuffer> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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): 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 return {\n parts: this.body ? [this.body] : [],\n type: contentType,\n size: this.body?.length || 0,\n };\n },\n clone(this: RequestState): RequestState {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n return {\n ...this,\n headersState: {\n headers: new Map(this.headersState.headers),\n },\n body: this.body ? new Uint8Array(this.body) : null,\n bodyUsed: false,\n };\n },\n async json(this: RequestState): Promise<unknown> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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): Promise<string> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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): 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 if (!this.body) {\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(this.body, contentType);\n } else if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n formDataState = parseUrlEncodedFormData(this.body);\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 * Create a RequestState from a native Request object\n */\nexport async function createRequestStateFromNative(\n request: Request\n): Promise<RequestState> {\n const body = request.body\n ? new Uint8Array(await request.arrayBuffer())\n : null;\n\n return {\n method: request.method,\n url: request.url,\n headersState: createHeadersStateFromNative(request.headers),\n body,\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 };\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "CE847DBCB06DA09264756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -46,16 +46,20 @@ function createResponseClass(context, stateMap, createStream) {
|
|
|
46
46
|
const bodyInit = args[0];
|
|
47
47
|
const init = args[1];
|
|
48
48
|
let body = null;
|
|
49
|
+
let bodyType = null;
|
|
49
50
|
const status = init?.status ?? 200;
|
|
50
51
|
const statusText = init?.statusText ?? "";
|
|
51
52
|
let headersState = { headers: new Map };
|
|
52
53
|
if (bodyInit !== null && bodyInit !== undefined) {
|
|
53
54
|
if (typeof bodyInit === "string") {
|
|
54
55
|
body = new TextEncoder().encode(bodyInit);
|
|
56
|
+
bodyType = "string";
|
|
55
57
|
} else if (bodyInit instanceof ArrayBuffer) {
|
|
56
58
|
body = new Uint8Array(bodyInit);
|
|
59
|
+
bodyType = "binary";
|
|
57
60
|
} else if (bodyInit instanceof Uint8Array) {
|
|
58
61
|
body = bodyInit;
|
|
62
|
+
bodyType = "binary";
|
|
59
63
|
} else if (bodyInit && typeof bodyInit === "object" && "parts" in bodyInit) {
|
|
60
64
|
const parts = bodyInit.parts;
|
|
61
65
|
const totalLength = parts.reduce((sum, p) => sum + p.length, 0);
|
|
@@ -65,6 +69,7 @@ function createResponseClass(context, stateMap, createStream) {
|
|
|
65
69
|
body.set(part, offset);
|
|
66
70
|
offset += part.length;
|
|
67
71
|
}
|
|
72
|
+
bodyType = "binary";
|
|
68
73
|
}
|
|
69
74
|
}
|
|
70
75
|
if (init?.headers) {
|
|
@@ -72,6 +77,14 @@ function createResponseClass(context, stateMap, createStream) {
|
|
|
72
77
|
headersState = {
|
|
73
78
|
headers: new Map(init.headers.headers)
|
|
74
79
|
};
|
|
80
|
+
} else if (init.headers && typeof init.headers === "object" && "__isDefineClassInstance__" in init.headers && init.headers.__isDefineClassInstance__ === true && "__instanceId__" in init.headers) {
|
|
81
|
+
const instanceId = init.headers.__instanceId__;
|
|
82
|
+
const state = import_quickjs_core.getInstanceStateById(instanceId);
|
|
83
|
+
if (state && state.headers instanceof Map) {
|
|
84
|
+
headersState = {
|
|
85
|
+
headers: new Map(state.headers)
|
|
86
|
+
};
|
|
87
|
+
}
|
|
75
88
|
} else {
|
|
76
89
|
headersState = { headers: new Map };
|
|
77
90
|
for (const [key, value] of Object.entries(init.headers)) {
|
|
@@ -88,7 +101,8 @@ function createResponseClass(context, stateMap, createStream) {
|
|
|
88
101
|
url: "",
|
|
89
102
|
redirected: false,
|
|
90
103
|
type: init?._type ?? "default",
|
|
91
|
-
ok: status >= 200 && status < 300
|
|
104
|
+
ok: status >= 200 && status < 300,
|
|
105
|
+
bodyType
|
|
92
106
|
};
|
|
93
107
|
},
|
|
94
108
|
properties: {
|
|
@@ -268,7 +282,8 @@ function addResponseStaticMethods(context) {
|
|
|
268
282
|
}
|
|
269
283
|
}
|
|
270
284
|
function responseStateToNative(state) {
|
|
271
|
-
const
|
|
285
|
+
const bodyBytes = state.body ?? state.body;
|
|
286
|
+
const bodyType = state.bodyType;
|
|
272
287
|
const status = state.status ?? 200;
|
|
273
288
|
const statusText = state.statusText ?? "";
|
|
274
289
|
let headersState;
|
|
@@ -284,6 +299,15 @@ function responseStateToNative(state) {
|
|
|
284
299
|
} else {
|
|
285
300
|
headersState = { headers: new Map };
|
|
286
301
|
}
|
|
302
|
+
let body = null;
|
|
303
|
+
if (bodyBytes) {
|
|
304
|
+
if (bodyType === "string") {
|
|
305
|
+
body = new TextDecoder().decode(bodyBytes);
|
|
306
|
+
} else {
|
|
307
|
+
const uint8 = bodyBytes;
|
|
308
|
+
body = uint8.buffer.slice(uint8.byteOffset, uint8.byteOffset + uint8.byteLength);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
287
311
|
return new Response(body, {
|
|
288
312
|
status,
|
|
289
313
|
statusText,
|
|
@@ -298,6 +322,15 @@ async function createResponseStateFromNative(response) {
|
|
|
298
322
|
existing.push(value);
|
|
299
323
|
headersState.headers.set(key.toLowerCase(), existing);
|
|
300
324
|
});
|
|
325
|
+
const contentType = response.headers.get("content-type");
|
|
326
|
+
let bodyType = null;
|
|
327
|
+
if (body) {
|
|
328
|
+
if (contentType && (contentType.startsWith("text/") || contentType.includes("json") || contentType.includes("xml"))) {
|
|
329
|
+
bodyType = "string";
|
|
330
|
+
} else {
|
|
331
|
+
bodyType = "binary";
|
|
332
|
+
}
|
|
333
|
+
}
|
|
301
334
|
return {
|
|
302
335
|
status: response.status,
|
|
303
336
|
statusText: response.statusText,
|
|
@@ -307,9 +340,10 @@ async function createResponseStateFromNative(response) {
|
|
|
307
340
|
url: response.url,
|
|
308
341
|
redirected: response.redirected,
|
|
309
342
|
type: response.type,
|
|
310
|
-
ok: response.ok
|
|
343
|
+
ok: response.ok,
|
|
344
|
+
bodyType
|
|
311
345
|
};
|
|
312
346
|
}
|
|
313
347
|
})
|
|
314
348
|
|
|
315
|
-
//# debugId=
|
|
349
|
+
//# debugId=253BFDBC49B0C92064756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/globals/response.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { StateMap } from \"@ricsam/quickjs-core\";\nimport { defineClass } from \"@ricsam/quickjs-core\";\nimport type { ResponseState, HeadersState, FormDataState } from \"../types.cjs\";\nimport { headersStateToNative, createHeadersLike } from \"./headers.cjs\";\nimport { parseMultipartFormData, parseUrlEncodedFormData } from \"./form-data.cjs\";\n\n/**\n * Type for the stream factory function\n */\ntype StreamFactory = (source: UnderlyingSource) => QuickJSHandle;\n\n/**\n * Create the Response class for QuickJS\n */\nexport function createResponseClass(\n context: QuickJSContext,\n stateMap: StateMap,\n createStream?: StreamFactory\n): QuickJSHandle {\n const classHandle = defineClass<ResponseState>(context, stateMap, {\n name: \"Response\",\n construct: (args) => {\n const bodyInit = args[0];\n const init = args[1] as {\n status?: number;\n statusText?: string;\n headers?: object;\n _type?: string; // Internal: for Response.error() to set type\n } | undefined;\n\n let body: Uint8Array | null = null;\n const status = init?.status ?? 200;\n const statusText = init?.statusText ?? \"\";\n let headersState: HeadersState = { headers: new Map() };\n\n // Parse body\n if (bodyInit !== null && bodyInit !== undefined) {\n if (typeof bodyInit === \"string\") {\n body = new TextEncoder().encode(bodyInit);\n } else if (bodyInit instanceof ArrayBuffer) {\n body = new Uint8Array(bodyInit);\n } else if (bodyInit instanceof Uint8Array) {\n body = bodyInit;\n } else if (\n bodyInit &&\n typeof bodyInit === \"object\" &&\n \"parts\" in bodyInit\n ) {\n // Blob-like\n const parts = (bodyInit as { parts: Uint8Array[] }).parts;\n const totalLength = parts.reduce((sum, p) => sum + p.length, 0);\n body = new Uint8Array(totalLength);\n let offset = 0;\n for (const part of parts) {\n body.set(part, offset);\n offset += part.length;\n }\n }\n }\n\n // Parse headers\n if (init?.headers) {\n if (\n init.headers &&\n typeof init.headers === \"object\" &&\n \"headers\" in init.headers &&\n init.headers.headers instanceof Map\n ) {\n headersState = {\n headers: new Map((init.headers as HeadersState).headers),\n };\n } else {\n headersState = { headers: new Map() };\n for (const [key, value] of Object.entries(init.headers)) {\n headersState.headers.set(key.toLowerCase(), [String(value)]);\n }\n }\n }\n\n return {\n status,\n statusText,\n headersState,\n body,\n bodyUsed: false,\n url: \"\",\n redirected: false,\n type: init?._type ?? \"default\",\n ok: status >= 200 && status < 300,\n };\n },\n properties: {\n body: {\n get(this: ResponseState) {\n if (!this.body) return null;\n if (!createStream) {\n // Fallback: return raw body if no stream factory\n return this.body;\n }\n // Create a ReadableStream from the body data\n const bodyData = this.body;\n let offset = 0;\n const chunkSize = 65536; // 64KB chunks\n return 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 },\n },\n bodyUsed: {\n get(this: ResponseState) {\n return this.bodyUsed;\n },\n },\n headers: {\n get(this: ResponseState) {\n return createHeadersLike(this.headersState);\n },\n },\n ok: {\n get(this: ResponseState) {\n return this.ok;\n },\n },\n redirected: {\n get(this: ResponseState) {\n return this.redirected;\n },\n },\n status: {\n get(this: ResponseState) {\n return this.status;\n },\n },\n statusText: {\n get(this: ResponseState) {\n return this.statusText;\n },\n },\n type: {\n get(this: ResponseState) {\n return this.type;\n },\n },\n url: {\n get(this: ResponseState) {\n return this.url;\n },\n },\n },\n methods: {\n async arrayBuffer(this: ResponseState): Promise<ArrayBuffer> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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: ResponseState): Promise<object> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n const contentType =\n this.headersState.headers.get(\"content-type\")?.[0] || \"\";\n return {\n parts: this.body ? [this.body] : [],\n type: contentType,\n size: this.body?.length || 0,\n };\n },\n clone(this: ResponseState): ResponseState {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n return {\n ...this,\n headersState: {\n headers: new Map(this.headersState.headers),\n },\n body: this.body ? new Uint8Array(this.body) : null,\n bodyUsed: false,\n };\n },\n async json(this: ResponseState): Promise<unknown> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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: ResponseState): Promise<string> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n if (!this.body) {\n return \"\";\n }\n return new TextDecoder().decode(this.body);\n },\n async formData(this: ResponseState): Promise<FormDataState> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n if (!this.body) {\n return { entries: [] };\n }\n\n const contentType = this.headersState.headers.get(\"content-type\")?.[0] || \"\";\n\n if (contentType.includes(\"multipart/form-data\")) {\n return parseMultipartFormData(this.body, contentType);\n } else if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n return parseUrlEncodedFormData(this.body);\n }\n\n throw new TypeError(\"Could not parse content as FormData\");\n },\n },\n });\n\n return classHandle;\n}\n\n/**\n * Add static methods to Response class after it's been set on global\n * This must be called after Response and Headers are available on global\n */\nexport function addResponseStaticMethods(context: QuickJSContext): void {\n const staticMethodsCode = `\n Response.error = function() {\n return new Response(null, { status: 0, _type: \"error\" });\n };\n\n Response.json = function(data, init = {}) {\n const body = JSON.stringify(data);\n // Merge content-type with any provided headers\n const headers = Object.assign(\n { \"content-type\": \"application/json\" },\n init.headers || {}\n );\n return new Response(body, {\n status: init.status ?? 200,\n statusText: init.statusText ?? \"\",\n headers: headers\n });\n };\n\n Response.redirect = function(url, status = 302) {\n return new Response(null, {\n status: status,\n headers: { \"location\": String(url) }\n });\n };\n `;\n const result = context.evalCode(staticMethodsCode);\n if (result.error) {\n result.error.dispose();\n } else {\n result.value.dispose();\n }\n}\n\n/**\n * Convert ResponseState (or unmarshalled Response object) to native Response\n */\nexport function responseStateToNative(state: ResponseState | Record<string, unknown>): Response {\n const body = (state as ResponseState).body ?? (state as Record<string, unknown>).body;\n const status = (state as ResponseState).status ?? 200;\n const statusText = (state as ResponseState).statusText ?? \"\";\n\n // Handle both headersState (internal) and headers (from getter)\n let headersState: HeadersState;\n if ((state as ResponseState).headersState) {\n headersState = (state as ResponseState).headersState;\n } else if ((state as Record<string, unknown>).headers) {\n // When unmarshalled, headers is the HeadersLike object from getter\n const headers = (state as Record<string, unknown>).headers as { headers?: Map<string, string[]> };\n if (headers.headers instanceof Map) {\n headersState = { headers: headers.headers };\n } else {\n headersState = { headers: new Map() };\n }\n } else {\n headersState = { headers: new Map() };\n }\n\n return new Response(body as BodyInit | null, {\n status,\n statusText,\n headers: headersStateToNative(headersState),\n });\n}\n\n/**\n * Create a ResponseState from a native Response\n */\nexport async function createResponseStateFromNative(\n response: Response\n): Promise<ResponseState> {\n const body = response.body\n ? new Uint8Array(await response.arrayBuffer())\n : null;\n\n const headersState: HeadersState = { headers: new Map() };\n response.headers.forEach((value, key) => {\n const existing = headersState.headers.get(key.toLowerCase()) || [];\n existing.push(value);\n headersState.headers.set(key.toLowerCase(), existing);\n });\n\n return {\n status: response.status,\n statusText: response.statusText,\n headersState,\n body,\n bodyUsed: false,\n url: response.url,\n redirected: response.redirected,\n type: response.type,\n ok: response.ok,\n };\n}\n"
|
|
5
|
+
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { StateMap } from \"@ricsam/quickjs-core\";\nimport { defineClass, getInstanceStateById } from \"@ricsam/quickjs-core\";\nimport type { ResponseState, HeadersState, FormDataState } from \"../types.cjs\";\nimport { headersStateToNative, createHeadersLike } from \"./headers.cjs\";\nimport { parseMultipartFormData, parseUrlEncodedFormData } from \"./form-data.cjs\";\n\n/**\n * Type for the stream factory function\n */\ntype StreamFactory = (source: UnderlyingSource) => QuickJSHandle;\n\n/**\n * Create the Response class for QuickJS\n */\nexport function createResponseClass(\n context: QuickJSContext,\n stateMap: StateMap,\n createStream?: StreamFactory\n): QuickJSHandle {\n const classHandle = defineClass<ResponseState>(context, stateMap, {\n name: \"Response\",\n construct: (args) => {\n const bodyInit = args[0];\n const init = args[1] as {\n status?: number;\n statusText?: string;\n headers?: object;\n _type?: string; // Internal: for Response.error() to set type\n } | undefined;\n\n let body: Uint8Array | null = null;\n let bodyType: \"string\" | \"binary\" | null = null;\n const status = init?.status ?? 200;\n const statusText = init?.statusText ?? \"\";\n let headersState: HeadersState = { headers: new Map() };\n\n // Parse body\n if (bodyInit !== null && bodyInit !== undefined) {\n if (typeof bodyInit === \"string\") {\n body = new TextEncoder().encode(bodyInit);\n bodyType = \"string\";\n } else if (bodyInit instanceof ArrayBuffer) {\n body = new Uint8Array(bodyInit);\n bodyType = \"binary\";\n } else if (bodyInit instanceof Uint8Array) {\n body = bodyInit;\n bodyType = \"binary\";\n } else if (\n bodyInit &&\n typeof bodyInit === \"object\" &&\n \"parts\" in bodyInit\n ) {\n // Blob-like\n const parts = (bodyInit as { parts: Uint8Array[] }).parts;\n const totalLength = parts.reduce((sum, p) => sum + p.length, 0);\n body = new Uint8Array(totalLength);\n let offset = 0;\n for (const part of parts) {\n body.set(part, offset);\n offset += part.length;\n }\n bodyType = \"binary\";\n }\n }\n\n // Parse headers\n if (init?.headers) {\n if (\n init.headers &&\n typeof init.headers === \"object\" &&\n \"headers\" in init.headers &&\n init.headers.headers instanceof Map\n ) {\n headersState = {\n headers: new Map((init.headers as HeadersState).headers),\n };\n } else if (\n init.headers &&\n typeof init.headers === \"object\" &&\n \"__isDefineClassInstance__\" in init.headers &&\n (init.headers as { __isDefineClassInstance__?: boolean }).__isDefineClassInstance__ === true &&\n \"__instanceId__\" in init.headers\n ) {\n // Unmarshalled Headers instance from defineClass\n const instanceId = (init.headers as { __instanceId__: number }).__instanceId__;\n const state = getInstanceStateById<HeadersState>(instanceId);\n if (state && state.headers instanceof Map) {\n headersState = {\n headers: new Map(state.headers),\n };\n }\n } else {\n headersState = { headers: new Map() };\n for (const [key, value] of Object.entries(init.headers)) {\n headersState.headers.set(key.toLowerCase(), [String(value)]);\n }\n }\n }\n\n return {\n status,\n statusText,\n headersState,\n body,\n bodyUsed: false,\n url: \"\",\n redirected: false,\n type: init?._type ?? \"default\",\n ok: status >= 200 && status < 300,\n bodyType,\n };\n },\n properties: {\n body: {\n get(this: ResponseState) {\n if (!this.body) return null;\n if (!createStream) {\n // Fallback: return raw body if no stream factory\n return this.body;\n }\n // Create a ReadableStream from the body data\n const bodyData = this.body;\n let offset = 0;\n const chunkSize = 65536; // 64KB chunks\n return 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 },\n },\n bodyUsed: {\n get(this: ResponseState) {\n return this.bodyUsed;\n },\n },\n headers: {\n get(this: ResponseState) {\n return createHeadersLike(this.headersState);\n },\n },\n ok: {\n get(this: ResponseState) {\n return this.ok;\n },\n },\n redirected: {\n get(this: ResponseState) {\n return this.redirected;\n },\n },\n status: {\n get(this: ResponseState) {\n return this.status;\n },\n },\n statusText: {\n get(this: ResponseState) {\n return this.statusText;\n },\n },\n type: {\n get(this: ResponseState) {\n return this.type;\n },\n },\n url: {\n get(this: ResponseState) {\n return this.url;\n },\n },\n },\n methods: {\n async arrayBuffer(this: ResponseState): Promise<ArrayBuffer> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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: ResponseState): Promise<object> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n const contentType =\n this.headersState.headers.get(\"content-type\")?.[0] || \"\";\n return {\n parts: this.body ? [this.body] : [],\n type: contentType,\n size: this.body?.length || 0,\n };\n },\n clone(this: ResponseState): ResponseState {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n return {\n ...this,\n headersState: {\n headers: new Map(this.headersState.headers),\n },\n body: this.body ? new Uint8Array(this.body) : null,\n bodyUsed: false,\n };\n },\n async json(this: ResponseState): Promise<unknown> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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: ResponseState): Promise<string> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n if (!this.body) {\n return \"\";\n }\n return new TextDecoder().decode(this.body);\n },\n async formData(this: ResponseState): Promise<FormDataState> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n if (!this.body) {\n return { entries: [] };\n }\n\n const contentType = this.headersState.headers.get(\"content-type\")?.[0] || \"\";\n\n if (contentType.includes(\"multipart/form-data\")) {\n return parseMultipartFormData(this.body, contentType);\n } else if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n return parseUrlEncodedFormData(this.body);\n }\n\n throw new TypeError(\"Could not parse content as FormData\");\n },\n },\n });\n\n return classHandle;\n}\n\n/**\n * Add static methods to Response class after it's been set on global\n * This must be called after Response and Headers are available on global\n */\nexport function addResponseStaticMethods(context: QuickJSContext): void {\n const staticMethodsCode = `\n Response.error = function() {\n return new Response(null, { status: 0, _type: \"error\" });\n };\n\n Response.json = function(data, init = {}) {\n const body = JSON.stringify(data);\n // Merge content-type with any provided headers\n const headers = Object.assign(\n { \"content-type\": \"application/json\" },\n init.headers || {}\n );\n return new Response(body, {\n status: init.status ?? 200,\n statusText: init.statusText ?? \"\",\n headers: headers\n });\n };\n\n Response.redirect = function(url, status = 302) {\n return new Response(null, {\n status: status,\n headers: { \"location\": String(url) }\n });\n };\n `;\n const result = context.evalCode(staticMethodsCode);\n if (result.error) {\n result.error.dispose();\n } else {\n result.value.dispose();\n }\n}\n\n/**\n * Convert ResponseState (or unmarshalled Response object) to native Response\n */\nexport function responseStateToNative(state: ResponseState | Record<string, unknown>): Response {\n const bodyBytes = (state as ResponseState).body ?? (state as Record<string, unknown>).body;\n const bodyType = (state as ResponseState).bodyType;\n const status = (state as ResponseState).status ?? 200;\n const statusText = (state as ResponseState).statusText ?? \"\";\n\n // Handle both headersState (internal) and headers (from getter)\n let headersState: HeadersState;\n if ((state as ResponseState).headersState) {\n headersState = (state as ResponseState).headersState;\n } else if ((state as Record<string, unknown>).headers) {\n // When unmarshalled, headers is the HeadersLike object from getter\n const headers = (state as Record<string, unknown>).headers as { headers?: Map<string, string[]> };\n if (headers.headers instanceof Map) {\n headersState = { headers: headers.headers };\n } else {\n headersState = { headers: new Map() };\n }\n } else {\n headersState = { headers: new Map() };\n }\n\n // Convert body back to string if it was originally a string\n // This ensures Bun.serve doesn't add application/octet-stream content-type\n let body: BodyInit | null = null;\n if (bodyBytes) {\n if (bodyType === \"string\") {\n body = new TextDecoder().decode(bodyBytes as Uint8Array);\n } else {\n // Cast to ArrayBuffer which is a valid BodyInit type\n const uint8 = bodyBytes as Uint8Array;\n body = uint8.buffer.slice(uint8.byteOffset, uint8.byteOffset + uint8.byteLength) as ArrayBuffer;\n }\n }\n\n return new Response(body, {\n status,\n statusText,\n headers: headersStateToNative(headersState),\n });\n}\n\n/**\n * Create a ResponseState from a native Response\n */\nexport async function createResponseStateFromNative(\n response: Response\n): Promise<ResponseState> {\n const body = response.body\n ? new Uint8Array(await response.arrayBuffer())\n : null;\n\n const headersState: HeadersState = { headers: new Map() };\n response.headers.forEach((value, key) => {\n const existing = headersState.headers.get(key.toLowerCase()) || [];\n existing.push(value);\n headersState.headers.set(key.toLowerCase(), existing);\n });\n\n // Detect body type from content-type header\n const contentType = response.headers.get(\"content-type\");\n let bodyType: \"string\" | \"binary\" | null = null;\n if (body) {\n if (contentType && (contentType.startsWith(\"text/\") || contentType.includes(\"json\") || contentType.includes(\"xml\"))) {\n bodyType = \"string\";\n } else {\n bodyType = \"binary\";\n }\n }\n\n return {\n status: response.status,\n statusText: response.statusText,\n headersState,\n body,\n bodyUsed: false,\n url: response.url,\n redirected: response.redirected,\n type: response.type,\n ok: response.ok,\n bodyType,\n };\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEkD,IAAlD;AAEwD,IAAxD;AACgE,IAAhE;AAUO,SAAS,mBAAmB,CACjC,SACA,UACA,cACe;AAAA,EACf,MAAM,cAAc,gCAA2B,SAAS,UAAU;AAAA,IAChE,MAAM;AAAA,IACN,WAAW,CAAC,SAAS;AAAA,MACnB,MAAM,WAAW,KAAK;AAAA,MACtB,MAAM,OAAO,KAAK;AAAA,MAOlB,IAAI,OAA0B;AAAA,MAC9B,IAAI,WAAuC;AAAA,MAC3C,MAAM,SAAS,MAAM,UAAU;AAAA,MAC/B,MAAM,aAAa,MAAM,cAAc;AAAA,MACvC,IAAI,eAA6B,EAAE,SAAS,IAAI,IAAM;AAAA,MAGtD,IAAI,aAAa,QAAQ,aAAa,WAAW;AAAA,QAC/C,IAAI,OAAO,aAAa,UAAU;AAAA,UAChC,OAAO,IAAI,YAAY,EAAE,OAAO,QAAQ;AAAA,UACxC,WAAW;AAAA,QACb,EAAO,SAAI,oBAAoB,aAAa;AAAA,UAC1C,OAAO,IAAI,WAAW,QAAQ;AAAA,UAC9B,WAAW;AAAA,QACb,EAAO,SAAI,oBAAoB,YAAY;AAAA,UACzC,OAAO;AAAA,UACP,WAAW;AAAA,QACb,EAAO,SACL,YACA,OAAO,aAAa,YACpB,WAAW,UACX;AAAA,UAEA,MAAM,QAAS,SAAqC;AAAA,UACpD,MAAM,cAAc,MAAM,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,QAAQ,CAAC;AAAA,UAC9D,OAAO,IAAI,WAAW,WAAW;AAAA,UACjC,IAAI,SAAS;AAAA,UACb,WAAW,QAAQ,OAAO;AAAA,YACxB,KAAK,IAAI,MAAM,MAAM;AAAA,YACrB,UAAU,KAAK;AAAA,UACjB;AAAA,UACA,WAAW;AAAA,QACb;AAAA,MACF;AAAA,MAGA,IAAI,MAAM,SAAS;AAAA,QACjB,IACE,KAAK,WACL,OAAO,KAAK,YAAY,YACxB,aAAa,KAAK,WAClB,KAAK,QAAQ,mBAAmB,KAChC;AAAA,UACA,eAAe;AAAA,YACb,SAAS,IAAI,IAAK,KAAK,QAAyB,OAAO;AAAA,UACzD;AAAA,QACF,EAAO,SACL,KAAK,WACL,OAAO,KAAK,YAAY,YACxB,+BAA+B,KAAK,WACnC,KAAK,QAAoD,8BAA8B,QACxF,oBAAoB,KAAK,SACzB;AAAA,UAEA,MAAM,aAAc,KAAK,QAAuC;AAAA,UAChE,MAAM,QAAQ,yCAAmC,UAAU;AAAA,UAC3D,IAAI,SAAS,MAAM,mBAAmB,KAAK;AAAA,YACzC,eAAe;AAAA,cACb,SAAS,IAAI,IAAI,MAAM,OAAO;AAAA,YAChC;AAAA,UACF;AAAA,QACF,EAAO;AAAA,UACL,eAAe,EAAE,SAAS,IAAI,IAAM;AAAA,UACpC,YAAY,KAAK,UAAU,OAAO,QAAQ,KAAK,OAAO,GAAG;AAAA,YACvD,aAAa,QAAQ,IAAI,IAAI,YAAY,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC;AAAA,UAC7D;AAAA;AAAA,MAEJ;AAAA,MAEA,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,KAAK;AAAA,QACL,YAAY;AAAA,QACZ,MAAM,MAAM,SAAS;AAAA,QACrB,IAAI,UAAU,OAAO,SAAS;AAAA,QAC9B;AAAA,MACF;AAAA;AAAA,IAEF,YAAY;AAAA,MACV,MAAM;AAAA,QACJ,GAAG,GAAsB;AAAA,UACvB,IAAI,CAAC,KAAK;AAAA,YAAM,OAAO;AAAA,UACvB,IAAI,CAAC,cAAc;AAAA,YAEjB,OAAO,KAAK;AAAA,UACd;AAAA,UAEA,MAAM,WAAW,KAAK;AAAA,UACtB,IAAI,SAAS;AAAA,UACb,MAAM,YAAY;AAAA,UAClB,OAAO,aAAa;AAAA,YAClB,IAAI,CAAC,YAAY;AAAA,cACf,IAAI,UAAU,SAAS,QAAQ;AAAA,gBAC7B,WAAW,MAAM;AAAA,gBACjB;AAAA,cACF;AAAA,cACA,MAAM,QAAQ,SAAS,MAAM,QAAQ,KAAK,IAAI,SAAS,WAAW,SAAS,MAAM,CAAC;AAAA,cAClF,UAAU,MAAM;AAAA,cAChB,WAAW,QAAQ,KAAK;AAAA;AAAA,UAE5B,CAAC;AAAA;AAAA,MAEL;AAAA,MACA,UAAU;AAAA,QACR,GAAG,GAAsB;AAAA,UACvB,OAAO,KAAK;AAAA;AAAA,MAEhB;AAAA,MACA,SAAS;AAAA,QACP,GAAG,GAAsB;AAAA,UACvB,OAAO,iCAAkB,KAAK,YAAY;AAAA;AAAA,MAE9C;AAAA,MACA,IAAI;AAAA,QACF,GAAG,GAAsB;AAAA,UACvB,OAAO,KAAK;AAAA;AAAA,MAEhB;AAAA,MACA,YAAY;AAAA,QACV,GAAG,GAAsB;AAAA,UACvB,OAAO,KAAK;AAAA;AAAA,MAEhB;AAAA,MACA,QAAQ;AAAA,QACN,GAAG,GAAsB;AAAA,UACvB,OAAO,KAAK;AAAA;AAAA,MAEhB;AAAA,MACA,YAAY;AAAA,QACV,GAAG,GAAsB;AAAA,UACvB,OAAO,KAAK;AAAA;AAAA,MAEhB;AAAA,MACA,MAAM;AAAA,QACJ,GAAG,GAAsB;AAAA,UACvB,OAAO,KAAK;AAAA;AAAA,MAEhB;AAAA,MACA,KAAK;AAAA,QACH,GAAG,GAAsB;AAAA,UACvB,OAAO,KAAK;AAAA;AAAA,MAEhB;AAAA,IACF;AAAA,IACA,SAAS;AAAA,WACD,YAAW,GAA4C;AAAA,QAC3D,IAAI,KAAK,UAAU;AAAA,UACjB,MAAM,IAAI,UAAU,gCAAgC;AAAA,QACtD;AAAA,QACA,KAAK,WAAW;AAAA,QAChB,IAAI,CAAC,KAAK,MAAM;AAAA,UACd,OAAO,IAAI,YAAY,CAAC;AAAA,QAC1B;AAAA,QACA,OAAO,KAAK,KAAK,OAAO,MACtB,KAAK,KAAK,YACV,KAAK,KAAK,aAAa,KAAK,KAAK,UACnC;AAAA;AAAA,WAEI,KAAI,GAAuC;AAAA,QAC/C,IAAI,KAAK,UAAU;AAAA,UACjB,MAAM,IAAI,UAAU,gCAAgC;AAAA,QACtD;AAAA,QACA,KAAK,WAAW;AAAA,QAChB,MAAM,cACJ,KAAK,aAAa,QAAQ,IAAI,cAAc,IAAI,MAAM;AAAA,QACxD,OAAO;AAAA,UACL,OAAO,KAAK,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC;AAAA,UAClC,MAAM;AAAA,UACN,MAAM,KAAK,MAAM,UAAU;AAAA,QAC7B;AAAA;AAAA,MAEF,KAAK,GAAqC;AAAA,QACxC,IAAI,KAAK,UAAU;AAAA,UACjB,MAAM,IAAI,UAAU,gCAAgC;AAAA,QACtD;AAAA,QACA,OAAO;AAAA,aACF;AAAA,UACH,cAAc;AAAA,YACZ,SAAS,IAAI,IAAI,KAAK,aAAa,OAAO;AAAA,UAC5C;AAAA,UACA,MAAM,KAAK,OAAO,IAAI,WAAW,KAAK,IAAI,IAAI;AAAA,UAC9C,UAAU;AAAA,QACZ;AAAA;AAAA,WAEI,KAAI,GAAwC;AAAA,QAChD,IAAI,KAAK,UAAU;AAAA,UACjB,MAAM,IAAI,UAAU,gCAAgC;AAAA,QACtD;AAAA,QACA,KAAK,WAAW;AAAA,QAChB,IAAI,CAAC,KAAK,MAAM;AAAA,UACd,OAAO,KAAK,MAAM,EAAE;AAAA,QACtB;AAAA,QACA,MAAM,OAAO,IAAI,YAAY,EAAE,OAAO,KAAK,IAAI;AAAA,QAC/C,OAAO,KAAK,MAAM,IAAI;AAAA;AAAA,WAElB,KAAI,GAAuC;AAAA,QAC/C,IAAI,KAAK,UAAU;AAAA,UACjB,MAAM,IAAI,UAAU,gCAAgC;AAAA,QACtD;AAAA,QACA,KAAK,WAAW;AAAA,QAChB,IAAI,CAAC,KAAK,MAAM;AAAA,UACd,OAAO;AAAA,QACT;AAAA,QACA,OAAO,IAAI,YAAY,EAAE,OAAO,KAAK,IAAI;AAAA;AAAA,WAErC,SAAQ,GAA8C;AAAA,QAC1D,IAAI,KAAK,UAAU;AAAA,UACjB,MAAM,IAAI,UAAU,gCAAgC;AAAA,QACtD;AAAA,QACA,KAAK,WAAW;AAAA,QAChB,IAAI,CAAC,KAAK,MAAM;AAAA,UACd,OAAO,EAAE,SAAS,CAAC,EAAE;AAAA,QACvB;AAAA,QAEA,MAAM,cAAc,KAAK,aAAa,QAAQ,IAAI,cAAc,IAAI,MAAM;AAAA,QAE1E,IAAI,YAAY,SAAS,qBAAqB,GAAG;AAAA,UAC/C,OAAO,wCAAuB,KAAK,MAAM,WAAW;AAAA,QACtD,EAAO,SAAI,YAAY,SAAS,mCAAmC,GAAG;AAAA,UACpE,OAAO,yCAAwB,KAAK,IAAI;AAAA,QAC1C;AAAA,QAEA,MAAM,IAAI,UAAU,qCAAqC;AAAA;AAAA,IAE7D;AAAA,EACF,CAAC;AAAA,EAED,OAAO;AAAA;AAOF,SAAS,wBAAwB,CAAC,SAA+B;AAAA,EACtE,MAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0B1B,MAAM,SAAS,QAAQ,SAAS,iBAAiB;AAAA,EACjD,IAAI,OAAO,OAAO;AAAA,IAChB,OAAO,MAAM,QAAQ;AAAA,EACvB,EAAO;AAAA,IACL,OAAO,MAAM,QAAQ;AAAA;AAAA;AAOlB,SAAS,qBAAqB,CAAC,OAA0D;AAAA,EAC9F,MAAM,YAAa,MAAwB,QAAS,MAAkC;AAAA,EACtF,MAAM,WAAY,MAAwB;AAAA,EAC1C,MAAM,SAAU,MAAwB,UAAU;AAAA,EAClD,MAAM,aAAc,MAAwB,cAAc;AAAA,EAG1D,IAAI;AAAA,EACJ,IAAK,MAAwB,cAAc;AAAA,IACzC,eAAgB,MAAwB;AAAA,EAC1C,EAAO,SAAK,MAAkC,SAAS;AAAA,IAErD,MAAM,UAAW,MAAkC;AAAA,IACnD,IAAI,QAAQ,mBAAmB,KAAK;AAAA,MAClC,eAAe,EAAE,SAAS,QAAQ,QAAQ;AAAA,IAC5C,EAAO;AAAA,MACL,eAAe,EAAE,SAAS,IAAI,IAAM;AAAA;AAAA,EAExC,EAAO;AAAA,IACL,eAAe,EAAE,SAAS,IAAI,IAAM;AAAA;AAAA,EAKtC,IAAI,OAAwB;AAAA,EAC5B,IAAI,WAAW;AAAA,IACb,IAAI,aAAa,UAAU;AAAA,MACzB,OAAO,IAAI,YAAY,EAAE,OAAO,SAAuB;AAAA,IACzD,EAAO;AAAA,MAEL,MAAM,QAAQ;AAAA,MACd,OAAO,MAAM,OAAO,MAAM,MAAM,YAAY,MAAM,aAAa,MAAM,UAAU;AAAA;AAAA,EAEnF;AAAA,EAEA,OAAO,IAAI,SAAS,MAAM;AAAA,IACxB;AAAA,IACA;AAAA,IACA,SAAS,oCAAqB,YAAY;AAAA,EAC5C,CAAC;AAAA;AAMH,eAAsB,6BAA6B,CACjD,UACwB;AAAA,EACxB,MAAM,OAAO,SAAS,OAClB,IAAI,WAAW,MAAM,SAAS,YAAY,CAAC,IAC3C;AAAA,EAEJ,MAAM,eAA6B,EAAE,SAAS,IAAI,IAAM;AAAA,EACxD,SAAS,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AAAA,IACvC,MAAM,WAAW,aAAa,QAAQ,IAAI,IAAI,YAAY,CAAC,KAAK,CAAC;AAAA,IACjE,SAAS,KAAK,KAAK;AAAA,IACnB,aAAa,QAAQ,IAAI,IAAI,YAAY,GAAG,QAAQ;AAAA,GACrD;AAAA,EAGD,MAAM,cAAc,SAAS,QAAQ,IAAI,cAAc;AAAA,EACvD,IAAI,WAAuC;AAAA,EAC3C,IAAI,MAAM;AAAA,IACR,IAAI,gBAAgB,YAAY,WAAW,OAAO,KAAK,YAAY,SAAS,MAAM,KAAK,YAAY,SAAS,KAAK,IAAI;AAAA,MACnH,WAAW;AAAA,IACb,EAAO;AAAA,MACL,WAAW;AAAA;AAAA,EAEf;AAAA,EAEA,OAAO;AAAA,IACL,QAAQ,SAAS;AAAA,IACjB,YAAY,SAAS;AAAA,IACrB;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,KAAK,SAAS;AAAA,IACd,YAAY,SAAS;AAAA,IACrB,MAAM,SAAS;AAAA,IACf,IAAI,SAAS;AAAA,IACb;AAAA,EACF;AAAA;",
|
|
8
|
+
"debugId": "253BFDBC49B0C92064756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/cjs/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/fetch/src/globals/request.ts
|
|
3
|
-
import { defineClass } from "@ricsam/quickjs-core";
|
|
3
|
+
import { defineClass, getInstanceStateById } from "@ricsam/quickjs-core";
|
|
4
4
|
import { createHeadersStateFromNative, createHeadersLike } from "./headers.mjs";
|
|
5
5
|
import { parseMultipartFormData, parseUrlEncodedFormData } from "./form-data.mjs";
|
|
6
6
|
function createRequestClass(context, stateMap, createStream) {
|
|
@@ -46,6 +46,14 @@ function createRequestClass(context, stateMap, createStream) {
|
|
|
46
46
|
headersState = {
|
|
47
47
|
headers: new Map(init.headers.headers)
|
|
48
48
|
};
|
|
49
|
+
} else if ("__isDefineClassInstance__" in init.headers && init.headers.__isDefineClassInstance__ === true && "__instanceId__" in init.headers) {
|
|
50
|
+
const instanceId = init.headers.__instanceId__;
|
|
51
|
+
const state = getInstanceStateById(instanceId);
|
|
52
|
+
if (state && state.headers instanceof Map) {
|
|
53
|
+
headersState = {
|
|
54
|
+
headers: new Map(state.headers)
|
|
55
|
+
};
|
|
56
|
+
}
|
|
49
57
|
} else {
|
|
50
58
|
headersState = { headers: new Map };
|
|
51
59
|
for (const [key, value] of Object.entries(init.headers)) {
|
|
@@ -326,4 +334,4 @@ export {
|
|
|
326
334
|
addRequestFormDataMethod
|
|
327
335
|
};
|
|
328
336
|
|
|
329
|
-
//# debugId=
|
|
337
|
+
//# debugId=5790EB732C5A0C5964756E2164756E21
|
|
@@ -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 { defineClass } from \"@ricsam/quickjs-core\";\nimport type { RequestState, HeadersState, AbortSignalState, FormDataState } from \"../types.mjs\";\nimport { createHeadersStateFromNative, createHeadersLike } from \"./headers.mjs\";\nimport { parseMultipartFormData, parseUrlEncodedFormData } from \"./form-data.mjs\";\n\n/**\n * Type for the stream factory function\n */\ntype StreamFactory = (source: UnderlyingSource) => QuickJSHandle;\n\n/**\n * Create the Request class for QuickJS\n */\nexport function createRequestClass(\n context: QuickJSContext,\n stateMap: StateMap,\n createStream?: StreamFactory\n): QuickJSHandle {\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 let url = \"\";\n let method = \"GET\";\n let headersState: HeadersState = { headers: new Map() };\n let body: Uint8Array | null = null;\n let signal: AbortSignalState | null = null;\n\n // Handle input\n if (typeof input === \"string\") {\n url = input;\n } else if (input && typeof input === \"object\") {\n // Could be URL or Request-like\n if (\"url\" in input) {\n url = String((input as { url: string }).url);\n }\n if (\"method\" in input) {\n method = String((input as { method: string }).method);\n }\n if (\"headersState\" in input) {\n const inputHeaders = (input as RequestState).headersState;\n headersState = {\n headers: new Map(inputHeaders.headers),\n };\n }\n if (\"body\" in input && (input as RequestState).body) {\n body = (input as RequestState).body;\n }\n if (\"signal\" in input) {\n signal = (input as RequestState).signal;\n }\n }\n\n // Apply init options\n if (init) {\n if (init.method) {\n method = init.method.toUpperCase();\n }\n if (init.headers) {\n if (init.headers && typeof init.headers === \"object\") {\n if (\"headers\" in init.headers && init.headers.headers instanceof Map) {\n headersState = {\n headers: new Map((init.headers as HeadersState).headers),\n };\n } else {\n headersState = { headers: new Map() };\n for (const [key, value] of Object.entries(init.headers)) {\n headersState.headers.set(key.toLowerCase(), [String(value)]);\n }\n }\n }\n }\n if (init.body !== undefined && init.body !== null) {\n if (typeof init.body === \"string\") {\n body = new TextEncoder().encode(init.body);\n } else if (init.body instanceof ArrayBuffer) {\n body = new Uint8Array(init.body);\n } else if (init.body instanceof Uint8Array) {\n body = init.body;\n }\n }\n if (init.signal) {\n signal = init.signal;\n }\n }\n\n return {\n method,\n url,\n headersState,\n body,\n bodyUsed: false,\n cache: init?.cache || \"default\",\n credentials: init?.credentials || \"same-origin\",\n destination: \"\",\n integrity: init?.integrity || \"\",\n keepalive: init?.keepalive || false,\n mode: init?.mode || \"cors\",\n redirect: init?.redirect || \"follow\",\n referrer: init?.referrer || \"about:client\",\n referrerPolicy: init?.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) {\n if (!this.body) return null;\n if (!createStream) {\n // Fallback: return raw body if no stream factory\n return this.body;\n }\n // Create a ReadableStream from the body data\n const bodyData = this.body;\n let offset = 0;\n const chunkSize = 65536; // 64KB chunks\n return 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 },\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): Promise<ArrayBuffer> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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): 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 return {\n parts: this.body ? [this.body] : [],\n type: contentType,\n size: this.body?.length || 0,\n };\n },\n clone(this: RequestState): RequestState {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n return {\n ...this,\n headersState: {\n headers: new Map(this.headersState.headers),\n },\n body: this.body ? new Uint8Array(this.body) : null,\n bodyUsed: false,\n };\n },\n async json(this: RequestState): Promise<unknown> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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): Promise<string> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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): 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 if (!this.body) {\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(this.body, contentType);\n } else if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n formDataState = parseUrlEncodedFormData(this.body);\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 * Create a RequestState from a native Request object\n */\nexport async function createRequestStateFromNative(\n request: Request\n): Promise<RequestState> {\n const body = request.body\n ? new Uint8Array(await request.arrayBuffer())\n : null;\n\n return {\n method: request.method,\n url: request.url,\n headersState: createHeadersStateFromNative(request.headers),\n body,\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 };\n}\n"
|
|
5
|
+
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { StateMap } from \"@ricsam/quickjs-core\";\nimport { defineClass, getInstanceStateById } from \"@ricsam/quickjs-core\";\nimport type { RequestState, HeadersState, AbortSignalState, FormDataState } from \"../types.mjs\";\nimport { createHeadersStateFromNative, createHeadersLike } from \"./headers.mjs\";\nimport { parseMultipartFormData, parseUrlEncodedFormData } from \"./form-data.mjs\";\n\n/**\n * Type for the stream factory function\n */\ntype StreamFactory = (source: UnderlyingSource) => QuickJSHandle;\n\n/**\n * Create the Request class for QuickJS\n */\nexport function createRequestClass(\n context: QuickJSContext,\n stateMap: StateMap,\n createStream?: StreamFactory\n): QuickJSHandle {\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 let url = \"\";\n let method = \"GET\";\n let headersState: HeadersState = { headers: new Map() };\n let body: Uint8Array | null = null;\n let signal: AbortSignalState | null = null;\n\n // Handle input\n if (typeof input === \"string\") {\n url = input;\n } else if (input && typeof input === \"object\") {\n // Could be URL or Request-like\n if (\"url\" in input) {\n url = String((input as { url: string }).url);\n }\n if (\"method\" in input) {\n method = String((input as { method: string }).method);\n }\n if (\"headersState\" in input) {\n const inputHeaders = (input as RequestState).headersState;\n headersState = {\n headers: new Map(inputHeaders.headers),\n };\n }\n if (\"body\" in input && (input as RequestState).body) {\n body = (input as RequestState).body;\n }\n if (\"signal\" in input) {\n signal = (input as RequestState).signal;\n }\n }\n\n // Apply init options\n if (init) {\n if (init.method) {\n method = init.method.toUpperCase();\n }\n if (init.headers) {\n if (init.headers && typeof init.headers === \"object\") {\n if (\"headers\" in init.headers && init.headers.headers instanceof Map) {\n headersState = {\n headers: new Map((init.headers as HeadersState).headers),\n };\n } else if (\n \"__isDefineClassInstance__\" in init.headers &&\n (init.headers as { __isDefineClassInstance__?: boolean }).__isDefineClassInstance__ === true &&\n \"__instanceId__\" in init.headers\n ) {\n // Unmarshalled Headers instance from defineClass\n const instanceId = (init.headers as { __instanceId__: number }).__instanceId__;\n const state = getInstanceStateById<HeadersState>(instanceId);\n if (state && state.headers instanceof Map) {\n headersState = {\n headers: new Map(state.headers),\n };\n }\n } else {\n headersState = { headers: new Map() };\n for (const [key, value] of Object.entries(init.headers)) {\n headersState.headers.set(key.toLowerCase(), [String(value)]);\n }\n }\n }\n }\n if (init.body !== undefined && init.body !== null) {\n if (typeof init.body === \"string\") {\n body = new TextEncoder().encode(init.body);\n } else if (init.body instanceof ArrayBuffer) {\n body = new Uint8Array(init.body);\n } else if (init.body instanceof Uint8Array) {\n body = init.body;\n }\n }\n if (init.signal) {\n signal = init.signal;\n }\n }\n\n return {\n method,\n url,\n headersState,\n body,\n bodyUsed: false,\n cache: init?.cache || \"default\",\n credentials: init?.credentials || \"same-origin\",\n destination: \"\",\n integrity: init?.integrity || \"\",\n keepalive: init?.keepalive || false,\n mode: init?.mode || \"cors\",\n redirect: init?.redirect || \"follow\",\n referrer: init?.referrer || \"about:client\",\n referrerPolicy: init?.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) {\n if (!this.body) return null;\n if (!createStream) {\n // Fallback: return raw body if no stream factory\n return this.body;\n }\n // Create a ReadableStream from the body data\n const bodyData = this.body;\n let offset = 0;\n const chunkSize = 65536; // 64KB chunks\n return 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 },\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): Promise<ArrayBuffer> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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): 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 return {\n parts: this.body ? [this.body] : [],\n type: contentType,\n size: this.body?.length || 0,\n };\n },\n clone(this: RequestState): RequestState {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n return {\n ...this,\n headersState: {\n headers: new Map(this.headersState.headers),\n },\n body: this.body ? new Uint8Array(this.body) : null,\n bodyUsed: false,\n };\n },\n async json(this: RequestState): Promise<unknown> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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): Promise<string> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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): 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 if (!this.body) {\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(this.body, contentType);\n } else if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n formDataState = parseUrlEncodedFormData(this.body);\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 * Create a RequestState from a native Request object\n */\nexport async function createRequestStateFromNative(\n request: Request\n): Promise<RequestState> {\n const body = request.body\n ? new Uint8Array(await request.arrayBuffer())\n : null;\n\n return {\n method: request.method,\n url: request.url,\n headersState: createHeadersStateFromNative(request.headers),\n body,\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 };\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "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",
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "5790EB732C5A0C5964756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/fetch/src/globals/response.ts
|
|
3
|
-
import { defineClass } from "@ricsam/quickjs-core";
|
|
3
|
+
import { defineClass, getInstanceStateById } from "@ricsam/quickjs-core";
|
|
4
4
|
import { headersStateToNative, createHeadersLike } from "./headers.mjs";
|
|
5
5
|
import { parseMultipartFormData, parseUrlEncodedFormData } from "./form-data.mjs";
|
|
6
6
|
function createResponseClass(context, stateMap, createStream) {
|
|
@@ -10,16 +10,20 @@ function createResponseClass(context, stateMap, createStream) {
|
|
|
10
10
|
const bodyInit = args[0];
|
|
11
11
|
const init = args[1];
|
|
12
12
|
let body = null;
|
|
13
|
+
let bodyType = null;
|
|
13
14
|
const status = init?.status ?? 200;
|
|
14
15
|
const statusText = init?.statusText ?? "";
|
|
15
16
|
let headersState = { headers: new Map };
|
|
16
17
|
if (bodyInit !== null && bodyInit !== undefined) {
|
|
17
18
|
if (typeof bodyInit === "string") {
|
|
18
19
|
body = new TextEncoder().encode(bodyInit);
|
|
20
|
+
bodyType = "string";
|
|
19
21
|
} else if (bodyInit instanceof ArrayBuffer) {
|
|
20
22
|
body = new Uint8Array(bodyInit);
|
|
23
|
+
bodyType = "binary";
|
|
21
24
|
} else if (bodyInit instanceof Uint8Array) {
|
|
22
25
|
body = bodyInit;
|
|
26
|
+
bodyType = "binary";
|
|
23
27
|
} else if (bodyInit && typeof bodyInit === "object" && "parts" in bodyInit) {
|
|
24
28
|
const parts = bodyInit.parts;
|
|
25
29
|
const totalLength = parts.reduce((sum, p) => sum + p.length, 0);
|
|
@@ -29,6 +33,7 @@ function createResponseClass(context, stateMap, createStream) {
|
|
|
29
33
|
body.set(part, offset);
|
|
30
34
|
offset += part.length;
|
|
31
35
|
}
|
|
36
|
+
bodyType = "binary";
|
|
32
37
|
}
|
|
33
38
|
}
|
|
34
39
|
if (init?.headers) {
|
|
@@ -36,6 +41,14 @@ function createResponseClass(context, stateMap, createStream) {
|
|
|
36
41
|
headersState = {
|
|
37
42
|
headers: new Map(init.headers.headers)
|
|
38
43
|
};
|
|
44
|
+
} else if (init.headers && typeof init.headers === "object" && "__isDefineClassInstance__" in init.headers && init.headers.__isDefineClassInstance__ === true && "__instanceId__" in init.headers) {
|
|
45
|
+
const instanceId = init.headers.__instanceId__;
|
|
46
|
+
const state = getInstanceStateById(instanceId);
|
|
47
|
+
if (state && state.headers instanceof Map) {
|
|
48
|
+
headersState = {
|
|
49
|
+
headers: new Map(state.headers)
|
|
50
|
+
};
|
|
51
|
+
}
|
|
39
52
|
} else {
|
|
40
53
|
headersState = { headers: new Map };
|
|
41
54
|
for (const [key, value] of Object.entries(init.headers)) {
|
|
@@ -52,7 +65,8 @@ function createResponseClass(context, stateMap, createStream) {
|
|
|
52
65
|
url: "",
|
|
53
66
|
redirected: false,
|
|
54
67
|
type: init?._type ?? "default",
|
|
55
|
-
ok: status >= 200 && status < 300
|
|
68
|
+
ok: status >= 200 && status < 300,
|
|
69
|
+
bodyType
|
|
56
70
|
};
|
|
57
71
|
},
|
|
58
72
|
properties: {
|
|
@@ -232,7 +246,8 @@ function addResponseStaticMethods(context) {
|
|
|
232
246
|
}
|
|
233
247
|
}
|
|
234
248
|
function responseStateToNative(state) {
|
|
235
|
-
const
|
|
249
|
+
const bodyBytes = state.body ?? state.body;
|
|
250
|
+
const bodyType = state.bodyType;
|
|
236
251
|
const status = state.status ?? 200;
|
|
237
252
|
const statusText = state.statusText ?? "";
|
|
238
253
|
let headersState;
|
|
@@ -248,6 +263,15 @@ function responseStateToNative(state) {
|
|
|
248
263
|
} else {
|
|
249
264
|
headersState = { headers: new Map };
|
|
250
265
|
}
|
|
266
|
+
let body = null;
|
|
267
|
+
if (bodyBytes) {
|
|
268
|
+
if (bodyType === "string") {
|
|
269
|
+
body = new TextDecoder().decode(bodyBytes);
|
|
270
|
+
} else {
|
|
271
|
+
const uint8 = bodyBytes;
|
|
272
|
+
body = uint8.buffer.slice(uint8.byteOffset, uint8.byteOffset + uint8.byteLength);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
251
275
|
return new Response(body, {
|
|
252
276
|
status,
|
|
253
277
|
statusText,
|
|
@@ -262,6 +286,15 @@ async function createResponseStateFromNative(response) {
|
|
|
262
286
|
existing.push(value);
|
|
263
287
|
headersState.headers.set(key.toLowerCase(), existing);
|
|
264
288
|
});
|
|
289
|
+
const contentType = response.headers.get("content-type");
|
|
290
|
+
let bodyType = null;
|
|
291
|
+
if (body) {
|
|
292
|
+
if (contentType && (contentType.startsWith("text/") || contentType.includes("json") || contentType.includes("xml"))) {
|
|
293
|
+
bodyType = "string";
|
|
294
|
+
} else {
|
|
295
|
+
bodyType = "binary";
|
|
296
|
+
}
|
|
297
|
+
}
|
|
265
298
|
return {
|
|
266
299
|
status: response.status,
|
|
267
300
|
statusText: response.statusText,
|
|
@@ -271,7 +304,8 @@ async function createResponseStateFromNative(response) {
|
|
|
271
304
|
url: response.url,
|
|
272
305
|
redirected: response.redirected,
|
|
273
306
|
type: response.type,
|
|
274
|
-
ok: response.ok
|
|
307
|
+
ok: response.ok,
|
|
308
|
+
bodyType
|
|
275
309
|
};
|
|
276
310
|
}
|
|
277
311
|
export {
|
|
@@ -281,4 +315,4 @@ export {
|
|
|
281
315
|
addResponseStaticMethods
|
|
282
316
|
};
|
|
283
317
|
|
|
284
|
-
//# debugId=
|
|
318
|
+
//# debugId=77C0707215771B4364756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/globals/response.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { StateMap } from \"@ricsam/quickjs-core\";\nimport { defineClass } from \"@ricsam/quickjs-core\";\nimport type { ResponseState, HeadersState, FormDataState } from \"../types.mjs\";\nimport { headersStateToNative, createHeadersLike } from \"./headers.mjs\";\nimport { parseMultipartFormData, parseUrlEncodedFormData } from \"./form-data.mjs\";\n\n/**\n * Type for the stream factory function\n */\ntype StreamFactory = (source: UnderlyingSource) => QuickJSHandle;\n\n/**\n * Create the Response class for QuickJS\n */\nexport function createResponseClass(\n context: QuickJSContext,\n stateMap: StateMap,\n createStream?: StreamFactory\n): QuickJSHandle {\n const classHandle = defineClass<ResponseState>(context, stateMap, {\n name: \"Response\",\n construct: (args) => {\n const bodyInit = args[0];\n const init = args[1] as {\n status?: number;\n statusText?: string;\n headers?: object;\n _type?: string; // Internal: for Response.error() to set type\n } | undefined;\n\n let body: Uint8Array | null = null;\n const status = init?.status ?? 200;\n const statusText = init?.statusText ?? \"\";\n let headersState: HeadersState = { headers: new Map() };\n\n // Parse body\n if (bodyInit !== null && bodyInit !== undefined) {\n if (typeof bodyInit === \"string\") {\n body = new TextEncoder().encode(bodyInit);\n } else if (bodyInit instanceof ArrayBuffer) {\n body = new Uint8Array(bodyInit);\n } else if (bodyInit instanceof Uint8Array) {\n body = bodyInit;\n } else if (\n bodyInit &&\n typeof bodyInit === \"object\" &&\n \"parts\" in bodyInit\n ) {\n // Blob-like\n const parts = (bodyInit as { parts: Uint8Array[] }).parts;\n const totalLength = parts.reduce((sum, p) => sum + p.length, 0);\n body = new Uint8Array(totalLength);\n let offset = 0;\n for (const part of parts) {\n body.set(part, offset);\n offset += part.length;\n }\n }\n }\n\n // Parse headers\n if (init?.headers) {\n if (\n init.headers &&\n typeof init.headers === \"object\" &&\n \"headers\" in init.headers &&\n init.headers.headers instanceof Map\n ) {\n headersState = {\n headers: new Map((init.headers as HeadersState).headers),\n };\n } else {\n headersState = { headers: new Map() };\n for (const [key, value] of Object.entries(init.headers)) {\n headersState.headers.set(key.toLowerCase(), [String(value)]);\n }\n }\n }\n\n return {\n status,\n statusText,\n headersState,\n body,\n bodyUsed: false,\n url: \"\",\n redirected: false,\n type: init?._type ?? \"default\",\n ok: status >= 200 && status < 300,\n };\n },\n properties: {\n body: {\n get(this: ResponseState) {\n if (!this.body) return null;\n if (!createStream) {\n // Fallback: return raw body if no stream factory\n return this.body;\n }\n // Create a ReadableStream from the body data\n const bodyData = this.body;\n let offset = 0;\n const chunkSize = 65536; // 64KB chunks\n return 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 },\n },\n bodyUsed: {\n get(this: ResponseState) {\n return this.bodyUsed;\n },\n },\n headers: {\n get(this: ResponseState) {\n return createHeadersLike(this.headersState);\n },\n },\n ok: {\n get(this: ResponseState) {\n return this.ok;\n },\n },\n redirected: {\n get(this: ResponseState) {\n return this.redirected;\n },\n },\n status: {\n get(this: ResponseState) {\n return this.status;\n },\n },\n statusText: {\n get(this: ResponseState) {\n return this.statusText;\n },\n },\n type: {\n get(this: ResponseState) {\n return this.type;\n },\n },\n url: {\n get(this: ResponseState) {\n return this.url;\n },\n },\n },\n methods: {\n async arrayBuffer(this: ResponseState): Promise<ArrayBuffer> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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: ResponseState): Promise<object> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n const contentType =\n this.headersState.headers.get(\"content-type\")?.[0] || \"\";\n return {\n parts: this.body ? [this.body] : [],\n type: contentType,\n size: this.body?.length || 0,\n };\n },\n clone(this: ResponseState): ResponseState {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n return {\n ...this,\n headersState: {\n headers: new Map(this.headersState.headers),\n },\n body: this.body ? new Uint8Array(this.body) : null,\n bodyUsed: false,\n };\n },\n async json(this: ResponseState): Promise<unknown> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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: ResponseState): Promise<string> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n if (!this.body) {\n return \"\";\n }\n return new TextDecoder().decode(this.body);\n },\n async formData(this: ResponseState): Promise<FormDataState> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n if (!this.body) {\n return { entries: [] };\n }\n\n const contentType = this.headersState.headers.get(\"content-type\")?.[0] || \"\";\n\n if (contentType.includes(\"multipart/form-data\")) {\n return parseMultipartFormData(this.body, contentType);\n } else if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n return parseUrlEncodedFormData(this.body);\n }\n\n throw new TypeError(\"Could not parse content as FormData\");\n },\n },\n });\n\n return classHandle;\n}\n\n/**\n * Add static methods to Response class after it's been set on global\n * This must be called after Response and Headers are available on global\n */\nexport function addResponseStaticMethods(context: QuickJSContext): void {\n const staticMethodsCode = `\n Response.error = function() {\n return new Response(null, { status: 0, _type: \"error\" });\n };\n\n Response.json = function(data, init = {}) {\n const body = JSON.stringify(data);\n // Merge content-type with any provided headers\n const headers = Object.assign(\n { \"content-type\": \"application/json\" },\n init.headers || {}\n );\n return new Response(body, {\n status: init.status ?? 200,\n statusText: init.statusText ?? \"\",\n headers: headers\n });\n };\n\n Response.redirect = function(url, status = 302) {\n return new Response(null, {\n status: status,\n headers: { \"location\": String(url) }\n });\n };\n `;\n const result = context.evalCode(staticMethodsCode);\n if (result.error) {\n result.error.dispose();\n } else {\n result.value.dispose();\n }\n}\n\n/**\n * Convert ResponseState (or unmarshalled Response object) to native Response\n */\nexport function responseStateToNative(state: ResponseState | Record<string, unknown>): Response {\n const body = (state as ResponseState).body ?? (state as Record<string, unknown>).body;\n const status = (state as ResponseState).status ?? 200;\n const statusText = (state as ResponseState).statusText ?? \"\";\n\n // Handle both headersState (internal) and headers (from getter)\n let headersState: HeadersState;\n if ((state as ResponseState).headersState) {\n headersState = (state as ResponseState).headersState;\n } else if ((state as Record<string, unknown>).headers) {\n // When unmarshalled, headers is the HeadersLike object from getter\n const headers = (state as Record<string, unknown>).headers as { headers?: Map<string, string[]> };\n if (headers.headers instanceof Map) {\n headersState = { headers: headers.headers };\n } else {\n headersState = { headers: new Map() };\n }\n } else {\n headersState = { headers: new Map() };\n }\n\n return new Response(body as BodyInit | null, {\n status,\n statusText,\n headers: headersStateToNative(headersState),\n });\n}\n\n/**\n * Create a ResponseState from a native Response\n */\nexport async function createResponseStateFromNative(\n response: Response\n): Promise<ResponseState> {\n const body = response.body\n ? new Uint8Array(await response.arrayBuffer())\n : null;\n\n const headersState: HeadersState = { headers: new Map() };\n response.headers.forEach((value, key) => {\n const existing = headersState.headers.get(key.toLowerCase()) || [];\n existing.push(value);\n headersState.headers.set(key.toLowerCase(), existing);\n });\n\n return {\n status: response.status,\n statusText: response.statusText,\n headersState,\n body,\n bodyUsed: false,\n url: response.url,\n redirected: response.redirected,\n type: response.type,\n ok: response.ok,\n };\n}\n"
|
|
5
|
+
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { StateMap } from \"@ricsam/quickjs-core\";\nimport { defineClass, getInstanceStateById } from \"@ricsam/quickjs-core\";\nimport type { ResponseState, HeadersState, FormDataState } from \"../types.mjs\";\nimport { headersStateToNative, createHeadersLike } from \"./headers.mjs\";\nimport { parseMultipartFormData, parseUrlEncodedFormData } from \"./form-data.mjs\";\n\n/**\n * Type for the stream factory function\n */\ntype StreamFactory = (source: UnderlyingSource) => QuickJSHandle;\n\n/**\n * Create the Response class for QuickJS\n */\nexport function createResponseClass(\n context: QuickJSContext,\n stateMap: StateMap,\n createStream?: StreamFactory\n): QuickJSHandle {\n const classHandle = defineClass<ResponseState>(context, stateMap, {\n name: \"Response\",\n construct: (args) => {\n const bodyInit = args[0];\n const init = args[1] as {\n status?: number;\n statusText?: string;\n headers?: object;\n _type?: string; // Internal: for Response.error() to set type\n } | undefined;\n\n let body: Uint8Array | null = null;\n let bodyType: \"string\" | \"binary\" | null = null;\n const status = init?.status ?? 200;\n const statusText = init?.statusText ?? \"\";\n let headersState: HeadersState = { headers: new Map() };\n\n // Parse body\n if (bodyInit !== null && bodyInit !== undefined) {\n if (typeof bodyInit === \"string\") {\n body = new TextEncoder().encode(bodyInit);\n bodyType = \"string\";\n } else if (bodyInit instanceof ArrayBuffer) {\n body = new Uint8Array(bodyInit);\n bodyType = \"binary\";\n } else if (bodyInit instanceof Uint8Array) {\n body = bodyInit;\n bodyType = \"binary\";\n } else if (\n bodyInit &&\n typeof bodyInit === \"object\" &&\n \"parts\" in bodyInit\n ) {\n // Blob-like\n const parts = (bodyInit as { parts: Uint8Array[] }).parts;\n const totalLength = parts.reduce((sum, p) => sum + p.length, 0);\n body = new Uint8Array(totalLength);\n let offset = 0;\n for (const part of parts) {\n body.set(part, offset);\n offset += part.length;\n }\n bodyType = \"binary\";\n }\n }\n\n // Parse headers\n if (init?.headers) {\n if (\n init.headers &&\n typeof init.headers === \"object\" &&\n \"headers\" in init.headers &&\n init.headers.headers instanceof Map\n ) {\n headersState = {\n headers: new Map((init.headers as HeadersState).headers),\n };\n } else if (\n init.headers &&\n typeof init.headers === \"object\" &&\n \"__isDefineClassInstance__\" in init.headers &&\n (init.headers as { __isDefineClassInstance__?: boolean }).__isDefineClassInstance__ === true &&\n \"__instanceId__\" in init.headers\n ) {\n // Unmarshalled Headers instance from defineClass\n const instanceId = (init.headers as { __instanceId__: number }).__instanceId__;\n const state = getInstanceStateById<HeadersState>(instanceId);\n if (state && state.headers instanceof Map) {\n headersState = {\n headers: new Map(state.headers),\n };\n }\n } else {\n headersState = { headers: new Map() };\n for (const [key, value] of Object.entries(init.headers)) {\n headersState.headers.set(key.toLowerCase(), [String(value)]);\n }\n }\n }\n\n return {\n status,\n statusText,\n headersState,\n body,\n bodyUsed: false,\n url: \"\",\n redirected: false,\n type: init?._type ?? \"default\",\n ok: status >= 200 && status < 300,\n bodyType,\n };\n },\n properties: {\n body: {\n get(this: ResponseState) {\n if (!this.body) return null;\n if (!createStream) {\n // Fallback: return raw body if no stream factory\n return this.body;\n }\n // Create a ReadableStream from the body data\n const bodyData = this.body;\n let offset = 0;\n const chunkSize = 65536; // 64KB chunks\n return 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 },\n },\n bodyUsed: {\n get(this: ResponseState) {\n return this.bodyUsed;\n },\n },\n headers: {\n get(this: ResponseState) {\n return createHeadersLike(this.headersState);\n },\n },\n ok: {\n get(this: ResponseState) {\n return this.ok;\n },\n },\n redirected: {\n get(this: ResponseState) {\n return this.redirected;\n },\n },\n status: {\n get(this: ResponseState) {\n return this.status;\n },\n },\n statusText: {\n get(this: ResponseState) {\n return this.statusText;\n },\n },\n type: {\n get(this: ResponseState) {\n return this.type;\n },\n },\n url: {\n get(this: ResponseState) {\n return this.url;\n },\n },\n },\n methods: {\n async arrayBuffer(this: ResponseState): Promise<ArrayBuffer> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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: ResponseState): Promise<object> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n const contentType =\n this.headersState.headers.get(\"content-type\")?.[0] || \"\";\n return {\n parts: this.body ? [this.body] : [],\n type: contentType,\n size: this.body?.length || 0,\n };\n },\n clone(this: ResponseState): ResponseState {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n return {\n ...this,\n headersState: {\n headers: new Map(this.headersState.headers),\n },\n body: this.body ? new Uint8Array(this.body) : null,\n bodyUsed: false,\n };\n },\n async json(this: ResponseState): Promise<unknown> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\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: ResponseState): Promise<string> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n if (!this.body) {\n return \"\";\n }\n return new TextDecoder().decode(this.body);\n },\n async formData(this: ResponseState): Promise<FormDataState> {\n if (this.bodyUsed) {\n throw new TypeError(\"Body has already been consumed\");\n }\n this.bodyUsed = true;\n if (!this.body) {\n return { entries: [] };\n }\n\n const contentType = this.headersState.headers.get(\"content-type\")?.[0] || \"\";\n\n if (contentType.includes(\"multipart/form-data\")) {\n return parseMultipartFormData(this.body, contentType);\n } else if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n return parseUrlEncodedFormData(this.body);\n }\n\n throw new TypeError(\"Could not parse content as FormData\");\n },\n },\n });\n\n return classHandle;\n}\n\n/**\n * Add static methods to Response class after it's been set on global\n * This must be called after Response and Headers are available on global\n */\nexport function addResponseStaticMethods(context: QuickJSContext): void {\n const staticMethodsCode = `\n Response.error = function() {\n return new Response(null, { status: 0, _type: \"error\" });\n };\n\n Response.json = function(data, init = {}) {\n const body = JSON.stringify(data);\n // Merge content-type with any provided headers\n const headers = Object.assign(\n { \"content-type\": \"application/json\" },\n init.headers || {}\n );\n return new Response(body, {\n status: init.status ?? 200,\n statusText: init.statusText ?? \"\",\n headers: headers\n });\n };\n\n Response.redirect = function(url, status = 302) {\n return new Response(null, {\n status: status,\n headers: { \"location\": String(url) }\n });\n };\n `;\n const result = context.evalCode(staticMethodsCode);\n if (result.error) {\n result.error.dispose();\n } else {\n result.value.dispose();\n }\n}\n\n/**\n * Convert ResponseState (or unmarshalled Response object) to native Response\n */\nexport function responseStateToNative(state: ResponseState | Record<string, unknown>): Response {\n const bodyBytes = (state as ResponseState).body ?? (state as Record<string, unknown>).body;\n const bodyType = (state as ResponseState).bodyType;\n const status = (state as ResponseState).status ?? 200;\n const statusText = (state as ResponseState).statusText ?? \"\";\n\n // Handle both headersState (internal) and headers (from getter)\n let headersState: HeadersState;\n if ((state as ResponseState).headersState) {\n headersState = (state as ResponseState).headersState;\n } else if ((state as Record<string, unknown>).headers) {\n // When unmarshalled, headers is the HeadersLike object from getter\n const headers = (state as Record<string, unknown>).headers as { headers?: Map<string, string[]> };\n if (headers.headers instanceof Map) {\n headersState = { headers: headers.headers };\n } else {\n headersState = { headers: new Map() };\n }\n } else {\n headersState = { headers: new Map() };\n }\n\n // Convert body back to string if it was originally a string\n // This ensures Bun.serve doesn't add application/octet-stream content-type\n let body: BodyInit | null = null;\n if (bodyBytes) {\n if (bodyType === \"string\") {\n body = new TextDecoder().decode(bodyBytes as Uint8Array);\n } else {\n // Cast to ArrayBuffer which is a valid BodyInit type\n const uint8 = bodyBytes as Uint8Array;\n body = uint8.buffer.slice(uint8.byteOffset, uint8.byteOffset + uint8.byteLength) as ArrayBuffer;\n }\n }\n\n return new Response(body, {\n status,\n statusText,\n headers: headersStateToNative(headersState),\n });\n}\n\n/**\n * Create a ResponseState from a native Response\n */\nexport async function createResponseStateFromNative(\n response: Response\n): Promise<ResponseState> {\n const body = response.body\n ? new Uint8Array(await response.arrayBuffer())\n : null;\n\n const headersState: HeadersState = { headers: new Map() };\n response.headers.forEach((value, key) => {\n const existing = headersState.headers.get(key.toLowerCase()) || [];\n existing.push(value);\n headersState.headers.set(key.toLowerCase(), existing);\n });\n\n // Detect body type from content-type header\n const contentType = response.headers.get(\"content-type\");\n let bodyType: \"string\" | \"binary\" | null = null;\n if (body) {\n if (contentType && (contentType.startsWith(\"text/\") || contentType.includes(\"json\") || contentType.includes(\"xml\"))) {\n bodyType = \"string\";\n } else {\n bodyType = \"binary\";\n }\n }\n\n return {\n status: response.status,\n statusText: response.statusText,\n headersState,\n body,\n bodyUsed: false,\n url: response.url,\n redirected: response.redirected,\n type: response.type,\n ok: response.ok,\n bodyType,\n };\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;AAEA;AAEA;AACA;AAUO,SAAS,mBAAmB,CACjC,SACA,UACA,cACe;AAAA,EACf,MAAM,cAAc,YAA2B,SAAS,UAAU;AAAA,IAChE,MAAM;AAAA,IACN,WAAW,CAAC,SAAS;AAAA,MACnB,MAAM,WAAW,KAAK;AAAA,MACtB,MAAM,OAAO,KAAK;AAAA,MAOlB,IAAI,OAA0B;AAAA,MAC9B,MAAM,SAAS,MAAM,UAAU;AAAA,MAC/B,MAAM,aAAa,MAAM,cAAc;AAAA,MACvC,IAAI,eAA6B,EAAE,SAAS,IAAI,IAAM;AAAA,MAGtD,IAAI,aAAa,QAAQ,aAAa,WAAW;AAAA,QAC/C,IAAI,OAAO,aAAa,UAAU;AAAA,UAChC,OAAO,IAAI,YAAY,EAAE,OAAO,QAAQ;AAAA,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "77C0707215771B4364756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/mjs/package.json
CHANGED
package/dist/types/types.d.ts
CHANGED
|
@@ -152,6 +152,8 @@ export interface ResponseState {
|
|
|
152
152
|
redirected: boolean;
|
|
153
153
|
type: string;
|
|
154
154
|
ok: boolean;
|
|
155
|
+
/** Original body type - used to convert back to string for native Response */
|
|
156
|
+
bodyType?: "string" | "binary" | null;
|
|
155
157
|
}
|
|
156
158
|
export interface AbortControllerState {
|
|
157
159
|
signalState: AbortSignalState;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ricsam/quickjs-fetch",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"main": "./dist/cjs/index.cjs",
|
|
5
5
|
"types": "./dist/types/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"typecheck": "tsc --noEmit"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@ricsam/quickjs-core": "^0.2.
|
|
19
|
+
"@ricsam/quickjs-core": "^0.2.6",
|
|
20
20
|
"quickjs-emscripten": "^0.31.0"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|