void NodeSet::traversalSort() const { HeapHashSet<Member<Node>> nodes; bool containsAttributeNodes = false; unsigned nodeCount = m_nodes.size(); DCHECK_GT(nodeCount, 1u); for (unsigned i = 0; i < nodeCount; ++i) { Node* node = m_nodes[i].get(); nodes.add(node); if (node->isAttributeNode()) containsAttributeNodes = true; } HeapVector<Member<Node>> sortedNodes; sortedNodes.reserveInitialCapacity(nodeCount); for (Node& n : NodeTraversal::startsAt(*findRootNode(m_nodes.first()))) { if (nodes.contains(&n)) sortedNodes.append(&n); if (!containsAttributeNodes || !n.isElementNode()) continue; Element* element = toElement(&n); AttributeCollection attributes = element->attributes(); for (auto& attribute : attributes) { Attr* attr = element->attrIfExists(attribute.name()); if (attr && nodes.contains(attr)) sortedNodes.append(attr); } } DCHECK_EQ(sortedNodes.size(), nodeCount); const_cast<HeapVector<Member<Node>>&>(m_nodes).swap(sortedNodes); }
HeapVector<Member<Element>> TreeScope::elementsFromHitTestResult( HitTestResult& result) const { HeapVector<Member<Element>> elements; Node* lastNode = nullptr; for (const auto rectBasedNode : result.listBasedTestResult()) { Node* node = rectBasedNode.get(); if (!node || !node->isElementNode() || node->isDocumentNode()) continue; if (node->isPseudoElement() || node->isTextNode()) node = node->parentOrShadowHostNode(); node = ancestorInThisScope(node); // Prune duplicate entries. A pseduo ::before content above its parent // node should only result in a single entry. if (node == lastNode) continue; if (node && node->isElementNode()) { elements.append(toElement(node)); lastNode = node; } } if (rootNode().isDocumentNode()) { if (Element* rootElement = toDocument(rootNode()).documentElement()) { if (elements.isEmpty() || elements.last() != rootElement) elements.append(rootElement); } } return elements; }
void VRHardwareUnit::addDevicesToVector(HeapVector<Member<VRDevice>>& vrDevices) { if (m_hmd) vrDevices.append(m_hmd); if (m_positionSensor) vrDevices.append(m_positionSensor); }
bool MHTMLParser::parseArchiveWithHeader( MIMEHeader* header, HeapVector<Member<ArchiveResource>>& resources) { if (!header) { DVLOG(1) << "Failed to parse MHTML part: no header."; return false; } if (!header->isMultipart()) { // With IE a page with no resource is not multi-part. bool endOfArchiveReached = false; ArchiveResource* resource = parseNextPart(*header, String(), String(), endOfArchiveReached); if (!resource) return false; resources.append(resource); return true; } // Skip the message content (it's a generic browser specific message). skipLinesUntilBoundaryFound(m_lineReader, header->endOfPartBoundary()); bool endOfArchive = false; while (!endOfArchive) { MIMEHeader* resourceHeader = MIMEHeader::parseHeader(&m_lineReader); if (!resourceHeader) { DVLOG(1) << "Failed to parse MHTML, invalid MIME header."; return false; } if (resourceHeader->contentType() == "multipart/alternative") { // Ignore IE nesting which makes little sense (IE seems to nest only some // of the frames). if (!parseArchiveWithHeader(resourceHeader, resources)) { DVLOG(1) << "Failed to parse MHTML subframe."; return false; } skipLinesUntilBoundaryFound(m_lineReader, header->endOfPartBoundary()); continue; } ArchiveResource* resource = parseNextPart(*resourceHeader, header->endOfPartBoundary(), header->endOfDocumentBoundary(), endOfArchive); if (!resource) { DVLOG(1) << "Failed to parse MHTML part."; return false; } resources.append(resource); } return true; }
void CSSAnimations::calculateTransitionActiveInterpolations(CSSAnimationUpdate& update, const Element* animatingElement, double timelineCurrentTime) { ElementAnimations* elementAnimations = animatingElement ? animatingElement->elementAnimations() : nullptr; AnimationStack* animationStack = elementAnimations ? &elementAnimations->defaultStack() : nullptr; ActiveInterpolationsMap activeInterpolationsForTransitions; if (update.newTransitions().isEmpty() && update.cancelledTransitions().isEmpty()) { activeInterpolationsForTransitions = AnimationStack::activeInterpolations(animationStack, 0, 0, KeyframeEffect::TransitionPriority, timelineCurrentTime); } else { HeapVector<Member<InertEffect>> newTransitions; for (const auto& entry : update.newTransitions()) newTransitions.append(entry.value.effect.get()); HeapHashSet<Member<const Animation>> cancelledAnimations; if (!update.cancelledTransitions().isEmpty()) { ASSERT(elementAnimations); const TransitionMap& transitionMap = elementAnimations->cssAnimations().m_transitions; for (CSSPropertyID id : update.cancelledTransitions()) { ASSERT(transitionMap.contains(id)); cancelledAnimations.add(transitionMap.get(id).animation.get()); } } activeInterpolationsForTransitions = AnimationStack::activeInterpolations(animationStack, &newTransitions, &cancelledAnimations, KeyframeEffect::TransitionPriority, timelineCurrentTime); } // Properties being animated by animations don't get values from transitions applied. if (!update.activeInterpolationsForAnimations().isEmpty() && !activeInterpolationsForTransitions.isEmpty()) { for (const auto& entry : update.activeInterpolationsForAnimations()) activeInterpolationsForTransitions.remove(entry.key); } update.adoptActiveInterpolationsForTransitions(activeInterpolationsForTransitions); }
void onSuccess(const WebVector<WebBluetoothRemoteGATTCharacteristicInit*>& webCharacteristics) override { if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContext()->activeDOMObjectsAreStopped()) return; // If the resolver is not in the set of ActiveAlgorithms then the frame // disconnected so we reject. if (!m_service->device()->gatt()->RemoveFromActiveAlgorithms( m_resolver.get())) { m_resolver->reject( DOMException::create(NetworkError, kGATTServerDisconnected)); return; } if (m_quantity == mojom::blink::WebBluetoothGATTQueryQuantity::SINGLE) { DCHECK_EQ(1u, webCharacteristics.size()); m_resolver->resolve(BluetoothRemoteGATTCharacteristic::take( m_resolver, wrapUnique(webCharacteristics[0]), m_service)); return; } HeapVector<Member<BluetoothRemoteGATTCharacteristic>> characteristics; characteristics.reserveInitialCapacity(webCharacteristics.size()); for (WebBluetoothRemoteGATTCharacteristicInit* webCharacteristic : webCharacteristics) { characteristics.append(BluetoothRemoteGATTCharacteristic::take( m_resolver, wrapUnique(webCharacteristic), m_service)); } m_resolver->resolve(characteristics); }
void onSuccess( const WebVector<WebBluetoothRemoteGATTService*>& webServices) override { if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContext()->isContextDestroyed()) return; // If the resolver is not in the set of ActiveAlgorithms then the frame // disconnected so we reject. if (!m_device->gatt()->RemoveFromActiveAlgorithms(m_resolver.get())) { m_resolver->reject( DOMException::create(NetworkError, kGATTServerDisconnected)); return; } if (m_quantity == mojom::blink::WebBluetoothGATTQueryQuantity::SINGLE) { DCHECK_EQ(1u, webServices.size()); m_resolver->resolve(m_device->getOrCreateBluetoothRemoteGATTService( WTF::wrapUnique(webServices[0]))); return; } HeapVector<Member<BluetoothRemoteGATTService>> services; services.reserveInitialCapacity(webServices.size()); for (WebBluetoothRemoteGATTService* webService : webServices) { services.append(m_device->getOrCreateBluetoothRemoteGATTService( WTF::wrapUnique(webService))); } m_resolver->resolve(services); }
void CSSSegmentedFontFace::match(const String& text, HeapVector<Member<FontFace>>& faces) const { for (const auto& fontFace : m_fontFaces) { if (fontFace->cssFontFace()->ranges()->intersectsWith(text)) faces.append(fontFace); } }
void AnimationTimeline::serviceAnimations(TimingUpdateReason reason) { TRACE_EVENT0("blink", "AnimationTimeline::serviceAnimations"); m_lastCurrentTimeInternal = currentTimeInternal(); HeapVector<Member<Animation>> animations; animations.reserveInitialCapacity(m_animationsNeedingUpdate.size()); for (Animation* animation : m_animationsNeedingUpdate) animations.append(animation); std::sort(animations.begin(), animations.end(), Animation::hasLowerPriority); for (Animation* animation : animations) { if (!animation->update(reason)) m_animationsNeedingUpdate.remove(animation); } ASSERT(m_outdatedAnimationCount == 0); ASSERT(m_lastCurrentTimeInternal == currentTimeInternal() || (std::isnan(currentTimeInternal()) && std::isnan(m_lastCurrentTimeInternal))); #if ENABLE(ASSERT) for (const auto& animation : m_animationsNeedingUpdate) ASSERT(!animation->outdated()); #endif }
void ScreenOrientationController::notifyOrientationChanged() { if (!isActiveAndVisible()) return; updateOrientation(); // Keep track of the frames that need to be notified before notifying the // current frame as it will prevent side effects from the change event // handlers. HeapVector<Member<LocalFrame>> childFrames; for (Frame* child = frame()->tree().firstChild(); child; child = child->tree().nextSibling()) { if (child->isLocalFrame()) childFrames.append(toLocalFrame(child)); } // Notify current orientation object. if (!m_dispatchEventTimer.isActive()) m_dispatchEventTimer.startOneShot(0, BLINK_FROM_HERE); // ... and child frames, if they have a ScreenOrientationController. for (size_t i = 0; i < childFrames.size(); ++i) { if (ScreenOrientationController* controller = ScreenOrientationController::from(*childFrames[i])) controller->notifyOrientationChanged(); } }
StaticNodeList* SVGSVGElement::collectIntersectionOrEnclosureList( const FloatRect& rect, SVGElement* referenceElement, CheckIntersectionOrEnclosure mode) const { HeapVector<Member<Node>> nodes; const SVGElement* root = this; if (referenceElement) { // Only the common subtree needs to be traversed. if (contains(referenceElement)) { root = referenceElement; } else if (!isDescendantOf(referenceElement)) { // No common subtree. return StaticNodeList::adopt(nodes); } } for (SVGGraphicsElement& element : Traversal<SVGGraphicsElement>::descendantsOf(*root)) { if (checkIntersectionOrEnclosure(element, rect, mode)) nodes.append(&element); } return StaticNodeList::adopt(nodes); }
DispatchEventResult IDBTransaction::dispatchEventInternal(Event* event) { IDB_TRACE("IDBTransaction::dispatchEvent"); if (!getExecutionContext()) { m_state = Finished; return DispatchEventResult::CanceledBeforeDispatch; } DCHECK_NE(m_state, Finished); DCHECK(m_hasPendingActivity); DCHECK(getExecutionContext()); DCHECK_EQ(event->target(), this); m_state = Finished; HeapVector<Member<EventTarget>> targets; targets.append(this); targets.append(db()); // FIXME: When we allow custom event dispatching, this will probably need to // change. DCHECK(event->type() == EventTypeNames::complete || event->type() == EventTypeNames::abort); DispatchEventResult dispatchResult = IDBEventDispatcher::dispatch(event, targets); // FIXME: Try to construct a test where |this| outlives openDBRequest and we // get a crash. if (m_openDBRequest) { DCHECK(isVersionChange()); m_openDBRequest->transactionDidFinishAndDispatch(); } m_hasPendingActivity = false; return dispatchResult; }
void runAdoptedCallback(Element* element, Document* oldOwner, Document* newOwner) override { m_logs.append(AdoptedCallback); EXPECT_EQ(element, m_element); m_adopted.append(new Adopted(oldOwner, newOwner)); }
void MutationObserver::deliver() { DCHECK(!shouldBeSuspended()); // Calling clearTransientRegistrations() can modify m_registrations, so it's // necessary to make a copy of the transient registrations before operating on // them. HeapVector<Member<MutationObserverRegistration>, 1> transientRegistrations; for (auto& registration : m_registrations) { if (registration->hasTransientRegistrations()) transientRegistrations.append(registration); } for (size_t i = 0; i < transientRegistrations.size(); ++i) transientRegistrations[i]->clearTransientRegistrations(); if (m_records.isEmpty()) return; MutationRecordVector records; records.swap(m_records); // Report the first (earliest) stack as the async cause. InspectorInstrumentation::AsyncTask asyncTask( m_callback->getExecutionContext(), records.first()); m_callback->call(records, this); }
void SplitElementCommand::executeApply() { if (m_atChild->parentNode() != m_element2) return; HeapVector<Member<Node>> children; for (Node* node = m_element2->firstChild(); node != m_atChild; node = node->nextSibling()) children.append(node); DummyExceptionStateForTesting exceptionState; ContainerNode* parent = m_element2->parentNode(); if (!parent || !hasEditableStyle(*parent)) return; parent->insertBefore(m_element1.get(), m_element2.get(), exceptionState); if (exceptionState.hadException()) return; // Delete id attribute from the second element because the same id cannot be // used for more than one element m_element2->removeAttribute(HTMLNames::idAttr); for (const auto& child : children) m_element1->appendChild(child, exceptionState); }
void Frame::didChangeVisibilityState() { HeapVector<Member<Frame>> childFrames; for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) childFrames.append(child); for (size_t i = 0; i < childFrames.size(); ++i) childFrames[i]->didChangeVisibilityState(); }
void AXObject::scrollToGlobalPoint(const IntPoint& globalPoint) const { // Search up the parent chain and create a vector of all scrollable parent objects // and ending with this object itself. HeapVector<Member<const AXObject>> objects; AXObject* parentObject; for (parentObject = this->parentObject(); parentObject; parentObject = parentObject->parentObject()) { if (parentObject->getScrollableAreaIfScrollable() && !parentObject->isAXScrollView()) objects.prepend(parentObject); } objects.append(this); // Start with the outermost scrollable (the main window) and try to scroll the // next innermost object to the given point. int offsetX = 0, offsetY = 0; IntPoint point = globalPoint; size_t levels = objects.size() - 1; for (size_t i = 0; i < levels; i++) { const AXObject* outer = objects[i]; const AXObject* inner = objects[i + 1]; ScrollableArea* scrollableArea = outer->getScrollableAreaIfScrollable(); IntRect innerRect = inner->isWebArea() ? pixelSnappedIntRect(inner->parentObject()->elementRect()) : pixelSnappedIntRect(inner->elementRect()); IntRect objectRect = innerRect; IntPoint scrollPosition = scrollableArea->scrollPosition(); // Convert the object rect into local coordinates. objectRect.move(offsetX, offsetY); if (!outer->isWebArea()) objectRect.move(scrollPosition.x(), scrollPosition.y()); int desiredX = computeBestScrollOffset( 0, objectRect.x(), objectRect.maxX(), objectRect.x(), objectRect.maxX(), point.x(), point.x()); int desiredY = computeBestScrollOffset( 0, objectRect.y(), objectRect.maxY(), objectRect.y(), objectRect.maxY(), point.y(), point.y()); outer->setScrollOffset(IntPoint(desiredX, desiredY)); if (outer->isWebArea() && !inner->isWebArea()) { // If outer object we just scrolled is a web area (frame) but the inner object // is not, keep track of the coordinate transformation to apply to // future nested calculations. scrollPosition = scrollableArea->scrollPosition(); offsetX -= (scrollPosition.x() + point.x()); offsetY -= (scrollPosition.y() + point.y()); point.move(scrollPosition.x() - innerRect.x(), scrollPosition.y() - innerRect.y()); } else if (inner->isWebArea()) { // Otherwise, if the inner object is a web area, reset the coordinate transformation. offsetX = 0; offsetY = 0; } } }
static Position findWordBoundary(const HTMLElement* innerEditor, const Position& startPosition, const Position& endPosition, FindOption findOption) { StringBuilder concatTexts; Vector<unsigned> lengthList; HeapVector<Member<Text>> textList; if (startPosition.anchorNode()->isTextNode()) ASSERT(startPosition.isOffsetInAnchor()); if (endPosition.anchorNode()->isTextNode()) ASSERT(endPosition.isOffsetInAnchor()); // Traverse text nodes. for (Node* node = startPosition.anchorNode(); node; node = NodeTraversal::next(*node, innerEditor)) { bool isStartNode = node == startPosition.anchorNode(); bool isEndNode = node == endPosition.anchorNode(); if (node->isTextNode()) { Text* text = toText(node); const unsigned start = isStartNode ? startPosition.offsetInContainerNode() : 0; const unsigned end = isEndNode ? endPosition.offsetInContainerNode() : text->data().length(); const unsigned length = end - start; concatTexts.append(text->data(), start, length); lengthList.append(length); textList.append(text); } if (isEndNode) break; } if (concatTexts.length() == 0) return startPosition; int start, end; if (findOption == FindEnd && concatTexts[0] == '\n') { // findWordBoundary("\ntext", 0, &start, &end) assigns 1 to |end| but // we expect 0 at the case. start = 0; end = 0; } else { Vector<UChar> characters; concatTexts.toString().appendTo(characters); findWordBoundary(characters.data(), characters.size(), findOption == FindStart ? characters.size() : 0, &start, &end); } ASSERT(start >= 0); ASSERT(end >= 0); unsigned remainingOffset = findOption == FindStart ? start : end; // Find position. for (unsigned i = 0; i < lengthList.size(); ++i) { if (remainingOffset <= lengthList[i]) return Position(textList[i], (textList[i] == startPosition.anchorNode()) ? remainingOffset + startPosition.offsetInContainerNode() : remainingOffset); remainingOffset -= lengthList[i]; } ASSERT_NOT_REACHED(); return Position(); }
inline void DistributionPool::populateChildren(const ContainerNode& parent) { clear(); for (Node* child = parent.firstChild(); child; child = child->nextSibling()) { if (isHTMLSlotElement(child)) { // TODO(hayato): Support re-distribution across v0 and v1 shadow trees continue; } if (isActiveInsertionPoint(*child)) { InsertionPoint* insertionPoint = toInsertionPoint(child); for (size_t i = 0; i < insertionPoint->distributedNodesSize(); ++i) m_nodes.append(insertionPoint->distributedNodeAt(i)); } else { m_nodes.append(child); } } m_distributed.resize(m_nodes.size()); m_distributed.fill(false); }
void executeScriptInIsolatedWorld(const String& script) const { v8::HandleScope scope(v8::Isolate::GetCurrent()); HeapVector<ScriptSourceCode> sources; sources.append(ScriptSourceCode(script)); Vector<v8::Local<v8::Value>> results; m_scriptController->executeScriptInIsolatedWorld(isolatedWorldId, sources, extensionGroup, 0); pumpPendingRequestsForFrameToLoad(m_webViewHelper.webView()->mainFrame()); }
void IntersectionObserverController::removeTrackedObserversForRoot( const Node& root) { HeapVector<Member<IntersectionObserver>> toRemove; for (auto& observer : m_trackedIntersectionObservers) { if (observer->rootNode() == &root) toRemove.append(observer); } m_trackedIntersectionObservers.removeAll(toRemove); }
void InsertParagraphSeparatorCommand::getAncestorsInsideBlock(const Node* insertionNode, Element* outerBlock, HeapVector<Member<Element>>& ancestors) { ancestors.clear(); // Build up list of ancestors elements between the insertion node and the outer block. if (insertionNode != outerBlock) { for (Element* n = insertionNode->parentElement(); n && n != outerBlock; n = n->parentElement()) ancestors.append(n); } }
HeapVector<Member<Animation>> AnimationTimeline::getAnimations() { HeapVector<Member<Animation>> animations; for (const auto& animation : m_animations) { if (animation->effect() && (animation->effect()->isCurrent() || animation->effect()->isInEffect())) animations.append(animation); } std::sort(animations.begin(), animations.end(), compareAnimations); return animations; }
PassRefPtrWillBeRawPtr<SpeechRecognitionEvent> SpeechRecognitionEvent::createNoMatch(SpeechRecognitionResult* result) { if (result) { HeapVector<Member<SpeechRecognitionResult>> results; results.append(result); return adoptRefWillBeNoop(new SpeechRecognitionEvent(EventTypeNames::nomatch, 0, SpeechRecognitionResultList::create(results))); } return adoptRefWillBeNoop(new SpeechRecognitionEvent(EventTypeNames::nomatch, 0, nullptr)); }
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. HeapVector<Member<FontFace>> fontFaces; if (inActiveDocumentContext()) { const HeapListHashSet<Member<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); }
PaymentAppRequestData PaymentAppRequestDataConversion::toPaymentAppRequestData( ScriptState* scriptState, const WebPaymentAppRequestData& webData) { PaymentAppRequestData data; data.setOrigin(webData.origin); HeapVector<PaymentMethodData> methodData; for (const auto& md : webData.methodData) { methodData.append(toPaymentMethodData(scriptState, md)); } data.setMethodData(methodData); data.setTotal(toPaymentItem(webData.total)); HeapVector<PaymentDetailsModifier> modifiers; for (const auto& modifier : webData.modifiers) { modifiers.append(toPaymentDetailsModifier(scriptState, modifier)); } data.setOptionId(webData.optionId); return data; }
bool TouchEventManager::generateTouchInfosAfterHittest( const PlatformTouchEvent& event, HeapVector<TouchInfo>& touchInfos) { bool newTouchSequence = true; bool allTouchesReleased = true; for (const auto& point : event.touchPoints()) { if (point.state() != PlatformTouchPoint::TouchPressed) newTouchSequence = false; if (point.state() != PlatformTouchPoint::TouchReleased && point.state() != PlatformTouchPoint::TouchCancelled) allTouchesReleased = false; } if (newTouchSequence) { // Ideally we'd ASSERT(!m_touchSequenceDocument) here since we should // have cleared the active document when we saw the last release. But we // have some tests that violate this, ClusterFuzz could trigger it, and // there may be cases where the browser doesn't reliably release all // touches. http://crbug.com/345372 tracks this. m_touchSequenceDocument.clear(); m_touchSequenceUserGestureToken.clear(); } ASSERT(m_frame->view()); if (m_touchSequenceDocument && (!m_touchSequenceDocument->frame() || !m_touchSequenceDocument->frame()->view())) { // If the active touch document has no frame or view, it's probably being destroyed // so we can't dispatch events. return false; } for (const auto& point : event.touchPoints()) { TouchEventManager::TouchInfo touchInfo; touchInfo.point = point; touchInfos.append(touchInfo); } updateTargetAndRegionMapsForTouchStarts(touchInfos); m_touchPressed = !allTouchesReleased; // If there's no document receiving touch events, or no handlers on the // document set to receive the events, then we can skip all the rest of // this work. if (!m_touchSequenceDocument || !m_touchSequenceDocument->frameHost() || !hasTouchHandlers(m_touchSequenceDocument->frameHost()->eventHandlerRegistry()) || !m_touchSequenceDocument->frame()) { if (allTouchesReleased) { m_touchSequenceDocument.clear(); m_touchSequenceUserGestureToken.clear(); } return false; } setAllPropertiesOfTouchInfos(touchInfos); return true; }
void CSSAnimations::calculateAnimationActiveInterpolations(CSSAnimationUpdate& update, const Element* animatingElement, double timelineCurrentTime) { ElementAnimations* elementAnimations = animatingElement ? animatingElement->elementAnimations() : nullptr; AnimationStack* animationStack = elementAnimations ? &elementAnimations->defaultStack() : nullptr; if (update.newAnimations().isEmpty() && update.suppressedAnimations().isEmpty()) { ActiveInterpolationsMap activeInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, 0, 0, KeyframeEffect::DefaultPriority, timelineCurrentTime)); update.adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimations); return; } HeapVector<Member<InertEffect>> newEffects; for (const auto& newAnimation : update.newAnimations()) newEffects.append(newAnimation.effect.get()); for (const auto& updatedAnimation : update.animationsWithUpdates()) newEffects.append(updatedAnimation.effect.get()); // Animations with updates use a temporary InertEffect for the current frame. ActiveInterpolationsMap activeInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, &newEffects, &update.suppressedAnimations(), KeyframeEffect::DefaultPriority, timelineCurrentTime)); update.adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimations); }
const TreeScope* TreeScope::commonAncestorTreeScope(const TreeScope& other) const { HeapVector<Member<const TreeScope>, 16> thisChain; for (const TreeScope* tree = this; tree; tree = tree->parentTreeScope()) thisChain.append(tree); HeapVector<Member<const TreeScope>, 16> otherChain; for (const TreeScope* tree = &other; tree; tree = tree->parentTreeScope()) otherChain.append(tree); // Keep popping out the last elements of these chains until a mismatched pair is found. If |this| and |other| // belong to different documents, null will be returned. const TreeScope* lastAncestor = nullptr; while (!thisChain.isEmpty() && !otherChain.isEmpty() && thisChain.last() == otherChain.last()) { lastAncestor = thisChain.last(); thisChain.removeLast(); otherChain.removeLast(); } return lastAncestor; }
PointerEvent* PointerEventFactory::create( const PlatformTouchPoint& touchPoint, const Vector<PlatformTouchPoint>& coalescedPoints, PlatformEvent::Modifiers modifiers, LocalFrame* targetFrame, DOMWindow* view) { const PlatformTouchPoint::TouchState pointState = touchPoint.state(); const AtomicString& type = pointerEventNameForTouchPointState(touchPoint.state()); DCHECK(type == EventTypeNames::pointermove || coalescedPoints.isEmpty()); bool pointerReleasedOrCancelled = pointState == PlatformTouchPoint::TouchReleased || pointState == PlatformTouchPoint::TouchCancelled; bool pointerPressedOrReleased = pointState == PlatformTouchPoint::TouchPressed || pointState == PlatformTouchPoint::TouchReleased; PointerEventInit pointerEventInit; setIdTypeButtons(pointerEventInit, touchPoint.pointerProperties(), pointerReleasedOrCancelled ? 0 : 1); pointerEventInit.setButton(static_cast<int>( pointerPressedOrReleased ? WebPointerProperties::Button::Left : WebPointerProperties::Button::NoButton)); pointerEventInit.setView(view); updateTouchPointerEventInit(touchPoint, targetFrame, &pointerEventInit); UIEventWithKeyState::setFromPlatformModifiers(pointerEventInit, modifiers); setEventSpecificFields(pointerEventInit, type); // Created coalesced events init structure HeapVector<Member<PointerEvent>> coalescedPointerEvents; for (const auto& coalescedTouchPoint : coalescedPoints) { DCHECK_EQ(touchPoint.state(), coalescedTouchPoint.state()); DCHECK_EQ(touchPoint.pointerProperties().id, coalescedTouchPoint.pointerProperties().id); DCHECK_EQ(touchPoint.pointerProperties().pointerType, coalescedTouchPoint.pointerProperties().pointerType); PointerEventInit coalescedEventInit = pointerEventInit; updateTouchPointerEventInit(coalescedTouchPoint, targetFrame, &coalescedEventInit); coalescedPointerEvents.append( PointerEvent::create(type, coalescedEventInit)); } pointerEventInit.setCoalescedEvents(coalescedPointerEvents); return PointerEvent::create(type, pointerEventInit); }