コード例 #1
0
void EventPath::calculatePath()
{
    ASSERT(m_node);
    ASSERT(m_nodeEventContexts.isEmpty());
    m_node->updateDistribution();

    // For performance and memory usage reasons we want to store the
    // path using as few bytes as possible and with as few allocations
    // as possible which is why we gather the data on the stack before
    // storing it in a perfectly sized m_nodeEventContexts Vector.
    WillBeHeapVector<RawPtrWillBeMember<Node>, 64> nodesInPath;
    Node* current = m_node;
    nodesInPath.append(current);
    while (current) {
        if (m_event && current->keepEventInNode(m_event))
            break;
        WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
        collectDestinationInsertionPoints(*current, insertionPoints);
        if (!insertionPoints.isEmpty()) {
            for (const auto& insertionPoint : insertionPoints) {
                if (insertionPoint->isShadowInsertionPoint()) {
                    ShadowRoot* containingShadowRoot = insertionPoint->containingShadowRoot();
                    ASSERT(containingShadowRoot);
                    if (!containingShadowRoot->isOldest())
                        nodesInPath.append(containingShadowRoot->olderShadowRoot());
                }
                nodesInPath.append(insertionPoint);
            }
            current = insertionPoints.last();
            continue;
        }
        if (current->isShadowRoot()) {
            if (m_event && shouldStopAtShadowRoot(*m_event, *toShadowRoot(current), *m_node))
                break;
            current = current->shadowHost();
#if !ENABLE(OILPAN)
            // TODO(kochi): crbug.com/507413 This check is necessary when some asynchronous event
            // is queued while its shadow host is removed and the shadow root gets the event
            // immediately after it.  When Oilpan is enabled, this situation does not happen.
            // Except this case, shadow root's host is assumed to be non-null.
            if (current)
                nodesInPath.append(current);
#else
            nodesInPath.append(current);
#endif
        } else {
            current = current->parentNode();
            if (current)
                nodesInPath.append(current);
        }
    }

    m_nodeEventContexts.reserveCapacity(nodesInPath.size());
    for (Node* nodeInPath : nodesInPath) {
        m_nodeEventContexts.append(NodeEventContext(nodeInPath, eventTargetRespectingTargetRules(*nodeInPath)));
    }
}
コード例 #2
0
const TreeScope* TreeScope::commonAncestorTreeScope(const TreeScope& other) const
{
    WillBeHeapVector<RawPtrWillBeMember<const TreeScope>, 16> thisChain;
    for (const TreeScope* tree = this; tree; tree = tree->parentTreeScope())
        thisChain.append(tree);

    WillBeHeapVector<RawPtrWillBeMember<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;
}
コード例 #3
0
WillBeHeapVector<RawPtrWillBeMember<Element>> TreeScope::elementsFromPoint(int x, int y) const
{
    WillBeHeapVector<RawPtrWillBeMember<Element>> elements;

    Document& document = rootNode().document();
    IntPoint hitPoint(x, y);
    if (!pointWithScrollAndZoomIfPossible(document, hitPoint))
        return elements;

    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ListBased | HitTestRequest::PenetratingList);
    HitTestResult result(request, hitPoint);
    document.layoutView()->hitTest(result);

    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;
}
コード例 #4
0
ファイル: EventPath.cpp プロジェクト: eth-srl/BlinkER
void EventPath::calculatePath()
{
    ASSERT(m_node);
    ASSERT(m_nodeEventContexts.isEmpty());
    m_node->document().updateDistributionForNodeIfNeeded(const_cast<Node*>(m_node.get()));

    Node* current = m_node;
    addNodeEventContext(*current);
    if (!m_node->inDocument())
        return;
    while (current) {
        if (m_event && current->keepEventInNode(m_event))
            break;
        WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
        collectDestinationInsertionPoints(*current, insertionPoints);
        if (!insertionPoints.isEmpty()) {
            for (const auto& insertionPoint : insertionPoints) {
                if (insertionPoint->isShadowInsertionPoint()) {
                    ShadowRoot* containingShadowRoot = insertionPoint->containingShadowRoot();
                    ASSERT(containingShadowRoot);
                    if (!containingShadowRoot->isOldest())
                        addNodeEventContext(*containingShadowRoot->olderShadowRoot());
                }
                addNodeEventContext(*insertionPoint);
            }
            current = insertionPoints.last();
            continue;
        }
        if (current->isShadowRoot()) {
            if (m_event && shouldStopAtShadowRoot(*m_event, *toShadowRoot(current), *m_node))
                break;
            current = current->shadowHost();
            addNodeEventContext(*current);
        } else {
            current = current->parentNode();
            if (current)
                addNodeEventContext(*current);
        }
    }
}