@ricsam/isolate-client 0.1.15 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,11 +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
- var TEST_REQUEST_TIMEOUT_BUFFER_MS = 1000;
54
53
  var isolateWsCallbacks = new Map;
55
54
  var isolateClientWebSockets = new Map;
56
55
  var isolateWebSocketCallbacks = new Map;
56
+ var isolateEventListeners = new Map;
57
57
  async function connect(options = {}) {
58
58
  const socket = await createSocket(options);
59
59
  const state = {
@@ -68,47 +68,142 @@ async function connect(options = {}) {
68
68
  streamResponses: new Map,
69
69
  uploadStreams: new Map,
70
70
  moduleSourceCache: new Map,
71
- callbackStreamReaders: new Map
71
+ callbackStreamReaders: new Map,
72
+ closing: false,
73
+ namespacedRuntimes: new Map
72
74
  };
73
- const parser = import_isolate_protocol.createFrameParser();
74
- socket.on("data", (data) => {
75
- try {
76
- for (const frame of parser.feed(new Uint8Array(data))) {
77
- handleMessage(frame.message, state);
75
+ function setupSocket(sock) {
76
+ const parser = import_isolate_protocol.createFrameParser();
77
+ sock.on("data", (data) => {
78
+ try {
79
+ for (const frame of parser.feed(new Uint8Array(data))) {
80
+ handleMessage(frame.message, state);
81
+ }
82
+ } catch (err) {
83
+ console.error("Error parsing frame:", err);
78
84
  }
79
- } catch (err) {
80
- console.error("Error parsing frame:", err);
81
- }
82
- });
83
- socket.on("close", () => {
84
- state.connected = false;
85
- for (const [, pending] of state.pendingRequests) {
86
- if (pending.timeoutId) {
87
- clearTimeout(pending.timeoutId);
85
+ });
86
+ sock.on("close", () => {
87
+ state.connected = false;
88
+ for (const [, pending] of state.pendingRequests) {
89
+ pending.reject(new Error("Connection closed"));
88
90
  }
89
- pending.reject(new Error("Connection closed"));
90
- }
91
- state.pendingRequests.clear();
92
- for (const [, receiver] of state.streamResponses) {
93
- receiver.state = "errored";
94
- receiver.error = new Error("Connection closed");
95
- const resolvers = receiver.pullResolvers.splice(0);
96
- for (const resolver of resolvers) {
97
- resolver();
91
+ state.pendingRequests.clear();
92
+ for (const [, receiver] of state.streamResponses) {
93
+ receiver.state = "errored";
94
+ receiver.error = new Error("Connection closed");
95
+ const resolvers = receiver.pullResolvers.splice(0);
96
+ for (const resolver of resolvers) {
97
+ resolver();
98
+ }
98
99
  }
99
- }
100
- state.streamResponses.clear();
101
- for (const [, session] of state.uploadStreams) {
102
- session.state = "closed";
103
- if (session.creditResolver) {
104
- session.creditResolver();
100
+ state.streamResponses.clear();
101
+ for (const [, session] of state.uploadStreams) {
102
+ session.state = "closed";
103
+ if (session.creditResolver) {
104
+ session.creditResolver();
105
+ }
106
+ }
107
+ state.uploadStreams.clear();
108
+ if (!state.closing && state.namespacedRuntimes.size > 0) {
109
+ state.reconnecting = reconnect(state, options).catch(() => {
110
+ state.namespacedRuntimes.clear();
111
+ state.reconnecting = undefined;
112
+ });
105
113
  }
114
+ });
115
+ sock.on("error", (err) => {
116
+ if (!state.closing && state.namespacedRuntimes.size > 0)
117
+ return;
118
+ console.error("Socket error:", err);
119
+ });
120
+ }
121
+ setupSocket(socket);
122
+ async function reconnect(st, opts) {
123
+ try {
124
+ const newSocket = await createSocket(opts);
125
+ st.socket = newSocket;
126
+ st.connected = true;
127
+ setupSocket(newSocket);
128
+ for (const [namespaceId, descriptor] of st.namespacedRuntimes) {
129
+ const runtimeOptions = descriptor.runtimeOptions;
130
+ const callbacks = {};
131
+ if (runtimeOptions.console) {
132
+ callbacks.console = registerConsoleCallbacks(st, runtimeOptions.console);
133
+ }
134
+ if (runtimeOptions.fetch) {
135
+ callbacks.fetch = registerFetchCallback(st, runtimeOptions.fetch);
136
+ }
137
+ if (runtimeOptions.fs) {
138
+ callbacks.fs = registerFsCallbacks(st, runtimeOptions.fs);
139
+ }
140
+ if (runtimeOptions.moduleLoader) {
141
+ callbacks.moduleLoader = registerModuleLoaderCallback(st, runtimeOptions.moduleLoader);
142
+ }
143
+ if (runtimeOptions.customFunctions) {
144
+ callbacks.custom = registerCustomFunctions(st, runtimeOptions.customFunctions);
145
+ }
146
+ if (runtimeOptions.playwright) {
147
+ const playwrightHandler = runtimeOptions.playwright.handler;
148
+ if (playwrightHandler) {
149
+ const handlerCallbackId = st.nextCallbackId++;
150
+ st.callbacks.set(handlerCallbackId, async (opJson) => {
151
+ const op = JSON.parse(opJson);
152
+ const result2 = await playwrightHandler(op);
153
+ return JSON.stringify(result2);
154
+ });
155
+ callbacks.playwright = {
156
+ handlerCallbackId,
157
+ console: runtimeOptions.playwright.console && !runtimeOptions.console?.onEntry
158
+ };
159
+ }
160
+ }
161
+ let testEnvironmentOption;
162
+ if (runtimeOptions.testEnvironment) {
163
+ if (typeof runtimeOptions.testEnvironment === "object") {
164
+ const testEnvOptions = runtimeOptions.testEnvironment;
165
+ const testEnvCallbacks = {};
166
+ if (testEnvOptions.onEvent) {
167
+ const userOnEvent = testEnvOptions.onEvent;
168
+ const onEventCallbackId = registerEventCallback(st, (eventJson) => {
169
+ const event = JSON.parse(eventJson);
170
+ userOnEvent(event);
171
+ });
172
+ testEnvCallbacks.onEvent = {
173
+ callbackId: onEventCallbackId,
174
+ name: "testEnvironment.onEvent",
175
+ type: "sync"
176
+ };
177
+ }
178
+ testEnvironmentOption = {
179
+ callbacks: testEnvCallbacks,
180
+ testTimeout: testEnvOptions.testTimeout
181
+ };
182
+ } else {
183
+ testEnvironmentOption = true;
184
+ }
185
+ }
186
+ const requestId = st.nextRequestId++;
187
+ const request = {
188
+ type: import_isolate_protocol.MessageType.CREATE_RUNTIME,
189
+ requestId,
190
+ options: {
191
+ memoryLimitMB: runtimeOptions.memoryLimitMB,
192
+ cwd: runtimeOptions.cwd,
193
+ callbacks,
194
+ testEnvironment: testEnvironmentOption,
195
+ namespaceId
196
+ }
197
+ };
198
+ const result = await sendRequest(st, request);
199
+ descriptor.isolateId = result.isolateId;
200
+ }
201
+ st.reconnecting = undefined;
202
+ } catch {
203
+ st.reconnecting = undefined;
204
+ throw new Error("Failed to reconnect to daemon");
106
205
  }
107
- state.uploadStreams.clear();
108
- });
109
- socket.on("error", (err) => {
110
- console.error("Socket error:", err);
111
- });
206
+ }
112
207
  return {
113
208
  createRuntime: (runtimeOptions) => createRuntime(state, runtimeOptions),
114
209
  createNamespace: (id) => ({
@@ -116,15 +211,16 @@ async function connect(options = {}) {
116
211
  createRuntime: (runtimeOptions) => createRuntime(state, runtimeOptions, id)
117
212
  }),
118
213
  close: async () => {
214
+ state.closing = true;
119
215
  state.connected = false;
120
- socket.destroy();
216
+ state.socket.destroy();
121
217
  },
122
218
  isConnected: () => state.connected
123
219
  };
124
220
  }
125
221
  function createSocket(options) {
126
222
  return new Promise((resolve, reject) => {
127
- const timeout = options.timeout ?? DEFAULT_TIMEOUT;
223
+ const timeout = options.timeout;
128
224
  let socket;
129
225
  const onError = (err) => {
130
226
  reject(err);
@@ -139,13 +235,15 @@ function createSocket(options) {
139
235
  socket = import_node_net.connect(options.port ?? 47891, options.host ?? "127.0.0.1", onConnect);
140
236
  }
141
237
  socket.on("error", onError);
142
- const timeoutId = setTimeout(() => {
143
- socket.destroy();
144
- reject(new Error("Connection timeout"));
145
- }, timeout);
146
- socket.once("connect", () => {
147
- clearTimeout(timeoutId);
148
- });
238
+ if (timeout && timeout > 0) {
239
+ const timeoutId = setTimeout(() => {
240
+ socket.destroy();
241
+ reject(new Error("Connection timeout"));
242
+ }, timeout);
243
+ socket.once("connect", () => {
244
+ clearTimeout(timeoutId);
245
+ });
246
+ }
149
247
  });
150
248
  }
151
249
  function handleMessage(message, state) {
@@ -155,8 +253,6 @@ function handleMessage(message, state) {
155
253
  const pending = state.pendingRequests.get(response.requestId);
156
254
  if (pending) {
157
255
  state.pendingRequests.delete(response.requestId);
158
- if (pending.timeoutId)
159
- clearTimeout(pending.timeoutId);
160
256
  pending.resolve(response.data);
161
257
  }
162
258
  break;
@@ -166,8 +262,6 @@ function handleMessage(message, state) {
166
262
  const pending = state.pendingRequests.get(response.requestId);
167
263
  if (pending) {
168
264
  state.pendingRequests.delete(response.requestId);
169
- if (pending.timeoutId)
170
- clearTimeout(pending.timeoutId);
171
265
  const error = new Error(response.message);
172
266
  if (response.details) {
173
267
  error.name = response.details.name;
@@ -194,42 +288,9 @@ function handleMessage(message, state) {
194
288
  }
195
289
  break;
196
290
  }
197
- case import_isolate_protocol.MessageType.WS_COMMAND: {
198
- const msg = message;
199
- const callbacks = isolateWsCallbacks.get(msg.isolateId);
200
- if (callbacks) {
201
- let data;
202
- if (msg.command.data instanceof Uint8Array) {
203
- data = msg.command.data.buffer.slice(msg.command.data.byteOffset, msg.command.data.byteOffset + msg.command.data.byteLength);
204
- } else {
205
- data = msg.command.data;
206
- }
207
- const cmd = {
208
- type: msg.command.type,
209
- connectionId: msg.command.connectionId,
210
- data,
211
- code: msg.command.code,
212
- reason: msg.command.reason
213
- };
214
- for (const cb of callbacks) {
215
- cb(cmd);
216
- }
217
- }
218
- break;
219
- }
220
- case import_isolate_protocol.MessageType.CLIENT_WS_CONNECT: {
221
- const msg = message;
222
- handleClientWsConnect(msg, state);
223
- break;
224
- }
225
- case import_isolate_protocol.MessageType.CLIENT_WS_SEND: {
291
+ case import_isolate_protocol.MessageType.ISOLATE_EVENT: {
226
292
  const msg = message;
227
- handleClientWsSend(msg, state);
228
- break;
229
- }
230
- case import_isolate_protocol.MessageType.CLIENT_WS_CLOSE: {
231
- const msg = message;
232
- handleClientWsClose(msg, state);
293
+ handleIsolateEvent(msg, state);
233
294
  break;
234
295
  }
235
296
  case import_isolate_protocol.MessageType.RESPONSE_STREAM_START: {
@@ -299,8 +360,6 @@ function handleMessage(message, state) {
299
360
  const pending = state.pendingRequests.get(msg.requestId);
300
361
  if (pending) {
301
362
  state.pendingRequests.delete(msg.requestId);
302
- if (pending.timeoutId)
303
- clearTimeout(pending.timeoutId);
304
363
  const response = new Response(readableStream, {
305
364
  status: msg.metadata?.status ?? 200,
306
365
  statusText: msg.metadata?.statusText ?? "OK",
@@ -425,25 +484,24 @@ function sendMessage(socket, message) {
425
484
  const frame = import_isolate_protocol.buildFrame(message);
426
485
  socket.write(frame);
427
486
  }
428
- function sendRequest(state, message, timeout = DEFAULT_TIMEOUT) {
487
+ function sendRequest(state, message) {
429
488
  return new Promise((resolve, reject) => {
430
489
  if (!state.connected) {
431
490
  reject(new Error("Not connected"));
432
491
  return;
433
492
  }
434
493
  const requestId = message.requestId;
435
- const timeoutId = setTimeout(() => {
436
- state.pendingRequests.delete(requestId);
437
- reject(new Error("Request timeout"));
438
- }, timeout);
439
494
  state.pendingRequests.set(requestId, {
440
495
  resolve,
441
- reject,
442
- timeoutId
496
+ reject
443
497
  });
444
498
  sendMessage(state.socket, message);
445
499
  });
446
500
  }
501
+ function isBenignDisposeError(error) {
502
+ const message = error instanceof Error ? error.message : String(error ?? "");
503
+ return /isolate not owned by this connection|isolate not found|not connected|connection closed/i.test(message);
504
+ }
447
505
  async function createRuntime(state, options = {}, namespaceId) {
448
506
  const callbacks = {};
449
507
  if (options.console) {
@@ -582,13 +640,26 @@ async function createRuntime(state, options = {}, namespaceId) {
582
640
  const result = await sendRequest(state, request);
583
641
  const isolateId = result.isolateId;
584
642
  const reused = result.reused ?? false;
643
+ if (namespaceId != null) {
644
+ state.namespacedRuntimes.set(namespaceId, {
645
+ isolateId,
646
+ runtimeOptions: options
647
+ });
648
+ }
585
649
  const wsCommandCallbacks = new Set;
586
650
  isolateWsCallbacks.set(isolateId, wsCommandCallbacks);
651
+ if (options.onWebSocketCommand) {
652
+ wsCommandCallbacks.add(options.onWebSocketCommand);
653
+ }
587
654
  if (options.webSocket) {
588
655
  isolateWebSocketCallbacks.set(isolateId, options.webSocket);
589
656
  }
590
657
  const fetchHandle = {
591
658
  async dispatchRequest(req, opts) {
659
+ const signal = opts?.signal;
660
+ if (signal?.aborted) {
661
+ throw new DOMException("The operation was aborted", "AbortError");
662
+ }
592
663
  const reqId = state.nextRequestId++;
593
664
  const serialized = await serializeRequestWithStreaming(state, req);
594
665
  const { bodyStream, ...serializableRequest } = serialized;
@@ -596,24 +667,40 @@ async function createRuntime(state, options = {}, namespaceId) {
596
667
  type: import_isolate_protocol.MessageType.DISPATCH_REQUEST,
597
668
  requestId: reqId,
598
669
  isolateId,
599
- request: serializableRequest,
600
- options: opts
670
+ request: serializableRequest
601
671
  };
602
672
  const handleResponse = (res) => {
603
673
  if (res.__streaming && res.response instanceof Response) {
604
674
  return res.response;
605
675
  }
606
- return deserializeResponse(res.response);
676
+ return import_isolate_protocol.deserializeResponse(res.response);
607
677
  };
608
- if (serialized.bodyStreamId !== undefined && bodyStream) {
609
- const streamId = serialized.bodyStreamId;
610
- const responsePromise = sendRequest(state, request2, opts?.timeout ?? DEFAULT_TIMEOUT);
611
- await sendBodyStream(state, streamId, bodyStream);
612
- const res = await responsePromise;
613
- return handleResponse(res);
614
- } else {
615
- const res = await sendRequest(state, request2, opts?.timeout ?? DEFAULT_TIMEOUT);
616
- return handleResponse(res);
678
+ let onAbort;
679
+ if (signal) {
680
+ onAbort = () => {
681
+ const pending = state.pendingRequests.get(reqId);
682
+ if (pending) {
683
+ state.pendingRequests.delete(reqId);
684
+ pending.reject(new DOMException("The operation was aborted", "AbortError"));
685
+ }
686
+ };
687
+ signal.addEventListener("abort", onAbort, { once: true });
688
+ }
689
+ try {
690
+ if (serialized.bodyStreamId !== undefined && bodyStream) {
691
+ const streamId = serialized.bodyStreamId;
692
+ const responsePromise = sendRequest(state, request2);
693
+ await sendBodyStream(state, streamId, bodyStream);
694
+ const res = await responsePromise;
695
+ return handleResponse(res);
696
+ } else {
697
+ const res = await sendRequest(state, request2);
698
+ return handleResponse(res);
699
+ }
700
+ } finally {
701
+ if (signal && onAbort) {
702
+ signal.removeEventListener("abort", onAbort);
703
+ }
617
704
  }
618
705
  },
619
706
  async getUpgradeRequest() {
@@ -760,8 +847,22 @@ async function createRuntime(state, options = {}, namespaceId) {
760
847
  isolateId,
761
848
  timeout
762
849
  };
763
- const requestTimeout = timeout === undefined ? DEFAULT_TIMEOUT : Math.max(timeout + TEST_REQUEST_TIMEOUT_BUFFER_MS, DEFAULT_TIMEOUT);
764
- return sendRequest(state, req, requestTimeout);
850
+ try {
851
+ return await sendRequest(state, req);
852
+ } catch (err) {
853
+ if (err instanceof Error && /connection closed|not connected/i.test(err.message) && state.reconnecting) {
854
+ await state.reconnecting;
855
+ const retryReqId = state.nextRequestId++;
856
+ const retryReq = {
857
+ type: import_isolate_protocol.MessageType.RUN_TESTS,
858
+ requestId: retryReqId,
859
+ isolateId,
860
+ timeout
861
+ };
862
+ return sendRequest(state, retryReq);
863
+ }
864
+ throw err;
865
+ }
765
866
  },
766
867
  async hasTests() {
767
868
  if (!testEnvironmentEnabled) {
@@ -836,17 +937,47 @@ async function createRuntime(state, options = {}, namespaceId) {
836
937
  requestId: reqId,
837
938
  isolateId,
838
939
  code,
839
- filename: options2?.filename,
840
- maxExecutionMs: options2?.maxExecutionMs
940
+ filename: options2?.filename
841
941
  };
842
942
  await sendRequest(state, req);
843
943
  },
944
+ on(event, callback) {
945
+ let listeners = isolateEventListeners.get(isolateId);
946
+ if (!listeners) {
947
+ listeners = new Map;
948
+ isolateEventListeners.set(isolateId, listeners);
949
+ }
950
+ let eventListeners = listeners.get(event);
951
+ if (!eventListeners) {
952
+ eventListeners = new Set;
953
+ listeners.set(event, eventListeners);
954
+ }
955
+ eventListeners.add(callback);
956
+ return () => {
957
+ eventListeners.delete(callback);
958
+ if (eventListeners.size === 0) {
959
+ listeners.delete(event);
960
+ if (listeners.size === 0) {
961
+ isolateEventListeners.delete(isolateId);
962
+ }
963
+ }
964
+ };
965
+ },
966
+ emit(event, payload) {
967
+ sendMessage(state.socket, {
968
+ type: import_isolate_protocol.MessageType.CLIENT_EVENT,
969
+ isolateId,
970
+ event,
971
+ payload
972
+ });
973
+ },
844
974
  dispose: async () => {
845
975
  for (const cleanup of pageListenerCleanups) {
846
976
  cleanup();
847
977
  }
848
978
  isolateWsCallbacks.delete(isolateId);
849
979
  isolateWebSocketCallbacks.delete(isolateId);
980
+ isolateEventListeners.delete(isolateId);
850
981
  const clientSockets = isolateClientWebSockets.get(isolateId);
851
982
  if (clientSockets) {
852
983
  for (const ws of clientSockets.values()) {
@@ -856,13 +987,22 @@ async function createRuntime(state, options = {}, namespaceId) {
856
987
  }
857
988
  isolateClientWebSockets.delete(isolateId);
858
989
  }
990
+ if (namespaceId != null) {
991
+ state.namespacedRuntimes.delete(namespaceId);
992
+ }
859
993
  const reqId = state.nextRequestId++;
860
994
  const req = {
861
995
  type: import_isolate_protocol.MessageType.DISPOSE_RUNTIME,
862
996
  requestId: reqId,
863
997
  isolateId
864
998
  };
865
- await sendRequest(state, req);
999
+ try {
1000
+ await sendRequest(state, req);
1001
+ } catch (error) {
1002
+ if (!isBenignDisposeError(error)) {
1003
+ throw error;
1004
+ }
1005
+ }
866
1006
  }
867
1007
  };
868
1008
  }
@@ -894,8 +1034,8 @@ function registerFetchCallback(state, callback) {
894
1034
  const init = {
895
1035
  method: data.method,
896
1036
  headers: data.headers,
897
- rawBody: data.body,
898
- body: data.body,
1037
+ rawBody: data.body ?? null,
1038
+ body: data.body ?? null,
899
1039
  signal: new AbortController().signal
900
1040
  };
901
1041
  const response = await callback(data.url, init);
@@ -923,7 +1063,7 @@ function registerFetchCallback(state, callback) {
923
1063
  streamCallbackResponseBody(state, streamId, requestId, response.body);
924
1064
  return { __callbackStreaming: true, streamId };
925
1065
  }
926
- return serializeResponse(response);
1066
+ return import_isolate_protocol.serializeResponse(response);
927
1067
  });
928
1068
  return { callbackId, name: "fetch", type: "async" };
929
1069
  }
@@ -1041,7 +1181,7 @@ function registerModuleLoaderCallback(state, callback) {
1041
1181
  const specifier = moduleName;
1042
1182
  const importerInfo = importer;
1043
1183
  const result = await callback(specifier, importerInfo);
1044
- const resolvedPath = import_node_path.default.posix.join(result.resolveDir, import_node_path.default.posix.basename(specifier));
1184
+ const resolvedPath = import_node_path.default.posix.join(result.resolveDir, result.filename);
1045
1185
  state.moduleSourceCache.set(resolvedPath, result.code);
1046
1186
  return result;
1047
1187
  });
@@ -1051,12 +1191,6 @@ var clientIteratorSessions = new Map;
1051
1191
  var nextClientIteratorId = 1;
1052
1192
  var returnedPromiseRegistry = new Map;
1053
1193
  var returnedIteratorRegistry = new Map;
1054
- function isPromiseRef(value) {
1055
- return typeof value === "object" && value !== null && value.__type === "PromiseRef";
1056
- }
1057
- function isAsyncIteratorRef(value) {
1058
- return typeof value === "object" && value !== null && value.__type === "AsyncIteratorRef";
1059
- }
1060
1194
  function registerCustomFunctions(state, customFunctions) {
1061
1195
  const registrations = {};
1062
1196
  for (const [name, def] of Object.entries(customFunctions)) {
@@ -1139,7 +1273,7 @@ function registerCustomFunctions(state, customFunctions) {
1139
1273
  if (value === null || typeof value !== "object") {
1140
1274
  return value;
1141
1275
  }
1142
- if (isPromiseRef(value)) {
1276
+ if (import_isolate_protocol.isPromiseRef(value)) {
1143
1277
  const resolveCallbackId = state.nextCallbackId++;
1144
1278
  state.callbacks.set(resolveCallbackId, async (...args2) => {
1145
1279
  const promiseId = args2[0];
@@ -1157,7 +1291,7 @@ function registerCustomFunctions(state, customFunctions) {
1157
1291
  __resolveCallbackId: resolveCallbackId
1158
1292
  };
1159
1293
  }
1160
- if (isAsyncIteratorRef(value)) {
1294
+ if (import_isolate_protocol.isAsyncIteratorRef(value)) {
1161
1295
  const nextCallbackId = state.nextCallbackId++;
1162
1296
  state.callbacks.set(nextCallbackId, async (...args2) => {
1163
1297
  const iteratorId = args2[0];
@@ -1240,29 +1374,6 @@ function registerCustomFunctions(state, customFunctions) {
1240
1374
  }
1241
1375
  return registrations;
1242
1376
  }
1243
- async function serializeResponse(response) {
1244
- const headers = [];
1245
- response.headers.forEach((value, key) => {
1246
- headers.push([key, value]);
1247
- });
1248
- let body = null;
1249
- if (response.body) {
1250
- body = new Uint8Array(await response.arrayBuffer());
1251
- }
1252
- return {
1253
- status: response.status,
1254
- statusText: response.statusText,
1255
- headers,
1256
- body
1257
- };
1258
- }
1259
- function deserializeResponse(data) {
1260
- return new Response(data.body, {
1261
- status: data.status,
1262
- statusText: data.statusText,
1263
- headers: data.headers
1264
- });
1265
- }
1266
1377
  async function serializeRequestWithStreaming(state, request) {
1267
1378
  const headers = [];
1268
1379
  request.headers.forEach((value, key) => {
@@ -1361,8 +1472,62 @@ async function sendBodyStream(state, streamId, body) {
1361
1472
  state.uploadStreams.delete(streamId);
1362
1473
  }
1363
1474
  }
1364
- function handleClientWsConnect(message, state) {
1365
- const { isolateId, socketId, url, protocols } = message;
1475
+ function handleIsolateEvent(message, state) {
1476
+ switch (message.event) {
1477
+ case import_isolate_protocol.IsolateEvents.WS_COMMAND: {
1478
+ const payload = message.payload;
1479
+ const callbacks = isolateWsCallbacks.get(message.isolateId);
1480
+ if (callbacks) {
1481
+ let data;
1482
+ if (payload.data instanceof Uint8Array) {
1483
+ data = payload.data.buffer.slice(payload.data.byteOffset, payload.data.byteOffset + payload.data.byteLength);
1484
+ } else {
1485
+ data = payload.data;
1486
+ }
1487
+ const cmd = {
1488
+ type: payload.type,
1489
+ connectionId: payload.connectionId,
1490
+ data,
1491
+ code: payload.code,
1492
+ reason: payload.reason
1493
+ };
1494
+ for (const cb of callbacks) {
1495
+ cb(cmd);
1496
+ }
1497
+ }
1498
+ break;
1499
+ }
1500
+ case import_isolate_protocol.IsolateEvents.WS_CLIENT_CONNECT: {
1501
+ const payload = message.payload;
1502
+ handleClientWsConnect(message.isolateId, payload, state);
1503
+ break;
1504
+ }
1505
+ case import_isolate_protocol.IsolateEvents.WS_CLIENT_SEND: {
1506
+ const payload = message.payload;
1507
+ handleClientWsSend(message.isolateId, payload, state);
1508
+ break;
1509
+ }
1510
+ case import_isolate_protocol.IsolateEvents.WS_CLIENT_CLOSE: {
1511
+ const payload = message.payload;
1512
+ handleClientWsClose(message.isolateId, payload, state);
1513
+ break;
1514
+ }
1515
+ default: {
1516
+ const listeners = isolateEventListeners.get(message.isolateId);
1517
+ if (listeners) {
1518
+ const eventListeners = listeners.get(message.event);
1519
+ if (eventListeners) {
1520
+ for (const cb of eventListeners) {
1521
+ cb(message.payload);
1522
+ }
1523
+ }
1524
+ }
1525
+ break;
1526
+ }
1527
+ }
1528
+ }
1529
+ function handleClientWsConnect(isolateId, payload, state) {
1530
+ const { socketId, url, protocols } = payload;
1366
1531
  let sockets = isolateClientWebSockets.get(isolateId);
1367
1532
  if (!sockets) {
1368
1533
  sockets = new Map;
@@ -1371,14 +1536,12 @@ function handleClientWsConnect(message, state) {
1371
1536
  const setupWebSocket = (ws) => {
1372
1537
  sockets.set(socketId, ws);
1373
1538
  ws.onopen = () => {
1374
- const msg = {
1375
- type: import_isolate_protocol.MessageType.CLIENT_WS_OPENED,
1539
+ sendMessage(state.socket, {
1540
+ type: import_isolate_protocol.MessageType.CLIENT_EVENT,
1376
1541
  isolateId,
1377
- socketId,
1378
- protocol: ws.protocol || "",
1379
- extensions: ws.extensions || ""
1380
- };
1381
- sendMessage(state.socket, msg);
1542
+ event: import_isolate_protocol.ClientEvents.WS_CLIENT_OPENED,
1543
+ payload: { socketId, protocol: ws.protocol || "", extensions: ws.extensions || "" }
1544
+ });
1382
1545
  };
1383
1546
  ws.onmessage = (event) => {
1384
1547
  let data;
@@ -1388,44 +1551,39 @@ function handleClientWsConnect(message, state) {
1388
1551
  data = new Uint8Array(event.data);
1389
1552
  } else if (event.data instanceof Blob) {
1390
1553
  event.data.arrayBuffer().then((buffer) => {
1391
- const msg2 = {
1392
- type: import_isolate_protocol.MessageType.CLIENT_WS_MESSAGE,
1554
+ sendMessage(state.socket, {
1555
+ type: import_isolate_protocol.MessageType.CLIENT_EVENT,
1393
1556
  isolateId,
1394
- socketId,
1395
- data: new Uint8Array(buffer)
1396
- };
1397
- sendMessage(state.socket, msg2);
1557
+ event: import_isolate_protocol.ClientEvents.WS_CLIENT_MESSAGE,
1558
+ payload: { socketId, data: new Uint8Array(buffer) }
1559
+ });
1398
1560
  });
1399
1561
  return;
1400
1562
  } else {
1401
1563
  data = String(event.data);
1402
1564
  }
1403
- const msg = {
1404
- type: import_isolate_protocol.MessageType.CLIENT_WS_MESSAGE,
1565
+ sendMessage(state.socket, {
1566
+ type: import_isolate_protocol.MessageType.CLIENT_EVENT,
1405
1567
  isolateId,
1406
- socketId,
1407
- data
1408
- };
1409
- sendMessage(state.socket, msg);
1568
+ event: import_isolate_protocol.ClientEvents.WS_CLIENT_MESSAGE,
1569
+ payload: { socketId, data }
1570
+ });
1410
1571
  };
1411
1572
  ws.onerror = () => {
1412
- const msg = {
1413
- type: import_isolate_protocol.MessageType.CLIENT_WS_ERROR,
1573
+ sendMessage(state.socket, {
1574
+ type: import_isolate_protocol.MessageType.CLIENT_EVENT,
1414
1575
  isolateId,
1415
- socketId
1416
- };
1417
- sendMessage(state.socket, msg);
1576
+ event: import_isolate_protocol.ClientEvents.WS_CLIENT_ERROR,
1577
+ payload: { socketId }
1578
+ });
1418
1579
  };
1419
1580
  ws.onclose = (event) => {
1420
- const msg = {
1421
- type: import_isolate_protocol.MessageType.CLIENT_WS_CLOSED,
1581
+ sendMessage(state.socket, {
1582
+ type: import_isolate_protocol.MessageType.CLIENT_EVENT,
1422
1583
  isolateId,
1423
- socketId,
1424
- code: event.code,
1425
- reason: event.reason,
1426
- wasClean: event.wasClean
1427
- };
1428
- sendMessage(state.socket, msg);
1584
+ event: import_isolate_protocol.ClientEvents.WS_CLIENT_CLOSED,
1585
+ payload: { socketId, code: event.code, reason: event.reason, wasClean: event.wasClean }
1586
+ });
1429
1587
  sockets?.delete(socketId);
1430
1588
  if (sockets?.size === 0) {
1431
1589
  isolateClientWebSockets.delete(isolateId);
@@ -1433,21 +1591,18 @@ function handleClientWsConnect(message, state) {
1433
1591
  };
1434
1592
  };
1435
1593
  const sendConnectionFailed = (reason) => {
1436
- const errorMsg = {
1437
- type: import_isolate_protocol.MessageType.CLIENT_WS_ERROR,
1594
+ sendMessage(state.socket, {
1595
+ type: import_isolate_protocol.MessageType.CLIENT_EVENT,
1438
1596
  isolateId,
1439
- socketId
1440
- };
1441
- sendMessage(state.socket, errorMsg);
1442
- const closeMsg = {
1443
- type: import_isolate_protocol.MessageType.CLIENT_WS_CLOSED,
1597
+ event: import_isolate_protocol.ClientEvents.WS_CLIENT_ERROR,
1598
+ payload: { socketId }
1599
+ });
1600
+ sendMessage(state.socket, {
1601
+ type: import_isolate_protocol.MessageType.CLIENT_EVENT,
1444
1602
  isolateId,
1445
- socketId,
1446
- code: 1006,
1447
- reason,
1448
- wasClean: false
1449
- };
1450
- sendMessage(state.socket, closeMsg);
1603
+ event: import_isolate_protocol.ClientEvents.WS_CLIENT_CLOSED,
1604
+ payload: { socketId, code: 1006, reason, wasClean: false }
1605
+ });
1451
1606
  };
1452
1607
  const callback = isolateWebSocketCallbacks.get(isolateId);
1453
1608
  if (callback) {
@@ -1480,8 +1635,8 @@ function handleClientWsConnect(message, state) {
1480
1635
  }
1481
1636
  }
1482
1637
  }
1483
- function handleClientWsSend(message, state) {
1484
- const { isolateId, socketId, data } = message;
1638
+ function handleClientWsSend(isolateId, payload, state) {
1639
+ const { socketId, data } = payload;
1485
1640
  const sockets = isolateClientWebSockets.get(isolateId);
1486
1641
  const ws = sockets?.get(socketId);
1487
1642
  if (!ws || ws.readyState !== WebSocket.OPEN) {
@@ -1492,13 +1647,13 @@ function handleClientWsSend(message, state) {
1492
1647
  const binary = Buffer.from(base64, "base64");
1493
1648
  ws.send(binary);
1494
1649
  } else if (data instanceof Uint8Array) {
1495
- ws.send(data);
1650
+ ws.send(Buffer.from(data));
1496
1651
  } else {
1497
1652
  ws.send(data);
1498
1653
  }
1499
1654
  }
1500
- function handleClientWsClose(message, state) {
1501
- const { isolateId, socketId, code, reason } = message;
1655
+ function handleClientWsClose(isolateId, payload, state) {
1656
+ const { socketId, code, reason } = payload;
1502
1657
  const sockets = isolateClientWebSockets.get(isolateId);
1503
1658
  const ws = sockets?.get(socketId);
1504
1659
  if (!ws) {
@@ -1509,4 +1664,4 @@ function handleClientWsClose(message, state) {
1509
1664
  }
1510
1665
  }
1511
1666
 
1512
- //# debugId=7A85E05BA8CAD49764756E2164756E21
1667
+ //# debugId=BB5A27475A32C8E264756E2164756E21