@ricsam/isolate-client 0.0.1 → 0.1.1
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/README.md +112 -43
- package/dist/cjs/connection.cjs +504 -0
- package/dist/cjs/connection.cjs.map +10 -0
- package/dist/cjs/index.cjs +39 -0
- package/dist/cjs/index.cjs.map +10 -0
- package/dist/cjs/package.json +5 -0
- package/dist/cjs/types.cjs +26 -0
- package/dist/cjs/types.cjs.map +9 -0
- package/dist/mjs/connection.mjs +477 -0
- package/dist/mjs/connection.mjs.map +10 -0
- package/dist/mjs/index.mjs +8 -0
- package/dist/mjs/index.mjs.map +10 -0
- package/dist/mjs/package.json +5 -0
- package/dist/mjs/types.mjs +3 -0
- package/dist/mjs/types.mjs.map +9 -0
- package/dist/types/connection.d.ts +8 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/types.d.ts +164 -0
- package/package.json +47 -6
package/README.md
CHANGED
|
@@ -1,45 +1,114 @@
|
|
|
1
1
|
# @ricsam/isolate-client
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
3
|
+
Client library for connecting to the isolate daemon. Works with **any JavaScript runtime** (Node.js, Bun, Deno) since it only requires standard socket APIs.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm add @ricsam/isolate-client
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
**Features:**
|
|
10
|
+
- Connect via Unix socket or TCP
|
|
11
|
+
- Create and manage remote runtimes
|
|
12
|
+
- Execute code in isolated V8 contexts
|
|
13
|
+
- Dispatch HTTP requests to isolate handlers
|
|
14
|
+
- Bidirectional callbacks (console, fetch, fs)
|
|
15
|
+
- Test environment and Playwright support
|
|
16
|
+
|
|
17
|
+
**Basic Usage:**
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { connect } from "@ricsam/isolate-client";
|
|
21
|
+
|
|
22
|
+
// Connect to daemon
|
|
23
|
+
const client = await connect({
|
|
24
|
+
socket: "/tmp/isolate-daemon.sock",
|
|
25
|
+
// Or TCP: host: "127.0.0.1", port: 47891
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Create a runtime with callbacks
|
|
29
|
+
const runtime = await client.createRuntime({
|
|
30
|
+
memoryLimit: 128,
|
|
31
|
+
console: {
|
|
32
|
+
log: (...args) => console.log("[isolate]", ...args),
|
|
33
|
+
error: (...args) => console.error("[isolate]", ...args),
|
|
34
|
+
},
|
|
35
|
+
fetch: async (request) => fetch(request),
|
|
36
|
+
fs: {
|
|
37
|
+
readFile: async (path) => Bun.file(path).arrayBuffer(),
|
|
38
|
+
writeFile: async (path, data) => Bun.write(path, data),
|
|
39
|
+
stat: async (path) => {
|
|
40
|
+
const stat = await Bun.file(path).stat();
|
|
41
|
+
return { isFile: true, isDirectory: false, size: stat.size };
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Execute code
|
|
47
|
+
await runtime.eval(`console.log("Hello from isolate!")`);
|
|
48
|
+
|
|
49
|
+
// Set up HTTP handler and dispatch requests
|
|
50
|
+
await runtime.eval(`
|
|
51
|
+
serve({
|
|
52
|
+
fetch(request) {
|
|
53
|
+
return Response.json({ message: "Hello!" });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
`);
|
|
57
|
+
|
|
58
|
+
const response = await runtime.dispatchRequest(
|
|
59
|
+
new Request("http://localhost/api")
|
|
60
|
+
);
|
|
61
|
+
console.log(await response.json()); // { message: "Hello!" }
|
|
62
|
+
|
|
63
|
+
// Cleanup
|
|
64
|
+
await runtime.dispose();
|
|
65
|
+
await client.close();
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Test Environment:**
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// Setup test framework in isolate
|
|
72
|
+
await runtime.setupTestEnvironment();
|
|
73
|
+
|
|
74
|
+
// Define tests
|
|
75
|
+
await runtime.eval(`
|
|
76
|
+
describe("math", () => {
|
|
77
|
+
it("adds numbers", () => {
|
|
78
|
+
expect(1 + 1).toBe(2);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
`);
|
|
82
|
+
|
|
83
|
+
// Run tests
|
|
84
|
+
const results = await runtime.runTests();
|
|
85
|
+
console.log(`${results.passed}/${results.total} passed`);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Playwright Integration:**
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
// Setup Playwright (daemon launches browser)
|
|
92
|
+
await runtime.setupPlaywright({
|
|
93
|
+
browserType: "chromium",
|
|
94
|
+
headless: true,
|
|
95
|
+
onConsoleLog: (log) => console.log("[browser]", log),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Define browser tests
|
|
99
|
+
await runtime.eval(`
|
|
100
|
+
test("homepage loads", async () => {
|
|
101
|
+
await page.goto("https://example.com");
|
|
102
|
+
await expect(page.getByText("Example Domain")).toBeVisible();
|
|
103
|
+
});
|
|
104
|
+
`);
|
|
105
|
+
|
|
106
|
+
// Run tests
|
|
107
|
+
const results = await runtime.runPlaywrightTests();
|
|
108
|
+
console.log(`${results.passed}/${results.total} passed`);
|
|
109
|
+
|
|
110
|
+
// Get collected data
|
|
111
|
+
const data = await runtime.getCollectedData();
|
|
112
|
+
console.log("Console logs:", data.consoleLogs);
|
|
113
|
+
console.log("Network requests:", data.networkRequests);
|
|
114
|
+
```
|
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
// @bun @bun-cjs
|
|
2
|
+
(function(exports, require, module, __filename, __dirname) {var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
7
|
+
var __toCommonJS = (from) => {
|
|
8
|
+
var entry = __moduleCache.get(from), desc;
|
|
9
|
+
if (entry)
|
|
10
|
+
return entry;
|
|
11
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
13
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
14
|
+
get: () => from[key],
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
}));
|
|
17
|
+
__moduleCache.set(from, entry);
|
|
18
|
+
return entry;
|
|
19
|
+
};
|
|
20
|
+
var __export = (target, all) => {
|
|
21
|
+
for (var name in all)
|
|
22
|
+
__defProp(target, name, {
|
|
23
|
+
get: all[name],
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
set: (newValue) => all[name] = () => newValue
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// packages/isolate-client/src/connection.ts
|
|
31
|
+
var exports_connection = {};
|
|
32
|
+
__export(exports_connection, {
|
|
33
|
+
connect: () => connect
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(exports_connection);
|
|
36
|
+
var import_node_net = require("net");
|
|
37
|
+
var import_isolate_protocol = require("@ricsam/isolate-protocol");
|
|
38
|
+
var DEFAULT_TIMEOUT = 30000;
|
|
39
|
+
async function connect(options = {}) {
|
|
40
|
+
const socket = await createSocket(options);
|
|
41
|
+
const state = {
|
|
42
|
+
socket,
|
|
43
|
+
pendingRequests: new Map,
|
|
44
|
+
callbacks: new Map,
|
|
45
|
+
nextRequestId: 1,
|
|
46
|
+
nextCallbackId: 1,
|
|
47
|
+
connected: true,
|
|
48
|
+
playwrightEventHandlers: new Map
|
|
49
|
+
};
|
|
50
|
+
const parser = import_isolate_protocol.createFrameParser();
|
|
51
|
+
socket.on("data", (data) => {
|
|
52
|
+
try {
|
|
53
|
+
for (const frame of parser.feed(new Uint8Array(data))) {
|
|
54
|
+
handleMessage(frame.message, state);
|
|
55
|
+
}
|
|
56
|
+
} catch (err) {
|
|
57
|
+
console.error("Error parsing frame:", err);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
socket.on("close", () => {
|
|
61
|
+
state.connected = false;
|
|
62
|
+
for (const [, pending] of state.pendingRequests) {
|
|
63
|
+
pending.reject(new Error("Connection closed"));
|
|
64
|
+
}
|
|
65
|
+
state.pendingRequests.clear();
|
|
66
|
+
});
|
|
67
|
+
socket.on("error", (err) => {
|
|
68
|
+
console.error("Socket error:", err);
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
createRuntime: (runtimeOptions) => createRuntime(state, runtimeOptions),
|
|
72
|
+
close: async () => {
|
|
73
|
+
state.connected = false;
|
|
74
|
+
socket.destroy();
|
|
75
|
+
},
|
|
76
|
+
isConnected: () => state.connected
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function createSocket(options) {
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
const timeout = options.timeout ?? DEFAULT_TIMEOUT;
|
|
82
|
+
let socket;
|
|
83
|
+
const onError = (err) => {
|
|
84
|
+
reject(err);
|
|
85
|
+
};
|
|
86
|
+
const onConnect = () => {
|
|
87
|
+
socket.removeListener("error", onError);
|
|
88
|
+
resolve(socket);
|
|
89
|
+
};
|
|
90
|
+
if (options.socket) {
|
|
91
|
+
socket = import_node_net.connect(options.socket, onConnect);
|
|
92
|
+
} else {
|
|
93
|
+
socket = import_node_net.connect(options.port ?? 47891, options.host ?? "127.0.0.1", onConnect);
|
|
94
|
+
}
|
|
95
|
+
socket.on("error", onError);
|
|
96
|
+
const timeoutId = setTimeout(() => {
|
|
97
|
+
socket.destroy();
|
|
98
|
+
reject(new Error("Connection timeout"));
|
|
99
|
+
}, timeout);
|
|
100
|
+
socket.once("connect", () => {
|
|
101
|
+
clearTimeout(timeoutId);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function handleMessage(message, state) {
|
|
106
|
+
switch (message.type) {
|
|
107
|
+
case import_isolate_protocol.MessageType.RESPONSE_OK: {
|
|
108
|
+
const response = message;
|
|
109
|
+
const pending = state.pendingRequests.get(response.requestId);
|
|
110
|
+
if (pending) {
|
|
111
|
+
state.pendingRequests.delete(response.requestId);
|
|
112
|
+
if (pending.timeoutId)
|
|
113
|
+
clearTimeout(pending.timeoutId);
|
|
114
|
+
pending.resolve(response.data);
|
|
115
|
+
}
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
case import_isolate_protocol.MessageType.RESPONSE_ERROR: {
|
|
119
|
+
const response = message;
|
|
120
|
+
const pending = state.pendingRequests.get(response.requestId);
|
|
121
|
+
if (pending) {
|
|
122
|
+
state.pendingRequests.delete(response.requestId);
|
|
123
|
+
if (pending.timeoutId)
|
|
124
|
+
clearTimeout(pending.timeoutId);
|
|
125
|
+
const error = new Error(response.message);
|
|
126
|
+
if (response.details) {
|
|
127
|
+
error.name = response.details.name;
|
|
128
|
+
if (response.details.stack) {
|
|
129
|
+
error.stack = response.details.stack;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
pending.reject(error);
|
|
133
|
+
}
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
case import_isolate_protocol.MessageType.CALLBACK_INVOKE: {
|
|
137
|
+
const invoke = message;
|
|
138
|
+
handleCallbackInvoke(invoke, state);
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
case import_isolate_protocol.MessageType.PONG:
|
|
142
|
+
break;
|
|
143
|
+
case import_isolate_protocol.MessageType.PLAYWRIGHT_EVENT: {
|
|
144
|
+
const event = message;
|
|
145
|
+
const handler = state.playwrightEventHandlers.get(event.isolateId);
|
|
146
|
+
if (handler) {
|
|
147
|
+
switch (event.eventType) {
|
|
148
|
+
case "consoleLog":
|
|
149
|
+
handler.onConsoleLog?.(event.payload);
|
|
150
|
+
break;
|
|
151
|
+
case "networkRequest":
|
|
152
|
+
handler.onNetworkRequest?.(event.payload);
|
|
153
|
+
break;
|
|
154
|
+
case "networkResponse":
|
|
155
|
+
handler.onNetworkResponse?.(event.payload);
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
default:
|
|
162
|
+
console.warn(`Unexpected message type: ${message.type}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async function handleCallbackInvoke(invoke, state) {
|
|
166
|
+
const callback = state.callbacks.get(invoke.callbackId);
|
|
167
|
+
const response = {
|
|
168
|
+
type: import_isolate_protocol.MessageType.CALLBACK_RESPONSE,
|
|
169
|
+
requestId: invoke.requestId
|
|
170
|
+
};
|
|
171
|
+
if (!callback) {
|
|
172
|
+
response.error = {
|
|
173
|
+
name: "Error",
|
|
174
|
+
message: `Unknown callback: ${invoke.callbackId}`
|
|
175
|
+
};
|
|
176
|
+
} else {
|
|
177
|
+
try {
|
|
178
|
+
const result = await callback(...invoke.args);
|
|
179
|
+
response.result = result;
|
|
180
|
+
} catch (err) {
|
|
181
|
+
const error = err;
|
|
182
|
+
response.error = {
|
|
183
|
+
name: error.name,
|
|
184
|
+
message: error.message,
|
|
185
|
+
stack: error.stack
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
sendMessage(state.socket, response);
|
|
190
|
+
}
|
|
191
|
+
function sendMessage(socket, message) {
|
|
192
|
+
const frame = import_isolate_protocol.buildFrame(message);
|
|
193
|
+
socket.write(frame);
|
|
194
|
+
}
|
|
195
|
+
function sendRequest(state, message, timeout = DEFAULT_TIMEOUT) {
|
|
196
|
+
return new Promise((resolve, reject) => {
|
|
197
|
+
if (!state.connected) {
|
|
198
|
+
reject(new Error("Not connected"));
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const requestId = message.requestId;
|
|
202
|
+
const timeoutId = setTimeout(() => {
|
|
203
|
+
state.pendingRequests.delete(requestId);
|
|
204
|
+
reject(new Error("Request timeout"));
|
|
205
|
+
}, timeout);
|
|
206
|
+
state.pendingRequests.set(requestId, {
|
|
207
|
+
resolve,
|
|
208
|
+
reject,
|
|
209
|
+
timeoutId
|
|
210
|
+
});
|
|
211
|
+
sendMessage(state.socket, message);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
async function createRuntime(state, options = {}) {
|
|
215
|
+
const callbacks = {};
|
|
216
|
+
if (options.console) {
|
|
217
|
+
callbacks.console = registerConsoleCallbacks(state, options.console);
|
|
218
|
+
}
|
|
219
|
+
if (options.fetch) {
|
|
220
|
+
callbacks.fetch = registerFetchCallback(state, options.fetch);
|
|
221
|
+
}
|
|
222
|
+
if (options.fs) {
|
|
223
|
+
callbacks.fs = registerFsCallbacks(state, options.fs);
|
|
224
|
+
}
|
|
225
|
+
const requestId = state.nextRequestId++;
|
|
226
|
+
const request = {
|
|
227
|
+
type: import_isolate_protocol.MessageType.CREATE_RUNTIME,
|
|
228
|
+
requestId,
|
|
229
|
+
options: {
|
|
230
|
+
memoryLimit: options.memoryLimit,
|
|
231
|
+
callbacks
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
const result = await sendRequest(state, request);
|
|
235
|
+
const isolateId = result.isolateId;
|
|
236
|
+
return {
|
|
237
|
+
isolateId,
|
|
238
|
+
eval: async (code, filename) => {
|
|
239
|
+
const reqId = state.nextRequestId++;
|
|
240
|
+
const req = {
|
|
241
|
+
type: import_isolate_protocol.MessageType.EVAL,
|
|
242
|
+
requestId: reqId,
|
|
243
|
+
isolateId,
|
|
244
|
+
code,
|
|
245
|
+
filename
|
|
246
|
+
};
|
|
247
|
+
const res = await sendRequest(state, req);
|
|
248
|
+
return res.value;
|
|
249
|
+
},
|
|
250
|
+
dispatchRequest: async (request2, dispatchOptions) => {
|
|
251
|
+
const reqId = state.nextRequestId++;
|
|
252
|
+
const serialized = await serializeRequest(request2);
|
|
253
|
+
const req = {
|
|
254
|
+
type: import_isolate_protocol.MessageType.DISPATCH_REQUEST,
|
|
255
|
+
requestId: reqId,
|
|
256
|
+
isolateId,
|
|
257
|
+
request: serialized,
|
|
258
|
+
options: dispatchOptions
|
|
259
|
+
};
|
|
260
|
+
const res = await sendRequest(state, req, dispatchOptions?.timeout ?? DEFAULT_TIMEOUT);
|
|
261
|
+
return deserializeResponse(res.response);
|
|
262
|
+
},
|
|
263
|
+
tick: async (ms) => {
|
|
264
|
+
const reqId = state.nextRequestId++;
|
|
265
|
+
const req = {
|
|
266
|
+
type: import_isolate_protocol.MessageType.TICK,
|
|
267
|
+
requestId: reqId,
|
|
268
|
+
isolateId,
|
|
269
|
+
ms
|
|
270
|
+
};
|
|
271
|
+
await sendRequest(state, req);
|
|
272
|
+
},
|
|
273
|
+
setupTestEnvironment: async () => {
|
|
274
|
+
const reqId = state.nextRequestId++;
|
|
275
|
+
const req = {
|
|
276
|
+
type: import_isolate_protocol.MessageType.SETUP_TEST_ENV,
|
|
277
|
+
requestId: reqId,
|
|
278
|
+
isolateId
|
|
279
|
+
};
|
|
280
|
+
await sendRequest(state, req);
|
|
281
|
+
},
|
|
282
|
+
runTests: async (timeout) => {
|
|
283
|
+
const reqId = state.nextRequestId++;
|
|
284
|
+
const req = {
|
|
285
|
+
type: import_isolate_protocol.MessageType.RUN_TESTS,
|
|
286
|
+
requestId: reqId,
|
|
287
|
+
isolateId,
|
|
288
|
+
timeout
|
|
289
|
+
};
|
|
290
|
+
return sendRequest(state, req, timeout ?? DEFAULT_TIMEOUT);
|
|
291
|
+
},
|
|
292
|
+
setupPlaywright: async (playwrightOptions) => {
|
|
293
|
+
const reqId = state.nextRequestId++;
|
|
294
|
+
const req = {
|
|
295
|
+
type: import_isolate_protocol.MessageType.SETUP_PLAYWRIGHT,
|
|
296
|
+
requestId: reqId,
|
|
297
|
+
isolateId,
|
|
298
|
+
options: {
|
|
299
|
+
browserType: playwrightOptions?.browserType,
|
|
300
|
+
headless: playwrightOptions?.headless,
|
|
301
|
+
baseURL: playwrightOptions?.baseURL
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
if (playwrightOptions?.onConsoleLog || playwrightOptions?.onNetworkRequest || playwrightOptions?.onNetworkResponse) {
|
|
305
|
+
state.playwrightEventHandlers.set(isolateId, {
|
|
306
|
+
onConsoleLog: playwrightOptions.onConsoleLog,
|
|
307
|
+
onNetworkRequest: playwrightOptions.onNetworkRequest,
|
|
308
|
+
onNetworkResponse: playwrightOptions.onNetworkResponse
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
await sendRequest(state, req);
|
|
312
|
+
},
|
|
313
|
+
runPlaywrightTests: async (timeout) => {
|
|
314
|
+
const reqId = state.nextRequestId++;
|
|
315
|
+
const req = {
|
|
316
|
+
type: import_isolate_protocol.MessageType.RUN_PLAYWRIGHT_TESTS,
|
|
317
|
+
requestId: reqId,
|
|
318
|
+
isolateId,
|
|
319
|
+
timeout
|
|
320
|
+
};
|
|
321
|
+
return sendRequest(state, req, timeout ?? DEFAULT_TIMEOUT);
|
|
322
|
+
},
|
|
323
|
+
resetPlaywrightTests: async () => {
|
|
324
|
+
const reqId = state.nextRequestId++;
|
|
325
|
+
const req = {
|
|
326
|
+
type: import_isolate_protocol.MessageType.RESET_PLAYWRIGHT_TESTS,
|
|
327
|
+
requestId: reqId,
|
|
328
|
+
isolateId
|
|
329
|
+
};
|
|
330
|
+
await sendRequest(state, req);
|
|
331
|
+
},
|
|
332
|
+
getCollectedData: async () => {
|
|
333
|
+
const reqId = state.nextRequestId++;
|
|
334
|
+
const req = {
|
|
335
|
+
type: import_isolate_protocol.MessageType.GET_COLLECTED_DATA,
|
|
336
|
+
requestId: reqId,
|
|
337
|
+
isolateId
|
|
338
|
+
};
|
|
339
|
+
return sendRequest(state, req);
|
|
340
|
+
},
|
|
341
|
+
dispose: async () => {
|
|
342
|
+
state.playwrightEventHandlers.delete(isolateId);
|
|
343
|
+
const reqId = state.nextRequestId++;
|
|
344
|
+
const req = {
|
|
345
|
+
type: import_isolate_protocol.MessageType.DISPOSE_RUNTIME,
|
|
346
|
+
requestId: reqId,
|
|
347
|
+
isolateId
|
|
348
|
+
};
|
|
349
|
+
await sendRequest(state, req);
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
function registerConsoleCallbacks(state, callbacks) {
|
|
354
|
+
const registrations = {};
|
|
355
|
+
const register = (name, fn) => {
|
|
356
|
+
const callbackId = state.nextCallbackId++;
|
|
357
|
+
state.callbacks.set(callbackId, (_level, ...args) => {
|
|
358
|
+
fn(...args);
|
|
359
|
+
});
|
|
360
|
+
registrations[name] = { callbackId, name, async: false };
|
|
361
|
+
};
|
|
362
|
+
if (callbacks.log)
|
|
363
|
+
register("log", callbacks.log);
|
|
364
|
+
if (callbacks.warn)
|
|
365
|
+
register("warn", callbacks.warn);
|
|
366
|
+
if (callbacks.error)
|
|
367
|
+
register("error", callbacks.error);
|
|
368
|
+
if (callbacks.info)
|
|
369
|
+
register("info", callbacks.info);
|
|
370
|
+
if (callbacks.debug)
|
|
371
|
+
register("debug", callbacks.debug);
|
|
372
|
+
if (callbacks.dir)
|
|
373
|
+
register("dir", callbacks.dir);
|
|
374
|
+
return registrations;
|
|
375
|
+
}
|
|
376
|
+
function registerFetchCallback(state, callback) {
|
|
377
|
+
const callbackId = state.nextCallbackId++;
|
|
378
|
+
state.callbacks.set(callbackId, async (serialized) => {
|
|
379
|
+
const request = deserializeRequest(serialized);
|
|
380
|
+
const response = await callback(request);
|
|
381
|
+
return serializeResponse(response);
|
|
382
|
+
});
|
|
383
|
+
return { callbackId, name: "fetch", async: true };
|
|
384
|
+
}
|
|
385
|
+
function registerFsCallbacks(state, callbacks) {
|
|
386
|
+
const registrations = {};
|
|
387
|
+
if (callbacks.readFile) {
|
|
388
|
+
const callbackId = state.nextCallbackId++;
|
|
389
|
+
state.callbacks.set(callbackId, async (path) => {
|
|
390
|
+
const result = await callbacks.readFile(path);
|
|
391
|
+
return new Uint8Array(result);
|
|
392
|
+
});
|
|
393
|
+
registrations.readFile = { callbackId, name: "readFile", async: true };
|
|
394
|
+
}
|
|
395
|
+
if (callbacks.writeFile) {
|
|
396
|
+
const callbackId = state.nextCallbackId++;
|
|
397
|
+
state.callbacks.set(callbackId, async (path, data) => {
|
|
398
|
+
let buffer;
|
|
399
|
+
if (data instanceof Uint8Array) {
|
|
400
|
+
buffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
|
|
401
|
+
} else if (Array.isArray(data)) {
|
|
402
|
+
buffer = new Uint8Array(data).buffer;
|
|
403
|
+
} else if (data instanceof ArrayBuffer) {
|
|
404
|
+
buffer = data;
|
|
405
|
+
} else {
|
|
406
|
+
buffer = new ArrayBuffer(0);
|
|
407
|
+
}
|
|
408
|
+
await callbacks.writeFile(path, buffer);
|
|
409
|
+
});
|
|
410
|
+
registrations.writeFile = { callbackId, name: "writeFile", async: true };
|
|
411
|
+
}
|
|
412
|
+
if (callbacks.unlink) {
|
|
413
|
+
const callbackId = state.nextCallbackId++;
|
|
414
|
+
state.callbacks.set(callbackId, async (path) => {
|
|
415
|
+
await callbacks.unlink(path);
|
|
416
|
+
});
|
|
417
|
+
registrations.unlink = { callbackId, name: "unlink", async: true };
|
|
418
|
+
}
|
|
419
|
+
if (callbacks.readdir) {
|
|
420
|
+
const callbackId = state.nextCallbackId++;
|
|
421
|
+
state.callbacks.set(callbackId, async (path) => {
|
|
422
|
+
return callbacks.readdir(path);
|
|
423
|
+
});
|
|
424
|
+
registrations.readdir = { callbackId, name: "readdir", async: true };
|
|
425
|
+
}
|
|
426
|
+
if (callbacks.mkdir) {
|
|
427
|
+
const callbackId = state.nextCallbackId++;
|
|
428
|
+
state.callbacks.set(callbackId, async (path, options) => {
|
|
429
|
+
await callbacks.mkdir(path, options);
|
|
430
|
+
});
|
|
431
|
+
registrations.mkdir = { callbackId, name: "mkdir", async: true };
|
|
432
|
+
}
|
|
433
|
+
if (callbacks.rmdir) {
|
|
434
|
+
const callbackId = state.nextCallbackId++;
|
|
435
|
+
state.callbacks.set(callbackId, async (path) => {
|
|
436
|
+
await callbacks.rmdir(path);
|
|
437
|
+
});
|
|
438
|
+
registrations.rmdir = { callbackId, name: "rmdir", async: true };
|
|
439
|
+
}
|
|
440
|
+
if (callbacks.stat) {
|
|
441
|
+
const callbackId = state.nextCallbackId++;
|
|
442
|
+
state.callbacks.set(callbackId, async (path) => {
|
|
443
|
+
return callbacks.stat(path);
|
|
444
|
+
});
|
|
445
|
+
registrations.stat = { callbackId, name: "stat", async: true };
|
|
446
|
+
}
|
|
447
|
+
if (callbacks.rename) {
|
|
448
|
+
const callbackId = state.nextCallbackId++;
|
|
449
|
+
state.callbacks.set(callbackId, async (from, to) => {
|
|
450
|
+
await callbacks.rename(from, to);
|
|
451
|
+
});
|
|
452
|
+
registrations.rename = { callbackId, name: "rename", async: true };
|
|
453
|
+
}
|
|
454
|
+
return registrations;
|
|
455
|
+
}
|
|
456
|
+
async function serializeRequest(request) {
|
|
457
|
+
const headers = [];
|
|
458
|
+
request.headers.forEach((value, key) => {
|
|
459
|
+
headers.push([key, value]);
|
|
460
|
+
});
|
|
461
|
+
let body = null;
|
|
462
|
+
if (request.body) {
|
|
463
|
+
body = new Uint8Array(await request.arrayBuffer());
|
|
464
|
+
}
|
|
465
|
+
return {
|
|
466
|
+
method: request.method,
|
|
467
|
+
url: request.url,
|
|
468
|
+
headers,
|
|
469
|
+
body
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
async function serializeResponse(response) {
|
|
473
|
+
const headers = [];
|
|
474
|
+
response.headers.forEach((value, key) => {
|
|
475
|
+
headers.push([key, value]);
|
|
476
|
+
});
|
|
477
|
+
let body = null;
|
|
478
|
+
if (response.body) {
|
|
479
|
+
body = new Uint8Array(await response.arrayBuffer());
|
|
480
|
+
}
|
|
481
|
+
return {
|
|
482
|
+
status: response.status,
|
|
483
|
+
statusText: response.statusText,
|
|
484
|
+
headers,
|
|
485
|
+
body
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
function deserializeRequest(data) {
|
|
489
|
+
return new Request(data.url, {
|
|
490
|
+
method: data.method,
|
|
491
|
+
headers: data.headers,
|
|
492
|
+
body: data.body
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
function deserializeResponse(data) {
|
|
496
|
+
return new Response(data.body, {
|
|
497
|
+
status: data.status,
|
|
498
|
+
statusText: data.statusText,
|
|
499
|
+
headers: data.headers
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
})
|
|
503
|
+
|
|
504
|
+
//# debugId=AC520FAF0080FE0764756E2164756E21
|