@grabbit-labs/dynafetch 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- 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 +230 -5
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -119,7 +119,7 @@ const page = await dynafetch({
|
|
|
119
119
|
|-|-|-|
|
|
120
120
|
| `minWaitMs` | `75` | Minimum ms before checking idle state |
|
|
121
121
|
| `idleWaitMs` | `100` | Ms of zero pending requests to consider settled |
|
|
122
|
-
| `maxWaitMs` | `
|
|
122
|
+
| `maxWaitMs` | `3000` | Hard cap on wait time |
|
|
123
123
|
| `moduleWaitMs` | `6000` | Max wait for ES module bundling |
|
|
124
124
|
| `timeoutMs` | none | Overall operation timeout |
|
|
125
125
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/index.js
CHANGED
|
@@ -764,8 +764,19 @@ var TELEMETRY_INLINE_PATTERNS = [
|
|
|
764
764
|
/\bhj\s*\(/i,
|
|
765
765
|
/\bnewrelic\b/i,
|
|
766
766
|
/\bdatadog\b/i,
|
|
767
|
-
/\bSentry\b/i,
|
|
768
|
-
/\bLogRocket\b/i
|
|
767
|
+
/\bSentry\.(?:init|capture|captureException|configureScope|withScope)\b/i,
|
|
768
|
+
/\bLogRocket\.(?:init|identify|track)\b/i
|
|
769
|
+
];
|
|
770
|
+
var INLINE_APPLICATION_PATTERNS = [
|
|
771
|
+
/\bwebpackChunk\w*/i,
|
|
772
|
+
/\b__webpack_require__\b/i,
|
|
773
|
+
/\b__SCRIPTS_LOADED__\b/i,
|
|
774
|
+
/\b__LOADABLE_LOADED_CHUNKS__\b/i,
|
|
775
|
+
/\bparcelRequire\b/i,
|
|
776
|
+
/\bwindow\.__[A-Z0-9_]{3,}\s*=/i,
|
|
777
|
+
/\bglobalThis\.__[A-Z0-9_]{3,}\s*=/i,
|
|
778
|
+
/\bself\.__[A-Z0-9_]{3,}\s*=/i,
|
|
779
|
+
/\bperformance\.mark\s*\(/i
|
|
769
780
|
];
|
|
770
781
|
function siteKey(hostname) {
|
|
771
782
|
const parts = hostname.split(".").filter(Boolean);
|
|
@@ -799,6 +810,7 @@ function classifyScriptAsset(script, pageUrl) {
|
|
|
799
810
|
if (script.scriptKind === "module") return "application";
|
|
800
811
|
return "unknown";
|
|
801
812
|
}
|
|
813
|
+
if (matchesAny(content, INLINE_APPLICATION_PATTERNS)) return "application";
|
|
802
814
|
if (matchesAny(content, TELEMETRY_INLINE_PATTERNS)) return "telemetry";
|
|
803
815
|
return "application";
|
|
804
816
|
}
|
|
@@ -878,6 +890,8 @@ var Executor = class {
|
|
|
878
890
|
this.originalGlobalMessageChannel = void 0;
|
|
879
891
|
this.originalGlobalMessagePort = void 0;
|
|
880
892
|
this.activeTimerHandles = /* @__PURE__ */ new Set();
|
|
893
|
+
this.domMutationVersion = 0;
|
|
894
|
+
this.domMutationObserver = null;
|
|
881
895
|
// Simple telemetry counters (useful for debugging).
|
|
882
896
|
this.telemetry_stubbed = 0;
|
|
883
897
|
this.telemetry_proxy = 0;
|
|
@@ -996,11 +1010,87 @@ var Executor = class {
|
|
|
996
1010
|
}
|
|
997
1011
|
this.activeTimerHandles.clear();
|
|
998
1012
|
}
|
|
1013
|
+
noteDomMutation() {
|
|
1014
|
+
this.domMutationVersion++;
|
|
1015
|
+
}
|
|
1016
|
+
async waitForDomSettle(window) {
|
|
1017
|
+
const quietMs = this.clampMs(
|
|
1018
|
+
Number(process.env.PHANTOM_DOM_SETTLE_MS ?? Math.max(this.quiescenceOptions.idleWaitMs * 4, 400)),
|
|
1019
|
+
50,
|
|
1020
|
+
5e3
|
|
1021
|
+
);
|
|
1022
|
+
const maxMs = this.clampMs(
|
|
1023
|
+
Number(process.env.PHANTOM_DOM_SETTLE_MAX_MS ?? Math.max(quietMs * 4, 2e3)),
|
|
1024
|
+
quietMs,
|
|
1025
|
+
1e4
|
|
1026
|
+
);
|
|
1027
|
+
const start = Date.now();
|
|
1028
|
+
let seenVersion = this.domMutationVersion;
|
|
1029
|
+
while (!this.windowClosed) {
|
|
1030
|
+
await new Promise((resolve) => setTimeout(resolve, quietMs));
|
|
1031
|
+
if (this.domMutationVersion === seenVersion) return;
|
|
1032
|
+
seenVersion = this.domMutationVersion;
|
|
1033
|
+
if (Date.now() - start >= maxMs) return;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
async performAutoScroll(window) {
|
|
1037
|
+
const steps = this.clampMs(Number(process.env.PHANTOM_AUTO_SCROLL_STEPS ?? 3), 0, 12);
|
|
1038
|
+
if (steps === 0) return false;
|
|
1039
|
+
const stepPx = this.clampMs(
|
|
1040
|
+
Number(process.env.PHANTOM_AUTO_SCROLL_STEP_PX ?? Math.max(Number(window.innerHeight) || 0, 900)),
|
|
1041
|
+
100,
|
|
1042
|
+
1e4
|
|
1043
|
+
);
|
|
1044
|
+
const delayMs = this.clampMs(Number(process.env.PHANTOM_AUTO_SCROLL_DELAY_MS ?? 150), 0, 5e3);
|
|
1045
|
+
const dispatchScroll = () => {
|
|
1046
|
+
try {
|
|
1047
|
+
window.dispatchEvent(new window.Event("scroll"));
|
|
1048
|
+
} catch {
|
|
1049
|
+
}
|
|
1050
|
+
try {
|
|
1051
|
+
window.document?.dispatchEvent?.(new window.Event("scroll"));
|
|
1052
|
+
} catch {
|
|
1053
|
+
}
|
|
1054
|
+
try {
|
|
1055
|
+
window.document?.documentElement?.dispatchEvent?.(new window.Event("scroll"));
|
|
1056
|
+
} catch {
|
|
1057
|
+
}
|
|
1058
|
+
};
|
|
1059
|
+
let didScroll = false;
|
|
1060
|
+
for (let step = 0; step < steps && !this.windowClosed; step++) {
|
|
1061
|
+
const nextY = (Number(window.scrollY) || 0) + stepPx;
|
|
1062
|
+
try {
|
|
1063
|
+
window.scrollTo(0, nextY);
|
|
1064
|
+
} catch {
|
|
1065
|
+
try {
|
|
1066
|
+
window.scrollY = nextY;
|
|
1067
|
+
} catch {
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
dispatchScroll();
|
|
1071
|
+
didScroll = true;
|
|
1072
|
+
if (delayMs > 0) {
|
|
1073
|
+
await new Promise((resolve) => window.setTimeout(resolve, delayMs));
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
if (didScroll) {
|
|
1077
|
+
try {
|
|
1078
|
+
window.scrollTo(0, 0);
|
|
1079
|
+
} catch {
|
|
1080
|
+
try {
|
|
1081
|
+
window.scrollY = 0;
|
|
1082
|
+
} catch {
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
dispatchScroll();
|
|
1086
|
+
}
|
|
1087
|
+
return didScroll;
|
|
1088
|
+
}
|
|
999
1089
|
applyDefaults(quiescence, moduleWaitMsOverride) {
|
|
1000
1090
|
const hardMaxCap = this.clampMs(Number(process.env.PHANTOM_QUIESCENCE_MAX_CAP_MS ?? 8e3), 500, 6e4);
|
|
1001
1091
|
const minWaitMs = this.clampMs(quiescence?.minWaitMs ?? 75, 0, 1e4);
|
|
1002
1092
|
const idleWaitMs = this.clampMs(quiescence?.idleWaitMs ?? 100, 0, 1e4);
|
|
1003
|
-
const maxWaitMs = this.clampMs(quiescence?.maxWaitMs ??
|
|
1093
|
+
const maxWaitMs = this.clampMs(quiescence?.maxWaitMs ?? 3e3, 0, hardMaxCap);
|
|
1004
1094
|
const hardModuleCap = this.clampMs(Number(process.env.PHANTOM_MODULE_WAIT_MAX_CAP_MS ?? 3e4), 1e3, 12e4);
|
|
1005
1095
|
this.moduleWaitMs = this.clampMs(Number(process.env.PHANTOM_MODULE_WAIT_MS ?? moduleWaitMsOverride ?? 6e3), 1e3, hardModuleCap);
|
|
1006
1096
|
this.quiescenceOptions = { minWaitMs, idleWaitMs, maxWaitMs };
|
|
@@ -1539,9 +1629,10 @@ var Executor = class {
|
|
|
1539
1629
|
};
|
|
1540
1630
|
}
|
|
1541
1631
|
if (!window.crypto) window.crypto = {};
|
|
1632
|
+
const nodeWebCrypto = g.crypto || nodeCrypto.webcrypto;
|
|
1542
1633
|
if (!window.crypto.getRandomValues) {
|
|
1543
|
-
if (
|
|
1544
|
-
window.crypto.getRandomValues =
|
|
1634
|
+
if (nodeWebCrypto && typeof nodeWebCrypto.getRandomValues === "function") {
|
|
1635
|
+
window.crypto.getRandomValues = nodeWebCrypto.getRandomValues.bind(nodeWebCrypto);
|
|
1545
1636
|
} else {
|
|
1546
1637
|
window.crypto.getRandomValues = (arr) => {
|
|
1547
1638
|
const buf = nodeCrypto.randomBytes(arr.length);
|
|
@@ -1550,6 +1641,22 @@ var Executor = class {
|
|
|
1550
1641
|
};
|
|
1551
1642
|
}
|
|
1552
1643
|
}
|
|
1644
|
+
if (!window.crypto.subtle && nodeWebCrypto?.subtle) {
|
|
1645
|
+
window.crypto.subtle = nodeWebCrypto.subtle;
|
|
1646
|
+
}
|
|
1647
|
+
if (!window.crypto.randomUUID) {
|
|
1648
|
+
if (typeof nodeWebCrypto?.randomUUID === "function") {
|
|
1649
|
+
window.crypto.randomUUID = nodeWebCrypto.randomUUID.bind(nodeWebCrypto);
|
|
1650
|
+
} else {
|
|
1651
|
+
window.crypto.randomUUID = () => nodeCrypto.randomUUID();
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
if (!window.CryptoKey && g.CryptoKey) {
|
|
1655
|
+
window.CryptoKey = g.CryptoKey;
|
|
1656
|
+
}
|
|
1657
|
+
if (!window.SubtleCrypto && g.SubtleCrypto) {
|
|
1658
|
+
window.SubtleCrypto = g.SubtleCrypto;
|
|
1659
|
+
}
|
|
1553
1660
|
{
|
|
1554
1661
|
const _g = globalThis;
|
|
1555
1662
|
if (_g.MessageChannel) {
|
|
@@ -1629,6 +1736,81 @@ var Executor = class {
|
|
|
1629
1736
|
availHeight: 900
|
|
1630
1737
|
};
|
|
1631
1738
|
}
|
|
1739
|
+
const parsePx = (value) => {
|
|
1740
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
1741
|
+
if (typeof value === "string") {
|
|
1742
|
+
const parsed = Number.parseFloat(value.replace(/px$/i, ""));
|
|
1743
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
1744
|
+
}
|
|
1745
|
+
return 0;
|
|
1746
|
+
};
|
|
1747
|
+
const fallbackViewportHeight = Math.max(Number(window.innerHeight) || 0, 900);
|
|
1748
|
+
const fallbackViewportWidth = Math.max(Number(window.innerWidth) || 0, 1440);
|
|
1749
|
+
const fallbackDocumentHeight = Math.max(fallbackViewportHeight * 6, 5400);
|
|
1750
|
+
const makeRect = (width, height) => ({
|
|
1751
|
+
x: 0,
|
|
1752
|
+
y: 0,
|
|
1753
|
+
top: 0,
|
|
1754
|
+
left: 0,
|
|
1755
|
+
bottom: height,
|
|
1756
|
+
right: width,
|
|
1757
|
+
width,
|
|
1758
|
+
height,
|
|
1759
|
+
toJSON() {
|
|
1760
|
+
return { x: 0, y: 0, top: 0, left: 0, bottom: height, right: width, width, height };
|
|
1761
|
+
}
|
|
1762
|
+
});
|
|
1763
|
+
const computeElementBox = (el) => {
|
|
1764
|
+
const tag = String(el?.tagName || "").toLowerCase();
|
|
1765
|
+
if (tag === "html" || tag === "body") {
|
|
1766
|
+
return {
|
|
1767
|
+
width: fallbackViewportWidth,
|
|
1768
|
+
height: fallbackDocumentHeight
|
|
1769
|
+
};
|
|
1770
|
+
}
|
|
1771
|
+
const width = parsePx(el?.style?.width) || parsePx(el?.getAttribute?.("width")) || fallbackViewportWidth;
|
|
1772
|
+
const height = parsePx(el?.style?.height) || parsePx(el?.getAttribute?.("height")) || 240;
|
|
1773
|
+
return { width, height };
|
|
1774
|
+
};
|
|
1775
|
+
try {
|
|
1776
|
+
const elementProto = window.Element?.prototype;
|
|
1777
|
+
if (elementProto) {
|
|
1778
|
+
const originalGetBoundingClientRect = elementProto.getBoundingClientRect;
|
|
1779
|
+
elementProto.getBoundingClientRect = function() {
|
|
1780
|
+
try {
|
|
1781
|
+
const rect = originalGetBoundingClientRect?.call(this);
|
|
1782
|
+
if (rect && (rect.width > 0 || rect.height > 0)) return rect;
|
|
1783
|
+
} catch {
|
|
1784
|
+
}
|
|
1785
|
+
const { width, height } = computeElementBox(this);
|
|
1786
|
+
return makeRect(width, height);
|
|
1787
|
+
};
|
|
1788
|
+
}
|
|
1789
|
+
const htmlEl = window.document?.documentElement;
|
|
1790
|
+
const bodyEl = window.document?.body;
|
|
1791
|
+
const defineSize = (target, name, value) => {
|
|
1792
|
+
try {
|
|
1793
|
+
Object.defineProperty(target, name, {
|
|
1794
|
+
configurable: true,
|
|
1795
|
+
get: () => value
|
|
1796
|
+
});
|
|
1797
|
+
} catch {
|
|
1798
|
+
}
|
|
1799
|
+
};
|
|
1800
|
+
if (htmlEl) {
|
|
1801
|
+
defineSize(htmlEl, "clientWidth", fallbackViewportWidth);
|
|
1802
|
+
defineSize(htmlEl, "clientHeight", fallbackViewportHeight);
|
|
1803
|
+
defineSize(htmlEl, "scrollWidth", fallbackViewportWidth);
|
|
1804
|
+
defineSize(htmlEl, "scrollHeight", fallbackDocumentHeight);
|
|
1805
|
+
}
|
|
1806
|
+
if (bodyEl) {
|
|
1807
|
+
defineSize(bodyEl, "clientWidth", fallbackViewportWidth);
|
|
1808
|
+
defineSize(bodyEl, "clientHeight", fallbackViewportHeight);
|
|
1809
|
+
defineSize(bodyEl, "scrollWidth", fallbackViewportWidth);
|
|
1810
|
+
defineSize(bodyEl, "scrollHeight", fallbackDocumentHeight);
|
|
1811
|
+
}
|
|
1812
|
+
} catch {
|
|
1813
|
+
}
|
|
1632
1814
|
if (!window.visualViewport) {
|
|
1633
1815
|
window.visualViewport = {
|
|
1634
1816
|
width: window.innerWidth,
|
|
@@ -2115,6 +2297,23 @@ var Executor = class {
|
|
|
2115
2297
|
}
|
|
2116
2298
|
});
|
|
2117
2299
|
const { window } = dom;
|
|
2300
|
+
this.domMutationVersion = 0;
|
|
2301
|
+
try {
|
|
2302
|
+
const MutationObserverCtor = window.MutationObserver;
|
|
2303
|
+
const targetNode = window.document?.documentElement || window.document?.body;
|
|
2304
|
+
if (MutationObserverCtor && targetNode) {
|
|
2305
|
+
this.domMutationObserver = new MutationObserverCtor(() => {
|
|
2306
|
+
this.noteDomMutation();
|
|
2307
|
+
});
|
|
2308
|
+
this.domMutationObserver.observe(targetNode, {
|
|
2309
|
+
subtree: true,
|
|
2310
|
+
childList: true,
|
|
2311
|
+
characterData: true,
|
|
2312
|
+
attributes: true
|
|
2313
|
+
});
|
|
2314
|
+
}
|
|
2315
|
+
} catch {
|
|
2316
|
+
}
|
|
2118
2317
|
let readyStateValue = "loading";
|
|
2119
2318
|
try {
|
|
2120
2319
|
Object.defineProperty(window.document, "readyState", {
|
|
@@ -2241,6 +2440,27 @@ var Executor = class {
|
|
|
2241
2440
|
this.timings.quiescence_ms = Date.now() - quiescenceStart;
|
|
2242
2441
|
const reason = this.matchFound && !this.findAll ? "(early exit on match)" : "";
|
|
2243
2442
|
log(`[Executor] Quiescence reached in ${Date.now() - quiescenceStart}ms ${reason}`);
|
|
2443
|
+
if (!this.matchFound || this.findAll) {
|
|
2444
|
+
const didScroll = await this.performAutoScroll(window);
|
|
2445
|
+
if (didScroll) {
|
|
2446
|
+
if (this.moduleInFlight.size > 0) {
|
|
2447
|
+
await this.waitForModuleWork(this.moduleWaitMs);
|
|
2448
|
+
}
|
|
2449
|
+
log("[Executor] Waiting for post-scroll quiescence...");
|
|
2450
|
+
const postScrollStart = Date.now();
|
|
2451
|
+
try {
|
|
2452
|
+
await this.waitForQuiescence();
|
|
2453
|
+
} catch (e) {
|
|
2454
|
+
warn("[Executor] Post-scroll quiescence wait failed:", e);
|
|
2455
|
+
}
|
|
2456
|
+
this.timings.quiescence_ms += Date.now() - postScrollStart;
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
try {
|
|
2460
|
+
await this.waitForDomSettle(window);
|
|
2461
|
+
} catch (e) {
|
|
2462
|
+
warn("[Executor] DOM settle wait failed:", e);
|
|
2463
|
+
}
|
|
2244
2464
|
const renderedHtml = this.serializeDocument(window);
|
|
2245
2465
|
this.windowClosed = true;
|
|
2246
2466
|
const result = {
|
|
@@ -2257,6 +2477,11 @@ var Executor = class {
|
|
|
2257
2477
|
this.unrefNewMessagePorts(initialActiveHandles);
|
|
2258
2478
|
return result;
|
|
2259
2479
|
} finally {
|
|
2480
|
+
try {
|
|
2481
|
+
this.domMutationObserver?.disconnect?.();
|
|
2482
|
+
} catch {
|
|
2483
|
+
}
|
|
2484
|
+
this.domMutationObserver = null;
|
|
2260
2485
|
const g = globalThis;
|
|
2261
2486
|
if (this.originalGlobalMessageChannel !== void 0) {
|
|
2262
2487
|
g.MessageChannel = this.originalGlobalMessageChannel;
|