@ricsam/isolate-runtime 0.1.14 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23,7 +23,9 @@ import {
23
23
  hasTests as hasTestsInContext,
24
24
  getTestCount as getTestCountInContext
25
25
  } from "@ricsam/isolate-test-environment";
26
- import { setupPlaywright } from "@ricsam/isolate-playwright";
26
+ import {
27
+ setupPlaywright
28
+ } from "@ricsam/isolate-playwright";
27
29
  import {
28
30
  marshalValue,
29
31
  unmarshalValue
@@ -47,10 +49,10 @@ import {
47
49
  } from "@ricsam/isolate-test-environment";
48
50
  import {
49
51
  setupPlaywright as setupPlaywright2,
50
- createPlaywrightHandler
52
+ createPlaywrightHandler,
53
+ defaultPlaywrightHandler,
54
+ getDefaultPlaywrightHandlerMetadata
51
55
  } from "@ricsam/isolate-playwright";
52
-
53
- export * from "./internal.mjs";
54
56
  var iteratorSessions = new Map;
55
57
  var nextIteratorId = 1;
56
58
  var ISOLATE_MARSHAL_CODE = `
@@ -176,6 +178,68 @@ var ISOLATE_MARSHAL_CODE = `
176
178
  }
177
179
  return fd;
178
180
  }
181
+ case 'CallbackRef': {
182
+ // Create a proxy function that invokes the callback
183
+ const callbackId = value.callbackId;
184
+ return function(...args) {
185
+ const argsJson = JSON.stringify(marshalForHost(args));
186
+ const resultJson = __customFn_invoke.applySyncPromise(undefined, [callbackId, argsJson]);
187
+ const result = JSON.parse(resultJson);
188
+ if (result.ok) {
189
+ return unmarshalFromHost(result.value);
190
+ } else {
191
+ const error = new Error(result.error.message);
192
+ error.name = result.error.name;
193
+ throw error;
194
+ }
195
+ };
196
+ }
197
+ case 'PromiseRef': {
198
+ // Create a proxy Promise that resolves via callback
199
+ const promiseId = value.promiseId;
200
+ return new Promise((resolve, reject) => {
201
+ try {
202
+ const argsJson = JSON.stringify([promiseId]);
203
+ const resultJson = __customFn_invoke.applySyncPromise(undefined, [value.__resolveCallbackId, argsJson]);
204
+ const result = JSON.parse(resultJson);
205
+ if (result.ok) {
206
+ resolve(unmarshalFromHost(result.value));
207
+ } else {
208
+ reject(new Error(result.error.message));
209
+ }
210
+ } catch (e) {
211
+ reject(e);
212
+ }
213
+ });
214
+ }
215
+ case 'AsyncIteratorRef': {
216
+ const iteratorId = value.iteratorId;
217
+ const nextCallbackId = value.__nextCallbackId;
218
+ const returnCallbackId = value.__returnCallbackId;
219
+ return {
220
+ [Symbol.asyncIterator]() { return this; },
221
+ async next() {
222
+ const argsJson = JSON.stringify([iteratorId]);
223
+ const resultJson = __customFn_invoke.applySyncPromise(undefined, [nextCallbackId, argsJson]);
224
+ const result = JSON.parse(resultJson);
225
+ if (!result.ok) {
226
+ const error = new Error(result.error.message);
227
+ error.name = result.error.name;
228
+ throw error;
229
+ }
230
+ return {
231
+ done: result.value.done,
232
+ value: unmarshalFromHost(result.value.value)
233
+ };
234
+ },
235
+ async return(v) {
236
+ const argsJson = JSON.stringify([iteratorId, marshalForHost(v)]);
237
+ const resultJson = __customFn_invoke.applySyncPromise(undefined, [returnCallbackId, argsJson]);
238
+ const result = JSON.parse(resultJson);
239
+ return { done: true, value: result.ok ? unmarshalFromHost(result.value) : undefined };
240
+ }
241
+ };
242
+ }
179
243
  default:
180
244
  // Unknown ref type, return as-is
181
245
  break;
@@ -199,9 +263,27 @@ var ISOLATE_MARSHAL_CODE = `
199
263
  globalThis.__unmarshalFromHost = unmarshalFromHost;
200
264
  })();
201
265
  `;
