<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://www.w3.org/Bugs/Public/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4"
          urlbase="https://www.w3.org/Bugs/Public/"
          
          maintainer="sysbot+bugzilla@w3.org"
>

    <bug>
          <bug_id>22141</bug_id>
          
          <creation_ts>2013-05-22 18:23:02 +0000</creation_ts>
          <short_desc>[Shadow]: Need mechanism to tell if an element in a ShadowRoot has been inserted into the Document</short_desc>
          <delta_ts>2015-05-27 02:44:16 +0000</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebAppsWG</product>
          <component>HISTORICAL - Component Model</component>
          <version>unspecified</version>
          <rep_platform>PC</rep_platform>
          <op_sys>All</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>MOVED</resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P2</priority>
          <bug_severity>normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          <blocked>15480</blocked>
          <everconfirmed>1</everconfirmed>
          <reporter name="Daniel Freedman">dfreedm</reporter>
          <assigned_to name="Hayato Ito">hayato</assigned_to>
          <cc>annevk</cc>
    
    <cc>bugs</cc>
    
    <cc>dglazkov</cc>
    
    <cc>dominicc</cc>
    
    <cc>erik.arvidsson</cc>
    
    <cc>esprehn</cc>
    
    <cc>hayato</cc>
    
    <cc>jan</cc>
    
    <cc>p3pedram</cc>
          
          <qa_contact>public-webapps-bugzilla</qa_contact>

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>88078</commentid>
    <comment_count>0</comment_count>
    <who name="Daniel Freedman">dfreedm</who>
    <bug_when>2013-05-22 18:23:02 +0000</bug_when>
    <thetext>Because of necessity of encapsulation, it is very hard to tell if an arbitrary element has been inserted into the document.
Blink current hides the insertion state from compareDocumentPosition,but document.contains will return the actual insertion state.
This seems fine to me, because contains would not leak the state of the surrounding elements like compareDocumentPosition would.
I can also imagine cases where user code may want to gate on the insertion state, such as updating a canvas.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>89675</commentid>
    <comment_count>1</comment_count>
    <who name="Dominic Cooney">dominicc</who>
    <bug_when>2013-06-21 04:27:34 +0000</bug_when>
    <thetext>Because the author has to have the node in question in hand, it seems like document.contains returning an accurate value for elements in Shadow DOM violates the letter of encapsulation but not the spirit.

