@grabbit-labs/dynafetch 0.2.5 → 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 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` | `2000` | Hard cap on wait time |
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
@@ -890,6 +890,8 @@ var Executor = class {
890
890
  this.originalGlobalMessageChannel = void 0;
891
891
  this.originalGlobalMessagePort = void 0;
892
892
  this.activeTimerHandles = /* @__PURE__ */ new Set();
893
+ this.domMutationVersion = 0;
894
+ this.domMutationObserver = null;
893
895
  // Simple telemetry counters (useful for debugging).
894
896
  this.telemetry_stubbed = 0;
895
897
  this.telemetry_proxy = 0;
@@ -1008,6 +1010,29 @@ var Executor = class {
1008
1010
  }
1009
1011
  this.activeTimerHandles.clear();
1010
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
+ }
1011
1036
  async performAutoScroll(window) {
1012
1037
  const steps = this.clampMs(Number(process.env.PHANTOM_AUTO_SCROLL_STEPS ?? 3), 0, 12);
1013
1038
  if (steps === 0) return false;
@@ -1065,7 +1090,7 @@ var Executor = class {
1065
1090
  const hardMaxCap = this.clampMs(Number(process.env.PHANTOM_QUIESCENCE_MAX_CAP_MS ?? 8e3), 500, 6e4);
1066
1091
  const minWaitMs = this.clampMs(quiescence?.minWaitMs ?? 75, 0, 1e4);
1067
1092
  const idleWaitMs = this.clampMs(quiescence?.idleWaitMs ?? 100, 0, 1e4);
1068
- const maxWaitMs = this.clampMs(quiescence?.maxWaitMs ?? 2e3, 0, hardMaxCap);
1093
+ const maxWaitMs = this.clampMs(quiescence?.maxWaitMs ?? 3e3, 0, hardMaxCap);
1069
1094
  const hardModuleCap = this.clampMs(Number(process.env.PHANTOM_MODULE_WAIT_MAX_CAP_MS ?? 3e4), 1e3, 12e4);
1070
1095
  this.moduleWaitMs = this.clampMs(Number(process.env.PHANTOM_MODULE_WAIT_MS ?? moduleWaitMsOverride ?? 6e3), 1e3, hardModuleCap);
1071
1096
  this.quiescenceOptions = { minWaitMs, idleWaitMs, maxWaitMs };
@@ -2272,6 +2297,23 @@ var Executor = class {
2272
2297
  }
2273
2298
  });
2274
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
+ }
2275
2317
  let readyStateValue = "loading";
2276
2318
  try {
2277
2319
  Object.defineProperty(window.document, "readyState", {
@@ -2414,6 +2456,11 @@ var Executor = class {
2414
2456
  this.timings.quiescence_ms += Date.now() - postScrollStart;
2415
2457
  }
2416
2458
  }
2459
+ try {
2460
+ await this.waitForDomSettle(window);
2461
+ } catch (e) {
2462
+ warn("[Executor] DOM settle wait failed:", e);
2463
+ }
2417
2464
  const renderedHtml = this.serializeDocument(window);
2418
2465
  this.windowClosed = true;
2419
2466
  const result = {
@@ -2430,6 +2477,11 @@ var Executor = class {
2430
2477
  this.unrefNewMessagePorts(initialActiveHandles);
2431
2478
  return result;
2432
2479
  } finally {
2480
+ try {
2481
+ this.domMutationObserver?.disconnect?.();
2482
+ } catch {
2483
+ }
2484
+ this.domMutationObserver = null;
2433
2485
  const g = globalThis;
2434
2486
  if (this.originalGlobalMessageChannel !== void 0) {
2435
2487
  g.MessageChannel = this.originalGlobalMessageChannel;