This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 18429 - [Shadow]: Specify imperative API for node distribution
Summary: [Shadow]: Specify imperative API for node distribution
Status: RESOLVED MOVED
Alias: None
Product: WebAppsWG
Classification: Unclassified
Component: HISTORICAL - Component Model (show other bugs)
Version: unspecified
Hardware: PC All
: P2 enhancement
Target Milestone: ---
Assignee: Dimitri Glazkov
QA Contact: public-webapps-bugzilla
URL:
Whiteboard:
Keywords:
Depends on: 18752 18753 18755 18756 18757 28443
Blocks: 22268 27994 28552 28561
  Show dependency treegraph
 
Reported: 2012-07-27 22:19 UTC by Dimitri Glazkov
Modified: 2015-05-27 03:24 UTC (History)
12 users (show)

See Also:


Attachments

Description Dimitri Glazkov 2012-07-27 22:19:33 UTC
Declarative insertion points syntax is not able to address several use cases (spec bugs to be filed by Hayato-san and Shinya-san). Here's a strawman for an imperative API:

The general idea is that the insertion point distribution is actually something that occurs as a result of running some function/callback. The callback could be powered with Mutation Observers, or some internal implementation. When this function runs, it operates on a special API of HTMLContentElement: the distributedChildren (name TBD) array.

Adding a Node to this array makes it appear projected into its HTMLContentElement. If a node is not a descendant of shadow host, an exception is thrown. If a node is a descendant of another node that is already a member of any distributedChildren array of the shadow subtree, that other node is ejected from the distributedChildren array to which it belonged. There are more cases to handle, but you get the gist.

The declarative API is simply a byproduct of some default function/callback. You can override this callback with your custom handler, thus disabling the declarative API.

The advantage here is that you can:

1) completely explain the magic of the declarative insertion point syntax

2) provide solutions to all of the use cases (including crazy stuff like dynamic creation of insertion points for varying number of children)

The disadvantage is that:

1) the API has tremendous foot-gun potential and we need to make darn sure to steer clear of those.

2) there are potential challenges with making this work in a performant fashion.
Comment 1 Dimitri Glazkov 2014-02-11 18:48:15 UTC
We still need the imperative API. It just needs to be addressed at the level of the underlying primitives and with proper layering.
Comment 2 Dimitri Glazkov 2014-03-07 18:39:46 UTC
There's an API proposed on http://lists.w3.org/Archives/Public/public-webapps/2014JanMar/0376.html. It needs a small tweak to play nice with distributions.

Distributions are necessary to maintain composability properties of Shadow DOM. Since it might be hard for a newcomer to reconstruct the whole picture from emails and bug comments, I took a bit of time to document it here: https://gist.github.com/dglazkov/e8402f9ab18ad7ef2e7d

tl;dr: distributions are a requirement for Shadow DOM. They are here to stay, because without them, Shadow DOM is just a fun theoretical exercise.

The tweak is minor: the add/remove methods populate a pool of candidates. We then hook processing this pool into pool population algorithm (http://w3c.github.io/webcomponents/spec/shadow/#dfn-pool-population-algorithm), modulo additional integrity checks (tbd). Even better, make this pool of candidates an Array.

This eliminates both the problem with the original proposal, and makes the recently proposed API work with distributions.
Comment 3 Dimitri Glazkov 2014-04-10 17:30:31 UTC
Here's a brainstorm gist for F2F session tomorrow.

https://gist.github.com/dglazkov/ce96f673b0b2ce7b8c55
Comment 4 Hayato Ito 2014-04-11 01:32:25 UTC
Inspired from the Dimitri's gist, here is yet another idea.
This is a kind of the mixture of 'Passive candidate array' and 'Selector-based Routing'.
I'd have to say that this is a *very* rough idea.

Given the same DOM tree from the gist,

>> // Make sure that contentSummaryUI selects 'all' from the pool.
>> contentSummaryUI.setAttribute('select', '*')
>> contentSummaryUI.getDistributedNode()
[firstSummary, <p>]

>> // New API for insertion point: addDistributionCandidate(shadow_host, selector)
>> // addDistributionCandidate(..., ...) takes a shadow host and "selector" expression to select nodes from the children of the shadow host.
>> var distributionCandidate1 = contentSummaryUI.addDistributionCandidate(div, "summary:first-of-type");

>> // Supports also specifying a distributed node directly???
>> // var distributionCandidate1 = contentSummaryUI.addDistributionCandidate(firstSummary);

>> contentSummaryUI.distributionCandidates()
[distributionCandidate1]

>> // If an insertion point has a non-empty distributionCandidates, the pool is populated from the list of candidates.

>> contentSummaryUI.getDistributedNodes()
[firstSummary]

>> Does `DistributionCandidate` have an API?
>> distributionCandidate1.nodes()
[firstSummary]

>> contentSummaryUI.removeDistributionCandidate(distributionCandidate1)
>> contentSummaryUI.distributionCandidates()
[]
>> contentSummaryUI.getDistributedNodes();
[firstSummary, <p>]
Comment 5 Dimitri Glazkov 2015-02-07 00:32:37 UTC
I just looked at this with fresh eyes and realized that I could polyfill an imperative API by using classes and matching their names to those of insertion points:

http://jsbin.com/baholi/3/edit?html,js,output
Comment 6 Dimitri Glazkov 2015-03-06 23:49:47 UTC
(In reply to Dimitri Glazkov from comment #5)
> I just looked at this with fresh eyes and realized that I could polyfill an
> imperative API by using classes and matching their names to those of
> insertion points:
> 
> http://jsbin.com/baholi/3/edit?html,js,output

Of course, it doesn't work with distributions :`(
Comment 7 Hayato Ito 2015-04-27 03:09:48 UTC
Let me move this bug to V2, assuming this is not a blocker for V1.
Comment 8 Anne 2015-04-27 03:20:19 UTC
Hayato, what would we do in v1? I think we concluded that since both <content select> and <content slot> were not working for everyone involved, we needed to do imperative distribution first.
Comment 9 Hayato Ito 2015-04-27 03:32:57 UTC
(In reply to Anne from comment #8)
> Hayato, what would we do in v1? I think we concluded that since both
> <content select> and <content slot> were not working for everyone involved,
> we needed to do imperative distribution first.

Yeah, imperative API is a stretch goal for v1, isn't it?

I'm okay to have a stretch goal under v1 umbrella. Let me move this back to v1.

We can decide to have the imperative APIs for v1 after July 13.
Comment 10 Anne 2015-04-27 05:37:01 UTC
I think that without an imperative API we're back to <content select> vs <content slot> and likely no closer to reaching agreement to ship. So my goal is to get the imperative API done.
Comment 11 Hayato Ito 2015-04-27 07:18:48 UTC
Thanks. I'm still uncertain, but let me contribute to the imperative API well and see how we can.

I really hope the discussion will be done in this bug. :)
Comment 12 Hayato Ito 2015-04-27 21:46:25 UTC
The relevant discussion on public-webapps@

https://lists.w3.org/Archives/Public/public-webapps/2015AprJun/0288.html
Comment 13 Hayato Ito 2015-04-30 14:36:05 UTC
For reference, could someone add a link to known use cases for an imperative API in this discussion?

I'd like to know every use cases we'd like to support in an imperative API.
Comment 14 Hayato Ito 2015-05-27 03:24:25 UTC
Moved to https://github.com/w3c/webcomponents/issues/60