202
- async function setupCustomFunctions(context, customFunctions) {
266
+ async function setupCustomFunctions(context, customFunctions, marshalOptions) {
203
267
  const global = context.global;
204
- const invokeCallbackRef = new ivm.Reference(async (name, argsJson) => {
268
+ const invokeCallbackRef = new ivm.Reference(async (nameOrId, argsJson) => {
269
+ if (typeof nameOrId === "number" && marshalOptions) {
270
+ const rawArgs2 = JSON.parse(argsJson);
271
+ const args2 = unmarshalValue(rawArgs2);
272
+ try {
273
+ const result = await marshalOptions.invokeCallback(nameOrId, args2);
274
+ const ctx = marshalOptions.createMarshalContext();
275
+ const marshalledResult = await marshalValue(result, ctx);
276
+ const processedResult = marshalOptions.addCallbackIdsToRefs(marshalledResult);
277
+ return JSON.stringify({ ok: true, value: processedResult });
278
+ } catch (error) {
279
+ const err = error;
280
+ return JSON.stringify({
281
+ ok: false,
282
+ error: { message: err.message, name: err.name }
283
+ });
284
+ }
285
+ }
286
+ const name = String(nameOrId);
205
287
  const def = customFunctions[name];
206
288
  if (!def) {
207
289
  return JSON.stringify({
@@ -215,7 +297,13 @@ async function setupCustomFunctions(context, customFunctions) {
215
297
  const rawArgs = JSON.parse(argsJson);
216
298
  const args = unmarshalValue(rawArgs);
217
299
  try {
218
- const result = def.type === "async" ? await def.fn(...args) : def.fn(...args);
300
+ const result = await def.fn(...args);
301
+ if (marshalOptions) {
302
+ const ctx = marshalOptions.createMarshalContext();
303
+ const marshalledResult2 = await marshalValue(result, ctx);
304
+ const processedResult = marshalOptions.addCallbackIdsToRefs(marshalledResult2);
305
+ return JSON.stringify({ ok: true, value: processedResult });
306
+ }
219
307
  const marshalledResult = await marshalValue(result);
220
308
  return JSON.stringify({ ok: true, value: marshalledResult });
221
309
  } catch (error) {
@@ -271,7 +359,14 @@ async function setupCustomFunctions(context, customFunctions) {
271
359
  if (result.done) {
272
360
  iteratorSessions.delete(iteratorId);
273
361
  }
274
- const marshalledValue = await marshalValue(result.value);
362
+ let marshalledValue;
363
+ if (marshalOptions) {
364
+ const ctx = marshalOptions.createMarshalContext();
365
+ marshalledValue = await marshalValue(result.value, ctx);
366
+ marshalledValue = marshalOptions.addCallbackIdsToRefs(marshalledValue);
367
+ } else {
368
+ marshalledValue = await marshalValue(result.value);
369
+ }
275
370
  return JSON.stringify({
276
371
  ok: true,
277
372
  done: result.done,
@@ -297,7 +392,14 @@ async function setupCustomFunctions(context, customFunctions) {
297
392
  const value = unmarshalValue(rawValue);
298
393
  const result = await session.iterator.return?.(value);
299
394
  iteratorSessions.delete(iteratorId);
300
- const marshalledValue = await marshalValue(result?.value);
395
+ let marshalledValue;
396
+ if (marshalOptions) {
397
+ const ctx = marshalOptions.createMarshalContext();
398
+ marshalledValue = await marshalValue(result?.value, ctx);
399
+ marshalledValue = marshalOptions.addCallbackIdsToRefs(marshalledValue);
400
+ } else {
401
+ marshalledValue = await marshalValue(result?.value);
402
+ }
301
403
  return JSON.stringify({ ok: true, done: true, value: marshalledValue });
302
404
  } catch (error) {
303
405
  const err = error;
@@ -327,7 +429,14 @@ async function setupCustomFunctions(context, customFunctions) {
327
429
  });
328
430
  const result = await session.iterator.throw?.(error);
329
431
  iteratorSessions.delete(iteratorId);
330
- const marshalledValue = await marshalValue(result?.value);
432
+ let marshalledValue;
433
+ if (marshalOptions) {
434
+ const ctx = marshalOptions.createMarshalContext();
435
+ marshalledValue = await marshalValue(result?.value, ctx);
436
+ marshalledValue = marshalOptions.addCallbackIdsToRefs(marshalledValue);
437
+ } else {
438
+ marshalledValue = await marshalValue(result?.value);
439
+ }
331
440
  return JSON.stringify({
332
441
  ok: true,
333
442
  done: result?.done ?? true,
@@ -418,8 +527,114 @@ async function setupCustomFunctions(context, customFunctions) {
418
527
  }
419
528
  return invokeCallbackRef;
420
529
  }
530
+ function createLocalCustomFunctionsMarshalOptions() {
531
+ const returnedCallbacks = new Map;
532
+ const returnedPromises = new Map;
533
+ const returnedIterators = new Map;
534
+ let nextLocalCallbackId = 1e6;
535
+ const createMarshalContext = () => ({
536
+ registerCallback: (fn) => {
537
+ const callbackId = nextLocalCallbackId++;
538
+ returnedCallbacks.set(callbackId, fn);
539
+ return callbackId;
540
+ },
541
+ registerPromise: (promise) => {
542
+ const promiseId = nextLocalCallbackId++;
543
+ returnedPromises.set(promiseId, promise);
544
+ return promiseId;
545
+ },
546
+ registerIterator: (iterator) => {
547
+ const iteratorId = nextLocalCallbackId++;
548
+ returnedIterators.set(iteratorId, iterator);
549
+ return iteratorId;
550
+ }
551
+ });
552
+ const isPromiseRef = (value) => typeof value === "object" && value !== null && value.__type === "PromiseRef";
553
+ const isAsyncIteratorRef = (value) => typeof value === "object" && value !== null && value.__type === "AsyncIteratorRef";
554
+ const addCallbackIdsToRefs = (value) => {
555
+ if (value === null || typeof value !== "object")
556
+ return value;
557
+ if (isPromiseRef(value)) {
558
+ if ("__resolveCallbackId" in value)
559
+ return value;
560
+ const resolveCallbackId = nextLocalCallbackId++;
561
+ returnedCallbacks.set(resolveCallbackId, async (promiseId) => {
562
+ const promise = returnedPromises.get(promiseId);
563
+ if (!promise) {
564
+ throw new Error(`Promise ${promiseId} not found`);
565
+ }
566
+ const result2 = await promise;
567
+ returnedPromises.delete(promiseId);
568
+ const ctx = createMarshalContext();
569
+ const marshalled = await marshalValue(result2, ctx);
570
+ return addCallbackIdsToRefs(marshalled);
571
+ });
572
+ return { ...value, __resolveCallbackId: resolveCallbackId };
573
+ }
574
+ if (isAsyncIteratorRef(value)) {
575
+ if ("__nextCallbackId" in value)
576
+ return value;
577
+ const nextCallbackId = nextLocalCallbackId++;
578
+ returnedCallbacks.set(nextCallbackId, async (iteratorId) => {
579
+ const iterator = returnedIterators.get(iteratorId);
580
+ if (!iterator) {
581
+ throw new Error(`Iterator ${iteratorId} not found`);
582
+ }
583
+ const result2 = await iterator.next();
584
+ if (result2.done) {
585
+ returnedIterators.delete(iteratorId);
586
+ }
587
+ const ctx = createMarshalContext();
588
+ const marshalledValue = await marshalValue(result2.value, ctx);
589
+ return {
590
+ done: result2.done,
591
+ value: addCallbackIdsToRefs(marshalledValue)
592
+ };
593
+ });
594
+ const returnCallbackId = nextLocalCallbackId++;
595
+ returnedCallbacks.set(returnCallbackId, async (iteratorId, returnValue) => {
596
+ const iterator = returnedIterators.get(iteratorId);
597
+ returnedIterators.delete(iteratorId);
598
+ if (!iterator || !iterator.return) {
599
+ return { done: true, value: undefined };
600
+ }
601
+ const result2 = await iterator.return(returnValue);
602
+ const ctx = createMarshalContext();
603
+ const marshalledValue = await marshalValue(result2.value, ctx);
604
+ return {
605
+ done: true,
606
+ value: addCallbackIdsToRefs(marshalledValue)
607
+ };
608
+ });
609
+ return {
610
+ ...value,
611
+ __nextCallbackId: nextCallbackId,
612
+ __returnCallbackId: returnCallbackId
613
+ };
614
+ }
615
+ if (Array.isArray(value)) {
616
+ return value.map((item) => addCallbackIdsToRefs(item));
617
+ }
618
+ const result = {};
619
+ for (const key of Object.keys(value)) {
620
+ result[key] = addCallbackIdsToRefs(value[key]);
621
+ }
622
+ return result;
623
+ };
624
+ const invokeCallback = async (callbackId, args) => {
625
+ const callback = returnedCallbacks.get(callbackId);
626
+ if (!callback) {
627
+ throw new Error(`Local callback ${callbackId} not found`);
628
+ }
629
+ return await callback(...args);
630
+ };
631
+ return { createMarshalContext, addCallbackIdsToRefs, invokeCallback };
632
+ }
421
633
  function createModuleResolver(state) {
422
634
  return async (specifier, referrer) => {
635
+ const staticCached = state.staticModuleCache.get(specifier);
636
+ if (staticCached)
637
+ return staticCached;
423
638
  const cached = state.moduleCache.get(specifier);
424
639
  if (cached)
425
640
  return cached;
@@ -428,29 +643,74 @@ function createModuleResolver(state) {
428
643
  }
429
644
  const importerPath = state.moduleToFilename.get(referrer) ?? "<unknown>";
430
645
  const importerResolveDir = path.posix.dirname(importerPath);
431
- const { code, resolveDir } = await state.moduleLoader(specifier, {
646
+ const result = await state.moduleLoader(specifier, {
432
647
  path: importerPath,
433
648
  resolveDir: importerResolveDir
434
649
  });
650
+ const { code, resolveDir } = result;
435
651
  const hash = contentHash(code);
436
652
  const cacheKey = `${specifier}:${hash}`;
653
+ const inFlightKey = `${result.static ? "static" : "dynamic"}:${cacheKey}`;
654
+ const staticCachedAfterLoad = state.staticModuleCache.get(specifier);
655
+ if (staticCachedAfterLoad)
656
+ return staticCachedAfterLoad;
657
+ const cachedAfterLoad = state.moduleCache.get(specifier);
658
+ if (cachedAfterLoad)
659
+ return cachedAfterLoad;
437
660
  const hashCached = state.moduleCache.get(cacheKey);
438
661
  if (hashCached)
439
662
  return hashCached;
440
- const transformed = await transformModuleCode(code, specifier);
441
- if (transformed.sourceMap) {
442
- state.sourceMaps.set(specifier, transformed.sourceMap);
663
+ const inFlight = state.moduleLoadsInFlight.get(inFlightKey);
664
+ if (inFlight)
665
+ return inFlight;
666
+ const loadPromise = (async () => {
667
+ let mod;
668
+ try {
669
+ let transformed = state.transformCache.get(hash);
670
+ if (!transformed) {
671
+ transformed = await transformModuleCode(code, specifier);
672
+ state.transformCache.set(hash, transformed);
673
+ }
674
+ if (transformed.sourceMap) {
675
+ state.sourceMaps.set(specifier, transformed.sourceMap);
676
+ }
677
+ mod = await state.isolate.compileModule(transformed.code, {
678
+ filename: specifier
679
+ });
680
+ const resolvedPath = path.posix.join(resolveDir, path.posix.basename(specifier));
681
+ state.moduleToFilename.set(mod, resolvedPath);
682
+ if (result.static) {
683
+ state.staticModuleCache.set(specifier, mod);
684
+ } else {
685
+ state.moduleCache.set(specifier, mod);
686
+ state.moduleCache.set(cacheKey, mod);
687
+ }
688
+ return mod;
689
+ } catch (err) {
690
+ if (mod) {
691
+ state.moduleToFilename.delete(mod);
692
+ if (result.static) {
693
+ if (state.staticModuleCache.get(specifier) === mod) {
694
+ state.staticModuleCache.delete(specifier);
695
+ }
696
+ } else {
697
+ if (state.moduleCache.get(specifier) === mod) {
698
+ state.moduleCache.delete(specifier);
699
+ }
700
+ if (state.moduleCache.get(cacheKey) === mod) {
701
+ state.moduleCache.delete(cacheKey);
702
+ }
703
+ }
704
+ }
705
+ throw err;
706
+ }
707
+ })();
708
+ state.moduleLoadsInFlight.set(inFlightKey, loadPromise);
709
+ try {
710
+ return await loadPromise;
711
+ } finally {
712
+ state.moduleLoadsInFlight.delete(inFlightKey);
443
713
  }
444
- const mod = await state.isolate.compileModule(transformed.code, {
445
- filename: specifier
446
- });
447
- const resolvedPath = path.posix.join(resolveDir, path.posix.basename(specifier));
448
- state.moduleToFilename.set(mod, resolvedPath);
449
- state.moduleCache.set(specifier, mod);
450
- state.moduleCache.set(cacheKey, mod);
451
- const resolver = createModuleResolver(state);
452
- await mod.instantiate(state.context, resolver);
453
- return mod;
454
714
  };
455
715
  }
456
716
  function convertFetchCallback(callback) {
@@ -458,8 +718,8 @@ function convertFetchCallback(callback) {
458
718
  return {};
459
719
  }
460
720
  return {
461
- onFetch: async (request) => {
462
- return Promise.resolve(callback(request));
721
+ onFetch: async (url, init) => {
722
+ return Promise.resolve(callback(url, init));
463
723
  }
464
724
  };
465
725
  }
@@ -475,8 +735,13 @@ async function createRuntime(options) {
475
735
  context,
476
736
  handles: {},
477
737
  moduleCache: new Map,
738
+ staticModuleCache: new Map,
739
+ moduleLoadsInFlight: new Map,
740
+ transformCache: new Map,
478
741
  moduleToFilename: new Map,
479
742
  sourceMaps: new Map,
743
+ pendingCallbacks: [],
744
+ evalChain: Promise.resolve(),
480
745
  moduleLoader: opts.moduleLoader,
481
746
  customFunctions: opts.customFunctions
482
747
  };
@@ -491,13 +756,17 @@ async function createRuntime(options) {
491
756
  state.handles.fs = await setupFs(context, opts.fs);
492
757
  }
493
758
  if (opts.customFunctions) {
494
- state.customFnInvokeRef = await setupCustomFunctions(context, opts.customFunctions);
759
+ const customMarshalOptions = opts.customFunctionsMarshalOptions ?? createLocalCustomFunctionsMarshalOptions();
760
+ state.customFnInvokeRef = await setupCustomFunctions(context, opts.customFunctions, customMarshalOptions);
495
761
  }
496
762
  if (opts.testEnvironment) {
497
763
  const testEnvOptions = typeof opts.testEnvironment === "object" ? opts.testEnvironment : undefined;
498
764
  state.handles.testEnvironment = await setupTestEnvironment(context, testEnvOptions);
499
765
  }
500
766
  if (opts.playwright) {
767
+ if (!opts.playwright.handler) {
768
+ throw new Error("Playwright configured without handler. Provide playwright.handler in createRuntime options.");
769
+ }
501
770
  let eventCallback = opts.playwright.onEvent;
502
771
  if (opts.playwright.console && opts.console?.onEntry) {
503
772
  const originalCallback = eventCallback;
@@ -516,12 +785,13 @@ async function createRuntime(options) {
516
785
  }
517
786
  };
518
787
  }
519
- state.handles.playwright = await setupPlaywright(context, {
520
- page: opts.playwright.page,
788
+ const playwrightSetupOptions = {
789
+ handler: opts.playwright.handler,
521
790
  timeout: opts.playwright.timeout,
522
791
  console: opts.playwright.console && !opts.console?.onEntry,
523
792
  onEvent: eventCallback
524
- });
793
+ };
794
+ state.handles.playwright = await setupPlaywright(context, playwrightSetupOptions);
525
795
  }
526
796
  const fetchHandle = {
527
797
  async dispatchRequest(request, options2) {
@@ -577,6 +847,48 @@ async function createRuntime(options) {
577
847
  throw new Error("Fetch handle not available");
578
848
  }
579
849
  return state.handles.fetch.hasActiveConnections();
850
+ },
851
+ dispatchClientWebSocketOpen(socketId, protocol, extensions) {
852
+ if (!state.handles.fetch) {
853
+ throw new Error("Fetch handle not available");
854
+ }
855
+ state.handles.fetch.dispatchClientWebSocketOpen(socketId, protocol, extensions);
856
+ },
857
+ dispatchClientWebSocketMessage(socketId, data) {
858
+ if (!state.handles.fetch) {
859
+ throw new Error("Fetch handle not available");
860
+ }
861
+ state.handles.fetch.dispatchClientWebSocketMessage(socketId, data);
862
+ },
863
+ dispatchClientWebSocketClose(socketId, code, reason, wasClean) {
864
+ if (!state.handles.fetch) {
865
+ throw new Error("Fetch handle not available");
866
+ }
867
+ state.handles.fetch.dispatchClientWebSocketClose(socketId, code, reason, wasClean);
868
+ },
869
+ dispatchClientWebSocketError(socketId) {
870
+ if (!state.handles.fetch) {
871
+ throw new Error("Fetch handle not available");
872
+ }
873
+ state.handles.fetch.dispatchClientWebSocketError(socketId);
874
+ },
875
+ onClientWebSocketCommand(callback) {
876
+ if (!state.handles.fetch) {
877
+ throw new Error("Fetch handle not available");
878
+ }
879
+ return state.handles.fetch.onClientWebSocketCommand(callback);
880
+ },
881
+ onEvent(callback) {
882
+ if (!state.handles.fetch) {
883
+ throw new Error("Fetch handle not available");
884
+ }
885
+ return state.handles.fetch.onEvent(callback);
886
+ },
887
+ dispatchEvent(event, payload) {
888
+ if (!state.handles.fetch) {
889
+ throw new Error("Fetch handle not available");
890
+ }
891
+ state.handles.fetch.dispatchEvent(event, payload);
580
892
  }
581
893
  };
582
894
  const timersHandle = {
@@ -599,11 +911,27 @@ async function createRuntime(options) {
599
911
  }
600
912
  };
601
913
  const testEnvironmentHandle = {
602
- async runTests(_timeout) {
914
+ async runTests(timeout) {
603
915
  if (!state.handles.testEnvironment) {
604
916
  throw new Error("Test environment not enabled. Set testEnvironment: true in createRuntime options.");
605
917
  }
606
- return runTestsInContext(state.context);
918
+ if (timeout === undefined) {
919
+ return runTestsInContext(state.context);
920
+ }
921
+ let timeoutId;
922
+ const timeoutPromise = new Promise((_, reject) => {
923
+ timeoutId = setTimeout(() => reject(new Error("Test timeout")), timeout);
924
+ });
925
+ try {
926
+ return await Promise.race([
927
+ runTestsInContext(state.context),
928
+ timeoutPromise
929
+ ]);
930
+ } finally {
931
+ if (timeoutId) {
932
+ clearTimeout(timeoutId);
933
+ }
934
+ }
607
935
  },
608
936
  hasTests() {
609
937
  if (!state.handles.testEnvironment) {
@@ -624,7 +952,7 @@ async function createRuntime(options) {
624
952
  const playwrightHandle = {
625
953
  getCollectedData() {
626
954
  if (!state.handles.playwright) {
627
- throw new Error("Playwright not configured. Provide playwright.page in createRuntime options.");
955
+ throw new Error("Playwright not configured. Provide playwright.handler in createRuntime options.");
628
956
  }
629
957
  return {
630
958
  browserConsoleLogs: state.handles.playwright.getBrowserConsoleLogs(),
@@ -638,43 +966,62 @@ async function createRuntime(options) {
638
966
  };
639
967
  return {
640
968
  id,
969
+ pendingCallbacks: state.pendingCallbacks,
641
970
  fetch: fetchHandle,
642
971
  timers: timersHandle,
643
972
  console: consoleHandle,
644
973
  testEnvironment: testEnvironmentHandle,
645
974
  playwright: playwrightHandle,
646
975
  async eval(code, filenameOrOptions) {
647
- const options2 = typeof filenameOrOptions === "string" ? { filename: filenameOrOptions } : filenameOrOptions;
648
- const filename = normalizeEntryFilename(options2?.filename);
649
- try {
650
- const transformed = await transformEntryCode(code, filename);
651
- if (transformed.sourceMap) {
652
- state.sourceMaps.set(filename, transformed.sourceMap);
653
- }
654
- const mod = await state.isolate.compileModule(transformed.code, {
655
- filename
656
- });
657
- state.moduleToFilename.set(mod, filename);
658
- const resolver = createModuleResolver(state);
659
- await mod.instantiate(state.context, resolver);
660
- await mod.evaluate();
661
- const ns = mod.namespace;
662
- const runRef = await ns.get("default", { reference: true });
976
+ const runEval = async () => {
977
+ const options2 = typeof filenameOrOptions === "string" ? { filename: filenameOrOptions } : filenameOrOptions;
978
+ const filename = normalizeEntryFilename(options2?.filename);
663
979
  try {
664
- await runRef.apply(undefined, [], {
665
- result: { promise: true },
666
- ...options2?.maxExecutionMs ? { timeout: options2.maxExecutionMs } : {}
980
+ const transformed = await transformEntryCode(code, filename);
981
+ if (transformed.sourceMap) {
982
+ state.sourceMaps.set(filename, transformed.sourceMap);
983
+ }
984
+ const mod = await state.isolate.compileModule(transformed.code, {
985
+ filename
667
986
  });
668
- } finally {
669
- runRef.release();
670
- }
671
- } catch (err) {
672
- const error = err;
673
- if (error.stack && state.sourceMaps.size > 0) {
674
- error.stack = mapErrorStack(error.stack, state.sourceMaps);
987
+ state.moduleToFilename.set(mod, filename);
988
+ const resolver = createModuleResolver(state);
989
+ await mod.instantiate(state.context, resolver);
990
+ await mod.evaluate();
991
+ const ns = mod.namespace;
992
+ const runRef = await ns.get("default", { reference: true });
993
+ try {
994
+ await runRef.apply(undefined, [], {
995
+ result: { promise: true }
996
+ });
997
+ } finally {
998
+ runRef.release();
999
+ }
1000
+ if (state.pendingCallbacks.length > 0) {
1001
+ await Promise.all(state.pendingCallbacks);
1002
+ state.pendingCallbacks.length = 0;
1003
+ }
1004
+ } catch (err) {
1005
+ const error = err;
1006
+ if (error.stack && state.sourceMaps.size > 0) {
1007
+ error.stack = mapErrorStack(error.stack, state.sourceMaps);
1008
+ }
1009
+ throw error;
675
1010
  }
676
- throw error;
677
- }
1011
+ };
1012
+ const queuedEval = state.evalChain.then(runEval, runEval);
1013
+ state.evalChain = queuedEval.then(() => {
1014
+ return;
1015
+ }, () => {
1016
+ return;
1017
+ });
1018
+ return queuedEval;
1019
+ },
1020
+ clearModuleCache() {
1021
+ state.moduleCache.clear();
1022
+ state.moduleLoadsInFlight.clear();
1023
+ state.moduleToFilename.clear();
1024
+ state.sourceMaps.clear();
678
1025
  },
679
1026
  async dispose() {
680
1027
  if (state.customFnInvokeRef) {
@@ -691,6 +1038,7 @@ async function createRuntime(options) {
691
1038
  state.handles.console?.dispose();
692
1039
  state.handles.core?.dispose();
693
1040
  state.moduleCache.clear();
1041
+ state.moduleLoadsInFlight.clear();
694
1042
  state.context.release();
695
1043
  state.isolate.dispose();
696
1044
  }
@@ -712,9 +1060,11 @@ export {
712
1060
  normalizeEntryFilename2 as normalizeEntryFilename,
713
1061
  hasTests,
714
1062
  getTestCount,
1063
+ getDefaultPlaywrightHandlerMetadata,
1064
+ defaultPlaywrightHandler,
715
1065
  createRuntime,
716
1066
  createPlaywrightHandler,
717
1067
  createNodeFileSystemHandler
718
1068
  };
719
1069
 
720
- //# debugId=5B1C4DA72893C8FA64756E2164756E21
1070
+ //# debugId=42C800BEB0731DA164756E2164756E21