I think document.contains should return a value reflecting whether the argument is in the document (including shadow trees.)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>89703</commentid>
    <comment_count>2</comment_count>
    <who name="Dimitri Glazkov">dglazkov</who>
    <bug_when>2013-06-21 15:00:58 +0000</bug_when>
    <thetext>(In reply to comment #1)
&gt; Because the author has to have the node in question in hand, it seems like
&gt; document.contains returning an accurate value for elements in Shadow DOM
&gt; violates the letter of encapsulation but not the spirit.
&gt; 
&gt; I think document.contains should return a value reflecting whether the
&gt; argument is in the document (including shadow trees.)

That&apos;s a neat way to look at the problem. I am convinced.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>91524</commentid>
    <comment_count>3</comment_count>
    <who name="Erik Arvidsson">erik.arvidsson</who>
    <bug_when>2013-08-01 20:05:42 +0000</bug_when>
    <thetext>I think this is the wrong solution. `contains` has always meant that I can walk from the node&apos;s parentNode to the ancestor. This changes the semantics of contains.

What is the scenario we are trying to solve? Figuring that out, we can then come up with a reasonable API without changing the semantics of existing methods.

Let me flip the coin a bit. I&apos;ve been using contains as a signal that the node is not in the main document (in a shadow tree or a disconnected tree).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>95325</commentid>
    <comment_count>4</comment_count>
    <who name="Jan Miksovsky">jan</who>
    <bug_when>2013-10-24 23:14:53 +0000</bug_when>
    <thetext>I ran across this issue this week, and Daniel pointed me at this bug. See the thread at https://groups.google.com/forum/#!topic/polymer-dev/mGs_zkA_7-4.

Erik was asking for a scenario, and this thread presents one. An overlay (popup) element wants to track and/or absorb all clicks on the document. Clicks outside the overlay should dismiss the overlay, while clicks inside the element should have no effect. The overlay author wires up a click handler on the document, capturing events so that it gets first crack at them (and stop them before they might inadvertently triggering other handlers). The overlay&apos;s click handler looks at the event target to decide whether the target is in the overlay or not. For this purpose, the developer decides to use contains(). The dev tests the overlay&apos;s click tracking behavior with light DOM content inside the overlay, and all works well.

Later, someone else (me) tries to include the overlay element in the shadow of another element, and distribute content into the overlay. When the user looks at the overlay, they see content presented inside the overlay. From the user&apos;s point of view, the overlay contains the content. However, if the user clicks on the (light DOM) content, the overlay&apos;s contains() check fails, and the overlay fails to behave properly.

One could argue the overlay element should be written differently. Maybe it could track clicks outside using capturing and track clicks inside using bubbling, or find some other solution. But I think the dev made a reasonable call to use contains() for this purpose, and it seemed to work for any tests they cared to make. It was only when the overlay element was subsumed into the shadow of another element that things broke.

I&apos;ll hazard that similar issues are likely to come up wherever a dev tries to use contains() within a custom element. Subsuming that element into the shadow of another element will cause problems. I believe custom elements will have a general need to know whether they (visually) contain a given element, regardless of whether the element is in their shadow or distributed to them.

How this is done, whether through modifying contains() or something new, I&apos;ll leave to people wiser than me to figure out.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>95334</commentid>
    <comment_count>5</comment_count>
    <who name="Hayato Ito">hayato</who>
    <bug_when>2013-10-25 04:09:07 +0000</bug_when>
    <thetext>I think we can simulate the proposed *contains()* in JavaScript by using InsertionPoint.getDistributedNodes() and Node.getDestinationInsertionPoints().
I am aware that this will be burden for users, but it could be possible though I&apos;ve not tried.

I don&apos;t think it&apos;s good idea to change the semantics of existing contains(). It should consider only a node tree and should ignore the status of the composed tree.

I am not against adding something new in native Shadow DOM if we need it absolutely.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>102215</commentid>
    <comment_count>6</comment_count>
    <who name="Daniel Freedman">dfreedm</who>
    <bug_when>2014-03-11 18:30:42 +0000</bug_when>
    <thetext>Unfortunately, I think this is a very bad user experience decision.

Yes, we would be breaking the written semantics of document.contains, but we would be keeping the developer expectation that document.contains(node) means &quot;this node is *in* the document&quot;.

Otherwise we&apos;ve broken the developer assumptions about this method, and introduced a whole new variety of bugs.

For example, the jQuery flot charting library draws a helpful chart hover target that follows the mouse. It uses document.contains to determine if it should add page scroll offsets to the mouse x/y position to draw the the target correctly.

In the Polymer ShadowDOM polyfill, we followed the spec, and it broke this library: https://github.com/Polymer/polymer/issues/162.

Ember is another library that uses document.contains to determine if an element should instantiate its controller: https://github.com/Polymer/ShadowDOM/issues/365

Even if we made a new function that does what we want, like Node.prototype.isInDocumentForReals, we still have to knock on all the library authors doors to get them to use the new method, or they say &quot;ShadowDOM broke my stuff, it sucks&quot; and everybody loses.

Web developers need their tools to work, and making document.contains continue to follow developer expectations seems like winning all around.

WDYT?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>102230</commentid>
    <comment_count>7</comment_count>
    <who name="Hayato Ito">hayato</who>
    <bug_when>2014-03-12 04:55:06 +0000</bug_when>
    <thetext>To interpret the current spec literally, I think:

- document.contains should always return *false* if the argument node is in a shadow tree, as Erik said in comment #3. There is no ancestor/descendant relationship if they are in the different node trees.

I understand that this might cause a very bad user experience.

How do we proceed? Let me propose some ideas.

A) Change the semantics of node.contains so that it should consider the tree of trees.
   That means we are extending ancestor/descendant relationships beyond one node tree. I am afraid that we have to do *monkey-patch* to `node.contains` in the Shadow DOM spec.

B) Leave node.contains as is. That means if the context object and argument node are in the different node trees, it always returns *false*.

 As alternative, we should provide a new API, such as node.inComposedTree(). node.inComposedTree return true if and only if:
   The node participates in the composed tree whose root node is document.

C) Better ideas are welcome.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>102233</commentid>
    <comment_count>8</comment_count>
    <who name="Hayato Ito">hayato</who>
    <bug_when>2014-03-12 06:02:35 +0000</bug_when>
    <thetext>FYI.

In blink, looks like the semantics of `node.contains` changed in
https://chromiumcodereview.appspot.com/21123005

However, we don&apos;t have any spec for that. I&apos;m not convinced with decision.

