@grabbit-labs/dynafetch 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/dynafetch-net-darwin-arm64 +0 -0
- package/bin/dynafetch-net-darwin-x64 +0 -0
- package/bin/dynafetch-net-linux-arm64 +0 -0
- package/bin/dynafetch-net-linux-x64 +0 -0
- package/bin/dynafetch-net-win32-x64.exe +0 -0
- package/dist/index.js +204 -16
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/index.js
CHANGED
|
@@ -325,7 +325,8 @@ async function withDynafetchSession(options, run) {
|
|
|
325
325
|
try {
|
|
326
326
|
return await sessionStore.run({ sessionId: session.sessionId }, run);
|
|
327
327
|
} finally {
|
|
328
|
-
|
|
328
|
+
const closeTimeoutMs = Math.min(resolveRpcTimeoutMs(options), 5e3);
|
|
329
|
+
await callWorker("closeSession", { sessionId: session.sessionId }, closeTimeoutMs).catch(() => {
|
|
329
330
|
});
|
|
330
331
|
transport.release();
|
|
331
332
|
}
|
|
@@ -814,6 +815,34 @@ function shouldSkipDynamicScriptUrl(url, pageUrl, policy) {
|
|
|
814
815
|
}
|
|
815
816
|
|
|
816
817
|
// ../../src/phantom/execute.ts
|
|
818
|
+
var esbuildModulePromise = null;
|
|
819
|
+
var esbuildRefCount = 0;
|
|
820
|
+
async function acquireEsbuildModule() {
|
|
821
|
+
if (!esbuildModulePromise) {
|
|
822
|
+
esbuildModulePromise = import("esbuild");
|
|
823
|
+
}
|
|
824
|
+
esbuildRefCount++;
|
|
825
|
+
try {
|
|
826
|
+
return await esbuildModulePromise;
|
|
827
|
+
} catch (error2) {
|
|
828
|
+
esbuildRefCount = Math.max(0, esbuildRefCount - 1);
|
|
829
|
+
if (esbuildRefCount === 0) esbuildModulePromise = null;
|
|
830
|
+
throw error2;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
function releaseEsbuildModule(esbuildMod) {
|
|
834
|
+
if (!esbuildMod) return;
|
|
835
|
+
esbuildRefCount = Math.max(0, esbuildRefCount - 1);
|
|
836
|
+
if (esbuildRefCount > 0) return;
|
|
837
|
+
const stopFn = esbuildMod?.stop || esbuildMod?.default?.stop;
|
|
838
|
+
if (typeof stopFn === "function") {
|
|
839
|
+
try {
|
|
840
|
+
stopFn.call(esbuildMod?.default ?? esbuildMod);
|
|
841
|
+
} catch {
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
esbuildModulePromise = null;
|
|
845
|
+
}
|
|
817
846
|
var Executor = class {
|
|
818
847
|
constructor(harvestData, options = null) {
|
|
819
848
|
this.logs = [];
|
|
@@ -845,6 +874,10 @@ var Executor = class {
|
|
|
845
874
|
this.moduleInFlight = /* @__PURE__ */ new Map();
|
|
846
875
|
// entryUrl -> promise
|
|
847
876
|
this.windowClosed = false;
|
|
877
|
+
this.esbuildModule = null;
|
|
878
|
+
this.originalGlobalMessageChannel = void 0;
|
|
879
|
+
this.originalGlobalMessagePort = void 0;
|
|
880
|
+
this.activeTimerHandles = /* @__PURE__ */ new Set();
|
|
848
881
|
// Simple telemetry counters (useful for debugging).
|
|
849
882
|
this.telemetry_stubbed = 0;
|
|
850
883
|
this.telemetry_proxy = 0;
|
|
@@ -936,6 +969,33 @@ var Executor = class {
|
|
|
936
969
|
if (!warning) return;
|
|
937
970
|
this.warnings.add(warning);
|
|
938
971
|
}
|
|
972
|
+
unrefNewMessagePorts(initialHandles) {
|
|
973
|
+
for (const handle of process._getActiveHandles()) {
|
|
974
|
+
if (initialHandles.has(handle)) continue;
|
|
975
|
+
if (handle?.constructor?.name !== "MessagePort") continue;
|
|
976
|
+
try {
|
|
977
|
+
handle.unref?.();
|
|
978
|
+
} catch {
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
clearTrackedTimers(window) {
|
|
983
|
+
for (const handle of this.activeTimerHandles) {
|
|
984
|
+
try {
|
|
985
|
+
window.clearTimeout?.(handle);
|
|
986
|
+
} catch {
|
|
987
|
+
}
|
|
988
|
+
try {
|
|
989
|
+
window.clearInterval?.(handle);
|
|
990
|
+
} catch {
|
|
991
|
+
}
|
|
992
|
+
try {
|
|
993
|
+
handle?.unref?.();
|
|
994
|
+
} catch {
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
this.activeTimerHandles.clear();
|
|
998
|
+
}
|
|
939
999
|
applyDefaults(quiescence, moduleWaitMsOverride) {
|
|
940
1000
|
const hardMaxCap = this.clampMs(Number(process.env.PHANTOM_QUIESCENCE_MAX_CAP_MS ?? 8e3), 500, 6e4);
|
|
941
1001
|
const minWaitMs = this.clampMs(quiescence?.minWaitMs ?? 75, 0, 1e4);
|
|
@@ -1213,7 +1273,8 @@ var Executor = class {
|
|
|
1213
1273
|
if (!this.windowClosed) window.eval(cached);
|
|
1214
1274
|
return;
|
|
1215
1275
|
}
|
|
1216
|
-
const esbuildMod = await
|
|
1276
|
+
const esbuildMod = this.esbuildModule ?? await acquireEsbuildModule();
|
|
1277
|
+
this.esbuildModule = esbuildMod;
|
|
1217
1278
|
const buildFn = esbuildMod?.build || esbuildMod?.default?.build;
|
|
1218
1279
|
if (typeof buildFn !== "function") {
|
|
1219
1280
|
throw new Error("esbuild.build not available (esbuild import failed)");
|
|
@@ -1372,14 +1433,66 @@ var Executor = class {
|
|
|
1372
1433
|
};
|
|
1373
1434
|
}
|
|
1374
1435
|
const g = globalThis;
|
|
1375
|
-
if (
|
|
1376
|
-
if (
|
|
1377
|
-
if (
|
|
1378
|
-
if (
|
|
1379
|
-
if (!window.AbortSignal && g.AbortSignal) window.AbortSignal = g.AbortSignal;
|
|
1436
|
+
if (g.Headers) window.Headers = g.Headers;
|
|
1437
|
+
if (g.Response) window.Response = g.Response;
|
|
1438
|
+
if (g.AbortController) window.AbortController = g.AbortController;
|
|
1439
|
+
if (g.AbortSignal) window.AbortSignal = g.AbortSignal;
|
|
1380
1440
|
if (!window.TextEncoder && g.TextEncoder) window.TextEncoder = g.TextEncoder;
|
|
1381
1441
|
if (!window.TextDecoder && g.TextDecoder) window.TextDecoder = g.TextDecoder;
|
|
1382
1442
|
if (!window.structuredClone && g.structuredClone) window.structuredClone = g.structuredClone.bind(g);
|
|
1443
|
+
const normalizeUrlForRequest = (value) => {
|
|
1444
|
+
if (typeof value !== "string") return value;
|
|
1445
|
+
try {
|
|
1446
|
+
return new URL(value, window.location.href).toString();
|
|
1447
|
+
} catch {
|
|
1448
|
+
return value;
|
|
1449
|
+
}
|
|
1450
|
+
};
|
|
1451
|
+
const normalizeAbortSignalForRequest = (signal) => {
|
|
1452
|
+
if (!signal || !g.AbortController || !g.AbortSignal) return signal;
|
|
1453
|
+
if (signal instanceof g.AbortSignal) return signal;
|
|
1454
|
+
if (typeof signal.aborted !== "boolean") return void 0;
|
|
1455
|
+
const controller = new g.AbortController();
|
|
1456
|
+
if (signal.aborted) {
|
|
1457
|
+
try {
|
|
1458
|
+
controller.abort(signal.reason);
|
|
1459
|
+
} catch {
|
|
1460
|
+
controller.abort();
|
|
1461
|
+
}
|
|
1462
|
+
return controller.signal;
|
|
1463
|
+
}
|
|
1464
|
+
if (typeof signal.addEventListener === "function") {
|
|
1465
|
+
try {
|
|
1466
|
+
signal.addEventListener("abort", () => {
|
|
1467
|
+
try {
|
|
1468
|
+
controller.abort(signal.reason);
|
|
1469
|
+
} catch {
|
|
1470
|
+
controller.abort();
|
|
1471
|
+
}
|
|
1472
|
+
}, { once: true });
|
|
1473
|
+
} catch {
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
return controller.signal;
|
|
1477
|
+
};
|
|
1478
|
+
if (g.Request) {
|
|
1479
|
+
const NativeRequest = g.Request;
|
|
1480
|
+
const RequestShim = class Request extends NativeRequest {
|
|
1481
|
+
constructor(input, init) {
|
|
1482
|
+
const normalizedInput = typeof input === "string" ? normalizeUrlForRequest(input) : input instanceof URL ? normalizeUrlForRequest(input.toString()) : input;
|
|
1483
|
+
const normalizedInit = init && typeof init === "object" ? {
|
|
1484
|
+
...init,
|
|
1485
|
+
signal: normalizeAbortSignalForRequest(init.signal)
|
|
1486
|
+
} : init;
|
|
1487
|
+
super(normalizedInput, normalizedInit);
|
|
1488
|
+
}
|
|
1489
|
+
};
|
|
1490
|
+
try {
|
|
1491
|
+
Object.setPrototypeOf(RequestShim, NativeRequest);
|
|
1492
|
+
} catch {
|
|
1493
|
+
}
|
|
1494
|
+
window.Request = RequestShim;
|
|
1495
|
+
}
|
|
1383
1496
|
const makeStorage = () => {
|
|
1384
1497
|
const store = /* @__PURE__ */ new Map();
|
|
1385
1498
|
return {
|
|
@@ -1439,8 +1552,27 @@ var Executor = class {
|
|
|
1439
1552
|
}
|
|
1440
1553
|
{
|
|
1441
1554
|
const _g = globalThis;
|
|
1442
|
-
if (
|
|
1443
|
-
|
|
1555
|
+
if (_g.MessageChannel) {
|
|
1556
|
+
if (this.originalGlobalMessageChannel === void 0) {
|
|
1557
|
+
this.originalGlobalMessageChannel = _g.MessageChannel;
|
|
1558
|
+
}
|
|
1559
|
+
const NativeMessageChannel = _g.MessageChannel;
|
|
1560
|
+
const UnrefMessageChannel = class MessageChannel extends NativeMessageChannel {
|
|
1561
|
+
constructor() {
|
|
1562
|
+
super();
|
|
1563
|
+
this.port1?.unref?.();
|
|
1564
|
+
this.port2?.unref?.();
|
|
1565
|
+
}
|
|
1566
|
+
};
|
|
1567
|
+
window.MessageChannel = UnrefMessageChannel;
|
|
1568
|
+
_g.MessageChannel = UnrefMessageChannel;
|
|
1569
|
+
}
|
|
1570
|
+
if (_g.MessagePort) {
|
|
1571
|
+
if (this.originalGlobalMessagePort === void 0) {
|
|
1572
|
+
this.originalGlobalMessagePort = _g.MessagePort;
|
|
1573
|
+
}
|
|
1574
|
+
window.MessagePort = _g.MessagePort;
|
|
1575
|
+
}
|
|
1444
1576
|
}
|
|
1445
1577
|
if (!window.requestIdleCallback) {
|
|
1446
1578
|
window.requestIdleCallback = (cb) => window.setTimeout(() => cb({
|
|
@@ -1559,8 +1691,41 @@ var Executor = class {
|
|
|
1559
1691
|
};
|
|
1560
1692
|
const _setTimeout = window.setTimeout?.bind(window);
|
|
1561
1693
|
const _setInterval = window.setInterval?.bind(window);
|
|
1562
|
-
|
|
1563
|
-
|
|
1694
|
+
const _clearTimeout = window.clearTimeout?.bind(window);
|
|
1695
|
+
const _clearInterval = window.clearInterval?.bind(window);
|
|
1696
|
+
if (_setTimeout) {
|
|
1697
|
+
window.setTimeout = (cb, ms, ...rest) => {
|
|
1698
|
+
let handle;
|
|
1699
|
+
const wrapped = wrapCb((...args) => {
|
|
1700
|
+
this.activeTimerHandles.delete(handle);
|
|
1701
|
+
return typeof cb === "function" ? cb(...args) : cb;
|
|
1702
|
+
});
|
|
1703
|
+
handle = _setTimeout(wrapped, ms, ...rest);
|
|
1704
|
+
this.activeTimerHandles.add(handle);
|
|
1705
|
+
handle?.unref?.();
|
|
1706
|
+
return handle;
|
|
1707
|
+
};
|
|
1708
|
+
}
|
|
1709
|
+
if (_setInterval) {
|
|
1710
|
+
window.setInterval = (cb, ms, ...rest) => {
|
|
1711
|
+
const handle = _setInterval(wrapCb(cb), ms, ...rest);
|
|
1712
|
+
this.activeTimerHandles.add(handle);
|
|
1713
|
+
handle?.unref?.();
|
|
1714
|
+
return handle;
|
|
1715
|
+
};
|
|
1716
|
+
}
|
|
1717
|
+
if (_clearTimeout) {
|
|
1718
|
+
window.clearTimeout = (handle) => {
|
|
1719
|
+
this.activeTimerHandles.delete(handle);
|
|
1720
|
+
return _clearTimeout(handle);
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
if (_clearInterval) {
|
|
1724
|
+
window.clearInterval = (handle) => {
|
|
1725
|
+
this.activeTimerHandles.delete(handle);
|
|
1726
|
+
return _clearInterval(handle);
|
|
1727
|
+
};
|
|
1728
|
+
}
|
|
1564
1729
|
if (window.queueMicrotask) {
|
|
1565
1730
|
const _q = window.queueMicrotask.bind(window);
|
|
1566
1731
|
window.queueMicrotask = (cb) => _q(wrapCb(cb));
|
|
@@ -1664,12 +1829,13 @@ var Executor = class {
|
|
|
1664
1829
|
async execute() {
|
|
1665
1830
|
const onNodeUncaught = (err) => this.recordExecutionError(err, "uncaughtException");
|
|
1666
1831
|
const onNodeUnhandled = (reason) => this.recordExecutionError(reason, "unhandledRejection");
|
|
1832
|
+
const initialActiveHandles = new Set(process._getActiveHandles());
|
|
1667
1833
|
process.on("uncaughtException", onNodeUncaught);
|
|
1668
1834
|
process.on("unhandledRejection", onNodeUnhandled);
|
|
1669
1835
|
try {
|
|
1670
1836
|
const virtualConsole = new VirtualConsole();
|
|
1671
1837
|
virtualConsole.on("log", (...args) => log("[JSDOM Log]", ...args));
|
|
1672
|
-
virtualConsole.on("error", (...args) =>
|
|
1838
|
+
virtualConsole.on("error", (...args) => warn("[JSDOM Error]", ...args));
|
|
1673
1839
|
virtualConsole.on("warn", (...args) => warn("[JSDOM Warn]", ...args));
|
|
1674
1840
|
const cookieJar = new CookieJar();
|
|
1675
1841
|
this.harvestData.cookies.forEach((c) => {
|
|
@@ -2077,10 +2243,6 @@ var Executor = class {
|
|
|
2077
2243
|
log(`[Executor] Quiescence reached in ${Date.now() - quiescenceStart}ms ${reason}`);
|
|
2078
2244
|
const renderedHtml = this.serializeDocument(window);
|
|
2079
2245
|
this.windowClosed = true;
|
|
2080
|
-
try {
|
|
2081
|
-
window.close();
|
|
2082
|
-
} catch {
|
|
2083
|
-
}
|
|
2084
2246
|
const result = {
|
|
2085
2247
|
logs: this.logs,
|
|
2086
2248
|
matchedRequests: this.earlyMatches,
|
|
@@ -2091,8 +2253,21 @@ var Executor = class {
|
|
|
2091
2253
|
};
|
|
2092
2254
|
const shutdownGraceMs = this.clampMs(Number(process.env.PHANTOM_SHUTDOWN_GRACE_MS ?? 50), 10, 5e3);
|
|
2093
2255
|
await new Promise((r) => setTimeout(r, shutdownGraceMs));
|
|
2256
|
+
this.clearTrackedTimers(window);
|
|
2257
|
+
this.unrefNewMessagePorts(initialActiveHandles);
|
|
2094
2258
|
return result;
|
|
2095
2259
|
} finally {
|
|
2260
|
+
const g = globalThis;
|
|
2261
|
+
if (this.originalGlobalMessageChannel !== void 0) {
|
|
2262
|
+
g.MessageChannel = this.originalGlobalMessageChannel;
|
|
2263
|
+
this.originalGlobalMessageChannel = void 0;
|
|
2264
|
+
}
|
|
2265
|
+
if (this.originalGlobalMessagePort !== void 0) {
|
|
2266
|
+
g.MessagePort = this.originalGlobalMessagePort;
|
|
2267
|
+
this.originalGlobalMessagePort = void 0;
|
|
2268
|
+
}
|
|
2269
|
+
releaseEsbuildModule(this.esbuildModule);
|
|
2270
|
+
this.esbuildModule = null;
|
|
2096
2271
|
process.off("uncaughtException", onNodeUncaught);
|
|
2097
2272
|
process.off("unhandledRejection", onNodeUnhandled);
|
|
2098
2273
|
}
|
|
@@ -2185,6 +2360,12 @@ var Executor = class {
|
|
|
2185
2360
|
};
|
|
2186
2361
|
window.__phantom = {
|
|
2187
2362
|
fetch: async (input, opts = {}) => {
|
|
2363
|
+
if (that.windowClosed) {
|
|
2364
|
+
return new (window.Response || global.Response)("", {
|
|
2365
|
+
status: 200,
|
|
2366
|
+
headers: toSafeResponseHeaders({})
|
|
2367
|
+
});
|
|
2368
|
+
}
|
|
2188
2369
|
const norm = await normalizeFetchInput(input, opts);
|
|
2189
2370
|
const start = Date.now();
|
|
2190
2371
|
const headers = {
|
|
@@ -2262,6 +2443,7 @@ var Executor = class {
|
|
|
2262
2443
|
}
|
|
2263
2444
|
},
|
|
2264
2445
|
dynamicImport: async (url) => {
|
|
2446
|
+
if (that.windowClosed) return {};
|
|
2265
2447
|
const fullUrl = new URL(url, window.location.href).toString();
|
|
2266
2448
|
const start = Date.now();
|
|
2267
2449
|
const logEntry = {
|
|
@@ -2374,6 +2556,12 @@ var Executor = class {
|
|
|
2374
2556
|
this.onloadend?.({ type: "loadend" });
|
|
2375
2557
|
}
|
|
2376
2558
|
async send(body) {
|
|
2559
|
+
if (that.windowClosed) {
|
|
2560
|
+
this.readyState = 4;
|
|
2561
|
+
this.status = 0;
|
|
2562
|
+
this.onloadend?.({ type: "loadend" });
|
|
2563
|
+
return;
|
|
2564
|
+
}
|
|
2377
2565
|
const start = Date.now();
|
|
2378
2566
|
const headers = {
|
|
2379
2567
|
"User-Agent": window.navigator.userAgent,
|