CSSOM/Layout Engine — Real getComputedStyle + Box Model Integration (#86 amazon.de) #96

Closed
opened 2026-06-19 11:41:36 +00:00 by Artur · 1 comment
Owner

Problembeschreibung

Vorher: getComputedStyle() und Layout-Properties (offsetWidth, getBoundingClientRect) gaben synthetische Fake-Werte zurück. Das reicht für einfache Bot-Detection, aber Frameworks die CSSOM/Layout lesen (React Scheduler, IntersectionObserver, ResizeObserver) bekommen falsche Daten.

Nachher: Echter CSS-Parser (cssom) + echte CSSStyleDeclaration (cssstyle) + kaskadierter Style-Resolver + vereinfachtes Box Model.

Architektur (aggressiv optimiert)

src/css/
├── types.ts              — 124 CSS Initial Values + Inheritance Map
├── selector-matcher.ts   — CSS Selector Parser + Matcher (5 Typen: element, class, id, descendant, comma)
├── style-engine.ts       — CSS Cascade + Computed Style Resolution (WeakMap-cached)
├── layout-engine.ts      — Box Model: offset*, client*, getBoundingClientRect
└── index.ts              — Re-exports

Shortcuts (was fehlt — kann später kommen):

  • [attr], :nth-child, :hover, ::before Selektoren → false (kein Error)
  • Flexbox/Grid Layout → nur Normal Flow (Standard-Framework-Fall ist OK)
  • External CSS Fetching → nur
## Problembeschreibung **Vorher:** `getComputedStyle()` und Layout-Properties (`offsetWidth`, `getBoundingClientRect`) gaben **synthetische Fake-Werte** zurück. Das reicht für einfache Bot-Detection, aber Frameworks die CSSOM/Layout lesen (React Scheduler, IntersectionObserver, ResizeObserver) bekommen falsche Daten. **Nachher:** Echter CSS-Parser (cssom) + echte CSSStyleDeclaration (cssstyle) + kaskadierter Style-Resolver + vereinfachtes Box Model. ## Architektur (aggressiv optimiert) ``` src/css/ ├── types.ts — 124 CSS Initial Values + Inheritance Map ├── selector-matcher.ts — CSS Selector Parser + Matcher (5 Typen: element, class, id, descendant, comma) ├── style-engine.ts — CSS Cascade + Computed Style Resolution (WeakMap-cached) ├── layout-engine.ts — Box Model: offset*, client*, getBoundingClientRect └── index.ts — Re-exports ``` **Shortcuts (was fehlt — kann später kommen):** - [attr], :nth-child, :hover, ::before Selektoren → false (kein Error) - Flexbox/Grid Layout → nur Normal Flow (Standard-Framework-Fall ist OK) - External CSS Fetching → nur <style> Tags (CDN CSS selten nötig) - !important → ignoriert (extrem selten in Framework-Code) - calc() → vereinfacht (selten für kritische Werte) **Was korrekt ist:** - getComputedStyle(el) → 124 Properties mit korrekten Initial Values - CSS Cascade: inline > id > class > element (volle Specificity) - Inheritance: font-size/color etc. vom Parent - Box Model: content-box + border-box, padding, margin, border - %-width/height aufgelöst gegen Parent - display:none → zero Box - offsetWidth/offsetHeight = border-box - clientWidth/clientHeight = padding-box - getBoundingClientRect = absolute Position + Dimension ## Integration in Page StyleEngine + LayoutEngine müssen in `page.ts` installiert werden: 1. `StyleEngine.install(win, doc)` → patcht `window.getComputedStyle` 2. `LayoutEngine.install(win)` → patcht Element.prototype (offsetWidth, etc.) 3. `StyleEngine.addStyleText()` für jedes <style> Tag während Parser 4. Invalidate Style Cache bei DOM-Mutationen ## Abhängigkeiten - `cssom@0.5.0` — CSS Text → CSSRuleList - `cssstyle@6.2.0` — CSSStyleDeclaration ## Tests 41 Tests in tests/unit/css-layout-engine.test.ts (alle grün): - 8 × Types (initial, inheritance, parsePx) - 12 × Selector Parser + Matcher - 11 × Style Engine (cascade, inline, inheritance, caching) - 10 × Layout Engine (offset*, client*, BoundingRect, box-sizing, %-values) ## Auswirkungen - amazon.de (#86): WAF-Challenge liest offsetWidth/Height → bisher Fake-Werte, jetzt reale - React 18: Scheduler nutzt getComputedStyle für Font-Metrics → bisher falsch - IntersectionObserver: boundingClientRect jetzt korrekt
Author
Owner

Issue #96 abgeschlossen

Branch: feat/issue-96-cssom-optimization
Commit: cba8d80

Was wurde gemacht?

AGGRESSIVE PERFORMANCE OPTIMIERUNGEN:

  • Selector-Parsing-Cache: Map<cssText, Selector[]> vermeidet wiederholtes Parsen
  • Initial-Declaration-Singleton: 124 Iterationen → 1 cssText + Clone (via getBaseCssText())
  • Re-entrancy-Guard: _scanning Flag verhindert rekursive scanDocument-Aufrufe
  • Dedup-Tracking: _seenCssTexts Set dedupliziert style tags
  • Attribut-Mutation-Observer: style/class/id Änderungen → auto-invalidate
  • Null-Safety: Layout-Getter geben 0 für null/undefined zurück
  • ZERO_BOX Singleton: display:none alloc-frei
  • Wildcard-Support: * Selector matcher funktioniert jetzt korrekt
  • Element.matches() + closest(): Patched auf unseren Selector Matcher

TEST-COVERAGE: 50 → 109 Tests (+118%, 247 expect())

  • 14x CSS Types (edge cases, shorthand, getBaseCssText singleton)
  • 14x Selector Parser (compound, specificity, child combinator, wildcard)
  • 14x Selector Matcher (deep descendant, wildcard, matchesSelectors)
  • 24x Style Engine (inheritance chain, @media skip, @import skip, reset, scanDocument dedup)
  • 19x Layout Engine (border, scroll, vw/vh/em, null safety)
  • 7x Integration (matches, closest, compound selectors)
  • 5x Performance (cache hit ratio, bulk rules)

Nächste Schritte

  • PR mergen → master
  • Issue #86 (amazon.de 0.5KB DOM) verifizieren — CSSOM/Layout Engine sollte viele WAF-Probleme lösen
  • Danach #103 CSP/Trusted Types
## ✅ Issue #96 abgeschlossen **Branch:** `feat/issue-96-cssom-optimization` **Commit:** `cba8d80` ### Was wurde gemacht? **AGGRESSIVE PERFORMANCE OPTIMIERUNGEN:** - **Selector-Parsing-Cache**: Map<cssText, Selector[]> vermeidet wiederholtes Parsen - **Initial-Declaration-Singleton**: 124 Iterationen → 1 cssText + Clone (via `getBaseCssText()`) - **Re-entrancy-Guard**: `_scanning` Flag verhindert rekursive `scanDocument`-Aufrufe - **Dedup-Tracking**: `_seenCssTexts` Set dedupliziert style tags - **Attribut-Mutation-Observer**: style/class/id Änderungen → auto-invalidate - **Null-Safety**: Layout-Getter geben 0 für null/undefined zurück - **ZERO_BOX Singleton**: display:none alloc-frei - **Wildcard-Support**: `*` Selector matcher funktioniert jetzt korrekt - **Element.matches() + closest()**: Patched auf unseren Selector Matcher **TEST-COVERAGE: 50 → 109 Tests (+118%, 247 expect())** - 14x CSS Types (edge cases, shorthand, getBaseCssText singleton) - 14x Selector Parser (compound, specificity, child combinator, wildcard) - 14x Selector Matcher (deep descendant, wildcard, matchesSelectors) - 24x Style Engine (inheritance chain, @media skip, @import skip, reset, scanDocument dedup) - 19x Layout Engine (border, scroll, vw/vh/em, null safety) - 7x Integration (matches, closest, compound selectors) - 5x Performance (cache hit ratio, bulk rules) ### Nächste Schritte - PR mergen → `master` - Issue #86 (amazon.de 0.5KB DOM) verifizieren — CSSOM/Layout Engine sollte viele WAF-Probleme lösen - Danach #103 CSP/Trusted Types
Artur closed this issue 2026-06-19 19:56:16 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
glow-all/true-headless-browser#96
No description provided.