diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/dom/TreeScope.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/dom/TreeScope.cpp')
-rw-r--r-- | Source/WebCore/dom/TreeScope.cpp | 328 |
1 files changed, 154 insertions, 174 deletions
diff --git a/Source/WebCore/dom/TreeScope.cpp b/Source/WebCore/dom/TreeScope.cpp index dcd165ec1..cc0e8e3ab 100644 --- a/Source/WebCore/dom/TreeScope.cpp +++ b/Source/WebCore/dom/TreeScope.cpp @@ -27,7 +27,6 @@ #include "config.h" #include "TreeScope.h" -#include "DOMSelection.h" #include "DOMWindow.h" #include "ElementIterator.h" #include "FocusController.h" @@ -40,6 +39,7 @@ #include "HitTestResult.h" #include "IdTargetObserverRegistry.h" #include "Page.h" +#include "PointerLockController.h" #include "RenderView.h" #include "RuntimeEnabledFeatures.h" #include "ShadowRoot.h" @@ -49,98 +49,71 @@ namespace WebCore { struct SameSizeAsTreeScope { - virtual ~SameSizeAsTreeScope(); - void* pointers[9]; - int ints[1]; + void* pointers[8]; }; COMPILE_ASSERT(sizeof(TreeScope) == sizeof(SameSizeAsTreeScope), treescope_should_stay_small); using namespace HTMLNames; -TreeScope::TreeScope(ContainerNode* rootNode, Document* document) - : m_rootNode(rootNode) +TreeScope::TreeScope(ShadowRoot& shadowRoot, Document& document) + : m_rootNode(shadowRoot) , m_documentScope(document) - , m_parentTreeScope(document) - , m_selfOnlyRefCount(0) - , m_idTargetObserverRegistry(IdTargetObserverRegistry::create()) + , m_parentTreeScope(&document) + , m_idTargetObserverRegistry(std::make_unique<IdTargetObserverRegistry>()) { - ASSERT(rootNode); - ASSERT(document); - ASSERT(rootNode != document); - m_parentTreeScope->selfOnlyRef(); - m_rootNode->setTreeScope(*this); + shadowRoot.setTreeScope(*this); } -TreeScope::TreeScope(Document* document) +TreeScope::TreeScope(Document& document) : m_rootNode(document) , m_documentScope(document) , m_parentTreeScope(nullptr) - , m_selfOnlyRefCount(0) - , m_idTargetObserverRegistry(IdTargetObserverRegistry::create()) -{ - ASSERT(document); - m_rootNode->setTreeScope(*this); -} - -TreeScope::TreeScope() - : m_rootNode(nullptr) - , m_documentScope(nullptr) - , m_parentTreeScope(nullptr) - , m_selfOnlyRefCount(0) + , m_idTargetObserverRegistry(std::make_unique<IdTargetObserverRegistry>()) { + document.setTreeScope(*this); } TreeScope::~TreeScope() { - ASSERT(!m_selfOnlyRefCount); - m_rootNode->setTreeScope(noDocumentInstance()); - - if (m_selection) { - m_selection->clearTreeScope(); - m_selection = nullptr; - } - - if (m_parentTreeScope) - m_parentTreeScope->selfOnlyDeref(); } void TreeScope::destroyTreeScopeData() { - m_elementsById.clear(); - m_imageMapsByName.clear(); - m_labelsByForAttribute.clear(); + m_elementsById = nullptr; + m_imageMapsByName = nullptr; + m_labelsByForAttribute = nullptr; } -void TreeScope::clearDocumentScope() -{ - ASSERT(rootNode()->isDocumentNode()); - m_documentScope = nullptr; -} - -void TreeScope::setParentTreeScope(TreeScope* newParentScope) +void TreeScope::setParentTreeScope(TreeScope& newParentScope) { // A document node cannot be re-parented. - ASSERT(!rootNode()->isDocumentNode()); - // Every scope other than document needs a parent scope. - ASSERT(newParentScope); - - newParentScope->selfOnlyRef(); - if (m_parentTreeScope) - m_parentTreeScope->selfOnlyDeref(); - m_parentTreeScope = newParentScope; - setDocumentScope(newParentScope->documentScope()); + ASSERT(!m_rootNode.isDocumentNode()); + + m_parentTreeScope = &newParentScope; + setDocumentScope(newParentScope.documentScope()); } Element* TreeScope::getElementById(const AtomicString& elementId) const { - if (elementId.isEmpty()) + if (elementId.isNull()) return nullptr; if (!m_elementsById) return nullptr; return m_elementsById->getElementById(*elementId.impl(), *this); } +Element* TreeScope::getElementById(const String& elementId) const +{ + if (!m_elementsById) + return nullptr; + + if (RefPtr<AtomicStringImpl> atomicElementId = AtomicStringImpl::lookUp(elementId.impl())) + return m_elementsById->getElementById(*atomicElementId, *this); + + return nullptr; +} + const Vector<Element*>* TreeScope::getAllElementsById(const AtomicString& elementId) const { if (elementId.isEmpty()) @@ -153,7 +126,7 @@ const Vector<Element*>* TreeScope::getAllElementsById(const AtomicString& elemen void TreeScope::addElementById(const AtomicStringImpl& elementId, Element& element, bool notifyObservers) { if (!m_elementsById) - m_elementsById = adoptPtr(new DocumentOrderedMap); + m_elementsById = std::make_unique<DocumentOrderedMap>(); m_elementsById->add(elementId, element, *this); if (notifyObservers) m_idTargetObserverRegistry->notifyObservers(elementId); @@ -180,7 +153,7 @@ Element* TreeScope::getElementByName(const AtomicString& name) const void TreeScope::addElementByName(const AtomicStringImpl& name, Element& element) { if (!m_elementsByName) - m_elementsByName = adoptPtr(new DocumentOrderedMap); + m_elementsByName = std::make_unique<DocumentOrderedMap>(); m_elementsByName->add(name, element, *this); } @@ -191,7 +164,39 @@ void TreeScope::removeElementByName(const AtomicStringImpl& name, Element& eleme m_elementsByName->remove(name, element); } -Node* TreeScope::ancestorInThisScope(Node* node) const + +Node& TreeScope::retargetToScope(Node& node) const +{ + auto& scope = node.treeScope(); + if (LIKELY(this == &scope || !node.isInShadowTree())) + return node; + ASSERT(is<ShadowRoot>(scope.rootNode())); + + Vector<TreeScope*, 8> nodeTreeScopes; + for (auto* currentScope = &scope; currentScope; currentScope = currentScope->parentTreeScope()) + nodeTreeScopes.append(currentScope); + ASSERT(nodeTreeScopes.size() >= 2); + + Vector<const TreeScope*, 8> ancestorScopes; + for (auto* currentScope = this; currentScope; currentScope = currentScope->parentTreeScope()) + ancestorScopes.append(currentScope); + + size_t i = nodeTreeScopes.size(); + size_t j = ancestorScopes.size(); + while (i > 0 && j > 0 && nodeTreeScopes[i - 1] == ancestorScopes[j - 1]) { + --i; + --j; + } + + bool nodeIsInOuterTreeScope = !i; + if (nodeIsInOuterTreeScope) + return node; + + ShadowRoot& shadowRootInLowestCommonTreeScope = downcast<ShadowRoot>(nodeTreeScopes[i - 1]->rootNode()); + return *shadowRootInLowestCommonTreeScope.host(); +} + +Node* TreeScope::ancestorNodeInThisScope(Node* node) const { for (; node; node = node->shadowHost()) { if (&node->treeScope() == this) @@ -202,13 +207,24 @@ Node* TreeScope::ancestorInThisScope(Node* node) const return nullptr; } +Element* TreeScope::ancestorElementInThisScope(Element* element) const +{ + for (; element; element = element->shadowHost()) { + if (&element->treeScope() == this) + return element; + if (!element->isInShadowTree()) + return nullptr; + } + return nullptr; +} + void TreeScope::addImageMap(HTMLMapElement& imageMap) { AtomicStringImpl* name = imageMap.getName().impl(); if (!name) return; if (!m_imageMapsByName) - m_imageMapsByName = adoptPtr(new DocumentOrderedMap); + m_imageMapsByName = std::make_unique<DocumentOrderedMap>(); m_imageMapsByName->add(*name, imageMap, *this); } @@ -224,63 +240,17 @@ void TreeScope::removeImageMap(HTMLMapElement& imageMap) HTMLMapElement* TreeScope::getImageMap(const String& url) const { - if (url.isNull()) - return nullptr; if (!m_imageMapsByName) return nullptr; - size_t hashPos = url.find('#'); - String name = (hashPos == notFound ? url : url.substring(hashPos + 1)).impl(); + auto hashPosition = url.find('#'); + if (hashPosition == notFound) + return nullptr; + String name = url.substring(hashPosition + 1); if (name.isEmpty()) return nullptr; - if (rootNode()->document().isHTMLDocument()) { - AtomicString lowercasedName = name.lower(); - return m_imageMapsByName->getElementByLowercasedMapName(*lowercasedName.impl(), *this); - } return m_imageMapsByName->getElementByMapName(*AtomicString(name).impl(), *this); } -Node* nodeFromPoint(Document* document, int x, int y, LayoutPoint* localPoint) -{ - Frame* frame = document->frame(); - - if (!frame) - return nullptr; - FrameView* frameView = frame->view(); - if (!frameView) - return nullptr; - - float scaleFactor = frame->pageZoomFactor() * frame->frameScaleFactor(); -#if !PLATFORM(IOS) - IntPoint point = roundedIntPoint(FloatPoint(x * scaleFactor + frameView->scrollX(), y * scaleFactor + frameView->scrollY())); - - if (!frameView->visibleContentRect().contains(point)) - return nullptr; -#else - IntPoint point = roundedIntPoint(FloatPoint(x * scaleFactor + frameView->actualScrollX(), y * scaleFactor + frameView->actualScrollY())); - - if (!frameView->actualVisibleContentRect().contains(point)) - return nullptr; -#endif - HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent); - HitTestResult result(point); - document->renderView()->hitTest(request, result); - - if (localPoint) - *localPoint = result.localPoint(); - - return result.innerNode(); -} - -Element* TreeScope::elementFromPoint(int x, int y) const -{ - Node* node = nodeFromPoint(&rootNode()->document(), x, y); - while (node && !node->isElementNode()) - node = node->parentNode(); - if (node) - node = ancestorInThisScope(node); - return toElement(node); -} - void TreeScope::addLabel(const AtomicStringImpl& forAttributeValue, HTMLLabelElement& element) { ASSERT(m_labelsByForAttribute); @@ -300,10 +270,10 @@ HTMLLabelElement* TreeScope::labelElementForId(const AtomicString& forAttributeV if (!m_labelsByForAttribute) { // Populate the map on first access. - m_labelsByForAttribute = adoptPtr(new DocumentOrderedMap); + m_labelsByForAttribute = std::make_unique<DocumentOrderedMap>(); - for (auto& label : descendantsOfType<HTMLLabelElement>(*rootNode())) { - const AtomicString& forValue = label.fastGetAttribute(forAttr); + for (auto& label : descendantsOfType<HTMLLabelElement>(m_rootNode)) { + const AtomicString& forValue = label.attributeWithoutSynchronization(forAttr); if (!forValue.isEmpty()) addLabel(*forValue.impl(), label); } @@ -312,29 +282,56 @@ HTMLLabelElement* TreeScope::labelElementForId(const AtomicString& forAttributeV return m_labelsByForAttribute->getElementByLabelForAttribute(*forAttributeValue.impl(), *this); } -DOMSelection* TreeScope::getSelection() const +Node* TreeScope::nodeFromPoint(const LayoutPoint& clientPoint, LayoutPoint* localPoint) { - if (!rootNode()->document().frame()) + auto* frame = documentScope().frame(); + auto* view = documentScope().view(); + if (!frame || !view) return nullptr; - if (m_selection) - return m_selection.get(); + float scaleFactor = frame->pageZoomFactor() * frame->frameScaleFactor(); - // FIXME: The correct selection in Shadow DOM requires that Position can have a ShadowRoot - // as a container. It is now enabled only if runtime Shadow DOM feature is enabled. - // See https://bugs.webkit.org/show_bug.cgi?id=82697 -#if ENABLE(SHADOW_DOM) - if (RuntimeEnabledFeatures::sharedFeatures().shadowDOMEnabled()) { - m_selection = DOMSelection::create(this); - return m_selection.get(); - } + LayoutPoint contentsPoint = clientPoint; + contentsPoint.scale(scaleFactor); + contentsPoint.moveBy(view->contentsScrollPosition()); + + LayoutRect visibleRect; +#if PLATFORM(IOS) + visibleRect = view->unobscuredContentRect(); +#else + visibleRect = view->visibleContentRect(); #endif + if (!visibleRect.contains(contentsPoint)) + return nullptr; + + HitTestResult result(contentsPoint); + documentScope().renderView()->hitTest(HitTestRequest(), result); + + if (localPoint) + *localPoint = result.localPoint(); + + return result.innerNode(); +} + +Element* TreeScope::elementFromPoint(double x, double y) +{ + Document& document = documentScope(); + if (!document.hasLivingRenderTree()) + return nullptr; - if (this != &rootNode()->document()) - return rootNode()->document().getSelection(); + Node* node = nodeFromPoint(LayoutPoint(x, y), nullptr); + if (!node) + return nullptr; + + node = &retargetToScope(*node); + while (!is<Element>(*node)) { + node = node->parentInComposedTree(); + if (!node) + break; + node = &retargetToScope(*node); + } - m_selection = DOMSelection::create(&rootNode()->document()); - return m_selection.get(); + return downcast<Element>(node); } Element* TreeScope::findAnchor(const String& name) @@ -343,10 +340,12 @@ Element* TreeScope::findAnchor(const String& name) return nullptr; if (Element* element = getElementById(name)) return element; - for (auto& anchor : descendantsOfType<HTMLAnchorElement>(*rootNode())) { - if (rootNode()->document().inQuirksMode()) { - // Quirks mode, case insensitive comparison of names. - if (equalIgnoringCase(anchor.name(), name)) + for (auto& anchor : descendantsOfType<HTMLAnchorElement>(m_rootNode)) { + if (m_rootNode.document().inQuirksMode()) { + // Quirks mode, ASCII case-insensitive comparison of names. + // FIXME: This behavior is not mentioned in the HTML specification. + // We should either remove this or get this into the specification. + if (equalIgnoringASCIICase(anchor.name(), name)) return &anchor; } else { // Strict mode, names need to match exactly. @@ -357,17 +356,10 @@ Element* TreeScope::findAnchor(const String& name) return nullptr; } -bool TreeScope::applyAuthorStyles() const -{ - return true; -} - -void TreeScope::adoptIfNeeded(Node* node) +void TreeScope::adoptIfNeeded(Node& node) { - ASSERT(this); - ASSERT(node); - ASSERT(!node->isDocumentNode()); - ASSERT(!node->m_deletionHasBegun); + ASSERT(!node.isDocumentNode()); + ASSERT(!node.m_deletionHasBegun); TreeScopeAdopter adopter(node, *this); if (adopter.needsScopeChange()) adopter.execute(); @@ -382,25 +374,33 @@ static Element* focusedFrameOwnerElement(Frame* focusedFrame, Frame* currentFram return nullptr; } -Element* TreeScope::focusedElement() +Element* TreeScope::focusedElementInScope() { - Document& document = rootNode()->document(); + Document& document = documentScope(); Element* element = document.focusedElement(); if (!element && document.page()) element = focusedFrameOwnerElement(document.page()->focusController().focusedFrame(), document.frame()); - if (!element) + + return ancestorElementInThisScope(element); +} + +#if ENABLE(POINTER_LOCK) + +Element* TreeScope::pointerLockElement() const +{ + Document& document = documentScope(); + Page* page = document.page(); + if (!page || page->pointerLockController().lockPending()) return nullptr; - TreeScope* treeScope = &element->treeScope(); - while (treeScope != this && treeScope != &document) { - element = toShadowRoot(treeScope->rootNode())->hostElement(); - treeScope = &element->treeScope(); - } - if (this != treeScope) + auto* element = page->pointerLockController().element(); + if (!element || &element->document() != &document) return nullptr; - return element; + return ancestorElementInThisScope(element); } +#endif + static void listTreeScopes(Node* node, Vector<TreeScope*, 5>& treeScopes) { while (true) { @@ -438,24 +438,4 @@ TreeScope* commonTreeScope(Node* nodeA, Node* nodeB) return treeScopesA[indexA] == treeScopesB[indexB] ? treeScopesA[indexA] : nullptr; } -#ifndef NDEBUG -bool TreeScope::deletionHasBegun() -{ - return rootNode() && rootNode()->m_deletionHasBegun; -} - -void TreeScope::beginDeletion() -{ - ASSERT(this != &noDocumentInstance()); - rootNode()->m_deletionHasBegun = true; -} -#endif - -int TreeScope::refCount() const -{ - if (Node* root = rootNode()) - return root->refCount(); - return 0; -} - } // namespace WebCore |