#105: Shadow DOM — attachShadow + Slot + Event-Retargeting (Non-Visual-Optimized) #105
Labels
No labels
bug
docs
feature
housekeeping
html-spec
performance
react-compat
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
glow-all/true-headless-browser#105
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problembeschreibung
OwnWindow/OwnDocument fehlt die Shadow-DOM-Implementierung (attachShadow, ShadowRoot, Slot). Viele Frameworks (Vue 3 Teleport, LitElement, Angular Components, Stencil) erstellen Shadow Roots für Kapselung. Ohne attachShadow stürzen diese Frameworks beim
el.attachShadow()-Aufruf ab.Betroffen: Vue 3 (Teleport/Komponenten-Isolation), LitElement, Angular, Stencil, YouTube (Polymer Shadow DOM), webcomponents.org
Architektur-Analyse
Aktueller Stand
Es gibt eine
installShadowDOM()-Funktion insrc/shadow-dom/, die auf Happy DOMs Prototypen patcht. Für OwnWindow muss dies auf unsere eigenen Klassen (OwnEvent,OwnEventTarget) umgestellt werden.Ziel-Architektur — Non-Visual-Optimized
Non-Visual Optimierungen
delegatesFocus: truewird akzeptiert aber visuelles Fokus-Management ist noopassignedNodes()— kein visuelles ReflowcomposedPath()auf OwnEvent — kein visueller Hit-Test, nur DOM-Tree-Walkslotchange-Event: Wird beiappendChild/removeChildim Slot ausgelöst — kein ResizeObserverRoot Causes
Element.prototype.attachShadowexistiert nicht auf unseren Dom-KlassenHTMLSlotElement.assignedNodes(),assignedElements(),slotchange-EventLosungsansatze
Option A (empfohlen): Minimaler Shadow DOM mit Fokus auf Framework-Kompatibilitat
Kernidee: Implementiere ShadowRoot als OwnDocumentFragment-Subklasse, patche attachShadow auf Element.prototype, installiere Slot-API + Event-Retargeting auf unsere Prototypen. Kein visuelles Rendering, kein Layout — nur DOM-Spezifikation.
Teil 1: ShadowRoot-Klasse
Non-Visual-Optimierungen:
elementFromPoint()/elementsFromPoint()gebenhost/[host]zurück — kein visueller Hit-TestpictureInPictureElement,fullscreenElementgebennullzurück — kein visueller FullscreengetSelection()gibtnullzurück — kein visuelles Selection-APITeil 2: attachShadow auf Element.prototype
Teil 3: Slot-API (Non-Visual-Optimized)
Teil 4: Event-Retargeting auf eigene Klassen
Vorteile:
composed: true/falsewird korrekt behandeltNachteile:
<slot>-Rendering (aber auch nicht benotigt fur Headless)slotchange-Ereignis nur bei DOM-Operationen, nicht bei CSS-basiertem Re-AssignmentOption B: Volle Shadow-DOM-Spezifikation
Komplette Implementierung nach DOM-Spec mit shadow-piercing, CSS-Scoping, ::part, ::theme.
Problem: ~2000 Zeilen fur Features die kein Headless-Browser braucht. CSS-Scoping, ::part, ::theme sind nutzlos ohne visuelles Rendering. React/Vue/Lit brauchen nur attachShadow + Slot + Event-Retargeting.
Option C: Happy DOMs Shadow-DOM recyceln
Happy DOM bietet Shadow-DOM out-of-the-box. Statt eigener Implementierung Shadow-DOM aus Happy DOM importieren und auf unsere Nodes mappen.
Problem: Happy DOMs Shadow-Root arbeitet mit Happy-DOM-Elementen, nicht unseren OwnElement-Instanzen. Ein Mapping ware komplexer als eine minimal-Eigenimplementierung (~500 Zeilen).
Entscheidung: Option A
attachShadow()undassignedNodes()— keinen CSS-Scoping-Algorithmus. Option A liefert das mit ~350 Zeilen.composedPath()ist ein DOM-Tree-Walk,assignedNodes()ist ein Name-Match.installShadowDOM()-Patching-Logik insrc/shadow-dom/event-retargeting.tskann mit minimalen Anderungen auf OwnEvent/OwnEventTarget umgestellt werden.Akzeptanzkriterien
Element.attachShadow(init)erstellt ShadowRootel.shadowRootgibt ShadowRoot beimode: "open"zuruckel.shadowRootgibtnullbeimode: "closed"zuruckshadowRoot.modeist korrekt gesetztshadowRoot.hostverweist auf das Host-ElementshadowRoot.appendChildfunktioniert (erbt von DocumentFragment)HTMLSlotElement.assignedNodes()gibt zugewiesene Nodes zuruckHTMLSlotElement.assignedElements()gibt zugewiesene Elemente zuruckslotchange-Event feuert bei Anderungen im Slotevent.composedPath()traversiert korrekt durch Shadow-Boundariesevent.targetwird beim Uberschreiten einer Shadow-Boundary retargetedcomposed: falseEvents stoppen an der Shadow-BoundaryattachShadow()wirftNotSupportedErrorelementFromPoint()gibtnullzuruck (kein visueller Hit-Test)Betroffene Dateien
src/dom/shadow-root.tssrc/dom/slot.tssrc/dom/node.tssrc/dom/event-target.tssrc/shadow-dom/event-retargeting.tssrc/shadow-dom/slot-assignment.tssrc/dom/index.tstests/unit/dom-shadow.test.tsDependencies
752554b) — ShadowRoot erbt von OwnDocumentFragmentQuerverweise
src/shadow-dom/event-retargeting.ts— bestehender Event-Retargeting-Code (Happy-DOM-Patching)references/non-visual-dom-opti.md— Non-Visual-DOM-Optimierungs-ProtocolTechnische Risiken
assignedNodes({ flatten: true })erfordert Traversal uber mehrere Shadow-Boundaries. Losung: flatten=true gibtassignedNodes()+ Fallback-Content.mode: "open"auf beiden Levels.Performance-Impact
Testplan
Unit-Tests (20+)
slotchangemehrfach hintereinander (bulk mutations)Integration-Tests (5+)
✅ Resolved in commit
440573b#106: MutationObserver vollstandig implementiert — MutationRecord, MutationObserver, MutationRegistry mit Mikrotask-Queueing, Node-Hooks fur childList/attributes/characterData
#109: Custom Elements Lifecycle — connectedCallback/disconnectedCallback/attributeChangedCallback, Parser-Integration via _customElementsRegistry, attachShadow in OwnDOM
#105/#107/#108/#110: Bereits implementiert (99 Tests grun)
Tests: 247 pass, 0 fail