Bug 1007743 - Update flattened tree to correctly handle nodes distributed into Shadow DOM insertion points. r=smaug
☠☠ backed out by 7b6a7a038a3c ☠ ☠
authorWilliam Chen <wchen@mozilla.com>
Tue, 03 Jun 2014 16:09:41 -0700
changeset 205685 58541e1f52d2bdd817fe759a7403947de33227cf
parent 205684 c15e59678a6036e9e3db78e0ae6460581a4da8f6
child 205686 dbbd754c9a24f6cbbeb4f5d6121a9f519965c68e
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1007743
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1007743 - Update flattened tree to correctly handle nodes distributed into Shadow DOM insertion points. r=smaug
content/base/src/ChildIterator.cpp
content/base/src/FragmentOrElement.cpp
layout/reftests/webcomponents/reftest.list
layout/reftests/webcomponents/update-dist-node-descendants-1-ref.html
layout/reftests/webcomponents/update-dist-node-descendants-1.html
--- a/content/base/src/ChildIterator.cpp
+++ b/content/base/src/ChildIterator.cpp
@@ -185,18 +185,18 @@ FlattenedChildIterator::FlattenedChildIt
 }
 
 nsIContent*
 ExplicitChildIterator::Get()
 {
   MOZ_ASSERT(!mIsFirst);
 
   if (mIndexInInserted) {
-    XBLChildrenElement* point = static_cast<XBLChildrenElement*>(mChild);
-    return point->mInsertedChildren[mIndexInInserted - 1];
+    MatchedNodes assignedChildren = GetMatchedNodesForPoint(mChild);
+    return assignedChildren[mIndexInInserted - 1];
   } else if (mShadowIterator)  {
     return mShadowIterator->Get();
   }
   return mDefaultChild ? mDefaultChild : mChild;
 }
 
 nsIContent*
 ExplicitChildIterator::GetPreviousChild()
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -148,24 +148,43 @@ nsIContent::FindFirstNonChromeOnlyAccess
     }
   }
   return nullptr;
 }
 
 nsIContent*
 nsIContent::GetFlattenedTreeParent() const
 {
-  if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
-    nsIContent* parent = GetXBLInsertionParent();
-    if (parent) {
-      return parent;
+  nsIContent* parent = nullptr;
+
+  nsTArray<nsIContent*>* destInsertionPoints = GetExistingDestInsertionPoints();
+  if (destInsertionPoints && !destInsertionPoints->IsEmpty()) {
+    // This node was distributed into an insertion point. The last node in
+    // the list of destination insertion insertion points is where this node
+    // appears in the composed tree (see Shadow DOM spec).
+    nsIContent* lastInsertionPoint = destInsertionPoints->LastElement();
+    parent = lastInsertionPoint->GetParent();
+  } else if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
+    parent = GetXBLInsertionParent();
+  }
+
+  if (!parent) {
+    parent = GetParent();
+  }
+
+  // Shadow roots never shows up in the flattened tree. Return the host
+  // instead.
+  if (parent && parent->HasFlag(NODE_IS_IN_SHADOW_TREE)) {
+    ShadowRoot* parentShadowRoot = ShadowRoot::FromNode(parent);
+    if (parentShadowRoot) {
+      return parentShadowRoot->GetHost();
     }
   }
 
-  return GetParent();
+  return parent;
 }
 
 nsIContent::IMEState
 nsIContent::GetDesiredIMEState()
 {
   if (!IsEditableInternal()) {
     // Check for the special case where we're dealing with elements which don't
     // have the editable flag set, but are readwrite (such as text controls).
--- a/layout/reftests/webcomponents/reftest.list
+++ b/layout/reftests/webcomponents/reftest.list
@@ -7,8 +7,9 @@ pref(dom.webcomponents.enabled,true) == 
 pref(dom.webcomponents.enabled,true) == basic-insertion-point-2.html basic-insertion-point-2-ref.html
 pref(dom.webcomponents.enabled,true) == adjacent-insertion-points-1.html adjacent-insertion-points-1-ref.html
 pref(dom.webcomponents.enabled,true) == adjacent-insertion-points-2.html adjacent-insertion-points-2-ref.html
 pref(dom.webcomponents.enabled,true) == fallback-content-1.html fallback-content-1-ref.html
 pref(dom.webcomponents.enabled,true) == remove-insertion-point-1.html remove-insertion-point-1-ref.html
 pref(dom.webcomponents.enabled,true) == nested-insertion-point-1.html nested-insertion-point-1-ref.html
 pref(dom.webcomponents.enabled,true) == basic-shadow-element-1.html basic-shadow-element-1-ref.html
 pref(dom.webcomponents.enabled,true) == nested-shadow-element-1.html nested-shadow-element-1-ref.html
+pref(dom.webcomponents.enabled,true) == update-dist-node-descendants-1.html update-dist-node-descendants-1-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/webcomponents/update-dist-node-descendants-1-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<div>
+  <div><div><span>Hello World</span></div></div>
+</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/webcomponents/update-dist-node-descendants-1.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+</head>
+<body>
+<div id="outer"><span id="distnode">Change me</span></div>
+<script>
+var shadowRoot = document.getElementById('outer').createShadowRoot();
+shadowRoot.innerHTML = '<div><content></content></div>';
+
+function tweak() {
+  var distNode = document.getElementById("distnode");
+  distNode.textContent = "Hello World";
+
+  document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("MozReftestInvalidate", tweak);
+</script>
+</body>
+</html>