- From: Elliott Sprehn <esprehn@chromium.org>
- Date: Tue, 28 Apr 2015 13:04:24 -0700
- To: Ryosuke Niwa <rniwa@apple.com>
- Cc: Justin Fagnani <justinfagnani@google.com>, Anne van Kesteren <annevk@annevk.nl>, WebApps WG <public-webapps@w3.org>, Erik Bryn <erik@erikbryn.com>, Dimitri Glazkov <dglazkov@google.com>, "Edward O'Connor" <eoconnor@apple.com>
- Message-ID: <CAO9Q3iLtMbfwdu7gfFznnRxnmfJJcPK2w6Du6N-1XMa72ksDzQ@mail.gmail.com>
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