@ricsam/isolate 0.0.1 → 0.1.1
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 +243 -34
- package/dist/cjs/bridge/diagnostics.cjs +58 -0
- package/dist/cjs/bridge/diagnostics.cjs.map +10 -0
- package/dist/cjs/bridge/legacy-adapters.cjs +242 -0
- package/dist/cjs/bridge/legacy-adapters.cjs.map +10 -0
- package/dist/cjs/bridge/request-context.cjs +59 -0
- package/dist/cjs/bridge/request-context.cjs.map +10 -0
- package/dist/cjs/bridge/runtime-bindings.cjs +367 -0
- package/dist/cjs/bridge/runtime-bindings.cjs.map +10 -0
- package/dist/cjs/browser/browser-runtime.cjs +157 -0
- package/dist/cjs/browser/browser-runtime.cjs.map +10 -0
- package/dist/cjs/daemon.cjs +91 -0
- package/dist/cjs/daemon.cjs.map +10 -0
- package/dist/cjs/files/index.cjs +140 -0
- package/dist/cjs/files/index.cjs.map +10 -0
- package/dist/cjs/host/create-isolate-host.cjs +235 -0
- package/dist/cjs/host/create-isolate-host.cjs.map +10 -0
- package/dist/cjs/host/index.cjs +47 -0
- package/dist/cjs/host/index.cjs.map +10 -0
- package/dist/cjs/index.cjs +55 -0
- package/dist/cjs/index.cjs.map +10 -0
- package/dist/cjs/internal/client/connection.cjs +1919 -0
- package/dist/cjs/internal/client/connection.cjs.map +10 -0
- package/dist/cjs/internal/client/index.cjs +48 -0
- package/dist/cjs/internal/client/index.cjs.map +10 -0
- package/dist/cjs/internal/client/types.cjs +30 -0
- package/dist/cjs/internal/client/types.cjs.map +9 -0
- package/dist/cjs/internal/console/index.cjs +506 -0
- package/dist/cjs/internal/console/index.cjs.map +10 -0
- package/dist/cjs/internal/console/utils.cjs +70 -0
- package/dist/cjs/internal/console/utils.cjs.map +10 -0
- package/dist/cjs/internal/core/index.cjs +2745 -0
- package/dist/cjs/internal/core/index.cjs.map +10 -0
- package/dist/cjs/internal/crypto/index.cjs +470 -0
- package/dist/cjs/internal/crypto/index.cjs.map +10 -0
- package/dist/cjs/internal/daemon/callback-fs-handler.cjs +355 -0
- package/dist/cjs/internal/daemon/callback-fs-handler.cjs.map +10 -0
- package/dist/cjs/internal/daemon/connection.cjs +1952 -0
- package/dist/cjs/internal/daemon/connection.cjs.map +10 -0
- package/dist/cjs/internal/daemon/daemon.cjs +98 -0
- package/dist/cjs/internal/daemon/daemon.cjs.map +10 -0
- package/dist/cjs/internal/daemon/index.cjs +145 -0
- package/dist/cjs/internal/daemon/index.cjs.map +10 -0
- package/dist/cjs/internal/daemon/runtime-pool.cjs +106 -0
- package/dist/cjs/internal/daemon/runtime-pool.cjs.map +10 -0
- package/dist/cjs/internal/daemon/types.cjs +30 -0
- package/dist/cjs/internal/daemon/types.cjs.map +9 -0
- package/dist/cjs/internal/encoding/index.cjs +419 -0
- package/dist/cjs/internal/encoding/index.cjs.map +10 -0
- package/dist/cjs/internal/fetch/consistency/origins.cjs +598 -0
- package/dist/cjs/internal/fetch/consistency/origins.cjs.map +10 -0
- package/dist/cjs/internal/fetch/index.cjs +2640 -0
- package/dist/cjs/internal/fetch/index.cjs.map +10 -0
- package/dist/cjs/internal/fetch/stream-state.cjs +256 -0
- package/dist/cjs/internal/fetch/stream-state.cjs.map +10 -0
- package/dist/cjs/internal/fs/index.cjs +847 -0
- package/dist/cjs/internal/fs/index.cjs.map +10 -0
- package/dist/cjs/internal/fs/node-adapter.cjs +254 -0
- package/dist/cjs/internal/fs/node-adapter.cjs.map +10 -0
- package/dist/cjs/internal/module-loader/bundle.cjs +482 -0
- package/dist/cjs/internal/module-loader/bundle.cjs.map +10 -0
- package/dist/cjs/internal/module-loader/index.cjs +240 -0
- package/dist/cjs/internal/module-loader/index.cjs.map +10 -0
- package/dist/cjs/internal/module-loader/mappings.cjs +120 -0
- package/dist/cjs/internal/module-loader/mappings.cjs.map +10 -0
- package/dist/cjs/internal/module-loader/resolve.cjs +177 -0
- package/dist/cjs/internal/module-loader/resolve.cjs.map +10 -0
- package/dist/cjs/internal/module-loader/strip-types.cjs +236 -0
- package/dist/cjs/internal/module-loader/strip-types.cjs.map +10 -0
- package/dist/cjs/internal/path/index.cjs +503 -0
- package/dist/cjs/internal/path/index.cjs.map +10 -0
- package/dist/cjs/internal/playwright/client.cjs +49 -0
- package/dist/cjs/internal/playwright/client.cjs.map +10 -0
- package/dist/cjs/internal/playwright/handler.cjs +1416 -0
- package/dist/cjs/internal/playwright/handler.cjs.map +10 -0
- package/dist/cjs/internal/playwright/index.cjs +1289 -0
- package/dist/cjs/internal/playwright/index.cjs.map +10 -0
- package/dist/cjs/internal/playwright/types.cjs +47 -0
- package/dist/cjs/internal/playwright/types.cjs.map +10 -0
- package/dist/cjs/internal/protocol/codec.cjs +510 -0
- package/dist/cjs/internal/protocol/codec.cjs.map +10 -0
- package/dist/cjs/internal/protocol/framing.cjs +141 -0
- package/dist/cjs/internal/protocol/framing.cjs.map +10 -0
- package/dist/cjs/internal/protocol/index.cjs +110 -0
- package/dist/cjs/internal/protocol/index.cjs.map +10 -0
- package/dist/cjs/internal/protocol/marshalValue.cjs +518 -0
- package/dist/cjs/internal/protocol/marshalValue.cjs.map +10 -0
- package/dist/cjs/internal/protocol/serialization.cjs +109 -0
- package/dist/cjs/internal/protocol/serialization.cjs.map +10 -0
- package/dist/cjs/internal/protocol/types.cjs +181 -0
- package/dist/cjs/internal/protocol/types.cjs.map +10 -0
- package/dist/cjs/internal/runtime/index.cjs +1235 -0
- package/dist/cjs/internal/runtime/index.cjs.map +10 -0
- package/dist/cjs/internal/server/index.cjs +223 -0
- package/dist/cjs/internal/server/index.cjs.map +10 -0
- package/dist/cjs/internal/test-environment/index.cjs +1415 -0
- package/dist/cjs/internal/test-environment/index.cjs.map +10 -0
- package/dist/cjs/internal/timers/index.cjs +200 -0
- package/dist/cjs/internal/timers/index.cjs.map +10 -0
- package/dist/cjs/internal/transform/index.cjs +361 -0
- package/dist/cjs/internal/transform/index.cjs.map +10 -0
- package/dist/cjs/internal/typecheck/index.cjs +60 -0
- package/dist/cjs/internal/typecheck/index.cjs.map +10 -0
- package/dist/cjs/internal/typecheck/isolate-types.cjs +2614 -0
- package/dist/cjs/internal/typecheck/isolate-types.cjs.map +10 -0
- package/dist/cjs/internal/typecheck/typecheck.cjs +131 -0
- package/dist/cjs/internal/typecheck/typecheck.cjs.map +10 -0
- package/dist/cjs/modules/index.cjs +160 -0
- package/dist/cjs/modules/index.cjs.map +10 -0
- package/dist/cjs/package.json +5 -0
- package/dist/cjs/runtime/script-runtime.cjs +97 -0
- package/dist/cjs/runtime/script-runtime.cjs.map +10 -0
- package/dist/cjs/server/app-server.cjs +158 -0
- package/dist/cjs/server/app-server.cjs.map +10 -0
- package/dist/cjs/testing/integration-helpers.cjs +127 -0
- package/dist/cjs/testing/integration-helpers.cjs.map +10 -0
- package/dist/cjs/typecheck/index.cjs +96 -0
- package/dist/cjs/typecheck/index.cjs.map +10 -0
- package/dist/cjs/types.cjs +30 -0
- package/dist/cjs/types.cjs.map +9 -0
- package/dist/mjs/bridge/diagnostics.mjs +18 -0
- package/dist/mjs/bridge/diagnostics.mjs.map +10 -0
- package/dist/mjs/bridge/legacy-adapters.mjs +178 -0
- package/dist/mjs/bridge/legacy-adapters.mjs.map +10 -0
- package/dist/mjs/bridge/request-context.mjs +19 -0
- package/dist/mjs/bridge/request-context.mjs.map +10 -0
- package/dist/mjs/bridge/runtime-bindings.mjs +303 -0
- package/dist/mjs/bridge/runtime-bindings.mjs.map +10 -0
- package/dist/mjs/browser/browser-runtime.mjs +93 -0
- package/dist/mjs/browser/browser-runtime.mjs.map +10 -0
- package/dist/mjs/daemon.mjs +91 -0
- package/dist/mjs/daemon.mjs.map +10 -0
- package/dist/mjs/files/index.mjs +76 -0
- package/dist/mjs/files/index.mjs.map +10 -0
- package/dist/mjs/host/create-isolate-host.mjs +171 -0
- package/dist/mjs/host/create-isolate-host.mjs.map +10 -0
- package/dist/mjs/host/index.mjs +7 -0
- package/dist/mjs/host/index.mjs.map +10 -0
- package/dist/mjs/index.mjs +15 -0
- package/dist/mjs/index.mjs.map +10 -0
- package/dist/mjs/internal/client/connection.mjs +1872 -0
- package/dist/mjs/internal/client/connection.mjs.map +10 -0
- package/dist/mjs/internal/client/index.mjs +8 -0
- package/dist/mjs/internal/client/index.mjs.map +10 -0
- package/dist/mjs/internal/client/types.mjs +2 -0
- package/dist/mjs/internal/client/types.mjs.map +9 -0
- package/dist/mjs/internal/console/index.mjs +442 -0
- package/dist/mjs/internal/console/index.mjs.map +10 -0
- package/dist/mjs/internal/console/utils.mjs +30 -0
- package/dist/mjs/internal/console/utils.mjs.map +10 -0
- package/dist/mjs/internal/core/index.mjs +2681 -0
- package/dist/mjs/internal/core/index.mjs.map +10 -0
- package/dist/mjs/internal/crypto/index.mjs +406 -0
- package/dist/mjs/internal/crypto/index.mjs.map +10 -0
- package/dist/mjs/internal/daemon/callback-fs-handler.mjs +315 -0
- package/dist/mjs/internal/daemon/callback-fs-handler.mjs.map +10 -0
- package/dist/mjs/internal/daemon/connection.mjs +1931 -0
- package/dist/mjs/internal/daemon/connection.mjs.map +10 -0
- package/dist/mjs/internal/daemon/daemon.mjs +98 -0
- package/dist/mjs/internal/daemon/daemon.mjs.map +10 -0
- package/dist/mjs/internal/daemon/index.mjs +105 -0
- package/dist/mjs/internal/daemon/index.mjs.map +10 -0
- package/dist/mjs/internal/daemon/runtime-pool.mjs +66 -0
- package/dist/mjs/internal/daemon/runtime-pool.mjs.map +10 -0
- package/dist/mjs/internal/daemon/types.mjs +2 -0
- package/dist/mjs/internal/daemon/types.mjs.map +9 -0
- package/dist/mjs/internal/encoding/index.mjs +379 -0
- package/dist/mjs/internal/encoding/index.mjs.map +10 -0
- package/dist/mjs/internal/fetch/consistency/origins.mjs +558 -0
- package/dist/mjs/internal/fetch/consistency/origins.mjs.map +10 -0
- package/dist/mjs/internal/fetch/index.mjs +2580 -0
- package/dist/mjs/internal/fetch/index.mjs.map +10 -0
- package/dist/mjs/internal/fetch/stream-state.mjs +216 -0
- package/dist/mjs/internal/fetch/stream-state.mjs.map +10 -0
- package/dist/mjs/internal/fs/index.mjs +783 -0
- package/dist/mjs/internal/fs/index.mjs.map +10 -0
- package/dist/mjs/internal/fs/node-adapter.mjs +190 -0
- package/dist/mjs/internal/fs/node-adapter.mjs.map +10 -0
- package/dist/mjs/internal/module-loader/bundle.mjs +418 -0
- package/dist/mjs/internal/module-loader/bundle.mjs.map +10 -0
- package/dist/mjs/internal/module-loader/index.mjs +185 -0
- package/dist/mjs/internal/module-loader/index.mjs.map +10 -0
- package/dist/mjs/internal/module-loader/mappings.mjs +80 -0
- package/dist/mjs/internal/module-loader/mappings.mjs.map +10 -0
- package/dist/mjs/internal/module-loader/resolve.mjs +113 -0
- package/dist/mjs/internal/module-loader/resolve.mjs.map +10 -0
- package/dist/mjs/internal/module-loader/strip-types.mjs +172 -0
- package/dist/mjs/internal/module-loader/strip-types.mjs.map +10 -0
- package/dist/mjs/internal/path/index.mjs +463 -0
- package/dist/mjs/internal/path/index.mjs.map +10 -0
- package/dist/mjs/internal/playwright/client.mjs +13 -0
- package/dist/mjs/internal/playwright/client.mjs.map +10 -0
- package/dist/mjs/internal/playwright/handler.mjs +1378 -0
- package/dist/mjs/internal/playwright/handler.mjs.map +10 -0
- package/dist/mjs/internal/playwright/index.mjs +1234 -0
- package/dist/mjs/internal/playwright/index.mjs.map +10 -0
- package/dist/mjs/internal/playwright/types.mjs +7 -0
- package/dist/mjs/internal/playwright/types.mjs.map +10 -0
- package/dist/mjs/internal/protocol/codec.mjs +470 -0
- package/dist/mjs/internal/protocol/codec.mjs.map +10 -0
- package/dist/mjs/internal/protocol/framing.mjs +101 -0
- package/dist/mjs/internal/protocol/framing.mjs.map +10 -0
- package/dist/mjs/internal/protocol/index.mjs +98 -0
- package/dist/mjs/internal/protocol/index.mjs.map +10 -0
- package/dist/mjs/internal/protocol/marshalValue.mjs +494 -0
- package/dist/mjs/internal/protocol/marshalValue.mjs.map +10 -0
- package/dist/mjs/internal/protocol/serialization.mjs +69 -0
- package/dist/mjs/internal/protocol/serialization.mjs.map +10 -0
- package/dist/mjs/internal/protocol/types.mjs +141 -0
- package/dist/mjs/internal/protocol/types.mjs.map +10 -0
- package/dist/mjs/internal/runtime/index.mjs +1198 -0
- package/dist/mjs/internal/runtime/index.mjs.map +10 -0
- package/dist/mjs/internal/server/index.mjs +183 -0
- package/dist/mjs/internal/server/index.mjs.map +10 -0
- package/dist/mjs/internal/test-environment/index.mjs +1351 -0
- package/dist/mjs/internal/test-environment/index.mjs.map +10 -0
- package/dist/mjs/internal/timers/index.mjs +136 -0
- package/dist/mjs/internal/timers/index.mjs.map +10 -0
- package/dist/mjs/internal/transform/index.mjs +321 -0
- package/dist/mjs/internal/transform/index.mjs.map +10 -0
- package/dist/mjs/internal/typecheck/index.mjs +35 -0
- package/dist/mjs/internal/typecheck/index.mjs.map +10 -0
- package/dist/mjs/internal/typecheck/isolate-types.mjs +2574 -0
- package/dist/mjs/internal/typecheck/isolate-types.mjs.map +10 -0
- package/dist/mjs/internal/typecheck/typecheck.mjs +91 -0
- package/dist/mjs/internal/typecheck/typecheck.mjs.map +10 -0
- package/dist/mjs/modules/index.mjs +96 -0
- package/dist/mjs/modules/index.mjs.map +10 -0
- package/dist/mjs/package.json +5 -0
- package/dist/mjs/runtime/script-runtime.mjs +57 -0
- package/dist/mjs/runtime/script-runtime.mjs.map +10 -0
- package/dist/mjs/server/app-server.mjs +118 -0
- package/dist/mjs/server/app-server.mjs.map +10 -0
- package/dist/mjs/testing/integration-helpers.mjs +63 -0
- package/dist/mjs/testing/integration-helpers.mjs.map +10 -0
- package/dist/mjs/typecheck/index.mjs +56 -0
- package/dist/mjs/typecheck/index.mjs.map +10 -0
- package/dist/mjs/types.mjs +2 -0
- package/dist/mjs/types.mjs.map +9 -0
- package/dist/types/bridge/diagnostics.d.ts +12 -0
- package/dist/types/bridge/legacy-adapters.d.ts +14 -0
- package/dist/types/bridge/request-context.d.ts +10 -0
- package/dist/types/bridge/runtime-bindings.d.ts +14 -0
- package/dist/types/browser/browser-runtime.d.ts +3 -0
- package/dist/types/daemon.d.ts +2 -0
- package/dist/types/files/index.d.ts +5 -0
- package/dist/types/host/create-isolate-host.d.ts +2 -0
- package/dist/types/host/index.d.ts +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/internal/client/connection.d.ts +9 -0
- package/dist/types/internal/client/index.d.ts +8 -0
- package/dist/types/internal/client/types.d.ts +198 -0
- package/dist/types/internal/console/index.d.ts +108 -0
- package/dist/types/internal/console/utils.d.ts +27 -0
- package/dist/types/internal/core/index.d.ts +119 -0
- package/dist/types/internal/crypto/index.d.ts +18 -0
- package/dist/types/internal/daemon/callback-fs-handler.d.ts +28 -0
- package/dist/types/internal/daemon/connection.d.ts +9 -0
- package/dist/types/internal/daemon/daemon.d.ts +2 -0
- package/dist/types/internal/daemon/index.d.ts +14 -0
- package/dist/types/internal/daemon/runtime-pool.d.ts +16 -0
- package/dist/types/internal/daemon/types.d.ts +211 -0
- package/dist/types/internal/encoding/index.d.ts +21 -0
- package/dist/types/internal/fetch/consistency/origins.d.ts +179 -0
- package/dist/types/internal/fetch/index.d.ts +93 -0
- package/dist/types/internal/fetch/stream-state.d.ts +65 -0
- package/dist/types/internal/fs/index.d.ts +70 -0
- package/dist/types/internal/fs/node-adapter.d.ts +24 -0
- package/dist/types/internal/module-loader/bundle.d.ts +33 -0
- package/dist/types/internal/module-loader/index.d.ts +30 -0
- package/dist/types/internal/module-loader/mappings.d.ts +47 -0
- package/dist/types/internal/module-loader/resolve.d.ts +26 -0
- package/dist/types/internal/module-loader/strip-types.d.ts +19 -0
- package/dist/types/internal/path/index.d.ts +23 -0
- package/dist/types/internal/playwright/client.d.ts +7 -0
- package/dist/types/internal/playwright/handler.d.ts +44 -0
- package/dist/types/internal/playwright/index.d.ts +14 -0
- package/dist/types/internal/playwright/types.d.ts +145 -0
- package/dist/types/internal/protocol/codec.d.ts +242 -0
- package/dist/types/internal/protocol/framing.d.ts +89 -0
- package/dist/types/internal/protocol/index.d.ts +10 -0
- package/dist/types/internal/protocol/marshalValue.d.ts +79 -0
- package/dist/types/internal/protocol/serialization.d.ts +23 -0
- package/dist/types/internal/protocol/types.d.ts +996 -0
- package/dist/types/internal/runtime/index.d.ts +200 -0
- package/dist/types/internal/server/index.d.ts +42 -0
- package/dist/types/internal/test-environment/index.d.ts +112 -0
- package/dist/types/internal/timers/index.d.ts +22 -0
- package/dist/types/internal/transform/index.d.ts +36 -0
- package/dist/types/internal/typecheck/index.d.ts +7 -0
- package/dist/types/internal/typecheck/isolate-types.d.ts +94 -0
- package/dist/types/internal/typecheck/typecheck.d.ts +148 -0
- package/dist/types/modules/index.d.ts +2 -0
- package/dist/types/runtime/script-runtime.d.ts +6 -0
- package/dist/types/server/app-server.d.ts +3 -0
- package/dist/types/testing/integration-helpers.d.ts +9 -0
- package/dist/types/typecheck/index.d.ts +8 -0
- package/dist/types/types.d.ts +233 -0
- package/package.json +82 -6
|
@@ -0,0 +1,1952 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
function __accessProp(key) {
|
|
6
|
+
return this[key];
|
|
7
|
+
}
|
|
8
|
+
var __toCommonJS = (from) => {
|
|
9
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
10
|
+
if (entry)
|
|
11
|
+
return entry;
|
|
12
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (var key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(entry, key))
|
|
16
|
+
__defProp(entry, key, {
|
|
17
|
+
get: __accessProp.bind(from, key),
|
|
18
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
__moduleCache.set(from, entry);
|
|
22
|
+
return entry;
|
|
23
|
+
};
|
|
24
|
+
var __moduleCache;
|
|
25
|
+
var __returnValue = (v) => v;
|
|
26
|
+
function __exportSetter(name, newValue) {
|
|
27
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
28
|
+
}
|
|
29
|
+
var __export = (target, all) => {
|
|
30
|
+
for (var name in all)
|
|
31
|
+
__defProp(target, name, {
|
|
32
|
+
get: all[name],
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
set: __exportSetter.bind(all, name)
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// src/internal/daemon/connection.ts
|
|
40
|
+
var exports_connection = {};
|
|
41
|
+
__export(exports_connection, {
|
|
42
|
+
handleConnection: () => handleConnection
|
|
43
|
+
});
|
|
44
|
+
module.exports = __toCommonJS(exports_connection);
|
|
45
|
+
var import_node_async_hooks = require("node:async_hooks");
|
|
46
|
+
var import_node_crypto = require("node:crypto");
|
|
47
|
+
var import_protocol = require("../protocol/index.cjs");
|
|
48
|
+
var import_callback_fs_handler = require("./callback-fs-handler.cjs");
|
|
49
|
+
var import_runtime = require("../runtime/index.cjs");
|
|
50
|
+
var import_runtime_pool = require("./runtime-pool.cjs");
|
|
51
|
+
var LINKER_CONFLICT_ERROR = "Module is currently being linked by another linker";
|
|
52
|
+
var NULL_BODY_STATUSES = new Set([101, 103, 204, 205, 304]);
|
|
53
|
+
var DEFAULT_CALLBACK_TIMEOUT_MS = 120000;
|
|
54
|
+
var FETCH_CALLBACK_TIMEOUT_MS = 35000;
|
|
55
|
+
var requestContextStorage = new import_node_async_hooks.AsyncLocalStorage;
|
|
56
|
+
function createAbortError(reason = "The operation was aborted") {
|
|
57
|
+
if (typeof DOMException !== "undefined") {
|
|
58
|
+
return new DOMException(reason, "AbortError");
|
|
59
|
+
}
|
|
60
|
+
const error = new Error(reason);
|
|
61
|
+
error.name = "AbortError";
|
|
62
|
+
return error;
|
|
63
|
+
}
|
|
64
|
+
function sendCallbackAbortMessage(connection, targetRequestId, reason) {
|
|
65
|
+
const abortMessage = {
|
|
66
|
+
type: import_protocol.MessageType.CALLBACK_ABORT,
|
|
67
|
+
requestId: connection.nextRequestId++,
|
|
68
|
+
targetRequestId,
|
|
69
|
+
reason
|
|
70
|
+
};
|
|
71
|
+
sendMessage(connection.socket, abortMessage);
|
|
72
|
+
}
|
|
73
|
+
function getErrorText(error) {
|
|
74
|
+
if (error instanceof Error) {
|
|
75
|
+
const cause = error.cause;
|
|
76
|
+
const causeText = cause instanceof Error ? `${cause.name}: ${cause.message}
|
|
77
|
+
${cause.stack ?? ""}` : cause != null ? String(cause) : "";
|
|
78
|
+
return [error.name, error.message, error.stack, causeText].filter((part) => part != null && part !== "").join(`
|
|
79
|
+
`);
|
|
80
|
+
}
|
|
81
|
+
if (typeof error === "string") {
|
|
82
|
+
return error;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
return JSON.stringify(error);
|
|
86
|
+
} catch {
|
|
87
|
+
return String(error ?? "");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function isLinkerConflictError(error) {
|
|
91
|
+
const text = getErrorText(error).toLowerCase();
|
|
92
|
+
return text.includes(LINKER_CONFLICT_ERROR.toLowerCase());
|
|
93
|
+
}
|
|
94
|
+
function isRuntimeTimeoutError(error) {
|
|
95
|
+
return error instanceof Error && /^(Execution|Test) timed out after \d+ms$/i.test(error.message);
|
|
96
|
+
}
|
|
97
|
+
function handleConnection(socket, state) {
|
|
98
|
+
const connection = {
|
|
99
|
+
socket,
|
|
100
|
+
isolates: new Set,
|
|
101
|
+
pendingRequests: new Map,
|
|
102
|
+
pendingCallbacks: new Map,
|
|
103
|
+
nextRequestId: 1,
|
|
104
|
+
nextCallbackId: 1,
|
|
105
|
+
nextStreamId: 1,
|
|
106
|
+
activeStreams: new Map,
|
|
107
|
+
streamReceivers: new Map,
|
|
108
|
+
callbackStreamReceivers: new Map,
|
|
109
|
+
dispatchAbortControllers: new Map,
|
|
110
|
+
earlyAbortedDispatches: new Set
|
|
111
|
+
};
|
|
112
|
+
state.connections.set(socket, connection);
|
|
113
|
+
const parser = import_protocol.createFrameParser();
|
|
114
|
+
socket.on("data", (data) => {
|
|
115
|
+
try {
|
|
116
|
+
for (const frame of parser.feed(new Uint8Array(data))) {
|
|
117
|
+
handleMessage(frame.message, connection, state).catch((err) => {
|
|
118
|
+
console.error("Error handling message:", err);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
} catch (err) {
|
|
122
|
+
console.error("Error parsing frame:", err);
|
|
123
|
+
socket.destroy();
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
socket.on("close", () => {
|
|
127
|
+
for (const streamId of Array.from(connection.activeStreams.keys())) {
|
|
128
|
+
closeActiveDownloadSession(connection, streamId);
|
|
129
|
+
}
|
|
130
|
+
for (const [, controller] of connection.dispatchAbortControllers) {
|
|
131
|
+
controller.abort();
|
|
132
|
+
}
|
|
133
|
+
connection.dispatchAbortControllers.clear();
|
|
134
|
+
connection.earlyAbortedDispatches.clear();
|
|
135
|
+
for (const isolateId of connection.isolates) {
|
|
136
|
+
const instance = state.isolates.get(isolateId);
|
|
137
|
+
if (instance) {
|
|
138
|
+
if (instance.namespaceId != null && !instance.isDisposed) {
|
|
139
|
+
if (instance.isPoisoned) {
|
|
140
|
+
hardDeleteRuntime(instance, state, "owner connection closed after runtime was poisoned").catch(() => {});
|
|
141
|
+
} else {
|
|
142
|
+
softDeleteRuntime(instance, state, "owner connection closed; preserving namespaced runtime for reuse");
|
|
143
|
+
}
|
|
144
|
+
} else if (!instance.isDisposed) {
|
|
145
|
+
hardDeleteRuntime(instance, state, "owner connection closed for non-namespaced runtime").catch(() => {});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
for (const [, pending] of connection.pendingCallbacks) {
|
|
150
|
+
pending.cleanup?.();
|
|
151
|
+
pending.reject(new Error("Connection closed"));
|
|
152
|
+
}
|
|
153
|
+
connection.pendingCallbacks.clear();
|
|
154
|
+
state.connections.delete(socket);
|
|
155
|
+
});
|
|
156
|
+
socket.on("error", (err) => {
|
|
157
|
+
console.error("Socket error:", err);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
function sendMessage(socket, message) {
|
|
161
|
+
const frame = import_protocol.buildFrame(message);
|
|
162
|
+
socket.write(frame);
|
|
163
|
+
}
|
|
164
|
+
function closeActiveDownloadSession(connection, streamId) {
|
|
165
|
+
const session = connection.activeStreams.get(streamId);
|
|
166
|
+
if (!session) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
session.state = "closed";
|
|
170
|
+
if (session.creditResolver) {
|
|
171
|
+
session.creditResolver();
|
|
172
|
+
session.creditResolver = undefined;
|
|
173
|
+
}
|
|
174
|
+
if (session.cancelReader) {
|
|
175
|
+
session.cancelReader();
|
|
176
|
+
session.cancelReader = undefined;
|
|
177
|
+
}
|
|
178
|
+
connection.activeStreams.delete(streamId);
|
|
179
|
+
}
|
|
180
|
+
function sendError(socket, requestId, code, message, details) {
|
|
181
|
+
const response = {
|
|
182
|
+
type: import_protocol.MessageType.RESPONSE_ERROR,
|
|
183
|
+
requestId,
|
|
184
|
+
code,
|
|
185
|
+
message,
|
|
186
|
+
details
|
|
187
|
+
};
|
|
188
|
+
sendMessage(socket, response);
|
|
189
|
+
}
|
|
190
|
+
function sendOk(socket, requestId, data) {
|
|
191
|
+
const response = {
|
|
192
|
+
type: import_protocol.MessageType.RESPONSE_OK,
|
|
193
|
+
requestId,
|
|
194
|
+
data
|
|
195
|
+
};
|
|
196
|
+
sendMessage(socket, response);
|
|
197
|
+
}
|
|
198
|
+
async function handleMessage(message, connection, state) {
|
|
199
|
+
state.stats.totalRequestsProcessed++;
|
|
200
|
+
switch (message.type) {
|
|
201
|
+
case import_protocol.MessageType.CREATE_RUNTIME:
|
|
202
|
+
await handleCreateRuntime(message, connection, state);
|
|
203
|
+
break;
|
|
204
|
+
case import_protocol.MessageType.DISPOSE_RUNTIME:
|
|
205
|
+
await handleDisposeRuntime(message, connection, state);
|
|
206
|
+
break;
|
|
207
|
+
case import_protocol.MessageType.EVAL:
|
|
208
|
+
await handleEval(message, connection, state);
|
|
209
|
+
break;
|
|
210
|
+
case import_protocol.MessageType.DISPATCH_REQUEST:
|
|
211
|
+
await handleDispatchRequest(message, connection, state);
|
|
212
|
+
break;
|
|
213
|
+
case import_protocol.MessageType.DISPATCH_REQUEST_ABORT:
|
|
214
|
+
handleDispatchRequestAbort(message, connection);
|
|
215
|
+
break;
|
|
216
|
+
case import_protocol.MessageType.CALLBACK_RESPONSE:
|
|
217
|
+
handleCallbackResponse(message, connection);
|
|
218
|
+
break;
|
|
219
|
+
case import_protocol.MessageType.WS_OPEN:
|
|
220
|
+
await handleWsOpen(message, connection, state);
|
|
221
|
+
break;
|
|
222
|
+
case import_protocol.MessageType.WS_MESSAGE:
|
|
223
|
+
await handleWsMessage(message, connection, state);
|
|
224
|
+
break;
|
|
225
|
+
case import_protocol.MessageType.WS_CLOSE:
|
|
226
|
+
await handleWsClose(message, connection, state);
|
|
227
|
+
break;
|
|
228
|
+
case import_protocol.MessageType.FETCH_GET_UPGRADE_REQUEST:
|
|
229
|
+
await handleFetchGetUpgradeRequest(message, connection, state);
|
|
230
|
+
break;
|
|
231
|
+
case import_protocol.MessageType.FETCH_HAS_SERVE_HANDLER:
|
|
232
|
+
await handleFetchHasServeHandler(message, connection, state);
|
|
233
|
+
break;
|
|
234
|
+
case import_protocol.MessageType.FETCH_HAS_ACTIVE_CONNECTIONS:
|
|
235
|
+
await handleFetchHasActiveConnections(message, connection, state);
|
|
236
|
+
break;
|
|
237
|
+
case import_protocol.MessageType.FETCH_WS_ERROR:
|
|
238
|
+
await handleFetchWsError(message, connection, state);
|
|
239
|
+
break;
|
|
240
|
+
case import_protocol.MessageType.TIMERS_CLEAR_ALL:
|
|
241
|
+
await handleTimersClearAll(message, connection, state);
|
|
242
|
+
break;
|
|
243
|
+
case import_protocol.MessageType.CONSOLE_RESET:
|
|
244
|
+
await handleConsoleReset(message, connection, state);
|
|
245
|
+
break;
|
|
246
|
+
case import_protocol.MessageType.CONSOLE_GET_TIMERS:
|
|
247
|
+
await handleConsoleGetTimers(message, connection, state);
|
|
248
|
+
break;
|
|
249
|
+
case import_protocol.MessageType.CONSOLE_GET_COUNTERS:
|
|
250
|
+
await handleConsoleGetCounters(message, connection, state);
|
|
251
|
+
break;
|
|
252
|
+
case import_protocol.MessageType.CONSOLE_GET_GROUP_DEPTH:
|
|
253
|
+
await handleConsoleGetGroupDepth(message, connection, state);
|
|
254
|
+
break;
|
|
255
|
+
case import_protocol.MessageType.RUN_TESTS:
|
|
256
|
+
await handleRunTests(message, connection, state);
|
|
257
|
+
break;
|
|
258
|
+
case import_protocol.MessageType.RESET_TEST_ENV:
|
|
259
|
+
await handleResetTestEnv(message, connection, state);
|
|
260
|
+
break;
|
|
261
|
+
case import_protocol.MessageType.HAS_TESTS:
|
|
262
|
+
await handleHasTests(message, connection, state);
|
|
263
|
+
break;
|
|
264
|
+
case import_protocol.MessageType.GET_TEST_COUNT:
|
|
265
|
+
await handleGetTestCount(message, connection, state);
|
|
266
|
+
break;
|
|
267
|
+
case import_protocol.MessageType.GET_COLLECTED_DATA:
|
|
268
|
+
await handleGetCollectedData(message, connection, state);
|
|
269
|
+
break;
|
|
270
|
+
case import_protocol.MessageType.CLEAR_COLLECTED_DATA:
|
|
271
|
+
await handleClearCollectedData(message, connection, state);
|
|
272
|
+
break;
|
|
273
|
+
case import_protocol.MessageType.PING:
|
|
274
|
+
sendMessage(connection.socket, { type: import_protocol.MessageType.PONG });
|
|
275
|
+
break;
|
|
276
|
+
case import_protocol.MessageType.STREAM_PUSH:
|
|
277
|
+
handleStreamPush(message, connection);
|
|
278
|
+
break;
|
|
279
|
+
case import_protocol.MessageType.STREAM_PULL:
|
|
280
|
+
handleStreamPull(message, connection);
|
|
281
|
+
break;
|
|
282
|
+
case import_protocol.MessageType.STREAM_CLOSE:
|
|
283
|
+
handleStreamClose(message, connection);
|
|
284
|
+
break;
|
|
285
|
+
case import_protocol.MessageType.STREAM_ERROR:
|
|
286
|
+
handleStreamError(message, connection);
|
|
287
|
+
break;
|
|
288
|
+
case import_protocol.MessageType.CALLBACK_STREAM_START:
|
|
289
|
+
handleCallbackStreamStart(message, connection);
|
|
290
|
+
break;
|
|
291
|
+
case import_protocol.MessageType.CALLBACK_STREAM_CHUNK:
|
|
292
|
+
handleCallbackStreamChunk(message, connection);
|
|
293
|
+
break;
|
|
294
|
+
case import_protocol.MessageType.CALLBACK_STREAM_END:
|
|
295
|
+
handleCallbackStreamEnd(message, connection);
|
|
296
|
+
break;
|
|
297
|
+
case import_protocol.MessageType.CLIENT_EVENT:
|
|
298
|
+
handleClientEvent(message, connection, state);
|
|
299
|
+
break;
|
|
300
|
+
default:
|
|
301
|
+
sendError(connection.socket, message.requestId ?? 0, import_protocol.ErrorCode.UNKNOWN_MESSAGE_TYPE, `Unknown message type: ${message.type}`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function logRuntimeLifecycle(state, event, instance, reason, level = "log") {
|
|
305
|
+
const logger = level === "warn" ? console.warn : console.log;
|
|
306
|
+
const poisonedSuffix = instance.isPoisoned ? " poisoned=true" : "";
|
|
307
|
+
const reasonSuffix = reason ? `: ${reason}` : "";
|
|
308
|
+
logger(`[isolate-daemon] ${event} runtime ${import_runtime_pool.formatRuntimeLabel(instance)}${poisonedSuffix}${reasonSuffix}; ${import_runtime_pool.formatRuntimePoolSnapshot(import_runtime_pool.collectRuntimePoolSnapshot(state))}`);
|
|
309
|
+
}
|
|
310
|
+
async function hardDeleteRuntime(instance, state, reason) {
|
|
311
|
+
const wasPooled = instance.isDisposed;
|
|
312
|
+
try {
|
|
313
|
+
if (instance.runtimeAbortController && !instance.runtimeAbortController.signal.aborted) {
|
|
314
|
+
instance.runtimeAbortController.abort(new Error(reason ?? "Runtime was permanently disposed"));
|
|
315
|
+
}
|
|
316
|
+
await instance.runtime.dispose();
|
|
317
|
+
} finally {
|
|
318
|
+
state.isolates.delete(instance.isolateId);
|
|
319
|
+
if (instance.namespaceId != null) {
|
|
320
|
+
const indexed = state.namespacedRuntimes.get(instance.namespaceId);
|
|
321
|
+
if (indexed?.isolateId === instance.isolateId) {
|
|
322
|
+
state.namespacedRuntimes.delete(instance.namespaceId);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
instance.isDisposed = true;
|
|
326
|
+
instance.disposedAt = undefined;
|
|
327
|
+
instance.ownerConnection = null;
|
|
328
|
+
if (instance.callbackContext) {
|
|
329
|
+
if (instance.callbackContext.reconnectionPromise) {
|
|
330
|
+
clearTimeout(instance.callbackContext.reconnectionPromise.timeoutId);
|
|
331
|
+
instance.callbackContext.reconnectionPromise.promise.catch(() => {});
|
|
332
|
+
instance.callbackContext.reconnectionPromise.reject(new Error("Runtime was permanently disposed"));
|
|
333
|
+
instance.callbackContext.reconnectionPromise = undefined;
|
|
334
|
+
}
|
|
335
|
+
instance.callbackContext.connection = null;
|
|
336
|
+
}
|
|
337
|
+
logRuntimeLifecycle(state, wasPooled ? "evicted pooled" : "hard-disposed", instance, reason);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
var RECONNECTION_TIMEOUT_MS = 30000;
|
|
341
|
+
function softDeleteRuntime(instance, state, reason) {
|
|
342
|
+
if (instance.runtimeAbortController && !instance.runtimeAbortController.signal.aborted) {
|
|
343
|
+
instance.runtimeAbortController.abort(new Error(reason ?? "Runtime was soft-disposed"));
|
|
344
|
+
}
|
|
345
|
+
instance.isDisposed = true;
|
|
346
|
+
instance.disposedAt = Date.now();
|
|
347
|
+
instance.ownerConnection = null;
|
|
348
|
+
if (instance.callbackContext) {
|
|
349
|
+
instance.callbackContext.connection = null;
|
|
350
|
+
let resolve;
|
|
351
|
+
let reject;
|
|
352
|
+
const promise = new Promise((res, rej) => {
|
|
353
|
+
resolve = res;
|
|
354
|
+
reject = rej;
|
|
355
|
+
});
|
|
356
|
+
promise.catch(() => {});
|
|
357
|
+
const timeoutId = setTimeout(() => {
|
|
358
|
+
if (instance.callbackContext?.reconnectionPromise) {
|
|
359
|
+
instance.callbackContext.reconnectionPromise = undefined;
|
|
360
|
+
reject(new Error("Reconnection timeout: no client reconnected within timeout"));
|
|
361
|
+
}
|
|
362
|
+
}, RECONNECTION_TIMEOUT_MS);
|
|
363
|
+
instance.callbackContext.reconnectionPromise = {
|
|
364
|
+
promise,
|
|
365
|
+
resolve,
|
|
366
|
+
reject,
|
|
367
|
+
timeoutId
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
instance.callbacks.clear();
|
|
371
|
+
instance.runtime.timers.clearAll();
|
|
372
|
+
instance.runtime.console.reset();
|
|
373
|
+
instance.runtime.pendingCallbacks.length = 0;
|
|
374
|
+
instance.returnedCallbacks?.clear();
|
|
375
|
+
instance.returnedPromises?.clear();
|
|
376
|
+
instance.returnedIterators?.clear();
|
|
377
|
+
instance.runtime.clearModuleCache();
|
|
378
|
+
logRuntimeLifecycle(state, "soft-disposed", instance, reason);
|
|
379
|
+
}
|
|
380
|
+
function reuseNamespacedRuntime(instance, connection, message, state) {
|
|
381
|
+
instance.ownerConnection = connection.socket;
|
|
382
|
+
instance.isDisposed = false;
|
|
383
|
+
instance.isPoisoned = false;
|
|
384
|
+
instance.disposedAt = undefined;
|
|
385
|
+
instance.lastActivity = Date.now();
|
|
386
|
+
instance.runtimeAbortController = new AbortController;
|
|
387
|
+
connection.isolates.add(instance.isolateId);
|
|
388
|
+
const callbacks = message.options.callbacks;
|
|
389
|
+
const testEnvOptions = message.options.testEnvironment != null && typeof message.options.testEnvironment === "object" ? message.options.testEnvironment : undefined;
|
|
390
|
+
if (instance.callbackContext) {
|
|
391
|
+
instance.callbackContext.connection = connection;
|
|
392
|
+
if (instance.callbackContext.reconnectionPromise) {
|
|
393
|
+
clearTimeout(instance.callbackContext.reconnectionPromise.timeoutId);
|
|
394
|
+
instance.callbackContext.reconnectionPromise.resolve(connection);
|
|
395
|
+
instance.callbackContext.reconnectionPromise = undefined;
|
|
396
|
+
}
|
|
397
|
+
instance.callbackContext.consoleOnEntry = callbacks?.console?.onEntry?.callbackId;
|
|
398
|
+
instance.callbackContext.fetch = callbacks?.fetch?.callbackId;
|
|
399
|
+
instance.callbackContext.moduleLoader = callbacks?.moduleLoader?.callbackId;
|
|
400
|
+
instance.callbackContext.testEnvironmentOnEvent = testEnvOptions?.callbacks?.onEvent?.callbackId;
|
|
401
|
+
instance.callbackContext.playwright = {
|
|
402
|
+
handlerCallbackId: callbacks?.playwright?.handlerCallbackId,
|
|
403
|
+
onBrowserConsoleLogCallbackId: callbacks?.playwright?.onBrowserConsoleLogCallbackId,
|
|
404
|
+
onNetworkRequestCallbackId: callbacks?.playwright?.onNetworkRequestCallbackId,
|
|
405
|
+
onNetworkResponseCallbackId: callbacks?.playwright?.onNetworkResponseCallbackId
|
|
406
|
+
};
|
|
407
|
+
instance.callbackContext.fs = {
|
|
408
|
+
readFile: callbacks?.fs?.readFile?.callbackId,
|
|
409
|
+
writeFile: callbacks?.fs?.writeFile?.callbackId,
|
|
410
|
+
stat: callbacks?.fs?.stat?.callbackId,
|
|
411
|
+
readdir: callbacks?.fs?.readdir?.callbackId,
|
|
412
|
+
unlink: callbacks?.fs?.unlink?.callbackId,
|
|
413
|
+
mkdir: callbacks?.fs?.mkdir?.callbackId,
|
|
414
|
+
rmdir: callbacks?.fs?.rmdir?.callbackId
|
|
415
|
+
};
|
|
416
|
+
instance.callbackContext.custom.clear();
|
|
417
|
+
if (callbacks?.custom) {
|
|
418
|
+
for (const [name, reg] of Object.entries(callbacks.custom)) {
|
|
419
|
+
if (reg) {
|
|
420
|
+
instance.callbackContext.custom.set(name, reg.callbackId);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
instance.callbacks.clear();
|
|
426
|
+
if (callbacks?.console?.onEntry) {
|
|
427
|
+
instance.callbacks.set(callbacks.console.onEntry.callbackId, {
|
|
428
|
+
...callbacks.console.onEntry,
|
|
429
|
+
name: "onEntry"
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
if (callbacks?.fetch) {
|
|
433
|
+
instance.callbacks.set(callbacks.fetch.callbackId, callbacks.fetch);
|
|
434
|
+
}
|
|
435
|
+
if (callbacks?.fs) {
|
|
436
|
+
for (const [name, reg] of Object.entries(callbacks.fs)) {
|
|
437
|
+
if (reg) {
|
|
438
|
+
instance.callbacks.set(reg.callbackId, { ...reg, name });
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
if (callbacks?.moduleLoader) {
|
|
443
|
+
instance.callbacks.set(callbacks.moduleLoader.callbackId, callbacks.moduleLoader);
|
|
444
|
+
}
|
|
445
|
+
if (callbacks?.custom) {
|
|
446
|
+
for (const [name, reg] of Object.entries(callbacks.custom)) {
|
|
447
|
+
if (reg) {
|
|
448
|
+
instance.callbacks.set(reg.callbackId, { ...reg, name });
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
if (testEnvOptions?.callbacks?.onEvent) {
|
|
453
|
+
instance.callbacks.set(testEnvOptions.callbacks.onEvent.callbackId, {
|
|
454
|
+
...testEnvOptions.callbacks.onEvent,
|
|
455
|
+
name: "testEnvironment.onEvent"
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
if (callbacks?.playwright) {
|
|
459
|
+
instance.callbacks.set(callbacks.playwright.handlerCallbackId, {
|
|
460
|
+
callbackId: callbacks.playwright.handlerCallbackId,
|
|
461
|
+
name: "playwright.handler",
|
|
462
|
+
type: "async"
|
|
463
|
+
});
|
|
464
|
+
if (callbacks.playwright.onBrowserConsoleLogCallbackId !== undefined) {
|
|
465
|
+
instance.callbacks.set(callbacks.playwright.onBrowserConsoleLogCallbackId, {
|
|
466
|
+
callbackId: callbacks.playwright.onBrowserConsoleLogCallbackId,
|
|
467
|
+
name: "playwright.onBrowserConsoleLog",
|
|
468
|
+
type: "sync"
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
if (callbacks.playwright.onNetworkRequestCallbackId !== undefined) {
|
|
472
|
+
instance.callbacks.set(callbacks.playwright.onNetworkRequestCallbackId, {
|
|
473
|
+
callbackId: callbacks.playwright.onNetworkRequestCallbackId,
|
|
474
|
+
name: "playwright.onNetworkRequest",
|
|
475
|
+
type: "sync"
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
if (callbacks.playwright.onNetworkResponseCallbackId !== undefined) {
|
|
479
|
+
instance.callbacks.set(callbacks.playwright.onNetworkResponseCallbackId, {
|
|
480
|
+
callbackId: callbacks.playwright.onNetworkResponseCallbackId,
|
|
481
|
+
name: "playwright.onNetworkResponse",
|
|
482
|
+
type: "sync"
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
instance.returnedCallbacks = new Map;
|
|
487
|
+
instance.returnedPromises = new Map;
|
|
488
|
+
instance.returnedIterators = new Map;
|
|
489
|
+
instance.nextLocalCallbackId = 1e6;
|
|
490
|
+
logRuntimeLifecycle(state, "reused pooled", instance);
|
|
491
|
+
}
|
|
492
|
+
async function waitForConnection(callbackContext) {
|
|
493
|
+
if (callbackContext.connection) {
|
|
494
|
+
return callbackContext.connection;
|
|
495
|
+
}
|
|
496
|
+
if (callbackContext.reconnectionPromise) {
|
|
497
|
+
return callbackContext.reconnectionPromise.promise;
|
|
498
|
+
}
|
|
499
|
+
throw new Error("No connection available and no reconnection pending");
|
|
500
|
+
}
|
|
501
|
+
function getCurrentHostSignal(instance) {
|
|
502
|
+
return requestContextStorage.getStore()?.signal ?? instance?.runtimeAbortController?.signal;
|
|
503
|
+
}
|
|
504
|
+
async function invokeCallbackWithReconnect(callbackContext, getCallbackId, args, label, invokeClientCallback, options) {
|
|
505
|
+
const conn = await waitForConnection(callbackContext);
|
|
506
|
+
const cbId = getCallbackId();
|
|
507
|
+
if (cbId === undefined) {
|
|
508
|
+
throw new Error(`${label} callback not available`);
|
|
509
|
+
}
|
|
510
|
+
try {
|
|
511
|
+
return await invokeClientCallback(conn, cbId, args, options);
|
|
512
|
+
} catch (err) {
|
|
513
|
+
if (callbackContext.reconnectionPromise && !callbackContext.connection) {
|
|
514
|
+
const newConn = await callbackContext.reconnectionPromise.promise;
|
|
515
|
+
const newCbId = getCallbackId();
|
|
516
|
+
if (newCbId === undefined) {
|
|
517
|
+
throw new Error(`${label} callback not available after reconnection`);
|
|
518
|
+
}
|
|
519
|
+
return invokeClientCallback(newConn, newCbId, args, options);
|
|
520
|
+
}
|
|
521
|
+
throw err;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
async function evictOldestDisposedRuntime(state) {
|
|
525
|
+
let oldest = null;
|
|
526
|
+
let oldestTime = Infinity;
|
|
527
|
+
for (const [, instance] of state.isolates) {
|
|
528
|
+
if (instance.isDisposed && instance.disposedAt !== undefined) {
|
|
529
|
+
if (instance.disposedAt < oldestTime) {
|
|
530
|
+
oldestTime = instance.disposedAt;
|
|
531
|
+
oldest = instance;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
if (oldest) {
|
|
536
|
+
try {
|
|
537
|
+
await hardDeleteRuntime(oldest, state, "LRU eviction to make room for a new runtime");
|
|
538
|
+
} catch {}
|
|
539
|
+
return true;
|
|
540
|
+
}
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
async function handleCreateRuntime(message, connection, state) {
|
|
544
|
+
const namespaceId = message.options.namespaceId;
|
|
545
|
+
let namespaceCreationLocked = false;
|
|
546
|
+
if (namespaceId != null) {
|
|
547
|
+
const existing = state.namespacedRuntimes.get(namespaceId);
|
|
548
|
+
if (existing) {
|
|
549
|
+
if (!existing.isDisposed) {
|
|
550
|
+
if (existing.ownerConnection === connection.socket) {
|
|
551
|
+
sendOk(connection.socket, message.requestId, {
|
|
552
|
+
isolateId: existing.isolateId,
|
|
553
|
+
reused: true
|
|
554
|
+
});
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, `Namespace "${namespaceId}" already has an active runtime`);
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
reuseNamespacedRuntime(existing, connection, message, state);
|
|
561
|
+
sendOk(connection.socket, message.requestId, {
|
|
562
|
+
isolateId: existing.isolateId,
|
|
563
|
+
reused: true
|
|
564
|
+
});
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
if (state.namespacedCreatesInFlight.has(namespaceId)) {
|
|
568
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, `Namespace "${namespaceId}" creation already in progress`);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
state.namespacedCreatesInFlight.add(namespaceId);
|
|
572
|
+
namespaceCreationLocked = true;
|
|
573
|
+
}
|
|
574
|
+
try {
|
|
575
|
+
if (state.isolates.size >= state.options.maxIsolates) {
|
|
576
|
+
if (!await evictOldestDisposedRuntime(state)) {
|
|
577
|
+
const targetLabel = namespaceId != null ? `namespace=${JSON.stringify(namespaceId)}` : "non-namespaced";
|
|
578
|
+
console.warn(`[isolate-daemon] denied runtime create for ${targetLabel}: ${import_runtime_pool.formatRuntimePoolSnapshot(import_runtime_pool.collectRuntimePoolSnapshot(state))}`);
|
|
579
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_MEMORY_LIMIT, `Maximum isolates (${state.options.maxIsolates}) reached`);
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
const isolateId = import_node_crypto.randomUUID();
|
|
584
|
+
const consoleCallbacks = message.options.callbacks?.console;
|
|
585
|
+
const fetchCallback = message.options.callbacks?.fetch;
|
|
586
|
+
const fsCallbacks = message.options.callbacks?.fs;
|
|
587
|
+
const moduleLoaderCallback = message.options.callbacks?.moduleLoader;
|
|
588
|
+
const customCallbacks = message.options.callbacks?.custom;
|
|
589
|
+
const callbackContext = {
|
|
590
|
+
connection,
|
|
591
|
+
consoleOnEntry: consoleCallbacks?.onEntry?.callbackId,
|
|
592
|
+
fetch: fetchCallback?.callbackId,
|
|
593
|
+
moduleLoader: moduleLoaderCallback?.callbackId,
|
|
594
|
+
testEnvironmentOnEvent: message.options.testEnvironment != null && typeof message.options.testEnvironment === "object" ? message.options.testEnvironment.callbacks?.onEvent?.callbackId : undefined,
|
|
595
|
+
playwright: {
|
|
596
|
+
handlerCallbackId: message.options.callbacks?.playwright?.handlerCallbackId,
|
|
597
|
+
onBrowserConsoleLogCallbackId: message.options.callbacks?.playwright?.onBrowserConsoleLogCallbackId,
|
|
598
|
+
onNetworkRequestCallbackId: message.options.callbacks?.playwright?.onNetworkRequestCallbackId,
|
|
599
|
+
onNetworkResponseCallbackId: message.options.callbacks?.playwright?.onNetworkResponseCallbackId
|
|
600
|
+
},
|
|
601
|
+
fs: {
|
|
602
|
+
readFile: fsCallbacks?.readFile?.callbackId,
|
|
603
|
+
writeFile: fsCallbacks?.writeFile?.callbackId,
|
|
604
|
+
stat: fsCallbacks?.stat?.callbackId,
|
|
605
|
+
readdir: fsCallbacks?.readdir?.callbackId,
|
|
606
|
+
unlink: fsCallbacks?.unlink?.callbackId,
|
|
607
|
+
mkdir: fsCallbacks?.mkdir?.callbackId,
|
|
608
|
+
rmdir: fsCallbacks?.rmdir?.callbackId
|
|
609
|
+
},
|
|
610
|
+
custom: new Map(customCallbacks ? Object.entries(customCallbacks).map(([name, reg]) => [name, reg.callbackId]) : [])
|
|
611
|
+
};
|
|
612
|
+
const instance = {
|
|
613
|
+
isolateId,
|
|
614
|
+
runtime: null,
|
|
615
|
+
ownerConnection: connection.socket,
|
|
616
|
+
callbacks: new Map,
|
|
617
|
+
createdAt: Date.now(),
|
|
618
|
+
lastActivity: Date.now(),
|
|
619
|
+
runtimeAbortController: new AbortController,
|
|
620
|
+
returnedCallbacks: new Map,
|
|
621
|
+
returnedPromises: new Map,
|
|
622
|
+
returnedIterators: new Map,
|
|
623
|
+
nextLocalCallbackId: 1e6,
|
|
624
|
+
namespaceId,
|
|
625
|
+
isDisposed: false,
|
|
626
|
+
isPoisoned: false,
|
|
627
|
+
callbackContext
|
|
628
|
+
};
|
|
629
|
+
let bridgedCustomFunctions;
|
|
630
|
+
let customFnMarshalOptions;
|
|
631
|
+
if (customCallbacks) {
|
|
632
|
+
const createMarshalContext = () => ({
|
|
633
|
+
registerCallback: (fn) => {
|
|
634
|
+
const callbackId = instance.nextLocalCallbackId++;
|
|
635
|
+
instance.returnedCallbacks.set(callbackId, fn);
|
|
636
|
+
return callbackId;
|
|
637
|
+
},
|
|
638
|
+
registerPromise: (promise) => {
|
|
639
|
+
const promiseId = instance.nextLocalCallbackId++;
|
|
640
|
+
instance.returnedPromises.set(promiseId, promise);
|
|
641
|
+
return promiseId;
|
|
642
|
+
},
|
|
643
|
+
registerIterator: (iterator) => {
|
|
644
|
+
const iteratorId = instance.nextLocalCallbackId++;
|
|
645
|
+
instance.returnedIterators.set(iteratorId, iterator);
|
|
646
|
+
return iteratorId;
|
|
647
|
+
}
|
|
648
|
+
});
|
|
649
|
+
const addCallbackIdsToRefs = (value) => {
|
|
650
|
+
if (value === null || typeof value !== "object")
|
|
651
|
+
return value;
|
|
652
|
+
if (import_protocol.isPromiseRef(value)) {
|
|
653
|
+
if ("__resolveCallbackId" in value)
|
|
654
|
+
return value;
|
|
655
|
+
const resolveCallbackId = instance.nextLocalCallbackId++;
|
|
656
|
+
instance.returnedCallbacks.set(resolveCallbackId, async (promiseId) => {
|
|
657
|
+
const promise = instance.returnedPromises.get(promiseId);
|
|
658
|
+
if (!promise)
|
|
659
|
+
throw new Error(`Promise ${promiseId} not found`);
|
|
660
|
+
const result2 = await promise;
|
|
661
|
+
instance.returnedPromises.delete(promiseId);
|
|
662
|
+
const ctx = createMarshalContext();
|
|
663
|
+
const marshalled = await import_protocol.marshalValue(result2, ctx);
|
|
664
|
+
return addCallbackIdsToRefs(marshalled);
|
|
665
|
+
});
|
|
666
|
+
return { ...value, __resolveCallbackId: resolveCallbackId };
|
|
667
|
+
}
|
|
668
|
+
if (import_protocol.isAsyncIteratorRef(value)) {
|
|
669
|
+
if ("__nextCallbackId" in value)
|
|
670
|
+
return value;
|
|
671
|
+
const nextCallbackId = instance.nextLocalCallbackId++;
|
|
672
|
+
instance.returnedCallbacks.set(nextCallbackId, async (iteratorId) => {
|
|
673
|
+
const iterator = instance.returnedIterators.get(iteratorId);
|
|
674
|
+
if (!iterator)
|
|
675
|
+
throw new Error(`Iterator ${iteratorId} not found`);
|
|
676
|
+
const result2 = await iterator.next();
|
|
677
|
+
if (result2.done)
|
|
678
|
+
instance.returnedIterators.delete(iteratorId);
|
|
679
|
+
const ctx = createMarshalContext();
|
|
680
|
+
const marshalledValue = await import_protocol.marshalValue(result2.value, ctx);
|
|
681
|
+
return { done: result2.done, value: addCallbackIdsToRefs(marshalledValue) };
|
|
682
|
+
});
|
|
683
|
+
const returnCallbackId = instance.nextLocalCallbackId++;
|
|
684
|
+
instance.returnedCallbacks.set(returnCallbackId, async (iteratorId, returnValue) => {
|
|
685
|
+
const iterator = instance.returnedIterators.get(iteratorId);
|
|
686
|
+
instance.returnedIterators.delete(iteratorId);
|
|
687
|
+
if (!iterator || !iterator.return)
|
|
688
|
+
return { done: true, value: undefined };
|
|
689
|
+
const result2 = await iterator.return(returnValue);
|
|
690
|
+
const ctx = createMarshalContext();
|
|
691
|
+
const marshalledValue = await import_protocol.marshalValue(result2.value, ctx);
|
|
692
|
+
return { done: true, value: addCallbackIdsToRefs(marshalledValue) };
|
|
693
|
+
});
|
|
694
|
+
const throwCallbackId = instance.nextLocalCallbackId++;
|
|
695
|
+
instance.returnedCallbacks.set(throwCallbackId, async (iteratorId, errorValue) => {
|
|
696
|
+
const iterator = instance.returnedIterators.get(iteratorId);
|
|
697
|
+
if (!iterator) {
|
|
698
|
+
throw new Error(`Iterator ${iteratorId} not found`);
|
|
699
|
+
}
|
|
700
|
+
try {
|
|
701
|
+
if (!iterator.throw) {
|
|
702
|
+
throw Object.assign(new Error(errorValue?.message ?? "Iterator does not support throw()"), { name: errorValue?.name ?? "Error", stack: errorValue?.stack });
|
|
703
|
+
}
|
|
704
|
+
const thrownError = Object.assign(new Error(errorValue?.message ?? "Iterator throw()"), { name: errorValue?.name ?? "Error", stack: errorValue?.stack });
|
|
705
|
+
const result2 = await iterator.throw(thrownError);
|
|
706
|
+
if (result2.done) {
|
|
707
|
+
instance.returnedIterators.delete(iteratorId);
|
|
708
|
+
}
|
|
709
|
+
const ctx = createMarshalContext();
|
|
710
|
+
const marshalledValue = await import_protocol.marshalValue(result2.value, ctx);
|
|
711
|
+
return { done: result2.done, value: addCallbackIdsToRefs(marshalledValue) };
|
|
712
|
+
} catch (error) {
|
|
713
|
+
instance.returnedIterators.delete(iteratorId);
|
|
714
|
+
throw error;
|
|
715
|
+
}
|
|
716
|
+
});
|
|
717
|
+
return {
|
|
718
|
+
...value,
|
|
719
|
+
__nextCallbackId: nextCallbackId,
|
|
720
|
+
__returnCallbackId: returnCallbackId,
|
|
721
|
+
__throwCallbackId: throwCallbackId
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
if (Array.isArray(value))
|
|
725
|
+
return value.map((item) => addCallbackIdsToRefs(item));
|
|
726
|
+
const result = {};
|
|
727
|
+
for (const key of Object.keys(value)) {
|
|
728
|
+
result[key] = addCallbackIdsToRefs(value[key]);
|
|
729
|
+
}
|
|
730
|
+
return result;
|
|
731
|
+
};
|
|
732
|
+
const LOCAL_CALLBACK_THRESHOLD = 1e6;
|
|
733
|
+
const invokeCallback = async (callbackId, args) => {
|
|
734
|
+
if (callbackId >= LOCAL_CALLBACK_THRESHOLD) {
|
|
735
|
+
const callback = instance.returnedCallbacks.get(callbackId);
|
|
736
|
+
if (!callback) {
|
|
737
|
+
throw new Error(`Local callback ${callbackId} not found`);
|
|
738
|
+
}
|
|
739
|
+
return await callback(...args);
|
|
740
|
+
} else {
|
|
741
|
+
const conn = await waitForConnection(callbackContext);
|
|
742
|
+
try {
|
|
743
|
+
return await invokeClientCallback(conn, callbackId, args, {
|
|
744
|
+
signal: getCurrentHostSignal(instance)
|
|
745
|
+
});
|
|
746
|
+
} catch (err) {
|
|
747
|
+
if (callbackContext.reconnectionPromise && !callbackContext.connection) {
|
|
748
|
+
const newConn = await callbackContext.reconnectionPromise.promise;
|
|
749
|
+
return invokeClientCallback(newConn, callbackId, args, {
|
|
750
|
+
signal: getCurrentHostSignal(instance)
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
throw err;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
customFnMarshalOptions = { createMarshalContext, addCallbackIdsToRefs, invokeCallback };
|
|
758
|
+
bridgedCustomFunctions = {};
|
|
759
|
+
for (const [name, registration] of Object.entries(customCallbacks)) {
|
|
760
|
+
if (name.includes(":"))
|
|
761
|
+
continue;
|
|
762
|
+
const callbackContext_ = callbackContext;
|
|
763
|
+
if (registration.type === "asyncIterator") {
|
|
764
|
+
bridgedCustomFunctions[name] = {
|
|
765
|
+
type: "asyncIterator",
|
|
766
|
+
fn: (...args) => {
|
|
767
|
+
const startCallbackId = callbackContext_.custom.get(`${name}:start`);
|
|
768
|
+
const nextCallbackId = callbackContext_.custom.get(`${name}:next`);
|
|
769
|
+
const returnCallbackId = callbackContext_.custom.get(`${name}:return`);
|
|
770
|
+
async function* bridgedIterator() {
|
|
771
|
+
const startResult = await invokeCallbackWithReconnect(callbackContext_, () => callbackContext_.custom.get(`${name}:start`), args, `AsyncIterator '${name}' start`, invokeClientCallback, { signal: getCurrentHostSignal(instance) });
|
|
772
|
+
const iteratorId = startResult.iteratorId;
|
|
773
|
+
try {
|
|
774
|
+
while (true) {
|
|
775
|
+
const nextResult = await invokeCallbackWithReconnect(callbackContext_, () => callbackContext_.custom.get(`${name}:next`), [iteratorId], `AsyncIterator '${name}' next`, invokeClientCallback, { signal: getCurrentHostSignal(instance) });
|
|
776
|
+
if (nextResult.done)
|
|
777
|
+
return nextResult.value;
|
|
778
|
+
yield nextResult.value;
|
|
779
|
+
}
|
|
780
|
+
} finally {
|
|
781
|
+
const retConn = callbackContext_.connection;
|
|
782
|
+
const retCbId = callbackContext_.custom.get(`${name}:return`);
|
|
783
|
+
if (retConn && retCbId !== undefined) {
|
|
784
|
+
await invokeClientCallback(retConn, retCbId, [iteratorId], {
|
|
785
|
+
signal: getCurrentHostSignal(instance)
|
|
786
|
+
}).catch(() => {});
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
return bridgedIterator();
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
} else {
|
|
794
|
+
bridgedCustomFunctions[name] = {
|
|
795
|
+
type: registration.type,
|
|
796
|
+
fn: async (...args) => {
|
|
797
|
+
return invokeCallbackWithReconnect(callbackContext_, () => callbackContext_.custom.get(name), args, `Custom function '${name}'`, invokeClientCallback, { signal: getCurrentHostSignal(instance) });
|
|
798
|
+
}
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
let moduleLoader;
|
|
804
|
+
if (moduleLoaderCallback) {
|
|
805
|
+
moduleLoader = async (specifier, importer) => {
|
|
806
|
+
return invokeCallbackWithReconnect(callbackContext, () => callbackContext.moduleLoader, [specifier, importer], "Module loader", invokeClientCallback, { signal: getCurrentHostSignal(instance) });
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
let testEnvironment;
|
|
810
|
+
if (message.options.testEnvironment) {
|
|
811
|
+
const testEnvOption = message.options.testEnvironment;
|
|
812
|
+
const testEnvOptions = typeof testEnvOption === "object" ? testEnvOption : undefined;
|
|
813
|
+
testEnvironment = {
|
|
814
|
+
onEvent: testEnvOptions?.callbacks?.onEvent ? (event) => {
|
|
815
|
+
const conn = callbackContext.connection;
|
|
816
|
+
const callbackId = callbackContext.testEnvironmentOnEvent;
|
|
817
|
+
if (!conn || callbackId === undefined) {
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
const promise = invokeClientCallback(conn, callbackId, [JSON.stringify(event)], { signal: getCurrentHostSignal(instance) }).catch(() => {});
|
|
821
|
+
instance.runtime?.pendingCallbacks?.push(promise);
|
|
822
|
+
} : undefined,
|
|
823
|
+
testTimeout: testEnvOptions?.testTimeout
|
|
824
|
+
};
|
|
825
|
+
if (testEnvOptions?.callbacks?.onEvent) {
|
|
826
|
+
instance.callbacks.set(testEnvOptions.callbacks.onEvent.callbackId, {
|
|
827
|
+
...testEnvOptions.callbacks.onEvent,
|
|
828
|
+
name: "testEnvironment.onEvent"
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
let playwrightOptions;
|
|
833
|
+
const playwrightCallbacks = message.options.callbacks?.playwright;
|
|
834
|
+
if (playwrightCallbacks) {
|
|
835
|
+
playwrightOptions = {
|
|
836
|
+
handler: async (op) => {
|
|
837
|
+
try {
|
|
838
|
+
const resultJson = await invokeCallbackWithReconnect(callbackContext, () => callbackContext.playwright.handlerCallbackId, [JSON.stringify(op)], "Playwright handler", invokeClientCallback, { signal: getCurrentHostSignal(instance) });
|
|
839
|
+
return JSON.parse(resultJson);
|
|
840
|
+
} catch (err) {
|
|
841
|
+
const error = err;
|
|
842
|
+
return { ok: false, error: { name: error.name, message: error.message } };
|
|
843
|
+
}
|
|
844
|
+
},
|
|
845
|
+
timeout: message.options.playwright?.timeout,
|
|
846
|
+
console: playwrightCallbacks.console,
|
|
847
|
+
onEvent: (event) => {
|
|
848
|
+
const conn = callbackContext.connection;
|
|
849
|
+
if (!conn) {
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
if (event.type === "browserConsoleLog" && callbackContext.playwright.onBrowserConsoleLogCallbackId !== undefined) {
|
|
853
|
+
const promise = invokeClientCallback(conn, callbackContext.playwright.onBrowserConsoleLogCallbackId, [{ level: event.level, stdout: event.stdout, timestamp: event.timestamp }], { signal: getCurrentHostSignal(instance) }).catch(() => {});
|
|
854
|
+
instance.runtime?.pendingCallbacks?.push(promise);
|
|
855
|
+
} else if (event.type === "networkRequest" && callbackContext.playwright.onNetworkRequestCallbackId !== undefined) {
|
|
856
|
+
const promise = invokeClientCallback(conn, callbackContext.playwright.onNetworkRequestCallbackId, [event], { signal: getCurrentHostSignal(instance) }).catch(() => {});
|
|
857
|
+
instance.runtime?.pendingCallbacks?.push(promise);
|
|
858
|
+
} else if (event.type === "networkResponse" && callbackContext.playwright.onNetworkResponseCallbackId !== undefined) {
|
|
859
|
+
const promise = invokeClientCallback(conn, callbackContext.playwright.onNetworkResponseCallbackId, [event], { signal: getCurrentHostSignal(instance) }).catch(() => {});
|
|
860
|
+
instance.runtime?.pendingCallbacks?.push(promise);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
const runtime = await import_runtime.createRuntime({
|
|
866
|
+
memoryLimitMB: message.options.memoryLimitMB ?? state.options.defaultMemoryLimitMB,
|
|
867
|
+
executionTimeout: message.options.executionTimeout,
|
|
868
|
+
cwd: message.options.cwd,
|
|
869
|
+
console: {
|
|
870
|
+
onEntry: (entry) => {
|
|
871
|
+
const conn = callbackContext.connection;
|
|
872
|
+
const callbackId = callbackContext.consoleOnEntry;
|
|
873
|
+
if (!conn || callbackId === undefined)
|
|
874
|
+
return;
|
|
875
|
+
const promise = invokeClientCallback(conn, callbackId, [entry]).catch(() => {});
|
|
876
|
+
runtime.pendingCallbacks.push(promise);
|
|
877
|
+
}
|
|
878
|
+
},
|
|
879
|
+
fetch: async (url, init) => {
|
|
880
|
+
if (init.signal.aborted) {
|
|
881
|
+
throw createAbortError();
|
|
882
|
+
}
|
|
883
|
+
const serialized = {
|
|
884
|
+
url,
|
|
885
|
+
method: init.method,
|
|
886
|
+
headers: init.headers,
|
|
887
|
+
body: init.rawBody,
|
|
888
|
+
signalAborted: init.signal.aborted
|
|
889
|
+
};
|
|
890
|
+
const callbackAbortController = new AbortController;
|
|
891
|
+
const onInitAbort = () => callbackAbortController.abort();
|
|
892
|
+
const currentSignal = getCurrentHostSignal(instance);
|
|
893
|
+
const onCurrentAbort = () => callbackAbortController.abort();
|
|
894
|
+
init.signal.addEventListener("abort", onInitAbort, { once: true });
|
|
895
|
+
currentSignal?.addEventListener("abort", onCurrentAbort, { once: true });
|
|
896
|
+
const result = await invokeCallbackWithReconnect(callbackContext, () => callbackContext.fetch, [serialized], "Fetch", invokeClientCallback, {
|
|
897
|
+
signal: callbackAbortController.signal,
|
|
898
|
+
timeoutMs: FETCH_CALLBACK_TIMEOUT_MS,
|
|
899
|
+
timeoutLabel: "fetch callback"
|
|
900
|
+
}).finally(() => {
|
|
901
|
+
init.signal.removeEventListener("abort", onInitAbort);
|
|
902
|
+
currentSignal?.removeEventListener("abort", onCurrentAbort);
|
|
903
|
+
});
|
|
904
|
+
if (result && typeof result === "object" && result.__streamingResponse) {
|
|
905
|
+
const response = result.response;
|
|
906
|
+
response.__isCallbackStream = true;
|
|
907
|
+
return response;
|
|
908
|
+
}
|
|
909
|
+
return import_protocol.deserializeResponse(result);
|
|
910
|
+
},
|
|
911
|
+
fs: {
|
|
912
|
+
getDirectory: async (dirPath) => {
|
|
913
|
+
const conn = await waitForConnection(callbackContext);
|
|
914
|
+
return import_callback_fs_handler.createCallbackFileSystemHandler({
|
|
915
|
+
connection: conn,
|
|
916
|
+
callbackContext,
|
|
917
|
+
invokeClientCallback,
|
|
918
|
+
basePath: dirPath,
|
|
919
|
+
getSignal: () => getCurrentHostSignal(instance)
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
},
|
|
923
|
+
moduleLoader,
|
|
924
|
+
customFunctions: bridgedCustomFunctions,
|
|
925
|
+
customFunctionsMarshalOptions: customFnMarshalOptions,
|
|
926
|
+
testEnvironment,
|
|
927
|
+
playwright: playwrightOptions
|
|
928
|
+
});
|
|
929
|
+
instance.runtime = runtime;
|
|
930
|
+
if (consoleCallbacks?.onEntry) {
|
|
931
|
+
instance.callbacks.set(consoleCallbacks.onEntry.callbackId, {
|
|
932
|
+
...consoleCallbacks.onEntry,
|
|
933
|
+
name: "onEntry"
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
if (fetchCallback) {
|
|
937
|
+
instance.callbacks.set(fetchCallback.callbackId, fetchCallback);
|
|
938
|
+
}
|
|
939
|
+
if (fsCallbacks) {
|
|
940
|
+
for (const [name, reg] of Object.entries(fsCallbacks)) {
|
|
941
|
+
if (reg) {
|
|
942
|
+
instance.callbacks.set(reg.callbackId, { ...reg, name });
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
if (moduleLoaderCallback) {
|
|
947
|
+
instance.callbacks.set(moduleLoaderCallback.callbackId, moduleLoaderCallback);
|
|
948
|
+
}
|
|
949
|
+
if (customCallbacks) {
|
|
950
|
+
for (const [name, reg] of Object.entries(customCallbacks)) {
|
|
951
|
+
if (reg) {
|
|
952
|
+
instance.callbacks.set(reg.callbackId, { ...reg, name });
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
if (playwrightCallbacks) {
|
|
957
|
+
instance.callbacks.set(playwrightCallbacks.handlerCallbackId, {
|
|
958
|
+
callbackId: playwrightCallbacks.handlerCallbackId,
|
|
959
|
+
name: "playwright.handler",
|
|
960
|
+
type: "async"
|
|
961
|
+
});
|
|
962
|
+
if (playwrightCallbacks.onBrowserConsoleLogCallbackId !== undefined) {
|
|
963
|
+
instance.callbacks.set(playwrightCallbacks.onBrowserConsoleLogCallbackId, {
|
|
964
|
+
callbackId: playwrightCallbacks.onBrowserConsoleLogCallbackId,
|
|
965
|
+
name: "playwright.onBrowserConsoleLog",
|
|
966
|
+
type: "sync"
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
if (playwrightCallbacks.onNetworkRequestCallbackId !== undefined) {
|
|
970
|
+
instance.callbacks.set(playwrightCallbacks.onNetworkRequestCallbackId, {
|
|
971
|
+
callbackId: playwrightCallbacks.onNetworkRequestCallbackId,
|
|
972
|
+
name: "playwright.onNetworkRequest",
|
|
973
|
+
type: "sync"
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
if (playwrightCallbacks.onNetworkResponseCallbackId !== undefined) {
|
|
977
|
+
instance.callbacks.set(playwrightCallbacks.onNetworkResponseCallbackId, {
|
|
978
|
+
callbackId: playwrightCallbacks.onNetworkResponseCallbackId,
|
|
979
|
+
name: "playwright.onNetworkResponse",
|
|
980
|
+
type: "sync"
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
state.isolates.set(isolateId, instance);
|
|
985
|
+
connection.isolates.add(isolateId);
|
|
986
|
+
state.stats.totalIsolatesCreated++;
|
|
987
|
+
if (namespaceId != null) {
|
|
988
|
+
state.namespacedRuntimes.set(namespaceId, instance);
|
|
989
|
+
}
|
|
990
|
+
runtime.fetch.onWebSocketCommand((cmd) => {
|
|
991
|
+
const targetConnection = callbackContext.connection;
|
|
992
|
+
if (!targetConnection) {
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
let data;
|
|
996
|
+
if (cmd.data instanceof ArrayBuffer) {
|
|
997
|
+
data = new Uint8Array(cmd.data);
|
|
998
|
+
} else {
|
|
999
|
+
data = cmd.data;
|
|
1000
|
+
}
|
|
1001
|
+
const payload = {
|
|
1002
|
+
type: cmd.type,
|
|
1003
|
+
connectionId: cmd.connectionId,
|
|
1004
|
+
data,
|
|
1005
|
+
code: cmd.code,
|
|
1006
|
+
reason: cmd.reason
|
|
1007
|
+
};
|
|
1008
|
+
sendMessage(targetConnection.socket, {
|
|
1009
|
+
type: import_protocol.MessageType.ISOLATE_EVENT,
|
|
1010
|
+
isolateId,
|
|
1011
|
+
event: import_protocol.IsolateEvents.WS_COMMAND,
|
|
1012
|
+
payload
|
|
1013
|
+
});
|
|
1014
|
+
});
|
|
1015
|
+
runtime.fetch.onClientWebSocketCommand((cmd) => {
|
|
1016
|
+
const targetConnection = callbackContext.connection;
|
|
1017
|
+
if (!targetConnection) {
|
|
1018
|
+
return;
|
|
1019
|
+
}
|
|
1020
|
+
let data;
|
|
1021
|
+
if (cmd.data instanceof ArrayBuffer) {
|
|
1022
|
+
data = new Uint8Array(cmd.data);
|
|
1023
|
+
} else {
|
|
1024
|
+
data = cmd.data;
|
|
1025
|
+
}
|
|
1026
|
+
if (cmd.type === "connect") {
|
|
1027
|
+
const payload = {
|
|
1028
|
+
socketId: cmd.socketId,
|
|
1029
|
+
url: cmd.url,
|
|
1030
|
+
protocols: cmd.protocols
|
|
1031
|
+
};
|
|
1032
|
+
sendMessage(targetConnection.socket, {
|
|
1033
|
+
type: import_protocol.MessageType.ISOLATE_EVENT,
|
|
1034
|
+
isolateId,
|
|
1035
|
+
event: import_protocol.IsolateEvents.WS_CLIENT_CONNECT,
|
|
1036
|
+
payload
|
|
1037
|
+
});
|
|
1038
|
+
} else if (cmd.type === "send") {
|
|
1039
|
+
const payload = {
|
|
1040
|
+
socketId: cmd.socketId,
|
|
1041
|
+
data
|
|
1042
|
+
};
|
|
1043
|
+
sendMessage(targetConnection.socket, {
|
|
1044
|
+
type: import_protocol.MessageType.ISOLATE_EVENT,
|
|
1045
|
+
isolateId,
|
|
1046
|
+
event: import_protocol.IsolateEvents.WS_CLIENT_SEND,
|
|
1047
|
+
payload
|
|
1048
|
+
});
|
|
1049
|
+
} else if (cmd.type === "close") {
|
|
1050
|
+
const payload = {
|
|
1051
|
+
socketId: cmd.socketId,
|
|
1052
|
+
code: cmd.code,
|
|
1053
|
+
reason: cmd.reason
|
|
1054
|
+
};
|
|
1055
|
+
sendMessage(targetConnection.socket, {
|
|
1056
|
+
type: import_protocol.MessageType.ISOLATE_EVENT,
|
|
1057
|
+
isolateId,
|
|
1058
|
+
event: import_protocol.IsolateEvents.WS_CLIENT_CLOSE,
|
|
1059
|
+
payload
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
});
|
|
1063
|
+
runtime.fetch.onEvent((eventName, payload) => {
|
|
1064
|
+
const targetConnection = callbackContext.connection;
|
|
1065
|
+
if (!targetConnection) {
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
sendMessage(targetConnection.socket, {
|
|
1069
|
+
type: import_protocol.MessageType.ISOLATE_EVENT,
|
|
1070
|
+
isolateId,
|
|
1071
|
+
event: eventName,
|
|
1072
|
+
payload
|
|
1073
|
+
});
|
|
1074
|
+
});
|
|
1075
|
+
sendOk(connection.socket, message.requestId, { isolateId, reused: false });
|
|
1076
|
+
logRuntimeLifecycle(state, "created", instance);
|
|
1077
|
+
} catch (err) {
|
|
1078
|
+
const error = err;
|
|
1079
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1080
|
+
} finally {
|
|
1081
|
+
if (namespaceCreationLocked && namespaceId != null) {
|
|
1082
|
+
state.namespacedCreatesInFlight.delete(namespaceId);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
async function handleDisposeRuntime(message, connection, state) {
|
|
1087
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1088
|
+
if (!instance) {
|
|
1089
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1090
|
+
return;
|
|
1091
|
+
}
|
|
1092
|
+
if (instance.ownerConnection !== connection.socket) {
|
|
1093
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not owned by this connection`);
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
try {
|
|
1097
|
+
connection.isolates.delete(message.isolateId);
|
|
1098
|
+
const requestReason = typeof message.reason === "string" && message.reason.length > 0 ? message.reason : message.hard ? "client requested hard dispose" : undefined;
|
|
1099
|
+
if (instance.namespaceId != null) {
|
|
1100
|
+
if (message.hard || instance.isPoisoned) {
|
|
1101
|
+
await hardDeleteRuntime(instance, state, requestReason);
|
|
1102
|
+
} else {
|
|
1103
|
+
softDeleteRuntime(instance, state, requestReason);
|
|
1104
|
+
}
|
|
1105
|
+
} else {
|
|
1106
|
+
await hardDeleteRuntime(instance, state, requestReason);
|
|
1107
|
+
}
|
|
1108
|
+
sendOk(connection.socket, message.requestId);
|
|
1109
|
+
} catch (err) {
|
|
1110
|
+
const error = err;
|
|
1111
|
+
if (instance.namespaceId != null && isLinkerConflictError(error)) {
|
|
1112
|
+
instance.isPoisoned = true;
|
|
1113
|
+
}
|
|
1114
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
async function handleEval(message, connection, state) {
|
|
1118
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1119
|
+
if (!instance) {
|
|
1120
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1123
|
+
instance.lastActivity = Date.now();
|
|
1124
|
+
try {
|
|
1125
|
+
await instance.runtime.eval(message.code, {
|
|
1126
|
+
filename: message.filename,
|
|
1127
|
+
executionTimeout: message.executionTimeout
|
|
1128
|
+
});
|
|
1129
|
+
sendOk(connection.socket, message.requestId, { value: undefined });
|
|
1130
|
+
} catch (err) {
|
|
1131
|
+
const error = err;
|
|
1132
|
+
if (isRuntimeTimeoutError(error)) {
|
|
1133
|
+
instance.isPoisoned = true;
|
|
1134
|
+
} else if (instance.namespaceId != null && isLinkerConflictError(error)) {
|
|
1135
|
+
instance.isPoisoned = true;
|
|
1136
|
+
}
|
|
1137
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
async function handleDispatchRequest(message, connection, state) {
|
|
1141
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1142
|
+
if (!instance) {
|
|
1143
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
1146
|
+
instance.lastActivity = Date.now();
|
|
1147
|
+
const dispatchAbortController = new AbortController;
|
|
1148
|
+
connection.dispatchAbortControllers.set(message.requestId, dispatchAbortController);
|
|
1149
|
+
if (connection.earlyAbortedDispatches.has(message.requestId) || message.request.signalAborted) {
|
|
1150
|
+
dispatchAbortController.abort();
|
|
1151
|
+
connection.earlyAbortedDispatches.delete(message.requestId);
|
|
1152
|
+
}
|
|
1153
|
+
await requestContextStorage.run({
|
|
1154
|
+
...message.context ?? {},
|
|
1155
|
+
signal: dispatchAbortController.signal
|
|
1156
|
+
}, async () => {
|
|
1157
|
+
try {
|
|
1158
|
+
let requestBody = null;
|
|
1159
|
+
if (message.request.bodyStreamId !== undefined) {
|
|
1160
|
+
requestBody = await receiveStreamedBody(connection, message.request.bodyStreamId);
|
|
1161
|
+
} else if (message.request.body) {
|
|
1162
|
+
requestBody = message.request.body;
|
|
1163
|
+
}
|
|
1164
|
+
const request = new Request(message.request.url, {
|
|
1165
|
+
method: message.request.method,
|
|
1166
|
+
headers: message.request.headers,
|
|
1167
|
+
body: requestBody,
|
|
1168
|
+
signal: dispatchAbortController.signal
|
|
1169
|
+
});
|
|
1170
|
+
const response = await instance.runtime.fetch.dispatchRequest(request, {
|
|
1171
|
+
signal: dispatchAbortController.signal
|
|
1172
|
+
});
|
|
1173
|
+
if (response.body) {
|
|
1174
|
+
await sendStreamedResponse(connection, message.requestId, response);
|
|
1175
|
+
} else {
|
|
1176
|
+
const headers = [];
|
|
1177
|
+
response.headers.forEach((value, key) => {
|
|
1178
|
+
headers.push([key, value]);
|
|
1179
|
+
});
|
|
1180
|
+
sendOk(connection.socket, message.requestId, {
|
|
1181
|
+
response: {
|
|
1182
|
+
status: response.status,
|
|
1183
|
+
statusText: response.statusText,
|
|
1184
|
+
headers,
|
|
1185
|
+
body: null
|
|
1186
|
+
}
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
} catch (err) {
|
|
1190
|
+
const error = err;
|
|
1191
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1192
|
+
} finally {
|
|
1193
|
+
connection.dispatchAbortControllers.delete(message.requestId);
|
|
1194
|
+
connection.earlyAbortedDispatches.delete(message.requestId);
|
|
1195
|
+
}
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1198
|
+
function handleDispatchRequestAbort(message, connection) {
|
|
1199
|
+
const controller = connection.dispatchAbortControllers.get(message.targetRequestId);
|
|
1200
|
+
if (controller) {
|
|
1201
|
+
controller.abort();
|
|
1202
|
+
return;
|
|
1203
|
+
}
|
|
1204
|
+
connection.earlyAbortedDispatches.add(message.targetRequestId);
|
|
1205
|
+
}
|
|
1206
|
+
function receiveStreamedBody(connection, streamId) {
|
|
1207
|
+
return new Promise((resolve, reject) => {
|
|
1208
|
+
const receiver = {
|
|
1209
|
+
streamId,
|
|
1210
|
+
requestId: 0,
|
|
1211
|
+
chunks: [],
|
|
1212
|
+
totalBytes: 0,
|
|
1213
|
+
resolve,
|
|
1214
|
+
reject
|
|
1215
|
+
};
|
|
1216
|
+
connection.streamReceivers.set(streamId, receiver);
|
|
1217
|
+
sendMessage(connection.socket, {
|
|
1218
|
+
type: import_protocol.MessageType.STREAM_PULL,
|
|
1219
|
+
streamId,
|
|
1220
|
+
maxBytes: import_protocol.STREAM_DEFAULT_CREDIT
|
|
1221
|
+
});
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
1224
|
+
async function handleWsOpen(message, connection, state) {
|
|
1225
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1226
|
+
if (!instance) {
|
|
1227
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1228
|
+
return;
|
|
1229
|
+
}
|
|
1230
|
+
instance.lastActivity = Date.now();
|
|
1231
|
+
try {
|
|
1232
|
+
instance.runtime.fetch.dispatchWebSocketOpen(message.connectionId);
|
|
1233
|
+
sendOk(connection.socket, message.requestId);
|
|
1234
|
+
} catch (err) {
|
|
1235
|
+
const error = err;
|
|
1236
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
async function handleWsMessage(message, connection, state) {
|
|
1240
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1241
|
+
if (!instance) {
|
|
1242
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
instance.lastActivity = Date.now();
|
|
1246
|
+
try {
|
|
1247
|
+
const data = message.data instanceof Uint8Array ? message.data.buffer.slice(message.data.byteOffset, message.data.byteOffset + message.data.byteLength) : message.data;
|
|
1248
|
+
instance.runtime.fetch.dispatchWebSocketMessage(message.connectionId, data);
|
|
1249
|
+
sendOk(connection.socket, message.requestId);
|
|
1250
|
+
} catch (err) {
|
|
1251
|
+
const error = err;
|
|
1252
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
async function handleWsClose(message, connection, state) {
|
|
1256
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1257
|
+
if (!instance) {
|
|
1258
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1259
|
+
return;
|
|
1260
|
+
}
|
|
1261
|
+
instance.lastActivity = Date.now();
|
|
1262
|
+
try {
|
|
1263
|
+
instance.runtime.fetch.dispatchWebSocketClose(message.connectionId, message.code, message.reason);
|
|
1264
|
+
sendOk(connection.socket, message.requestId);
|
|
1265
|
+
} catch (err) {
|
|
1266
|
+
const error = err;
|
|
1267
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
function handleClientEvent(message, connection, state) {
|
|
1271
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1272
|
+
if (!instance)
|
|
1273
|
+
return;
|
|
1274
|
+
instance.lastActivity = Date.now();
|
|
1275
|
+
switch (message.event) {
|
|
1276
|
+
case import_protocol.ClientEvents.WS_CLIENT_OPENED: {
|
|
1277
|
+
const payload = message.payload;
|
|
1278
|
+
instance.runtime.fetch.dispatchClientWebSocketOpen(payload.socketId, payload.protocol, payload.extensions);
|
|
1279
|
+
break;
|
|
1280
|
+
}
|
|
1281
|
+
case import_protocol.ClientEvents.WS_CLIENT_MESSAGE: {
|
|
1282
|
+
const payload = message.payload;
|
|
1283
|
+
const data = payload.data instanceof Uint8Array ? payload.data.buffer.slice(payload.data.byteOffset, payload.data.byteOffset + payload.data.byteLength) : payload.data;
|
|
1284
|
+
instance.runtime.fetch.dispatchClientWebSocketMessage(payload.socketId, data);
|
|
1285
|
+
break;
|
|
1286
|
+
}
|
|
1287
|
+
case import_protocol.ClientEvents.WS_CLIENT_CLOSED: {
|
|
1288
|
+
const payload = message.payload;
|
|
1289
|
+
instance.runtime.fetch.dispatchClientWebSocketClose(payload.socketId, payload.code, payload.reason, payload.wasClean);
|
|
1290
|
+
break;
|
|
1291
|
+
}
|
|
1292
|
+
case import_protocol.ClientEvents.WS_CLIENT_ERROR: {
|
|
1293
|
+
const payload = message.payload;
|
|
1294
|
+
instance.runtime.fetch.dispatchClientWebSocketError(payload.socketId);
|
|
1295
|
+
break;
|
|
1296
|
+
}
|
|
1297
|
+
default: {
|
|
1298
|
+
instance.runtime.fetch.dispatchEvent(message.event, message.payload);
|
|
1299
|
+
break;
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
async function handleFetchGetUpgradeRequest(message, connection, state) {
|
|
1304
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1305
|
+
if (!instance) {
|
|
1306
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1307
|
+
return;
|
|
1308
|
+
}
|
|
1309
|
+
instance.lastActivity = Date.now();
|
|
1310
|
+
try {
|
|
1311
|
+
const upgradeRequest = instance.runtime.fetch.getUpgradeRequest();
|
|
1312
|
+
sendOk(connection.socket, message.requestId, upgradeRequest);
|
|
1313
|
+
} catch (err) {
|
|
1314
|
+
const error = err;
|
|
1315
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
async function handleFetchHasServeHandler(message, connection, state) {
|
|
1319
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1320
|
+
if (!instance) {
|
|
1321
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1322
|
+
return;
|
|
1323
|
+
}
|
|
1324
|
+
instance.lastActivity = Date.now();
|
|
1325
|
+
try {
|
|
1326
|
+
const hasHandler = instance.runtime.fetch.hasServeHandler();
|
|
1327
|
+
sendOk(connection.socket, message.requestId, hasHandler);
|
|
1328
|
+
} catch (err) {
|
|
1329
|
+
const error = err;
|
|
1330
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
async function handleFetchHasActiveConnections(message, connection, state) {
|
|
1334
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1335
|
+
if (!instance) {
|
|
1336
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1337
|
+
return;
|
|
1338
|
+
}
|
|
1339
|
+
instance.lastActivity = Date.now();
|
|
1340
|
+
try {
|
|
1341
|
+
const hasConnections = instance.runtime.fetch.hasActiveConnections();
|
|
1342
|
+
sendOk(connection.socket, message.requestId, hasConnections);
|
|
1343
|
+
} catch (err) {
|
|
1344
|
+
const error = err;
|
|
1345
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
async function handleFetchWsError(message, connection, state) {
|
|
1349
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1350
|
+
if (!instance) {
|
|
1351
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
instance.lastActivity = Date.now();
|
|
1355
|
+
try {
|
|
1356
|
+
instance.runtime.fetch.dispatchWebSocketError(message.connectionId, new Error(message.error));
|
|
1357
|
+
sendOk(connection.socket, message.requestId);
|
|
1358
|
+
} catch (err) {
|
|
1359
|
+
const error = err;
|
|
1360
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
async function handleTimersClearAll(message, connection, state) {
|
|
1364
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1365
|
+
if (!instance) {
|
|
1366
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1367
|
+
return;
|
|
1368
|
+
}
|
|
1369
|
+
instance.lastActivity = Date.now();
|
|
1370
|
+
try {
|
|
1371
|
+
instance.runtime.timers.clearAll();
|
|
1372
|
+
sendOk(connection.socket, message.requestId);
|
|
1373
|
+
} catch (err) {
|
|
1374
|
+
const error = err;
|
|
1375
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
async function handleConsoleReset(message, connection, state) {
|
|
1379
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1380
|
+
if (!instance) {
|
|
1381
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1384
|
+
instance.lastActivity = Date.now();
|
|
1385
|
+
try {
|
|
1386
|
+
instance.runtime.console.reset();
|
|
1387
|
+
sendOk(connection.socket, message.requestId);
|
|
1388
|
+
} catch (err) {
|
|
1389
|
+
const error = err;
|
|
1390
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
async function handleConsoleGetTimers(message, connection, state) {
|
|
1394
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1395
|
+
if (!instance) {
|
|
1396
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1397
|
+
return;
|
|
1398
|
+
}
|
|
1399
|
+
instance.lastActivity = Date.now();
|
|
1400
|
+
try {
|
|
1401
|
+
const timers = instance.runtime.console.getTimers();
|
|
1402
|
+
sendOk(connection.socket, message.requestId, Object.fromEntries(timers));
|
|
1403
|
+
} catch (err) {
|
|
1404
|
+
const error = err;
|
|
1405
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
async function handleConsoleGetCounters(message, connection, state) {
|
|
1409
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1410
|
+
if (!instance) {
|
|
1411
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1412
|
+
return;
|
|
1413
|
+
}
|
|
1414
|
+
instance.lastActivity = Date.now();
|
|
1415
|
+
try {
|
|
1416
|
+
const counters = instance.runtime.console.getCounters();
|
|
1417
|
+
sendOk(connection.socket, message.requestId, Object.fromEntries(counters));
|
|
1418
|
+
} catch (err) {
|
|
1419
|
+
const error = err;
|
|
1420
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
async function handleConsoleGetGroupDepth(message, connection, state) {
|
|
1424
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1425
|
+
if (!instance) {
|
|
1426
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1427
|
+
return;
|
|
1428
|
+
}
|
|
1429
|
+
instance.lastActivity = Date.now();
|
|
1430
|
+
try {
|
|
1431
|
+
const depth = instance.runtime.console.getGroupDepth();
|
|
1432
|
+
sendOk(connection.socket, message.requestId, depth);
|
|
1433
|
+
} catch (err) {
|
|
1434
|
+
const error = err;
|
|
1435
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
function handleCallbackResponse(message, connection) {
|
|
1439
|
+
const pending = connection.pendingCallbacks.get(message.requestId);
|
|
1440
|
+
if (!pending) {
|
|
1441
|
+
console.warn(`No pending callback for requestId: ${message.requestId}`);
|
|
1442
|
+
return;
|
|
1443
|
+
}
|
|
1444
|
+
connection.pendingCallbacks.delete(message.requestId);
|
|
1445
|
+
pending.cleanup?.();
|
|
1446
|
+
if (message.error) {
|
|
1447
|
+
const error = new Error(message.error.message);
|
|
1448
|
+
error.name = message.error.name;
|
|
1449
|
+
if (message.error.stack) {
|
|
1450
|
+
error.stack = message.error.stack;
|
|
1451
|
+
}
|
|
1452
|
+
pending.reject(error);
|
|
1453
|
+
} else {
|
|
1454
|
+
pending.resolve(message.result);
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
async function invokeClientCallback(connection, callbackId, args, options) {
|
|
1458
|
+
const requestId = connection.nextCallbackId++;
|
|
1459
|
+
const timeoutMs = options?.timeoutMs ?? DEFAULT_CALLBACK_TIMEOUT_MS;
|
|
1460
|
+
return new Promise((resolve, reject) => {
|
|
1461
|
+
let settled = false;
|
|
1462
|
+
let timeoutId;
|
|
1463
|
+
let onAbort;
|
|
1464
|
+
let callbackInvokeSent = false;
|
|
1465
|
+
const settle = (handler, value) => {
|
|
1466
|
+
if (settled)
|
|
1467
|
+
return;
|
|
1468
|
+
settled = true;
|
|
1469
|
+
connection.pendingCallbacks.delete(requestId);
|
|
1470
|
+
if (timeoutId) {
|
|
1471
|
+
clearTimeout(timeoutId);
|
|
1472
|
+
timeoutId = undefined;
|
|
1473
|
+
}
|
|
1474
|
+
if (options?.signal && onAbort) {
|
|
1475
|
+
options.signal.removeEventListener("abort", onAbort);
|
|
1476
|
+
}
|
|
1477
|
+
handler(value);
|
|
1478
|
+
};
|
|
1479
|
+
onAbort = () => {
|
|
1480
|
+
if (settled)
|
|
1481
|
+
return;
|
|
1482
|
+
if (callbackInvokeSent) {
|
|
1483
|
+
sendCallbackAbortMessage(connection, requestId, options?.timeoutLabel ? `${options.timeoutLabel} aborted` : "Callback aborted");
|
|
1484
|
+
}
|
|
1485
|
+
settle(reject, createAbortError());
|
|
1486
|
+
};
|
|
1487
|
+
if (options?.signal) {
|
|
1488
|
+
if (options.signal.aborted) {
|
|
1489
|
+
onAbort();
|
|
1490
|
+
return;
|
|
1491
|
+
}
|
|
1492
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
1493
|
+
}
|
|
1494
|
+
if (timeoutMs > 0) {
|
|
1495
|
+
timeoutId = setTimeout(() => {
|
|
1496
|
+
if (settled)
|
|
1497
|
+
return;
|
|
1498
|
+
const label = options?.timeoutLabel ?? "callback";
|
|
1499
|
+
const timeoutError = new Error(`${label} timed out after ${timeoutMs}ms`);
|
|
1500
|
+
if (callbackInvokeSent) {
|
|
1501
|
+
sendCallbackAbortMessage(connection, requestId, timeoutError.message);
|
|
1502
|
+
}
|
|
1503
|
+
settle(reject, timeoutError);
|
|
1504
|
+
}, timeoutMs);
|
|
1505
|
+
}
|
|
1506
|
+
const pending = {
|
|
1507
|
+
callbackId,
|
|
1508
|
+
cleanup: () => {
|
|
1509
|
+
if (timeoutId) {
|
|
1510
|
+
clearTimeout(timeoutId);
|
|
1511
|
+
timeoutId = undefined;
|
|
1512
|
+
}
|
|
1513
|
+
if (options?.signal && onAbort) {
|
|
1514
|
+
options.signal.removeEventListener("abort", onAbort);
|
|
1515
|
+
}
|
|
1516
|
+
},
|
|
1517
|
+
resolve: (result) => settle(resolve, result),
|
|
1518
|
+
reject: (error) => settle(reject, error)
|
|
1519
|
+
};
|
|
1520
|
+
connection.pendingCallbacks.set(requestId, pending);
|
|
1521
|
+
const requestContext = requestContextStorage.getStore();
|
|
1522
|
+
const invoke = {
|
|
1523
|
+
type: import_protocol.MessageType.CALLBACK_INVOKE,
|
|
1524
|
+
requestId,
|
|
1525
|
+
callbackId,
|
|
1526
|
+
args,
|
|
1527
|
+
context: requestContext ? {
|
|
1528
|
+
requestId: requestContext.requestId,
|
|
1529
|
+
metadata: requestContext.metadata
|
|
1530
|
+
} : undefined
|
|
1531
|
+
};
|
|
1532
|
+
sendMessage(connection.socket, invoke);
|
|
1533
|
+
callbackInvokeSent = true;
|
|
1534
|
+
});
|
|
1535
|
+
}
|
|
1536
|
+
function handleStreamPush(message, connection) {
|
|
1537
|
+
const receiver = connection.streamReceivers.get(message.streamId);
|
|
1538
|
+
if (!receiver) {
|
|
1539
|
+
sendMessage(connection.socket, {
|
|
1540
|
+
type: import_protocol.MessageType.STREAM_ERROR,
|
|
1541
|
+
streamId: message.streamId,
|
|
1542
|
+
error: "Stream not found"
|
|
1543
|
+
});
|
|
1544
|
+
return;
|
|
1545
|
+
}
|
|
1546
|
+
receiver.chunks.push(message.chunk);
|
|
1547
|
+
receiver.totalBytes += message.chunk.length;
|
|
1548
|
+
sendMessage(connection.socket, {
|
|
1549
|
+
type: import_protocol.MessageType.STREAM_PULL,
|
|
1550
|
+
streamId: message.streamId,
|
|
1551
|
+
maxBytes: import_protocol.STREAM_DEFAULT_CREDIT
|
|
1552
|
+
});
|
|
1553
|
+
}
|
|
1554
|
+
function handleStreamPull(message, connection) {
|
|
1555
|
+
const session = connection.activeStreams.get(message.streamId);
|
|
1556
|
+
if (!session) {
|
|
1557
|
+
return;
|
|
1558
|
+
}
|
|
1559
|
+
session.credit += message.maxBytes;
|
|
1560
|
+
if (session.creditResolver) {
|
|
1561
|
+
session.creditResolver();
|
|
1562
|
+
session.creditResolver = undefined;
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
function handleStreamClose(message, connection) {
|
|
1566
|
+
const receiver = connection.streamReceivers.get(message.streamId);
|
|
1567
|
+
if (!receiver) {
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
const totalLength = receiver.chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
1571
|
+
const body = new Uint8Array(totalLength);
|
|
1572
|
+
let offset = 0;
|
|
1573
|
+
for (const chunk of receiver.chunks) {
|
|
1574
|
+
body.set(chunk, offset);
|
|
1575
|
+
offset += chunk.length;
|
|
1576
|
+
}
|
|
1577
|
+
receiver.resolve(body);
|
|
1578
|
+
connection.streamReceivers.delete(message.streamId);
|
|
1579
|
+
}
|
|
1580
|
+
function handleStreamError(message, connection) {
|
|
1581
|
+
const receiver = connection.streamReceivers.get(message.streamId);
|
|
1582
|
+
if (receiver) {
|
|
1583
|
+
receiver.reject(new Error(message.error));
|
|
1584
|
+
connection.streamReceivers.delete(message.streamId);
|
|
1585
|
+
}
|
|
1586
|
+
const session = connection.activeStreams.get(message.streamId);
|
|
1587
|
+
if (session) {
|
|
1588
|
+
closeActiveDownloadSession(connection, message.streamId);
|
|
1589
|
+
}
|
|
1590
|
+
const callbackReceiver = connection.callbackStreamReceivers.get(message.streamId);
|
|
1591
|
+
if (callbackReceiver && callbackReceiver.state === "active") {
|
|
1592
|
+
callbackReceiver.state = "errored";
|
|
1593
|
+
callbackReceiver.error = new Error(message.error);
|
|
1594
|
+
const resolvers = callbackReceiver.pullResolvers.splice(0);
|
|
1595
|
+
for (const resolver of resolvers) {
|
|
1596
|
+
resolver();
|
|
1597
|
+
}
|
|
1598
|
+
connection.callbackStreamReceivers.delete(message.streamId);
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
function handleCallbackStreamStart(message, connection) {
|
|
1602
|
+
const receiver = {
|
|
1603
|
+
streamId: message.streamId,
|
|
1604
|
+
requestId: message.requestId,
|
|
1605
|
+
metadata: message.metadata,
|
|
1606
|
+
controller: null,
|
|
1607
|
+
state: "active",
|
|
1608
|
+
pendingChunks: [],
|
|
1609
|
+
pullResolvers: [],
|
|
1610
|
+
controllerFinalized: false
|
|
1611
|
+
};
|
|
1612
|
+
const readableStream = new ReadableStream({
|
|
1613
|
+
start(controller) {
|
|
1614
|
+
receiver.controller = controller;
|
|
1615
|
+
},
|
|
1616
|
+
pull(_controller) {
|
|
1617
|
+
if (receiver.controllerFinalized) {
|
|
1618
|
+
return;
|
|
1619
|
+
}
|
|
1620
|
+
if (receiver.pendingChunks.length > 0) {
|
|
1621
|
+
const chunk = receiver.pendingChunks.shift();
|
|
1622
|
+
receiver.controller.enqueue(chunk);
|
|
1623
|
+
return Promise.resolve();
|
|
1624
|
+
}
|
|
1625
|
+
if (receiver.state === "closed") {
|
|
1626
|
+
if (!receiver.controllerFinalized) {
|
|
1627
|
+
receiver.controllerFinalized = true;
|
|
1628
|
+
receiver.controller.close();
|
|
1629
|
+
}
|
|
1630
|
+
return Promise.resolve();
|
|
1631
|
+
}
|
|
1632
|
+
if (receiver.state === "errored") {
|
|
1633
|
+
if (!receiver.controllerFinalized && receiver.error) {
|
|
1634
|
+
receiver.controllerFinalized = true;
|
|
1635
|
+
receiver.controller.error(receiver.error);
|
|
1636
|
+
}
|
|
1637
|
+
return Promise.resolve();
|
|
1638
|
+
}
|
|
1639
|
+
return new Promise((resolve) => {
|
|
1640
|
+
receiver.pullResolvers.push(resolve);
|
|
1641
|
+
});
|
|
1642
|
+
},
|
|
1643
|
+
cancel(_reason) {
|
|
1644
|
+
receiver.state = "closed";
|
|
1645
|
+
receiver.controllerFinalized = true;
|
|
1646
|
+
const resolvers = receiver.pullResolvers.splice(0);
|
|
1647
|
+
for (const resolver of resolvers) {
|
|
1648
|
+
resolver();
|
|
1649
|
+
}
|
|
1650
|
+
connection.callbackStreamReceivers.delete(message.streamId);
|
|
1651
|
+
sendMessage(connection.socket, {
|
|
1652
|
+
type: import_protocol.MessageType.CALLBACK_STREAM_CANCEL,
|
|
1653
|
+
streamId: message.streamId
|
|
1654
|
+
});
|
|
1655
|
+
return Promise.resolve();
|
|
1656
|
+
}
|
|
1657
|
+
});
|
|
1658
|
+
const cancelStream = () => {
|
|
1659
|
+
connection.callbackStreamReceivers.delete(message.streamId);
|
|
1660
|
+
sendMessage(connection.socket, {
|
|
1661
|
+
type: import_protocol.MessageType.CALLBACK_STREAM_CANCEL,
|
|
1662
|
+
streamId: message.streamId
|
|
1663
|
+
});
|
|
1664
|
+
};
|
|
1665
|
+
connection.callbackStreamReceivers.set(message.streamId, receiver);
|
|
1666
|
+
const pending = connection.pendingCallbacks.get(message.requestId);
|
|
1667
|
+
if (!pending) {
|
|
1668
|
+
cancelStream();
|
|
1669
|
+
return;
|
|
1670
|
+
}
|
|
1671
|
+
try {
|
|
1672
|
+
const body = NULL_BODY_STATUSES.has(message.metadata.status) ? null : readableStream;
|
|
1673
|
+
const response = new Response(body, {
|
|
1674
|
+
status: message.metadata.status,
|
|
1675
|
+
statusText: message.metadata.statusText,
|
|
1676
|
+
headers: message.metadata.headers
|
|
1677
|
+
});
|
|
1678
|
+
connection.pendingCallbacks.delete(message.requestId);
|
|
1679
|
+
pending.resolve({ __streamingResponse: true, response });
|
|
1680
|
+
if (body === null) {
|
|
1681
|
+
cancelStream();
|
|
1682
|
+
}
|
|
1683
|
+
} catch (err) {
|
|
1684
|
+
connection.pendingCallbacks.delete(message.requestId);
|
|
1685
|
+
cancelStream();
|
|
1686
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1687
|
+
pending.reject(error);
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
function handleCallbackStreamChunk(message, connection) {
|
|
1691
|
+
const receiver = connection.callbackStreamReceivers.get(message.streamId);
|
|
1692
|
+
if (receiver && receiver.state === "active") {
|
|
1693
|
+
if (receiver.pullResolvers.length > 0) {
|
|
1694
|
+
receiver.controller.enqueue(message.chunk);
|
|
1695
|
+
const resolver = receiver.pullResolvers.shift();
|
|
1696
|
+
resolver();
|
|
1697
|
+
} else {
|
|
1698
|
+
receiver.pendingChunks.push(message.chunk);
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
function handleCallbackStreamEnd(message, connection) {
|
|
1703
|
+
const receiver = connection.callbackStreamReceivers.get(message.streamId);
|
|
1704
|
+
if (receiver) {
|
|
1705
|
+
receiver.state = "closed";
|
|
1706
|
+
while (receiver.pendingChunks.length > 0) {
|
|
1707
|
+
const chunk = receiver.pendingChunks.shift();
|
|
1708
|
+
receiver.controller.enqueue(chunk);
|
|
1709
|
+
}
|
|
1710
|
+
if (!receiver.controllerFinalized) {
|
|
1711
|
+
receiver.controllerFinalized = true;
|
|
1712
|
+
receiver.controller.close();
|
|
1713
|
+
}
|
|
1714
|
+
const resolvers = receiver.pullResolvers.splice(0);
|
|
1715
|
+
for (const resolver of resolvers) {
|
|
1716
|
+
resolver();
|
|
1717
|
+
}
|
|
1718
|
+
connection.callbackStreamReceivers.delete(message.streamId);
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
function waitForCredit(session) {
|
|
1722
|
+
return new Promise((resolve) => {
|
|
1723
|
+
session.creditResolver = resolve;
|
|
1724
|
+
});
|
|
1725
|
+
}
|
|
1726
|
+
async function sendStreamedResponse(connection, requestId, response) {
|
|
1727
|
+
const SEND_LOOP_YIELD_BYTES = 64 * 1024;
|
|
1728
|
+
const streamId = connection.nextStreamId++;
|
|
1729
|
+
const headers = [];
|
|
1730
|
+
response.headers.forEach((value, key) => {
|
|
1731
|
+
headers.push([key, value]);
|
|
1732
|
+
});
|
|
1733
|
+
const startMsg = {
|
|
1734
|
+
type: import_protocol.MessageType.RESPONSE_STREAM_START,
|
|
1735
|
+
requestId,
|
|
1736
|
+
streamId,
|
|
1737
|
+
metadata: {
|
|
1738
|
+
status: response.status,
|
|
1739
|
+
statusText: response.statusText,
|
|
1740
|
+
headers
|
|
1741
|
+
}
|
|
1742
|
+
};
|
|
1743
|
+
sendMessage(connection.socket, startMsg);
|
|
1744
|
+
if (!response.body) {
|
|
1745
|
+
const endMsg = {
|
|
1746
|
+
type: import_protocol.MessageType.RESPONSE_STREAM_END,
|
|
1747
|
+
requestId,
|
|
1748
|
+
streamId
|
|
1749
|
+
};
|
|
1750
|
+
sendMessage(connection.socket, endMsg);
|
|
1751
|
+
return;
|
|
1752
|
+
}
|
|
1753
|
+
const session = {
|
|
1754
|
+
streamId,
|
|
1755
|
+
direction: "download",
|
|
1756
|
+
requestId,
|
|
1757
|
+
state: "active",
|
|
1758
|
+
bytesTransferred: 0,
|
|
1759
|
+
credit: import_protocol.STREAM_DEFAULT_CREDIT
|
|
1760
|
+
};
|
|
1761
|
+
connection.activeStreams.set(streamId, session);
|
|
1762
|
+
const reader = response.body.getReader();
|
|
1763
|
+
session.cancelReader = () => {
|
|
1764
|
+
reader.cancel("Stream cancelled by client").catch(() => {});
|
|
1765
|
+
};
|
|
1766
|
+
let cancelledByClient = false;
|
|
1767
|
+
let bytesSinceYield = 0;
|
|
1768
|
+
let chunksSinceYield = 0;
|
|
1769
|
+
try {
|
|
1770
|
+
streamLoop:
|
|
1771
|
+
while (true) {
|
|
1772
|
+
while (session.credit < import_protocol.STREAM_CHUNK_SIZE && session.state === "active") {
|
|
1773
|
+
await waitForCredit(session);
|
|
1774
|
+
}
|
|
1775
|
+
if (session.state !== "active") {
|
|
1776
|
+
cancelledByClient = true;
|
|
1777
|
+
break;
|
|
1778
|
+
}
|
|
1779
|
+
const { done, value } = await reader.read();
|
|
1780
|
+
if (done) {
|
|
1781
|
+
const endMsg = {
|
|
1782
|
+
type: import_protocol.MessageType.RESPONSE_STREAM_END,
|
|
1783
|
+
requestId,
|
|
1784
|
+
streamId
|
|
1785
|
+
};
|
|
1786
|
+
sendMessage(connection.socket, endMsg);
|
|
1787
|
+
break;
|
|
1788
|
+
}
|
|
1789
|
+
for (let offset = 0;offset < value.length; offset += import_protocol.STREAM_CHUNK_SIZE) {
|
|
1790
|
+
const chunk = value.slice(offset, offset + import_protocol.STREAM_CHUNK_SIZE);
|
|
1791
|
+
const chunkMsg = {
|
|
1792
|
+
type: import_protocol.MessageType.RESPONSE_STREAM_CHUNK,
|
|
1793
|
+
requestId,
|
|
1794
|
+
streamId,
|
|
1795
|
+
chunk
|
|
1796
|
+
};
|
|
1797
|
+
sendMessage(connection.socket, chunkMsg);
|
|
1798
|
+
const creditCost = Math.max(chunk.length, import_protocol.STREAM_CHUNK_SIZE);
|
|
1799
|
+
session.credit -= creditCost;
|
|
1800
|
+
session.bytesTransferred += chunk.length;
|
|
1801
|
+
bytesSinceYield += chunk.length;
|
|
1802
|
+
chunksSinceYield += 1;
|
|
1803
|
+
if (chunk.length < 1024 || bytesSinceYield >= SEND_LOOP_YIELD_BYTES || chunksSinceYield >= 256) {
|
|
1804
|
+
bytesSinceYield = 0;
|
|
1805
|
+
chunksSinceYield = 0;
|
|
1806
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
1807
|
+
if (session.state !== "active") {
|
|
1808
|
+
cancelledByClient = true;
|
|
1809
|
+
break streamLoop;
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
} catch (err) {
|
|
1815
|
+
if (cancelledByClient || session.state !== "active") {
|
|
1816
|
+
return;
|
|
1817
|
+
}
|
|
1818
|
+
const errorMsg = {
|
|
1819
|
+
type: import_protocol.MessageType.STREAM_ERROR,
|
|
1820
|
+
streamId,
|
|
1821
|
+
error: err.message
|
|
1822
|
+
};
|
|
1823
|
+
sendMessage(connection.socket, errorMsg);
|
|
1824
|
+
} finally {
|
|
1825
|
+
if (cancelledByClient) {
|
|
1826
|
+
await Promise.race([
|
|
1827
|
+
reader.cancel("Stream cancelled by client").catch(() => {}),
|
|
1828
|
+
new Promise((resolve) => setTimeout(resolve, 50))
|
|
1829
|
+
]);
|
|
1830
|
+
}
|
|
1831
|
+
session.cancelReader = undefined;
|
|
1832
|
+
reader.releaseLock();
|
|
1833
|
+
closeActiveDownloadSession(connection, streamId);
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
async function handleRunTests(message, connection, state) {
|
|
1837
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1838
|
+
if (!instance) {
|
|
1839
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1840
|
+
return;
|
|
1841
|
+
}
|
|
1842
|
+
instance.lastActivity = Date.now();
|
|
1843
|
+
if (instance.pendingTestRun) {
|
|
1844
|
+
try {
|
|
1845
|
+
const results = await instance.pendingTestRun.promise;
|
|
1846
|
+
const currentConn = instance.callbackContext?.connection;
|
|
1847
|
+
if (currentConn) {
|
|
1848
|
+
sendOk(currentConn.socket, message.requestId, results);
|
|
1849
|
+
}
|
|
1850
|
+
} catch (err) {
|
|
1851
|
+
const error = err;
|
|
1852
|
+
const currentConn = instance.callbackContext?.connection;
|
|
1853
|
+
if (currentConn) {
|
|
1854
|
+
sendError(currentConn.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
return;
|
|
1858
|
+
}
|
|
1859
|
+
try {
|
|
1860
|
+
const runPromise = instance.runtime.testEnvironment.runTests(message.timeout);
|
|
1861
|
+
instance.pendingTestRun = { promise: runPromise };
|
|
1862
|
+
const results = await runPromise;
|
|
1863
|
+
instance.pendingTestRun = undefined;
|
|
1864
|
+
const currentConn = instance.callbackContext?.connection ?? connection;
|
|
1865
|
+
sendOk(currentConn.socket, message.requestId, results);
|
|
1866
|
+
} catch (err) {
|
|
1867
|
+
instance.pendingTestRun = undefined;
|
|
1868
|
+
const error = err;
|
|
1869
|
+
if (isRuntimeTimeoutError(error)) {
|
|
1870
|
+
instance.isPoisoned = true;
|
|
1871
|
+
}
|
|
1872
|
+
const currentConn = instance.callbackContext?.connection ?? connection;
|
|
1873
|
+
sendError(currentConn.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
async function handleResetTestEnv(message, connection, state) {
|
|
1877
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1878
|
+
if (!instance) {
|
|
1879
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1880
|
+
return;
|
|
1881
|
+
}
|
|
1882
|
+
instance.lastActivity = Date.now();
|
|
1883
|
+
try {
|
|
1884
|
+
instance.runtime.testEnvironment.reset();
|
|
1885
|
+
sendOk(connection.socket, message.requestId);
|
|
1886
|
+
} catch (err) {
|
|
1887
|
+
const error = err;
|
|
1888
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
async function handleHasTests(message, connection, state) {
|
|
1892
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1893
|
+
if (!instance) {
|
|
1894
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1895
|
+
return;
|
|
1896
|
+
}
|
|
1897
|
+
instance.lastActivity = Date.now();
|
|
1898
|
+
try {
|
|
1899
|
+
const result = instance.runtime.testEnvironment.hasTests();
|
|
1900
|
+
sendOk(connection.socket, message.requestId, result);
|
|
1901
|
+
} catch (err) {
|
|
1902
|
+
const error = err;
|
|
1903
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
async function handleGetTestCount(message, connection, state) {
|
|
1907
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1908
|
+
if (!instance) {
|
|
1909
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1910
|
+
return;
|
|
1911
|
+
}
|
|
1912
|
+
instance.lastActivity = Date.now();
|
|
1913
|
+
try {
|
|
1914
|
+
const result = instance.runtime.testEnvironment.getTestCount();
|
|
1915
|
+
sendOk(connection.socket, message.requestId, result);
|
|
1916
|
+
} catch (err) {
|
|
1917
|
+
const error = err;
|
|
1918
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
async function handleGetCollectedData(message, connection, state) {
|
|
1922
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1923
|
+
if (!instance) {
|
|
1924
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1925
|
+
return;
|
|
1926
|
+
}
|
|
1927
|
+
instance.lastActivity = Date.now();
|
|
1928
|
+
try {
|
|
1929
|
+
const data = instance.runtime.playwright.getCollectedData();
|
|
1930
|
+
sendOk(connection.socket, message.requestId, data);
|
|
1931
|
+
} catch (err) {
|
|
1932
|
+
const error = err;
|
|
1933
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
async function handleClearCollectedData(message, connection, state) {
|
|
1937
|
+
const instance = state.isolates.get(message.isolateId);
|
|
1938
|
+
if (!instance) {
|
|
1939
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.ISOLATE_NOT_FOUND, `Isolate not found: ${message.isolateId}`);
|
|
1940
|
+
return;
|
|
1941
|
+
}
|
|
1942
|
+
instance.lastActivity = Date.now();
|
|
1943
|
+
try {
|
|
1944
|
+
instance.runtime.playwright.clearCollectedData();
|
|
1945
|
+
sendOk(connection.socket, message.requestId);
|
|
1946
|
+
} catch (err) {
|
|
1947
|
+
const error = err;
|
|
1948
|
+
sendError(connection.socket, message.requestId, import_protocol.ErrorCode.SCRIPT_ERROR, error.message, { name: error.name, stack: error.stack });
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
//# debugId=16FDF3C30EC7DFD264756E2164756E21
|