@ricsam/isolate-client 0.1.1 → 0.1.5

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