Changes between Initial Version and Version 1 of ShadowDOMDesignathon


Ignore:
Timestamp:
Apr 20, 2012 8:19:12 PM (12 years ago)
Author:
Dimitri Glazkov
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • ShadowDOMDesignathon

    v1 v1  
     1                                                                     
     2                                                                     
     3                                                                     
     4                                             
     5
     6A ShadowTree is an extra thing that is attached to a DOM element. The
     7ShadowTree is the stack of ShadowRoot elements; it has a list of
     8ShadowRoots, a HTMLContentSelector.
     9
     10Issue 1: HTMLContentSelector has a doubly linked list of RefPtr
     11references to nodes--this needs to be fixed.
     12
     13Each ShadowRoot is a document fragment because it is behaviorally
     14similar to a document fragment. When you operate on it in DOM, you
     15aren’t able to copy it. If you try to appendChild(shadowRoot),
     16appendChild will steal its children but not disconnect the ShadowRoot
     17from his host, etc.
     18
     19apply-author-sheets: This controls whether stylesheets from the
     20document apply to elements in the shadow.
     21
     22When you look at the element and see how it operates on the shadow
     23tree, it passes pretty much all of the style recalc things to it if
     24you look at attach, and the shadow tree passes that on to the
     25ShadowRoots in the stack.
     26
     27Terminology--oldest and youngest ShadowRoots. Younger shadow roots are
     28ones that were created later; they are towards the top of the
     29stack. User-agent shadows are always the oldest, bottom-of-the-stack
     30shadows.
     31
     32There are two special nodes, HTMLContentElement and HTMLShadowElement,
     33which are subtypes of InsertionPoint. These are special in Shadow
     34DOM--see the spec--a thing that doesn't render but stuff goes into
     35it. The InsertionPoint has a list of nodes that are distributed to the
     36insertion point.
     37
     38The InsertionPoint takes the children of the host and, using the a CSS
     39selector, lays claim to light children of a node to populate this list.
     40
     41(??? The CSS selector for <content> is actually a member of
     42InsertionPoint. This is to simulate user-agent shadows for all
     43elements. ???)
     44
     45HTMLShadowElement is an InsertionPoint that is a reference to an older
     46tree in the stack. There are pointers from the ShadowRoot to the
     47HTMLShadowElement that includes it. We need these back pointers to
     48walk nodes in the flattened tree -- we never explicitly construct the
     49flattened tree, just leave enough breadcrumbs in the tree to construct
     50it implicitly.
     51
     52There's a thing called NodeRenderingContext which knows how to find
     53the renderer that is the renderer of the node that is effectively the
     54parent of a node in a flattened tree. For example, <content> and
     55<shadow> are "erased" by the flattened tree, so if your nextSibling in
     56the DOM is a <content>, NodeRenderingContext knows to recurse into
     57what nodes it has selected. Since flattened tree construction is
     58implicit, this is effected in how the renderers are wired up. Hence
     59NodeRenderingContext::parentNodeForRenderingAndStyle.
     60
     61Issues: NodeRenderingContext is a beast with phases, etc. etc. We like
     62having all of this indirection logic in one class, just the class
     63needs to be simplified.
     64
     65Issues: Distribution should be separated from attachment.
     66
     67With Shadow DOM suddenly you have an added level of complexity on node
     68attachment and detachment, computing styles, etc.
     69
     70Q? How do we calculate the insertion point for a node?
     71
     72In InsertionPoint::attach, ShadowTree starts with the youngest
     73ShadowRoot and distributes light children into its <content> insertion
     74points and the next oldest ShadowRoot into its <shadow> insertion
     75point (if any.) If the next oldest ShadowRoot was distributed into
     76this ShadowRoot, assignment iterates and and does assignment (and
     77attach) in the next oldest ShadowRoot on the stack.
     78
     79HTMLContentSelector has the logic to populate itself with light
     80children if they match a CSS selector.
     81
     82First it collects all of the host children to distribute later. Then
     83each <content> is traversed and candidates are drawn from the set.
     84
     85HTMLContentSelector has a "phase" which is to prevent reentrancy. If a
     86ShadowTree subtree is reattached, you don’t want to tickle the
     87distribution in reattach. tree->selector().isSelecting().
     88
     89HTMLContentSelector is basically the table mapping insertion point to
     90the nodes distributed to it.
     91
     92Bug: Rename ShadowTree to ShadowRootStack.
     93
     94Bug: Switch from HTMLContentSelector phase to a flag as the reentrancy
     95guard.
     96
     97(TODO: UML diagram)
     98
     99Bug: Remove the HTMLContent* (eg SelectionList, etc.) naming
     100convention, because HTMLX is for HTML element X, and we already have
     101HTMLContentElement. So let’s call it Content*.
     102
     103Bug: Rename HTMLContentSelection to something. "Selection" is bad
     104because it is like click-and-drag selection.
     105
     106Bug: Can HTMLContentSelection be just a list of nodes in the insertion
     107point, and get rid of HTMLContentSelection?
     108
     109We need the table to find the rendering parent of the distributed
     110node.
     111
     112Could consider a design where a ShadowRoot has a bit whether it has
     113been included with <shadow> or not, but not a pointer to the specific
     114<shadow> element itself, and have each ShadowRoot point to its first
     115docorder <shadow>.
     116
     117ComposedShadowTreeWalker -- this class gives you a facility to walk
     118the DOM as it is viewed as a result of the composition of this tree,
     119kind of as the user sitting in front of the browser sees it:
     120firstChild, lastChild, nextSibling, next (in tree order) etc. If you
     121want to access the tree "as it all looks as it is composed", use
     122ComposedTreeWalker. This is useful for event dispatch and things like
     123that. For example FocusController uses this because it needs to walk
     124the composed tree.
     125
     126TreeScope -- Document is a tree scope, but you can have subtrees that
     127are in separate tree scopes. It is a tree overlaid on the document
     128tree. Shadow DOM subtrees are in their own TreeScope and it is used to
     129control how style (CSSStyleSelector
     130... treeScope->applyAuthorSheets()) is applied in Shadow DOM.
     131
     132Replaced Elements and Shadow DOM
     133--------------------------------
     134
     135Suppose you have an <img> element or a <video> element and you create
     136a ShadowRoot for it. What the hell happens? ShadowRoot implies that
     137there is content and it messes with (replaces) the content. But
     138replaced elements are RenderReplaced and don’t render their content
     139like a <div>, etc.
     140
     141But what if you want to have an <img> and use Shadow DOM to give it a
     142polaroid frame?
     143
     144Conceptually this translates into the <img> node being built like this:
     145
     146img
     147+ {SR} <<user-agent shadow root>>
     148  + {image surface}
     149
     150Essentially what you have is an img node and then it has a Shadow Root
     151built-in (user-agent ShadowRoot) and it has something magic called an image surface which really renders the image.
     152
     153So if you have this:
     154
     155img
     156+ {SR} <<author shadow root>>
     157  + div
     158    + div
     159      + <shadow>
     160+ {SR} <<user-agent shadow root>>
     161  + {image surface}
     162
     163then you can achieve your Polaroid border.
     164
     165But today RenderReplaced is a completely black box, so we’re looking
     166for ideas about how to achieve this {image surface} thing.
     167
     168For form elements we just converted them to use Shadow DOM. With the
     169replaced elements like video and image... video is an interesting case
     170because it has some surface which is part of its render replaced
     171identity.
     172
     173RenderMedia m_children has one element in there. It lays out the image
     174to get the coordinates and then it lays out the controls.
     175
     176rniwa wanted to add :before and :after to RenderReplaced, so this
     177might be useful discussion for him.
     178
     179We could shim RenderReplaceds that have Shadow DOM and keep the
     180original RenderObject for use at <shadow>.
     181
     182This applies to: iframe, object, embed, img, video, audio, etc.
     183
     184One radical idea of dglazkov's: We create a different renderer
     185depending on whether it has a ShadowRoot or not. In createRenderer we
     186ask, do you have a ShadowRoot attached, and create a RenderBlock if it
     187does. We still have the same exact RenderMedia, RenderImage, etc. that
     188will set its size the right way and style will just work
     189correctly. Let's try it and see. shinyak thinks it will work.
     190
     191Events and Shadow DOM
     192---------------------
     193
     194Event retargeting is really really hard. hayato has a document
     195("Events in Shadow DOM") with ideas on how to improve it. It has to do
     196with the retargeting of related target eevents. Suppose we are in the
     197tree somewhere, moving a mouse from node X to node Y.
     198
     199o
     200+ o
     201  + Y <<mouseover>>
     202+ o
     203  + X <<mouseout>>
     204
     205the target for mouseout will be X and related target will by Y. The
     206target for mouseover will be Y and related target will be X.
     207
     208When you get into Shadow DOM this gets really complex. The code is
     209simple but it is conceptually hard. It is OK if your nodes are in the
     210same tree, but what if they’re in a different tree? For example:
     211
     212o
     213+ {SR}
     214  + Y
     215+ X
     216
     217you don't want to leak node Y. So you have to retarget it to o.
     218
     219If you have
     220
     221a
     222+ {SR}
     223  + Y
     224  + X
     225+ o
     226
     227when you listen on a and retarget the events for X and Y to a, and the
     228event bubbles, you have to not let the event escape. Otherwise you get
     229nonsense like mouseout from a to a and mouseover form a to a.
     230
     231When you have multiple shadow trees things get really complicated.
     232
     233Event war story: The first implementation of the media controls
     234generated a spew of mouseover mouseout as the mouse moved over the
     235volume button to the volume slider and they were fired out of the
     236video element, with mouseover video from video to video and mouseout
     237of video from video to video etc.
     238
     239Events are basically dispatched "as rendered."