Intent to Implement and Ship: Node.getRootNode(options)

99 views
Skip to first unread message

Hayato Ito

unread,
Jul 20, 2016, 2:05:47 AM7/20/16
to blink-dev
Contact emails

Spec

Summary
Node.getRootNode() is the new name for Node.rootNode [1].

Blink had shipped Node.rootNode, however, it turned out that it was not Web compatible [2], and Node.rootNode was removed from Blink [3].
Node.getRootNode() is the new name on which browser vendors agreed as the new name for Node.rootNode.


Interoperability and Compatibility Risk
This is a new feature, hoping this name is Web compatible.

Ongoing technical constraints
No.

Will this feature be supported on all six Blink platforms (Windows, Mac, Linux, Chrome OS, Android, and Android WebView)?
Yes.

OWP launch tracking bug

Link to entry on the feature dashboard

Requesting approval to ship?
Yes.

Elliott Sprehn

unread,
Jul 20, 2016, 12:18:55 PM7/20/16
to Hayato Ito, blink-dev

This isn't just a rename, it's adding features at this same time with the options dictionary. Hopefully in the future we don't add features at the same time we fix name conflicts. :)

It's really hard to parse that spec language, in examples what do the two modes do?

Hayato Ito

unread,
Jul 20, 2016, 9:18:29 PM7/20/16
to Elliott Sprehn, blink-dev
Yeah, that's a good point. Sorry for not mentioning it.

An optional parameter allows us to get the root's host's root's host's root's host's root, .... recursively, until it reaches the most *ancestor* root.

Example:

let host1 = document.createElement('div');

let root1 = host1.attachShadow({ mode: 'open' };
let host2 = document.createElement('div');
root1.appendChild(host2);

let root2 = host2.attachShadow({ mode: 'open' };
let child2 = root2.appendChild
root2.appendChild(child2)

Now, we have the following hierarchy:

<div> # host1
  <#root1>   # host1's shadow root
    <div> #host2
      <#root2> # host2's shadow root
        <div>  # child2

Optional parameter changes the getRootNodes(optional)'s behavior as follows:

assert(child2.getRootNode() == root2);
assert(child2.getRootNode({ composed: true}) == host1);

assert(host2.getRootNode() == root1);
assert(host2.getRootNode({ composed: true}) == host1);

assert(host1.getRootNode() == host1);
assert(host1.getRootNode({ composed: true}) == host1);

If we append host1 to document.body:
> document.body.appendChild(host1)

Then, getRootNode({ composed: true}) would return a document.

assert(child2.getRootNode() == root2);
assert(child2.getRootNode({ composed: true}) == document);

assert(host2.getRootNode() == root1);
assert(host2.getRootNode({ composed: true}) == document);

assert(host1.getRootNode() == document);
assert(host1.getRootNode({ composed: true}) == document);

TAMURA, Kent

unread,
Jul 20, 2016, 9:45:31 PM7/20/16
to Hayato Ito, blink-dev
LGTM1

--
TAMURA Kent
Software Engineer, Google


Elliott Sprehn

unread,
Jul 20, 2016, 9:49:20 PM7/20/16
to Hayato Ito, blink-dev

So if you're in the document composed: true always returns the document otherwise it returns the top of the subtree crossing shadow boundaries?

Hayato Ito

unread,
Jul 20, 2016, 10:32:19 PM7/20/16
to Elliott Sprehn, blink-dev
Yes. If we are *in the document* (in a traditional meaning, now it is called *is connected* ), getRootNode({ composed: true }) can return the document in O(1).

Philip Jägenstedt

unread,
Jul 21, 2016, 11:54:15 PM7/21/16
to Hayato Ito, Elliott Sprehn, blink-dev
Elliott, do you have any concerns with the options? I've taken a quick look at the spec and it looks sane to me, so LGTM2.

Elliott Sprehn

unread,
Jul 22, 2016, 1:40:59 AM7/22/16
to Philip Jägenstedt, Hayato Ito, blink-dev
On Thu, Jul 21, 2016 at 11:54 PM, Philip Jägenstedt <foo...@chromium.org> wrote:
Elliott, do you have any concerns with the options? I've taken a quick look at the spec and it looks sane to me, so LGTM2.

Seems fine to me though I wish we would have added features in a separate step from doing a rename. :) Do we have some use cases or examples for the composed: true case? Is it just to save people from writing a loop? I guess that's okay since we can do it in O(1) for you. :)

Hayato Ito

unread,
Jul 22, 2016, 2:29:02 AM7/22/16
to Elliott Sprehn, Philip Jägenstedt, blink-dev
Yeah, in a case of "nodeWhichIsNotConnected.getRootNode({composed: true})", this is just to save people from writing a loop.
I guess many frameworks have to write their own similar loop unless the platform provides it.

Note that adding optional "{composed: true}" parameter to this API does not contribute to decreasing the time complexity for this use case. It is not O(1) because we do not keep a *super-root* anywhere for a disconnected tree. :(
It takes O(N + M), where N is the *height* of "tree of trees" and M is "height of a (top) node tree".

Chris Harrelson

unread,
Jul 22, 2016, 11:19:05 AM7/22/16
to Hayato Ito, Elliott Sprehn, Philip Jägenstedt, blink-dev
LGTM3

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.

Reply all
Reply to author
Forward
0 new messages