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