void AnimationTimeline::serviceAnimations(TimingUpdateReason reason) { TRACE_EVENT0("blink", "AnimationTimeline::serviceAnimations"); m_timing->cancelWake(); double timeToNextEffect = std::numeric_limits<double>::infinity(); WillBeHeapVector<RawPtrWillBeMember<AnimationPlayer> > players; players.reserveInitialCapacity(m_playersNeedingUpdate.size()); for (WillBeHeapHashSet<RefPtrWillBeMember<AnimationPlayer> >::iterator it = m_playersNeedingUpdate.begin(); it != m_playersNeedingUpdate.end(); ++it) players.append(it->get()); std::sort(players.begin(), players.end(), AnimationPlayer::hasLowerPriority); for (size_t i = 0; i < players.size(); ++i) { AnimationPlayer* player = players[i]; if (player->update(reason)) timeToNextEffect = std::min(timeToNextEffect, player->timeToEffectChange()); else m_playersNeedingUpdate.remove(player); } if (timeToNextEffect < s_minimumDelay) m_timing->serviceOnNextFrame(); else if (timeToNextEffect != std::numeric_limits<double>::infinity()) m_timing->wakeAfter(timeToNextEffect - s_minimumDelay); ASSERT(!hasOutdatedAnimationPlayer()); }
void AnimationTimeline::serviceAnimations(TimingUpdateReason reason) { TRACE_EVENT0("blink", "AnimationTimeline::serviceAnimations"); m_lastCurrentTimeInternal = currentTimeInternal(); m_timing->cancelWake(); WillBeHeapVector<RawPtrWillBeMember<Animation>> animations; animations.reserveInitialCapacity(m_animationsNeedingUpdate.size()); for (RefPtrWillBeMember<Animation> animation : m_animationsNeedingUpdate) animations.append(animation.get()); std::sort(animations.begin(), animations.end(), Animation::hasLowerPriority); for (Animation* animation : animations) { if (!animation->update(reason)) m_animationsNeedingUpdate.remove(animation); } ASSERT(m_outdatedAnimationCount == 0); #if ENABLE(ASSERT) for (const auto& animation : m_animationsNeedingUpdate) ASSERT(!animation->outdated()); #endif }
PassRefPtrWillBeRawPtr<StaticNodeList> InsertionPoint::getDistributedNodes() { updateDistribution(); WillBeHeapVector<RefPtrWillBeMember<Node>> nodes; nodes.reserveInitialCapacity(m_distributedNodes.size()); for (size_t i = 0; i < m_distributedNodes.size(); ++i) nodes.uncheckedAppend(m_distributedNodes.at(i)); return StaticNodeList::adopt(nodes); }
PassRefPtrWillBeRawPtr<MutableStylePropertySet> StylePropertySet::copyPropertiesInSet(const Vector<CSSPropertyID>& properties) const { WillBeHeapVector<CSSProperty, 256> list; list.reserveInitialCapacity(properties.size()); for (unsigned i = 0; i < properties.size(); ++i) { RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(properties[i]); if (value) list.append(CSSProperty(properties[i], value.release(), false)); } return MutableStylePropertySet::create(list.data(), list.size()); }
FontFaceSetIterable::IterationSource* FontFaceSet::startIteration(ScriptState*, ExceptionState&) { // Setlike should iterate each item in insertion order, and items should // be keep on up to date. But since blink does not have a way to hook up CSS // modification, take a snapshot here, and make it ordered as follows. WillBeHeapVector<RefPtrWillBeMember<FontFace>> fontFaces; if (inActiveDocumentContext()) { const WillBeHeapListHashSet<RefPtrWillBeMember<FontFace>>& cssConnectedFaces = cssConnectedFontFaceList(); fontFaces.reserveInitialCapacity(cssConnectedFaces.size() + m_nonCSSConnectedFaces.size()); for (const auto& fontFace : cssConnectedFaces) fontFaces.append(fontFace); for (const auto& fontFace : m_nonCSSConnectedFaces) fontFaces.append(fontFace); } return new IterationSource(fontFaces); }
PassRefPtrWillBeRawPtr<NodeList> TreeScopeEventContext::ensureEventPath(EventPath& path) { if (m_eventPath) return m_eventPath; WillBeHeapVector<RefPtrWillBeMember<Node> > nodes; nodes.reserveInitialCapacity(path.size()); for (size_t i = 0; i < path.size(); ++i) { TreeScope& treeScope = path[i].treeScopeEventContext().treeScope(); if (treeScope.rootNode().isShadowRoot() && toShadowRoot(treeScope).type() == ShadowRoot::AuthorShadowRoot) nodes.append(path[i].node()); else if (path[i].treeScopeEventContext().isInclusiveAncestorOf(*this)) nodes.append(path[i].node()); } m_eventPath = StaticNodeList::adopt(nodes); return m_eventPath; }
void NodeSet::sort() const { if (m_isSorted) return; unsigned nodeCount = m_nodes.size(); if (nodeCount < 2) { const_cast<bool&>(m_isSorted) = true; return; } if (nodeCount > traversalSortCutoff) { traversalSort(); return; } bool containsAttributeNodes = false; WillBeHeapVector<NodeSetVector> parentMatrix(nodeCount); for (unsigned i = 0; i < nodeCount; ++i) { NodeSetVector& parentsVector = parentMatrix[i]; Node* n = m_nodes[i].get(); parentsVector.append(n); if (n->isAttributeNode()) { n = toAttr(n)->ownerElement(); parentsVector.append(n); containsAttributeNodes = true; } while ((n = n->parentNode())) parentsVector.append(n); } sortBlock(0, nodeCount, parentMatrix, containsAttributeNodes); // It is not possible to just assign the result to m_nodes, because some // nodes may get dereferenced and destroyed. WillBeHeapVector<RefPtrWillBeMember<Node> > sortedNodes; sortedNodes.reserveInitialCapacity(nodeCount); for (unsigned i = 0; i < nodeCount; ++i) sortedNodes.append(parentMatrix[i][0]); const_cast<WillBeHeapVector<RefPtrWillBeMember<Node> >&>(m_nodes).swap(sortedNodes); }
void HTMLFormattingElementList::ensureNoahsArkCondition(HTMLStackItem* newItem) { WillBeHeapVector<RawPtrWillBeMember<HTMLStackItem> > candidates; tryToEnsureNoahsArkConditionQuickly(newItem, candidates); if (candidates.isEmpty()) return; // We pre-allocate and re-use this second vector to save one malloc per // attribute that we verify. WillBeHeapVector<RawPtrWillBeMember<HTMLStackItem> > remainingCandidates; remainingCandidates.reserveInitialCapacity(candidates.size()); const Vector<Attribute>& attributes = newItem->attributes(); for (size_t i = 0; i < attributes.size(); ++i) { const Attribute& attribute = attributes[i]; for (size_t j = 0; j < candidates.size(); ++j) { HTMLStackItem* candidate = candidates[j]; // These properties should already have been checked by tryToEnsureNoahsArkConditionQuickly. ASSERT(newItem->attributes().size() == candidate->attributes().size()); ASSERT(newItem->localName() == candidate->localName() && newItem->namespaceURI() == candidate->namespaceURI()); Attribute* candidateAttribute = candidate->getAttributeItem(attribute.name()); if (candidateAttribute && candidateAttribute->value() == attribute.value()) remainingCandidates.append(candidate); } if (remainingCandidates.size() < kNoahsArkCapacity) return; candidates.swap(remainingCandidates); remainingCandidates.shrink(0); } // Inductively, we shouldn't spin this loop very many times. It's possible, // however, that we wil spin the loop more than once because of how the // formatting element list gets permuted. for (size_t i = kNoahsArkCapacity - 1; i < candidates.size(); ++i) remove(candidates[i]->element()); }
void NodeSet::traversalSort() const { WillBeHeapHashSet<RawPtrWillBeMember<Node> > nodes; bool containsAttributeNodes = false; unsigned nodeCount = m_nodes.size(); ASSERT(nodeCount > 1); for (unsigned i = 0; i < nodeCount; ++i) { Node* node = m_nodes[i].get(); nodes.add(node); if (node->isAttributeNode()) containsAttributeNodes = true; } WillBeHeapVector<RefPtrWillBeMember<Node> > sortedNodes; sortedNodes.reserveInitialCapacity(nodeCount); for (Node* n = findRootNode(m_nodes.first().get()); n; n = NodeTraversal::next(*n)) { if (nodes.contains(n)) sortedNodes.append(n); if (!containsAttributeNodes || !n->isElementNode()) continue; Element* element = toElement(n); if (!element->hasAttributes()) continue; AttributeCollection attributes = element->attributes(); AttributeCollection::const_iterator end = attributes.end(); for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) { RefPtrWillBeRawPtr<Attr> attr = element->attrIfExists(it->name()); if (attr && nodes.contains(attr.get())) sortedNodes.append(attr); } } ASSERT(sortedNodes.size() == nodeCount); const_cast<WillBeHeapVector<RefPtrWillBeMember<Node> >&>(m_nodes).swap(sortedNodes); }
void AnimationTimeline::serviceAnimations(TimingUpdateReason reason) { TRACE_EVENT0("blink", "AnimationTimeline::serviceAnimations"); m_lastCurrentTimeInternal = currentTimeInternal(); m_timing->cancelWake(); WillBeHeapVector<RawPtrWillBeMember<AnimationPlayer>> players; players.reserveInitialCapacity(m_playersNeedingUpdate.size()); for (RefPtrWillBeMember<AnimationPlayer> player : m_playersNeedingUpdate) players.append(player.get()); std::sort(players.begin(), players.end(), AnimationPlayer::hasLowerPriority); for (AnimationPlayer* player : players) { if (!player->update(reason)) m_playersNeedingUpdate.remove(player); } ASSERT(!hasOutdatedAnimationPlayer()); }
void NodeSet::traversalSort() const { WillBeHeapHashSet<RawPtrWillBeMember<Node>> nodes; bool containsAttributeNodes = false; unsigned nodeCount = m_nodes.size(); ASSERT(nodeCount > 1); for (unsigned i = 0; i < nodeCount; ++i) { Node* node = m_nodes[i].get(); nodes.add(node); if (node->isAttributeNode()) containsAttributeNodes = true; } WillBeHeapVector<RefPtrWillBeMember<Node>> sortedNodes; sortedNodes.reserveInitialCapacity(nodeCount); for (Node& n : NodeTraversal::startsAt(findRootNode(m_nodes.first().get()))) { if (nodes.contains(&n)) sortedNodes.append(&n); if (!containsAttributeNodes || !n.isElementNode()) continue; Element* element = toElement(&n); AttributeCollection attributes = element->attributes(); for (auto& attribute : attributes) { RefPtrWillBeRawPtr<Attr> attr = element->attrIfExists(attribute.name()); if (attr && nodes.contains(attr.get())) sortedNodes.append(attr); } } ASSERT(sortedNodes.size() == nodeCount); const_cast<WillBeHeapVector<RefPtrWillBeMember<Node>>&>(m_nodes).swap(sortedNodes); }