#!/usr/bin/env python3 """One-off diagnostic: which subtree creates the page-level +N px? Bisects by hiding top-level subtrees (topbar vs main etc.) and reading documentElement.scrollWidth, then descends into the guilty container's children. Prints the culprit chain. Not part of the bundle; a T12 development aid kept for reproducibility. """ import json import os import sys HERE = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, HERE) import mobile_audit as ma # noqa: E402 import harness # noqa: E402 if "WEBSTACK_WORK" not in os.environ: os.environ["WEBSTACK_WORK"] = os.path.join( harness.REPO, "build", "ws-mobile") def bisect(chrome): js = r""" (() => { const de = document.documentElement; const base = de.scrollWidth - de.clientWidth; const report = {base: base, steps: []}; const direct = []; // step 1: each direct child of body toggled alone for (const child of document.body.children) { const prev = child.style.display; child.style.display = 'none'; report.steps.push({hide: child.tagName + '.' + child.className, dx: de.scrollWidth - de.clientWidth}); child.style.display = prev; } // step 2: every element with scrollWidth > clientWidth (visible ox), // skipping elements inside a scroll container const inScroller = (el) => { for (let a = el.parentElement; a; a = a.parentElement) { const ox = getComputedStyle(a).overflowX; if (ox !== 'visible') return true; } return false; }; for (const el of document.querySelectorAll('*')) { if (inScroller(el)) continue; const cs = getComputedStyle(el); if (cs.position === 'fixed') continue; if (el.scrollWidth - el.clientWidth > 4 && el.clientWidth > 0) { direct.push({el: el.tagName + '.' + (el.className || ''), over: el.scrollWidth - el.clientWidth, rectRight: Math.round(el.getBoundingClientRect().right)}); } } // step 3: text nodes whose range right edge exceeds the viewport const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT); const texts = []; let node; while ((node = walker.nextNode())) { const range = document.createRange(); range.selectNodeContents(node); const rects = range.getClientRects(); for (const r of rects) { if (r.width > 0 && r.right > de.clientWidth + 0.5) { texts.push({text: node.textContent.slice(0, 60), right: Math.round(r.right), parent: node.parentElement.tagName + '.' + (node.parentElement.className || '')}); break; } } } report.direct = direct.slice(0, 20); report.texts = texts.slice(0, 20); return report; })() """ return chrome._eval(js) def main(): route = sys.argv[1] if len(sys.argv) > 1 else "/rules" width = int(sys.argv[2]) if len(sys.argv) > 2 else 360 chromium = ma.find_chromium() ctx = harness.start_bundle("t12dbg") harness.CTX = ctx try: ids = ma.seed(ctx) # fresh login frame for the browser frames = harness.directives("/login") content = json.loads(frames[0]["snapshot_frame"]["content"]) action = content["public"]["login"] status, body = harness.http("POST", action["uri"], {"username": "admin", "password": "adminpass123"}) frame = None for directive in json.loads(body): if directive["type"] == "set": candidate = json.loads(directive["snapshot_frame"]["content"]) if candidate["slot"]["type"] == "auth": frame = directive["snapshot_frame"] chrome = ma.Chrome(chromium, harness.free_port()) try: chrome.connect() chrome.add_init_script( "try { localStorage.setItem('statum:auth', %s); } catch (e) {}" % json.dumps(json.dumps(frame))) chrome.set_viewport(width) chrome.goto(harness.WEB + route) print(json.dumps(bisect(chrome), indent=1)) finally: chrome.close() finally: try: ctx.app.terminate() ctx.app.wait(timeout=10) except OSError: pass if __name__ == "__main__": main()