@grabbit-labs/dynafetch 0.2.4 → 0.2.5

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.
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
  }
@@ -996,6 +1008,59 @@ var Executor = class {
996
1008
  }
997
1009
  this.activeTimerHandles.clear();
998
1010
  }
1011
+ async performAutoScroll(window) {
1012
+ const steps = this.clampMs(Number(process.env.PHANTOM_AUTO_SCROLL_STEPS ?? 3), 0, 12);
1013
+ if (steps === 0) return false;
1014
+ const stepPx = this.clampMs(
1015
+ Number(process.env.PHANTOM_AUTO_SCROLL_STEP_PX ?? Math.max(Number(window.innerHeight) || 0, 900)),
1016
+ 100,
1017
+ 1e4
1018
+ );
1019
+ const delayMs = this.clampMs(Number(process.env.PHANTOM_AUTO_SCROLL_DELAY_MS ?? 150), 0, 5e3);
1020
+ const dispatchScroll = () => {
1021
+ try {
1022
+ window.dispatchEvent(new window.Event("scroll"));
1023
+ } catch {
1024
+ }
1025
+ try {
1026
+ window.document?.dispatchEvent?.(new window.Event("scroll"));
1027
+ } catch {
1028
+ }
1029
+ try {
1030
+ window.document?.documentElement?.dispatchEvent?.(new window.Event("scroll"));
1031
+ } catch {
1032
+ }
1033
+ };
1034
+ let didScroll = false;
1035
+ for (let step = 0; step < steps && !this.windowClosed; step++) {
1036
+ const nextY = (Number(window.scrollY) || 0) + stepPx;
1037
+ try {
1038
+ window.scrollTo(0, nextY);
1039
+ } catch {
1040
+ try {
1041
+ window.scrollY = nextY;
1042
+ } catch {
1043
+ }
1044
+ }
1045
+ dispatchScroll();
1046
+ didScroll = true;
1047
+ if (delayMs > 0) {
1048
+ await new Promise((resolve) => window.setTimeout(resolve, delayMs));
1049
+ }
1050
+ }
1051
+ if (didScroll) {
1052
+ try {
1053
+ window.scrollTo(0, 0);
1054
+ } catch {
1055
+ try {
1056
+ window.scrollY = 0;
1057
+ } catch {
1058
+ }
1059
+ }
1060
+ dispatchScroll();
1061
+ }
1062
+ return didScroll;
1063
+ }
999
1064
  applyDefaults(quiescence, moduleWaitMsOverride) {
1000
1065
  const hardMaxCap = this.clampMs(Number(process.env.PHANTOM_QUIESCENCE_MAX_CAP_MS ?? 8e3), 500, 6e4);
1001
1066
  const minWaitMs = this.clampMs(quiescence?.minWaitMs ?? 75, 0, 1e4);
@@ -1539,9 +1604,10 @@ var Executor = class {
1539
1604
  };
1540
1605
  }
1541
1606
  if (!window.crypto) window.crypto = {};