I prefer Idea B.  WDYT?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>102292</commentid>
    <comment_count>9</comment_count>
    <who name="Hayato Ito">hayato</who>
    <bug_when>2014-03-13 05:07:45 +0000</bug_when>
    <thetext>If we go for idea B, we need API to satisfy the original requirement.

Because node.inComposedTree() is just an tentative idea, I appreciate opinions for better API to satisfy the requirement.

Other ideas:
- document.containsInComposedTree(node) - I think this is preferred.

Any ideas are welcome!</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>102406</commentid>
    <comment_count>10</comment_count>
    <who name="Elliott Sprehn">esprehn</who>
    <bug_when>2014-03-15 02:12:08 +0000</bug_when>
    <thetext>(In reply to Hayato Ito from comment #9)
&gt; If we go for idea B, we need API to satisfy the original requirement.
&gt; 
&gt; Because node.inComposedTree() is just an tentative idea, I appreciate
&gt; opinions for better API to satisfy the requirement.
&gt; 
&gt; Other ideas:
&gt; - document.containsInComposedTree(node) - I think this is preferred.
&gt; 
&gt; Any ideas are welcome!

I think there&apos;s two separate questions here, Document.contains and Node.contains seem like totally separate questions.

&quot;Am I in this Document&quot;
&quot;Am I a child of this Node&quot;

Now that we have ShadowRoot.host you can actually walk up to the root and get the answer you want though, so perhaps reverting this is okay. We should probably add an inDocument() method though.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>102438</commentid>
    <comment_count>11</comment_count>
    <who name="Hayato Ito">hayato</who>
    <bug_when>2014-03-17 04:44:16 +0000</bug_when>
    <thetext>FYI,
In blink, I&apos;ve reverted the change of &quot;node.contains&quot;: https://codereview.chromium.org/197283016/

(In reply to Elliott Sprehn from comment #10)
&gt; (In reply to Hayato Ito from comment #9)
&gt; &gt; If we go for idea B, we need API to satisfy the original requirement.
&gt; &gt; 
&gt; &gt; Because node.inComposedTree() is just an tentative idea, I appreciate
&gt; &gt; opinions for better API to satisfy the requirement.
&gt; &gt; 
&gt; &gt; Other ideas:
&gt; &gt; - document.containsInComposedTree(node) - I think this is preferred.
&gt; &gt; 
&gt; &gt; Any ideas are welcome!
&gt; 
&gt; I think there&apos;s two separate questions here, Document.contains and
&gt; Node.contains seem like totally separate questions.
&gt; 
&gt; &quot;Am I in this Document&quot;
&gt; &quot;Am I a child of this Node&quot;

Agreed. IMO, we should avoid such a double meaning.
We should have a more explicit API instead of re-using &apos;document.contains&apos;.

&gt; 
&gt; Now that we have ShadowRoot.host you can actually walk up to the root and
&gt; get the answer you want though, so perhaps reverting this is okay. We should
&gt; probably add an inDocument() method though.

Yeah, we should discuss further to pursuit a good API.
I&apos;d like to hear opinions from developers to address their use cases.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>109983</commentid>
    <comment_count>12</comment_count>
    <who name="Hayato Ito">hayato</who>
    <bug_when>2014-08-06 08:23:58 +0000</bug_when>
    <thetext>Because we already have /deep/ combinator, http://drafts.csswg.org/css-scoping/#selectordef-deep, I think `document.deepContains(node)` might be a good name.

WDYT? If it&apos;s okay, let me spec that.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>109987</commentid>
    <comment_count>13</comment_count>
    <who name="Hayato Ito">hayato</who>
    <bug_when>2014-08-06 08:37:35 +0000</bug_when>
    <thetext>It seems that Document doesn&apos;t have `contains`.
http://dom.spec.whatwg.org/#interface-document

We should add `deepContains` to Node, instead of Document.
http://dom.spec.whatwg.org/#dom-node-contains</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>110018</commentid>
    <comment_count>14</comment_count>
    <who name="Hayato Ito">hayato</who>
    <bug_when>2014-08-07 05:37:19 +0000</bug_when>
    <thetext>I&apos;ve added &apos;Node.deepContains(Node? other)&apos; in
https://github.com/w3c/webcomponents/commit/14322e526d53cde0814bec041d7fab6dd77f7e88

I need a feedback.
Could someone verify whether this definition satisfies our requirements or not?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>110020</commentid>
    <comment_count>15</comment_count>
    <who name="Olli Pettay">bugs</who>
    <bug_when>2014-08-07 09:56:50 +0000</bug_when>
    <thetext>I don&apos;t really like deepContains (partly because I think CSS is wrong by exposing
shadow dom in that way, and also because &apos;deep&apos; doesn&apos;t really say anything.)

Couldn&apos;t we change contains() to take second param, which could be
some dictionary.

bool contains(Node? other, optional ContainsFilter filter)

dictionary ContainsFilter
{
  bool includeShadowDOM = false; // includeShadowDOM is a bit bad name.
}</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>110056</commentid>
    <comment_count>16</comment_count>
    <who name="Hayato Ito">hayato</who>
    <bug_when>2014-08-11 03:08:26 +0000</bug_when>
    <thetext>Thank you for the feedback!

(In reply to Olli Pettay from comment #15)
&gt; I don&apos;t really like deepContains (partly because I think CSS is wrong by
&gt; exposing
&gt; shadow dom in that way, and also because &apos;deep&apos; doesn&apos;t really say anything.)
&gt; 
&gt; Couldn&apos;t we change contains() to take second param, which could be
&gt; some dictionary.
&gt; 
&gt; bool contains(Node? other, optional ContainsFilter filter)
&gt; 
&gt; dictionary ContainsFilter
&gt; {
&gt;   bool includeShadowDOM = false; // includeShadowDOM is a bit bad name.
&gt; }

It looks better to me than deepContains. I like it.
If no one have better idea than this, I&apos;l change the spec.
In this case, should I make a patch for DOM spec?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>110518</commentid>
    <comment_count>17</comment_count>
    <who name="Anne">annevk</who>
    <bug_when>2014-08-25 08:12:30 +0000</bug_when>
    <thetext>Well, includeShadow or some such could work. Or includeShadowNodes. Let&apos;s not use the term &quot;DOM&quot; in any API. Ideally, the terms we use for shadow nodes are consistent in some way.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>110519</commentid>
    <comment_count>18</comment_count>
    <who name="Hayato Ito">hayato</who>
    <bug_when>2014-08-25 08:35:46 +0000</bug_when>
    <thetext>Well, actually, the Shadow DOM spec doesn&apos;t define any technical definition of &apos;Shadow DOM&apos;. That isn&apos;t well defined term. We should avoid using the term of &apos;Shadow DOM&apos; in APIs.

includeNodesInShadowTrees might be the most unambiguous, however it looks too redundant.

My preferences are:

- Most preferred -

A. includeShadow
B. includeShadowTrees
C. includeNodesInShadowTrees
D. includeShadowNodes

- Least preferred -

I don&apos;t have a strong opinion either. I am aware this might be bike-shed discussion, but the naming of API is important.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>110520</commentid>
    <comment_count>19</comment_count>
    <who name="Anne">annevk</who>
    <bug_when>2014-08-25 08:40:45 +0000</bug_when>
    <thetext>includeShadow seems fine. Shortest and to the point. So I guess we&apos;ll have shadow trees and the one &lt;textarea&gt; and friends use are isolated shadow trees? (And won&apos;t be exposed here of course.)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>110521</commentid>
    <comment_count>20</comment_count>
    <who name="Hayato Ito">hayato</who>
    <bug_when>2014-08-25 09:02:57 +0000</bug_when>
    <thetext>Good question.

IMO, document.contains(nodeInShadowTreesHostedByTextAreaElementInDocument, { includeShadow: treu}) should return `true`. However, I&apos;m not confident.

I am not sure whether there is a use case for that, assuming external developers can&apos;t get an access for such a node usually.

AFAIK, only use cases I&apos;ve heard so far is for nodes which are in user-created shadow trees, rather than nodes in UA shadow trees for built-in elements.

If I misunderstand your question, please correct me.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>117935</commentid>
    <comment_count>21</comment_count>
    <who name="Pedram Emrouznejad">p3pedram</who>
    <bug_when>2015-02-15 17:33:11 +0000</bug_when>
    <thetext>For what&apos;s it worth, I managed to solve my need for a document.contains that cuts across shadow boundaries by doing: 

element.matches(&apos;:host-context(body) *&apos;)

(essentially, I needed to know if a shadow-nested element was in the main document)

+1 to a more versatile document.contains though. I&apos;m not sure what other possible options a dictionary would be good for, so I think just a simple true/false as the second parameter would work well. If there is need for further config in the future, then I guess you can still keep the true/false parameter and overload it with a dictionary.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>120490</commentid>
    <comment_count>22</comment_count>
    <who name="Hayato Ito">hayato</who>
    <bug_when>2015-05-27 02:44:16 +0000</bug_when>
    <thetext>Moved to https://github.com/w3c/webcomponents/issues/81</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>