@ricsam/isolate-client 0.1.14 → 0.1.16
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 +238 -6
- package/dist/cjs/connection.cjs +377 -165
- package/dist/cjs/connection.cjs.map +3 -3
- package/dist/cjs/index.cjs +2 -1
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/connection.mjs +383 -163
- package/dist/mjs/connection.mjs.map +3 -3
- package/dist/mjs/index.mjs +3 -2
- package/dist/mjs/index.mjs.map +2 -2
- package/dist/mjs/package.json +1 -1
- package/dist/types/connection.d.ts +1 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/types.d.ts +17 -10
- package/package.json +1 -1
package/dist/cjs/connection.cjs
CHANGED
|
@@ -42,6 +42,7 @@ var __export = (target, all) => {
|
|
|
42
42
|
// packages/isolate-client/src/connection.ts
|
|
43
43
|
var exports_connection = {};
|
|
44
44
|
__export(exports_connection, {
|
|
45
|
+
isBenignDisposeError: () => isBenignDisposeError,
|
|
45
46
|
connect: () => connect
|
|
46
47
|
});
|
|
47
48
|
module.exports = __toCommonJS(exports_connection);
|
|
@@ -49,8 +50,10 @@ var import_node_net = require("node:net");
|
|
|
49
50
|
var import_node_path = __toESM(require("node:path"));
|
|
50
51
|
var import_isolate_protocol = require("@ricsam/isolate-protocol");
|
|
51
52
|
var import_client = require("@ricsam/isolate-playwright/client");
|
|
52
|
-
var DEFAULT_TIMEOUT = 30000;
|
|
53
53
|
var isolateWsCallbacks = new Map;
|
|
54
|
+
var isolateClientWebSockets = new Map;
|
|
55
|
+
var isolateWebSocketCallbacks = new Map;
|
|
56
|
+
var isolateEventListeners = new Map;
|
|
54
57
|
async function connect(options = {}) {
|
|
55
58
|
const socket = await createSocket(options);
|
|
56
59
|
const state = {
|
|
@@ -80,9 +83,6 @@ async function connect(options = {}) {
|
|
|
80
83
|
socket.on("close", () => {
|
|
81
84
|
state.connected = false;
|
|
82
85
|
for (const [, pending] of state.pendingRequests) {
|
|
83
|
-
if (pending.timeoutId) {
|
|
84
|
-
clearTimeout(pending.timeoutId);
|
|
85
|
-
}
|
|
86
86
|
pending.reject(new Error("Connection closed"));
|
|
87
87
|
}
|
|
88
88
|
state.pendingRequests.clear();
|
|
@@ -121,7 +121,7 @@ async function connect(options = {}) {
|
|
|
121
121
|
}
|
|
122
122
|
function createSocket(options) {
|
|
123
123
|
return new Promise((resolve, reject) => {
|
|
124
|
-
const timeout = options.timeout
|
|
124
|
+
const timeout = options.timeout;
|
|
125
125
|
let socket;
|
|
126
126
|
const onError = (err) => {
|
|
127
127
|
reject(err);
|
|
@@ -136,13 +136,15 @@ function createSocket(options) {
|
|
|
136
136
|
socket = import_node_net.connect(options.port ?? 47891, options.host ?? "127.0.0.1", onConnect);
|
|
137
137
|
}
|
|
138
138
|
socket.on("error", onError);
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
139
|
+
if (timeout && timeout > 0) {
|
|
140
|
+
const timeoutId = setTimeout(() => {
|
|
141
|
+
socket.destroy();
|
|
142
|
+
reject(new Error("Connection timeout"));
|
|
143
|
+
}, timeout);
|
|
144
|
+
socket.once("connect", () => {
|
|
145
|
+
clearTimeout(timeoutId);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
146
148
|
});
|
|
147
149
|
}
|
|
148
150
|
function handleMessage(message, state) {
|
|
@@ -152,8 +154,6 @@ function handleMessage(message, state) {
|
|
|
152
154
|
const pending = state.pendingRequests.get(response.requestId);
|
|
153
155
|
if (pending) {
|
|
154
156
|
state.pendingRequests.delete(response.requestId);
|
|
155
|
-
if (pending.timeoutId)
|
|
156
|
-
clearTimeout(pending.timeoutId);
|
|
157
157
|
pending.resolve(response.data);
|
|
158
158
|
}
|
|
159
159
|
break;
|
|
@@ -163,8 +163,6 @@ function handleMessage(message, state) {
|
|
|
163
163
|
const pending = state.pendingRequests.get(response.requestId);
|
|
164
164
|
if (pending) {
|
|
165
165
|
state.pendingRequests.delete(response.requestId);
|
|
166
|
-
if (pending.timeoutId)
|
|
167
|
-
clearTimeout(pending.timeoutId);
|
|
168
166
|
const error = new Error(response.message);
|
|
169
167
|
if (response.details) {
|
|
170
168
|
error.name = response.details.name;
|
|
@@ -191,27 +189,9 @@ function handleMessage(message, state) {
|
|
|
191
189
|
}
|
|
192
190
|
break;
|
|
193
191
|
}
|
|
194
|
-
case import_isolate_protocol.MessageType.
|
|
192
|
+
case import_isolate_protocol.MessageType.ISOLATE_EVENT: {
|
|
195
193
|
const msg = message;
|
|
196
|
-
|
|
197
|
-
if (callbacks) {
|
|
198
|
-
let data;
|
|
199
|
-
if (msg.command.data instanceof Uint8Array) {
|
|
200
|
-
data = msg.command.data.buffer.slice(msg.command.data.byteOffset, msg.command.data.byteOffset + msg.command.data.byteLength);
|
|
201
|
-
} else {
|
|
202
|
-
data = msg.command.data;
|
|
203
|
-
}
|
|
204
|
-
const cmd = {
|
|
205
|
-
type: msg.command.type,
|
|
206
|
-
connectionId: msg.command.connectionId,
|
|
207
|
-
data,
|
|
208
|
-
code: msg.command.code,
|
|
209
|
-
reason: msg.command.reason
|
|
210
|
-
};
|
|
211
|
-
for (const cb of callbacks) {
|
|
212
|
-
cb(cmd);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
194
|
+
handleIsolateEvent(msg, state);
|
|
215
195
|
break;
|
|
216
196
|
}
|
|
217
197
|
case import_isolate_protocol.MessageType.RESPONSE_STREAM_START: {
|
|
@@ -281,8 +261,6 @@ function handleMessage(message, state) {
|
|
|
281
261
|
const pending = state.pendingRequests.get(msg.requestId);
|
|
282
262
|
if (pending) {
|
|
283
263
|
state.pendingRequests.delete(msg.requestId);
|
|
284
|
-
if (pending.timeoutId)
|
|
285
|
-
clearTimeout(pending.timeoutId);
|
|
286
264
|
const response = new Response(readableStream, {
|
|
287
265
|
status: msg.metadata?.status ?? 200,
|
|
288
266
|
statusText: msg.metadata?.statusText ?? "OK",
|
|
@@ -407,25 +385,24 @@ function sendMessage(socket, message) {
|
|
|
407
385
|
const frame = import_isolate_protocol.buildFrame(message);
|
|
408
386
|
socket.write(frame);
|
|
409
387
|
}
|
|
410
|
-
function sendRequest(state, message
|
|
388
|
+
function sendRequest(state, message) {
|
|
411
389
|
return new Promise((resolve, reject) => {
|
|
412
390
|
if (!state.connected) {
|
|
413
391
|
reject(new Error("Not connected"));
|
|
414
392
|
return;
|
|
415
393
|
}
|
|
416
394
|
const requestId = message.requestId;
|
|
417
|
-
const timeoutId = setTimeout(() => {
|
|
418
|
-
state.pendingRequests.delete(requestId);
|
|
419
|
-
reject(new Error("Request timeout"));
|
|
420
|
-
}, timeout);
|
|
421
395
|
state.pendingRequests.set(requestId, {
|
|
422
396
|
resolve,
|
|
423
|
-
reject
|
|
424
|
-
timeoutId
|
|
397
|
+
reject
|
|
425
398
|
});
|
|
426
399
|
sendMessage(state.socket, message);
|
|
427
400
|
});
|
|
428
401
|
}
|
|
402
|
+
function isBenignDisposeError(error) {
|
|
403
|
+
const message = error instanceof Error ? error.message : String(error ?? "");
|
|
404
|
+
return /isolate not owned by this connection|isolate not found|not connected|connection closed/i.test(message);
|
|
405
|
+
}
|
|
429
406
|
async function createRuntime(state, options = {}, namespaceId) {
|
|
430
407
|
const callbacks = {};
|
|
431
408
|
if (options.console) {
|
|
@@ -449,73 +426,76 @@ async function createRuntime(state, options = {}, namespaceId) {
|
|
|
449
426
|
const networkResponses = [];
|
|
450
427
|
const pageListenerCleanups = [];
|
|
451
428
|
if (options.playwright) {
|
|
452
|
-
playwrightHandler =
|
|
453
|
-
|
|
454
|
-
|
|
429
|
+
playwrightHandler = options.playwright.handler;
|
|
430
|
+
if (!playwrightHandler) {
|
|
431
|
+
throw new Error("playwright.handler is required when using playwright options");
|
|
432
|
+
}
|
|
433
|
+
const page = import_client.getDefaultPlaywrightHandlerMetadata(playwrightHandler)?.page;
|
|
455
434
|
const handlerCallbackId = state.nextCallbackId++;
|
|
456
435
|
state.callbacks.set(handlerCallbackId, async (opJson) => {
|
|
457
436
|
const op = JSON.parse(opJson);
|
|
458
437
|
const result2 = await playwrightHandler(op);
|
|
459
438
|
return JSON.stringify(result2);
|
|
460
439
|
});
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
440
|
+
if (page) {
|
|
441
|
+
const onConsole = (msg) => {
|
|
442
|
+
const entry = {
|
|
443
|
+
level: msg.type(),
|
|
444
|
+
stdout: msg.text(),
|
|
445
|
+
timestamp: Date.now()
|
|
446
|
+
};
|
|
447
|
+
browserConsoleLogs.push(entry);
|
|
448
|
+
if (options.playwright.onEvent) {
|
|
449
|
+
options.playwright.onEvent({
|
|
450
|
+
type: "browserConsoleLog",
|
|
451
|
+
...entry
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
if (options.playwright.console && options.console?.onEntry) {
|
|
455
|
+
options.console.onEntry({
|
|
456
|
+
type: "browserOutput",
|
|
457
|
+
...entry
|
|
458
|
+
});
|
|
459
|
+
} else if (options.playwright.console) {
|
|
460
|
+
const prefix = entry.level === "error" ? "[browser:error]" : "[browser]";
|
|
461
|
+
console.log(prefix, entry.stdout);
|
|
462
|
+
}
|
|
467
463
|
};
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
options.
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
console.log(prefix, entry.stdout);
|
|
483
|
-
}
|
|
484
|
-
};
|
|
485
|
-
const onRequest = (request2) => {
|
|
486
|
-
const info = {
|
|
487
|
-
url: request2.url(),
|
|
488
|
-
method: request2.method(),
|
|
489
|
-
headers: request2.headers(),
|
|
490
|
-
timestamp: Date.now()
|
|
464
|
+
const onRequest = (request2) => {
|
|
465
|
+
const info = {
|
|
466
|
+
url: request2.url(),
|
|
467
|
+
method: request2.method(),
|
|
468
|
+
headers: request2.headers(),
|
|
469
|
+
timestamp: Date.now()
|
|
470
|
+
};
|
|
471
|
+
networkRequests.push(info);
|
|
472
|
+
if (options.playwright.onEvent) {
|
|
473
|
+
options.playwright.onEvent({
|
|
474
|
+
type: "networkRequest",
|
|
475
|
+
...info
|
|
476
|
+
});
|
|
477
|
+
}
|
|
491
478
|
};
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
479
|
+
const onResponse = (response) => {
|
|
480
|
+
const info = {
|
|
481
|
+
url: response.url(),
|
|
482
|
+
status: response.status(),
|
|
483
|
+
headers: response.headers(),
|
|
484
|
+
timestamp: Date.now()
|
|
485
|
+
};
|
|
486
|
+
networkResponses.push(info);
|
|
487
|
+
if (options.playwright.onEvent) {
|
|
488
|
+
options.playwright.onEvent({
|
|
489
|
+
type: "networkResponse",
|
|
490
|
+
...info
|
|
491
|
+
});
|
|
492
|
+
}
|
|
506
493
|
};
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
});
|
|
513
|
-
}
|
|
514
|
-
};
|
|
515
|
-
page.on("console", onConsole);
|
|
516
|
-
page.on("request", onRequest);
|
|
517
|
-
page.on("response", onResponse);
|
|
518
|
-
pageListenerCleanups.push(() => page.removeListener("console", onConsole), () => page.removeListener("request", onRequest), () => page.removeListener("response", onResponse));
|
|
494
|
+
page.on("console", onConsole);
|
|
495
|
+
page.on("request", onRequest);
|
|
496
|
+
page.on("response", onResponse);
|
|
497
|
+
pageListenerCleanups.push(() => page.removeListener("console", onConsole), () => page.removeListener("request", onRequest), () => page.removeListener("response", onResponse));
|
|
498
|
+
}
|
|
519
499
|
callbacks.playwright = {
|
|
520
500
|
handlerCallbackId,
|
|
521
501
|
console: options.playwright.console && !options.console?.onEntry
|
|
@@ -563,8 +543,18 @@ async function createRuntime(state, options = {}, namespaceId) {
|
|
|
563
543
|
const reused = result.reused ?? false;
|
|
564
544
|
const wsCommandCallbacks = new Set;
|
|
565
545
|
isolateWsCallbacks.set(isolateId, wsCommandCallbacks);
|
|
546
|
+
if (options.onWebSocketCommand) {
|
|
547
|
+
wsCommandCallbacks.add(options.onWebSocketCommand);
|
|
548
|
+
}
|
|
549
|
+
if (options.webSocket) {
|
|
550
|
+
isolateWebSocketCallbacks.set(isolateId, options.webSocket);
|
|
551
|
+
}
|
|
566
552
|
const fetchHandle = {
|
|
567
553
|
async dispatchRequest(req, opts) {
|
|
554
|
+
const signal = opts?.signal;
|
|
555
|
+
if (signal?.aborted) {
|
|
556
|
+
throw new DOMException("The operation was aborted", "AbortError");
|
|
557
|
+
}
|
|
568
558
|
const reqId = state.nextRequestId++;
|
|
569
559
|
const serialized = await serializeRequestWithStreaming(state, req);
|
|
570
560
|
const { bodyStream, ...serializableRequest } = serialized;
|
|
@@ -572,24 +562,40 @@ async function createRuntime(state, options = {}, namespaceId) {
|
|
|
572
562
|
type: import_isolate_protocol.MessageType.DISPATCH_REQUEST,
|
|
573
563
|
requestId: reqId,
|
|
574
564
|
isolateId,
|
|
575
|
-
request: serializableRequest
|
|
576
|
-
options: opts
|
|
565
|
+
request: serializableRequest
|
|
577
566
|
};
|
|
578
567
|
const handleResponse = (res) => {
|
|
579
568
|
if (res.__streaming && res.response instanceof Response) {
|
|
580
569
|
return res.response;
|
|
581
570
|
}
|
|
582
|
-
return deserializeResponse(res.response);
|
|
571
|
+
return import_isolate_protocol.deserializeResponse(res.response);
|
|
583
572
|
};
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
573
|
+
let onAbort;
|
|
574
|
+
if (signal) {
|
|
575
|
+
onAbort = () => {
|
|
576
|
+
const pending = state.pendingRequests.get(reqId);
|
|
577
|
+
if (pending) {
|
|
578
|
+
state.pendingRequests.delete(reqId);
|
|
579
|
+
pending.reject(new DOMException("The operation was aborted", "AbortError"));
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
583
|
+
}
|
|
584
|
+
try {
|
|
585
|
+
if (serialized.bodyStreamId !== undefined && bodyStream) {
|
|
586
|
+
const streamId = serialized.bodyStreamId;
|
|
587
|
+
const responsePromise = sendRequest(state, request2);
|
|
588
|
+
await sendBodyStream(state, streamId, bodyStream);
|
|
589
|
+
const res = await responsePromise;
|
|
590
|
+
return handleResponse(res);
|
|
591
|
+
} else {
|
|
592
|
+
const res = await sendRequest(state, request2);
|
|
593
|
+
return handleResponse(res);
|
|
594
|
+
}
|
|
595
|
+
} finally {
|
|
596
|
+
if (signal && onAbort) {
|
|
597
|
+
signal.removeEventListener("abort", onAbort);
|
|
598
|
+
}
|
|
593
599
|
}
|
|
594
600
|
},
|
|
595
601
|
async getUpgradeRequest() {
|
|
@@ -736,7 +742,7 @@ async function createRuntime(state, options = {}, namespaceId) {
|
|
|
736
742
|
isolateId,
|
|
737
743
|
timeout
|
|
738
744
|
};
|
|
739
|
-
return sendRequest(state, req
|
|
745
|
+
return sendRequest(state, req);
|
|
740
746
|
},
|
|
741
747
|
async hasTests() {
|
|
742
748
|
if (!testEnvironmentEnabled) {
|
|
@@ -778,7 +784,7 @@ async function createRuntime(state, options = {}, namespaceId) {
|
|
|
778
784
|
const playwrightHandle = {
|
|
779
785
|
getCollectedData() {
|
|
780
786
|
if (!playwrightEnabled) {
|
|
781
|
-
throw new Error("Playwright not configured. Provide playwright.
|
|
787
|
+
throw new Error("Playwright not configured. Provide playwright.handler in createRuntime options.");
|
|
782
788
|
}
|
|
783
789
|
return {
|
|
784
790
|
browserConsoleLogs: [...browserConsoleLogs],
|
|
@@ -788,7 +794,7 @@ async function createRuntime(state, options = {}, namespaceId) {
|
|
|
788
794
|
},
|
|
789
795
|
clearCollectedData() {
|
|
790
796
|
if (!playwrightEnabled) {
|
|
791
|
-
throw new Error("Playwright not configured. Provide playwright.
|
|
797
|
+
throw new Error("Playwright not configured. Provide playwright.handler in createRuntime options.");
|
|
792
798
|
}
|
|
793
799
|
browserConsoleLogs.length = 0;
|
|
794
800
|
networkRequests.length = 0;
|
|
@@ -797,7 +803,6 @@ async function createRuntime(state, options = {}, namespaceId) {
|
|
|
797
803
|
};
|
|
798
804
|
return {
|
|
799
805
|
id: isolateId,
|
|
800
|
-
isolateId,
|
|
801
806
|
reused,
|
|
802
807
|
fetch: fetchHandle,
|
|
803
808
|
timers: timersHandle,
|
|
@@ -812,24 +817,69 @@ async function createRuntime(state, options = {}, namespaceId) {
|
|
|
812
817
|
requestId: reqId,
|
|
813
818
|
isolateId,
|
|
814
819
|
code,
|
|
815
|
-
filename: options2?.filename
|
|
816
|
-
maxExecutionMs: options2?.maxExecutionMs,
|
|
817
|
-
module: true
|
|
820
|
+
filename: options2?.filename
|
|
818
821
|
};
|
|
819
822
|
await sendRequest(state, req);
|
|
820
823
|
},
|
|
824
|
+
on(event, callback) {
|
|
825
|
+
let listeners = isolateEventListeners.get(isolateId);
|
|
826
|
+
if (!listeners) {
|
|
827
|
+
listeners = new Map;
|
|
828
|
+
isolateEventListeners.set(isolateId, listeners);
|
|
829
|
+
}
|
|
830
|
+
let eventListeners = listeners.get(event);
|
|
831
|
+
if (!eventListeners) {
|
|
832
|
+
eventListeners = new Set;
|
|
833
|
+
listeners.set(event, eventListeners);
|
|
834
|
+
}
|
|
835
|
+
eventListeners.add(callback);
|
|
836
|
+
return () => {
|
|
837
|
+
eventListeners.delete(callback);
|
|
838
|
+
if (eventListeners.size === 0) {
|
|
839
|
+
listeners.delete(event);
|
|
840
|
+
if (listeners.size === 0) {
|
|
841
|
+
isolateEventListeners.delete(isolateId);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
};
|
|
845
|
+
},
|
|
846
|
+
emit(event, payload) {
|
|
847
|
+
sendMessage(state.socket, {
|
|
848
|
+
type: import_isolate_protocol.MessageType.CLIENT_EVENT,
|
|
849
|
+
isolateId,
|
|
850
|
+
event,
|
|
851
|
+
payload
|
|
852
|
+
});
|
|
853
|
+
},
|
|
821
854
|
dispose: async () => {
|
|
822
855
|
for (const cleanup of pageListenerCleanups) {
|
|
823
856
|
cleanup();
|
|
824
857
|
}
|
|
825
858
|
isolateWsCallbacks.delete(isolateId);
|
|
859
|
+
isolateWebSocketCallbacks.delete(isolateId);
|
|
860
|
+
isolateEventListeners.delete(isolateId);
|
|
861
|
+
const clientSockets = isolateClientWebSockets.get(isolateId);
|
|
862
|
+
if (clientSockets) {
|
|
863
|
+
for (const ws of clientSockets.values()) {
|
|
864
|
+
if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) {
|
|
865
|
+
ws.close(1000, "Isolate disposed");
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
isolateClientWebSockets.delete(isolateId);
|
|
869
|
+
}
|
|
826
870
|
const reqId = state.nextRequestId++;
|
|
827
871
|
const req = {
|
|
828
872
|
type: import_isolate_protocol.MessageType.DISPOSE_RUNTIME,
|
|
829
873
|
requestId: reqId,
|
|
830
874
|
isolateId
|
|
831
875
|
};
|
|
832
|
-
|
|
876
|
+
try {
|
|
877
|
+
await sendRequest(state, req);
|
|
878
|
+
} catch (error) {
|
|
879
|
+
if (!isBenignDisposeError(error)) {
|
|
880
|
+
throw error;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
833
883
|
}
|
|
834
884
|
};
|
|
835
885
|
}
|
|
@@ -857,8 +907,15 @@ function registerFetchCallback(state, callback) {
|
|
|
857
907
|
const callbackId = state.nextCallbackId++;
|
|
858
908
|
state.callbacksNeedingRequestId.add(callbackId);
|
|
859
909
|
state.callbacks.set(callbackId, async (serialized, requestId) => {
|
|
860
|
-
const
|
|
861
|
-
const
|
|
910
|
+
const data = serialized;
|
|
911
|
+
const init = {
|
|
912
|
+
method: data.method,
|
|
913
|
+
headers: data.headers,
|
|
914
|
+
rawBody: data.body ?? null,
|
|
915
|
+
body: data.body ?? null,
|
|
916
|
+
signal: new AbortController().signal
|
|
917
|
+
};
|
|
918
|
+
const response = await callback(data.url, init);
|
|
862
919
|
const contentLength = response.headers.get("content-length");
|
|
863
920
|
const knownSize = contentLength ? parseInt(contentLength, 10) : null;
|
|
864
921
|
const isNetworkResponse = response.url && (response.url.startsWith("http://") || response.url.startsWith("https://"));
|
|
@@ -883,7 +940,7 @@ function registerFetchCallback(state, callback) {
|
|
|
883
940
|
streamCallbackResponseBody(state, streamId, requestId, response.body);
|
|
884
941
|
return { __callbackStreaming: true, streamId };
|
|
885
942
|
}
|
|
886
|
-
return serializeResponse(response);
|
|
943
|
+
return import_isolate_protocol.serializeResponse(response);
|
|
887
944
|
});
|
|
888
945
|
return { callbackId, name: "fetch", type: "async" };
|
|
889
946
|
}
|
|
@@ -1011,12 +1068,6 @@ var clientIteratorSessions = new Map;
|
|
|
1011
1068
|
var nextClientIteratorId = 1;
|
|
1012
1069
|
var returnedPromiseRegistry = new Map;
|
|
1013
1070
|
var returnedIteratorRegistry = new Map;
|
|
1014
|
-
function isPromiseRef(value) {
|
|
1015
|
-
return typeof value === "object" && value !== null && value.__type === "PromiseRef";
|
|
1016
|
-
}
|
|
1017
|
-
function isAsyncIteratorRef(value) {
|
|
1018
|
-
return typeof value === "object" && value !== null && value.__type === "AsyncIteratorRef";
|
|
1019
|
-
}
|
|
1020
1071
|
function registerCustomFunctions(state, customFunctions) {
|
|
1021
1072
|
const registrations = {};
|
|
1022
1073
|
for (const [name, def] of Object.entries(customFunctions)) {
|
|
@@ -1099,7 +1150,7 @@ function registerCustomFunctions(state, customFunctions) {
|
|
|
1099
1150
|
if (value === null || typeof value !== "object") {
|
|
1100
1151
|
return value;
|
|
1101
1152
|
}
|
|
1102
|
-
if (isPromiseRef(value)) {
|
|
1153
|
+
if (import_isolate_protocol.isPromiseRef(value)) {
|
|
1103
1154
|
const resolveCallbackId = state.nextCallbackId++;
|
|
1104
1155
|
state.callbacks.set(resolveCallbackId, async (...args2) => {
|
|
1105
1156
|
const promiseId = args2[0];
|
|
@@ -1117,7 +1168,7 @@ function registerCustomFunctions(state, customFunctions) {
|
|
|
1117
1168
|
__resolveCallbackId: resolveCallbackId
|
|
1118
1169
|
};
|
|
1119
1170
|
}
|
|
1120
|
-
if (isAsyncIteratorRef(value)) {
|
|
1171
|
+
if (import_isolate_protocol.isAsyncIteratorRef(value)) {
|
|
1121
1172
|
const nextCallbackId = state.nextCallbackId++;
|
|
1122
1173
|
state.callbacks.set(nextCallbackId, async (...args2) => {
|
|
1123
1174
|
const iteratorId = args2[0];
|
|
@@ -1200,36 +1251,6 @@ function registerCustomFunctions(state, customFunctions) {
|
|
|
1200
1251
|
}
|
|
1201
1252
|
return registrations;
|
|
1202
1253
|
}
|
|
1203
|
-
async function serializeResponse(response) {
|
|
1204
|
-
const headers = [];
|
|
1205
|
-
response.headers.forEach((value, key) => {
|
|
1206
|
-
headers.push([key, value]);
|
|
1207
|
-
});
|
|
1208
|
-
let body = null;
|
|
1209
|
-
if (response.body) {
|
|
1210
|
-
body = new Uint8Array(await response.arrayBuffer());
|
|
1211
|
-
}
|
|
1212
|
-
return {
|
|
1213
|
-
status: response.status,
|
|
1214
|
-
statusText: response.statusText,
|
|
1215
|
-
headers,
|
|
1216
|
-
body
|
|
1217
|
-
};
|
|
1218
|
-
}
|
|
1219
|
-
function deserializeRequest(data) {
|
|
1220
|
-
return new Request(data.url, {
|
|
1221
|
-
method: data.method,
|
|
1222
|
-
headers: data.headers,
|
|
1223
|
-
body: data.body
|
|
1224
|
-
});
|
|
1225
|
-
}
|
|
1226
|
-
function deserializeResponse(data) {
|
|
1227
|
-
return new Response(data.body, {
|
|
1228
|
-
status: data.status,
|
|
1229
|
-
statusText: data.statusText,
|
|
1230
|
-
headers: data.headers
|
|
1231
|
-
});
|
|
1232
|
-
}
|
|
1233
1254
|
async function serializeRequestWithStreaming(state, request) {
|
|
1234
1255
|
const headers = [];
|
|
1235
1256
|
request.headers.forEach((value, key) => {
|
|
@@ -1328,5 +1349,196 @@ async function sendBodyStream(state, streamId, body) {
|
|
|
1328
1349
|
state.uploadStreams.delete(streamId);
|
|
1329
1350
|
}
|
|
1330
1351
|
}
|
|
1352
|
+
function handleIsolateEvent(message, state) {
|
|
1353
|
+
switch (message.event) {
|
|
1354
|
+
case import_isolate_protocol.IsolateEvents.WS_COMMAND: {
|
|
1355
|
+
const payload = message.payload;
|
|
1356
|
+
const callbacks = isolateWsCallbacks.get(message.isolateId);
|
|
1357
|
+
if (callbacks) {
|
|
1358
|
+
let data;
|
|
1359
|
+
if (payload.data instanceof Uint8Array) {
|
|
1360
|
+
data = payload.data.buffer.slice(payload.data.byteOffset, payload.data.byteOffset + payload.data.byteLength);
|
|
1361
|
+
} else {
|
|
1362
|
+
data = payload.data;
|
|
1363
|
+
}
|
|
1364
|
+
const cmd = {
|
|
1365
|
+
type: payload.type,
|
|
1366
|
+
connectionId: payload.connectionId,
|
|
1367
|
+
data,
|
|
1368
|
+
code: payload.code,
|
|
1369
|
+
reason: payload.reason
|
|
1370
|
+
};
|
|
1371
|
+
for (const cb of callbacks) {
|
|
1372
|
+
cb(cmd);
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
break;
|
|
1376
|
+
}
|
|
1377
|
+
case import_isolate_protocol.IsolateEvents.WS_CLIENT_CONNECT: {
|
|
1378
|
+
const payload = message.payload;
|
|
1379
|
+
handleClientWsConnect(message.isolateId, payload, state);
|
|
1380
|
+
break;
|
|
1381
|
+
}
|
|
1382
|
+
case import_isolate_protocol.IsolateEvents.WS_CLIENT_SEND: {
|
|
1383
|
+
const payload = message.payload;
|
|
1384
|
+
handleClientWsSend(message.isolateId, payload, state);
|
|
1385
|
+
break;
|
|
1386
|
+
}
|
|
1387
|
+
case import_isolate_protocol.IsolateEvents.WS_CLIENT_CLOSE: {
|
|
1388
|
+
const payload = message.payload;
|
|
1389
|
+
handleClientWsClose(message.isolateId, payload, state);
|
|
1390
|
+
break;
|
|
1391
|
+
}
|
|
1392
|
+
default: {
|
|
1393
|
+
const listeners = isolateEventListeners.get(message.isolateId);
|
|
1394
|
+
if (listeners) {
|
|
1395
|
+
const eventListeners = listeners.get(message.event);
|
|
1396
|
+
if (eventListeners) {
|
|
1397
|
+
for (const cb of eventListeners) {
|
|
1398
|
+
cb(message.payload);
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
break;
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
function handleClientWsConnect(isolateId, payload, state) {
|
|
1407
|
+
const { socketId, url, protocols } = payload;
|
|
1408
|
+
let sockets = isolateClientWebSockets.get(isolateId);
|
|
1409
|
+
if (!sockets) {
|
|
1410
|
+
sockets = new Map;
|
|
1411
|
+
isolateClientWebSockets.set(isolateId, sockets);
|
|
1412
|
+
}
|
|
1413
|
+
const setupWebSocket = (ws) => {
|
|
1414
|
+
sockets.set(socketId, ws);
|
|
1415
|
+
ws.onopen = () => {
|
|
1416
|
+
sendMessage(state.socket, {
|
|
1417
|
+
type: import_isolate_protocol.MessageType.CLIENT_EVENT,
|
|
1418
|
+
isolateId,
|
|
1419
|
+
event: import_isolate_protocol.ClientEvents.WS_CLIENT_OPENED,
|
|
1420
|
+
payload: { socketId, protocol: ws.protocol || "", extensions: ws.extensions || "" }
|
|
1421
|
+
});
|
|
1422
|
+
};
|
|
1423
|
+
ws.onmessage = (event) => {
|
|
1424
|
+
let data;
|
|
1425
|
+
if (typeof event.data === "string") {
|
|
1426
|
+
data = event.data;
|
|
1427
|
+
} else if (event.data instanceof ArrayBuffer) {
|
|
1428
|
+
data = new Uint8Array(event.data);
|
|
1429
|
+
} else if (event.data instanceof Blob) {
|
|
1430
|
+
event.data.arrayBuffer().then((buffer) => {
|
|
1431
|
+
sendMessage(state.socket, {
|
|
1432
|
+
type: import_isolate_protocol.MessageType.CLIENT_EVENT,
|
|
1433
|
+
isolateId,
|
|
1434
|
+
event: import_isolate_protocol.ClientEvents.WS_CLIENT_MESSAGE,
|
|
1435
|
+
payload: { socketId, data: new Uint8Array(buffer) }
|
|
1436
|
+
});
|
|
1437
|
+
});
|
|
1438
|
+
return;
|
|
1439
|
+
} else {
|
|
1440
|
+
data = String(event.data);
|
|
1441
|
+
}
|
|
1442
|
+
sendMessage(state.socket, {
|
|
1443
|
+
type: import_isolate_protocol.MessageType.CLIENT_EVENT,
|
|
1444
|
+
isolateId,
|
|
1445
|
+
event: import_isolate_protocol.ClientEvents.WS_CLIENT_MESSAGE,
|
|
1446
|
+
payload: { socketId, data }
|
|
1447
|
+
});
|
|
1448
|
+
};
|
|
1449
|
+
ws.onerror = () => {
|
|
1450
|
+
sendMessage(state.socket, {
|
|
1451
|
+
type: import_isolate_protocol.MessageType.CLIENT_EVENT,
|
|
1452
|
+
isolateId,
|
|
1453
|
+
event: import_isolate_protocol.ClientEvents.WS_CLIENT_ERROR,
|
|
1454
|
+
payload: { socketId }
|
|
1455
|
+
});
|
|
1456
|
+
};
|
|
1457
|
+
ws.onclose = (event) => {
|
|
1458
|
+
sendMessage(state.socket, {
|
|
1459
|
+
type: import_isolate_protocol.MessageType.CLIENT_EVENT,
|
|
1460
|
+
isolateId,
|
|
1461
|
+
event: import_isolate_protocol.ClientEvents.WS_CLIENT_CLOSED,
|
|
1462
|
+
payload: { socketId, code: event.code, reason: event.reason, wasClean: event.wasClean }
|
|
1463
|
+
});
|
|
1464
|
+
sockets?.delete(socketId);
|
|
1465
|
+
if (sockets?.size === 0) {
|
|
1466
|
+
isolateClientWebSockets.delete(isolateId);
|
|
1467
|
+
}
|
|
1468
|
+
};
|
|
1469
|
+
};
|
|
1470
|
+
const sendConnectionFailed = (reason) => {
|
|
1471
|
+
sendMessage(state.socket, {
|
|
1472
|
+
type: import_isolate_protocol.MessageType.CLIENT_EVENT,
|
|
1473
|
+
isolateId,
|
|
1474
|
+
event: import_isolate_protocol.ClientEvents.WS_CLIENT_ERROR,
|
|
1475
|
+
payload: { socketId }
|
|
1476
|
+
});
|
|
1477
|
+
sendMessage(state.socket, {
|
|
1478
|
+
type: import_isolate_protocol.MessageType.CLIENT_EVENT,
|
|
1479
|
+
isolateId,
|
|
1480
|
+
event: import_isolate_protocol.ClientEvents.WS_CLIENT_CLOSED,
|
|
1481
|
+
payload: { socketId, code: 1006, reason, wasClean: false }
|
|
1482
|
+
});
|
|
1483
|
+
};
|
|
1484
|
+
const callback = isolateWebSocketCallbacks.get(isolateId);
|
|
1485
|
+
if (callback) {
|
|
1486
|
+
try {
|
|
1487
|
+
const result = callback(url, protocols || []);
|
|
1488
|
+
if (result instanceof Promise) {
|
|
1489
|
+
result.then((ws) => {
|
|
1490
|
+
if (ws === null) {
|
|
1491
|
+
sendConnectionFailed("Connection blocked");
|
|
1492
|
+
} else {
|
|
1493
|
+
setupWebSocket(ws);
|
|
1494
|
+
}
|
|
1495
|
+
}).catch(() => {
|
|
1496
|
+
sendConnectionFailed("Callback error");
|
|
1497
|
+
});
|
|
1498
|
+
} else if (result === null) {
|
|
1499
|
+
sendConnectionFailed("Connection blocked");
|
|
1500
|
+
} else {
|
|
1501
|
+
setupWebSocket(result);
|
|
1502
|
+
}
|
|
1503
|
+
} catch {
|
|
1504
|
+
sendConnectionFailed("Callback error");
|
|
1505
|
+
}
|
|
1506
|
+
} else {
|
|
1507
|
+
try {
|
|
1508
|
+
const ws = protocols && protocols.length > 0 ? new WebSocket(url, protocols) : new WebSocket(url);
|
|
1509
|
+
setupWebSocket(ws);
|
|
1510
|
+
} catch {
|
|
1511
|
+
sendConnectionFailed("Connection failed");
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
function handleClientWsSend(isolateId, payload, state) {
|
|
1516
|
+
const { socketId, data } = payload;
|
|
1517
|
+
const sockets = isolateClientWebSockets.get(isolateId);
|
|
1518
|
+
const ws = sockets?.get(socketId);
|
|
1519
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
1520
|
+
return;
|
|
1521
|
+
}
|
|
1522
|
+
if (typeof data === "string" && data.startsWith("__BINARY__")) {
|
|
1523
|
+
const base64 = data.slice(10);
|
|
1524
|
+
const binary = Buffer.from(base64, "base64");
|
|
1525
|
+
ws.send(binary);
|
|
1526
|
+
} else if (data instanceof Uint8Array) {
|
|
1527
|
+
ws.send(data);
|
|
1528
|
+
} else {
|
|
1529
|
+
ws.send(data);
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
function handleClientWsClose(isolateId, payload, state) {
|
|
1533
|
+
const { socketId, code, reason } = payload;
|
|
1534
|
+
const sockets = isolateClientWebSockets.get(isolateId);
|
|
1535
|
+
const ws = sockets?.get(socketId);
|
|
1536
|
+
if (!ws) {
|
|
1537
|
+
return;
|
|
1538
|
+
}
|
|
1539
|
+
if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) {
|
|
1540
|
+
ws.close(code ?? 1000, reason ?? "");
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1331
1543
|
|
|
1332
|
-
//# debugId=
|
|
1544
|
+
//# debugId=1DAE4D8C13C4D6B364756E2164756E21
|