@ricsam/quickjs-test-utils 1.0.17 → 1.0.19

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.
@@ -11,6 +11,9 @@ import {
11
11
  useFetchTestContext
12
12
  } from "./fetch-context.mjs";
13
13
  import { evalCode, evalCodeAsync } from "./eval.mjs";
14
+ import {
15
+ runTestCode
16
+ } from "./native-input-test.mjs";
14
17
  import {
15
18
  startIntegrationServer
16
19
  } from "./integration-server.mjs";
@@ -29,6 +32,7 @@ export {
29
32
  useFetchTestContext,
30
33
  typecheckQuickJSCode,
31
34
  startIntegrationServer,
35
+ runTestCode,
32
36
  formatTypecheckErrors,
33
37
  evalCodeAsync,
34
38
  evalCode,
@@ -42,4 +46,4 @@ export {
42
46
  CORE_TYPES
43
47
  };
44
48
 
45
- //# debugId=E7F326004DCE839564756E2164756E21
49
+ //# debugId=D68E092BABACFD0664756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts"],
4
4
  "sourcesContent": [
5
- "export {\n createTestContext,\n disposeTestContext,\n useTestContext,\n type TestContext,\n} from \"./context.mjs\";\n\nexport {\n createFetchTestContext,\n disposeFetchTestContext,\n useFetchTestContext,\n type FetchTestContext,\n type CreateFetchTestContextOptions,\n} from \"./fetch-context.mjs\";\n\nexport { evalCode, evalCodeAsync } from \"./eval.mjs\";\n\nexport {\n startIntegrationServer,\n type IntegrationTestServer,\n type StartIntegrationServerOptions,\n} from \"./integration-server.mjs\";\n\nexport {\n typecheckQuickJSCode,\n formatTypecheckErrors,\n type TypecheckResult,\n type TypecheckError,\n type TypecheckOptions,\n type LibraryTypes,\n type LibraryTypeFile,\n} from \"./typecheck.mjs\";\n\nexport {\n CORE_TYPES,\n FETCH_TYPES,\n FS_TYPES,\n TYPE_DEFINITIONS,\n type TypeDefinitionKey,\n} from \"./quickjs-types.mjs\";\n\n// For fs and runtime contexts, import from subpaths:\n// import { createFsTestContext } from \"@ricsam/quickjs-test-utils/fs\";\n// import { createRuntimeTestContext } from \"@ricsam/quickjs-test-utils/runtime\";\n"
5
+ "export {\n createTestContext,\n disposeTestContext,\n useTestContext,\n type TestContext,\n} from \"./context.mjs\";\n\nexport {\n createFetchTestContext,\n disposeFetchTestContext,\n useFetchTestContext,\n type FetchTestContext,\n type CreateFetchTestContextOptions,\n} from \"./fetch-context.mjs\";\n\nexport { evalCode, evalCodeAsync } from \"./eval.mjs\";\n\nexport {\n runTestCode,\n type TestRuntime,\n type TestRunner,\n} from \"./native-input-test.mjs\";\n\nexport {\n startIntegrationServer,\n type IntegrationTestServer,\n type StartIntegrationServerOptions,\n} from \"./integration-server.mjs\";\n\nexport {\n typecheckQuickJSCode,\n formatTypecheckErrors,\n type TypecheckResult,\n type TypecheckError,\n type TypecheckOptions,\n type LibraryTypes,\n type LibraryTypeFile,\n} from \"./typecheck.mjs\";\n\nexport {\n CORE_TYPES,\n FETCH_TYPES,\n FS_TYPES,\n TYPE_DEFINITIONS,\n type TypeDefinitionKey,\n} from \"./quickjs-types.mjs\";\n\n// For fs and runtime contexts, import from subpaths:\n// import { createFsTestContext } from \"@ricsam/quickjs-test-utils/fs\";\n// import { createRuntimeTestContext } from \"@ricsam/quickjs-test-utils/runtime\";\n"
6
6
  ],
7
- "mappings": ";;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA;AAAA;AAAA;AAAA;AAAA;AAQA;AAEA;AAAA;AAAA;AAMA;AAAA;AAAA;AAAA;AAUA;AAAA;AAAA;AAAA;AAAA;AAAA;",
8
- "debugId": "E7F326004DCE839564756E2164756E21",
7
+ "mappings": ";;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA;AAAA;AAAA;AAAA;AAAA;AAQA;AAEA;AAAA;AAAA;AAMA;AAAA;AAAA;AAMA;AAAA;AAAA;AAAA;AAUA;AAAA;AAAA;AAAA;AAAA;AAAA;",
8
+ "debugId": "D68E092BABACFD0664756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -3,6 +3,7 @@
3
3
  import { getQuickJS } from "quickjs-emscripten";
4
4
  import { setupFetch } from "@ricsam/quickjs-fetch";
5
5
  import { setupCore } from "@ricsam/quickjs-core";
6
+ import { setupConsole } from "@ricsam/quickjs-console";
6
7
  async function startIntegrationServer(quickJSCode, options) {
7
8
  const QuickJS = await getQuickJS();
8
9
  const runtime = QuickJS.newRuntime();
@@ -12,6 +13,7 @@ async function startIntegrationServer(quickJSCode, options) {
12
13
  coreHandle,
13
14
  onFetch: options?.onFetch
14
15
  });
16
+ const consoleHandle = options?.consoleHandlers ? setupConsole(context, { handlers: options.consoleHandlers, coreHandle }) : undefined;
15
17
  const wsConnections = new Map;
16
18
  fetchHandle.onWebSocketCommand((cmd) => {
17
19
  const ws = wsConnections.get(cmd.connectionId);
@@ -85,6 +87,7 @@ async function startIntegrationServer(quickJSCode, options) {
85
87
  context,
86
88
  runtime,
87
89
  coreHandle,
90
+ consoleHandle,
88
91
  async stop() {
89
92
  for (const ws of wsConnections.values()) {
90
93
  ws.close(1000, "Server stopping");
@@ -92,6 +95,7 @@ async function startIntegrationServer(quickJSCode, options) {
92
95
  wsConnections.clear();
93
96
  server.stop(true);
94
97
  fetchHandle.dispose();
98
+ consoleHandle?.dispose();
95
99
  coreHandle.dispose();
96
100
  context.dispose();
97
101
  runtime.dispose();
@@ -102,4 +106,4 @@ export {
102
106
  startIntegrationServer
103
107
  };
104
108
 
105
- //# debugId=6D46A77DBCE9B97364756E2164756E21
109
+ //# debugId=97F49DC31D81D1FD64756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/integration-server.ts"],
4
4
  "sourcesContent": [
5
- "import { getQuickJS, type QuickJSContext, type QuickJSRuntime } from \"quickjs-emscripten\";\nimport { setupFetch, type FetchHandle, type WebSocketCommand, type SetupFetchOptions } from \"@ricsam/quickjs-fetch\";\nimport { setupCore, type CoreHandle } from \"@ricsam/quickjs-core\";\nimport type { Server, ServerWebSocket } from \"bun\";\n\ninterface WsData {\n connectionId: string;\n}\n\nexport interface IntegrationTestServer {\n baseURL: string;\n wsURL: string;\n port: number;\n fetchHandle: FetchHandle;\n context: QuickJSContext;\n runtime: QuickJSRuntime;\n coreHandle: CoreHandle;\n stop(): Promise<void>;\n}\n\nexport interface StartIntegrationServerOptions {\n /** Handler for outbound fetch() calls from QuickJS */\n onFetch?: SetupFetchOptions[\"onFetch\"];\n}\n\n/**\n * Start a real HTTP server that dispatches requests to a QuickJS serve() handler.\n *\n * @param quickJSCode - JavaScript code to run in QuickJS, should call serve()\n * @param options - Optional configuration\n * @returns Server info including baseURL, wsURL, and stop function\n *\n * @example\n * const server = await startIntegrationServer(`\n * serve({\n * fetch(request) {\n * return new Response(\"Hello!\");\n * }\n * });\n * `);\n *\n * const response = await fetch(\\`\\${server.baseURL}/test\\`);\n * expect(await response.text()).toBe(\"Hello!\");\n *\n * await server.stop();\n */\nexport async function startIntegrationServer(\n quickJSCode: string,\n options?: StartIntegrationServerOptions\n): Promise<IntegrationTestServer> {\n const QuickJS = await getQuickJS();\n const runtime = QuickJS.newRuntime();\n const context = runtime.newContext();\n\n // Setup core and fetch APIs\n const coreHandle = setupCore(context);\n const fetchHandle = setupFetch(context, {\n coreHandle,\n onFetch: options?.onFetch,\n });\n\n // Track WebSocket connections\n const wsConnections = new Map<string, ServerWebSocket<WsData>>();\n\n // Handle outgoing WebSocket commands from QuickJS\n fetchHandle.onWebSocketCommand((cmd: WebSocketCommand) => {\n const ws = wsConnections.get(cmd.connectionId);\n if (!ws) return;\n\n if (cmd.type === \"message\") {\n ws.send(cmd.data);\n } else if (cmd.type === \"close\") {\n ws.close(cmd.code, cmd.reason);\n }\n });\n\n // Run the user's QuickJS code\n const result = context.evalCode(quickJSCode);\n if (result.error) {\n const error = context.dump(result.error);\n result.error.dispose();\n fetchHandle.dispose();\n coreHandle.dispose();\n context.dispose();\n runtime.dispose();\n throw new Error(`Failed to evaluate QuickJS code: ${JSON.stringify(error)}`);\n }\n result.value.dispose();\n\n // Start Bun server with port 0 for dynamic assignment\n const server: Server<WsData> = Bun.serve<WsData>({\n port: 0,\n async fetch(req, server) {\n try {\n // Dispatch to QuickJS handler\n const response = await fetchHandle.dispatchRequest(req);\n\n // Check if QuickJS requested a WebSocket upgrade\n const upgrade = fetchHandle.getUpgradeRequest();\n if (upgrade?.requested) {\n // The connectionId is generated by QuickJS in server.upgrade()\n // User data is stored in QuickJS registry - we just pass the connectionId\n const success = server.upgrade(req, {\n data: { connectionId: upgrade.connectionId },\n });\n if (success) {\n return undefined;\n }\n return new Response(\"WebSocket upgrade failed\", { status: 500 });\n }\n\n return response;\n } catch (error) {\n console.error(\"Integration test request failed:\", error);\n return new Response(\"Internal Server Error\", { status: 500 });\n }\n },\n websocket: {\n open(ws) {\n const { connectionId } = ws.data;\n wsConnections.set(connectionId, ws);\n // User data is looked up from QuickJS registry using connectionId\n fetchHandle.dispatchWebSocketOpen(connectionId);\n },\n message(ws, message) {\n const msg = typeof message === \"string\" ? message : message.buffer;\n fetchHandle.dispatchWebSocketMessage(ws.data.connectionId, msg as string | ArrayBuffer);\n },\n close(ws, code, reason) {\n fetchHandle.dispatchWebSocketClose(ws.data.connectionId, code, reason);\n wsConnections.delete(ws.data.connectionId);\n },\n },\n });\n\n const port = server.port;\n if (port === undefined) {\n throw new Error(\"Server failed to get port\");\n }\n const baseURL = `http://localhost:${port}`;\n const wsURL = `ws://localhost:${port}`;\n\n return {\n baseURL,\n wsURL,\n port,\n fetchHandle,\n context,\n runtime,\n coreHandle,\n async stop() {\n // Close all WebSocket connections\n for (const ws of wsConnections.values()) {\n ws.close(1000, \"Server stopping\");\n }\n wsConnections.clear();\n\n // Stop the server\n server.stop(true);\n\n // Dispose QuickJS resources\n fetchHandle.dispose();\n coreHandle.dispose();\n context.dispose();\n runtime.dispose();\n },\n };\n}\n"
5
+ "import { getQuickJS, type QuickJSContext, type QuickJSRuntime } from \"quickjs-emscripten\";\nimport { setupFetch, type FetchHandle, type WebSocketCommand, type SetupFetchOptions } from \"@ricsam/quickjs-fetch\";\nimport { setupCore, type CoreHandle } from \"@ricsam/quickjs-core\";\nimport type { Server, ServerWebSocket } from \"bun\";\nimport { setupConsole, type ConsoleOutputHandler, type ConsoleHandle } from \"@ricsam/quickjs-console\";\n\ninterface WsData {\n connectionId: string;\n}\n\nexport interface IntegrationTestServer {\n baseURL: string;\n wsURL: string;\n port: number;\n fetchHandle: FetchHandle;\n context: QuickJSContext;\n runtime: QuickJSRuntime;\n coreHandle: CoreHandle;\n consoleHandle?: ConsoleHandle;\n stop(): Promise<void>;\n}\n\nexport interface StartIntegrationServerOptions {\n /** Handler for outbound fetch() calls from QuickJS */\n onFetch?: SetupFetchOptions[\"onFetch\"];\n /** Handlers for console output from QuickJS */\n consoleHandlers?: ConsoleOutputHandler;\n}\n\n/**\n * Start a real HTTP server that dispatches requests to a QuickJS serve() handler.\n *\n * @param quickJSCode - JavaScript code to run in QuickJS, should call serve()\n * @param options - Optional configuration\n * @returns Server info including baseURL, wsURL, and stop function\n *\n * @example\n * const server = await startIntegrationServer(`\n * serve({\n * fetch(request) {\n * return new Response(\"Hello!\");\n * }\n * });\n * `);\n *\n * const response = await fetch(\\`\\${server.baseURL}/test\\`);\n * expect(await response.text()).toBe(\"Hello!\");\n *\n * await server.stop();\n */\nexport async function startIntegrationServer(\n quickJSCode: string,\n options?: StartIntegrationServerOptions\n): Promise<IntegrationTestServer> {\n const QuickJS = await getQuickJS();\n const runtime = QuickJS.newRuntime();\n const context = runtime.newContext();\n\n // Setup core and fetch APIs\n const coreHandle = setupCore(context);\n const fetchHandle = setupFetch(context, {\n coreHandle,\n onFetch: options?.onFetch,\n });\n\n // Setup console if handlers provided\n const consoleHandle = options?.consoleHandlers\n ? setupConsole(context, { handlers: options.consoleHandlers, coreHandle })\n : undefined;\n\n // Track WebSocket connections\n const wsConnections = new Map<string, ServerWebSocket<WsData>>();\n\n // Handle outgoing WebSocket commands from QuickJS\n fetchHandle.onWebSocketCommand((cmd: WebSocketCommand) => {\n const ws = wsConnections.get(cmd.connectionId);\n if (!ws) return;\n\n if (cmd.type === \"message\") {\n ws.send(cmd.data);\n } else if (cmd.type === \"close\") {\n ws.close(cmd.code, cmd.reason);\n }\n });\n\n // Run the user's QuickJS code\n const result = context.evalCode(quickJSCode);\n if (result.error) {\n const error = context.dump(result.error);\n result.error.dispose();\n fetchHandle.dispose();\n coreHandle.dispose();\n context.dispose();\n runtime.dispose();\n throw new Error(`Failed to evaluate QuickJS code: ${JSON.stringify(error)}`);\n }\n result.value.dispose();\n\n // Start Bun server with port 0 for dynamic assignment\n const server: Server<WsData> = Bun.serve<WsData>({\n port: 0,\n async fetch(req, server) {\n try {\n // Dispatch to QuickJS handler\n const response = await fetchHandle.dispatchRequest(req);\n\n // Check if QuickJS requested a WebSocket upgrade\n const upgrade = fetchHandle.getUpgradeRequest();\n if (upgrade?.requested) {\n // The connectionId is generated by QuickJS in server.upgrade()\n // User data is stored in QuickJS registry - we just pass the connectionId\n const success = server.upgrade(req, {\n data: { connectionId: upgrade.connectionId },\n });\n if (success) {\n return undefined;\n }\n return new Response(\"WebSocket upgrade failed\", { status: 500 });\n }\n\n return response;\n } catch (error) {\n console.error(\"Integration test request failed:\", error);\n return new Response(\"Internal Server Error\", { status: 500 });\n }\n },\n websocket: {\n open(ws) {\n const { connectionId } = ws.data;\n wsConnections.set(connectionId, ws);\n // User data is looked up from QuickJS registry using connectionId\n fetchHandle.dispatchWebSocketOpen(connectionId);\n },\n message(ws, message) {\n const msg = typeof message === \"string\" ? message : message.buffer;\n fetchHandle.dispatchWebSocketMessage(ws.data.connectionId, msg as string | ArrayBuffer);\n },\n close(ws, code, reason) {\n fetchHandle.dispatchWebSocketClose(ws.data.connectionId, code, reason);\n wsConnections.delete(ws.data.connectionId);\n },\n },\n });\n\n const port = server.port;\n if (port === undefined) {\n throw new Error(\"Server failed to get port\");\n }\n const baseURL = `http://localhost:${port}`;\n const wsURL = `ws://localhost:${port}`;\n\n return {\n baseURL,\n wsURL,\n port,\n fetchHandle,\n context,\n runtime,\n coreHandle,\n consoleHandle,\n async stop() {\n // Close all WebSocket connections\n for (const ws of wsConnections.values()) {\n ws.close(1000, \"Server stopping\");\n }\n wsConnections.clear();\n\n // Stop the server\n server.stop(true);\n\n // Dispose QuickJS resources\n fetchHandle.dispose();\n consoleHandle?.dispose();\n coreHandle.dispose();\n context.dispose();\n runtime.dispose();\n },\n };\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "6D46A77DBCE9B97364756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "97F49DC31D81D1FD64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -0,0 +1,534 @@
1
+ // @bun
2
+ // packages/test-utils/src/native-input-test.ts
3
+ import { marshal } from "@ricsam/quickjs-core";
4
+ function runTestCode(context, code) {
5
+ return {
6
+ input(inputs) {
7
+ const logs = {};
8
+ const logFn = context.newFunction("log", (tagHandle, valueHandle) => {
9
+ const tag = context.getString(tagHandle);
10
+ const value = unmarshalWithClassConversion(context, valueHandle);
11
+ logs[tag] = value;
12
+ });
13
+ context.setProp(context.global, "log", logFn);
14
+ logFn.dispose();
15
+ const inputHandle = marshalWithClassConversion(context, inputs);
16
+ context.setProp(context.global, "testingInput", inputHandle);
17
+ inputHandle.dispose();
18
+ const result = context.evalCode(code);
19
+ let returnValue = undefined;
20
+ if (result.error) {
21
+ const error = context.dump(result.error);
22
+ result.error.dispose();
23
+ context.setProp(context.global, "testingInput", context.undefined);
24
+ context.setProp(context.global, "log", context.undefined);
25
+ throw new Error(`Test code failed: ${JSON.stringify(error)}`);
26
+ } else {
27
+ returnValue = context.dump(result.value);
28
+ result.value.dispose();
29
+ }
30
+ context.setProp(context.global, "testingInput", context.undefined);
31
+ context.setProp(context.global, "log", context.undefined);
32
+ return { logs, result: returnValue };
33
+ }
34
+ };
35
+ }
36
+ function marshalWithClassConversion(context, value) {
37
+ if (value instanceof Headers) {
38
+ return createQJSHeadersFromNative(context, value);
39
+ }
40
+ if (value instanceof Request) {
41
+ return createQJSRequestFromNative(context, value);
42
+ }
43
+ if (value instanceof Response) {
44
+ return createQJSResponseFromNative(context, value);
45
+ }
46
+ if (value instanceof URL) {
47
+ return createQJSURLFromNative(context, value);
48
+ }
49
+ if (value instanceof Blob && !(value instanceof File)) {
50
+ return createQJSBlobFromNative(context, value);
51
+ }
52
+ if (value instanceof File) {
53
+ return createQJSFileFromNative(context, value);
54
+ }
55
+ if (value instanceof FormData) {
56
+ return createQJSFormDataFromNative(context, value);
57
+ }
58
+ if (Array.isArray(value)) {
59
+ const arr = context.newArray();
60
+ for (let i = 0;i < value.length; i++) {
61
+ const itemHandle = marshalWithClassConversion(context, value[i]);
62
+ context.setProp(arr, i, itemHandle);
63
+ itemHandle.dispose();
64
+ }
65
+ return arr;
66
+ }
67
+ if (value && typeof value === "object" && value.constructor === Object) {
68
+ const obj = context.newObject();
69
+ for (const [key, val] of Object.entries(value)) {
70
+ const valHandle = marshalWithClassConversion(context, val);
71
+ context.setProp(obj, key, valHandle);
72
+ valHandle.dispose();
73
+ }
74
+ return obj;
75
+ }
76
+ return marshal(context, value);
77
+ }
78
+ function createQJSHeadersFromNative(context, native) {
79
+ const pairs = [];
80
+ native.forEach((value, key) => {
81
+ pairs.push([key, value]);
82
+ });
83
+ const pairsJson = JSON.stringify(pairs);
84
+ const result = context.evalCode(`new Headers(${pairsJson})`);
85
+ if (result.error) {
86
+ const err = context.dump(result.error);
87
+ result.error.dispose();
88
+ throw new Error(`Failed to create Headers from native: ${JSON.stringify(err)}`);
89
+ }
90
+ return result.value;
91
+ }
92
+ function createQJSRequestFromNative(context, native) {
93
+ const headersHandle = createQJSHeadersFromNative(context, native.headers);
94
+ context.setProp(context.global, "__nativeRequestHeaders__", headersHandle);
95
+ headersHandle.dispose();
96
+ const urlJson = JSON.stringify(native.url);
97
+ const methodJson = JSON.stringify(native.method);
98
+ const modeJson = JSON.stringify(native.mode);
99
+ const credentialsJson = JSON.stringify(native.credentials);
100
+ const cacheJson = JSON.stringify(native.cache);
101
+ const redirectJson = JSON.stringify(native.redirect);
102
+ const referrerJson = JSON.stringify(native.referrer);
103
+ const referrerPolicyJson = JSON.stringify(native.referrerPolicy);
104
+ const integrityJson = JSON.stringify(native.integrity);
105
+ const result = context.evalCode(`
106
+ (function() {
107
+ const req = new Request(${urlJson}, {
108
+ method: ${methodJson},
109
+ headers: __nativeRequestHeaders__,
110
+ mode: ${modeJson},
111
+ credentials: ${credentialsJson},
112
+ cache: ${cacheJson},
113
+ redirect: ${redirectJson},
114
+ referrer: ${referrerJson},
115
+ referrerPolicy: ${referrerPolicyJson},
116
+ integrity: ${integrityJson},
117
+ });
118
+ delete globalThis.__nativeRequestHeaders__;
119
+ return req;
120
+ })()
121
+ `);
122
+ if (result.error) {
123
+ const err = context.dump(result.error);
124
+ result.error.dispose();
125
+ throw new Error(`Failed to create Request from native: ${JSON.stringify(err)}`);
126
+ }
127
+ return result.value;
128
+ }
129
+ function createQJSResponseFromNative(context, native) {
130
+ const headersHandle = createQJSHeadersFromNative(context, native.headers);
131
+ context.setProp(context.global, "__nativeResponseHeaders__", headersHandle);
132
+ headersHandle.dispose();
133
+ const statusJson = JSON.stringify(native.status);
134
+ const statusTextJson = JSON.stringify(native.statusText);
135
+ const result = context.evalCode(`
136
+ (function() {
137
+ const res = new Response(null, {
138
+ status: ${statusJson},
139
+ statusText: ${statusTextJson},
140
+ headers: __nativeResponseHeaders__,
141
+ });
142
+ delete globalThis.__nativeResponseHeaders__;
143
+ return res;
144
+ })()
145
+ `);
146
+ if (result.error) {
147
+ const err = context.dump(result.error);
148
+ result.error.dispose();
149
+ throw new Error(`Failed to create Response from native: ${JSON.stringify(err)}`);
150
+ }
151
+ return result.value;
152
+ }
153
+ function createQJSURLFromNative(context, native) {
154
+ const hrefJson = JSON.stringify(native.href);
155
+ const result = context.evalCode(`new URL(${hrefJson})`);
156
+ if (result.error) {
157
+ const err = context.dump(result.error);
158
+ result.error.dispose();
159
+ throw new Error(`Failed to create URL from native: ${JSON.stringify(err)}`);
160
+ }
161
+ return result.value;
162
+ }
163
+ function createQJSBlobFromNative(context, native) {
164
+ const typeJson = JSON.stringify(native.type);
165
+ const result = context.evalCode(`new Blob([], { type: ${typeJson} })`);
166
+ if (result.error) {
167
+ const err = context.dump(result.error);
168
+ result.error.dispose();
169
+ throw new Error(`Failed to create Blob from native: ${JSON.stringify(err)}`);
170
+ }
171
+ return result.value;
172
+ }
173
+ function createQJSFileFromNative(context, native) {
174
+ const nameJson = JSON.stringify(native.name);
175
+ const typeJson = JSON.stringify(native.type);
176
+ const lastModifiedJson = JSON.stringify(native.lastModified);
177
+ const result = context.evalCode(`
178
+ new File([], ${nameJson}, { type: ${typeJson}, lastModified: ${lastModifiedJson} })
179
+ `);
180
+ if (result.error) {
181
+ const err = context.dump(result.error);
182
+ result.error.dispose();
183
+ throw new Error(`Failed to create File from native: ${JSON.stringify(err)}`);
184
+ }
185
+ return result.value;
186
+ }
187
+ function createQJSFormDataFromNative(context, native) {
188
+ const result = context.evalCode(`new FormData()`);
189
+ if (result.error) {
190
+ const err = context.dump(result.error);
191
+ result.error.dispose();
192
+ throw new Error(`Failed to create FormData from native: ${JSON.stringify(err)}`);
193
+ }
194
+ const formDataHandle = result.value;
195
+ for (const [key, entryValue] of native.entries()) {
196
+ const keyJson = JSON.stringify(key);
197
+ if (typeof entryValue !== "string") {
198
+ const fileValue = entryValue;
199
+ const nameJson = JSON.stringify(fileValue.name);
200
+ const typeJson = JSON.stringify(fileValue.type);
201
+ const appendResult = context.evalCode(`
202
+ (function(fd) {
203
+ const file = new File([], ${nameJson}, { type: ${typeJson} });
204
+ fd.append(${keyJson}, file);
205
+ return fd;
206
+ })
207
+ `);
208
+ if (appendResult.error) {
209
+ appendResult.error.dispose();
210
+ formDataHandle.dispose();
211
+ throw new Error("Failed to create append function for File");
212
+ }
213
+ const appendFn = appendResult.value;
214
+ const callResult = context.callFunction(appendFn, context.undefined, formDataHandle);
215
+ appendFn.dispose();
216
+ if (callResult.error) {
217
+ callResult.error.dispose();
218
+ formDataHandle.dispose();
219
+ throw new Error("Failed to append File to FormData");
220
+ }
221
+ callResult.value.dispose();
222
+ } else {
223
+ const valueJson = JSON.stringify(entryValue);
224
+ const appendResult = context.evalCode(`
225
+ (function(fd) {
226
+ fd.append(${keyJson}, ${valueJson});
227
+ return fd;
228
+ })
229
+ `);
230
+ if (appendResult.error) {
231
+ appendResult.error.dispose();
232
+ formDataHandle.dispose();
233
+ throw new Error("Failed to create append function");
234
+ }
235
+ const appendFn = appendResult.value;
236
+ const callResult = context.callFunction(appendFn, context.undefined, formDataHandle);
237
+ appendFn.dispose();
238
+ if (callResult.error) {
239
+ callResult.error.dispose();
240
+ formDataHandle.dispose();
241
+ throw new Error("Failed to append to FormData");
242
+ }
243
+ callResult.value.dispose();
244
+ }
245
+ }
246
+ return formDataHandle;
247
+ }
248
+ function unmarshalWithClassConversion(context, handle) {
249
+ if (isInstanceOf(context, handle, "Headers")) {
250
+ return createNativeHeadersFromQJS(context, handle);
251
+ }
252
+ if (isInstanceOf(context, handle, "Request")) {
253
+ return createNativeRequestFromQJS(context, handle);
254
+ }
255
+ if (isInstanceOf(context, handle, "Response")) {
256
+ return createNativeResponseFromQJS(context, handle);
257
+ }
258
+ if (isInstanceOf(context, handle, "URL")) {
259
+ return createNativeURLFromQJS(context, handle);
260
+ }
261
+ if (isInstanceOf(context, handle, "File")) {
262
+ return createNativeFileFromQJS(context, handle);
263
+ }
264
+ if (isInstanceOf(context, handle, "Blob")) {
265
+ return createNativeBlobFromQJS(context, handle);
266
+ }
267
+ if (isInstanceOf(context, handle, "FormData")) {
268
+ return createNativeFormDataFromQJS(context, handle);
269
+ }
270
+ const typeofResult = context.typeof(handle);
271
+ if (typeofResult === "object") {
272
+ const isArrayResult = context.evalCode(`(function(obj) { return Array.isArray(obj); })`);
273
+ if (!isArrayResult.error) {
274
+ const checkResult = context.callFunction(isArrayResult.value, context.undefined, handle);
275
+ isArrayResult.value.dispose();
276
+ if (!checkResult.error && context.dump(checkResult.value) === true) {
277
+ checkResult.value.dispose();
278
+ return unmarshalArray(context, handle);
279
+ }
280
+ if (checkResult.error)
281
+ checkResult.error.dispose();
282
+ else if (checkResult.value)
283
+ checkResult.value.dispose();
284
+ } else {
285
+ isArrayResult.error.dispose();
286
+ }
287
+ const isPlainObjectResult = context.evalCode(`(function(obj) {
288
+ return obj !== null && typeof obj === 'object' && obj.constructor === Object;
289
+ })`);
290
+ if (!isPlainObjectResult.error) {
291
+ const checkResult = context.callFunction(isPlainObjectResult.value, context.undefined, handle);
292
+ isPlainObjectResult.value.dispose();
293
+ if (!checkResult.error && context.dump(checkResult.value) === true) {
294
+ checkResult.value.dispose();
295
+ return unmarshalObject(context, handle);
296
+ }
297
+ if (checkResult.error)
298
+ checkResult.error.dispose();
299
+ else if (checkResult.value)
300
+ checkResult.value.dispose();
301
+ } else {
302
+ isPlainObjectResult.error.dispose();
303
+ }
304
+ }
305
+ return context.dump(handle);
306
+ }
307
+ function isInstanceOf(context, handle, className) {
308
+ const checkResult = context.evalCode(`(function(obj) { return obj instanceof ${className}; })`);
309
+ if (checkResult.error) {
310
+ checkResult.error.dispose();
311
+ return false;
312
+ }
313
+ const result = context.callFunction(checkResult.value, context.undefined, handle);
314
+ checkResult.value.dispose();
315
+ if (result.error) {
316
+ result.error.dispose();
317
+ return false;
318
+ }
319
+ const isInstance = context.dump(result.value) === true;
320
+ result.value.dispose();
321
+ return isInstance;
322
+ }
323
+ function unmarshalArray(context, handle) {
324
+ const lengthHandle = context.getProp(handle, "length");
325
+ const length = context.dump(lengthHandle);
326
+ lengthHandle.dispose();
327
+ const result = [];
328
+ for (let i = 0;i < length; i++) {
329
+ const itemHandle = context.getProp(handle, i);
330
+ result.push(unmarshalWithClassConversion(context, itemHandle));
331
+ itemHandle.dispose();
332
+ }
333
+ return result;
334
+ }
335
+ function unmarshalObject(context, handle) {
336
+ const keysResult = context.evalCode(`(function(obj) { return Object.keys(obj); })`);
337
+ if (keysResult.error) {
338
+ keysResult.error.dispose();
339
+ return context.dump(handle);
340
+ }
341
+ const keysCallResult = context.callFunction(keysResult.value, context.undefined, handle);
342
+ keysResult.value.dispose();
343
+ if (keysCallResult.error) {
344
+ keysCallResult.error.dispose();
345
+ return context.dump(handle);
346
+ }
347
+ const keys = context.dump(keysCallResult.value);
348
+ keysCallResult.value.dispose();
349
+ const result = {};
350
+ for (const key of keys) {
351
+ const propHandle = context.getProp(handle, key);
352
+ result[key] = unmarshalWithClassConversion(context, propHandle);
353
+ propHandle.dispose();
354
+ }
355
+ return result;
356
+ }
357
+ function createNativeHeadersFromQJS(context, qjsHandle) {
358
+ const extractResult = context.evalCode(`
359
+ (function(headers) {
360
+ const pairs = [];
361
+ for (const [key, value] of headers) {
362
+ pairs.push([key, value]);
363
+ }
364
+ return pairs;
365
+ })
366
+ `);
367
+ if (extractResult.error) {
368
+ extractResult.error.dispose();
369
+ throw new Error("Failed to create extract function for Headers");
370
+ }
371
+ const result = context.callFunction(extractResult.value, context.undefined, qjsHandle);
372
+ extractResult.value.dispose();
373
+ if (result.error) {
374
+ result.error.dispose();
375
+ throw new Error("Failed to call header extraction function");
376
+ }
377
+ const pairs = context.dump(result.value);
378
+ result.value.dispose();
379
+ const native = new Headers;
380
+ for (const [key, value] of pairs) {
381
+ native.append(key, value);
382
+ }
383
+ return native;
384
+ }
385
+ function createNativeRequestFromQJS(context, qjsHandle) {
386
+ const extractResult = context.evalCode(`
387
+ (function(req) {
388
+ const headers = [];
389
+ for (const [key, value] of req.headers) {
390
+ headers.push([key, value]);
391
+ }
392
+ return {
393
+ url: req.url,
394
+ method: req.method,
395
+ headers: headers,
396
+ mode: req.mode,
397
+ credentials: req.credentials,
398
+ cache: req.cache,
399
+ redirect: req.redirect,
400
+ referrer: req.referrer,
401
+ referrerPolicy: req.referrerPolicy,
402
+ integrity: req.integrity,
403
+ };
404
+ })
405
+ `);
406
+ if (extractResult.error) {
407
+ extractResult.error.dispose();
408
+ throw new Error("Failed to create extract function for Request");
409
+ }
410
+ const result = context.callFunction(extractResult.value, context.undefined, qjsHandle);
411
+ extractResult.value.dispose();
412
+ if (result.error) {
413
+ result.error.dispose();
414
+ throw new Error("Failed to call request extraction function");
415
+ }
416
+ const props = context.dump(result.value);
417
+ result.value.dispose();
418
+ const headers = new Headers;
419
+ for (const [key, value] of props.headers) {
420
+ headers.append(key, value);
421
+ }
422
+ return new Request(props.url, {
423
+ method: props.method,
424
+ headers,
425
+ mode: props.mode,
426
+ credentials: props.credentials,
427
+ cache: props.cache,
428
+ redirect: props.redirect,
429
+ referrer: props.referrer,
430
+ referrerPolicy: props.referrerPolicy,
431
+ integrity: props.integrity
432
+ });
433
+ }
434
+ function createNativeResponseFromQJS(context, qjsHandle) {
435
+ const extractResult = context.evalCode(`
436
+ (function(res) {
437
+ const headers = [];
438
+ for (const [key, value] of res.headers) {
439
+ headers.push([key, value]);
440
+ }
441
+ return {
442
+ status: res.status,
443
+ statusText: res.statusText,
444
+ headers: headers,
445
+ };
446
+ })
447
+ `);
448
+ if (extractResult.error) {
449
+ extractResult.error.dispose();
450
+ throw new Error("Failed to create extract function for Response");
451
+ }
452
+ const result = context.callFunction(extractResult.value, context.undefined, qjsHandle);
453
+ extractResult.value.dispose();
454
+ if (result.error) {
455
+ result.error.dispose();
456
+ throw new Error("Failed to call response extraction function");
457
+ }
458
+ const props = context.dump(result.value);
459
+ result.value.dispose();
460
+ const headers = new Headers;
461
+ for (const [key, value] of props.headers) {
462
+ headers.append(key, value);
463
+ }
464
+ return new Response(null, {
465
+ status: props.status,
466
+ statusText: props.statusText,
467
+ headers
468
+ });
469
+ }
470
+ function createNativeURLFromQJS(context, qjsHandle) {
471
+ const hrefHandle = context.getProp(qjsHandle, "href");
472
+ const href = context.dump(hrefHandle);
473
+ hrefHandle.dispose();
474
+ return new URL(href);
475
+ }
476
+ function createNativeBlobFromQJS(context, qjsHandle) {
477
+ const typeHandle = context.getProp(qjsHandle, "type");
478
+ const type = context.dump(typeHandle);
479
+ typeHandle.dispose();
480
+ return new Blob([], { type });
481
+ }
482
+ function createNativeFileFromQJS(context, qjsHandle) {
483
+ const nameHandle = context.getProp(qjsHandle, "name");
484
+ const name = context.dump(nameHandle);
485
+ nameHandle.dispose();
486
+ const typeHandle = context.getProp(qjsHandle, "type");
487
+ const type = context.dump(typeHandle);
488
+ typeHandle.dispose();
489
+ const lastModifiedHandle = context.getProp(qjsHandle, "lastModified");
490
+ const lastModified = context.dump(lastModifiedHandle);
491
+ lastModifiedHandle.dispose();
492
+ return new File([], name, { type, lastModified });
493
+ }
494
+ function createNativeFormDataFromQJS(context, qjsHandle) {
495
+ const extractResult = context.evalCode(`
496
+ (function(fd) {
497
+ const entries = [];
498
+ for (const [key, value] of fd) {
499
+ if (value instanceof File) {
500
+ entries.push([key, { type: 'file', name: value.name, fileType: value.type, lastModified: value.lastModified }]);
501
+ } else {
502
+ entries.push([key, { type: 'string', value: value }]);
503
+ }
504
+ }
505
+ return entries;
506
+ })
507
+ `);
508
+ if (extractResult.error) {
509
+ extractResult.error.dispose();
510
+ throw new Error("Failed to create extract function for FormData");
511
+ }
512
+ const result = context.callFunction(extractResult.value, context.undefined, qjsHandle);
513
+ extractResult.value.dispose();
514
+ if (result.error) {
515
+ result.error.dispose();
516
+ throw new Error("Failed to call formdata extraction function");
517
+ }
518
+ const entries = context.dump(result.value);
519
+ result.value.dispose();
520
+ const formData = new FormData;
521
+ for (const [key, entry] of entries) {
522
+ if (entry.type === "file") {
523
+ formData.append(key, new File([], entry.name, { type: entry.fileType, lastModified: entry.lastModified }));
524
+ } else {
525
+ formData.append(key, entry.value);
526
+ }
527
+ }
528
+ return formData;
529
+ }
530
+ export {
531
+ runTestCode
532
+ };
533
+
534
+ //# debugId=69B05738000763A164756E2164756E21