Skip to content

Commit 990ff9e

Browse files
committed
fix(autoHeightBridge): clamp runaway heights, extend anomaly retries, and robustly collect measurement nodes
- add MAX_REASONABLE_HEIGHT (120000) and use it to sanitize oversized measurements - increase anomaly retry window and retry before clamping; fallback to last known good height when available - make element collection resilient when wrapper is missing (collect body/html appropriately) - update README to document the sanity guard and media / ResizeObserver behavior
1 parent 0ca6ff3 commit 990ff9e

2 files changed

Lines changed: 22 additions & 10 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ React Native WebView that auto-sizes to match its HTML content—whether you loa
1818
- 🚀 Modern pipeline powered by `ResizeObserver`, `MutationObserver`, `visualViewport`, and font-load events with graceful fallbacks.
1919
- 🖼 Media aware: images, iframes, and videos schedule immediate + next-frame re-measures as soon as they finish loading.
2020
- 🧼 Auto-prunes trailing `<br>`/empty `<p>` tags that CMS editors often append, eliminating phantom spacing.
21+
- 🛡️ Sanity guard clamps runaway heights and retries with the last good value, so flaky pages never lock your layout.
2122
- 🧵 Keeps the WebView scroll-disabled so outer `ScrollView`s and gesture handlers stay silky smooth.
2223
- 🎨 Transparent background by default; style the container however you like.
2324
- ⚙️ Friendly API with `minHeight`, `containerStyle`, and `onHeightChange` callbacks.
@@ -92,11 +93,13 @@ The example showcases:
9293
- Trailing `<br>` and empty `<p>` tags are stripped automatically so CMS exports don’t leave phantom padding.
9394
- Images, iframes, and videos reschedule measurements the moment they finish loading—perfect for hero images at the end of an article.
9495
- Wrapper rebuild + fallback timers keep measurements stable even if the remote page rewrites the entire DOM after load.
96+
- Measurements above safe bounds are retried and then clamped to the last known good height, protecting against broken markup or third-party scripts.
9597

9698
## 🧠 How It Works
9799

98100
- Injected bridge re-parents all body children into a dedicated wrapper, trims trailing blanks, and observes DOM mutations, layout changes, font loads, and viewport shifts.
99101
- Media events (images / iframes / video) trigger immediate + next-frame samples so late assets still report accurate heights.
102+
- Media elements stay observed via `ResizeObserver` + decode promises, catching intrinsic size changes without duplicate network requests.
100103
- Height calculations are debounced via `requestAnimationFrame` and a short idle timer to prevent resize storms.
101104
- Measurements arrive through `postMessage`, then `useAutoHeight` coalesces them into a single render per frame.
102105
- Package exports the bridge, hook, and helpers individually, making it easy to build bespoke wrappers when needed.

src/constants/autoHeightBridge.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const AUTO_HEIGHT_BRIDGE = `(() => {
1111
var IDLE_DEBOUNCE_MS = 160;
1212
var INITIAL_FALLBACK_MS = 600;
1313
var MAX_FALLBACK_MS = 4000;
14+
var MAX_REASONABLE_HEIGHT = 120000;
1415
1516
if (typeof window === 'undefined' || typeof document === 'undefined') {
1617
return;
@@ -274,16 +275,17 @@ export const AUTO_HEIGHT_BRIDGE = `(() => {
274275
);
275276
};
276277
277-
collect(wrapper);
278-
if (body && body !== wrapper) {
279-
collect(body);
280-
}
281-
if (html && html !== wrapper) {
282-
collect(html);
278+
if (wrapper) {
279+
collect(wrapper);
280+
} else {
281+
if (body) {
282+
collect(body);
283+
}
284+
if (html && html !== body) {
285+
collect(html);
286+
}
283287
}
284288
285-
values.push(window.innerHeight || 0);
286-
287289
if (!values.length) {
288290
return 0;
289291
}
@@ -304,12 +306,19 @@ export const AUTO_HEIGHT_BRIDGE = `(() => {
304306
return;
305307
}
306308
307-
if (sanitized > 100000) {
309+
if (sanitized > MAX_REASONABLE_HEIGHT) {
308310
state.anomalyCount += 1;
309-
if (state.anomalyCount < 3) {
311+
312+
if (state.anomalyCount <= 5) {
310313
scheduleMeasure(true);
311314
return;
312315
}
316+
317+
if (state.lastHeight > 0 && state.lastHeight <= MAX_REASONABLE_HEIGHT) {
318+
sanitized = state.lastHeight;
319+
} else {
320+
sanitized = MAX_REASONABLE_HEIGHT;
321+
}
313322
} else {
314323
state.anomalyCount = 0;
315324
}

0 commit comments

Comments
 (0)