@ricsam/isolate-runtime 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -27
- package/dist/cjs/index.cjs +308 -39
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/index.mjs +314 -25
- package/dist/mjs/index.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/types/index.d.ts +41 -5
- package/package.json +1 -1
- package/dist/cjs/internal.cjs +0 -95
- package/dist/cjs/internal.cjs.map +0 -10
- package/dist/mjs/internal.mjs +0 -52
- package/dist/mjs/internal.mjs.map +0 -10
- package/dist/types/internal.d.ts +0 -39
package/dist/mjs/index.mjs
CHANGED
|
@@ -23,7 +23,9 @@ import {
|
|
|
23
23
|
hasTests as hasTestsInContext,
|
|
24
24
|
getTestCount as getTestCountInContext
|
|
25
25
|
} from "@ricsam/isolate-test-environment";
|
|
26
|
-
import {
|
|
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 (
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,16 +643,21 @@ function createModuleResolver(state) {
|
|
|
428
643
|
}
|
|
429
644
|
const importerPath = state.moduleToFilename.get(referrer) ?? "<unknown>";
|
|
430
645
|
const importerResolveDir = path.posix.dirname(importerPath);
|
|
431
|
-
const
|
|
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}`;
|
|
437
653
|
const hashCached = state.moduleCache.get(cacheKey);
|
|
438
654
|
if (hashCached)
|
|
439
655
|
return hashCached;
|
|
440
|
-
|
|
656
|
+
let transformed = state.transformCache.get(hash);
|
|
657
|
+
if (!transformed) {
|
|
658
|
+
transformed = await transformModuleCode(code, specifier);
|
|
659
|
+
state.transformCache.set(hash, transformed);
|
|
660
|
+
}
|
|
441
661
|
if (transformed.sourceMap) {
|
|
442
662
|
state.sourceMaps.set(specifier, transformed.sourceMap);
|
|
443
663
|
}
|
|
@@ -446,8 +666,12 @@ function createModuleResolver(state) {
|
|
|
446
666
|
});
|
|
447
667
|
const resolvedPath = path.posix.join(resolveDir, path.posix.basename(specifier));
|
|
448
668
|
state.moduleToFilename.set(mod, resolvedPath);
|
|
449
|
-
|
|
450
|
-
|
|
669
|
+
if (result.static) {
|
|
670
|
+
state.staticModuleCache.set(specifier, mod);
|
|
671
|
+
} else {
|
|
672
|
+
state.moduleCache.set(specifier, mod);
|
|
673
|
+
state.moduleCache.set(cacheKey, mod);
|
|
674
|
+
}
|
|
451
675
|
const resolver = createModuleResolver(state);
|
|
452
676
|
await mod.instantiate(state.context, resolver);
|
|
453
677
|
return mod;
|
|
@@ -458,8 +682,8 @@ function convertFetchCallback(callback) {
|
|
|
458
682
|
return {};
|
|
459
683
|
}
|
|
460
684
|
return {
|
|
461
|
-
onFetch: async (
|
|
462
|
-
return Promise.resolve(callback(
|
|
685
|
+
onFetch: async (url, init) => {
|
|
686
|
+
return Promise.resolve(callback(url, init));
|
|
463
687
|
}
|
|
464
688
|
};
|
|
465
689
|
}
|
|
@@ -475,8 +699,11 @@ async function createRuntime(options) {
|
|
|
475
699
|
context,
|
|
476
700
|
handles: {},
|
|
477
701
|
moduleCache: new Map,
|
|
702
|
+
staticModuleCache: new Map,
|
|
703
|
+
transformCache: new Map,
|
|
478
704
|
moduleToFilename: new Map,
|
|
479
705
|
sourceMaps: new Map,
|
|
706
|
+
pendingCallbacks: [],
|
|
480
707
|
moduleLoader: opts.moduleLoader,
|
|
481
708
|
customFunctions: opts.customFunctions
|
|
482
709
|
};
|
|
@@ -491,13 +718,17 @@ async function createRuntime(options) {
|
|
|
491
718
|
state.handles.fs = await setupFs(context, opts.fs);
|
|
492
719
|
}
|
|
493
720
|
if (opts.customFunctions) {
|
|
494
|
-
|
|
721
|
+
const customMarshalOptions = opts.customFunctionsMarshalOptions ?? createLocalCustomFunctionsMarshalOptions();
|
|
722
|
+
state.customFnInvokeRef = await setupCustomFunctions(context, opts.customFunctions, customMarshalOptions);
|
|
495
723
|
}
|
|
496
724
|
if (opts.testEnvironment) {
|
|
497
725
|
const testEnvOptions = typeof opts.testEnvironment === "object" ? opts.testEnvironment : undefined;
|
|
498
726
|
state.handles.testEnvironment = await setupTestEnvironment(context, testEnvOptions);
|
|
499
727
|
}
|
|
500
728
|
if (opts.playwright) {
|
|
729
|
+
if (!opts.playwright.handler) {
|
|
730
|
+
throw new Error("Playwright configured without handler. Provide playwright.handler in createRuntime options.");
|
|
731
|
+
}
|
|
501
732
|
let eventCallback = opts.playwright.onEvent;
|
|
502
733
|
if (opts.playwright.console && opts.console?.onEntry) {
|
|
503
734
|
const originalCallback = eventCallback;
|
|
@@ -516,13 +747,13 @@ async function createRuntime(options) {
|
|
|
516
747
|
}
|
|
517
748
|
};
|
|
518
749
|
}
|
|
519
|
-
|
|
520
|
-
|
|
750
|
+
const playwrightSetupOptions = {
|
|
751
|
+
handler: opts.playwright.handler,
|
|
521
752
|
timeout: opts.playwright.timeout,
|
|
522
|
-
baseUrl: opts.playwright.baseUrl,
|
|
523
753
|
console: opts.playwright.console && !opts.console?.onEntry,
|
|
524
754
|
onEvent: eventCallback
|
|
525
|
-
}
|
|
755
|
+
};
|
|
756
|
+
state.handles.playwright = await setupPlaywright(context, playwrightSetupOptions);
|
|
526
757
|
}
|
|
527
758
|
const fetchHandle = {
|
|
528
759
|
async dispatchRequest(request, options2) {
|
|
@@ -578,6 +809,36 @@ async function createRuntime(options) {
|
|
|
578
809
|
throw new Error("Fetch handle not available");
|
|
579
810
|
}
|
|
580
811
|
return state.handles.fetch.hasActiveConnections();
|
|
812
|
+
},
|
|
813
|
+
dispatchClientWebSocketOpen(socketId, protocol, extensions) {
|
|
814
|
+
if (!state.handles.fetch) {
|
|
815
|
+
throw new Error("Fetch handle not available");
|
|
816
|
+
}
|
|
817
|
+
state.handles.fetch.dispatchClientWebSocketOpen(socketId, protocol, extensions);
|
|
818
|
+
},
|
|
819
|
+
dispatchClientWebSocketMessage(socketId, data) {
|
|
820
|
+
if (!state.handles.fetch) {
|
|
821
|
+
throw new Error("Fetch handle not available");
|
|
822
|
+
}
|
|
823
|
+
state.handles.fetch.dispatchClientWebSocketMessage(socketId, data);
|
|
824
|
+
},
|
|
825
|
+
dispatchClientWebSocketClose(socketId, code, reason, wasClean) {
|
|
826
|
+
if (!state.handles.fetch) {
|
|
827
|
+
throw new Error("Fetch handle not available");
|
|
828
|
+
}
|
|
829
|
+
state.handles.fetch.dispatchClientWebSocketClose(socketId, code, reason, wasClean);
|
|
830
|
+
},
|
|
831
|
+
dispatchClientWebSocketError(socketId) {
|
|
832
|
+
if (!state.handles.fetch) {
|
|
833
|
+
throw new Error("Fetch handle not available");
|
|
834
|
+
}
|
|
835
|
+
state.handles.fetch.dispatchClientWebSocketError(socketId);
|
|
836
|
+
},
|
|
837
|
+
onClientWebSocketCommand(callback) {
|
|
838
|
+
if (!state.handles.fetch) {
|
|
839
|
+
throw new Error("Fetch handle not available");
|
|
840
|
+
}
|
|
841
|
+
return state.handles.fetch.onClientWebSocketCommand(callback);
|
|
581
842
|
}
|
|
582
843
|
};
|
|
583
844
|
const timersHandle = {
|
|
@@ -600,11 +861,27 @@ async function createRuntime(options) {
|
|
|
600
861
|
}
|
|
601
862
|
};
|
|
602
863
|
const testEnvironmentHandle = {
|
|
603
|
-
async runTests(
|
|
864
|
+
async runTests(timeout) {
|
|
604
865
|
if (!state.handles.testEnvironment) {
|
|
605
866
|
throw new Error("Test environment not enabled. Set testEnvironment: true in createRuntime options.");
|
|
606
867
|
}
|
|
607
|
-
|
|
868
|
+
if (timeout === undefined) {
|
|
869
|
+
return runTestsInContext(state.context);
|
|
870
|
+
}
|
|
871
|
+
let timeoutId;
|
|
872
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
873
|
+
timeoutId = setTimeout(() => reject(new Error("Test timeout")), timeout);
|
|
874
|
+
});
|
|
875
|
+
try {
|
|
876
|
+
return await Promise.race([
|
|
877
|
+
runTestsInContext(state.context),
|
|
878
|
+
timeoutPromise
|
|
879
|
+
]);
|
|
880
|
+
} finally {
|
|
881
|
+
if (timeoutId) {
|
|
882
|
+
clearTimeout(timeoutId);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
608
885
|
},
|
|
609
886
|
hasTests() {
|
|
610
887
|
if (!state.handles.testEnvironment) {
|
|
@@ -625,7 +902,7 @@ async function createRuntime(options) {
|
|
|
625
902
|
const playwrightHandle = {
|
|
626
903
|
getCollectedData() {
|
|
627
904
|
if (!state.handles.playwright) {
|
|
628
|
-
throw new Error("Playwright not configured. Provide playwright.
|
|
905
|
+
throw new Error("Playwright not configured. Provide playwright.handler in createRuntime options.");
|
|
629
906
|
}
|
|
630
907
|
return {
|
|
631
908
|
browserConsoleLogs: state.handles.playwright.getBrowserConsoleLogs(),
|
|
@@ -639,6 +916,7 @@ async function createRuntime(options) {
|
|
|
639
916
|
};
|
|
640
917
|
return {
|
|
641
918
|
id,
|
|
919
|
+
pendingCallbacks: state.pendingCallbacks,
|
|
642
920
|
fetch: fetchHandle,
|
|
643
921
|
timers: timersHandle,
|
|
644
922
|
console: consoleHandle,
|
|
@@ -669,6 +947,10 @@ async function createRuntime(options) {
|
|
|
669
947
|
} finally {
|
|
670
948
|
runRef.release();
|
|
671
949
|
}
|
|
950
|
+
if (state.pendingCallbacks.length > 0) {
|
|
951
|
+
await Promise.all(state.pendingCallbacks);
|
|
952
|
+
state.pendingCallbacks.length = 0;
|
|
953
|
+
}
|
|
672
954
|
} catch (err) {
|
|
673
955
|
const error = err;
|
|
674
956
|
if (error.stack && state.sourceMaps.size > 0) {
|
|
@@ -677,6 +959,11 @@ async function createRuntime(options) {
|
|
|
677
959
|
throw error;
|
|
678
960
|
}
|
|
679
961
|
},
|
|
962
|
+
clearModuleCache() {
|
|
963
|
+
state.moduleCache.clear();
|
|
964
|
+
state.moduleToFilename.clear();
|
|
965
|
+
state.sourceMaps.clear();
|
|
966
|
+
},
|
|
680
967
|
async dispose() {
|
|
681
968
|
if (state.customFnInvokeRef) {
|
|
682
969
|
state.customFnInvokeRef.release();
|
|
@@ -713,9 +1000,11 @@ export {
|
|
|
713
1000
|
normalizeEntryFilename2 as normalizeEntryFilename,
|
|
714
1001
|
hasTests,
|
|
715
1002
|
getTestCount,
|
|
1003
|
+
getDefaultPlaywrightHandlerMetadata,
|
|
1004
|
+
defaultPlaywrightHandler,
|
|
716
1005
|
createRuntime,
|
|
717
1006
|
createPlaywrightHandler,
|
|
718
1007
|
createNodeFileSystemHandler
|
|
719
1008
|
};
|
|
720
1009
|
|
|
721
|
-
//# debugId=
|
|
1010
|
+
//# debugId=D363252DB857D59164756E2164756E21
|