blob: 1ced8033ead50a11723d21ed71225a44f38f5f2b [file] [log] [blame]
/*
* Copyright (C) 2004-2020 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#pragma once
#include "CharacterData.h"
#include "Document.h"
#include "Element.h"
#include "InspectorInstrumentationPublic.h"
#include "LayoutRect.h"
#include "Node.h"
#include "PseudoElement.h"
#include "RenderBox.h"
#include "TreeScopeInlines.h"
#include "WebCoreOpaqueRoot.h"
namespace WebCore {
inline RefPtr<ScriptExecutionContext> Node::protectedScriptExecutionContext() const
{
return scriptExecutionContext();
}
inline WebCoreOpaqueRoot Node::opaqueRoot() const
{
if (isConnected()) {
Locker locker { TreeScope::treeScopeMutationLock() };
return WebCoreOpaqueRoot { &treeScope().documentScope() };
}
// FIXME: Possible race?
return traverseToOpaqueRoot();
}
inline Document& Node::document() const
{
return treeScope().documentScope();
}
inline Ref<Document> Node::protectedDocument() const
{
return document();
}
inline Ref<TreeScope> Node::protectedTreeScope() const
{
return treeScope();
}
inline RenderBox* Node::renderBox() const
{
return dynamicDowncast<RenderBox>(renderer());
}
inline RenderBoxModelObject* Node::renderBoxModelObject() const
{
return dynamicDowncast<RenderBoxModelObject>(renderer());
}
inline bool Node::hasAttributes() const
{
auto* element = dynamicDowncast<Element>(*this);
return element && element->hasAttributes();
}
inline NamedNodeMap* Node::attributesMap() const
{
if (auto* element = dynamicDowncast<Element>(*this))
return &element->attributesMap();
return nullptr;
}
CheckedPtr<RenderObject> Node::checkedRenderer() const
{
return renderer();
}
inline void Node::setRenderer(RenderObject* renderer)
{
m_renderer = renderer;
if (InspectorInstrumentationPublic::hasFrontends()) [[unlikely]]
notifyInspectorOfRendererChange();
}
inline Element* Node::parentElement() const
{
return dynamicDowncast<Element>(parentNode());
}
inline RefPtr<Element> Node::protectedParentElement() const
{
return parentElement();
}
bool Node::isBeforePseudoElement() const
{
return pseudoId() == PseudoId::Before;
}
bool Node::isAfterPseudoElement() const
{
return pseudoId() == PseudoId::After;
}
PseudoId Node::pseudoId() const
{
if (auto* pseudoElement = dynamicDowncast<PseudoElement>(*this))
return pseudoElement->pseudoId();
return PseudoId::None;
}
inline void Node::setTabIndexState(TabIndexState state)
{
auto bitfields = rareDataBitfields();
bitfields.tabIndexState = enumToUnderlyingType(state);
setRareDataBitfields(bitfields);
}
inline unsigned Node::length() const
{
if (auto characterData = dynamicDowncast<CharacterData>(*this))
return characterData->length();
return countChildNodes();
}
inline unsigned Node::countChildNodes() const
{
auto* containerNode = dynamicDowncast<ContainerNode>(*this);
return containerNode ? containerNode->countChildNodes() : 0;
}
inline Node* Node::traverseToChildAt(unsigned index) const
{
auto* containerNode = dynamicDowncast<ContainerNode>(*this);
return containerNode ? containerNode->traverseToChildAt(index) : nullptr;
}
inline Node* Node::firstChild() const
{
auto* containerNode = dynamicDowncast<ContainerNode>(*this);
return containerNode ? containerNode->firstChild() : nullptr;
}
inline RefPtr<Node> Node::protectedFirstChild() const
{
return firstChild();
}
inline Node* Node::lastChild() const
{
auto* containerNode = dynamicDowncast<ContainerNode>(*this);
return containerNode ? containerNode->lastChild() : nullptr;
}
inline RefPtr<Node> Node::protectedLastChild() const
{
return lastChild();
}
inline bool Node::hasChildNodes() const
{
return firstChild();
}
inline Node& Node::rootNode() const
{
if (isInTreeScope())
return treeScope().rootNode();
return traverseToRootNode();
}
inline void Node::setParentNode(ContainerNode* parent)
{
ASSERT(isMainThread());
m_parentNode = parent;
m_refCountAndParentBit = (m_refCountAndParentBit & s_refCountMask) | !!parent;
}
inline RefPtr<ContainerNode> Node::protectedParentNode() const
{
return parentNode();
}
ALWAYS_INLINE bool Node::hasOneRef() const
{
ASSERT(!deletionHasBegun());
ASSERT(!m_inRemovedLastRefFunction);
return refCount() == 1;
}
ALWAYS_INLINE void Node::clearStyleFlags(OptionSet<NodeStyleFlag> flags)
{
auto bitfields = styleBitfields();
bitfields.clearFlags(flags);
setStyleBitfields(bitfields);
}
inline void Node::clearChildNeedsStyleRecalc()
{
auto bitfields = styleBitfields();
bitfields.clearDescendantsNeedStyleResolution();
setStyleBitfields(bitfields);
}
inline void Node::setHasValidStyle()
{
auto bitfields = styleBitfields();
bitfields.setStyleValidity(Style::Validity::Valid);
setStyleBitfields(bitfields);
clearStateFlag(StateFlag::IsComputedStyleInvalidFlag);
clearStateFlag(StateFlag::HasInvalidRenderer);
clearStateFlag(StateFlag::StyleResolutionShouldRecompositeLayer);
}
inline void Node::setTreeScopeRecursively(TreeScope& newTreeScope)
{
ASSERT(!isDocumentNode());
ASSERT(!deletionHasBegun());
if (m_treeScope != &newTreeScope) {
Ref oldTreeScope = *m_treeScope;
moveTreeToNewScope(*this, oldTreeScope, newTreeScope);
}
}
inline ContainerNode* Node::parentNodeGuaranteedHostFree() const
{
ASSERT(!isShadowRoot());
return parentNode();
}
inline void Node::setTreeScope(TreeScope& scope)
{
Locker locker { TreeScope::treeScopeMutationLock() };
m_treeScope = &scope;
}
template<typename NodeClass>
inline NodeClass& Node::traverseToRootNodeInternal(const NodeClass& node)
{
auto* current = const_cast<NodeClass*>(&node);
while (current->parentNode())
current = current->parentNode();
return *current;
}
inline void Node::relaxAdoptionRequirement()
{
#if ASSERT_ENABLED
ASSERT_WITH_SECURITY_IMPLICATION(!deletionHasBegun());
ASSERT(m_adoptionIsRequired);
m_adoptionIsRequired = false;
#endif
}
inline IntRect Node::pixelSnappedAbsoluteBoundingRect(bool* isReplaced)
{
return snappedIntRect(absoluteBoundingRect(isReplaced));
}
// Used in Node::addSubresourceAttributeURLs() and in addSubresourceStyleURLs()
inline void addSubresourceURL(ListHashSet<URL>& urls, const URL& url)
{
if (!url.isNull())
urls.add(url);
}
inline void collectChildNodes(Node& node, NodeVector& children)
{
for (SUPPRESS_UNCOUNTED_LOCAL Node* child = node.firstChild(); child; child = child->nextSibling())
children.append(*child);
}
} // namespace WebCore