@ricsam/isolate-daemon 0.1.5 → 0.1.6
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 +27 -0
- package/dist/cjs/callback-fs-handler.cjs +68 -37
- package/dist/cjs/callback-fs-handler.cjs.map +3 -3
- package/dist/cjs/connection.cjs +255 -69
- package/dist/cjs/connection.cjs.map +3 -3
- package/dist/cjs/index.cjs +4 -2
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/callback-fs-handler.mjs +68 -37
- package/dist/mjs/callback-fs-handler.mjs.map +3 -3
- package/dist/mjs/connection.mjs +255 -70
- package/dist/mjs/connection.mjs.map +3 -3
- package/dist/mjs/index.mjs +4 -2
- package/dist/mjs/index.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/types/callback-fs-handler.d.ts +3 -3
- package/dist/types/types.d.ts +37 -1
- package/package.json +1 -1
package/dist/mjs/connection.mjs
CHANGED
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
buildFrame,
|
|
8
8
|
MessageType,
|
|
9
9
|
ErrorCode,
|
|
10
|
-
STREAM_THRESHOLD,
|
|
11
10
|
STREAM_CHUNK_SIZE,
|
|
12
11
|
STREAM_DEFAULT_CREDIT,
|
|
13
12
|
marshalValue,
|
|
@@ -56,18 +55,26 @@ function handleConnection(socket, state) {
|
|
|
56
55
|
for (const isolateId of connection.isolates) {
|
|
57
56
|
const instance = state.isolates.get(isolateId);
|
|
58
57
|
if (instance) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
if (instance.namespaceId != null && !instance.isDisposed) {
|
|
59
|
+
softDeleteRuntime(instance, state);
|
|
60
|
+
} else if (!instance.isDisposed) {
|
|
61
|
+
try {
|
|
62
|
+
if (instance.playwrightHandle) {
|
|
63
|
+
instance.playwrightHandle.dispose();
|
|
64
|
+
}
|
|
65
|
+
instance.runtime.dispose();
|
|
66
|
+
} catch {}
|
|
67
|
+
state.isolates.delete(isolateId);
|
|
68
|
+
}
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
71
|
for (const [, pending] of connection.pendingCallbacks) {
|
|
72
|
+
if (pending.timeoutId) {
|
|
73
|
+
clearTimeout(pending.timeoutId);
|
|
74
|
+
}
|
|
69
75
|
pending.reject(new Error("Connection closed"));
|
|
70
76
|
}
|
|
77
|
+
connection.pendingCallbacks.clear();
|
|
71
78
|
state.connections.delete(socket);
|
|
72
79
|
});
|
|
73
80
|
socket.on("error", (err) => {
|
|
@@ -193,10 +200,147 @@ async function handleMessage(message, connection, state) {
|
|
|
193
200
|
sendError(connection.socket, message.requestId ?? 0, ErrorCode.UNKNOWN_MESSAGE_TYPE, `Unknown message type: ${message.type}`);
|
|
194
201
|
}
|
|
195
202
|
}
|
|
203
|
+
function softDeleteRuntime(instance, state) {
|
|
204
|
+
instance.isDisposed = true;
|
|
205
|
+
instance.disposedAt = Date.now();
|
|
206
|
+
instance.ownerConnection = null;
|
|
207
|
+
instance.callbacks.clear();
|
|
208
|
+
instance.runtime.timers.clearAll();
|
|
209
|
+
instance.runtime.console.reset();
|
|
210
|
+
instance.pendingCallbacks.length = 0;
|
|
211
|
+
instance.returnedCallbacks?.clear();
|
|
212
|
+
instance.returnedPromises?.clear();
|
|
213
|
+
instance.returnedIterators?.clear();
|
|
214
|
+
}
|
|
215
|
+
function reuseNamespacedRuntime(instance, connection, message, state) {
|
|
216
|
+
instance.ownerConnection = connection.socket;
|
|
217
|
+
instance.isDisposed = false;
|
|
218
|
+
instance.disposedAt = undefined;
|
|
219
|
+
instance.lastActivity = Date.now();
|
|
220
|
+
connection.isolates.add(instance.isolateId);
|
|
221
|
+
const callbacks = message.options.callbacks;
|
|
222
|
+
if (instance.callbackContext) {
|
|
223
|
+
instance.callbackContext.connection = connection;
|
|
224
|
+
instance.callbackContext.consoleOnEntry = callbacks?.console?.onEntry?.callbackId;
|
|
225
|
+
instance.callbackContext.fetch = callbacks?.fetch?.callbackId;
|
|
226
|
+
instance.callbackContext.moduleLoader = callbacks?.moduleLoader?.callbackId;
|
|
227
|
+
instance.callbackContext.fs = {
|
|
228
|
+
readFile: callbacks?.fs?.readFile?.callbackId,
|
|
229
|
+
writeFile: callbacks?.fs?.writeFile?.callbackId,
|
|
230
|
+
stat: callbacks?.fs?.stat?.callbackId,
|
|
231
|
+
readdir: callbacks?.fs?.readdir?.callbackId,
|
|
232
|
+
unlink: callbacks?.fs?.unlink?.callbackId,
|
|
233
|
+
mkdir: callbacks?.fs?.mkdir?.callbackId,
|
|
234
|
+
rmdir: callbacks?.fs?.rmdir?.callbackId
|
|
235
|
+
};
|
|
236
|
+
instance.callbackContext.custom.clear();
|
|
237
|
+
if (callbacks?.custom) {
|
|
238
|
+
for (const [name, reg] of Object.entries(callbacks.custom)) {
|
|
239
|
+
if (reg) {
|
|
240
|
+
instance.callbackContext.custom.set(name, reg.callbackId);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
instance.callbacks.clear();
|
|
246
|
+
if (callbacks?.console?.onEntry) {
|
|
247
|
+
instance.callbacks.set(callbacks.console.onEntry.callbackId, {
|
|
248
|
+
...callbacks.console.onEntry,
|
|
249
|
+
name: "onEntry"
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
if (callbacks?.fetch) {
|
|
253
|
+
instance.callbacks.set(callbacks.fetch.callbackId, callbacks.fetch);
|
|
254
|
+
}
|
|
255
|
+
if (callbacks?.fs) {
|
|
256
|
+
for (const [name, reg] of Object.entries(callbacks.fs)) {
|
|
257
|
+
if (reg) {
|
|
258
|
+
instance.callbacks.set(reg.callbackId, { ...reg, name });
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (callbacks?.moduleLoader) {
|
|
263
|
+
instance.moduleLoaderCallbackId = callbacks.moduleLoader.callbackId;
|
|
264
|
+
instance.callbacks.set(callbacks.moduleLoader.callbackId, callbacks.moduleLoader);
|
|
265
|
+
}
|
|
266
|
+
if (callbacks?.custom) {
|
|
267
|
+
for (const [name, reg] of Object.entries(callbacks.custom)) {
|
|
268
|
+
if (reg) {
|
|
269
|
+
instance.callbacks.set(reg.callbackId, { ...reg, name });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
instance.returnedCallbacks = new Map;
|
|
274
|
+
instance.returnedPromises = new Map;
|
|
275
|
+
instance.returnedIterators = new Map;
|
|
276
|
+
instance.nextLocalCallbackId = 1e6;
|
|
277
|
+
if (callbacks?.custom) {
|
|
278
|
+
const newCallbackIdMap = {};
|
|
279
|
+
for (const [name, reg] of Object.entries(callbacks.custom)) {
|
|
280
|
+
if (reg) {
|
|
281
|
+
newCallbackIdMap[name] = reg.callbackId;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
try {
|
|
285
|
+
instance.runtime.context.global.setSync("__customFnCallbackIds", new ivm.ExternalCopy(newCallbackIdMap).copyInto());
|
|
286
|
+
} catch {}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
function evictOldestDisposedRuntime(state) {
|
|
290
|
+
let oldest = null;
|
|
291
|
+
let oldestTime = Infinity;
|
|
292
|
+
for (const [, instance] of state.isolates) {
|
|
293
|
+
if (instance.isDisposed && instance.disposedAt !== undefined) {
|
|
294
|
+
if (instance.disposedAt < oldestTime) {
|
|
295
|
+
oldestTime = instance.disposedAt;
|
|
296
|
+
oldest = instance;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (oldest) {
|
|
301
|
+
try {
|
|
302
|
+
if (oldest.playwrightHandle) {
|
|
303
|
+
oldest.playwrightHandle.dispose();
|
|
304
|
+
}
|
|
305
|
+
oldest.runtime.dispose();
|
|
306
|
+
} catch {}
|
|
307
|
+
state.isolates.delete(oldest.isolateId);
|
|
308
|
+
if (oldest.namespaceId != null) {
|
|
309
|
+
state.namespacedRuntimes.delete(oldest.namespaceId);
|
|
310
|
+
}
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
196
315
|
async function handleCreateRuntime(message, connection, state) {
|
|
316
|
+
const namespaceId = message.options.namespaceId;
|
|
317
|
+
if (namespaceId != null) {
|
|
318
|
+
const existing = state.namespacedRuntimes.get(namespaceId);
|
|
319
|
+
if (existing) {
|
|
320
|
+
if (!existing.isDisposed) {
|
|
321
|
+
if (existing.ownerConnection === connection.socket) {
|
|
322
|
+
sendOk(connection.socket, message.requestId, {
|
|
323
|
+
isolateId: existing.isolateId,
|
|
324
|
+
reused: true
|
|
325
|
+
});
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
sendError(connection.socket, message.requestId, ErrorCode.SCRIPT_ERROR, `Namespace "${namespaceId}" already has an active runtime`);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
reuseNamespacedRuntime(existing, connection, message, state);
|
|
332
|
+
sendOk(connection.socket, message.requestId, {
|
|
333
|
+
isolateId: existing.isolateId,
|
|
334
|
+
reused: true
|
|
335
|
+
});
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
197
339
|
if (state.isolates.size >= state.options.maxIsolates) {
|
|
198
|
-
|
|
199
|
-
|
|
340
|
+
if (!evictOldestDisposedRuntime(state)) {
|
|
341
|
+
sendError(connection.socket, message.requestId, ErrorCode.ISOLATE_MEMORY_LIMIT, `Maximum isolates (${state.options.maxIsolates}) reached`);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
200
344
|
}
|
|
201
345
|
try {
|
|
202
346
|
const isolateId = randomUUID();
|
|
@@ -206,32 +350,61 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
206
350
|
const moduleLoaderCallback = message.options.callbacks?.moduleLoader;
|
|
207
351
|
const customCallbacks = message.options.callbacks?.custom;
|
|
208
352
|
const pendingCallbacks = [];
|
|
353
|
+
const callbackContext = {
|
|
354
|
+
connection,
|
|
355
|
+
consoleOnEntry: consoleCallbacks?.onEntry?.callbackId,
|
|
356
|
+
fetch: fetchCallback?.callbackId,
|
|
357
|
+
moduleLoader: moduleLoaderCallback?.callbackId,
|
|
358
|
+
fs: {
|
|
359
|
+
readFile: fsCallbacks?.readFile?.callbackId,
|
|
360
|
+
writeFile: fsCallbacks?.writeFile?.callbackId,
|
|
361
|
+
stat: fsCallbacks?.stat?.callbackId,
|
|
362
|
+
readdir: fsCallbacks?.readdir?.callbackId,
|
|
363
|
+
unlink: fsCallbacks?.unlink?.callbackId,
|
|
364
|
+
mkdir: fsCallbacks?.mkdir?.callbackId,
|
|
365
|
+
rmdir: fsCallbacks?.rmdir?.callbackId
|
|
366
|
+
},
|
|
367
|
+
custom: new Map(customCallbacks ? Object.entries(customCallbacks).map(([name, reg]) => [name, reg.callbackId]) : [])
|
|
368
|
+
};
|
|
209
369
|
const runtime = await createInternalRuntime({
|
|
210
370
|
memoryLimitMB: message.options.memoryLimitMB ?? state.options.defaultMemoryLimitMB,
|
|
211
371
|
cwd: message.options.cwd,
|
|
212
|
-
console:
|
|
372
|
+
console: {
|
|
213
373
|
onEntry: (entry) => {
|
|
214
|
-
const
|
|
374
|
+
const conn = callbackContext.connection;
|
|
375
|
+
const callbackId = callbackContext.consoleOnEntry;
|
|
376
|
+
if (!conn || callbackId === undefined)
|
|
377
|
+
return;
|
|
378
|
+
const promise = invokeClientCallback(conn, callbackId, [entry]).catch(() => {});
|
|
215
379
|
pendingCallbacks.push(promise);
|
|
216
380
|
}
|
|
217
|
-
}
|
|
218
|
-
fetch:
|
|
381
|
+
},
|
|
382
|
+
fetch: {
|
|
219
383
|
onFetch: async (request) => {
|
|
384
|
+
const conn = callbackContext.connection;
|
|
385
|
+
const callbackId = callbackContext.fetch;
|
|
386
|
+
if (!conn || callbackId === undefined) {
|
|
387
|
+
throw new Error("Fetch callback not available");
|
|
388
|
+
}
|
|
220
389
|
const serialized = await serializeRequest(request);
|
|
221
|
-
const result = await invokeClientCallback(
|
|
390
|
+
const result = await invokeClientCallback(conn, callbackId, [serialized]);
|
|
222
391
|
return deserializeResponse(result);
|
|
223
392
|
}
|
|
224
|
-
}
|
|
225
|
-
fs:
|
|
393
|
+
},
|
|
394
|
+
fs: {
|
|
226
395
|
getDirectory: async (path) => {
|
|
396
|
+
const conn = callbackContext.connection;
|
|
397
|
+
if (!conn) {
|
|
398
|
+
throw new Error("FS callbacks not available");
|
|
399
|
+
}
|
|
227
400
|
return createCallbackFileSystemHandler({
|
|
228
|
-
connection,
|
|
229
|
-
|
|
401
|
+
connection: conn,
|
|
402
|
+
callbackContext,
|
|
230
403
|
invokeClientCallback,
|
|
231
404
|
basePath: path
|
|
232
405
|
});
|
|
233
406
|
}
|
|
234
|
-
}
|
|
407
|
+
}
|
|
235
408
|
});
|
|
236
409
|
const instance = {
|
|
237
410
|
isolateId,
|
|
@@ -244,7 +417,10 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
244
417
|
returnedCallbacks: new Map,
|
|
245
418
|
returnedPromises: new Map,
|
|
246
419
|
returnedIterators: new Map,
|
|
247
|
-
nextLocalCallbackId: 1e6
|
|
420
|
+
nextLocalCallbackId: 1e6,
|
|
421
|
+
namespaceId,
|
|
422
|
+
isDisposed: false,
|
|
423
|
+
callbackContext
|
|
248
424
|
};
|
|
249
425
|
if (moduleLoaderCallback) {
|
|
250
426
|
instance.moduleLoaderCallbackId = moduleLoaderCallback.callbackId;
|
|
@@ -329,6 +505,9 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
329
505
|
state.isolates.set(isolateId, instance);
|
|
330
506
|
connection.isolates.add(isolateId);
|
|
331
507
|
state.stats.totalIsolatesCreated++;
|
|
508
|
+
if (namespaceId != null) {
|
|
509
|
+
state.namespacedRuntimes.set(namespaceId, instance);
|
|
510
|
+
}
|
|
332
511
|
instance.runtime.fetch.onWebSocketCommand((cmd) => {
|
|
333
512
|
let data;
|
|
334
513
|
if (cmd.data instanceof ArrayBuffer) {
|
|
@@ -349,7 +528,7 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
349
528
|
};
|
|
350
529
|
sendMessage(connection.socket, wsCommandMsg);
|
|
351
530
|
});
|
|
352
|
-
sendOk(connection.socket, message.requestId, { isolateId });
|
|
531
|
+
sendOk(connection.socket, message.requestId, { isolateId, reused: false });
|
|
353
532
|
} catch (err) {
|
|
354
533
|
const error = err;
|
|
355
534
|
sendError(connection.socket, message.requestId, ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
@@ -366,12 +545,16 @@ async function handleDisposeRuntime(message, connection, state) {
|
|
|
366
545
|
return;
|
|
367
546
|
}
|
|
368
547
|
try {
|
|
369
|
-
if (instance.playwrightHandle) {
|
|
370
|
-
instance.playwrightHandle.dispose();
|
|
371
|
-
}
|
|
372
|
-
instance.runtime.dispose();
|
|
373
|
-
state.isolates.delete(message.isolateId);
|
|
374
548
|
connection.isolates.delete(message.isolateId);
|
|
549
|
+
if (instance.namespaceId != null) {
|
|
550
|
+
softDeleteRuntime(instance, state);
|
|
551
|
+
} else {
|
|
552
|
+
if (instance.playwrightHandle) {
|
|
553
|
+
instance.playwrightHandle.dispose();
|
|
554
|
+
}
|
|
555
|
+
instance.runtime.dispose();
|
|
556
|
+
state.isolates.delete(message.isolateId);
|
|
557
|
+
}
|
|
375
558
|
sendOk(connection.socket, message.requestId);
|
|
376
559
|
} catch (err) {
|
|
377
560
|
const error = err;
|
|
@@ -428,22 +611,21 @@ async function handleDispatchRequest(message, connection, state) {
|
|
|
428
611
|
body: requestBody
|
|
429
612
|
});
|
|
430
613
|
const response = await instance.runtime.fetch.dispatchRequest(request);
|
|
431
|
-
|
|
432
|
-
const knownSize = contentLength ? parseInt(contentLength, 10) : null;
|
|
433
|
-
if (knownSize !== null && knownSize > STREAM_THRESHOLD) {
|
|
614
|
+
if (response.body) {
|
|
434
615
|
await sendStreamedResponse(connection, message.requestId, response);
|
|
435
616
|
} else {
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
617
|
+
const headers = [];
|
|
618
|
+
response.headers.forEach((value, key) => {
|
|
619
|
+
headers.push([key, value]);
|
|
620
|
+
});
|
|
621
|
+
sendOk(connection.socket, message.requestId, {
|
|
622
|
+
response: {
|
|
623
|
+
status: response.status,
|
|
624
|
+
statusText: response.statusText,
|
|
625
|
+
headers,
|
|
626
|
+
body: null
|
|
443
627
|
}
|
|
444
|
-
}
|
|
445
|
-
await sendStreamedResponse(connection, message.requestId, clonedResponse);
|
|
446
|
-
}
|
|
628
|
+
});
|
|
447
629
|
}
|
|
448
630
|
} catch (err) {
|
|
449
631
|
const error = err;
|
|
@@ -1018,7 +1200,8 @@ async function setupCustomFunctions(context, customCallbacks, connection, instan
|
|
|
1018
1200
|
}
|
|
1019
1201
|
result = await callback(...args);
|
|
1020
1202
|
} else {
|
|
1021
|
-
|
|
1203
|
+
const conn = instance.callbackContext?.connection || connection;
|
|
1204
|
+
result = await invokeClientCallback(conn, callbackId, args);
|
|
1022
1205
|
}
|
|
1023
1206
|
const ctx = createMarshalContext();
|
|
1024
1207
|
const marshalledResult = await marshalValue({ ok: true, value: result }, ctx);
|
|
@@ -1034,6 +1217,11 @@ async function setupCustomFunctions(context, customCallbacks, connection, instan
|
|
|
1034
1217
|
});
|
|
1035
1218
|
global.setSync("__customFn_invoke", invokeCallbackRef);
|
|
1036
1219
|
context.evalSync(ISOLATE_MARSHAL_CODE);
|
|
1220
|
+
const callbackIdMap = {};
|
|
1221
|
+
for (const [name, registration] of Object.entries(customCallbacks)) {
|
|
1222
|
+
callbackIdMap[name] = registration.callbackId;
|
|
1223
|
+
}
|
|
1224
|
+
global.setSync("__customFnCallbackIds", new ivm.ExternalCopy(callbackIdMap).copyInto());
|
|
1037
1225
|
for (const [name, registration] of Object.entries(customCallbacks)) {
|
|
1038
1226
|
if (name.includes(":")) {
|
|
1039
1227
|
continue;
|
|
@@ -1041,10 +1229,11 @@ async function setupCustomFunctions(context, customCallbacks, connection, instan
|
|
|
1041
1229
|
if (registration.type === "sync") {
|
|
1042
1230
|
context.evalSync(`
|
|
1043
1231
|
globalThis.${name} = function(...args) {
|
|
1232
|
+
const callbackId = globalThis.__customFnCallbackIds["${name}"];
|
|
1044
1233
|
const argsJson = JSON.stringify(__marshalForHost(args));
|
|
1045
1234
|
const resultJson = __customFn_invoke.applySyncPromise(
|
|
1046
1235
|
undefined,
|
|
1047
|
-
[
|
|
1236
|
+
[callbackId, argsJson]
|
|
1048
1237
|
);
|
|
1049
1238
|
const result = JSON.parse(resultJson);
|
|
1050
1239
|
if (result.ok) {
|
|
@@ -1067,10 +1256,11 @@ async function setupCustomFunctions(context, customCallbacks, connection, instan
|
|
|
1067
1256
|
context.evalSync(`
|
|
1068
1257
|
globalThis.${name} = function(...args) {
|
|
1069
1258
|
// Start the iterator and get the iteratorId
|
|
1259
|
+
const startCallbackId = globalThis.__customFnCallbackIds["${name}:start"];
|
|
1070
1260
|
const argsJson = JSON.stringify(__marshalForHost(args));
|
|
1071
1261
|
const startResultJson = __customFn_invoke.applySyncPromise(
|
|
1072
1262
|
undefined,
|
|
1073
|
-
[
|
|
1263
|
+
[startCallbackId, argsJson]
|
|
1074
1264
|
);
|
|
1075
1265
|
const startResult = JSON.parse(startResultJson);
|
|
1076
1266
|
if (!startResult.ok) {
|
|
@@ -1083,10 +1273,11 @@ async function setupCustomFunctions(context, customCallbacks, connection, instan
|
|
|
1083
1273
|
return {
|
|
1084
1274
|
[Symbol.asyncIterator]() { return this; },
|
|
1085
1275
|
async next() {
|
|
1276
|
+
const nextCallbackId = globalThis.__customFnCallbackIds["${name}:next"];
|
|
1086
1277
|
const argsJson = JSON.stringify(__marshalForHost([iteratorId]));
|
|
1087
1278
|
const resultJson = __customFn_invoke.applySyncPromise(
|
|
1088
1279
|
undefined,
|
|
1089
|
-
[
|
|
1280
|
+
[nextCallbackId, argsJson]
|
|
1090
1281
|
);
|
|
1091
1282
|
const result = JSON.parse(resultJson);
|
|
1092
1283
|
if (!result.ok) {
|
|
@@ -1098,19 +1289,21 @@ async function setupCustomFunctions(context, customCallbacks, connection, instan
|
|
|
1098
1289
|
return { done: val.done, value: val.value };
|
|
1099
1290
|
},
|
|
1100
1291
|
async return(v) {
|
|
1292
|
+
const returnCallbackId = globalThis.__customFnCallbackIds["${name}:return"];
|
|
1101
1293
|
const argsJson = JSON.stringify(__marshalForHost([iteratorId, v]));
|
|
1102
1294
|
const resultJson = __customFn_invoke.applySyncPromise(
|
|
1103
1295
|
undefined,
|
|
1104
|
-
[
|
|
1296
|
+
[returnCallbackId, argsJson]
|
|
1105
1297
|
);
|
|
1106
1298
|
const result = JSON.parse(resultJson);
|
|
1107
1299
|
return { done: true, value: result.ok ? __unmarshalFromHost(result.value) : undefined };
|
|
1108
1300
|
},
|
|
1109
1301
|
async throw(e) {
|
|
1302
|
+
const throwCallbackId = globalThis.__customFnCallbackIds["${name}:throw"];
|
|
1110
1303
|
const argsJson = JSON.stringify(__marshalForHost([iteratorId, { message: e?.message, name: e?.name }]));
|
|
1111
1304
|
const resultJson = __customFn_invoke.applySyncPromise(
|
|
1112
1305
|
undefined,
|
|
1113
|
-
[
|
|
1306
|
+
[throwCallbackId, argsJson]
|
|
1114
1307
|
);
|
|
1115
1308
|
const result = JSON.parse(resultJson);
|
|
1116
1309
|
if (!result.ok) {
|
|
@@ -1127,10 +1320,11 @@ async function setupCustomFunctions(context, customCallbacks, connection, instan
|
|
|
1127
1320
|
} else if (registration.type === "async") {
|
|
1128
1321
|
context.evalSync(`
|
|
1129
1322
|
globalThis.${name} = async function(...args) {
|
|
1323
|
+
const callbackId = globalThis.__customFnCallbackIds["${name}"];
|
|
1130
1324
|
const argsJson = JSON.stringify(__marshalForHost(args));
|
|
1131
1325
|
const resultJson = __customFn_invoke.applySyncPromise(
|
|
1132
1326
|
undefined,
|
|
1133
|
-
[
|
|
1327
|
+
[callbackId, argsJson]
|
|
1134
1328
|
);
|
|
1135
1329
|
const result = JSON.parse(resultJson);
|
|
1136
1330
|
if (result.ok) {
|
|
@@ -1179,22 +1373,6 @@ async function serializeRequest(request) {
|
|
|
1179
1373
|
body
|
|
1180
1374
|
};
|
|
1181
1375
|
}
|
|
1182
|
-
async function serializeResponse(response) {
|
|
1183
|
-
const headers = [];
|
|
1184
|
-
response.headers.forEach((value, key) => {
|
|
1185
|
-
headers.push([key, value]);
|
|
1186
|
-
});
|
|
1187
|
-
let body = null;
|
|
1188
|
-
if (response.body) {
|
|
1189
|
-
body = new Uint8Array(await response.arrayBuffer());
|
|
1190
|
-
}
|
|
1191
|
-
return {
|
|
1192
|
-
status: response.status,
|
|
1193
|
-
statusText: response.statusText,
|
|
1194
|
-
headers,
|
|
1195
|
-
body
|
|
1196
|
-
};
|
|
1197
|
-
}
|
|
1198
1376
|
function deserializeResponse(data) {
|
|
1199
1377
|
return new Response(data.body, {
|
|
1200
1378
|
status: data.status,
|
|
@@ -1355,14 +1533,21 @@ async function handleRunTests(message, connection, state) {
|
|
|
1355
1533
|
instance.lastActivity = Date.now();
|
|
1356
1534
|
try {
|
|
1357
1535
|
const timeout = message.timeout ?? 30000;
|
|
1536
|
+
let timeoutId;
|
|
1358
1537
|
const timeoutPromise = new Promise((_, reject) => {
|
|
1359
|
-
setTimeout(() => reject(new Error("Test timeout")), timeout);
|
|
1538
|
+
timeoutId = setTimeout(() => reject(new Error("Test timeout")), timeout);
|
|
1360
1539
|
});
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1540
|
+
try {
|
|
1541
|
+
const results = await Promise.race([
|
|
1542
|
+
runTestsInContext(instance.runtime.context),
|
|
1543
|
+
timeoutPromise
|
|
1544
|
+
]);
|
|
1545
|
+
sendOk(connection.socket, message.requestId, results);
|
|
1546
|
+
} finally {
|
|
1547
|
+
if (timeoutId) {
|
|
1548
|
+
clearTimeout(timeoutId);
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1366
1551
|
} catch (err) {
|
|
1367
1552
|
const error = err;
|
|
1368
1553
|
sendError(connection.socket, message.requestId, ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
@@ -1477,4 +1662,4 @@ export {
|
|
|
1477
1662
|
handleConnection
|
|
1478
1663
|
};
|
|
1479
1664
|
|
|
1480
|
-
//# debugId=
|
|
1665
|
+
//# debugId=EC4C1FF56C0445D064756E2164756E21
|