1607
+ const nodeWebCrypto = g.crypto || nodeCrypto.webcrypto;
1542
1608
  if (!window.crypto.getRandomValues) {
1543
- if (g.crypto && typeof g.crypto.getRandomValues === "function") {
1544
- window.crypto.getRandomValues = g.crypto.getRandomValues.bind(g.crypto);
1609
+ if (nodeWebCrypto && typeof nodeWebCrypto.getRandomValues === "function") {
1610
+ window.crypto.getRandomValues = nodeWebCrypto.getRandomValues.bind(nodeWebCrypto);
1545
1611
  } else {
1546
1612
  window.crypto.getRandomValues = (arr) => {
1547
1613
  const buf = nodeCrypto.randomBytes(arr.length);
@@ -1550,6 +1616,22 @@ var Executor = class {
1550
1616
  };
1551
1617
  }
1552
1618
  }
1619
+ if (!window.crypto.subtle && nodeWebCrypto?.subtle) {
1620
+ window.crypto.subtle = nodeWebCrypto.subtle;
1621
+ }
1622
+ if (!window.crypto.randomUUID) {
1623
+ if (typeof nodeWebCrypto?.randomUUID === "function") {
1624
+ window.crypto.randomUUID = nodeWebCrypto.randomUUID.bind(nodeWebCrypto);
1625
+ } else {
1626
+ window.crypto.randomUUID = () => nodeCrypto.randomUUID();
1627
+ }
1628
+ }
1629
+ if (!window.CryptoKey && g.CryptoKey) {
1630
+ window.CryptoKey = g.CryptoKey;
1631
+ }
1632
+ if (!window.SubtleCrypto && g.SubtleCrypto) {
1633
+ window.SubtleCrypto = g.SubtleCrypto;
1634
+ }
1553
1635
  {
1554
1636
  const _g = globalThis;
1555
1637
  if (_g.MessageChannel) {
@@ -1629,6 +1711,81 @@ var Executor = class {
1629
1711
  availHeight: 900
1630
1712
  };
1631
1713
  }
1714
+ const parsePx = (value) => {
1715
+ if (typeof value === "number" && Number.isFinite(value)) return value;
1716
+ if (typeof value === "string") {
1717
+ const parsed = Number.parseFloat(value.replace(/px$/i, ""));
1718
+ if (Number.isFinite(parsed)) return parsed;
1719
+ }
1720
+ return 0;
1721
+ };
1722
+ const fallbackViewportHeight = Math.max(Number(window.innerHeight) || 0, 900);
1723
+ const fallbackViewportWidth = Math.max(Number(window.innerWidth) || 0, 1440);
1724
+ const fallbackDocumentHeight = Math.max(fallbackViewportHeight * 6, 5400);
1725
+ const makeRect = (width, height) => ({
1726
+ x: 0,
1727
+ y: 0,
1728
+ top: 0,
1729
+ left: 0,
1730
+ bottom: height,
1731
+ right: width,
1732
+ width,
1733
+ height,
1734
+ toJSON() {
1735
+ return { x: 0, y: 0, top: 0, left: 0, bottom: height, right: width, width, height };
1736
+ }
1737
+ });
1738
+ const computeElementBox = (el) => {
1739
+ const tag = String(el?.tagName || "").toLowerCase();
1740
+ if (tag === "html" || tag === "body") {
1741
+ return {
1742
+ width: fallbackViewportWidth,
1743
+ height: fallbackDocumentHeight
1744
+ };
1745
+ }
1746
+ const width = parsePx(el?.style?.width) || parsePx(el?.getAttribute?.("width")) || fallbackViewportWidth;
1747
+ const height = parsePx(el?.style?.height) || parsePx(el?.getAttribute?.("height")) || 240;
1748
+ return { width, height };
1749
+ };
1750
+ try {
1751
+ const elementProto = window.Element?.prototype;
1752
+ if (elementProto) {
1753
+ const originalGetBoundingClientRect = elementProto.getBoundingClientRect;
1754
+ elementProto.getBoundingClientRect = function() {
1755
+ try {
1756
+ const rect = originalGetBoundingClientRect?.call(this);
1757
+ if (rect && (rect.width > 0 || rect.height > 0)) return rect;
1758
+ } catch {
1759
+ }
1760
+ const { width, height } = computeElementBox(this);
1761
+ return makeRect(width, height);
1762
+ };
1763
+ }
1764
+ const htmlEl = window.document?.documentElement;
1765
+ const bodyEl = window.document?.body;
1766
+ const defineSize = (target, name, value) => {
1767
+ try {
1768
+ Object.defineProperty(target, name, {
1769
+ configurable: true,
1770
+ get: () => value
1771
+ });
1772
+ } catch {
1773
+ }
1774
+ };
1775
+ if (htmlEl) {
1776
+ defineSize(htmlEl, "clientWidth", fallbackViewportWidth);
1777
+ defineSize(htmlEl, "clientHeight", fallbackViewportHeight);
1778
+ defineSize(htmlEl, "scrollWidth", fallbackViewportWidth);
1779
+ defineSize(htmlEl, "scrollHeight", fallbackDocumentHeight);
1780
+ }
1781
+ if (bodyEl) {
1782
+ defineSize(bodyEl, "clientWidth", fallbackViewportWidth);
1783
+ defineSize(bodyEl, "clientHeight", fallbackViewportHeight);
1784
+ defineSize(bodyEl, "scrollWidth", fallbackViewportWidth);
1785
+ defineSize(bodyEl, "scrollHeight", fallbackDocumentHeight);
1786
+ }
1787
+ } catch {
1788
+ }
1632
1789
  if (!window.visualViewport) {
1633
1790
  window.visualViewport = {
1634
1791
  width: window.innerWidth,
@@ -2241,6 +2398,22 @@ var Executor = class {
2241
2398
  this.timings.quiescence_ms = Date.now() - quiescenceStart;
2242
2399
  const reason = this.matchFound && !this.findAll ? "(early exit on match)" : "";
2243
2400
  log(`[Executor] Quiescence reached in ${Date.now() - quiescenceStart}ms ${reason}`);
2401
+ if (!this.matchFound || this.findAll) {
2402
+ const didScroll = await this.performAutoScroll(window);
2403
+ if (didScroll) {
2404
+ if (this.moduleInFlight.size > 0) {
2405
+ await this.waitForModuleWork(this.moduleWaitMs);
2406
+ }
2407
+ log("[Executor] Waiting for post-scroll quiescence...");
2408
+ const postScrollStart = Date.now();
2409
+ try {
2410
+ await this.waitForQuiescence();
2411
+ } catch (e) {
2412
+ warn("[Executor] Post-scroll quiescence wait failed:", e);
2413
+ }
2414
+ this.timings.quiescence_ms += Date.now() - postScrollStart;
2415
+ }
2416
+ }
2244
2417
  const renderedHtml = this.serializeDocument(window);
2245
2418
  this.windowClosed = true;
2246
2419
  const result = {