Re: Imperative API for Node Distribution in Shadow DOM (Revisited)

A distribute callback means running script any time we update distribution,
which is inside the style update phase (or event path computation phase,
...) which is not a location we can run script. We could run script in
another scripting context like is being considered for custom layout and
paint though, but that has a different API shape since you'd register a
separate .js file as the "custom distributor." like

(document || shadowRoot).registerCustomDistributor({src: "distributor.js"});

I also don't believe we should support distributing any arbitrary
descendant, that has a large complexity cost and doesn't feel like
simplification. It makes computing style and generating boxes much more
complicated.

A synchronous childrenChanged callback has similar issues with when it's
safe to run script, we'd have to defer it's execution in a number of
situations, and it feels like a duplication of MutationObservers which
specifically were designed to operate in batch for better performance and
fewer footguns (ex. a naive childrenChanged based distributor will be n^2).


On Mon, Apr 27, 2015 at 8:48 PM, Ryosuke Niwa <rniwa@apple.com> wrote:

>
> > On Apr 27, 2015, at 12:25 AM, Justin Fagnani <justinfagnani@google.com>
> wrote:
> >
> > On Sun, Apr 26, 2015 at 11:05 PM, Anne van Kesteren <annevk@annevk.nl>
> wrote:
> >> On Sat, Apr 25, 2015 at 10:49 PM, Ryosuke Niwa <rniwa@apple.com> wrote:
> >> > If we wanted to allow non-direct child descendent (e.g. grand child
> node) of
> >> > the host to be distributed, then we'd also need O(m) algorithm where
> m is
> >> > the number of under the host element.  It might be okay to carry on
> the
> >> > current restraint that only direct child of shadow host can be
> distributed
> >> > into insertion points but I can't think of a good reason as to why
> such a
> >> > restriction is desirable.
> >
> > The main reason is that you know that only a direct parent of a node can
> distribute it. Otherwise any ancestor could distribute a node, and in
> addition to probably being confusing and fragile, you have to define who
> wins when multiple ancestors try to.
> >
> > There are cases where you really want to group element logically by one
> tree structure and visually by another, like tabs. I think an alternative
> approach to distributing arbitrary descendants would be to see if nodes can
> cooperate on distribution so that a node could pass its direct children to
> another node's insertion point. The direct child restriction would still be
> there, so you always know who's responsible, but you can get the same
> effect as distributing descendants for a cooperating sets of elements.
>
> That's an interesting approach. Ted and I discussed this design, and it
> seems workable with Anne's `distribute` callback approach (= the second
> approach in my proposal).
>
> Conceptually, we ask each child of a shadow host the list of distributable
> node for under that child (including itself). For normal node without a
> shadow root, it'll simply itself along with all the distribution candidates
> returned by its children. For a node with a shadow root, we ask its
> implementation. The recursive algorithm can be written as follows in pseudo
> code:
>
> ```
> NodeList distributionList(Node n):
>   if n has shadowRoot:
>     return <ask n the list of distributable noes under n (1)>
>   else:
>     list = [n]
>     for each child in n:
>       list += distributionList(n)
>     return list
> ```
>
> Now, if we adopted `distribute` callback approach, one obvious mechanism
> to do (1) is to call `distribute` on n and return whatever it didn't
> distribute as a list. Another obvious approach is to simply return [n] to
> avoid the mess of n later deciding to distribute a new node.
>
> >> So you mean that we'd turn distributionList into a subtree? I.e. you
> >> can pass all descendants of a host element to add()? I remember Yehuda
> >> making the point that this was desirable to him.
> >>
> >> The other thing I would like to explore is what an API would look like
> >> that does the subclassing as well. Even though we deferred that to v2
> >> I got the impression talking to some folks after the meeting that
> >> there might be more common ground than I thought.
> >
> > I really don't think the platform needs to do anything to support
> subclassing since it can be done so easily at the library level now that
> multiple generations of shadow roots are gone. As long as a subclass and
> base class can cooperate to produce a single shadow root with insertion
> points, the platform doesn't need to know how they did it.
>
> I think we should eventually add native declarative inheritance support
> for all of this.
>
> One thing that worries me about the `distribute` callback approach (a.k.a.
> Anne's approach) is that it bakes distribution algorithm into the platform
> without us having thoroughly studied how subclassing will be done upfront.
>
> Mozilla tried to solve this problem with XBS, and they seem to think what
> they have isn't really great. Google has spent multiple years working on
> this problem but they come around to say their solution, multiple
> generations of shadow DOM, may not be as great as they thought it would be.
> Given that, I'm quite terrified of making the same mistake in spec'ing how
> distribution works and later regretting it.
>
> In that regard, the first approach w/o distribution has an advantage of
> letting Web developer experiment with the bare minimum and try out which
> distribution algorithms and mechanisms work best.
>
> - R. Niwa
>
>
>

Received on Tuesday, 28 April 2015 20:05:34 UTC