@ricsam/isolate-client 0.1.1 → 0.1.4

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.
@@ -35,7 +35,9 @@ __export(exports_connection, {
35
35
  module.exports = __toCommonJS(exports_connection);
36
36
  var import_node_net = require("net");
37
37
  var import_isolate_protocol = require("@ricsam/isolate-protocol");
38
+ var import_isolate_playwright = require("@ricsam/isolate-playwright");
38
39
  var DEFAULT_TIMEOUT = 30000;
40
+ var isolateWsCallbacks = new Map;
39
41
  async function connect(options = {}) {
40
42
  const socket = await createSocket(options);
41
43
  const state = {
@@ -44,8 +46,10 @@ async function connect(options = {}) {
44
46
  callbacks: new Map,
45
47
  nextRequestId: 1,
46
48
  nextCallbackId: 1,
49
+ nextStreamId: 1,
47
50
  connected: true,
48
- playwrightEventHandlers: new Map
51
+ streamResponses: new Map,
52
+ uploadStreams: new Map
49
53
  };
50
54
  const parser = import_isolate_protocol.createFrameParser();
51
55
  socket.on("data", (data) => {
@@ -140,21 +144,112 @@ function handleMessage(message, state) {
140
144
  }
141
145
  case import_isolate_protocol.MessageType.PONG:
142
146
  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;
147
+ case import_isolate_protocol.MessageType.WS_COMMAND: {
148
+ const msg = message;
149
+ const callbacks = isolateWsCallbacks.get(msg.isolateId);
150
+ if (callbacks) {
151
+ let data;
152
+ if (msg.command.data instanceof Uint8Array) {
153
+ data = msg.command.data.buffer.slice(msg.command.data.byteOffset, msg.command.data.byteOffset + msg.command.data.byteLength);
154
+ } else {
155
+ data = msg.command.data;
157
156
  }
157
+ const cmd = {
158
+ type: msg.command.type,
159
+ connectionId: msg.command.connectionId,
160
+ data,
161
+ code: msg.command.code,
162
+ reason: msg.command.reason
163
+ };
164
+ for (const cb of callbacks) {
165
+ cb(cmd);
166
+ }
167
+ }
168
+ break;
169
+ }
170
+ case import_isolate_protocol.MessageType.RESPONSE_STREAM_START: {
171
+ const msg = message;
172
+ const receiver = {
173
+ streamId: msg.streamId,
174
+ requestId: msg.requestId,
175
+ metadata: msg.metadata,
176
+ chunks: [],
177
+ totalBytes: 0
178
+ };
179
+ state.streamResponses.set(msg.streamId, receiver);
180
+ sendMessage(state.socket, {
181
+ type: import_isolate_protocol.MessageType.STREAM_PULL,
182
+ streamId: msg.streamId,
183
+ maxBytes: import_isolate_protocol.STREAM_DEFAULT_CREDIT
184
+ });
185
+ break;
186
+ }
187
+ case import_isolate_protocol.MessageType.RESPONSE_STREAM_CHUNK: {
188
+ const msg = message;
189
+ const receiver = state.streamResponses.get(msg.streamId);
190
+ if (receiver) {
191
+ receiver.chunks.push(msg.chunk);
192
+ receiver.totalBytes += msg.chunk.length;
193
+ sendMessage(state.socket, {
194
+ type: import_isolate_protocol.MessageType.STREAM_PULL,
195
+ streamId: msg.streamId,
196
+ maxBytes: import_isolate_protocol.STREAM_DEFAULT_CREDIT
197
+ });
198
+ }
199
+ break;
200
+ }
201
+ case import_isolate_protocol.MessageType.RESPONSE_STREAM_END: {
202
+ const msg = message;
203
+ const receiver = state.streamResponses.get(msg.streamId);
204
+ if (receiver) {
205
+ const body = concatUint8Arrays(receiver.chunks);
206
+ const pending = state.pendingRequests.get(receiver.requestId);
207
+ if (pending) {
208
+ state.pendingRequests.delete(receiver.requestId);
209
+ if (pending.timeoutId)
210
+ clearTimeout(pending.timeoutId);
211
+ pending.resolve({
212
+ response: {
213
+ status: receiver.metadata?.status ?? 200,
214
+ statusText: receiver.metadata?.statusText ?? "OK",
215
+ headers: receiver.metadata?.headers ?? [],
216
+ body
217
+ }
218
+ });
219
+ }
220
+ state.streamResponses.delete(msg.streamId);
221
+ }
222
+ break;
223
+ }
224
+ case import_isolate_protocol.MessageType.STREAM_PULL: {
225
+ const msg = message;
226
+ const session = state.uploadStreams.get(msg.streamId);
227
+ if (session) {
228
+ session.credit += msg.maxBytes;
229
+ if (session.creditResolver) {
230
+ session.creditResolver();
231
+ session.creditResolver = undefined;
232
+ }
233
+ }
234
+ break;
235
+ }
236
+ case import_isolate_protocol.MessageType.STREAM_ERROR: {
237
+ const msg = message;
238
+ const uploadSession = state.uploadStreams.get(msg.streamId);
239
+ if (uploadSession) {
240
+ uploadSession.state = "closed";
241
+ state.uploadStreams.delete(msg.streamId);
242
+ }
243
+ const receiver = state.streamResponses.get(msg.streamId);
244
+ if (receiver) {
245
+ const pending = state.pendingRequests.get(receiver.requestId);
246
+ if (pending) {
247
+ state.pendingRequests.delete(receiver.requestId);
248
+ if (pending.timeoutId)
249
+ clearTimeout(pending.timeoutId);
250
+ pending.reject(new Error(msg.error));
251
+ }
252
+ state.streamResponses.delete(msg.streamId);
158
253
  }
159
254
  break;
160
255
  }
@@ -162,6 +257,16 @@ function handleMessage(message, state) {
162
257
  console.warn(`Unexpected message type: ${message.type}`);
163
258
  }
164
259
  }
260
+ function concatUint8Arrays(arrays) {
261
+ const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
262
+ const result = new Uint8Array(totalLength);
263
+ let offset = 0;
264
+ for (const arr of arrays) {
265
+ result.set(arr, offset);
266
+ offset += arr.length;
267
+ }
268
+ return result;
269
+ }
165
270
  async function handleCallbackInvoke(invoke, state) {
166
271
  const callback = state.callbacks.get(invoke.callbackId);
167
272
  const response = {
@@ -222,64 +327,285 @@ async function createRuntime(state, options = {}) {
222
327
  if (options.fs) {
223
328
  callbacks.fs = registerFsCallbacks(state, options.fs);
224
329
  }
330
+ if (options.moduleLoader) {
331
+ callbacks.moduleLoader = registerModuleLoaderCallback(state, options.moduleLoader);
332
+ }
333
+ if (options.customFunctions) {
334
+ callbacks.custom = registerCustomFunctions(state, options.customFunctions);
335
+ }
336
+ let playwrightHandler;
337
+ if (options.playwright) {
338
+ playwrightHandler = import_isolate_playwright.createPlaywrightHandler(options.playwright.page, {
339
+ timeout: options.playwright.timeout,
340
+ baseUrl: options.playwright.baseUrl
341
+ });
342
+ const handlerCallbackId = state.nextCallbackId++;
343
+ state.callbacks.set(handlerCallbackId, async (opJson) => {
344
+ const op = JSON.parse(opJson);
345
+ const result2 = await playwrightHandler(op);
346
+ return JSON.stringify(result2);
347
+ });
348
+ const hasOnEvent = !!options.playwright.onEvent;
349
+ const hasConsoleHandler = options.playwright.console && options.console?.onEntry;
350
+ let browserConsoleLogCallbackId;
351
+ if (hasOnEvent || hasConsoleHandler) {
352
+ browserConsoleLogCallbackId = registerEventCallback(state, (entry) => {
353
+ const browserEntry = entry;
354
+ if (options.playwright.onEvent) {
355
+ options.playwright.onEvent({
356
+ type: "browserConsoleLog",
357
+ level: browserEntry.level,
358
+ args: browserEntry.args,
359
+ timestamp: browserEntry.timestamp
360
+ });
361
+ }
362
+ if (options.playwright.console && options.console?.onEntry) {
363
+ options.console.onEntry({
364
+ type: "browserOutput",
365
+ level: browserEntry.level,
366
+ args: browserEntry.args,
367
+ timestamp: browserEntry.timestamp
368
+ });
369
+ }
370
+ });
371
+ }
372
+ let networkRequestCallbackId;
373
+ if (hasOnEvent) {
374
+ networkRequestCallbackId = registerEventCallback(state, (info) => {
375
+ const reqInfo = info;
376
+ options.playwright.onEvent({
377
+ type: "networkRequest",
378
+ url: reqInfo.url,
379
+ method: reqInfo.method,
380
+ headers: reqInfo.headers,
381
+ postData: reqInfo.postData,
382
+ resourceType: reqInfo.resourceType,
383
+ timestamp: reqInfo.timestamp
384
+ });
385
+ });
386
+ }
387
+ let networkResponseCallbackId;
388
+ if (hasOnEvent) {
389
+ networkResponseCallbackId = registerEventCallback(state, (info) => {
390
+ const resInfo = info;
391
+ options.playwright.onEvent({
392
+ type: "networkResponse",
393
+ url: resInfo.url,
394
+ status: resInfo.status,
395
+ statusText: resInfo.statusText,
396
+ headers: resInfo.headers,
397
+ timestamp: resInfo.timestamp
398
+ });
399
+ });
400
+ }
401
+ callbacks.playwright = {
402
+ handlerCallbackId,
403
+ console: options.playwright.console && !options.console?.onEntry,
404
+ onBrowserConsoleLogCallbackId: browserConsoleLogCallbackId,
405
+ onNetworkRequestCallbackId: networkRequestCallbackId,
406
+ onNetworkResponseCallbackId: networkResponseCallbackId
407
+ };
408
+ }
409
+ let testEnvironmentOption;
410
+ if (options.testEnvironment) {
411
+ if (typeof options.testEnvironment === "object") {
412
+ const testEnvOptions = options.testEnvironment;
413
+ const testEnvCallbacks = {};
414
+ if (testEnvOptions.onEvent) {
415
+ const userOnEvent = testEnvOptions.onEvent;
416
+ const onEventCallbackId = registerEventCallback(state, (eventJson) => {
417
+ const event = JSON.parse(eventJson);
418
+ userOnEvent(event);
419
+ });
420
+ testEnvCallbacks.onEvent = {
421
+ callbackId: onEventCallbackId,
422
+ name: "testEnvironment.onEvent",
423
+ type: "sync"
424
+ };
425
+ }
426
+ testEnvironmentOption = {
427
+ callbacks: testEnvCallbacks,
428
+ testTimeout: testEnvOptions.testTimeout
429
+ };
430
+ } else {
431
+ testEnvironmentOption = true;
432
+ }
433
+ }
225
434
  const requestId = state.nextRequestId++;
226
435
  const request = {
227
436
  type: import_isolate_protocol.MessageType.CREATE_RUNTIME,
228
437
  requestId,
229
438
  options: {
230
- memoryLimit: options.memoryLimit,
231
- callbacks
439
+ memoryLimitMB: options.memoryLimitMB,
440
+ cwd: options.cwd,
441
+ callbacks,
442
+ testEnvironment: testEnvironmentOption
232
443
  }
233
444
  };
234
445
  const result = await sendRequest(state, request);
235
446
  const isolateId = result.isolateId;
236
- return {
237
- isolateId,
238
- eval: async (code, filename) => {
447
+ const wsCommandCallbacks = new Set;
448
+ isolateWsCallbacks.set(isolateId, wsCommandCallbacks);
449
+ const fetchHandle = {
450
+ async dispatchRequest(req, opts) {
451
+ const reqId = state.nextRequestId++;
452
+ const serialized = await serializeRequestWithStreaming(state, req);
453
+ const { bodyStream, ...serializableRequest } = serialized;
454
+ const request2 = {
455
+ type: import_isolate_protocol.MessageType.DISPATCH_REQUEST,
456
+ requestId: reqId,
457
+ isolateId,
458
+ request: serializableRequest,
459
+ options: opts
460
+ };
461
+ if (serialized.bodyStreamId !== undefined && bodyStream) {
462
+ const streamId = serialized.bodyStreamId;
463
+ const responsePromise = sendRequest(state, request2, opts?.timeout ?? DEFAULT_TIMEOUT);
464
+ await sendBodyStream(state, streamId, bodyStream);
465
+ const res = await responsePromise;
466
+ return deserializeResponse(res.response);
467
+ } else {
468
+ const res = await sendRequest(state, request2, opts?.timeout ?? DEFAULT_TIMEOUT);
469
+ return deserializeResponse(res.response);
470
+ }
471
+ },
472
+ async getUpgradeRequest() {
239
473
  const reqId = state.nextRequestId++;
240
474
  const req = {
241
- type: import_isolate_protocol.MessageType.EVAL,
475
+ type: import_isolate_protocol.MessageType.FETCH_GET_UPGRADE_REQUEST,
476
+ requestId: reqId,
477
+ isolateId
478
+ };
479
+ return sendRequest(state, req);
480
+ },
481
+ async dispatchWebSocketOpen(connectionId) {
482
+ const reqId = state.nextRequestId++;
483
+ const req = {
484
+ type: import_isolate_protocol.MessageType.WS_OPEN,
242
485
  requestId: reqId,
243
486
  isolateId,
244
- code,
245
- filename
487
+ connectionId
246
488
  };
247
- const res = await sendRequest(state, req);
248
- return res.value;
489
+ await sendRequest(state, req);
249
490
  },
250
- dispatchRequest: async (request2, dispatchOptions) => {
491
+ async dispatchWebSocketMessage(connectionId, message) {
251
492
  const reqId = state.nextRequestId++;
252
- const serialized = await serializeRequest(request2);
493
+ const data = message instanceof ArrayBuffer ? new Uint8Array(message) : message;
253
494
  const req = {
254
- type: import_isolate_protocol.MessageType.DISPATCH_REQUEST,
495
+ type: import_isolate_protocol.MessageType.WS_MESSAGE,
255
496
  requestId: reqId,
256
497
  isolateId,
257
- request: serialized,
258
- options: dispatchOptions
498
+ connectionId,
499
+ data
259
500
  };
260
- const res = await sendRequest(state, req, dispatchOptions?.timeout ?? DEFAULT_TIMEOUT);
261
- return deserializeResponse(res.response);
501
+ await sendRequest(state, req);
262
502
  },
263
- tick: async (ms) => {
503
+ async dispatchWebSocketClose(connectionId, code, reason) {
264
504
  const reqId = state.nextRequestId++;
265
505
  const req = {
266
- type: import_isolate_protocol.MessageType.TICK,
506
+ type: import_isolate_protocol.MessageType.WS_CLOSE,
267
507
  requestId: reqId,
268
508
  isolateId,
269
- ms
509
+ connectionId,
510
+ code,
511
+ reason
270
512
  };
271
513
  await sendRequest(state, req);
272
514
  },
273
- setupTestEnvironment: async () => {
515
+ async dispatchWebSocketError(connectionId, error) {
274
516
  const reqId = state.nextRequestId++;
275
517
  const req = {
276
- type: import_isolate_protocol.MessageType.SETUP_TEST_ENV,
518
+ type: import_isolate_protocol.MessageType.FETCH_WS_ERROR,
519
+ requestId: reqId,
520
+ isolateId,
521
+ connectionId,
522
+ error: error.message
523
+ };
524
+ await sendRequest(state, req);
525
+ },
526
+ onWebSocketCommand(callback) {
527
+ wsCommandCallbacks.add(callback);
528
+ return () => {
529
+ wsCommandCallbacks.delete(callback);
530
+ };
531
+ },
532
+ async hasServeHandler() {
533
+ const reqId = state.nextRequestId++;
534
+ const req = {
535
+ type: import_isolate_protocol.MessageType.FETCH_HAS_SERVE_HANDLER,
536
+ requestId: reqId,
537
+ isolateId
538
+ };
539
+ return sendRequest(state, req);
540
+ },
541
+ async hasActiveConnections() {
542
+ const reqId = state.nextRequestId++;
543
+ const req = {
544
+ type: import_isolate_protocol.MessageType.FETCH_HAS_ACTIVE_CONNECTIONS,
545
+ requestId: reqId,
546
+ isolateId
547
+ };
548
+ return sendRequest(state, req);
549
+ }
550
+ };
551
+ const timersHandle = {
552
+ async clearAll() {
553
+ const reqId = state.nextRequestId++;
554
+ const req = {
555
+ type: import_isolate_protocol.MessageType.TIMERS_CLEAR_ALL,
556
+ requestId: reqId,
557
+ isolateId
558
+ };
559
+ await sendRequest(state, req);
560
+ }
561
+ };
562
+ const consoleHandle = {
563
+ async reset() {
564
+ const reqId = state.nextRequestId++;
565
+ const req = {
566
+ type: import_isolate_protocol.MessageType.CONSOLE_RESET,
277
567
  requestId: reqId,
278
568
  isolateId
279
569
  };
280
570
  await sendRequest(state, req);
281
571
  },
282
- runTests: async (timeout) => {
572
+ async getTimers() {
573
+ const reqId = state.nextRequestId++;
574
+ const req = {
575
+ type: import_isolate_protocol.MessageType.CONSOLE_GET_TIMERS,
576
+ requestId: reqId,
577
+ isolateId
578
+ };
579
+ const result2 = await sendRequest(state, req);
580
+ return new Map(Object.entries(result2));
581
+ },
582
+ async getCounters() {
583
+ const reqId = state.nextRequestId++;
584
+ const req = {
585
+ type: import_isolate_protocol.MessageType.CONSOLE_GET_COUNTERS,
586
+ requestId: reqId,
587
+ isolateId
588
+ };
589
+ const result2 = await sendRequest(state, req);
590
+ return new Map(Object.entries(result2));
591
+ },
592
+ async getGroupDepth() {
593
+ const reqId = state.nextRequestId++;
594
+ const req = {
595
+ type: import_isolate_protocol.MessageType.CONSOLE_GET_GROUP_DEPTH,
596
+ requestId: reqId,
597
+ isolateId
598
+ };
599
+ return sendRequest(state, req);
600
+ }
601
+ };
602
+ const testEnvironmentEnabled = !!options.testEnvironment;
603
+ const playwrightEnabled = !!options.playwright;
604
+ const testEnvironmentHandle = {
605
+ async runTests(timeout) {
606
+ if (!testEnvironmentEnabled) {
607
+ throw new Error("Test environment not enabled. Set testEnvironment: true in createRuntime options.");
608
+ }
283
609
  const reqId = state.nextRequestId++;
284
610
  const req = {
285
611
  type: import_isolate_protocol.MessageType.RUN_TESTS,
@@ -289,47 +615,48 @@ async function createRuntime(state, options = {}) {
289
615
  };
290
616
  return sendRequest(state, req, timeout ?? DEFAULT_TIMEOUT);
291
617
  },
292
- setupPlaywright: async (playwrightOptions) => {
618
+ async hasTests() {
619
+ if (!testEnvironmentEnabled) {
620
+ throw new Error("Test environment not enabled. Set testEnvironment: true in createRuntime options.");
621
+ }
293
622
  const reqId = state.nextRequestId++;
294
623
  const req = {
295
- type: import_isolate_protocol.MessageType.SETUP_PLAYWRIGHT,
624
+ type: import_isolate_protocol.MessageType.HAS_TESTS,
296
625
  requestId: reqId,
297
- isolateId,
298
- options: {
299
- browserType: playwrightOptions?.browserType,
300
- headless: playwrightOptions?.headless,
301
- baseURL: playwrightOptions?.baseURL
302
- }
626
+ isolateId
303
627
  };
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);
628
+ return sendRequest(state, req);
312
629
  },
313
- runPlaywrightTests: async (timeout) => {
630
+ async getTestCount() {
631
+ if (!testEnvironmentEnabled) {
632
+ throw new Error("Test environment not enabled. Set testEnvironment: true in createRuntime options.");
633
+ }
314
634
  const reqId = state.nextRequestId++;
315
635
  const req = {
316
- type: import_isolate_protocol.MessageType.RUN_PLAYWRIGHT_TESTS,
636
+ type: import_isolate_protocol.MessageType.GET_TEST_COUNT,
317
637
  requestId: reqId,
318
- isolateId,
319
- timeout
638
+ isolateId
320
639
  };
321
- return sendRequest(state, req, timeout ?? DEFAULT_TIMEOUT);
640
+ return sendRequest(state, req);
322
641
  },
323
- resetPlaywrightTests: async () => {
642
+ async reset() {
643
+ if (!testEnvironmentEnabled) {
644
+ throw new Error("Test environment not enabled. Set testEnvironment: true in createRuntime options.");
645
+ }
324
646
  const reqId = state.nextRequestId++;
325
647
  const req = {
326
- type: import_isolate_protocol.MessageType.RESET_PLAYWRIGHT_TESTS,
648
+ type: import_isolate_protocol.MessageType.RESET_TEST_ENV,
327
649
  requestId: reqId,
328
650
  isolateId
329
651
  };
330
652
  await sendRequest(state, req);
331
- },
332
- getCollectedData: async () => {
653
+ }
654
+ };
655
+ const playwrightHandle = {
656
+ async getCollectedData() {
657
+ if (!playwrightEnabled) {
658
+ throw new Error("Playwright not configured. Provide playwright.page in createRuntime options.");
659
+ }
333
660
  const reqId = state.nextRequestId++;
334
661
  const req = {
335
662
  type: import_isolate_protocol.MessageType.GET_COLLECTED_DATA,
@@ -338,8 +665,43 @@ async function createRuntime(state, options = {}) {
338
665
  };
339
666
  return sendRequest(state, req);
340
667
  },
668
+ async clearCollectedData() {
669
+ if (!playwrightEnabled) {
670
+ throw new Error("Playwright not configured. Provide playwright.page in createRuntime options.");
671
+ }
672
+ const reqId = state.nextRequestId++;
673
+ const req = {
674
+ type: import_isolate_protocol.MessageType.CLEAR_COLLECTED_DATA,
675
+ requestId: reqId,
676
+ isolateId
677
+ };
678
+ await sendRequest(state, req);
679
+ }
680
+ };
681
+ return {
682
+ id: isolateId,
683
+ isolateId,
684
+ fetch: fetchHandle,
685
+ timers: timersHandle,
686
+ console: consoleHandle,
687
+ testEnvironment: testEnvironmentHandle,
688
+ playwright: playwrightHandle,
689
+ eval: async (code, filenameOrOptions) => {
690
+ const reqId = state.nextRequestId++;
691
+ const options2 = typeof filenameOrOptions === "string" ? { filename: filenameOrOptions } : filenameOrOptions;
692
+ const req = {
693
+ type: import_isolate_protocol.MessageType.EVAL,
694
+ requestId: reqId,
695
+ isolateId,
696
+ code,
697
+ filename: options2?.filename,
698
+ maxExecutionMs: options2?.maxExecutionMs,
699
+ module: true
700
+ };
701
+ await sendRequest(state, req);
702
+ },
341
703
  dispose: async () => {
342
- state.playwrightEventHandlers.delete(isolateId);
704
+ isolateWsCallbacks.delete(isolateId);
343
705
  const reqId = state.nextRequestId++;
344
706
  const req = {
345
707
  type: import_isolate_protocol.MessageType.DISPOSE_RUNTIME,
@@ -350,27 +712,23 @@ async function createRuntime(state, options = {}) {
350
712
  }
351
713
  };
352
714
  }
715
+ function registerEventCallback(state, handler) {
716
+ const callbackId = state.nextCallbackId++;
717
+ state.callbacks.set(callbackId, (data) => {
718
+ handler(data);
719
+ return;
720
+ });
721
+ return callbackId;
722
+ }
353
723
  function registerConsoleCallbacks(state, callbacks) {
354
724
  const registrations = {};
355
- const register = (name, fn) => {
725
+ if (callbacks.onEntry) {
356
726
  const callbackId = state.nextCallbackId++;
357
- state.callbacks.set(callbackId, (_level, ...args) => {
358
- fn(...args);
727
+ state.callbacks.set(callbackId, (entry) => {
728
+ callbacks.onEntry(entry);
359
729
  });
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);
730
+ registrations.onEntry = { callbackId, name: "onEntry", type: "sync" };
731
+ }
374
732
  return registrations;
375
733
  }
376
734
  function registerFetchCallback(state, callback) {
@@ -380,7 +738,7 @@ function registerFetchCallback(state, callback) {
380
738
  const response = await callback(request);
381
739
  return serializeResponse(response);
382
740
  });
383
- return { callbackId, name: "fetch", async: true };
741
+ return { callbackId, name: "fetch", type: "async" };
384
742
  }
385
743
  function registerFsCallbacks(state, callbacks) {
386
744
  const registrations = {};
@@ -390,7 +748,7 @@ function registerFsCallbacks(state, callbacks) {
390
748
  const result = await callbacks.readFile(path);
391
749
  return new Uint8Array(result);
392
750
  });
393
- registrations.readFile = { callbackId, name: "readFile", async: true };
751
+ registrations.readFile = { callbackId, name: "readFile", type: "async" };
394
752
  }
395
753
  if (callbacks.writeFile) {
396
754
  const callbackId = state.nextCallbackId++;
@@ -407,67 +765,251 @@ function registerFsCallbacks(state, callbacks) {
407
765
  }
408
766
  await callbacks.writeFile(path, buffer);
409
767
  });
410
- registrations.writeFile = { callbackId, name: "writeFile", async: true };
768
+ registrations.writeFile = { callbackId, name: "writeFile", type: "async" };
411
769
  }
412
770
  if (callbacks.unlink) {
413
771
  const callbackId = state.nextCallbackId++;
414
772
  state.callbacks.set(callbackId, async (path) => {
415
773
  await callbacks.unlink(path);
416
774
  });
417
- registrations.unlink = { callbackId, name: "unlink", async: true };
775
+ registrations.unlink = { callbackId, name: "unlink", type: "async" };
418
776
  }
419
777
  if (callbacks.readdir) {
420
778
  const callbackId = state.nextCallbackId++;
421
779
  state.callbacks.set(callbackId, async (path) => {
422
780
  return callbacks.readdir(path);
423
781
  });
424
- registrations.readdir = { callbackId, name: "readdir", async: true };
782
+ registrations.readdir = { callbackId, name: "readdir", type: "async" };
425
783
  }
426
784
  if (callbacks.mkdir) {
427
785
  const callbackId = state.nextCallbackId++;
428
786
  state.callbacks.set(callbackId, async (path, options) => {
429
787
  await callbacks.mkdir(path, options);
430
788
  });
431
- registrations.mkdir = { callbackId, name: "mkdir", async: true };
789
+ registrations.mkdir = { callbackId, name: "mkdir", type: "async" };
432
790
  }
433
791
  if (callbacks.rmdir) {
434
792
  const callbackId = state.nextCallbackId++;
435
793
  state.callbacks.set(callbackId, async (path) => {
436
794
  await callbacks.rmdir(path);
437
795
  });
438
- registrations.rmdir = { callbackId, name: "rmdir", async: true };
796
+ registrations.rmdir = { callbackId, name: "rmdir", type: "async" };
439
797
  }
440
798
  if (callbacks.stat) {
441
799
  const callbackId = state.nextCallbackId++;
442
800
  state.callbacks.set(callbackId, async (path) => {
443
801
  return callbacks.stat(path);
444
802
  });
445
- registrations.stat = { callbackId, name: "stat", async: true };
803
+ registrations.stat = { callbackId, name: "stat", type: "async" };
446
804
  }
447
805
  if (callbacks.rename) {
448
806
  const callbackId = state.nextCallbackId++;
449
807
  state.callbacks.set(callbackId, async (from, to) => {
450
808
  await callbacks.rename(from, to);
451
809
  });
452
- registrations.rename = { callbackId, name: "rename", async: true };
810
+ registrations.rename = { callbackId, name: "rename", type: "async" };
453
811
  }
454
812
  return registrations;
455
813
  }
456
- async function serializeRequest(request) {
457
- const headers = [];
458
- request.headers.forEach((value, key) => {
459
- headers.push([key, value]);
814
+ function registerModuleLoaderCallback(state, callback) {
815
+ const callbackId = state.nextCallbackId++;
816
+ state.callbacks.set(callbackId, async (moduleName) => {
817
+ return callback(moduleName);
460
818
  });
461
- let body = null;
462
- if (request.body) {
463
- body = new Uint8Array(await request.arrayBuffer());
819
+ return { callbackId, name: "moduleLoader", type: "async" };
820
+ }
821
+ var clientIteratorSessions = new Map;
822
+ var nextClientIteratorId = 1;
823
+ var returnedPromiseRegistry = new Map;
824
+ var returnedIteratorRegistry = new Map;
825
+ function isPromiseRef(value) {
826
+ return typeof value === "object" && value !== null && value.__type === "PromiseRef";
827
+ }
828
+ function isAsyncIteratorRef(value) {
829
+ return typeof value === "object" && value !== null && value.__type === "AsyncIteratorRef";
830
+ }
831
+ function registerCustomFunctions(state, customFunctions) {
832
+ const registrations = {};
833
+ for (const [name, def] of Object.entries(customFunctions)) {
834
+ if (def.type === "asyncIterator") {
835
+ const startCallbackId = state.nextCallbackId++;
836
+ state.callbacks.set(startCallbackId, async (...args) => {
837
+ try {
838
+ const fn = def.fn;
839
+ const iterator = fn(...args);
840
+ const iteratorId = nextClientIteratorId++;
841
+ clientIteratorSessions.set(iteratorId, { iterator });
842
+ return { iteratorId };
843
+ } catch (error) {
844
+ throw error;
845
+ }
846
+ });
847
+ const nextCallbackId = state.nextCallbackId++;
848
+ state.callbacks.set(nextCallbackId, async (iteratorId) => {
849
+ const session = clientIteratorSessions.get(iteratorId);
850
+ if (!session) {
851
+ throw new Error(`Iterator session ${iteratorId} not found`);
852
+ }
853
+ try {
854
+ const result = await session.iterator.next();
855
+ if (result.done) {
856
+ clientIteratorSessions.delete(iteratorId);
857
+ }
858
+ return { done: result.done, value: await import_isolate_protocol.marshalValue(result.value) };
859
+ } catch (error) {
860
+ clientIteratorSessions.delete(iteratorId);
861
+ throw error;
862
+ }
863
+ });
864
+ const returnCallbackId = state.nextCallbackId++;
865
+ state.callbacks.set(returnCallbackId, async (iteratorId, value) => {
866
+ const session = clientIteratorSessions.get(iteratorId);
867
+ if (!session) {
868
+ return { done: true, value: await import_isolate_protocol.marshalValue(undefined) };
869
+ }
870
+ try {
871
+ const result = await session.iterator.return?.(value);
872
+ clientIteratorSessions.delete(iteratorId);
873
+ return { done: true, value: await import_isolate_protocol.marshalValue(result?.value) };
874
+ } catch (error) {
875
+ clientIteratorSessions.delete(iteratorId);
876
+ throw error;
877
+ }
878
+ });
879
+ const throwCallbackId = state.nextCallbackId++;
880
+ state.callbacks.set(throwCallbackId, async (iteratorId, errorData) => {
881
+ const session = clientIteratorSessions.get(iteratorId);
882
+ if (!session) {
883
+ throw new Error(`Iterator session ${iteratorId} not found`);
884
+ }
885
+ try {
886
+ const errInfo = errorData;
887
+ const error = Object.assign(new Error(errInfo.message), { name: errInfo.name });
888
+ const result = await session.iterator.throw?.(error);
889
+ clientIteratorSessions.delete(iteratorId);
890
+ return { done: result?.done ?? true, value: await import_isolate_protocol.marshalValue(result?.value) };
891
+ } catch (error) {
892
+ clientIteratorSessions.delete(iteratorId);
893
+ throw error;
894
+ }
895
+ });
896
+ registrations[`${name}:start`] = { callbackId: startCallbackId, name: `${name}:start`, type: "async" };
897
+ registrations[`${name}:next`] = { callbackId: nextCallbackId, name: `${name}:next`, type: "async" };
898
+ registrations[`${name}:return`] = { callbackId: returnCallbackId, name: `${name}:return`, type: "async" };
899
+ registrations[`${name}:throw`] = { callbackId: throwCallbackId, name: `${name}:throw`, type: "async" };
900
+ registrations[name] = {
901
+ callbackId: startCallbackId,
902
+ name,
903
+ type: "asyncIterator"
904
+ };
905
+ } else {
906
+ const callbackId = state.nextCallbackId++;
907
+ state.callbacks.set(callbackId, async (...args) => {
908
+ const result = await def.fn(...args);
909
+ const addCallbackIdsToRefs = (value) => {
910
+ if (value === null || typeof value !== "object") {
911
+ return value;
912
+ }
913
+ if (isPromiseRef(value)) {
914
+ const resolveCallbackId = state.nextCallbackId++;
915
+ state.callbacks.set(resolveCallbackId, async (...args2) => {
916
+ const promiseId = args2[0];
917
+ const promise = returnedPromiseRegistry.get(promiseId);
918
+ if (!promise) {
919
+ throw new Error(`Promise ${promiseId} not found`);
920
+ }
921
+ const promiseResult = await promise;
922
+ returnedPromiseRegistry.delete(promiseId);
923
+ const marshalledResult = await import_isolate_protocol.marshalValue(promiseResult, marshalCtx);
924
+ return addCallbackIdsToRefs(marshalledResult);
925
+ });
926
+ return {
927
+ ...value,
928
+ __resolveCallbackId: resolveCallbackId
929
+ };
930
+ }
931
+ if (isAsyncIteratorRef(value)) {
932
+ const nextCallbackId = state.nextCallbackId++;
933
+ state.callbacks.set(nextCallbackId, async (...args2) => {
934
+ const iteratorId = args2[0];
935
+ const iterator = returnedIteratorRegistry.get(iteratorId);
936
+ if (!iterator) {
937
+ throw new Error(`Iterator ${iteratorId} not found`);
938
+ }
939
+ const iterResult = await iterator.next();
940
+ if (iterResult.done) {
941
+ returnedIteratorRegistry.delete(iteratorId);
942
+ }
943
+ const marshalledValue = await import_isolate_protocol.marshalValue(iterResult.value, marshalCtx);
944
+ return {
945
+ done: iterResult.done,
946
+ value: addCallbackIdsToRefs(marshalledValue)
947
+ };
948
+ });
949
+ const returnCallbackId = state.nextCallbackId++;
950
+ state.callbacks.set(returnCallbackId, async (...args2) => {
951
+ const iteratorId = args2[0];
952
+ const returnValue = args2[1];
953
+ const iterator = returnedIteratorRegistry.get(iteratorId);
954
+ returnedIteratorRegistry.delete(iteratorId);
955
+ if (!iterator || !iterator.return) {
956
+ return { done: true, value: undefined };
957
+ }
958
+ const iterResult = await iterator.return(returnValue);
959
+ const marshalledValue = await import_isolate_protocol.marshalValue(iterResult.value, marshalCtx);
960
+ return {
961
+ done: true,
962
+ value: addCallbackIdsToRefs(marshalledValue)
963
+ };
964
+ });
965
+ return {
966
+ ...value,
967
+ __nextCallbackId: nextCallbackId,
968
+ __returnCallbackId: returnCallbackId
969
+ };
970
+ }
971
+ if (Array.isArray(value)) {
972
+ return value.map((item) => addCallbackIdsToRefs(item));
973
+ }
974
+ const objResult = {};
975
+ for (const key of Object.keys(value)) {
976
+ objResult[key] = addCallbackIdsToRefs(value[key]);
977
+ }
978
+ return objResult;
979
+ };
980
+ const marshalCtx = {
981
+ registerCallback: (fn) => {
982
+ const returnedCallbackId = state.nextCallbackId++;
983
+ state.callbacks.set(returnedCallbackId, async (...args2) => {
984
+ const fnResult = await fn(...args2);
985
+ const marshalledResult = await import_isolate_protocol.marshalValue(fnResult, marshalCtx);
986
+ return addCallbackIdsToRefs(marshalledResult);
987
+ });
988
+ return returnedCallbackId;
989
+ },
990
+ registerPromise: (promise) => {
991
+ const promiseId = state.nextCallbackId++;
992
+ returnedPromiseRegistry.set(promiseId, promise);
993
+ return promiseId;
994
+ },
995
+ registerIterator: (iterator) => {
996
+ const iteratorId = state.nextCallbackId++;
997
+ returnedIteratorRegistry.set(iteratorId, iterator);
998
+ return iteratorId;
999
+ }
1000
+ };
1001
+ const marshalled = await import_isolate_protocol.marshalValue(result, marshalCtx);
1002
+ const withCallbackIds = addCallbackIdsToRefs(marshalled);
1003
+ return withCallbackIds;
1004
+ });
1005
+ registrations[name] = {
1006
+ callbackId,
1007
+ name,
1008
+ type: def.type
1009
+ };
1010
+ }
464
1011
  }
465
- return {
466
- method: request.method,
467
- url: request.url,
468
- headers,
469
- body
470
- };
1012
+ return registrations;
471
1013
  }
472
1014
  async function serializeResponse(response) {
473
1015
  const headers = [];
@@ -499,6 +1041,104 @@ function deserializeResponse(data) {
499
1041
  headers: data.headers
500
1042
  });
501
1043
  }
1044
+ async function serializeRequestWithStreaming(state, request) {
1045
+ const headers = [];
1046
+ request.headers.forEach((value, key) => {
1047
+ headers.push([key, value]);
1048
+ });
1049
+ let body = null;
1050
+ let bodyStreamId;
1051
+ let bodyStream;
1052
+ if (request.body) {
1053
+ const contentLength = request.headers.get("content-length");
1054
+ const knownSize = contentLength ? parseInt(contentLength, 10) : null;
1055
+ if (knownSize !== null && knownSize > import_isolate_protocol.STREAM_THRESHOLD) {
1056
+ bodyStreamId = state.nextStreamId++;
1057
+ bodyStream = request.body;
1058
+ } else {
1059
+ const clonedRequest = request.clone();
1060
+ try {
1061
+ body = new Uint8Array(await request.arrayBuffer());
1062
+ if (body.length > import_isolate_protocol.STREAM_THRESHOLD) {
1063
+ bodyStreamId = state.nextStreamId++;
1064
+ bodyStream = clonedRequest.body;
1065
+ body = null;
1066
+ }
1067
+ } catch {
1068
+ bodyStreamId = state.nextStreamId++;
1069
+ bodyStream = clonedRequest.body;
1070
+ }
1071
+ }
1072
+ }
1073
+ const result = {
1074
+ method: request.method,
1075
+ url: request.url,
1076
+ headers,
1077
+ body
1078
+ };
1079
+ if (bodyStreamId !== undefined) {
1080
+ result.bodyStreamId = bodyStreamId;
1081
+ result.bodyStream = bodyStream;
1082
+ }
1083
+ return result;
1084
+ }
1085
+ function waitForUploadCredit(session) {
1086
+ return new Promise((resolve) => {
1087
+ session.creditResolver = resolve;
1088
+ });
1089
+ }
1090
+ async function sendBodyStream(state, streamId, body) {
1091
+ const session = {
1092
+ streamId,
1093
+ requestId: 0,
1094
+ state: "active",
1095
+ bytesTransferred: 0,
1096
+ credit: 0
1097
+ };
1098
+ state.uploadStreams.set(streamId, session);
1099
+ const reader = body.getReader();
1100
+ try {
1101
+ while (true) {
1102
+ if (session.state !== "active") {
1103
+ throw new Error("Stream cancelled");
1104
+ }
1105
+ while (session.credit < import_isolate_protocol.STREAM_CHUNK_SIZE && session.state === "active") {
1106
+ await waitForUploadCredit(session);
1107
+ }
1108
+ if (session.state !== "active") {
1109
+ throw new Error("Stream cancelled");
1110
+ }
1111
+ const { done, value } = await reader.read();
1112
+ if (done) {
1113
+ sendMessage(state.socket, {
1114
+ type: import_isolate_protocol.MessageType.STREAM_CLOSE,
1115
+ streamId
1116
+ });
1117
+ break;
1118
+ }
1119
+ for (let offset = 0;offset < value.length; offset += import_isolate_protocol.STREAM_CHUNK_SIZE) {
1120
+ const chunk = value.slice(offset, offset + import_isolate_protocol.STREAM_CHUNK_SIZE);
1121
+ sendMessage(state.socket, {
1122
+ type: import_isolate_protocol.MessageType.STREAM_PUSH,
1123
+ streamId,
1124
+ chunk
1125
+ });
1126
+ session.credit -= chunk.length;
1127
+ session.bytesTransferred += chunk.length;
1128
+ }
1129
+ }
1130
+ } catch (err) {
1131
+ sendMessage(state.socket, {
1132
+ type: import_isolate_protocol.MessageType.STREAM_ERROR,
1133
+ streamId,
1134
+ error: err.message
1135
+ });
1136
+ throw err;
1137
+ } finally {
1138
+ reader.releaseLock();
1139
+ state.uploadStreams.delete(streamId);
1140
+ }
1141
+ }
502
1142
  })
503
1143
 
504
- //# debugId=AC520FAF0080FE0764756E2164756E21
1144
+ //# debugId=7380B90E2B96832A64756E2164756E21