| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- #!/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()
|