| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2015 Google Inc. All rights reserved. | 2 * Copyright (C) 2015 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 const HeapVector<Member<Node>>& HTMLSlotElement::assignedNodes() { | 61 const HeapVector<Member<Node>>& HTMLSlotElement::assignedNodes() { |
| 62 DCHECK(!needsDistributionRecalc()); | 62 DCHECK(!needsDistributionRecalc()); |
| 63 DCHECK(isInShadowTree() || m_assignedNodes.isEmpty()); | 63 DCHECK(isInShadowTree() || m_assignedNodes.isEmpty()); |
| 64 return m_assignedNodes; | 64 return m_assignedNodes; |
| 65 } | 65 } |
| 66 | 66 |
| 67 const HeapVector<Member<Node>> HTMLSlotElement::assignedNodesForBinding( | 67 const HeapVector<Member<Node>> HTMLSlotElement::assignedNodesForBinding( |
| 68 const AssignedNodesOptions& options) { | 68 const AssignedNodesOptions& options) { |
| 69 updateDistribution(); | 69 updateDistribution(); |
| 70 if (options.hasFlatten() && options.flatten()) | 70 if (options.hasFlatten() && options.flatten()) |
| 71 return getDistributedNodes(); | 71 return getDistributedNodesForBinding(); |
| 72 return m_assignedNodes; | 72 return m_assignedNodes; |
| 73 } | 73 } |
| 74 | 74 |
| 75 void HTMLSlotElement::updateDistributedNodesManually() { | 75 const HeapVector<Member<Node>> |
| 76 DCHECK(!supportsDistribution()); | 76 HTMLSlotElement::getDistributedNodesForBinding() { |
| 77 // A slot is unlikely to be used outside of a shadow tree. | 77 DCHECK(!needsDistributionRecalc()); |
| 78 // We do not need to optimize this case in most cases. | 78 if (supportsDistribution()) |
| 79 // TODO(hayato): If this path causes a performance issue, we should move | 79 return m_distributedNodes; |
| 80 // ShadowRoot::m_slotAssignment into TreeScopreRareData-ish and | 80 |
| 81 // update the distribution code so it considers a document tree too. | 81 // If a slot does not support distribution, its m_distributedNodes should not |
| 82 clearDistribution(); | 82 // be used. Instead, calculate distribution manually here. This happens only |
| 83 // in a slot in non-shadow trees, so its assigned nodes are always empty. |
| 84 HeapVector<Member<Node>> distributedNodes; |
| 83 Node* child = NodeTraversal::firstChild(*this); | 85 Node* child = NodeTraversal::firstChild(*this); |
| 84 while (child) { | 86 while (child) { |
| 85 if (!child->isSlotable()) { | 87 if (!child->isSlotable()) { |
| 86 child = NodeTraversal::nextSkippingChildren(*child, this); | 88 child = NodeTraversal::nextSkippingChildren(*child, this); |
| 87 continue; | 89 continue; |
| 88 } | 90 } |
| 89 if (isHTMLSlotElement(child)) { | 91 if (isHTMLSlotElement(child)) { |
| 90 child = NodeTraversal::next(*child, this); | 92 child = NodeTraversal::next(*child, this); |
| 91 } else { | 93 } else { |
| 92 m_distributedNodes.append(child); | 94 distributedNodes.append(child); |
| 93 child = NodeTraversal::nextSkippingChildren(*child, this); | 95 child = NodeTraversal::nextSkippingChildren(*child, this); |
| 94 } | 96 } |
| 95 } | 97 } |
| 98 return distributedNodes; |
| 96 } | 99 } |
| 97 | 100 |
| 98 const HeapVector<Member<Node>>& HTMLSlotElement::getDistributedNodes() { | 101 const HeapVector<Member<Node>>& HTMLSlotElement::getDistributedNodes() { |
| 99 DCHECK(!needsDistributionRecalc()); | 102 DCHECK(!needsDistributionRecalc()); |
| 100 // m_distributedNodes of slots in non-shadow trees are not updated in recalc | 103 DCHECK(supportsDistribution() || m_distributedNodes.isEmpty()); |
| 101 // distribution flow. | |
| 102 if (!supportsDistribution()) | |
| 103 updateDistributedNodesManually(); | |
| 104 return m_distributedNodes; | 104 return m_distributedNodes; |
| 105 } | 105 } |
| 106 | 106 |
| 107 void HTMLSlotElement::appendAssignedNode(Node& hostChild) { | 107 void HTMLSlotElement::appendAssignedNode(Node& hostChild) { |
| 108 DCHECK(hostChild.isSlotable()); | 108 DCHECK(hostChild.isSlotable()); |
| 109 m_assignedNodes.append(&hostChild); | 109 m_assignedNodes.append(&hostChild); |
| 110 } | 110 } |
| 111 | 111 |
| 112 void HTMLSlotElement::resolveDistributedNodes() { | 112 void HTMLSlotElement::resolveDistributedNodes() { |
| 113 for (auto& node : m_assignedNodes) { | 113 for (auto& node : m_assignedNodes) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 } | 149 } |
| 150 | 150 |
| 151 void HTMLSlotElement::dispatchSlotChangeEvent() { | 151 void HTMLSlotElement::dispatchSlotChangeEvent() { |
| 152 m_slotchangeEventEnqueued = false; | 152 m_slotchangeEventEnqueued = false; |
| 153 Event* event = Event::createBubble(EventTypeNames::slotchange); | 153 Event* event = Event::createBubble(EventTypeNames::slotchange); |
| 154 event->setTarget(this); | 154 event->setTarget(this); |
| 155 dispatchScopedEvent(event); | 155 dispatchScopedEvent(event); |
| 156 } | 156 } |
| 157 | 157 |
| 158 Node* HTMLSlotElement::distributedNodeNextTo(const Node& node) const { | 158 Node* HTMLSlotElement::distributedNodeNextTo(const Node& node) const { |
| 159 DCHECK(supportsDistribution()); |
| 159 const auto& it = m_distributedIndices.find(&node); | 160 const auto& it = m_distributedIndices.find(&node); |
| 160 if (it == m_distributedIndices.end()) | 161 if (it == m_distributedIndices.end()) |
| 161 return nullptr; | 162 return nullptr; |
| 162 size_t index = it->value; | 163 size_t index = it->value; |
| 163 if (index + 1 == m_distributedNodes.size()) | 164 if (index + 1 == m_distributedNodes.size()) |
| 164 return nullptr; | 165 return nullptr; |
| 165 return m_distributedNodes[index + 1].get(); | 166 return m_distributedNodes[index + 1].get(); |
| 166 } | 167 } |
| 167 | 168 |
| 168 Node* HTMLSlotElement::distributedNodePreviousTo(const Node& node) const { | 169 Node* HTMLSlotElement::distributedNodePreviousTo(const Node& node) const { |
| 170 DCHECK(supportsDistribution()); |
| 169 const auto& it = m_distributedIndices.find(&node); | 171 const auto& it = m_distributedIndices.find(&node); |
| 170 if (it == m_distributedIndices.end()) | 172 if (it == m_distributedIndices.end()) |
| 171 return nullptr; | 173 return nullptr; |
| 172 size_t index = it->value; | 174 size_t index = it->value; |
| 173 if (index == 0) | 175 if (index == 0) |
| 174 return nullptr; | 176 return nullptr; |
| 175 return m_distributedNodes[index - 1].get(); | 177 return m_distributedNodes[index - 1].get(); |
| 176 } | 178 } |
| 177 | 179 |
| 178 AtomicString HTMLSlotElement::name() const { | 180 AtomicString HTMLSlotElement::name() const { |
| 179 return normalizeSlotName(fastGetAttribute(HTMLNames::nameAttr)); | 181 return normalizeSlotName(fastGetAttribute(HTMLNames::nameAttr)); |
| 180 } | 182 } |
| 181 | 183 |
| 182 void HTMLSlotElement::attachLayoutTree(const AttachContext& context) { | 184 void HTMLSlotElement::attachLayoutTree(const AttachContext& context) { |
| 183 for (auto& node : getDistributedNodes()) { | 185 if (supportsDistribution()) { |
| 184 if (node->needsAttach()) | 186 for (auto& node : m_distributedNodes) { |
| 185 node->attachLayoutTree(context); | 187 if (node->needsAttach()) |
| 188 node->attachLayoutTree(context); |
| 189 } |
| 186 } | 190 } |
| 187 | |
| 188 HTMLElement::attachLayoutTree(context); | 191 HTMLElement::attachLayoutTree(context); |
| 189 } | 192 } |
| 190 | 193 |
| 191 void HTMLSlotElement::detachLayoutTree(const AttachContext& context) { | 194 void HTMLSlotElement::detachLayoutTree(const AttachContext& context) { |
| 192 for (auto& node : m_distributedNodes) | 195 if (supportsDistribution()) { |
| 193 node->lazyReattachIfAttached(); | 196 for (auto& node : m_distributedNodes) |
| 194 | 197 node->lazyReattachIfAttached(); |
| 198 } |
| 195 HTMLElement::detachLayoutTree(context); | 199 HTMLElement::detachLayoutTree(context); |
| 196 } | 200 } |
| 197 | 201 |
| 198 void HTMLSlotElement::attributeChanged(const QualifiedName& name, | 202 void HTMLSlotElement::attributeChanged(const QualifiedName& name, |
| 199 const AtomicString& oldValue, | 203 const AtomicString& oldValue, |
| 200 const AtomicString& newValue, | 204 const AtomicString& newValue, |
| 201 AttributeModificationReason reason) { | 205 AttributeModificationReason reason) { |
| 202 if (name == nameAttr) { | 206 if (name == nameAttr) { |
| 203 if (ShadowRoot* root = containingShadowRoot()) { | 207 if (ShadowRoot* root = containingShadowRoot()) { |
| 204 if (root->isV1() && oldValue != newValue) | 208 if (root->isV1() && oldValue != newValue) |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 | 357 |
| 354 DEFINE_TRACE(HTMLSlotElement) { | 358 DEFINE_TRACE(HTMLSlotElement) { |
| 355 visitor->trace(m_assignedNodes); | 359 visitor->trace(m_assignedNodes); |
| 356 visitor->trace(m_distributedNodes); | 360 visitor->trace(m_distributedNodes); |
| 357 visitor->trace(m_oldDistributedNodes); | 361 visitor->trace(m_oldDistributedNodes); |
| 358 visitor->trace(m_distributedIndices); | 362 visitor->trace(m_distributedIndices); |
| 359 HTMLElement::trace(visitor); | 363 HTMLElement::trace(visitor); |
| 360 } | 364 } |
| 361 | 365 |
| 362 } // namespace blink | 366 } // namespace blink |
| OLD | NEW |