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 206769 58541e1f52d2bdd817fe759a7403947de33227cf
parent 206768 c15e59678a6036e9e3db78e0ae6460581a4da8f6
child 206770 dbbd754c9a24f6cbbeb4f5d6121a9f519965c68e
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [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>