Merge from Chromium at DEPS revision 257591
This commit was generated by merge_to_master.py.
Change-Id: I834f3ca85c1ef7ec2c1061847a3d92aa461da043
diff --git a/Source/core/dom/ActiveDOMObject.cpp b/Source/core/dom/ActiveDOMObject.cpp
index be52d0f..9ff9b5f 100644
--- a/Source/core/dom/ActiveDOMObject.cpp
+++ b/Source/core/dom/ActiveDOMObject.cpp
@@ -79,8 +79,29 @@
{
}
+void ActiveDOMObject::willStop()
+{
+}
+
void ActiveDOMObject::stop()
{
}
+void ActiveDOMObject::didMoveToNewExecutionContext(ExecutionContext* context)
+{
+ observeContext(context);
+
+ if (context->activeDOMObjectsAreStopped()) {
+ stop();
+ return;
+ }
+
+ if (context->activeDOMObjectsAreSuspended()) {
+ suspend();
+ return;
+ }
+
+ resume();
+}
+
} // namespace WebCore
diff --git a/Source/core/dom/ActiveDOMObject.h b/Source/core/dom/ActiveDOMObject.h
index 1157363..d51cac9 100644
--- a/Source/core/dom/ActiveDOMObject.h
+++ b/Source/core/dom/ActiveDOMObject.h
@@ -55,8 +55,13 @@
// which don't need special treatment can skip implementation.
virtual void suspend();
virtual void resume();
+ // willStop is called when stop() for the owner worker is called. It's not
+ // called if the owner is a Document. It's ok to post a task to the context.
+ virtual void willStop();
virtual void stop();
+ void didMoveToNewExecutionContext(ExecutionContext*);
+
protected:
virtual ~ActiveDOMObject();
diff --git a/Source/core/dom/ActiveDOMObjectTest.cpp b/Source/core/dom/ActiveDOMObjectTest.cpp
new file mode 100644
index 0000000..9be6d83
--- /dev/null
+++ b/Source/core/dom/ActiveDOMObjectTest.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/Document.h"
+
+#include "core/testing/DummyPageHolder.h"
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+
+namespace {
+
+class MockActiveDOMObject : public ActiveDOMObject {
+public:
+ MockActiveDOMObject(ExecutionContext* context) : ActiveDOMObject(context) { }
+
+ MOCK_METHOD0(suspend, void());
+ MOCK_METHOD0(resume, void());
+ MOCK_METHOD0(stop, void());
+};
+
+class ActiveDOMObjectTest : public ::testing::Test {
+protected:
+ ActiveDOMObjectTest();
+
+ Document& srcDocument() const { return m_srcPageHolder->document(); }
+ Document& destDocument() const { return m_destPageHolder->document(); }
+ MockActiveDOMObject& activeDOMObject() { return m_activeDOMObject; }
+
+private:
+ OwnPtr<DummyPageHolder> m_srcPageHolder;
+ OwnPtr<DummyPageHolder> m_destPageHolder;
+ MockActiveDOMObject m_activeDOMObject;
+};
+
+ActiveDOMObjectTest::ActiveDOMObjectTest()
+ : m_srcPageHolder(DummyPageHolder::create(IntSize(800, 600)))
+ , m_destPageHolder(DummyPageHolder::create(IntSize(800, 600)))
+ , m_activeDOMObject(&m_srcPageHolder->document())
+{
+ m_activeDOMObject.suspendIfNeeded();
+}
+
+TEST_F(ActiveDOMObjectTest, NewContextObserved)
+{
+ unsigned initialSrcCount = srcDocument().activeDOMObjectCount();
+ unsigned initialDestCount = destDocument().activeDOMObjectCount();
+
+ EXPECT_CALL(activeDOMObject(), resume());
+ activeDOMObject().didMoveToNewExecutionContext(&destDocument());
+
+ EXPECT_EQ(initialSrcCount - 1, srcDocument().activeDOMObjectCount());
+ EXPECT_EQ(initialDestCount + 1, destDocument().activeDOMObjectCount());
+}
+
+TEST_F(ActiveDOMObjectTest, MoveToActiveDocument)
+{
+ EXPECT_CALL(activeDOMObject(), resume());
+ activeDOMObject().didMoveToNewExecutionContext(&destDocument());
+}
+
+TEST_F(ActiveDOMObjectTest, MoveToSuspendedDocument)
+{
+ destDocument().suspendScheduledTasks();
+
+ EXPECT_CALL(activeDOMObject(), suspend());
+ activeDOMObject().didMoveToNewExecutionContext(&destDocument());
+}
+
+TEST_F(ActiveDOMObjectTest, MoveToStoppedDocument)
+{
+ destDocument().detach();
+
+ EXPECT_CALL(activeDOMObject(), stop());
+ activeDOMObject().didMoveToNewExecutionContext(&destDocument());
+}
+
+} // unnamed namespace
diff --git a/Source/core/dom/Attr.cpp b/Source/core/dom/Attr.cpp
index 93c3c94..c6454fa 100644
--- a/Source/core/dom/Attr.cpp
+++ b/Source/core/dom/Attr.cpp
@@ -170,7 +170,7 @@
{
ASSERT(m_element);
ASSERT(m_element->elementData());
- return *m_element->ensureUniqueElementData()->getAttributeItem(qualifiedName());
+ return *m_element->ensureUniqueElementData().getAttributeItem(qualifiedName());
}
void Attr::detachFromElementWithValue(const AtomicString& value)
diff --git a/Source/core/dom/Attr.idl b/Source/core/dom/Attr.idl
index 2403170..a2fab30 100644
--- a/Source/core/dom/Attr.idl
+++ b/Source/core/dom/Attr.idl
@@ -24,7 +24,7 @@
[TreatReturnedNullStringAs=Null] readonly attribute DOMString name;
- [DeprecateAs=AttributeSpecified] readonly attribute boolean specified;
+ [MeasureAs=AttributeSpecified] readonly attribute boolean specified;
[TreatReturnedNullStringAs=Null, TreatNullAs=NullString, RaisesException=Setter, CustomElementCallbacks] attribute DOMString value;
diff --git a/Source/core/dom/CSSSelectorWatch.cpp b/Source/core/dom/CSSSelectorWatch.cpp
index b6ac2e3..a9f941d 100644
--- a/Source/core/dom/CSSSelectorWatch.cpp
+++ b/Source/core/dom/CSSSelectorWatch.cpp
@@ -36,8 +36,8 @@
#include "core/css/StylePropertySet.h"
#include "core/dom/Document.h"
#include "core/dom/ExecutionContext.h"
+#include "core/frame/LocalFrame.h"
#include "core/loader/FrameLoaderClient.h"
-#include "core/frame/Frame.h"
#include "core/rendering/style/StyleRareNonInheritedData.h"
namespace WebCore {
@@ -54,10 +54,10 @@
CSSSelectorWatch& CSSSelectorWatch::from(Document& document)
{
- CSSSelectorWatch* watch = static_cast<CSSSelectorWatch*>(DocumentSupplement::from(&document, kSupplementName));
+ CSSSelectorWatch* watch = static_cast<CSSSelectorWatch*>(DocumentSupplement::from(document, kSupplementName));
if (!watch) {
watch = new CSSSelectorWatch(document);
- DocumentSupplement::provideTo(&document, kSupplementName, adoptPtr(watch));
+ DocumentSupplement::provideTo(document, kSupplementName, adoptPtr(watch));
}
return *watch;
}
@@ -69,7 +69,7 @@
if (m_timerExpirations < 1) {
m_timerExpirations++;
- m_callbackSelectorChangeTimer.startOneShot(0);
+ m_callbackSelectorChangeTimer.startOneShot(0, FROM_HERE);
return;
}
if (m_document.frame()) {
@@ -125,7 +125,7 @@
} else {
m_timerExpirations = 0;
if (!m_callbackSelectorChangeTimer.isActive())
- m_callbackSelectorChangeTimer.startOneShot(0);
+ m_callbackSelectorChangeTimer.startOneShot(0, FROM_HERE);
}
}
@@ -156,7 +156,7 @@
if (!allCompound(selectorList))
continue;
- RefPtr<StyleRule> rule = StyleRule::create();
+ RefPtrWillBeRawPtr<StyleRule> rule = StyleRule::create();
rule->wrapperAdoptSelectorList(selectorList);
rule->setProperties(callbackPropertySet);
m_watchedCallbackSelectors.append(rule.release());
diff --git a/Source/core/dom/CSSSelectorWatch.h b/Source/core/dom/CSSSelectorWatch.h
index e1cbbed..79a19d6 100644
--- a/Source/core/dom/CSSSelectorWatch.h
+++ b/Source/core/dom/CSSSelectorWatch.h
@@ -50,7 +50,7 @@
static CSSSelectorWatch& from(Document&);
void watchCSSSelectors(const Vector<String>& selectors);
- const Vector<RefPtr<StyleRule> >& watchedCallbackSelectors() const { return m_watchedCallbackSelectors; }
+ const WillBeHeapVector<RefPtrWillBeMember<StyleRule> >& watchedCallbackSelectors() const { return m_watchedCallbackSelectors; }
void updateSelectorMatches(const Vector<String>& removedSelectors, const Vector<String>& addedSelectors);
@@ -60,7 +60,7 @@
Document& m_document;
- Vector<RefPtr<StyleRule> > m_watchedCallbackSelectors;
+ WillBePersistentHeapVector<RefPtrWillBeMember<StyleRule> > m_watchedCallbackSelectors;
// Maps a CSS selector string with a -webkit-callback property to the number
// of matching RenderStyle objects in this document.
diff --git a/Source/core/dom/CharacterData.cpp b/Source/core/dom/CharacterData.cpp
index 2eecf98..4b2a386 100644
--- a/Source/core/dom/CharacterData.cpp
+++ b/Source/core/dom/CharacterData.cpp
@@ -195,7 +195,7 @@
if (!isInShadowTree()) {
if (document().hasListenerType(Document::DOMCHARACTERDATAMODIFIED_LISTENER))
- dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMCharacterDataModified, true, 0, oldData, m_data));
+ dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMCharacterDataModified, true, nullptr, oldData, m_data));
dispatchSubtreeModifiedEvent();
}
InspectorInstrumentation::characterDataModified(this);
diff --git a/Source/core/dom/ChildNode.h b/Source/core/dom/ChildNode.h
index 79aa891..19bcc5a 100644
--- a/Source/core/dom/ChildNode.h
+++ b/Source/core/dom/ChildNode.h
@@ -12,22 +12,19 @@
class ChildNode {
public:
- static Element* previousElementSibling(Node* node)
+ static Element* previousElementSibling(Node& node)
{
- ASSERT(node);
- return ElementTraversal::previousSibling(*node);
+ return ElementTraversal::previousSibling(node);
}
- static Element* nextElementSibling(Node* node)
+ static Element* nextElementSibling(Node& node)
{
- ASSERT(node);
- return ElementTraversal::nextSibling(*node);
+ return ElementTraversal::nextSibling(node);
}
- static void remove(Node* node, ExceptionState& exceptionState)
+ static void remove(Node& node, ExceptionState& exceptionState)
{
- ASSERT(node);
- return node->remove(exceptionState);
+ return node.remove(exceptionState);
}
};
diff --git a/Source/core/dom/ChildNodeList.cpp b/Source/core/dom/ChildNodeList.cpp
index ee585c4..bdef1e0 100644
--- a/Source/core/dom/ChildNodeList.cpp
+++ b/Source/core/dom/ChildNodeList.cpp
@@ -29,15 +29,14 @@
namespace WebCore {
-ChildNodeList::ChildNodeList(PassRefPtr<ContainerNode> parent)
+ChildNodeList::ChildNodeList(ContainerNode& parent)
: m_parent(parent)
{
- ASSERT(m_parent);
}
Node* ChildNodeList::virtualOwnerNode() const
{
- return ownerNode();
+ return &ownerNode();
}
ChildNodeList::~ChildNodeList()
diff --git a/Source/core/dom/ChildNodeList.h b/Source/core/dom/ChildNodeList.h
index 0fe38cc..c91a043 100644
--- a/Source/core/dom/ChildNodeList.h
+++ b/Source/core/dom/ChildNodeList.h
@@ -33,7 +33,7 @@
class ChildNodeList FINAL : public NodeList {
public:
- static PassRefPtr<ChildNodeList> create(PassRefPtr<ContainerNode> rootNode)
+ static PassRefPtr<ChildNodeList> create(ContainerNode& rootNode)
{
return adoptRef(new ChildNodeList(rootNode));
}
@@ -46,17 +46,17 @@
// Non-DOM API.
void invalidateCache() { m_collectionIndexCache.invalidate(); }
- ContainerNode* ownerNode() const { return m_parent.get(); }
+ ContainerNode& ownerNode() const { return *m_parent; }
// CollectionIndexCache API.
- ContainerNode& rootNode() const { return *m_parent; }
+ ContainerNode& rootNode() const { return ownerNode(); }
bool canTraverseBackward() const { return true; }
Node* itemBefore(const Node* previousItem) const;
Node* traverseToFirstElement(const ContainerNode& root) const { return root.firstChild(); }
Node* traverseForwardToOffset(unsigned offset, Node& currentNode, unsigned& currentOffset, const ContainerNode& root) const;
private:
- explicit ChildNodeList(PassRefPtr<ContainerNode> rootNode);
+ explicit ChildNodeList(ContainerNode& rootNode);
virtual bool isChildNodeList() const OVERRIDE { return true; }
virtual Node* virtualOwnerNode() const OVERRIDE;
diff --git a/Source/core/dom/ClassCollection.cpp b/Source/core/dom/ClassCollection.cpp
index 59099c0..73d6a3a 100644
--- a/Source/core/dom/ClassCollection.cpp
+++ b/Source/core/dom/ClassCollection.cpp
@@ -35,7 +35,7 @@
namespace WebCore {
-ClassCollection::ClassCollection(ContainerNode* rootNode, const AtomicString& classNames)
+ClassCollection::ClassCollection(ContainerNode& rootNode, const AtomicString& classNames)
: HTMLCollection(rootNode, ClassCollectionType, DoesNotOverrideItemAfter)
, m_classNames(classNames, document().inQuirksMode())
, m_originalClassNames(classNames)
@@ -44,7 +44,7 @@
ClassCollection::~ClassCollection()
{
- ownerNode()->nodeLists()->removeCache(this, ClassCollectionType, m_originalClassNames);
+ ownerNode().nodeLists()->removeCache(this, ClassCollectionType, m_originalClassNames);
}
} // namespace WebCore
diff --git a/Source/core/dom/ClassCollection.h b/Source/core/dom/ClassCollection.h
index a906537..257cbb3 100644
--- a/Source/core/dom/ClassCollection.h
+++ b/Source/core/dom/ClassCollection.h
@@ -40,7 +40,7 @@
public:
// classNames argument is an AtomicString because it is common for Elements to share the same class names.
// It is also used to construct a SpaceSplitString (m_classNames) and its constructor requires an AtomicString.
- static PassRefPtr<ClassCollection> create(ContainerNode* rootNode, CollectionType type, const AtomicString& classNames)
+ static PassRefPtr<ClassCollection> create(ContainerNode& rootNode, CollectionType type, const AtomicString& classNames)
{
ASSERT_UNUSED(type, type == ClassCollectionType);
return adoptRef(new ClassCollection(rootNode, classNames));
@@ -51,7 +51,7 @@
bool elementMatches(const Element&) const;
private:
- ClassCollection(ContainerNode* rootNode, const AtomicString& classNames);
+ ClassCollection(ContainerNode& rootNode, const AtomicString& classNames);
SpaceSplitString m_classNames;
AtomicString m_originalClassNames;
diff --git a/Source/core/dom/ContainerNode.cpp b/Source/core/dom/ContainerNode.cpp
index d63b98e..a722ab5 100644
--- a/Source/core/dom/ContainerNode.cpp
+++ b/Source/core/dom/ContainerNode.cpp
@@ -268,7 +268,7 @@
ASSERT(newChild);
ASSERT(nextChild.parentNode() == this);
ASSERT(!newChild->isDocumentFragment());
- ASSERT(!hasTagName(templateTag));
+ ASSERT(!isHTMLTemplateElement(this));
if (nextChild.previousSibling() == newChild || nextChild == newChild) // nothing to do
return;
@@ -425,7 +425,7 @@
document().removeFocusedElementOfSubtree(child.get());
- if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(&document()))
+ if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(document()))
fullscreen->removeFullScreenElementOfSubtree(child.get());
// Events fired when blurring currently focused node might have moved this
@@ -509,7 +509,7 @@
// The container node can be removed from event handlers.
RefPtr<ContainerNode> protect(this);
- if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(&document()))
+ if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(document()))
fullscreen->removeFullScreenElementOfSubtree(this, true);
// Do any prep work needed before actually starting to detach
@@ -528,7 +528,7 @@
document().removeFocusedElementOfSubtree(this, true);
// Removing a node from a selection can cause widget updates.
- document().nodeChildrenWillBeRemoved(this);
+ document().nodeChildrenWillBeRemoved(*this);
}
@@ -537,7 +537,7 @@
RenderWidget::UpdateSuspendScope suspendWidgetHierarchyUpdates;
{
NoEventDispatchAssertion assertNoEventDispatch;
- removedChildren.reserveInitialCapacity(childNodeCount());
+ removedChildren.reserveInitialCapacity(countChildren());
while (m_firstChild) {
removedChildren.append(m_firstChild);
removeBetween(0, m_firstChild->nextSibling(), *m_firstChild);
@@ -614,7 +614,7 @@
ASSERT(newChild);
ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events).
ASSERT(!newChild->isDocumentFragment());
- ASSERT(!hasTagName(templateTag));
+ ASSERT(!isHTMLTemplateElement(this));
if (document() != newChild->document())
document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
@@ -711,7 +711,7 @@
} else if ((o->isText() && !o->isBR()) || o->isReplaced()) {
point = FloatPoint();
if (o->isText() && toRenderText(o)->firstTextBox()) {
- point.move(toRenderText(o)->linesBoundingBox().x(), toRenderText(o)->firstTextBox()->root()->lineTop());
+ point.move(toRenderText(o)->linesBoundingBox().x(), toRenderText(o)->firstTextBox()->root().lineTop().toFloat());
} else if (o->isBox()) {
RenderBox* box = toRenderBox(o);
point.moveBy(box->location());
@@ -808,10 +808,13 @@
// renderer we can just ignore the state change.
if (!renderer())
return;
- // FIXME: This could probably setNeedsStyleRecalc(LocalStyleChange) in the affectedByFocus case
- // and only setNeedsStyleRecalc(SubtreeStyleChange) in the childrenAffectedByFocus case.
- if (renderStyle()->affectedByFocus() || (isElementNode() && toElement(this)->childrenAffectedByFocus()))
+
+ if ((isElementNode() && toElement(this)->childrenAffectedByFocus())
+ || (renderStyle()->affectedByFocus() && renderStyle()->hasPseudoStyle(FIRST_LETTER)))
setNeedsStyleRecalc(SubtreeStyleChange);
+ else if (renderStyle()->affectedByFocus())
+ setNeedsStyleRecalc(LocalStyleChange);
+
if (renderer() && renderer()->style()->hasAppearance())
RenderTheme::theme().stateChanged(renderer(), FocusState);
}
@@ -824,9 +827,15 @@
Node::setFocus(received);
focusStateChanged();
+
+ if (renderer() || received)
+ return;
+
// If :focus sets display: none, we lose focus but still need to recalc our style.
- if (!renderer() && !received)
+ if (isElementNode() && toElement(this)->childrenAffectedByFocus())
setNeedsStyleRecalc(SubtreeStyleChange);
+ else
+ setNeedsStyleRecalc(LocalStyleChange);
}
void ContainerNode::setActive(bool down)
@@ -838,7 +847,8 @@
// FIXME: Why does this not need to handle the display: none transition like :hover does?
if (renderer()) {
- if (isElementNode() && toElement(this)->childrenAffectedByActive())
+ if ((isElementNode() && toElement(this)->childrenAffectedByActive())
+ || (renderStyle()->affectedByActive() && renderStyle()->hasPseudoStyle(FIRST_LETTER)))
setNeedsStyleRecalc(SubtreeStyleChange);
else if (renderStyle()->affectedByActive())
setNeedsStyleRecalc(LocalStyleChange);
@@ -866,7 +876,8 @@
return;
}
- if (isElementNode() && toElement(this)->childrenAffectedByHover())
+ if ((isElementNode() && toElement(this)->childrenAffectedByHover())
+ || (renderStyle()->affectedByHover() && renderStyle()->hasPseudoStyle(FIRST_LETTER)))
setNeedsStyleRecalc(SubtreeStyleChange);
else if (renderStyle()->affectedByHover())
setNeedsStyleRecalc(LocalStyleChange);
@@ -877,10 +888,10 @@
PassRefPtr<HTMLCollection> ContainerNode::children()
{
- return ensureRareData().ensureNodeLists().addCache<HTMLCollection>(this, NodeChildren);
+ return ensureRareData().ensureNodeLists().addCache<HTMLCollection>(*this, NodeChildren);
}
-unsigned ContainerNode::childNodeCount() const
+unsigned ContainerNode::countChildren() const
{
unsigned count = 0;
Node *n;
@@ -889,7 +900,7 @@
return count;
}
-Node *ContainerNode::childNode(unsigned index) const
+Node* ContainerNode::traverseToChildAt(unsigned index) const
{
unsigned i;
Node *n = firstChild();
@@ -902,12 +913,12 @@
{
if (selectors.isEmpty()) {
exceptionState.throwDOMException(SyntaxError, "The provided selector is empty.");
- return 0;
+ return nullptr;
}
SelectorQuery* selectorQuery = document().selectorQueryCache().add(selectors, document(), exceptionState);
if (!selectorQuery)
- return 0;
+ return nullptr;
return selectorQuery->queryFirst(*this);
}
@@ -915,12 +926,12 @@
{
if (selectors.isEmpty()) {
exceptionState.throwDOMException(SyntaxError, "The provided selector is empty.");
- return 0;
+ return nullptr;
}
SelectorQuery* selectorQuery = document().selectorQueryCache().add(selectors, document(), exceptionState);
if (!selectorQuery)
- return 0;
+ return nullptr;
return selectorQuery->queryAll(*this);
}
@@ -989,43 +1000,43 @@
PassRefPtr<HTMLCollection> ContainerNode::getElementsByTagName(const AtomicString& localName)
{
if (localName.isNull())
- return 0;
+ return nullptr;
if (document().isHTMLDocument())
- return ensureRareData().ensureNodeLists().addCache<HTMLTagCollection>(this, HTMLTagCollectionType, localName);
- return ensureRareData().ensureNodeLists().addCache<TagCollection>(this, TagCollectionType, localName);
+ return ensureRareData().ensureNodeLists().addCache<HTMLTagCollection>(*this, HTMLTagCollectionType, localName);
+ return ensureRareData().ensureNodeLists().addCache<TagCollection>(*this, TagCollectionType, localName);
}
PassRefPtr<HTMLCollection> ContainerNode::getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName)
{
if (localName.isNull())
- return 0;
+ return nullptr;
if (namespaceURI == starAtom)
return getElementsByTagName(localName);
- return ensureRareData().ensureNodeLists().addCache(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localName);
+ return ensureRareData().ensureNodeLists().addCache(*this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localName);
}
// Takes an AtomicString in argument because it is common for elements to share the same name attribute.
// Therefore, the NameNodeList factory function expects an AtomicString type.
PassRefPtr<NodeList> ContainerNode::getElementsByName(const AtomicString& elementName)
{
- return ensureRareData().ensureNodeLists().addCache<NameNodeList>(this, NameNodeListType, elementName);
+ return ensureRareData().ensureNodeLists().addCache<NameNodeList>(*this, NameNodeListType, elementName);
}
// Takes an AtomicString in argument because it is common for elements to share the same set of class names.
// Therefore, the ClassNodeList factory function expects an AtomicString type.
PassRefPtr<HTMLCollection> ContainerNode::getElementsByClassName(const AtomicString& classNames)
{
- return ensureRareData().ensureNodeLists().addCache<ClassCollection>(this, ClassCollectionType, classNames);
+ return ensureRareData().ensureNodeLists().addCache<ClassCollection>(*this, ClassCollectionType, classNames);
}
PassRefPtr<RadioNodeList> ContainerNode::radioNodeList(const AtomicString& name, bool onlyMatchImgElements)
{
- ASSERT(hasTagName(formTag) || hasTagName(fieldsetTag));
+ ASSERT(isHTMLFormElement(this) || isHTMLFieldSetElement(this));
CollectionType type = onlyMatchImgElements ? RadioImgNodeListType : RadioNodeListType;
- return ensureRareData().ensureNodeLists().addCache<RadioNodeList>(this, type, name);
+ return ensureRareData().ensureNodeLists().addCache<RadioNodeList>(*this, type, name);
}
#ifndef NDEBUG
diff --git a/Source/core/dom/ContainerNode.h b/Source/core/dom/ContainerNode.h
index b0b1ee5..9f22455 100644
--- a/Source/core/dom/ContainerNode.h
+++ b/Source/core/dom/ContainerNode.h
@@ -82,15 +82,16 @@
Node* firstChild() const { return m_firstChild; }
Node* lastChild() const { return m_lastChild; }
- bool hasChildNodes() const { return m_firstChild; }
+ bool hasChildren() const { return m_firstChild; }
bool hasOneChild() const { return m_firstChild && !m_firstChild->nextSibling(); }
bool hasOneTextChild() const { return hasOneChild() && m_firstChild->isTextNode(); }
+ bool hasChildCount(unsigned) const;
PassRefPtr<HTMLCollection> children();
- unsigned childNodeCount() const;
- Node* childNode(unsigned index) const;
+ unsigned countChildren() const;
+ Node* traverseToChildAt(unsigned index) const;
PassRefPtr<Element> querySelector(const AtomicString& selectors, ExceptionState&);
PassRefPtr<NodeList> querySelectorAll(const AtomicString& selectors, ExceptionState&);
@@ -176,6 +177,16 @@
DEFINE_NODE_TYPE_CASTS(ContainerNode, isContainerNode());
+inline bool ContainerNode::hasChildCount(unsigned count) const
+{
+ Node* child = m_firstChild;
+ while (count && child) {
+ child = child->nextSibling();
+ --count;
+ }
+ return !count && !child;
+}
+
inline ContainerNode::ContainerNode(TreeScope* treeScope, ConstructionType type)
: Node(treeScope, type)
, m_firstChild(0)
@@ -204,18 +215,18 @@
child->detach(childrenContext);
}
-inline unsigned Node::childNodeCount() const
+inline unsigned Node::countChildren() const
{
if (!isContainerNode())
return 0;
- return toContainerNode(this)->childNodeCount();
+ return toContainerNode(this)->countChildren();
}
-inline Node* Node::childNode(unsigned index) const
+inline Node* Node::traverseToChildAt(unsigned index) const
{
if (!isContainerNode())
return 0;
- return toContainerNode(this)->childNode(index);
+ return toContainerNode(this)->traverseToChildAt(index);
}
inline Node* Node::firstChild() const
@@ -232,13 +243,19 @@
return toContainerNode(this)->lastChild();
}
-inline Node* Node::highestAncestor() const
+inline Node& Node::highestAncestor() const
{
Node* node = const_cast<Node*>(this);
Node* highest = node;
for (; node; node = node->parentNode())
highest = node;
- return highest;
+ return *highest;
+}
+
+inline Node* Node::parentElementOrShadowRoot() const
+{
+ ContainerNode* parent = parentNode();
+ return parent && (parent->isElementNode() || parent->isShadowRoot()) ? parent : 0;
}
// This constant controls how much buffer is initially allocated
@@ -282,7 +299,7 @@
}
Vector<RefPtr<Node> >& nodeVector = *m_childNodes;
if (m_currentIndex >= nodeVector.size())
- return 0;
+ return nullptr;
return nodeVector[m_currentIndex++];
}
diff --git a/Source/core/dom/ContainerNodeAlgorithms.h b/Source/core/dom/ContainerNodeAlgorithms.h
index b863c25..f7cefcb 100644
--- a/Source/core/dom/ContainerNodeAlgorithms.h
+++ b/Source/core/dom/ContainerNodeAlgorithms.h
@@ -96,7 +96,7 @@
if (next == 0)
tail = 0;
- if (n->hasChildNodes())
+ if (n->hasChildren())
Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContainer>(head, tail, static_cast<GenericNodeContainer&>(*n));
delete n;
diff --git a/Source/core/dom/ContextFeatures.cpp b/Source/core/dom/ContextFeatures.cpp
index 980dde1..377c50e 100644
--- a/Source/core/dom/ContextFeatures.cpp
+++ b/Source/core/dom/ContextFeatures.cpp
@@ -54,21 +54,21 @@
{
if (!document)
return RuntimeEnabledFeatures::dialogElementEnabled();
- return document->contextFeatures()->isEnabled(document, DialogElement, RuntimeEnabledFeatures::dialogElementEnabled());
+ return document->contextFeatures().isEnabled(document, DialogElement, RuntimeEnabledFeatures::dialogElementEnabled());
}
bool ContextFeatures::styleScopedEnabled(Document* document)
{
if (!document)
return RuntimeEnabledFeatures::styleScopedEnabled();
- return document->contextFeatures()->isEnabled(document, StyleScoped, RuntimeEnabledFeatures::styleScopedEnabled());
+ return document->contextFeatures().isEnabled(document, StyleScoped, RuntimeEnabledFeatures::styleScopedEnabled());
}
bool ContextFeatures::pagePopupEnabled(Document* document)
{
if (!document)
return false;
- return document->contextFeatures()->isEnabled(document, PagePopup, false);
+ return document->contextFeatures().isEnabled(document, PagePopup, false);
}
bool ContextFeatures::mutationEventsEnabled(Document* document)
@@ -76,25 +76,25 @@
ASSERT(document);
if (!document)
return true;
- return document->contextFeatures()->isEnabled(document, MutationEvents, true);
+ return document->contextFeatures().isEnabled(document, MutationEvents, true);
}
bool ContextFeatures::pushStateEnabled(Document* document)
{
- return document->contextFeatures()->isEnabled(document, PushState, true);
+ return document->contextFeatures().isEnabled(document, PushState, true);
}
-void provideContextFeaturesTo(Page* page, ContextFeaturesClient* client)
+void provideContextFeaturesTo(Page& page, ContextFeaturesClient* client)
{
RefCountedSupplement<Page, ContextFeatures>::provideTo(page, ContextFeatures::supplementName(), ContextFeatures::create(client));
}
-void provideContextFeaturesToDocumentFrom(Document* document, Page* page)
+void provideContextFeaturesToDocumentFrom(Document& document, Page& page)
{
ContextFeatures* provided = static_cast<ContextFeatures*>(RefCountedSupplement<Page, ContextFeatures>::from(page, ContextFeatures::supplementName()));
if (!provided)
return;
- document->setContextFeatures(provided);
+ document.setContextFeatures(*provided);
}
}
diff --git a/Source/core/dom/ContextFeatures.h b/Source/core/dom/ContextFeatures.h
index 109b781..8868cc8 100644
--- a/Source/core/dom/ContextFeatures.h
+++ b/Source/core/dom/ContextFeatures.h
@@ -85,8 +85,8 @@
virtual void urlDidChange(Document*) { }
};
-void provideContextFeaturesTo(Page*, ContextFeaturesClient*);
-void provideContextFeaturesToDocumentFrom(Document*, Page*);
+void provideContextFeaturesTo(Page&, ContextFeaturesClient*);
+void provideContextFeaturesToDocumentFrom(Document&, Page&);
inline PassRefPtr<ContextFeatures> ContextFeatures::create(ContextFeaturesClient* client)
{
diff --git a/Source/core/dom/ContextLifecycleNotifier.cpp b/Source/core/dom/ContextLifecycleNotifier.cpp
index 048978c..9a585d8 100644
--- a/Source/core/dom/ContextLifecycleNotifier.cpp
+++ b/Source/core/dom/ContextLifecycleNotifier.cpp
@@ -86,6 +86,17 @@
}
}
+void ContextLifecycleNotifier::notifyWillStopActiveDOMObjects()
+{
+ TemporaryChange<IterationType> scope(this->m_iterating, IteratingOverActiveDOMObjects);
+ ActiveDOMObjectSet::iterator activeObjectsEnd = m_activeDOMObjects.end();
+ for (ActiveDOMObjectSet::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
+ ASSERT((*iter)->executionContext() == context());
+ ASSERT((*iter)->suspendIfNeededCalled());
+ (*iter)->willStop();
+ }
+}
+
void ContextLifecycleNotifier::notifyStoppingActiveDOMObjects()
{
TemporaryChange<IterationType> scope(this->m_iterating, IteratingOverActiveDOMObjects);
diff --git a/Source/core/dom/ContextLifecycleNotifier.h b/Source/core/dom/ContextLifecycleNotifier.h
index 93d8540..f5f7599 100644
--- a/Source/core/dom/ContextLifecycleNotifier.h
+++ b/Source/core/dom/ContextLifecycleNotifier.h
@@ -53,6 +53,7 @@
void notifyResumingActiveDOMObjects();
void notifySuspendingActiveDOMObjects();
+ void notifyWillStopActiveDOMObjects();
void notifyStoppingActiveDOMObjects();
bool contains(ActiveDOMObject* object) const { return m_activeDOMObjects.contains(object); }
diff --git a/Source/core/dom/DOMError.h b/Source/core/dom/DOMError.h
index a66d0e2..bd442ed 100644
--- a/Source/core/dom/DOMError.h
+++ b/Source/core/dom/DOMError.h
@@ -29,36 +29,39 @@
#include "bindings/v8/ScriptWrappable.h"
#include "core/dom/DOMException.h"
#include "core/dom/ExceptionCode.h"
+#include "heap/Handle.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefCounted.h"
#include "wtf/text/WTFString.h"
namespace WebCore {
-class DOMError : public RefCounted<DOMError>, public ScriptWrappable {
+class DOMError : public RefCountedWillBeGarbageCollectedFinalized<DOMError>, public ScriptWrappable {
public:
- static PassRefPtr<DOMError> create(const String& name)
+ static PassRefPtrWillBeRawPtr<DOMError> create(const String& name)
{
- return adoptRef(new DOMError(name));
+ return adoptRefWillBeNoop(new DOMError(name));
}
- static PassRefPtr<DOMError> create(const String& name, const String& message)
+ static PassRefPtrWillBeRawPtr<DOMError> create(const String& name, const String& message)
{
- return adoptRef(new DOMError(name, message));
+ return adoptRefWillBeNoop(new DOMError(name, message));
}
- static PassRefPtr<DOMError> create(ExceptionCode ec)
+ static PassRefPtrWillBeRawPtr<DOMError> create(ExceptionCode ec)
{
- return adoptRef(new DOMError(DOMException::getErrorName(ec), DOMException::getErrorMessage(ec)));
+ return adoptRefWillBeNoop(new DOMError(DOMException::getErrorName(ec), DOMException::getErrorMessage(ec)));
}
- static PassRefPtr<DOMError> create(ExceptionCode ec, const String& message)
+ static PassRefPtrWillBeRawPtr<DOMError> create(ExceptionCode ec, const String& message)
{
- return adoptRef(new DOMError(DOMException::getErrorName(ec), message));
+ return adoptRefWillBeNoop(new DOMError(DOMException::getErrorName(ec), message));
}
const String& name() const { return m_name; }
const String& message() const { return m_message; }
+ void trace(Visitor*) { }
+
protected:
explicit DOMError(const String& name);
DOMError(const String& name, const String& message);
diff --git a/Source/core/dom/DOMError.idl b/Source/core/dom/DOMError.idl
index b2ea60f..8e8d494 100644
--- a/Source/core/dom/DOMError.idl
+++ b/Source/core/dom/DOMError.idl
@@ -26,6 +26,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
[
+ WillBeGarbageCollected,
NoInterfaceObject
] interface DOMError {
readonly attribute DOMString name;
diff --git a/Source/core/dom/DOMImplementation.cpp b/Source/core/dom/DOMImplementation.cpp
index 661d4f5..0bf96bf 100644
--- a/Source/core/dom/DOMImplementation.cpp
+++ b/Source/core/dom/DOMImplementation.cpp
@@ -38,6 +38,8 @@
#include "core/dom/ExceptionCode.h"
#include "core/dom/XMLDocument.h"
#include "core/dom/custom/CustomElementRegistrationContext.h"
+#include "core/frame/LocalFrame.h"
+#include "core/frame/UseCounter.h"
#include "core/html/HTMLDocument.h"
#include "core/html/HTMLMediaElement.h"
#include "core/html/HTMLViewSourceDocument.h"
@@ -46,8 +48,6 @@
#include "core/html/PluginDocument.h"
#include "core/html/TextDocument.h"
#include "core/loader/FrameLoader.h"
-#include "core/frame/Frame.h"
-#include "core/frame/UseCounter.h"
#include "core/page/Page.h"
#include "core/svg/SVGDocument.h"
#include "platform/ContentType.h"
@@ -193,7 +193,7 @@
{
AtomicString prefix, localName;
if (!Document::parseQualifiedName(qualifiedName, prefix, localName, exceptionState))
- return 0;
+ return nullptr;
return DocumentType::create(&m_document, qualifiedName, publicId, systemId);
}
@@ -225,7 +225,7 @@
if (!qualifiedName.isEmpty()) {
documentElement = doc->createElementNS(namespaceURI, qualifiedName, exceptionState);
if (exceptionState.hadException())
- return 0;
+ return nullptr;
}
if (doctype)
@@ -349,7 +349,7 @@
return d.release();
}
-PassRefPtr<Document> DOMImplementation::createDocument(const String& type, Frame* frame, const KURL& url, bool inViewSourceMode)
+PassRefPtr<Document> DOMImplementation::createDocument(const String& type, LocalFrame* frame, const KURL& url, bool inViewSourceMode)
{
return createDocument(type, DocumentInit(url, frame), inViewSourceMode);
}
diff --git a/Source/core/dom/DOMImplementation.h b/Source/core/dom/DOMImplementation.h
index 7a93cc0..429aa8b 100644
--- a/Source/core/dom/DOMImplementation.h
+++ b/Source/core/dom/DOMImplementation.h
@@ -35,7 +35,7 @@
class DocumentInit;
class DocumentType;
class ExceptionState;
-class Frame;
+class LocalFrame;
class HTMLDocument;
class KURL;
class XMLDocument;
@@ -47,7 +47,7 @@
void ref() { m_document.ref(); }
void deref() { m_document.deref(); }
- Document* document() { return &m_document; }
+ Document& document() const { return m_document; }
// DOM methods & attributes for DOMImplementation
static bool hasFeature(const String& feature, const String& version);
@@ -64,7 +64,7 @@
PassRefPtr<HTMLDocument> createHTMLDocument(const String& title);
// Other methods (not part of DOM)
- static PassRefPtr<Document> createDocument(const String& mimeType, Frame*, const KURL&, bool inViewSourceMode);
+ static PassRefPtr<Document> createDocument(const String& mimeType, LocalFrame*, const KURL&, bool inViewSourceMode);
static PassRefPtr<Document> createDocument(const String& mimeType, const DocumentInit&, bool inViewSourceMode);
static bool isXMLMIMEType(const String&);
diff --git a/Source/core/dom/DOMStringList.idl b/Source/core/dom/DOMStringList.idl
index 1c75bcb..06e7f3e 100644
--- a/Source/core/dom/DOMStringList.idl
+++ b/Source/core/dom/DOMStringList.idl
@@ -27,6 +27,5 @@
] interface DOMStringList {
readonly attribute unsigned long length;
[TreatReturnedNullStringAs=Null] getter DOMString item([Default=Undefined] optional unsigned long index);
- boolean contains([Default=Undefined] optional DOMString string);
+ [MeasureAs=DOMStringListContains] boolean contains([Default=Undefined] optional DOMString string);
};
-
diff --git a/Source/core/dom/DOMURL.cpp b/Source/core/dom/DOMURL.cpp
index 8881223..feba9b9 100644
--- a/Source/core/dom/DOMURL.cpp
+++ b/Source/core/dom/DOMURL.cpp
@@ -63,20 +63,24 @@
}
}
-String DOMURL::createObjectURL(ExecutionContext* executionContext, Blob* blob)
+String DOMURL::createObjectURL(ExecutionContext* executionContext, Blob* blob, ExceptionState& exceptionState)
{
if (!executionContext || !blob)
return String();
- return createPublicURL(executionContext, blob);
+ if (blob->hasBeenClosed()) {
+ exceptionState.throwDOMException(InvalidStateError, String(blob->isFile() ? "File" : "Blob") + " has been closed.");
+ return String();
+ }
+ return createPublicURL(executionContext, blob, blob->uuid());
}
-String DOMURL::createPublicURL(ExecutionContext* executionContext, URLRegistrable* registrable)
+String DOMURL::createPublicURL(ExecutionContext* executionContext, URLRegistrable* registrable, const String& uuid)
{
KURL publicURL = BlobURL::createPublicURL(executionContext->securityOrigin());
if (publicURL.isEmpty())
return String();
- executionContext->publicURLManager().registerURL(executionContext->securityOrigin(), publicURL, registrable);
+ executionContext->publicURLManager().registerURL(executionContext->securityOrigin(), publicURL, registrable, uuid);
return publicURL.string();
}
@@ -91,4 +95,12 @@
executionContext->publicURLManager().revoke(url);
}
+void DOMURL::revokeObjectUUID(ExecutionContext* executionContext, const String& uuid)
+{
+ if (!executionContext)
+ return;
+
+ executionContext->publicURLManager().revoke(uuid);
+}
+
} // namespace WebCore
diff --git a/Source/core/dom/DOMURL.h b/Source/core/dom/DOMURL.h
index 2b112f7..60a4af2 100644
--- a/Source/core/dom/DOMURL.h
+++ b/Source/core/dom/DOMURL.h
@@ -29,6 +29,7 @@
#include "bindings/v8/ScriptWrappable.h"
#include "core/dom/DOMURLUtils.h"
+#include "heap/Handle.h"
#include "platform/weborigin/KURL.h"
#include "wtf/Forward.h"
#include "wtf/PassRefPtr.h"
@@ -42,27 +43,27 @@
class ExecutionContext;
class URLRegistrable;
-class DOMURL FINAL : public ScriptWrappable, public DOMURLUtils, public RefCounted<DOMURL> {
-
+class DOMURL FINAL : public RefCountedWillBeGarbageCollectedFinalized<DOMURL>, public ScriptWrappable, public DOMURLUtils {
public:
- static PassRefPtr<DOMURL> create(const String& url, ExceptionState& exceptionState)
+ static PassRefPtrWillBeRawPtr<DOMURL> create(const String& url, ExceptionState& exceptionState)
{
- return adoptRef(new DOMURL(url, blankURL(), exceptionState));
+ return adoptRefWillBeNoop(new DOMURL(url, blankURL(), exceptionState));
}
- static PassRefPtr<DOMURL> create(const String& url, const String& base, ExceptionState& exceptionState)
+ static PassRefPtrWillBeRawPtr<DOMURL> create(const String& url, const String& base, ExceptionState& exceptionState)
{
- return adoptRef(new DOMURL(url, KURL(KURL(), base), exceptionState));
+ return adoptRefWillBeNoop(new DOMURL(url, KURL(KURL(), base), exceptionState));
}
- static PassRefPtr<DOMURL> create(const String& url, PassRefPtr<DOMURL> base, ExceptionState& exceptionState)
+ static PassRefPtrWillBeRawPtr<DOMURL> create(const String& url, PassRefPtrWillBeRawPtr<DOMURL> base, ExceptionState& exceptionState)
{
ASSERT(base);
- return adoptRef(new DOMURL(url, base->m_url, exceptionState));
+ return adoptRefWillBeNoop(new DOMURL(url, base->m_url, exceptionState));
}
- static String createObjectURL(ExecutionContext*, Blob*);
+ static String createObjectURL(ExecutionContext*, Blob*, ExceptionState&);
static void revokeObjectURL(ExecutionContext*, const String&);
- static String createPublicURL(ExecutionContext*, URLRegistrable*);
+ static String createPublicURL(ExecutionContext*, URLRegistrable*, const String& uuid = String());
+ static void revokeObjectUUID(ExecutionContext*, const String&);
virtual KURL url() const OVERRIDE { return m_url; }
virtual void setURL(const KURL& url) OVERRIDE { m_url = url; }
@@ -70,6 +71,8 @@
virtual String input() const OVERRIDE { return m_input; }
virtual void setInput(const String&) OVERRIDE;
+ void trace(Visitor*) { }
+
private:
DOMURL(const String& url, const KURL& base, ExceptionState&);
diff --git a/Source/core/dom/DOMURLUtils.cpp b/Source/core/dom/DOMURLUtils.cpp
index 7e1fa19..0ac6d79 100644
--- a/Source/core/dom/DOMURLUtils.cpp
+++ b/Source/core/dom/DOMURLUtils.cpp
@@ -31,54 +31,54 @@
namespace WebCore {
-void DOMURLUtils::setHref(DOMURLUtils* impl, const String& value)
+void DOMURLUtils::setHref(DOMURLUtils& impl, const String& value)
{
- impl->setInput(value);
+ impl.setInput(value);
}
-void DOMURLUtils::setProtocol(DOMURLUtils* impl, const String& value)
+void DOMURLUtils::setProtocol(DOMURLUtils& impl, const String& value)
{
- KURL url = impl->url();
+ KURL url = impl.url();
if (url.isNull())
return;
url.setProtocol(value);
- impl->setURL(url);
+ impl.setURL(url);
}
-void DOMURLUtils::setUsername(DOMURLUtils* impl, const String& value)
+void DOMURLUtils::setUsername(DOMURLUtils& impl, const String& value)
{
- KURL url = impl->url();
+ KURL url = impl.url();
if (url.isNull())
return;
url.setUser(value);
- impl->setURL(url);
+ impl.setURL(url);
}
-void DOMURLUtils::setPassword(DOMURLUtils* impl, const String& value)
+void DOMURLUtils::setPassword(DOMURLUtils& impl, const String& value)
{
- KURL url = impl->url();
+ KURL url = impl.url();
if (url.isNull())
return;
url.setPass(value);
- impl->setURL(url);
+ impl.setURL(url);
}
-void DOMURLUtils::setHost(DOMURLUtils* impl, const String& value)
+void DOMURLUtils::setHost(DOMURLUtils& impl, const String& value)
{
if (value.isEmpty())
return;
- KURL url = impl->url();
+ KURL url = impl.url();
if (!url.canSetHostOrPort())
return;
url.setHostAndPort(value);
- impl->setURL(url);
+ impl.setURL(url);
}
-void DOMURLUtils::setHostname(DOMURLUtils* impl, const String& value)
+void DOMURLUtils::setHostname(DOMURLUtils& impl, const String& value)
{
- KURL url = impl->url();
+ KURL url = impl.url();
if (!url.canSetHostOrPort())
return;
@@ -94,40 +94,40 @@
url.setHost(value.substring(i));
- impl->setURL(url);
+ impl.setURL(url);
}
-void DOMURLUtils::setPort(DOMURLUtils* impl, const String& value)
+void DOMURLUtils::setPort(DOMURLUtils& impl, const String& value)
{
- KURL url = impl->url();
+ KURL url = impl.url();
if (!url.canSetHostOrPort())
return;
url.setPort(value);
- impl->setURL(url);
+ impl.setURL(url);
}
-void DOMURLUtils::setPathname(DOMURLUtils* impl, const String& value)
+void DOMURLUtils::setPathname(DOMURLUtils& impl, const String& value)
{
- KURL url = impl->url();
+ KURL url = impl.url();
if (!url.canSetPathname())
return;
url.setPath(value);
- impl->setURL(url);
+ impl.setURL(url);
}
-void DOMURLUtils::setSearch(DOMURLUtils* impl, const String& value)
+void DOMURLUtils::setSearch(DOMURLUtils& impl, const String& value)
{
- KURL url = impl->url();
+ KURL url = impl.url();
if (!url.isValid())
return;
url.setQuery(value);
- impl->setURL(url);
+ impl.setURL(url);
}
-void DOMURLUtils::setHash(DOMURLUtils* impl, const String& value)
+void DOMURLUtils::setHash(DOMURLUtils& impl, const String& value)
{
- KURL url = impl->url();
+ KURL url = impl.url();
if (url.isNull())
return;
@@ -136,7 +136,7 @@
else
url.setFragmentIdentifier(value);
- impl->setURL(url);
+ impl.setURL(url);
}
} // namespace WebCore
diff --git a/Source/core/dom/DOMURLUtils.h b/Source/core/dom/DOMURLUtils.h
index 1987ecd..e871ebf 100644
--- a/Source/core/dom/DOMURLUtils.h
+++ b/Source/core/dom/DOMURLUtils.h
@@ -41,17 +41,17 @@
virtual void setInput(const String&) = 0;
virtual ~DOMURLUtils() { };
- static void setHref(DOMURLUtils*, const String&);
+ static void setHref(DOMURLUtils&, const String&);
- static void setProtocol(DOMURLUtils*, const String&);
- static void setUsername(DOMURLUtils*, const String&);
- static void setPassword(DOMURLUtils*, const String&);
- static void setHost(DOMURLUtils*, const String&);
- static void setHostname(DOMURLUtils*, const String&);
- static void setPort(DOMURLUtils*, const String&);
- static void setPathname(DOMURLUtils*, const String&);
- static void setSearch(DOMURLUtils*, const String&);
- static void setHash(DOMURLUtils*, const String&);
+ static void setProtocol(DOMURLUtils&, const String&);
+ static void setUsername(DOMURLUtils&, const String&);
+ static void setPassword(DOMURLUtils&, const String&);
+ static void setHost(DOMURLUtils&, const String&);
+ static void setHostname(DOMURLUtils&, const String&);
+ static void setPort(DOMURLUtils&, const String&);
+ static void setPathname(DOMURLUtils&, const String&);
+ static void setSearch(DOMURLUtils&, const String&);
+ static void setHash(DOMURLUtils&, const String&);
};
} // namespace WebCore
diff --git a/Source/core/dom/DOMURLUtilsReadOnly.cpp b/Source/core/dom/DOMURLUtilsReadOnly.cpp
index 15b1268..61dc0ad 100644
--- a/Source/core/dom/DOMURLUtilsReadOnly.cpp
+++ b/Source/core/dom/DOMURLUtilsReadOnly.cpp
@@ -32,11 +32,11 @@
namespace WebCore {
-String DOMURLUtilsReadOnly::href(DOMURLUtilsReadOnly* impl)
+String DOMURLUtilsReadOnly::href(DOMURLUtilsReadOnly& impl)
{
- const KURL& url = impl->url();
+ const KURL& url = impl.url();
if (url.isNull())
- return impl->input();
+ return impl.input();
return url.string();
}
diff --git a/Source/core/dom/DOMURLUtilsReadOnly.h b/Source/core/dom/DOMURLUtilsReadOnly.h
index 36d6085..7f49e8c 100644
--- a/Source/core/dom/DOMURLUtilsReadOnly.h
+++ b/Source/core/dom/DOMURLUtilsReadOnly.h
@@ -39,37 +39,37 @@
virtual String input() const = 0;
virtual ~DOMURLUtilsReadOnly() { };
- static String href(DOMURLUtilsReadOnly*);
+ static String href(DOMURLUtilsReadOnly&);
static String origin(const KURL&);
- static String origin(DOMURLUtilsReadOnly* impl) { return origin(impl->url()); }
+ static String origin(DOMURLUtilsReadOnly& impl) { return origin(impl.url()); }
static String protocol(const KURL& url) { return url.protocol() + ":"; }
- static String protocol(DOMURLUtilsReadOnly* impl) { return protocol(impl->url()); }
+ static String protocol(DOMURLUtilsReadOnly& impl) { return protocol(impl.url()); }
static String username(const KURL& url) { return url.user(); }
- static String username(DOMURLUtilsReadOnly* impl) { return username(impl->url()); }
+ static String username(DOMURLUtilsReadOnly& impl) { return username(impl.url()); }
static String password(const KURL& url) { return url.pass(); }
- static String password(DOMURLUtilsReadOnly* impl) { return password(impl->url()); }
+ static String password(DOMURLUtilsReadOnly& impl) { return password(impl.url()); }
static String host(const KURL&);
- static String host(DOMURLUtilsReadOnly* impl) { return host(impl->url()); }
+ static String host(DOMURLUtilsReadOnly& impl) { return host(impl.url()); }
static String hostname(const KURL& url) { return url.host(); }
- static String hostname(DOMURLUtilsReadOnly* impl) { return hostname(impl->url()); }
+ static String hostname(DOMURLUtilsReadOnly& impl) { return hostname(impl.url()); }
static String port(const KURL&);
- static String port(DOMURLUtilsReadOnly* impl) { return port(impl->url()); }
+ static String port(DOMURLUtilsReadOnly& impl) { return port(impl.url()); }
static String pathname(const KURL& url) { return url.path(); }
- static String pathname(DOMURLUtilsReadOnly* impl) { return pathname(impl->url()); }
+ static String pathname(DOMURLUtilsReadOnly& impl) { return pathname(impl.url()); }
static String search(const KURL&);
- static String search(DOMURLUtilsReadOnly* impl) { return search(impl->url()); }
+ static String search(DOMURLUtilsReadOnly& impl) { return search(impl.url()); }
static String hash(const KURL&);
- static String hash(DOMURLUtilsReadOnly* impl) { return hash(impl->url()); }
+ static String hash(DOMURLUtilsReadOnly& impl) { return hash(impl.url()); }
};
} // namespace WebCore
diff --git a/Source/core/dom/DatasetDOMStringMap.cpp b/Source/core/dom/DatasetDOMStringMap.cpp
index 14c082d..8690449 100644
--- a/Source/core/dom/DatasetDOMStringMap.cpp
+++ b/Source/core/dom/DatasetDOMStringMap.cpp
@@ -26,7 +26,6 @@
#include "config.h"
#include "core/dom/DatasetDOMStringMap.h"
-#include "bindings/v8/ExceptionMessages.h"
#include "bindings/v8/ExceptionState.h"
#include "core/dom/Attribute.h"
#include "core/dom/Element.h"
@@ -71,14 +70,9 @@
return stringBuilder.toString();
}
-static bool propertyNameMatchesAttributeName(const String& propertyName, const String& attributeName)
+template<typename CharType1, typename CharType2>
+static bool propertyNameMatchesAttributeName(const CharType1* propertyName, const CharType2* attributeName, unsigned propertyLength, unsigned attributeLength)
{
- if (!attributeName.startsWith("data-"))
- return false;
-
- unsigned propertyLength = propertyName.length();
- unsigned attributeLength = attributeName.length();
-
unsigned a = 5;
unsigned p = 0;
bool wordBoundary = false;
@@ -97,6 +91,25 @@
return (a == attributeLength && p == propertyLength);
}
+static bool propertyNameMatchesAttributeName(const String& propertyName, const String& attributeName)
+{
+ if (!attributeName.startsWith("data-"))
+ return false;
+
+ unsigned propertyLength = propertyName.length();
+ unsigned attributeLength = attributeName.length();
+
+ if (propertyName.is8Bit()) {
+ if (attributeName.is8Bit())
+ return propertyNameMatchesAttributeName(propertyName.characters8(), attributeName.characters8(), propertyLength, attributeLength);
+ return propertyNameMatchesAttributeName(propertyName.characters8(), attributeName.characters16(), propertyLength, attributeLength);
+ }
+
+ if (attributeName.is8Bit())
+ return propertyNameMatchesAttributeName(propertyName.characters16(), attributeName.characters8(), propertyLength, attributeLength);
+ return propertyNameMatchesAttributeName(propertyName.characters16(), attributeName.characters16(), propertyLength, attributeLength);
+}
+
static bool isValidPropertyName(const String& name)
{
unsigned length = name.length();
@@ -144,9 +157,9 @@
unsigned length = m_element->attributeCount();
for (unsigned i = 0; i < length; i++) {
- const Attribute* attribute = m_element->attributeItem(i);
- if (isValidAttributeName(attribute->localName()))
- names.append(convertAttributeNameToPropertyName(attribute->localName()));
+ const Attribute& attribute = m_element->attributeItem(i);
+ if (isValidAttributeName(attribute.localName()))
+ names.append(convertAttributeNameToPropertyName(attribute.localName()));
}
}
@@ -157,9 +170,9 @@
unsigned length = m_element->attributeCount();
for (unsigned i = 0; i < length; i++) {
- const Attribute* attribute = m_element->attributeItem(i);
- if (propertyNameMatchesAttributeName(name, attribute->localName()))
- return attribute->value();
+ const Attribute& attribute = m_element->attributeItem(i);
+ if (propertyNameMatchesAttributeName(name, attribute.localName()))
+ return attribute.value();
}
return String();
@@ -172,8 +185,8 @@
unsigned length = m_element->attributeCount();
for (unsigned i = 0; i < length; i++) {
- const Attribute* attribute = m_element->attributeItem(i);
- if (propertyNameMatchesAttributeName(name, attribute->localName()))
+ const Attribute& attribute = m_element->attributeItem(i);
+ if (propertyNameMatchesAttributeName(name, attribute.localName()))
return true;
}
@@ -183,7 +196,7 @@
void DatasetDOMStringMap::setItem(const String& name, const String& value, ExceptionState& exceptionState)
{
if (!isValidPropertyName(name)) {
- exceptionState.throwDOMException(SyntaxError, ExceptionMessages::failedToSet(name, "DOMStringMap", "'" + name + "' is not a valid property name."));
+ exceptionState.throwDOMException(SyntaxError, "'" + name + "' is not a valid property name.");
return;
}
diff --git a/Source/core/dom/Document.cpp b/Source/core/dom/Document.cpp
index 13a6cc2..db5f3b0 100644
--- a/Source/core/dom/Document.cpp
+++ b/Source/core/dom/Document.cpp
@@ -109,16 +109,17 @@
#include "core/events/ScopedEventQueue.h"
#include "core/events/ThreadLocalEventNames.h"
#include "core/fetch/ResourceFetcher.h"
-#include "core/frame/ContentSecurityPolicy.h"
#include "core/frame/DOMWindow.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
#include "core/frame/History.h"
+#include "core/frame/LocalFrame.h"
#include "core/frame/PageConsole.h"
#include "core/frame/Settings.h"
+#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/HTMLAllCollection.h"
#include "core/html/HTMLAnchorElement.h"
+#include "core/html/HTMLBaseElement.h"
#include "core/html/HTMLCanvasElement.h"
#include "core/html/HTMLCollection.h"
#include "core/html/HTMLDialogElement.h"
@@ -126,16 +127,20 @@
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/HTMLHeadElement.h"
#include "core/html/HTMLIFrameElement.h"
-#include "core/html/HTMLImport.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLLinkElement.h"
#include "core/html/HTMLMetaElement.h"
#include "core/html/HTMLNameCollection.h"
#include "core/html/HTMLScriptElement.h"
#include "core/html/HTMLStyleElement.h"
+#include "core/html/HTMLTemplateElement.h"
#include "core/html/HTMLTitleElement.h"
#include "core/html/PluginDocument.h"
+#include "core/html/canvas/CanvasRenderingContext.h"
+#include "core/html/canvas/CanvasRenderingContext2D.h"
+#include "core/html/canvas/WebGLRenderingContext.h"
#include "core/html/forms/FormController.h"
+#include "core/html/imports/HTMLImport.h"
#include "core/html/parser/HTMLDocumentParser.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/html/parser/NestingLevelIncrementer.h"
@@ -173,6 +178,7 @@
#include "platform/DateComponents.h"
#include "platform/Language.h"
#include "platform/TraceEvent.h"
+#include "platform/network/ContentSecurityPolicyParsers.h"
#include "platform/network/HTTPParsers.h"
#include "platform/scroll/ScrollbarTheme.h"
#include "platform/text/PlatformLocale.h"
@@ -304,7 +310,7 @@
return element.document().frame() && element.rootEditableElement();
}
-static bool canAccessAncestor(const SecurityOrigin& activeSecurityOrigin, Frame* targetFrame)
+static bool canAccessAncestor(const SecurityOrigin& activeSecurityOrigin, LocalFrame* targetFrame)
{
// targetFrame can be 0 when we're trying to navigate a top-level frame
// that has a 0 opener.
@@ -312,7 +318,7 @@
return false;
const bool isLocalActiveOrigin = activeSecurityOrigin.isLocal();
- for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree().parent()) {
+ for (LocalFrame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree().parent()) {
Document* ancestorDocument = ancestorFrame->document();
// FIXME: Should be an ASSERT? Frames should alway have documents.
if (!ancestorDocument)
@@ -332,7 +338,7 @@
return false;
}
-static void printNavigationErrorMessage(const Frame& frame, const KURL& activeURL, const char* reason)
+static void printNavigationErrorMessage(const LocalFrame& frame, const KURL& activeURL, const char* reason)
{
String message = "Unsafe JavaScript attempt to initiate navigation for frame with URL '" + frame.document()->url().string() + "' from frame with URL '" + activeURL.string() + "'. " + reason + "\n";
@@ -422,6 +428,7 @@
, m_visuallyOrdered(false)
, m_readyState(Complete)
, m_isParsing(false)
+ , m_historyItemDocumentStateDirty(false)
, m_gotoAnchorNeededAfterStylesheetsLoad(false)
, m_containsValidityStyleRules(false)
, m_updateFocusAppearanceRestoresSelection(false)
@@ -477,7 +484,8 @@
ScriptWrappable::init(this);
if (m_frame) {
- provideContextFeaturesToDocumentFrom(this, m_frame->page());
+ ASSERT(m_frame->page());
+ provideContextFeaturesToDocumentFrom(*this, *m_frame->page());
m_fetcher = m_frame->loader().documentLoader()->fetcher();
}
@@ -545,15 +553,12 @@
m_import = 0;
}
- if (m_timeline) {
- m_timeline->detachFromDocument();
- }
+ m_timeline->detachFromDocument();
+ m_transitionTimeline->detachFromDocument();
- if (m_transitionTimeline) {
- m_transitionTimeline->detachFromDocument();
- }
-
- m_styleEngine.clear(); // We need to destory CSSFontSelector before destroying m_fetcher.
+ // We need to destroy CSSFontSelector before destroying m_fetcher.
+ if (m_styleEngine)
+ m_styleEngine->detachFromDocument();
if (m_elemSheet)
m_elemSheet->clearOwnerNode();
@@ -584,12 +589,12 @@
ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);
// We must make sure not to be retaining any of our children through
// these extra pointers or we will create a reference cycle.
- m_docType = 0;
- m_focusedElement = 0;
- m_hoverNode = 0;
- m_activeHoverElement = 0;
- m_titleElement = 0;
- m_documentElement = 0;
+ m_docType = nullptr;
+ m_focusedElement = nullptr;
+ m_hoverNode = nullptr;
+ m_activeHoverElement = nullptr;
+ m_titleElement = nullptr;
+ m_documentElement = nullptr;
m_contextFeatures = ContextFeatures::defaultSwitch();
m_userActionElements.documentDidRemoveLastRef();
m_associatedFormControls.clear();
@@ -620,7 +625,7 @@
m_scriptedAnimationController.clear();
if (svgExtensions())
- accessSVGExtensions()->pauseAnimations();
+ accessSVGExtensions().pauseAnimations();
m_lifecycle.advanceTo(DocumentLifecycle::Disposed);
lifecycleNotifier().notifyDocumentWasDisposed();
@@ -677,16 +682,16 @@
clearStyleResolver();
}
-DOMImplementation* Document::implementation()
+DOMImplementation& Document::implementation()
{
if (!m_implementation)
m_implementation = DOMImplementation::create(*this);
- return m_implementation.get();
+ return *m_implementation;
}
bool Document::hasManifest() const
{
- return documentElement() && documentElement()->hasTagName(htmlTag) && documentElement()->hasAttribute(manifestAttr);
+ return isHTMLHtmlElement(documentElement()) && documentElement()->hasAttribute(manifestAttr);
}
Location* Document::location() const
@@ -694,7 +699,7 @@
if (!frame())
return 0;
- return domWindow()->location();
+ return &domWindow()->location();
}
void Document::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
@@ -713,7 +718,7 @@
{
if (!isValidName(name)) {
exceptionState.throwDOMException(InvalidCharacterError, "The tag name provided ('" + name + "') is not a valid name.");
- return 0;
+ return nullptr;
}
if (isXHTMLDocument() || isHTMLDocument())
@@ -726,7 +731,7 @@
{
if (!isValidName(localName)) {
exceptionState.throwDOMException(InvalidCharacterError, "The tag name provided ('" + localName + "') is not a valid name.");
- return 0;
+ return nullptr;
}
RefPtr<Element> element;
@@ -736,7 +741,7 @@
} else {
element = createElement(localName, exceptionState);
if (exceptionState.hadException())
- return 0;
+ return nullptr;
}
if (!typeExtension.isEmpty())
@@ -764,7 +769,7 @@
{
QualifiedName qName(createQualifiedName(namespaceURI, qualifiedName, exceptionState));
if (qName == nullQName())
- return 0;
+ return nullptr;
return createElement(qName, false);
}
@@ -773,7 +778,7 @@
{
QualifiedName qName(createQualifiedName(namespaceURI, qualifiedName, exceptionState));
if (qName == nullQName())
- return 0;
+ return nullptr;
RefPtr<Element> element;
if (CustomElement::isValidName(qName.localName()) && registrationContext())
@@ -829,7 +834,7 @@
return 0;
}
-Frame* Document::executingFrame()
+LocalFrame* Document::executingFrame()
{
DOMWindow* window = executingWindow();
if (!window)
@@ -856,11 +861,11 @@
{
if (isHTMLDocument()) {
exceptionState.throwDOMException(NotSupportedError, "This operation is not supported for HTML documents.");
- return 0;
+ return nullptr;
}
if (data.contains("]]>")) {
exceptionState.throwDOMException(InvalidCharacterError, "String cannot contain ']]>' since that is the end delimiter of a CData section.");
- return 0;
+ return nullptr;
}
return CDATASection::create(*this, data);
}
@@ -869,11 +874,11 @@
{
if (!isValidName(target)) {
exceptionState.throwDOMException(InvalidCharacterError, "The target provided ('" + target + "') is not a valid name.");
- return 0;
+ return nullptr;
}
if (data.contains("?>")) {
exceptionState.throwDOMException(InvalidCharacterError, "The data provided ('" + data + "') contains '?>'.");
- return 0;
+ return nullptr;
}
return ProcessingInstruction::create(*this, target, data);
}
@@ -883,11 +888,25 @@
return Text::createEditingText(*this, text);
}
+bool Document::importContainerNodeChildren(ContainerNode* oldContainerNode, PassRefPtr<ContainerNode> newContainerNode, ExceptionState& exceptionState)
+{
+ for (Node* oldChild = oldContainerNode->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
+ RefPtr<Node> newChild = importNode(oldChild, true, exceptionState);
+ if (exceptionState.hadException())
+ return false;
+ newContainerNode->appendChild(newChild.release(), exceptionState);
+ if (exceptionState.hadException())
+ return false;
+ }
+
+ return true;
+}
+
PassRefPtr<Node> Document::importNode(Node* importedNode, bool deep, ExceptionState& exceptionState)
{
if (!importedNode) {
- exceptionState.throwDOMException(NotSupportedError, "The node provided is invalid.");
- return 0;
+ exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node"));
+ return nullptr;
}
switch (importedNode->nodeType()) {
@@ -909,21 +928,18 @@
// oldElement has mismatched prefix/namespace?
if (!hasValidNamespaceForElements(oldElement->tagQName())) {
exceptionState.throwDOMException(NamespaceError, "The imported node has an invalid namespace.");
- return 0;
+ return nullptr;
}
RefPtr<Element> newElement = createElement(oldElement->tagQName(), false);
newElement->cloneDataFromElement(*oldElement);
if (deep) {
- for (Node* oldChild = oldElement->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
- RefPtr<Node> newChild = importNode(oldChild, true, exceptionState);
- if (exceptionState.hadException())
- return 0;
- newElement->appendChild(newChild.release(), exceptionState);
- if (exceptionState.hadException())
- return 0;
- }
+ if (!importContainerNodeChildren(oldElement, newElement, exceptionState))
+ return nullptr;
+ if (isHTMLTemplateElement(*oldElement)
+ && !importContainerNodeChildren(toHTMLTemplateElement(oldElement)->content(), toHTMLTemplateElement(newElement)->content(), exceptionState))
+ return nullptr;
}
return newElement.release();
@@ -935,37 +951,29 @@
// ShadowRoot nodes should not be explicitly importable.
// Either they are imported along with their host node, or created implicitly.
exceptionState.throwDOMException(NotSupportedError, "The node provided is a shadow root, which may not be imported.");
- return 0;
+ return nullptr;
}
DocumentFragment* oldFragment = toDocumentFragment(importedNode);
RefPtr<DocumentFragment> newFragment = createDocumentFragment();
- if (deep) {
- for (Node* oldChild = oldFragment->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
- RefPtr<Node> newChild = importNode(oldChild, true, exceptionState);
- if (exceptionState.hadException())
- return 0;
- newFragment->appendChild(newChild.release(), exceptionState);
- if (exceptionState.hadException())
- return 0;
- }
- }
+ if (deep && !importContainerNodeChildren(oldFragment, newFragment, exceptionState))
+ return nullptr;
return newFragment.release();
}
case DOCUMENT_NODE:
exceptionState.throwDOMException(NotSupportedError, "The node provided is a document, which may not be imported.");
- return 0;
+ return nullptr;
}
ASSERT_NOT_REACHED();
- return 0;
+ return nullptr;
}
PassRefPtr<Node> Document::adoptNode(PassRefPtr<Node> source, ExceptionState& exceptionState)
{
if (!source) {
- exceptionState.throwDOMException(NotSupportedError, "The node provided is invalid.");
- return 0;
+ exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node"));
+ return nullptr;
}
EventQueueScope scope;
@@ -974,7 +982,7 @@
case DOCUMENT_NODE:
case DOCUMENT_TYPE_NODE:
exceptionState.throwDOMException(NotSupportedError, "The node provided is of type '" + source->nodeName() + "', which may not be adopted.");
- return 0;
+ return nullptr;
case ATTRIBUTE_NODE: {
Attr* attr = toAttr(source.get());
if (attr->ownerElement())
@@ -985,20 +993,20 @@
if (source->isShadowRoot()) {
// ShadowRoot cannot disconnect itself from the host node.
exceptionState.throwDOMException(HierarchyRequestError, "The node provided is a shadow root, which may not be adopted.");
- return 0;
+ return nullptr;
}
if (source->isFrameOwnerElement()) {
HTMLFrameOwnerElement* frameOwnerElement = toHTMLFrameOwnerElement(source.get());
if (frame() && frame()->tree().isDescendantOf(frameOwnerElement->contentFrame())) {
exceptionState.throwDOMException(HierarchyRequestError, "The node provided is a frame which contains this document.");
- return 0;
+ return nullptr;
}
}
if (source->parentNode()) {
source->parentNode()->removeChild(source.get(), exceptionState);
if (exceptionState.hadException())
- return 0;
+ return nullptr;
}
}
@@ -1148,7 +1156,7 @@
void Document::setXMLVersion(const String& version, ExceptionState& exceptionState)
{
- if (!implementation()->hasFeature("XML", String())) {
+ if (!implementation().hasFeature("XML", String())) {
exceptionState.throwDOMException(NotSupportedError, "This document does not support XML.");
return;
}
@@ -1163,7 +1171,7 @@
void Document::setXMLStandalone(bool standalone, ExceptionState& exceptionState)
{
- if (!implementation()->hasFeature("XML", String())) {
+ if (!implementation().hasFeature("XML", String())) {
exceptionState.throwDOMException(NotSupportedError, "This document does not support XML.");
return;
}
@@ -1218,11 +1226,11 @@
PassRefPtr<Range> Document::caretRangeFromPoint(int x, int y)
{
if (!renderView())
- return 0;
+ return nullptr;
HitTestResult result = hitTestInDocument(this, x, y);
RenderObject* renderer = result.renderer();
if (!renderer)
- return 0;
+ return nullptr;
Node* node = renderer->node();
Node* shadowAncestorNode = ancestorInThisScope(node);
@@ -1234,7 +1242,7 @@
PositionWithAffinity positionWithAffinity = renderer->positionForPoint(result.localPoint());
if (positionWithAffinity.position().isNull())
- return 0;
+ return nullptr;
Position rangeCompliantPosition = positionWithAffinity.position().parentAnchoredEquivalent();
return Range::create(*this, rangeCompliantPosition, rangeCompliantPosition);
@@ -1321,7 +1329,7 @@
// Title set by JavaScript -- overrides any title elements.
m_titleSetExplicitly = true;
if (!isHTMLDocument() && !isXHTMLDocument())
- m_titleElement = 0;
+ m_titleElement = nullptr;
else if (!m_titleElement) {
if (HTMLElement* headElement = head()) {
m_titleElement = HTMLTitleElement::create(*this);
@@ -1329,7 +1337,7 @@
}
}
- if (m_titleElement && m_titleElement->hasTagName(titleTag))
+ if (isHTMLTitleElement(m_titleElement))
toHTMLTitleElement(m_titleElement)->setText(title);
else
updateTitle(title);
@@ -1352,19 +1360,14 @@
if (m_titleElement != titleElement)
return;
- m_titleElement = 0;
+ m_titleElement = nullptr;
m_titleSetExplicitly = false;
// FIXME: This is broken for SVG.
// Update title based on first title element in the head, if one exists.
if (HTMLElement* headElement = head()) {
- for (Element* element = ElementTraversal::firstWithin(*headElement); element; element = ElementTraversal::nextSibling(*element)) {
- if (!element->hasTagName(titleTag))
- continue;
- HTMLTitleElement* title = toHTMLTitleElement(element);
+ if (HTMLTitleElement* title = Traversal<HTMLTitleElement>::firstChild(*headElement))
setTitleElement(title->text(), title);
- break;
- }
}
if (!m_titleElement)
@@ -1426,11 +1429,11 @@
return DOCUMENT_NODE;
}
-FormController* Document::formController()
+FormController& Document::formController()
{
if (!m_formController)
m_formController = FormController::create();
- return m_formController.get();
+ return *m_formController;
}
Vector<String> Document::formElementsState() const
@@ -1444,7 +1447,7 @@
{
if (!stateVector.size() && !m_formController)
return;
- formController()->setStateForNewFormElements(stateVector);
+ formController().setStateForNewFormElements(stateVector);
}
FrameView* Document::view() const
@@ -1476,8 +1479,8 @@
{
// FIXME: Probably this should be handled within the bindings layer and TypeError should be thrown.
if (!root) {
- exceptionState.throwDOMException(NotSupportedError, "The provided node is invalid.");
- return 0;
+ exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node"));
+ return nullptr;
}
return NodeIterator::create(root, NodeFilter::SHOW_ALL, PassRefPtr<NodeFilter>());
}
@@ -1485,8 +1488,8 @@
PassRefPtr<NodeIterator> Document::createNodeIterator(Node* root, unsigned whatToShow, ExceptionState& exceptionState)
{
if (!root) {
- exceptionState.throwDOMException(NotSupportedError, "The provided node is invalid.");
- return 0;
+ exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node"));
+ return nullptr;
}
// FIXME: It might be a good idea to emit a warning if |whatToShow| contains a bit that is not defined in
// NodeFilter.
@@ -1496,8 +1499,8 @@
PassRefPtr<NodeIterator> Document::createNodeIterator(Node* root, unsigned whatToShow, PassRefPtr<NodeFilter> filter, ExceptionState& exceptionState)
{
if (!root) {
- exceptionState.throwDOMException(NotSupportedError, "The provided node is invalid.");
- return 0;
+ exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node"));
+ return nullptr;
}
// FIXME: Ditto.
return NodeIterator::create(root, whatToShow, filter);
@@ -1506,8 +1509,8 @@
PassRefPtr<TreeWalker> Document::createTreeWalker(Node* root, ExceptionState& exceptionState)
{
if (!root) {
- exceptionState.throwDOMException(NotSupportedError, "The provided node is invalid.");
- return 0;
+ exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node"));
+ return nullptr;
}
return TreeWalker::create(root, NodeFilter::SHOW_ALL, PassRefPtr<NodeFilter>());
}
@@ -1515,8 +1518,8 @@
PassRefPtr<TreeWalker> Document::createTreeWalker(Node* root, unsigned whatToShow, ExceptionState& exceptionState)
{
if (!root) {
- exceptionState.throwDOMException(NotSupportedError, "The provided node is invalid.");
- return 0;
+ exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node"));
+ return nullptr;
}
return TreeWalker::create(root, whatToShow, PassRefPtr<NodeFilter>());
}
@@ -1524,8 +1527,8 @@
PassRefPtr<TreeWalker> Document::createTreeWalker(Node* root, unsigned whatToShow, PassRefPtr<NodeFilter> filter, ExceptionState& exceptionState)
{
if (!root) {
- exceptionState.throwDOMException(NotSupportedError, "The provided node is invalid.");
- return 0;
+ exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node"));
+ return nullptr;
}
return TreeWalker::create(root, whatToShow, filter);
}
@@ -1560,8 +1563,7 @@
ASSERT(shouldCallRecalcStyleForDocument());
- if (!view()->isServicingAnimations())
- view()->scheduleAnimation();
+ page()->animator().scheduleVisualUpdate();
m_lifecycle.advanceTo(DocumentLifecycle::StyleRecalcPending);
InspectorInstrumentation::didScheduleStyleRecalculation(this);
@@ -1582,17 +1584,14 @@
void Document::updateStyleInvalidationIfNeeded()
{
+ if (!isActive())
+ return;
if (!childNeedsStyleInvalidation())
return;
TRACE_EVENT0("webkit", "Document::computeNeedsStyleRecalcState");
- if (!styleResolver()) {
- clearChildNeedsStyleInvalidation();
- return;
- }
+ ASSERT(styleResolver());
- // FIXME: the style resolver can be deleted at present. Either resolve
- // crbug.com/335964 or move the invalidation data elsewhere.
- styleResolver()->ensureRuleFeatureSet().computeStyleInvalidation(*this);
+ styleResolver()->ruleFeatureSet().computeStyleInvalidation(*this);
}
void Document::updateDistributionForNodeIfNeeded(Node* node)
@@ -1664,28 +1663,32 @@
documentElement()->setNeedsStyleRecalc(SubtreeStyleChange);
}
+ EOverflow overflowX = OAUTO;
+ EOverflow overflowY = OAUTO;
+ float columnGap = 0;
+ if (overflowStyle) {
+ overflowX = overflowStyle->overflowX();
+ overflowY = overflowStyle->overflowY();
+ // Visible overflow on the viewport is meaningless, and the spec says to treat it as 'auto':
+ if (overflowX == OVISIBLE)
+ overflowX = OAUTO;
+ if (overflowY == OVISIBLE)
+ overflowY = OAUTO;
+ // Column-gap is (ab)used by the current paged overflow implementation (in lack of other
+ // ways to specify gaps between pages), so we have to propagate it too.
+ columnGap = overflowStyle->columnGap();
+ }
+
RefPtr<RenderStyle> documentStyle = renderView()->style();
if (documentStyle->writingMode() != rootWritingMode
|| documentStyle->direction() != rootDirection
- || (overflowStyle && (documentStyle->overflowX() != overflowStyle->overflowX() || documentStyle->overflowY() != overflowStyle->overflowY()))) {
+ || documentStyle->overflowX() != overflowX
+ || documentStyle->overflowY() != overflowY
+ || documentStyle->columnGap() != columnGap) {
RefPtr<RenderStyle> newStyle = RenderStyle::clone(documentStyle.get());
newStyle->setWritingMode(rootWritingMode);
newStyle->setDirection(rootDirection);
- EOverflow overflowX = OAUTO;
- EOverflow overflowY = OAUTO;
- if (overflowStyle) {
- overflowX = overflowStyle->overflowX();
- overflowY = overflowStyle->overflowY();
- // Visible overflow on the viewport is meaningless, and the spec says to treat it as 'auto':
- if (overflowX == OVISIBLE)
- overflowX = OAUTO;
- if (overflowY == OVISIBLE)
- overflowY = OAUTO;
-
- // Column-gap is (ab)used by the current paged overflow implementation (in lack of other
- // ways to specify gaps between pages), so we have to propagate it too.
- newStyle->setColumnGap(overflowStyle->columnGap());
- }
+ newStyle->setColumnGap(columnGap);
newStyle->setOverflowX(overflowX);
newStyle->setOverflowY(overflowY);
renderView()->setStyle(newStyle);
@@ -1716,7 +1719,7 @@
{
ASSERT(isMainThread());
- if (!shouldCallRecalcStyleForDocument())
+ if (change != Force && !shouldCallRecalcStyleForDocument())
return;
if (inStyleRecalc())
@@ -1728,8 +1731,8 @@
RELEASE_ASSERT(!view()->isInPerformLayout());
RELEASE_ASSERT(!view()->isPainting());
- // Script can run below in PostAttachCallbacks or WidgetUpdates, so protect the Frame.
- RefPtr<Frame> protect(m_frame);
+ // Script can run below in PostAttachCallbacks or WidgetUpdates, so protect the LocalFrame.
+ RefPtr<LocalFrame> protect(m_frame);
TRACE_EVENT0("webkit", "Document::recalcStyle");
TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "RecalcStyle");
@@ -1746,8 +1749,8 @@
}
// FIXME: We should update style on our ancestor chain before proceeding
- // however doing so currently causes several tests to crash, as Frame::setDocument calls Document::attach
- // before setting the DOMWindow on the Frame, or the SecurityOrigin on the document. The attach, in turn
+ // however doing so currently causes several tests to crash, as LocalFrame::setDocument calls Document::attach
+ // before setting the DOMWindow on the LocalFrame, or the SecurityOrigin on the document. The attach, in turn
// resolves style (here) and then when we resolve style on the parent chain, we may end up
// re-attaching our containing iframe, which when asked HTMLFrameElementBase::isURLAllowed
// hits a null-dereference due to security code always assuming the document has a SecurityOrigin.
@@ -1802,7 +1805,7 @@
if (m_styleEngine->hasResolver()) {
// Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc.
StyleResolver& resolver = m_styleEngine->ensureResolver();
- m_styleEngine->resetCSSFeatureFlags(resolver.ensureRuleFeatureSet());
+ m_styleEngine->resetCSSFeatureFlags(resolver.ensureUpdatedRuleFeatureSet());
resolver.clearStyleSharingList();
}
@@ -1821,8 +1824,6 @@
if (m_focusedElement && !m_focusedElement->isFocusable())
clearFocusedElementSoon();
- DocumentAnimations::serviceAfterStyleRecalc(*this);
-
InspectorInstrumentation::didRecalculateStyle(cookie);
}
@@ -1864,9 +1865,6 @@
// Only do a layout if changes have occurred that make it necessary.
if (isActive() && frameView && renderView() && (frameView->layoutPending() || renderView()->needsLayout()))
frameView->layout();
-
- if (isActive() && frameView)
- frameView->partialLayout().reset();
}
void Document::setNeedsFocusedElementCheck()
@@ -1877,7 +1875,7 @@
void Document::clearFocusedElementSoon()
{
if (!m_clearFocusedElementTimer.isActive())
- m_clearFocusedElementTimer.startOneShot(0);
+ m_clearFocusedElementTimer.startOneShot(0, FROM_HERE);
}
void Document::clearFocusedElementTimerFired(Timer<Document>*)
@@ -1886,7 +1884,7 @@
m_clearFocusedElementTimer.stop();
if (m_focusedElement && !m_focusedElement->isFocusable())
- setFocusedElement(0);
+ setFocusedElement(nullptr);
}
void Document::recalcStyleForLayoutIgnoringPendingStylesheets()
@@ -1930,38 +1928,6 @@
view()->flushAnyPendingPostLayoutTasks();
}
-void Document::partialUpdateLayoutIgnorePendingStylesheets(Node* stopLayoutAtNode)
-{
- // Non-overlay scrollbars can cause a second layout that is dependent
- // on a first layout. This is disabled for partial layout for now.
- if (!RuntimeEnabledFeatures::partialLayoutEnabled() || !ScrollbarTheme::theme()->usesOverlayScrollbars()) {
- updateLayoutIgnorePendingStylesheets();
- return;
- }
-
- StyleEngine::IgnoringPendingStylesheet ignoring(m_styleEngine.get());
- recalcStyleForLayoutIgnoringPendingStylesheets();
-
- if (stopLayoutAtNode) {
- RenderObject* renderer = stopLayoutAtNode->renderer();
- bool canPartialLayout = renderer;
- while (renderer) {
- if (!renderer->supportsPartialLayout()) {
- canPartialLayout = false;
- break;
- }
- renderer = renderer->parent();
- }
- if (canPartialLayout && view())
- view()->partialLayout().setStopAtRenderer(stopLayoutAtNode->renderer());
- }
-
- updateLayout();
-
- if (view())
- view()->partialLayout().reset();
-}
-
PassRefPtr<RenderStyle> Document::styleForElementIgnoringPendingStylesheets(Element* element)
{
ASSERT_ARG(element, element->document() == this);
@@ -2106,7 +2072,7 @@
m_scriptedAnimationController.clear();
if (svgExtensions())
- accessSVGExtensions()->pauseAnimations();
+ accessSVGExtensions().pauseAnimations();
// FIXME: This shouldn't be needed once DOMWindow becomes ExecutionContext.
if (m_domWindow)
@@ -2128,10 +2094,10 @@
setRenderer(0);
m_renderView = 0;
- m_hoverNode = 0;
- m_focusedElement = 0;
- m_activeHoverElement = 0;
- m_autofocusElement = 0;
+ m_hoverNode = nullptr;
+ m_focusedElement = nullptr;
+ m_activeHoverElement = nullptr;
+ m_autofocusElement = nullptr;
ContainerNode::detach(context);
@@ -2143,7 +2109,7 @@
if (Document* parentDoc = parentDocument())
parentDoc->didClearTouchEventHandlers(this);
- // This is required, as our Frame might delete itself as soon as it detaches
+ // This is required, as our LocalFrame might delete itself as soon as it detaches
// us. However, this violates Node::detach() semantics, as it's never
// possible to re-attach. Eventually Document::detach() should be renamed,
// or this setting of the frame to 0 could be made explicit in each of the
@@ -2196,10 +2162,10 @@
// If the renderer is gone then we are in the process of destruction.
// This method will be called before m_frame = 0.
- if (!topDocument()->renderView())
+ if (!topDocument().renderView())
return 0;
- return topDocument()->m_axObjectCache.get();
+ return topDocument().m_axObjectCache.get();
}
AXObjectCache* Document::axObjectCache() const
@@ -2211,16 +2177,16 @@
// document. This is because we need to be able to get from any WebCoreAXObject
// to any other WebCoreAXObject on the same page. Using a single cache allows
// lookups across nested webareas (i.e. multiple documents).
- Document* topDocument = this->topDocument();
+ Document& topDocument = this->topDocument();
// If the document has already been detached, do not make a new axObjectCache.
- if (!topDocument->renderView())
+ if (!topDocument.renderView())
return 0;
ASSERT(topDocument == this || !m_axObjectCache);
- if (!topDocument->m_axObjectCache)
- topDocument->m_axObjectCache = adoptPtr(new AXObjectCache(topDocument));
- return topDocument->m_axObjectCache.get();
+ if (!topDocument.m_axObjectCache)
+ topDocument.m_axObjectCache = adoptPtr(new AXObjectCache(topDocument));
+ return topDocument.m_axObjectCache.get();
}
PassRefPtr<DocumentParser> Document::createParser()
@@ -2237,8 +2203,7 @@
{
if (!isHTMLDocument())
return false;
- HTMLElement* bodyElement = body();
- return bodyElement && bodyElement->hasTagName(framesetTag);
+ return isHTMLFrameSetElement(body());
}
ScriptableDocumentParser* Document::scriptableDocumentParser() const
@@ -2323,9 +2288,9 @@
if (!documentElement())
return 0;
- for (Node* child = documentElement()->firstChild(); child; child = child->nextSibling()) {
- if (child->hasTagName(framesetTag) || child->hasTagName(bodyTag))
- return toHTMLElement(child);
+ for (HTMLElement* child = Traversal<HTMLElement>::firstWithin(*documentElement()); child; child = Traversal<HTMLElement>::nextSibling(*child)) {
+ if (isHTMLFrameSetElement(*child) || isHTMLBodyElement(*child))
+ return child;
}
return 0;
@@ -2336,7 +2301,7 @@
RefPtr<HTMLElement> newBody = prpNewBody;
if (!newBody) {
- exceptionState.throwDOMException(HierarchyRequestError, "The node provided is invalid.");
+ exceptionState.throwDOMException(HierarchyRequestError, ExceptionMessages::argumentNullOrIncorrectType(1, "HTMLElement"));
return;
}
if (!documentElement()) {
@@ -2344,7 +2309,7 @@
return;
}
- if (!newBody->hasTagName(bodyTag) && !newBody->hasTagName(framesetTag)) {
+ if (!isHTMLBodyElement(*newBody) && !isHTMLFrameSetElement(*newBody)) {
exceptionState.throwDOMException(HierarchyRequestError, "The new body element is of type '" + newBody->tagName() + "'. It must be either a 'BODY' or 'FRAMESET' element.");
return;
}
@@ -2365,11 +2330,7 @@
if (!de)
return 0;
- for (Node* node = de->firstChild(); node; node = node->nextSibling()) {
- if (node->hasTagName(headTag))
- return toHTMLHeadElement(node);
- }
- return 0;
+ return Traversal<HTMLHeadElement>::firstChild(*de);
}
Element* Document::viewportDefiningElement(RenderStyle* rootStyle) const
@@ -2389,7 +2350,7 @@
if (!rootStyle)
return 0;
}
- if (bodyElement && rootStyle->isOverflowVisible() && rootElement->hasTagName(htmlTag))
+ if (bodyElement && rootStyle->isOverflowVisible() && isHTMLHtmlElement(*rootElement))
return bodyElement;
return rootElement;
}
@@ -2463,7 +2424,7 @@
// To align the HTML load event and the SVGLoad event for the outermost <svg> element, fire it from
// here, instead of doing it from SVGElement::finishedParsingChildren.
if (svgExtensions())
- accessSVGExtensions()->dispatchSVGLoadEventToOutermostSVGElements();
+ accessSVGExtensions().dispatchSVGLoadEventToOutermostSVGElements();
if (protectedWindow)
protectedWindow->documentWasClosed();
@@ -2520,7 +2481,7 @@
}
if (svgExtensions())
- accessSVGExtensions()->startAnimations();
+ accessSVGExtensions().startAnimations();
}
bool Document::dispatchBeforeUnloadEvent(Chrome& chrome, bool& didAllowNavigation)
@@ -2563,8 +2524,8 @@
if (m_loadEventProgress >= LoadEventTried && m_loadEventProgress <= UnloadEventInProgress) {
Element* currentFocusedElement = focusedElement();
- if (currentFocusedElement && currentFocusedElement->hasTagName(inputTag))
- toHTMLInputElement(currentFocusedElement)->endEditing();
+ if (isHTMLInputElement(currentFocusedElement))
+ toHTMLInputElement(*currentFocusedElement).endEditing();
if (m_loadEventProgress < PageHideInProgress) {
m_loadEventProgress = PageHideInProgress;
if (DOMWindow* window = domWindow())
@@ -2628,8 +2589,8 @@
// (a) Only schedule a layout once the stylesheets are loaded.
// (b) Only schedule layout once we have a body element.
- return (haveStylesheetsLoaded() && body())
- || (documentElement() && !documentElement()->hasTagName(htmlTag));
+ return (haveStylesheetsAndImportsLoaded() && body())
+ || (documentElement() && !isHTMLHtmlElement(*documentElement()));
}
bool Document::shouldParserYieldAgressivelyBeforeScriptExecution()
@@ -2713,7 +2674,7 @@
m_url = newURL;
updateBaseURL();
- contextFeatures()->urlDidChange(this);
+ contextFeatures().urlDidChange(this);
}
void Document::updateBaseURL()
@@ -2746,10 +2707,8 @@
if (!equalIgnoringFragmentIdentifier(oldBaseURL, m_baseURL)) {
// Base URL change changes any relative visited links.
// FIXME: There are other URLs in the tree that would need to be re-evaluated on dynamic base URL change. Style should be invalidated too.
- for (Element* element = ElementTraversal::firstWithin(*this); element; element = ElementTraversal::next(*element)) {
- if (element->hasTagName(aTag))
- toHTMLAnchorElement(element)->invalidateCachedVisitedLinkHash();
- }
+ for (HTMLAnchorElement* anchor = Traversal<HTMLAnchorElement>::firstWithin(*this); anchor; anchor = Traversal<HTMLAnchorElement>::next(*anchor))
+ anchor->invalidateCachedVisitedLinkHash();
}
}
@@ -2764,21 +2723,19 @@
// Find the first href attribute in a base element and the first target attribute in a base element.
const AtomicString* href = 0;
const AtomicString* target = 0;
- for (Element* element = ElementTraversal::firstWithin(*this); element && (!href || !target); element = ElementTraversal::next(*element)) {
- if (element->hasTagName(baseTag)) {
- if (!href) {
- const AtomicString& value = element->fastGetAttribute(hrefAttr);
- if (!value.isNull())
- href = &value;
- }
- if (!target) {
- const AtomicString& value = element->fastGetAttribute(targetAttr);
- if (!value.isNull())
- target = &value;
- }
- if (contentSecurityPolicy()->isActive())
- UseCounter::count(*this, UseCounter::ContentSecurityPolicyWithBaseElement);
+ for (HTMLBaseElement* base = Traversal<HTMLBaseElement>::firstWithin(*this); base && (!href || !target); base = Traversal<HTMLBaseElement>::next(*base)) {
+ if (!href) {
+ const AtomicString& value = base->fastGetAttribute(hrefAttr);
+ if (!value.isNull())
+ href = &value;
}
+ if (!target) {
+ const AtomicString& value = base->fastGetAttribute(targetAttr);
+ if (!value.isNull())
+ target = &value;
+ }
+ if (contentSecurityPolicy()->isActive())
+ UseCounter::count(*this, UseCounter::ContentSecurityPolicyWithBaseElement);
}
// FIXME: Since this doesn't share code with completeURL it may not handle encodings correctly.
@@ -2809,7 +2766,7 @@
frame()->script().disableEval(errorMessage);
}
-bool Document::canNavigate(Frame* targetFrame)
+bool Document::canNavigate(LocalFrame* targetFrame)
{
if (!m_frame)
return false;
@@ -2820,7 +2777,7 @@
if (!targetFrame)
return true;
- // Frame-busting is generally allowed, but blocked for sandboxed frames lacking the 'allow-top-navigation' flag.
+ // LocalFrame-busting is generally allowed, but blocked for sandboxed frames lacking the 'allow-top-navigation' flag.
if (!isSandboxed(SandboxTopNavigation) && targetFrame == m_frame->tree().top())
return true;
@@ -2872,10 +2829,10 @@
return false;
}
-Frame* Document::findUnsafeParentScrollPropagationBoundary()
+LocalFrame* Document::findUnsafeParentScrollPropagationBoundary()
{
- Frame* currentFrame = m_frame;
- Frame* ancestorFrame = currentFrame->tree().parent();
+ LocalFrame* currentFrame = m_frame;
+ LocalFrame* ancestorFrame = currentFrame->tree().parent();
while (ancestorFrame) {
if (!ancestorFrame->document()->securityOrigin()->canAccess(securityOrigin()))
@@ -2890,11 +2847,14 @@
{
m_needsNotifyRemoveAllPendingStylesheet = false;
- styleResolverChanged(RecalcStyleDeferred, AnalyzedStyleUpdate);
+ styleResolverChanged(RecalcStyleDeferred, hasNodesWithPlaceholderStyle() ? FullStyleUpdate : AnalyzedStyleUpdate);
executeScriptsWaitingForResourcesIfNeeded();
if (m_gotoAnchorNeededAfterStylesheetsLoad && view())
view()->scrollToFragment(m_url);
+
+ if (m_import)
+ m_import->didRemoveAllPendingStylesheet();
}
void Document::executeScriptsWaitingForResourcesIfNeeded()
@@ -2906,11 +2866,11 @@
}
-CSSStyleSheet* Document::elementSheet()
+CSSStyleSheet& Document::elementSheet()
{
if (!m_elemSheet)
m_elemSheet = CSSStyleSheet::createInline(this, m_baseURL);
- return m_elemSheet.get();
+ return *m_elemSheet;
}
void Document::processHttpEquiv(const AtomicString& equiv, const AtomicString& content, bool inDocumentHeadElement)
@@ -2939,10 +2899,12 @@
void Document::processHttpEquivContentSecurityPolicy(const AtomicString& equiv, const AtomicString& content)
{
+ if (import() && import()->isChild())
+ return;
if (equalIgnoringCase(equiv, "content-security-policy"))
- contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::Enforce, ContentSecurityPolicy::HeaderSourceMeta);
+ contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicyHeaderTypeEnforce, ContentSecurityPolicyHeaderSourceMeta);
else if (equalIgnoringCase(equiv, "content-security-policy-report-only"))
- contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::Report, ContentSecurityPolicy::HeaderSourceMeta);
+ contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicyHeaderTypeReport, ContentSecurityPolicyHeaderSourceMeta);
else
ASSERT_NOT_REACHED();
}
@@ -3005,7 +2967,7 @@
void Document::processHttpEquivXFrameOptions(const AtomicString& content)
{
- Frame* frame = this->frame();
+ LocalFrame* frame = this->frame();
if (!frame)
return;
@@ -3095,7 +3057,7 @@
// See http://www.whatwg.org/specs/web-apps/current-work/#fetching-resources
// for why we walk the parent chain for srcdoc documents.
Document* referrerDocument = this;
- if (Frame* frame = m_frame) {
+ if (LocalFrame* frame = m_frame) {
while (frame->document()->isSrcdocDocument()) {
frame = frame->tree().parent();
// Srcdoc documents cannot be top-level documents, by definition,
@@ -3347,7 +3309,7 @@
return;
bool contains = node->containsIncludingShadowDOM(m_focusedElement.get());
if (contains && (m_focusedElement != node || !amongChildrenOnly))
- setFocusedElement(0);
+ setFocusedElement(nullptr);
}
void Document::hoveredNodeDetached(Node* node)
@@ -3416,7 +3378,7 @@
bool focusChangeBlocked = false;
RefPtr<Element> oldFocusedElement = m_focusedElement;
- m_focusedElement = 0;
+ m_focusedElement = nullptr;
// Remove focus from the existing focus node (if any)
if (oldFocusedElement) {
@@ -3435,7 +3397,7 @@
if (m_focusedElement) {
// handler shifted focus
focusChangeBlocked = true;
- newFocusedElement = 0;
+ newFocusedElement = nullptr;
}
oldFocusedElement->dispatchFocusOutEvent(EventTypeNames::focusout, newFocusedElement.get()); // DOM level 3 name for the bubbling blur event.
@@ -3446,7 +3408,7 @@
if (m_focusedElement) {
// handler shifted focus
focusChangeBlocked = true;
- newFocusedElement = 0;
+ newFocusedElement = nullptr;
}
}
@@ -3534,7 +3496,7 @@
SetFocusedElementDone:
updateStyleIfNeeded();
- if (Frame* frame = this->frame())
+ if (LocalFrame* frame = this->frame())
frame->selection().didChangeFocus();
return !focusChangeBlocked;
}
@@ -3597,7 +3559,7 @@
}
}
-void Document::nodeChildrenWillBeRemoved(ContainerNode* container)
+void Document::nodeChildrenWillBeRemoved(ContainerNode& container)
{
NoEventDispatchAssertion assertNoEventDispatch;
if (!m_ranges.isEmpty()) {
@@ -3608,12 +3570,12 @@
HashSet<NodeIterator*>::const_iterator nodeIteratorsEnd = m_nodeIterators.end();
for (HashSet<NodeIterator*>::const_iterator it = m_nodeIterators.begin(); it != nodeIteratorsEnd; ++it) {
- for (Node* n = container->firstChild(); n; n = n->nextSibling())
+ for (Node* n = container.firstChild(); n; n = n->nextSibling())
(*it)->nodeWillBeRemoved(*n);
}
- if (Frame* frame = this->frame()) {
- for (Node* n = container->firstChild(); n; n = n->nextSibling()) {
+ if (LocalFrame* frame = this->frame()) {
+ for (Node* n = container.firstChild(); n; n = n->nextSibling()) {
frame->eventHandler().nodeWillBeRemoved(*n);
frame->selection().nodeWillBeRemoved(*n);
frame->page()->dragCaretController().nodeWillBeRemoved(*n);
@@ -3633,7 +3595,7 @@
(*it)->nodeWillBeRemoved(n);
}
- if (Frame* frame = this->frame()) {
+ if (LocalFrame* frame = this->frame()) {
frame->eventHandler().nodeWillBeRemoved(n);
frame->selection().nodeWillBeRemoved(n);
frame->page()->dragCaretController().nodeWillBeRemoved(n);
@@ -3665,7 +3627,7 @@
m_markers->shiftMarkers(text, offset + length, 0 - length);
}
-void Document::didMergeTextNodes(Text* oldNode, unsigned offset)
+void Document::didMergeTextNodes(Text& oldNode, unsigned offset)
{
if (!m_ranges.isEmpty()) {
NodeWithIndex oldNodeWithIndex(oldNode);
@@ -3675,12 +3637,12 @@
}
if (m_frame)
- m_frame->selection().didMergeTextNodes(*oldNode, offset);
+ m_frame->selection().didMergeTextNodes(oldNode, offset);
// FIXME: This should update markers for spelling and grammar checking.
}
-void Document::didSplitTextNode(Text* oldNode)
+void Document::didSplitTextNode(Text& oldNode)
{
if (!m_ranges.isEmpty()) {
HashSet<Range*>::const_iterator end = m_ranges.end();
@@ -3689,7 +3651,7 @@
}
if (m_frame)
- m_frame->selection().didSplitTextNode(*oldNode);
+ m_frame->selection().didSplitTextNode(oldNode);
// FIXME: This should update markers for spelling and grammar checking.
}
@@ -3744,14 +3706,14 @@
return event.release();
exceptionState.throwDOMException(NotSupportedError, "The provided event type ('" + eventType + "') is invalid.");
- return 0;
+ return nullptr;
}
PassRefPtr<Event> Document::createEvent(ExceptionState& exceptionState)
{
if (!isSVGDocument()) {
exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(1, 0));
- return 0;
+ return nullptr;
}
UseCounter::count(this, UseCounter::DocumentCreateEventOptionalArgument);
@@ -3945,7 +3907,7 @@
const KURL& Document::firstPartyForCookies() const
{
- return topDocument()->url();
+ return topDocument().url();
}
static bool isValidNameNonASCII(const LChar* characters, unsigned length)
@@ -4113,7 +4075,7 @@
CString originalBytes = m_titleElement->textContent().latin1();
OwnPtr<TextCodec> codec = newTextCodec(newData.encoding());
- String correctlyDecodedTitle = codec->decode(originalBytes.data(), originalBytes.length(), true);
+ String correctlyDecodedTitle = codec->decode(originalBytes.data(), originalBytes.length(), DataEOF);
m_titleElement->setTextContent(correctlyDecodedTitle);
}
@@ -4163,7 +4125,7 @@
static Editor::Command command(Document* document, const String& commandName, bool userInterface = false)
{
- Frame* frame = document->frame();
+ LocalFrame* frame = document->frame();
if (!frame || frame->document() != document)
return Editor::Command();
@@ -4233,11 +4195,7 @@
if (!head())
return KURL();
- RefPtr<HTMLCollection> children = head()->children();
- for (unsigned i = 0; Element* child = children->item(i); i++) {
- if (!child->hasTagName(linkTag))
- continue;
- HTMLLinkElement* linkElement = toHTMLLinkElement(child);
+ for (HTMLLinkElement* linkElement = Traversal<HTMLLinkElement>::firstChild(*head()); linkElement; linkElement = Traversal<HTMLLinkElement>::nextSibling(*linkElement)) {
if (!equalIgnoringCase(linkElement->type(), openSearchMIMEType) || !equalIgnoringCase(linkElement->rel(), openSearchRelation))
continue;
if (linkElement->href().isEmpty())
@@ -4264,7 +4222,7 @@
{
ASSERT(!pi->isLoading());
UseCounter::count(*this, UseCounter::XSLProcessingInstruction);
- RefPtr<XSLTProcessor> processor = XSLTProcessor::create();
+ RefPtrWillBeRawPtr<XSLTProcessor> processor = XSLTProcessor::create();
processor->setXSLStyleSheet(toXSLStyleSheet(pi->sheet()));
String resultMIMEType;
String newSource;
@@ -4272,7 +4230,7 @@
if (!processor->transformToString(this, resultMIMEType, newSource, resultEncoding))
return;
// FIXME: If the transform failed we should probably report an error (like Mozilla does).
- Frame* ownerFrame = frame();
+ LocalFrame* ownerFrame = frame();
processor->createDocumentFromSource(newSource, resultEncoding, resultMIMEType, this, ownerFrame);
InspectorInstrumentation::frameDocumentUpdated(ownerFrame);
}
@@ -4285,7 +4243,7 @@
void Document::setDesignMode(InheritedBool value)
{
m_designMode = value;
- for (Frame* frame = m_frame; frame && frame->document(); frame = frame->tree().traverseNext(m_frame))
+ for (LocalFrame* frame = m_frame; frame && frame->document(); frame = frame->tree().traverseNext(m_frame))
frame->document()->setNeedsStyleRecalc(SubtreeStyleChange);
}
@@ -4307,20 +4265,21 @@
{
if (!m_frame)
return 0;
- Frame* parent = m_frame->tree().parent();
+ LocalFrame* parent = m_frame->tree().parent();
if (!parent)
return 0;
return parent->document();
}
-Document* Document::topDocument() const
+Document& Document::topDocument() const
{
Document* doc = const_cast<Document*>(this);
Element* element;
while ((element = doc->ownerElement()))
doc = &element->document();
- return doc;
+ ASSERT(doc);
+ return *doc;
}
WeakPtr<Document> Document::contextDocument()
@@ -4329,14 +4288,14 @@
return m_contextDocument;
if (m_frame)
return m_weakFactory.createWeakPtr();
- return WeakPtr<Document>(0);
+ return WeakPtr<Document>(nullptr);
}
PassRefPtr<Attr> Document::createAttribute(const AtomicString& name, ExceptionState& exceptionState)
{
AtomicString prefix, localName;
if (!parseQualifiedName(name, prefix, localName, exceptionState))
- return 0;
+ return nullptr;
QualifiedName qName(prefix, localName, nullAtom);
@@ -4348,21 +4307,21 @@
return m_svgExtensions.get();
}
-SVGDocumentExtensions* Document::accessSVGExtensions()
+SVGDocumentExtensions& Document::accessSVGExtensions()
{
if (!m_svgExtensions)
m_svgExtensions = adoptPtr(new SVGDocumentExtensions(this));
- return m_svgExtensions.get();
+ return *m_svgExtensions;
}
bool Document::hasSVGRootNode() const
{
- return documentElement() && documentElement()->hasTagName(SVGNames::svgTag);
+ return isSVGSVGElement(documentElement());
}
PassRefPtr<HTMLCollection> Document::ensureCachedCollection(CollectionType type)
{
- return ensureRareData().ensureNodeLists().addCache<HTMLCollection>(this, type);
+ return ensureRareData().ensureNodeLists().addCache<HTMLCollection>(*this, type);
}
PassRefPtr<HTMLCollection> Document::images()
@@ -4408,17 +4367,17 @@
PassRefPtr<HTMLCollection> Document::all()
{
- return ensureRareData().ensureNodeLists().addCache<HTMLAllCollection>(this, DocAll);
+ return ensureRareData().ensureNodeLists().addCache<HTMLAllCollection>(*this, DocAll);
}
PassRefPtr<HTMLCollection> Document::windowNamedItems(const AtomicString& name)
{
- return ensureRareData().ensureNodeLists().addCache<HTMLNameCollection>(this, WindowNamedItems, name);
+ return ensureRareData().ensureNodeLists().addCache<HTMLNameCollection>(*this, WindowNamedItems, name);
}
PassRefPtr<HTMLCollection> Document::documentNamedItems(const AtomicString& name)
{
- return ensureRareData().ensureNodeLists().addCache<HTMLNameCollection>(this, DocumentNamedItems, name);
+ return ensureRareData().ensureNodeLists().addCache<HTMLNameCollection>(*this, DocumentNamedItems, name);
}
void Document::finishedParsing()
@@ -4437,7 +4396,7 @@
// Keep it alive until we are done.
RefPtr<Document> protect(this);
- if (RefPtr<Frame> f = frame()) {
+ if (RefPtr<LocalFrame> f = frame()) {
// FrameLoader::finishedParsing() might end up calling Document::implicitClose() if all
// resource loads are complete. HTMLObjectElements can start loading their resources from
// post attach callbacks triggered by recalcStyle(). This means if we parse out an <object>
@@ -4456,7 +4415,7 @@
// so that dynamically inserted content can also benefit from sharing optimizations.
// Note that we don't refresh the timer on cache access since that could lead to huge caches being kept
// alive indefinitely by something innocuous like JS setting .innerHTML repeatedly on a timer.
- m_elementDataCacheClearTimer.startOneShot(10);
+ m_elementDataCacheClearTimer.startOneShot(10, FROM_HERE);
// Parser should have picked up all preloads by now
m_fetcher->clearPreloads();
@@ -4478,13 +4437,7 @@
Vector<IconURL> secondaryIcons;
// Start from the last child node so that icons seen later take precedence as required by the spec.
- RefPtr<HTMLCollection> children = head() ? head()->children() : 0;
- unsigned length = children ? children->length() : 0;
- for (unsigned i = 0; i < length; i++) {
- Element* child = children->item(i);
- if (!child->hasTagName(linkTag))
- continue;
- HTMLLinkElement* linkElement = toHTMLLinkElement(child);
+ for (HTMLLinkElement* linkElement = head() ? Traversal<HTMLLinkElement>::firstChild(*head()) : 0; linkElement; linkElement = Traversal<HTMLLinkElement>::nextSibling(*linkElement)) {
if (!(linkElement->iconType() & iconTypesMask))
continue;
if (linkElement->href().isEmpty())
@@ -4544,6 +4497,13 @@
initSecurityContext(DocumentInit(m_url, m_frame, contextDocument(), m_import));
}
+static PassRefPtr<ContentSecurityPolicy> contentSecurityPolicyFor(Document* document)
+{
+ if (document->import() && document->import()->isChild())
+ return document->import()->master()->contentSecurityPolicy();
+ return ContentSecurityPolicy::create(document);
+}
+
void Document::initSecurityContext(const DocumentInit& initializer)
{
if (haveInitializedSecurityOrigin()) {
@@ -4565,7 +4525,7 @@
m_cookieURL = m_url;
enforceSandboxFlags(initializer.sandboxFlags());
setSecurityOrigin(isSandboxed(SandboxOrigin) ? SecurityOrigin::createUnique() : SecurityOrigin::create(m_url));
- setContentSecurityPolicy(ContentSecurityPolicy::create(this));
+ setContentSecurityPolicy(contentSecurityPolicyFor(this));
if (Settings* settings = initializer.settings()) {
if (!settings->webSecurityEnabled()) {
@@ -4633,7 +4593,7 @@
// http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#event-handler-attributes
// Also, if the listening node came from other document, which happens on context-less event dispatching,
// we also need to ask the owner document of the node.
- Frame* frame = executingFrame();
+ LocalFrame* frame = executingFrame();
if (!frame)
return false;
if (!frame->script().canExecuteScripts(NotAboutToExecuteScript))
@@ -4649,7 +4609,7 @@
// FIXME: Eventually we'd like to evaluate scripts which are inserted into a
// viewless document but this'll do for now.
// See http://bugs.webkit.org/show_bug.cgi?id=5727
- Frame* frame = executingFrame();
+ LocalFrame* frame = executingFrame();
if (!frame)
return false;
if (!node->document().executingFrame())
@@ -4681,7 +4641,7 @@
{
m_updateFocusAppearanceRestoresSelection = restorePreviousSelection;
if (!m_updateFocusAppearanceTimer.isActive())
- m_updateFocusAppearanceTimer.startOneShot(0);
+ m_updateFocusAppearanceTimer.startOneShot(0, FROM_HERE);
}
void Document::cancelFocusAppearanceUpdate()
@@ -4712,23 +4672,31 @@
m_ranges.remove(range);
}
-CanvasRenderingContext* Document::getCSSCanvasContext(const String& type, const String& name, int width, int height)
+void Document::getCSSCanvasContext(const String& type, const String& name, int width, int height, bool& is2d, RefPtr<CanvasRenderingContext2D>& context2d, bool& is3d, RefPtr<WebGLRenderingContext>& context3d)
{
- HTMLCanvasElement* element = getCSSCanvasElement(name);
- if (!element)
- return 0;
- element->setSize(IntSize(width, height));
- return element->getContext(type);
+ HTMLCanvasElement& element = getCSSCanvasElement(name);
+ element.setSize(IntSize(width, height));
+ CanvasRenderingContext* context = element.getContext(type);
+ if (!context)
+ return;
+
+ if (context->is2d()) {
+ is2d = true;
+ context2d = toCanvasRenderingContext2D(context);
+ } else if (context->is3d()) {
+ is3d = true;
+ context3d = toWebGLRenderingContext(context);
+ }
}
-HTMLCanvasElement* Document::getCSSCanvasElement(const String& name)
+HTMLCanvasElement& Document::getCSSCanvasElement(const String& name)
{
- RefPtr<HTMLCanvasElement>& element = m_cssCanvasElements.add(name, 0).storedValue->value;
+ RefPtr<HTMLCanvasElement>& element = m_cssCanvasElements.add(name, nullptr).storedValue->value;
if (!element) {
element = HTMLCanvasElement::create(*this);
element->setAccelerationDisabled(true);
}
- return element.get();
+ return *element;
}
void Document::initDNSPrefetch()
@@ -4763,7 +4731,7 @@
void Document::addMessage(MessageSource source, MessageLevel level, const String& message, const String& sourceURL, unsigned lineNumber, ScriptState* state)
{
- internalAddMessage(source, level, message, sourceURL, lineNumber, 0, state);
+ internalAddMessage(source, level, message, sourceURL, lineNumber, nullptr, state);
}
void Document::internalAddMessage(MessageSource source, MessageLevel level, const String& message, const String& sourceURL, unsigned lineNumber, PassRefPtr<ScriptCallStack> callStack, ScriptState* state)
@@ -4796,7 +4764,7 @@
}
if (FrameHost* host = frameHost())
- host->console().addMessage(source, level, message, String(), 0, 0, 0, 0, requestIdentifier);
+ host->console().addMessage(source, level, message, String(), 0, 0, nullptr, 0, requestIdentifier);
}
// FIXME(crbug.com/305497): This should be removed after ExecutionContext-DOMWindow migration.
@@ -4908,7 +4876,7 @@
--m_loadEventDelayCount;
if (frame() && !m_loadEventDelayCount && !m_loadEventDelayTimer.isActive())
- m_loadEventDelayTimer.startOneShot(0);
+ m_loadEventDelayTimer.startOneShot(0, FROM_HERE);
}
void Document::loadEventDelayTimerFired(Timer<Document>*)
@@ -4921,7 +4889,7 @@
{
// FIXME: Remove this timer once we don't need to compute layout to load plugins.
if (!m_pluginLoadingTimer.isActive())
- m_pluginLoadingTimer.startOneShot(0);
+ m_pluginLoadingTimer.startOneShot(0, FROM_HERE);
}
void Document::pluginLoadingTimerFired(Timer<Document>*)
@@ -4959,17 +4927,17 @@
m_scriptedAnimationController->serviceScriptedAnimations(monotonicAnimationStartTime);
}
-PassRefPtr<Touch> Document::createTouch(DOMWindow* window, EventTarget* target, int identifier, int pageX, int pageY, int screenX, int screenY, int radiusX, int radiusY, float rotationAngle, float force) const
+PassRefPtrWillBeRawPtr<Touch> Document::createTouch(DOMWindow* window, EventTarget* target, int identifier, int pageX, int pageY, int screenX, int screenY, int radiusX, int radiusY, float rotationAngle, float force) const
{
// FIXME: It's not clear from the documentation at
// http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/DocumentAdditionsReference/DocumentAdditions/DocumentAdditions.html
// when this method should throw and nor is it by inspection of iOS behavior. It would be nice to verify any cases where it throws under iOS
// and implement them here. See https://bugs.webkit.org/show_bug.cgi?id=47819
- Frame* frame = window ? window->frame() : this->frame();
+ LocalFrame* frame = window ? window->frame() : this->frame();
return Touch::create(frame, target, identifier, screenX, screenY, pageX, pageY, radiusX, radiusY, rotationAngle, force);
}
-PassRefPtr<TouchList> Document::createTouchList(Vector<RefPtr<Touch> >& touches) const
+PassRefPtrWillBeRawPtr<TouchList> Document::createTouchList(WillBeHeapVector<RefPtrWillBeMember<Touch> >& touches) const
{
return TouchList::create(touches);
}
@@ -5072,7 +5040,7 @@
{
if (!view())
return IntSize();
- return view()->unscaledVisibleContentSize(ScrollableArea::IncludeScrollbars);
+ return view()->unscaledVisibleContentSize(IncludeScrollbars);
}
Node* eventTargetNodeForDocument(Document* doc)
@@ -5098,7 +5066,7 @@
LayoutRect visibleContentRect = view()->visibleContentRect();
for (size_t i = 0; i < quads.size(); ++i) {
- quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
+ quads[i].move(-FloatSize(visibleContentRect.x(), visibleContentRect.y()));
adjustFloatQuadForAbsoluteZoom(quads[i], renderer);
}
}
@@ -5109,7 +5077,7 @@
return;
LayoutRect visibleContentRect = view()->visibleContentRect();
- rect.move(-visibleContentRect.x(), -visibleContentRect.y());
+ rect.move(-FloatSize(visibleContentRect.x(), visibleContentRect.y()));
adjustFloatRectForAbsoluteZoom(rect, renderer);
}
@@ -5130,9 +5098,9 @@
frame()->loader().checkLoadComplete();
}
-void Document::setContextFeatures(PassRefPtr<ContextFeatures> features)
+void Document::setContextFeatures(ContextFeatures& features)
{
- m_contextFeatures = features;
+ m_contextFeatures = PassRefPtr<ContextFeatures>(features);
}
static RenderObject* nearestCommonHoverAncestor(RenderObject* obj1, RenderObject* obj2)
@@ -5173,7 +5141,7 @@
m_userActionElements.setInActiveChain(curr->node(), false);
}
}
- setActiveHoverElement(0);
+ setActiveHoverElement(nullptr);
} else {
Element* newActiveElement = innerElementInDocument;
if (!oldActiveElement && newActiveElement && request.active() && !request.touchMove()) {
@@ -5336,7 +5304,7 @@
return;
m_associatedFormControls.add(element);
if (!m_didAssociateFormControlsTimer.isActive())
- m_didAssociateFormControlsTimer.startOneShot(0);
+ m_didAssociateFormControlsTimer.startOneShot(0, FROM_HERE);
}
void Document::didAssociateFormControlsTimerFired(Timer<Document>* timer)
@@ -5404,7 +5372,7 @@
void Document::setAutofocusElement(Element* element)
{
if (!element) {
- m_autofocusElement = 0;
+ m_autofocusElement = nullptr;
return;
}
if (m_hasAutofocused)
@@ -5429,7 +5397,7 @@
return false;
if (!page->focusController().isActive() || !page->focusController().isFocused())
return false;
- if (Frame* focusedFrame = page->focusController().focusedFrame()) {
+ if (LocalFrame* focusedFrame = page->focusController().focusedFrame()) {
if (focusedFrame->tree().isDescendantOf(frame()))
return true;
}
@@ -5447,4 +5415,38 @@
Node::defaultEventHandler(event);
}
+template<unsigned type>
+bool shouldInvalidateNodeListCachesForAttr(const unsigned nodeListCounts[], const QualifiedName& attrName)
+{
+ if (nodeListCounts[type] && LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(static_cast<NodeListInvalidationType>(type), attrName))
+ return true;
+ return shouldInvalidateNodeListCachesForAttr<type + 1>(nodeListCounts, attrName);
+}
+
+template<>
+bool shouldInvalidateNodeListCachesForAttr<numNodeListInvalidationTypes>(const unsigned[], const QualifiedName&)
+{
+ return false;
+}
+
+bool Document::shouldInvalidateNodeListCaches(const QualifiedName* attrName) const
+{
+ if (attrName)
+ return shouldInvalidateNodeListCachesForAttr<DoNotInvalidateOnAttributeChanges + 1>(m_nodeListCounts, *attrName);
+
+ for (int type = 0; type < numNodeListInvalidationTypes; type++) {
+ if (m_nodeListCounts[type])
+ return true;
+ }
+
+ return false;
+}
+
+void Document::invalidateNodeListCaches(const QualifiedName* attrName)
+{
+ HashSet<LiveNodeListBase*>::iterator end = m_listsInvalidatedAtDocument.end();
+ for (HashSet<LiveNodeListBase*>::iterator it = m_listsInvalidatedAtDocument.begin(); it != end; ++it)
+ (*it)->invalidateCache(attrName);
+}
+
} // namespace WebCore
diff --git a/Source/core/dom/Document.h b/Source/core/dom/Document.h
index 43ed676..18e4b8b 100644
--- a/Source/core/dom/Document.h
+++ b/Source/core/dom/Document.h
@@ -31,7 +31,6 @@
#include "bindings/v8/ScriptValue.h"
#include "core/animation/css/CSSPendingAnimations.h"
#include "core/dom/ContainerNode.h"
-#include "core/dom/DOMTimeStamp.h"
#include "core/dom/DocumentEncodingData.h"
#include "core/dom/DocumentInit.h"
#include "core/dom/DocumentLifecycle.h"
@@ -50,6 +49,7 @@
#include "core/page/FocusType.h"
#include "core/page/PageVisibilityState.h"
#include "core/rendering/HitTestRequest.h"
+#include "heap/Handle.h"
#include "platform/Timer.h"
#include "platform/weborigin/KURL.h"
#include "platform/weborigin/ReferrerPolicy.h"
@@ -69,7 +69,7 @@
class CSSStyleDeclaration;
class CSSStyleSheet;
class CSSStyleSheetResource;
-class CanvasRenderingContext;
+class CanvasRenderingContext2D;
class CharacterData;
class Chrome;
class Comment;
@@ -99,7 +99,7 @@
class FloatRect;
class FontFaceSet;
class FormController;
-class Frame;
+class LocalFrame;
class FrameHost;
class FrameView;
class HTMLAllCollection;
@@ -162,6 +162,7 @@
class TransformSource;
class TreeWalker;
class VisitedLinkState;
+class WebGLRenderingContext;
class XMLHttpRequest;
struct AnnotatedRegionValue;
@@ -295,7 +296,7 @@
void setDoctype(PassRefPtr<DocumentType>);
DocumentType* doctype() const { return m_docType.get(); }
- DOMImplementation* implementation();
+ DOMImplementation& implementation();
Element* documentElement() const
{
@@ -440,13 +441,12 @@
void evaluateMediaQueryList();
- // Never returns 0.
- FormController* formController();
+ FormController& formController();
Vector<String> formElementsState() const;
void setStateForNewFormElements(const Vector<String>&);
FrameView* view() const; // can be null
- Frame* frame() const { return m_frame; } // can be null
+ LocalFrame* frame() const { return m_frame; } // can be null
FrameHost* frameHost() const; // can be null
Page* page() const; // can be null
Settings* settings() const; // can be null
@@ -476,7 +476,6 @@
RunPostLayoutTasksSynchronously,
};
void updateLayoutIgnorePendingStylesheets(RunPostLayoutTasks = RunPostLayoutTasksAsyhnchronously);
- void partialUpdateLayoutIgnorePendingStylesheets(Node*);
PassRefPtr<RenderStyle> styleForElementIgnoringPendingStylesheets(Element*);
PassRefPtr<RenderStyle> styleForPage(int pageIndex);
@@ -557,10 +556,10 @@
virtual String userAgent(const KURL&) const OVERRIDE FINAL;
virtual void disableEval(const String& errorMessage) OVERRIDE FINAL;
- bool canNavigate(Frame* targetFrame);
- Frame* findUnsafeParentScrollPropagationBoundary();
+ bool canNavigate(LocalFrame* targetFrame);
+ LocalFrame* findUnsafeParentScrollPropagationBoundary();
- CSSStyleSheet* elementSheet();
+ CSSStyleSheet& elementSheet();
virtual PassRefPtr<DocumentParser> createParser();
DocumentParser* parser() const { return m_parser.get(); }
@@ -597,6 +596,9 @@
void setParsing(bool);
bool parsing() const { return m_isParsing; }
+ void setHistoryItemDocumentStateDirty(bool dirty) { m_historyItemDocumentStateDirty = dirty; }
+ bool historyItemDocumentStateDirty() const { return m_historyItemDocumentStateDirty; }
+
bool shouldScheduleLayout();
bool shouldParserYieldAgressivelyBeforeScriptExecution();
int elapsedTime() const;
@@ -657,15 +659,15 @@
void updateRangesAfterChildrenChanged(ContainerNode*);
// nodeChildrenWillBeRemoved is used when removing all node children at once.
- void nodeChildrenWillBeRemoved(ContainerNode*);
+ void nodeChildrenWillBeRemoved(ContainerNode&);
// nodeWillBeRemoved is only safe when removing one node at a time.
void nodeWillBeRemoved(Node&);
bool canReplaceChild(const Node& newChild, const Node& oldChild) const;
void didInsertText(Node*, unsigned offset, unsigned length);
void didRemoveText(Node*, unsigned offset, unsigned length);
- void didMergeTextNodes(Text* oldNode, unsigned offset);
- void didSplitTextNode(Text* oldNode);
+ void didMergeTextNodes(Text& oldNode, unsigned offset);
+ void didSplitTextNode(Text& oldNode);
void clearDOMWindow() { m_domWindow = 0; }
DOMWindow* domWindow() const { return m_domWindow; }
@@ -783,7 +785,7 @@
// have been calculated on the fly (without associating it with the actual element) somewhere.
Element* viewportDefiningElement(RenderStyle* rootStyle = 0) const;
- DocumentMarkerController* markers() const { return m_markers.get(); }
+ DocumentMarkerController& markers() const { return *m_markers; }
bool directionSetOnDocumentElement() const { return m_directionSetOnDocumentElement; }
bool writingModeSetOnDocumentElement() const { return m_writingModeSetOnDocumentElement; }
@@ -806,7 +808,7 @@
bool inDesignMode() const;
Document* parentDocument() const;
- Document* topDocument() const;
+ Document& topDocument() const;
WeakPtr<Document> contextDocument();
ScriptRunner* scriptRunner() { return m_scriptRunner.get(); }
@@ -841,8 +843,8 @@
void cancelFocusAppearanceUpdate();
// Extension for manipulating canvas drawing contexts for use in CSS
- CanvasRenderingContext* getCSSCanvasContext(const String& type, const String& name, int width, int height);
- HTMLCanvasElement* getCSSCanvasElement(const String& name);
+ void getCSSCanvasContext(const String& type, const String& name, int width, int height, bool&, RefPtr<CanvasRenderingContext2D>&, bool&, RefPtr<WebGLRenderingContext>&);
+ HTMLCanvasElement& getCSSCanvasElement(const String& name);
bool isDNSPrefetchEnabled() const { return m_isDNSPrefetchEnabled; }
void parseDNSPrefetchControlHeader(const String&);
@@ -874,7 +876,7 @@
virtual void removeAllEventListeners() OVERRIDE FINAL;
const SVGDocumentExtensions* svgExtensions();
- SVGDocumentExtensions* accessSVGExtensions();
+ SVGDocumentExtensions& accessSVGExtensions();
void initSecurityContext();
void initSecurityContext(const DocumentInit&);
@@ -926,10 +928,10 @@
bool isDelayingLoadEvent() const { return m_loadEventDelayCount; }
void loadPluginsSoon();
- PassRefPtr<Touch> createTouch(DOMWindow*, EventTarget*, int identifier, int pageX, int pageY, int screenX, int screenY, int radiusX, int radiusY, float rotationAngle, float force) const;
- PassRefPtr<TouchList> createTouchList(Vector<RefPtr<Touch> >&) const;
+ PassRefPtrWillBeRawPtr<Touch> createTouch(DOMWindow*, EventTarget*, int identifier, int pageX, int pageY, int screenX, int screenY, int radiusX, int radiusY, float rotationAngle, float force) const;
+ PassRefPtrWillBeRawPtr<TouchList> createTouchList(WillBeHeapVector<RefPtrWillBeMember<Touch> >&) const;
- const DocumentTiming* timing() const { return &m_documentTiming; }
+ const DocumentTiming& timing() const { return m_documentTiming; }
int requestAnimationFrame(PassOwnPtr<RequestAnimationFrameCallback>);
void cancelAnimationFrame(int id);
@@ -986,8 +988,8 @@
void incrementActiveParserCount() { ++m_activeParserCount; }
void decrementActiveParserCount();
- void setContextFeatures(PassRefPtr<ContextFeatures>);
- ContextFeatures* contextFeatures() const { return m_contextFeatures.get(); }
+ void setContextFeatures(ContextFeatures&);
+ ContextFeatures& contextFeatures() const { return *m_contextFeatures; }
ElementDataCache* elementDataCache() { return m_elementDataCache.get(); }
@@ -1001,8 +1003,8 @@
Locale& getCachedLocale(const AtomicString& locale = nullAtom);
AnimationClock& animationClock() { return *m_animationClock; }
- DocumentTimeline* timeline() const { return m_timeline.get(); }
- DocumentTimeline* transitionTimeline() const { return m_transitionTimeline.get(); }
+ DocumentTimeline& timeline() const { return *m_timeline; }
+ DocumentTimeline& transitionTimeline() const { return *m_transitionTimeline; }
CSSPendingAnimations& cssPendingAnimations() { return m_cssPendingAnimations; }
void addToTopLayer(Element*, const Element* before = 0);
@@ -1021,7 +1023,7 @@
virtual DOMWindow* executingWindow() OVERRIDE FINAL;
virtual void userEventWasHandled() OVERRIDE FINAL { resetLastHandledUserGestureTimestamp(); }
- Frame* executingFrame();
+ LocalFrame* executingFrame();
DocumentLifecycleNotifier& lifecycleNotifier();
DocumentLifecycle& lifecycle() { return m_lifecycle; }
@@ -1048,6 +1050,8 @@
// process. See http://crbug.com/339659.
virtual void defaultEventHandler(Event*) OVERRIDE;
+ void updateStyleInvalidationIfNeeded();
+
protected:
Document(const DocumentInit&, DocumentClassFlags = DefaultDocumentClass);
@@ -1059,6 +1063,8 @@
virtual PassRefPtr<Document> cloneDocumentWithoutChildren();
+ bool importContainerNodeChildren(ContainerNode* oldContainerNode, PassRefPtr<ContainerNode> newContainerNode, ExceptionState&);
+
private:
friend class Node;
friend class IgnoreDestructiveWriteCountIncrementer;
@@ -1070,7 +1076,6 @@
void inheritHtmlAndBodyElementStyles(StyleRecalcChange);
void updateDistributionIfNeeded();
- void updateStyleInvalidationIfNeeded();
void updateUseShadowTreesIfNeeded();
void updateStyle(StyleRecalcChange);
@@ -1119,7 +1124,7 @@
PassRefPtr<HTMLCollection> ensureCachedCollection(CollectionType);
// Note that dispatching a window load event may cause the DOMWindow to be detached from
- // the Frame, so callers should take a reference to the DOMWindow (which owns us) to
+ // the LocalFrame, so callers should take a reference to the DOMWindow (which owns us) to
// prevent the Document from getting blown away from underneath them.
void dispatchWindowLoadEvent();
@@ -1154,7 +1159,7 @@
// do eventually load.
PendingSheetLayout m_pendingSheetLayout;
- Frame* m_frame;
+ LocalFrame* m_frame;
DOMWindow* m_domWindow;
HTMLImport* m_import;
@@ -1204,8 +1209,8 @@
MutationObserverOptions m_mutationObserverTypes;
- OwnPtr<StyleEngine> m_styleEngine;
- RefPtr<StyleSheetList> m_styleSheetList;
+ OwnPtrWillBePersistent<StyleEngine> m_styleEngine;
+ RefPtrWillBePersistent<StyleSheetList> m_styleSheetList;
OwnPtr<FormController> m_formController;
@@ -1215,6 +1220,7 @@
bool m_visuallyOrdered;
ReadyState m_readyState;
bool m_isParsing;
+ bool m_historyItemDocumentStateDirty;
bool m_gotoAnchorNeededAfterStylesheetsLoad;
bool m_isDNSPrefetchEnabled;
@@ -1304,7 +1310,7 @@
bool m_directionSetOnDocumentElement;
bool m_writingModeSetOnDocumentElement;
DocumentTiming m_documentTiming;
- RefPtr<MediaQueryMatcher> m_mediaQueryMatcher;
+ RefPtrWillBePersistent<MediaQueryMatcher> m_mediaQueryMatcher;
bool m_writeRecursionIsTooDeep;
unsigned m_writeRecursionDepth;
diff --git a/Source/core/dom/Document.idl b/Source/core/dom/Document.idl
index 158f5bb..e61390b 100644
--- a/Source/core/dom/Document.idl
+++ b/Source/core/dom/Document.idl
@@ -20,6 +20,8 @@
callback CustomElementConstructor = Element ();
+typedef (CanvasRenderingContext2D or WebGLRenderingContext) RenderingContext;
+
[
SpecialWrapFor=HTMLDocument|XMLDocument
] interface Document : Node {
@@ -139,9 +141,9 @@
// WebKit extensions
[TreatReturnedNullStringAs=Null] readonly attribute DOMString preferredStylesheetSet;
- [TreatReturnedNullStringAs=Null, TreatNullAs=NullString] attribute DOMString selectedStylesheetSet;
+ [TreatReturnedNullStringAs=Null, TreatNullAs=NullString] attribute DOMString selectedStylesheetSet;
- CanvasRenderingContext getCSSCanvasContext(DOMString contextId, DOMString name, long width, long height);
+ RenderingContext getCSSCanvasContext(DOMString contextId, DOMString name, long width, long height);
// HTML 5
HTMLCollection getElementsByClassName(DOMString classNames);
diff --git a/Source/core/dom/DocumentFullscreen.cpp b/Source/core/dom/DocumentFullscreen.cpp
index 407e55d..b1f88cd 100644
--- a/Source/core/dom/DocumentFullscreen.cpp
+++ b/Source/core/dom/DocumentFullscreen.cpp
@@ -30,47 +30,47 @@
namespace WebCore {
-bool DocumentFullscreen::webkitIsFullScreen(Document* document)
+bool DocumentFullscreen::webkitIsFullScreen(Document& document)
{
if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(document))
return fullscreen->webkitIsFullScreen();
return false;
}
-bool DocumentFullscreen::webkitFullScreenKeyboardInputAllowed(Document* document)
+bool DocumentFullscreen::webkitFullScreenKeyboardInputAllowed(Document& document)
{
if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(document))
return fullscreen->webkitFullScreenKeyboardInputAllowed();
return false;
}
-Element* DocumentFullscreen::webkitCurrentFullScreenElement(Document* document)
+Element* DocumentFullscreen::webkitCurrentFullScreenElement(Document& document)
{
if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(document))
return fullscreen->webkitCurrentFullScreenElement();
return 0;
}
-void DocumentFullscreen::webkitCancelFullScreen(Document* document)
+void DocumentFullscreen::webkitCancelFullScreen(Document& document)
{
- FullscreenElementStack::from(document)->webkitCancelFullScreen();
+ FullscreenElementStack::from(document).webkitCancelFullScreen();
}
-bool DocumentFullscreen::webkitFullscreenEnabled(Document* document)
+bool DocumentFullscreen::webkitFullscreenEnabled(Document& document)
{
return FullscreenElementStack::webkitFullscreenEnabled(document);
}
-Element* DocumentFullscreen::webkitFullscreenElement(Document* document)
+Element* DocumentFullscreen::webkitFullscreenElement(Document& document)
{
if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(document))
return fullscreen->webkitFullscreenElement();
return 0;
}
-void DocumentFullscreen::webkitExitFullscreen(Document* document)
+void DocumentFullscreen::webkitExitFullscreen(Document& document)
{
- FullscreenElementStack::from(document)->webkitExitFullscreen();
+ FullscreenElementStack::from(document).webkitExitFullscreen();
}
} // namespace WebCore
diff --git a/Source/core/dom/DocumentFullscreen.h b/Source/core/dom/DocumentFullscreen.h
index ff5338d..01a5ac9 100644
--- a/Source/core/dom/DocumentFullscreen.h
+++ b/Source/core/dom/DocumentFullscreen.h
@@ -33,14 +33,14 @@
class DocumentFullscreen {
public:
- static bool webkitIsFullScreen(Document*);
- static bool webkitFullScreenKeyboardInputAllowed(Document*);
- static Element* webkitCurrentFullScreenElement(Document*);
- static void webkitCancelFullScreen(Document*);
+ static bool webkitIsFullScreen(Document&);
+ static bool webkitFullScreenKeyboardInputAllowed(Document&);
+ static Element* webkitCurrentFullScreenElement(Document&);
+ static void webkitCancelFullScreen(Document&);
- static bool webkitFullscreenEnabled(Document*);
- static Element* webkitFullscreenElement(Document*);
- static void webkitExitFullscreen(Document*);
+ static bool webkitFullscreenEnabled(Document&);
+ static Element* webkitFullscreenElement(Document&);
+ static void webkitExitFullscreen(Document&);
};
} // namespace WebCore
diff --git a/Source/core/dom/DocumentFullscreen.idl b/Source/core/dom/DocumentFullscreen.idl
index 917d481..6e9a236 100644
--- a/Source/core/dom/DocumentFullscreen.idl
+++ b/Source/core/dom/DocumentFullscreen.idl
@@ -19,9 +19,7 @@
* Boston, MA 02110-1301, USA.
*/
-[
- RuntimeEnabled=Fullscreen,
-] partial interface Document {
+partial interface Document {
// Mozilla version
readonly attribute boolean webkitIsFullScreen;
readonly attribute boolean webkitFullScreenKeyboardInputAllowed;
diff --git a/Source/core/dom/DocumentInit.cpp b/Source/core/dom/DocumentInit.cpp
index 0c3013a..922ad7e 100644
--- a/Source/core/dom/DocumentInit.cpp
+++ b/Source/core/dom/DocumentInit.cpp
@@ -31,13 +31,13 @@
#include "RuntimeEnabledFeatures.h"
#include "core/dom/Document.h"
#include "core/dom/custom/CustomElementRegistrationContext.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLFrameOwnerElement.h"
-#include "core/html/HTMLImportsController.h"
-#include "core/frame/Frame.h"
+#include "core/html/imports/HTMLImportsController.h"
namespace WebCore {
-static Document* parentDocument(Frame* frame)
+static Document* parentDocument(LocalFrame* frame)
{
if (!frame)
return 0;
@@ -48,12 +48,12 @@
}
-static Document* ownerDocument(Frame* frame)
+static Document* ownerDocument(LocalFrame* frame)
{
if (!frame)
return 0;
- Frame* ownerFrame = frame->tree().parent();
+ LocalFrame* ownerFrame = frame->tree().parent();
if (!ownerFrame)
ownerFrame = frame->loader().opener();
if (!ownerFrame)
@@ -61,7 +61,7 @@
return ownerFrame->document();
}
-DocumentInit::DocumentInit(const KURL& url, Frame* frame, WeakPtr<Document> contextDocument, HTMLImport* import)
+DocumentInit::DocumentInit(const KURL& url, LocalFrame* frame, WeakPtr<Document> contextDocument, HTMLImport* import)
: m_url(url)
, m_frame(frame)
, m_parent(parentDocument(frame))
@@ -90,7 +90,7 @@
bool DocumentInit::shouldSetURL() const
{
- Frame* frame = frameForSecurityContext();
+ LocalFrame* frame = frameForSecurityContext();
return (frame && frame->ownerElement()) || !m_url.isEmpty();
}
@@ -99,7 +99,7 @@
return m_parent && m_frame->loader().shouldTreatURLAsSrcdocDocument(m_url);
}
-Frame* DocumentInit::frameForSecurityContext() const
+LocalFrame* DocumentInit::frameForSecurityContext() const
{
if (m_frame)
return m_frame;
@@ -142,7 +142,7 @@
PassRefPtr<CustomElementRegistrationContext> DocumentInit::registrationContext(Document* document) const
{
if (!document->isHTMLDocument() && !document->isXHTMLDocument())
- return 0;
+ return nullptr;
if (m_createNewRegistrationContext)
return CustomElementRegistrationContext::create();
diff --git a/Source/core/dom/DocumentInit.h b/Source/core/dom/DocumentInit.h
index 9bc28cd..bd5f7f6 100644
--- a/Source/core/dom/DocumentInit.h
+++ b/Source/core/dom/DocumentInit.h
@@ -39,18 +39,18 @@
class CustomElementRegistrationContext;
class Document;
-class Frame;
+class LocalFrame;
class HTMLImport;
class Settings;
class DocumentInit {
public:
- explicit DocumentInit(const KURL& = KURL(), Frame* = 0, WeakPtr<Document> = WeakPtr<Document>(), HTMLImport* = 0);
+ explicit DocumentInit(const KURL& = KURL(), LocalFrame* = 0, WeakPtr<Document> = WeakPtr<Document>(), HTMLImport* = 0);
DocumentInit(const DocumentInit&);
~DocumentInit();
const KURL& url() const { return m_url; }
- Frame* frame() const { return m_frame; }
+ LocalFrame* frame() const { return m_frame; }
HTMLImport* import() const { return m_import; }
bool hasSecurityContext() const { return frameForSecurityContext(); }
@@ -62,7 +62,7 @@
Document* parent() const { return m_parent.get(); }
Document* owner() const { return m_owner.get(); }
KURL parentBaseURL() const;
- Frame* ownerFrame() const;
+ LocalFrame* ownerFrame() const;
Settings* settings() const;
DocumentInit& withRegistrationContext(CustomElementRegistrationContext*);
@@ -73,10 +73,10 @@
static DocumentInit fromContext(WeakPtr<Document> contextDocument, const KURL& = KURL());
private:
- Frame* frameForSecurityContext() const;
+ LocalFrame* frameForSecurityContext() const;
KURL m_url;
- Frame* m_frame;
+ LocalFrame* m_frame;
RefPtr<Document> m_parent;
RefPtr<Document> m_owner;
WeakPtr<Document> m_contextDocument;
diff --git a/Source/core/dom/DocumentMarker.cpp b/Source/core/dom/DocumentMarker.cpp
index 5796c8e..a37e522 100644
--- a/Source/core/dom/DocumentMarker.cpp
+++ b/Source/core/dom/DocumentMarker.cpp
@@ -117,7 +117,7 @@
: m_type(type)
, m_startOffset(startOffset)
, m_endOffset(endOffset)
- , m_details(description.isEmpty() ? 0 : DocumentMarkerDescription::create(description))
+ , m_details(description.isEmpty() ? nullptr : DocumentMarkerDescription::create(description))
, m_hash(0)
{
}
@@ -126,7 +126,7 @@
: m_type(type)
, m_startOffset(startOffset)
, m_endOffset(endOffset)
- , m_details(description.isEmpty() ? 0 : DocumentMarkerDescription::create(description))
+ , m_details(description.isEmpty() ? nullptr : DocumentMarkerDescription::create(description))
, m_hash(hash)
{
}
diff --git a/Source/core/dom/DocumentMarkerControllerTest.cpp b/Source/core/dom/DocumentMarkerControllerTest.cpp
index f7132ed..b218814 100644
--- a/Source/core/dom/DocumentMarkerControllerTest.cpp
+++ b/Source/core/dom/DocumentMarkerControllerTest.cpp
@@ -51,7 +51,7 @@
virtual void SetUp() OVERRIDE;
Document& document() const { return *m_document; }
- DocumentMarkerController& markerController() const { return *m_document->markers(); }
+ DocumentMarkerController& markerController() const { return m_document->markers(); }
PassRefPtr<Text> createTextNode(const char*);
void markNodeContents(PassRefPtr<Node>);
diff --git a/Source/core/dom/DocumentOrderedMap.cpp b/Source/core/dom/DocumentOrderedMap.cpp
index cd28b03..5989a2b 100644
--- a/Source/core/dom/DocumentOrderedMap.cpp
+++ b/Source/core/dom/DocumentOrderedMap.cpp
@@ -41,24 +41,24 @@
using namespace HTMLNames;
-inline bool keyMatchesId(StringImpl* key, Element* element)
+inline bool keyMatchesId(StringImpl* key, Element& element)
{
- return element->getIdAttribute().impl() == key;
+ return element.getIdAttribute().impl() == key;
}
-inline bool keyMatchesMapName(StringImpl* key, Element* element)
+inline bool keyMatchesMapName(StringImpl* key, Element& element)
{
- return element->hasTagName(mapTag) && toHTMLMapElement(element)->getName().impl() == key;
+ return isHTMLMapElement(element) && toHTMLMapElement(element).getName().impl() == key;
}
-inline bool keyMatchesLowercasedMapName(StringImpl* key, Element* element)
+inline bool keyMatchesLowercasedMapName(StringImpl* key, Element& element)
{
- return element->hasTagName(mapTag) && toHTMLMapElement(element)->getName().lower().impl() == key;
+ return isHTMLMapElement(element) && toHTMLMapElement(element).getName().lower().impl() == key;
}
-inline bool keyMatchesLabelForAttribute(StringImpl* key, Element* element)
+inline bool keyMatchesLabelForAttribute(StringImpl* key, Element& element)
{
- return element->hasTagName(labelTag) && element->getAttribute(forAttr).impl() == key;
+ return isHTMLLabelElement(element) && element.getAttribute(forAttr).impl() == key;
}
void DocumentOrderedMap::add(StringImpl* key, Element* element)
@@ -101,7 +101,7 @@
}
}
-template<bool keyMatches(StringImpl*, Element*)>
+template<bool keyMatches(StringImpl*, Element&)>
inline Element* DocumentOrderedMap::get(StringImpl* key, const TreeScope* scope) const
{
ASSERT(key);
@@ -117,7 +117,7 @@
// We know there's at least one node that matches; iterate to find the first one.
for (Element* element = ElementTraversal::firstWithin(scope->rootNode()); element; element = ElementTraversal::next(*element)) {
- if (!keyMatches(key, element))
+ if (!keyMatches(key, *element))
continue;
entry->element = element;
return element;
@@ -148,7 +148,7 @@
entry->orderedList.reserveCapacity(entry->count);
for (Element* element = entry->element ? entry->element : ElementTraversal::firstWithin(scope->rootNode()); entry->orderedList.size() < entry->count; element = ElementTraversal::next(*element)) {
ASSERT(element);
- if (!keyMatchesId(key, element))
+ if (!keyMatchesId(key, *element))
continue;
entry->orderedList.uncheckedAppend(element);
}
diff --git a/Source/core/dom/DocumentOrderedMap.h b/Source/core/dom/DocumentOrderedMap.h
index 19c470e..fdcf438 100644
--- a/Source/core/dom/DocumentOrderedMap.h
+++ b/Source/core/dom/DocumentOrderedMap.h
@@ -55,7 +55,7 @@
Element* getElementByLabelForAttribute(StringImpl*, const TreeScope*) const;
private:
- template<bool keyMatches(StringImpl*, Element*)> Element* get(StringImpl*, const TreeScope*) const;
+ template<bool keyMatches(StringImpl*, Element&)> Element* get(StringImpl*, const TreeScope*) const;
struct MapEntry {
explicit MapEntry(Element* firstElement)
diff --git a/Source/core/dom/DocumentStyleSheetCollection.cpp b/Source/core/dom/DocumentStyleSheetCollection.cpp
index c252e12..7d86028 100644
--- a/Source/core/dom/DocumentStyleSheetCollection.cpp
+++ b/Source/core/dom/DocumentStyleSheetCollection.cpp
@@ -81,6 +81,9 @@
Document* document = candidate.importedDocument();
if (!document)
continue;
+ if (collector.hasVisited(document))
+ continue;
+ collector.willVisit(document);
document->styleEngine()->updateStyleSheetsInImport(collector);
continue;
}
diff --git a/Source/core/dom/DocumentStyleSheetCollector.cpp b/Source/core/dom/DocumentStyleSheetCollector.cpp
index f3dd8a6..a624b53 100644
--- a/Source/core/dom/DocumentStyleSheetCollector.cpp
+++ b/Source/core/dom/DocumentStyleSheetCollector.cpp
@@ -33,9 +33,10 @@
namespace WebCore {
-DocumentStyleSheetCollector::DocumentStyleSheetCollector(Vector<RefPtr<StyleSheet> >& sheetsForList, Vector<RefPtr<CSSStyleSheet> >& activeList)
+DocumentStyleSheetCollector::DocumentStyleSheetCollector(WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& sheetsForList, WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& activeList, HashSet<Document*>& visitedDocuments)
: m_styleSheetsForStyleSheetList(sheetsForList)
, m_activeAuthorStyleSheets(activeList)
+ , m_visitedDocuments(visitedDocuments)
{
}
@@ -43,9 +44,9 @@
{
}
-void DocumentStyleSheetCollector::appendActiveStyleSheets(const Vector<RefPtr<CSSStyleSheet> >& sheets)
+void DocumentStyleSheetCollector::appendActiveStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& sheets)
{
- m_activeAuthorStyleSheets.append(sheets);
+ m_activeAuthorStyleSheets.appendVector(sheets);
}
void DocumentStyleSheetCollector::appendActiveStyleSheet(CSSStyleSheet* sheet)
@@ -59,12 +60,12 @@
}
ActiveDocumentStyleSheetCollector::ActiveDocumentStyleSheetCollector(StyleSheetCollection& collection)
- : DocumentStyleSheetCollector(collection.m_styleSheetsForStyleSheetList, collection.m_activeAuthorStyleSheets)
+ : DocumentStyleSheetCollector(collection.m_styleSheetsForStyleSheetList, collection.m_activeAuthorStyleSheets, m_visitedDocuments)
{
}
-ImportedDocumentStyleSheetCollector::ImportedDocumentStyleSheetCollector(DocumentStyleSheetCollector& collector, Vector<RefPtr<StyleSheet> >& sheetForList)
- : DocumentStyleSheetCollector(sheetForList, collector.m_activeAuthorStyleSheets)
+ImportedDocumentStyleSheetCollector::ImportedDocumentStyleSheetCollector(DocumentStyleSheetCollector& collector, WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& sheetForList)
+ : DocumentStyleSheetCollector(sheetForList, collector.m_activeAuthorStyleSheets, collector.m_visitedDocuments)
{
}
diff --git a/Source/core/dom/DocumentStyleSheetCollector.h b/Source/core/dom/DocumentStyleSheetCollector.h
index fef627c..531970e 100644
--- a/Source/core/dom/DocumentStyleSheetCollector.h
+++ b/Source/core/dom/DocumentStyleSheetCollector.h
@@ -27,39 +27,52 @@
#ifndef DocumentStyleSheetCollector_h
#define DocumentStyleSheetCollector_h
+#include "heap/Handle.h"
+#include "wtf/HashSet.h"
#include "wtf/RefPtr.h"
#include "wtf/Vector.h"
namespace WebCore {
class CSSStyleSheet;
+class Document;
class StyleSheet;
class StyleSheetCollection;
class DocumentStyleSheetCollector {
+ // This class contains references to two on-heap collections, therefore
+ // it's unhealthy to have it anywhere but on the stack, where stack
+ // scanning will keep them alive.
+ STACK_ALLOCATED();
public:
friend class ImportedDocumentStyleSheetCollector;
- DocumentStyleSheetCollector(Vector<RefPtr<StyleSheet> >& sheetsForList, Vector<RefPtr<CSSStyleSheet> >& activeList);
+ DocumentStyleSheetCollector(WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& sheetsForList, WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& activeList, HashSet<Document*>&);
~DocumentStyleSheetCollector();
- void appendActiveStyleSheets(const Vector<RefPtr<CSSStyleSheet> >&);
+ void appendActiveStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >&);
void appendActiveStyleSheet(CSSStyleSheet*);
void appendSheetForList(StyleSheet*);
+ bool hasVisited(Document* document) const { return m_visitedDocuments.contains(document); }
+ void willVisit(Document* document) { m_visitedDocuments.add(document); }
+
private:
- Vector<RefPtr<StyleSheet> >& m_styleSheetsForStyleSheetList;
- Vector<RefPtr<CSSStyleSheet> >& m_activeAuthorStyleSheets;
+ WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& m_styleSheetsForStyleSheetList;
+ WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& m_activeAuthorStyleSheets;
+ HashSet<Document*>& m_visitedDocuments;
};
class ActiveDocumentStyleSheetCollector FINAL : public DocumentStyleSheetCollector {
public:
ActiveDocumentStyleSheetCollector(StyleSheetCollection&);
+private:
+ HashSet<Document*> m_visitedDocuments;
};
class ImportedDocumentStyleSheetCollector FINAL : public DocumentStyleSheetCollector {
public:
- ImportedDocumentStyleSheetCollector(DocumentStyleSheetCollector&, Vector<RefPtr<StyleSheet> >&);
+ ImportedDocumentStyleSheetCollector(DocumentStyleSheetCollector&, WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >&);
};
} // namespace WebCore
diff --git a/Source/core/dom/DocumentType.cpp b/Source/core/dom/DocumentType.cpp
index 7c392a7..e4b02d8 100644
--- a/Source/core/dom/DocumentType.cpp
+++ b/Source/core/dom/DocumentType.cpp
@@ -71,7 +71,7 @@
void DocumentType::removedFrom(ContainerNode* insertionPoint)
{
- document().setDoctype(0);
+ document().setDoctype(nullptr);
Node::removedFrom(insertionPoint);
}
diff --git a/Source/core/dom/DocumentType.idl b/Source/core/dom/DocumentType.idl
index 330aa72..bafdfc7 100644
--- a/Source/core/dom/DocumentType.idl
+++ b/Source/core/dom/DocumentType.idl
@@ -25,8 +25,8 @@
// DOM Level 2
- [TreatReturnedNullStringAs=Null] readonly attribute DOMString publicId;
- [TreatReturnedNullStringAs=Null] readonly attribute DOMString systemId;
+ readonly attribute DOMString publicId;
+ readonly attribute DOMString systemId;
[TreatReturnedNullStringAs=Null, MeasureAs=DocumentTypeInternalSubset] readonly attribute DOMString internalSubset; // Removed from DOM4.
};
diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp
index 5f2ae80..1b88ddb 100644
--- a/Source/core/dom/Element.cpp
+++ b/Source/core/dom/Element.cpp
@@ -31,10 +31,12 @@
#include "SVGNames.h"
#include "XMLNames.h"
#include "bindings/v8/Dictionary.h"
+#include "bindings/v8/ExceptionMessages.h"
#include "bindings/v8/ExceptionState.h"
#include "core/accessibility/AXObjectCache.h"
#include "core/animation/DocumentTimeline.h"
#include "core/animation/css/CSSAnimations.h"
+#include "core/css/CSSImageValue.h"
#include "core/css/CSSStyleSheet.h"
#include "core/css/CSSValuePool.h"
#include "core/css/PropertySetCSSStyleDeclaration.h"
@@ -61,6 +63,7 @@
#include "core/dom/RenderTreeBuilder.h"
#include "core/dom/ScriptableDocumentParser.h"
#include "core/dom/SelectorQuery.h"
+#include "core/dom/SiblingRuleHelper.h"
#include "core/dom/Text.h"
#include "core/dom/custom/CustomElement.h"
#include "core/dom/custom/CustomElementRegistrationContext.h"
@@ -72,10 +75,10 @@
#include "core/editing/markup.h"
#include "core/events/EventDispatcher.h"
#include "core/events/FocusEvent.h"
-#include "core/frame/ContentSecurityPolicy.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/frame/UseCounter.h"
+#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/ClassList.h"
#include "core/html/HTMLCollection.h"
#include "core/html/HTMLDocument.h"
@@ -208,7 +211,7 @@
detachAllAttrNodesFromElement();
if (hasPendingResources()) {
- document().accessSVGExtensions()->removeElementFromPendingResources(this);
+ document().accessSVGExtensions().removeElementFromPendingResources(this);
ASSERT(!hasPendingResources());
}
}
@@ -306,12 +309,12 @@
PassRefPtr<Attr> Element::detachAttribute(size_t index)
{
ASSERT(elementData());
- const Attribute* attribute = elementData()->attributeItem(index);
- RefPtr<Attr> attrNode = attrIfExists(attribute->name());
+ const Attribute& attribute = elementData()->attributeItem(index);
+ RefPtr<Attr> attrNode = attrIfExists(attribute.name());
if (attrNode)
detachAttrNodeAtIndex(attrNode.get(), index);
else {
- attrNode = Attr::create(document(), attribute->name(), attribute->value());
+ attrNode = Attr::create(document(), attribute.name(), attribute.value());
removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
}
return attrNode.release();
@@ -322,10 +325,9 @@
ASSERT(attr);
ASSERT(elementData());
- const Attribute* attribute = elementData()->attributeItem(index);
- ASSERT(attribute);
- ASSERT(attribute->name() == attr->qualifiedName());
- detachAttrNodeFromElementWithValue(attr, attribute->value());
+ const Attribute& attribute = elementData()->attributeItem(index);
+ ASSERT(attribute.name() == attr->qualifiedName());
+ detachAttrNodeFromElementWithValue(attr, attribute.value());
removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
}
@@ -366,12 +368,12 @@
return 0;
}
-ActiveAnimations* Element::ensureActiveAnimations()
+ActiveAnimations& Element::ensureActiveAnimations()
{
ElementRareData& rareData = ensureElementRareData();
if (!rareData.activeAnimations())
rareData.setActiveAnimations(adoptPtr(new ActiveAnimations()));
- return rareData.activeAnimations();
+ return *rareData.activeAnimations();
}
bool Element::hasActiveAnimations() const
@@ -554,7 +556,7 @@
int Element::offsetLeft()
{
- document().partialUpdateLayoutIgnorePendingStylesheets(this);
+ document().updateLayoutIgnorePendingStylesheets();
if (RenderBoxModelObject* renderer = renderBoxModelObject())
return adjustForLocalZoom(renderer->pixelSnappedOffsetLeft(), *renderer);
return 0;
@@ -562,7 +564,7 @@
int Element::offsetTop()
{
- document().partialUpdateLayoutIgnorePendingStylesheets(this);
+ document().updateLayoutIgnorePendingStylesheets();
if (RenderBoxModelObject* renderer = renderBoxModelObject())
return adjustForLocalZoom(renderer->pixelSnappedOffsetTop(), *renderer);
return 0;
@@ -577,7 +579,7 @@
return adjustLayoutUnitForAbsoluteZoom(renderer->fixedOffsetWidth(), *renderer).round();
}
- document().partialUpdateLayoutIgnorePendingStylesheets(this);
+ document().updateLayoutIgnorePendingStylesheets();
if (RenderBoxModelObject* renderer = renderBoxModelObject())
return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedOffsetWidth(), *renderer).round();
return 0;
@@ -585,7 +587,7 @@
int Element::offsetHeight()
{
- document().partialUpdateLayoutIgnorePendingStylesheets(this);
+ document().updateLayoutIgnorePendingStylesheets();
if (RenderBoxModelObject* renderer = renderBoxModelObject())
return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedOffsetHeight(), *renderer).round();
return 0;
@@ -726,7 +728,7 @@
if (document().inQuirksMode())
return;
- Frame* frame = document().frame();
+ LocalFrame* frame = document().frame();
if (!frame)
return;
FrameView* view = frame->view();
@@ -772,7 +774,7 @@
if (document().inQuirksMode())
return;
- Frame* frame = document().frame();
+ LocalFrame* frame = document().frame();
if (!frame)
return;
FrameView* view = frame->view();
@@ -932,7 +934,7 @@
const AtomicString& caseAdjustedLocalName = shouldIgnoreAttributeCase() ? localName.lower() : localName;
size_t index = elementData() ? elementData()->getAttributeItemIndex(caseAdjustedLocalName, false) : kNotFound;
- const QualifiedName& qName = index != kNotFound ? attributeItem(index)->name() : QualifiedName(nullAtom, caseAdjustedLocalName, nullAtom);
+ const QualifiedName& qName = index != kNotFound ? attributeItem(index).name() : QualifiedName(nullAtom, caseAdjustedLocalName, nullAtom);
setAttributeInternal(index, qName, value, NotInSynchronizationOfLazyAttribute);
}
@@ -962,20 +964,20 @@
return;
}
- const Attribute* existingAttribute = attributeItem(index);
- QualifiedName existingAttributeName = existingAttribute->name();
+ const Attribute& existingAttribute = attributeItem(index);
+ QualifiedName existingAttributeName = existingAttribute.name();
if (!inSynchronizationOfLazyAttribute)
- willModifyAttribute(existingAttributeName, existingAttribute->value(), newValue);
+ willModifyAttribute(existingAttributeName, existingAttribute.value(), newValue);
- if (newValue != existingAttribute->value()) {
+ if (newValue != existingAttribute.value()) {
// If there is an Attr node hooked to this attribute, the Attr::setValue() call below
// will write into the ElementData.
// FIXME: Refactor this so it makes some sense.
- if (RefPtr<Attr> attrNode = inSynchronizationOfLazyAttribute ? 0 : attrIfExists(existingAttributeName))
+ if (RefPtr<Attr> attrNode = inSynchronizationOfLazyAttribute ? nullptr : attrIfExists(existingAttributeName))
attrNode->setValue(newValue);
else
- ensureUniqueElementData()->attributeItem(index)->setValue(newValue);
+ ensureUniqueElementData().attributeItem(index).setValue(newValue);
}
if (!inSynchronizationOfLazyAttribute)
@@ -1026,12 +1028,14 @@
AtomicString newId = makeIdForStyleResolution(newValue, document().inQuirksMode());
if (newId != oldId) {
elementData()->setIdForStyleResolution(newId);
- shouldInvalidateStyle = testShouldInvalidateStyle && checkNeedsStyleInvalidationForIdChange(oldId, newId, styleResolver->ensureRuleFeatureSet());
+ shouldInvalidateStyle = testShouldInvalidateStyle && checkNeedsStyleInvalidationForIdChange(oldId, newId, styleResolver->ensureUpdatedRuleFeatureSet());
}
} else if (name == classAttr) {
classAttributeChanged(newValue);
} else if (name == HTMLNames::nameAttr) {
setHasName(!newValue.isNull());
+ } else if (name == HTMLNames::pseudoAttr) {
+ shouldInvalidateStyle |= testShouldInvalidateStyle && isInShadowTree();
}
invalidateNodeListCachesInAncestors(&name, this);
@@ -1085,17 +1089,18 @@
StyleResolver* styleResolver = document().styleResolver();
bool testShouldInvalidateStyle = inActiveDocument() && styleResolver && styleChangeType() < SubtreeStyleChange;
+ ASSERT(elementData());
if (classStringHasClassName(newClassString)) {
const bool shouldFoldCase = document().inQuirksMode();
const SpaceSplitString oldClasses = elementData()->classNames();
elementData()->setClass(newClassString, shouldFoldCase);
const SpaceSplitString& newClasses = elementData()->classNames();
if (testShouldInvalidateStyle)
- styleResolver->ensureRuleFeatureSet().scheduleStyleInvalidationForClassChange(oldClasses, newClasses, this);
+ styleResolver->ensureUpdatedRuleFeatureSet().scheduleStyleInvalidationForClassChange(oldClasses, newClasses, this);
} else {
const SpaceSplitString& oldClasses = elementData()->classNames();
if (testShouldInvalidateStyle)
- styleResolver->ensureRuleFeatureSet().scheduleStyleInvalidationForClassChange(oldClasses, this);
+ styleResolver->ensureUpdatedRuleFeatureSet().scheduleStyleInvalidationForClassChange(oldClasses, this);
elementData()->clearClass();
}
@@ -1246,11 +1251,12 @@
return prefix();
if (hasAttributes()) {
- for (unsigned i = 0; i < attributeCount(); i++) {
- const Attribute* attr = attributeItem(i);
+ unsigned attributeCount = this->attributeCount();
+ for (unsigned i = 0; i < attributeCount; ++i) {
+ const Attribute& attr = attributeItem(i);
- if (attr->prefix() == xmlnsAtom && attr->value() == namespaceToLocate)
- return attr->localName();
+ if (attr.prefix() == xmlnsAtom && attr.value() == namespaceToLocate)
+ return attr.localName();
}
}
@@ -1325,7 +1331,7 @@
if (!nameValue.isNull())
updateName(nullAtom, nameValue);
- if (hasTagName(labelTag)) {
+ if (isHTMLLabelElement(*this)) {
if (scope.shouldCacheLabelsByForAttribute())
updateLabel(scope, nullAtom, fastGetAttribute(forAttr));
}
@@ -1359,7 +1365,7 @@
if (!nameValue.isNull())
updateName(nameValue, nullAtom);
- if (hasTagName(labelTag)) {
+ if (isHTMLLabelElement(*this)) {
TreeScope& treeScope = insertionPoint->treeScope();
if (treeScope.shouldCacheLabelsByForAttribute())
updateLabel(treeScope, fastGetAttribute(forAttr), nullAtom);
@@ -1369,7 +1375,7 @@
ContainerNode::removedFrom(insertionPoint);
if (wasInDocument) {
if (hasPendingResources())
- document().accessSVGExtensions()->removeElementFromPendingResources(this);
+ document().accessSVGExtensions().removeElementFromPendingResources(this);
if (isUpgradedCustomElement())
CustomElement::didLeaveDocument(this, insertionPoint->document());
@@ -1592,8 +1598,11 @@
if (localChange == Reattach) {
AttachContext reattachContext;
reattachContext.resolvedStyle = newStyle.get();
+ bool rendererWillChange = needsAttach() || renderer();
reattach(reattachContext);
- return Reattach;
+ if (rendererWillChange || renderer())
+ return Reattach;
+ return ReattachNoRenderer;
}
ASSERT(oldStyle);
@@ -1647,7 +1656,7 @@
updatePseudoElement(BEFORE, change);
if (change < Force && hasRareData() && childNeedsStyleRecalc())
- checkForChildrenAdjacentRuleChanges();
+ SiblingRuleHelper(this).checkForChildrenAdjacentRuleChanges();
if (change > UpdatePseudoElements || childNeedsStyleRecalc()) {
// This loop is deliberately backwards because we use insertBefore in the rendering tree, and want to avoid
@@ -1678,36 +1687,6 @@
updatePseudoElement(BACKDROP, change);
}
-void Element::checkForChildrenAdjacentRuleChanges()
-{
- bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules();
- bool hasIndirectAdjacentRules = childrenAffectedByForwardPositionalRules();
-
- if (!hasDirectAdjacentRules && !hasIndirectAdjacentRules)
- return;
-
- unsigned forceCheckOfNextElementCount = 0;
- bool forceCheckOfAnyElementSibling = false;
-
- for (Node* child = firstChild(); child; child = child->nextSibling()) {
- if (!child->isElementNode())
- continue;
- Element* element = toElement(child);
- bool childRulesChanged = element->needsStyleRecalc() && element->styleChangeType() >= SubtreeStyleChange;
-
- if (forceCheckOfNextElementCount || forceCheckOfAnyElementSibling)
- element->setNeedsStyleRecalc(SubtreeStyleChange);
-
- if (forceCheckOfNextElementCount)
- forceCheckOfNextElementCount--;
-
- if (childRulesChanged && hasDirectAdjacentRules)
- forceCheckOfNextElementCount = document().styleEngine()->maxDirectAdjacentSelectors();
-
- forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);
- }
-}
-
void Element::updateCallbackSelectors(RenderStyle* oldStyle, RenderStyle* newStyle)
{
Vector<String> emptyVector;
@@ -1771,7 +1750,7 @@
// flag is provided for testing how author shadows interact on these elements.
if (!areAuthorShadowsAllowed() && !RuntimeEnabledFeatures::authorShadowDOMForAnyElementEnabled()) {
exceptionState.throwDOMException(HierarchyRequestError, "Author-created shadow roots are disabled for this element.");
- return 0;
+ return nullptr;
}
return PassRefPtr<ShadowRoot>(ensureShadow().addShadowRoot(*this, ShadowRoot::AuthorShadowRoot));
@@ -1833,7 +1812,7 @@
if (!style && !styleAffectedByEmpty())
return;
- if (!style || (styleAffectedByEmpty() && (!style->emptyState() || hasChildNodes())))
+ if (!style || (styleAffectedByEmpty() && (!style->emptyState() || hasChildren())))
setNeedsStyleRecalc(SubtreeStyleChange);
}
@@ -1973,8 +1952,8 @@
PassRefPtr<Attr> Element::setAttributeNode(Attr* attrNode, ExceptionState& exceptionState)
{
if (!attrNode) {
- exceptionState.throwDOMException(TypeMismatchError, "The node provided is invalid.");
- return 0;
+ exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "Attr"));
+ return nullptr;
}
RefPtr<Attr> oldAttrNode = attrIfExists(attrNode->qualifiedName());
@@ -1985,18 +1964,18 @@
// The DOM user must explicitly clone Attr nodes to re-use them in other elements.
if (attrNode->ownerElement()) {
exceptionState.throwDOMException(InUseAttributeError, "The node provided is an attribute node that is already an attribute of another Element; attribute nodes must be explicitly cloned.");
- return 0;
+ return nullptr;
}
synchronizeAllAttributes();
- UniqueElementData* elementData = ensureUniqueElementData();
+ UniqueElementData& elementData = ensureUniqueElementData();
- size_t index = elementData->getAttributeItemIndex(attrNode->qualifiedName(), shouldIgnoreAttributeCase());
+ size_t index = elementData.getAttributeItemIndex(attrNode->qualifiedName(), shouldIgnoreAttributeCase());
if (index != kNotFound) {
if (oldAttrNode)
- detachAttrNodeFromElementWithValue(oldAttrNode.get(), elementData->attributeItem(index)->value());
+ detachAttrNodeFromElementWithValue(oldAttrNode.get(), elementData.attributeItem(index).value());
else
- oldAttrNode = Attr::create(document(), attrNode->qualifiedName(), elementData->attributeItem(index)->value());
+ oldAttrNode = Attr::create(document(), attrNode->qualifiedName(), elementData.attributeItem(index).value());
}
setAttributeInternal(index, attrNode->qualifiedName(), attrNode->value(), NotInSynchronizationOfLazyAttribute);
@@ -2011,12 +1990,12 @@
PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionState& exceptionState)
{
if (!attr) {
- exceptionState.throwDOMException(TypeMismatchError, "The node provided is invalid.");
- return 0;
+ exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "Attr"));
+ return nullptr;
}
if (attr->ownerElement() != this) {
exceptionState.throwDOMException(NotFoundError, "The node provided is owned by another element.");
- return 0;
+ return nullptr;
}
ASSERT(document() == attr->document());
@@ -2026,7 +2005,7 @@
size_t index = elementData()->getAttrIndex(attr);
if (index == kNotFound) {
exceptionState.throwDOMException(NotFoundError, "The attribute was not found on this element.");
- return 0;
+ return nullptr;
}
RefPtr<Attr> guard(attr);
@@ -2064,10 +2043,10 @@
{
ASSERT_WITH_SECURITY_IMPLICATION(index < attributeCount());
- UniqueElementData* elementData = ensureUniqueElementData();
+ UniqueElementData& elementData = ensureUniqueElementData();
- QualifiedName name = elementData->attributeItem(index)->name();
- AtomicString valueBeingRemoved = elementData->attributeItem(index)->value();
+ QualifiedName name = elementData.attributeItem(index).name();
+ AtomicString valueBeingRemoved = elementData.attributeItem(index).value();
if (!inSynchronizationOfLazyAttribute) {
if (!valueBeingRemoved.isNull())
@@ -2075,9 +2054,9 @@
}
if (RefPtr<Attr> attrNode = attrIfExists(name))
- detachAttrNodeFromElementWithValue(attrNode.get(), elementData->attributeItem(index)->value());
+ detachAttrNodeFromElementWithValue(attrNode.get(), elementData.attributeItem(index).value());
- elementData->removeAttribute(index);
+ elementData.removeAttribute(index);
if (!inSynchronizationOfLazyAttribute)
didRemoveAttribute(name);
@@ -2087,7 +2066,7 @@
{
if (!inSynchronizationOfLazyAttribute)
willModifyAttribute(name, nullAtom, value);
- ensureUniqueElementData()->addAttribute(name, value);
+ ensureUniqueElementData().addAttribute(name, value);
if (!inSynchronizationOfLazyAttribute)
didAddAttribute(name, value);
}
@@ -2116,23 +2095,23 @@
PassRefPtr<Attr> Element::getAttributeNode(const AtomicString& localName)
{
if (!elementData())
- return 0;
+ return nullptr;
synchronizeAttribute(localName);
const Attribute* attribute = elementData()->getAttributeItem(localName, shouldIgnoreAttributeCase());
if (!attribute)
- return 0;
+ return nullptr;
return ensureAttr(attribute->name());
}
PassRefPtr<Attr> Element::getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName)
{
if (!elementData())
- return 0;
+ return nullptr;
QualifiedName qName(nullAtom, localName, namespaceURI);
synchronizeAttribute(qName);
const Attribute* attribute = elementData()->getAttributeItem(qName);
if (!attribute)
- return 0;
+ return nullptr;
return ensureAttr(attribute->name());
}
@@ -2199,7 +2178,7 @@
void Element::updateFocusAppearance(bool /*restorePreviousSelection*/)
{
if (isRootEditableElement()) {
- Frame* frame = document().frame();
+ LocalFrame* frame = document().frame();
if (!frame)
return;
@@ -2223,7 +2202,7 @@
if (doc.page())
doc.page()->focusController().setFocusedElement(0, doc.frame());
else
- doc.setFocusedElement(0);
+ doc.setFocusedElement(nullptr);
}
}
@@ -2282,7 +2261,7 @@
{
if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(html, this, AllowScriptingContent, "innerHTML", exceptionState)) {
ContainerNode* container = this;
- if (hasTagName(templateTag))
+ if (isHTMLTemplateElement(*this))
container = toHTMLTemplateElement(this)->content();
replaceChildrenWithFragment(container, fragment.release(), exceptionState);
}
@@ -2461,16 +2440,11 @@
const AtomicString& Element::shadowPseudoId() const
{
- if (ShadowRoot* root = containingShadowRoot()) {
- if (root->type() == ShadowRoot::UserAgentShadowRoot)
- return fastGetAttribute(pseudoAttr);
- }
- return nullAtom;
+ return getAttribute(pseudoAttr);
}
void Element::setShadowPseudoId(const AtomicString& id)
{
- ASSERT(CSSSelector::parsePseudoType(id) == CSSSelector::PseudoWebKitCustomElement || CSSSelector::parsePseudoType(id) == CSSSelector::PseudoUserAgentCustomElement);
setAttribute(pseudoAttr, id);
}
@@ -2719,8 +2693,10 @@
{
if (!hasAttributes())
return;
+ // attributeCount() cannot be cached before the loop because the attributes
+ // list is altered while iterating.
for (unsigned i = 0; i < attributeCount(); ++i) {
- if (RefPtr<Attr> attr = attrIfExists(attributeItem(i)->name()))
+ if (RefPtr<Attr> attr = attrIfExists(attributeItem(i).name()))
attr->normalize();
}
}
@@ -2746,7 +2722,7 @@
// when RenderObject::isChildAllowed on our parent returns false for the
// PseudoElement's renderer for each style recalc.
if (!renderer() || !pseudoElementRendererIsNeeded(renderer()->getCachedPseudoStyle(pseudoId)))
- elementRareData()->setPseudoElement(pseudoId, 0);
+ elementRareData()->setPseudoElement(pseudoId, nullptr);
} else if (change >= UpdatePseudoElements) {
createPseudoElementIfNeeded(pseudoId);
}
@@ -2791,20 +2767,20 @@
return selectorQuery->matches(*this);
}
-DOMTokenList* Element::classList()
+DOMTokenList& Element::classList()
{
ElementRareData& rareData = ensureElementRareData();
if (!rareData.classList())
rareData.setClassList(ClassList::create(this));
- return rareData.classList();
+ return *rareData.classList();
}
-DOMStringMap* Element::dataset()
+DOMStringMap& Element::dataset()
{
ElementRareData& rareData = ensureElementRareData();
if (!rareData.dataset())
rareData.setDataset(DatasetDOMStringMap::create(this));
- return rareData.dataset();
+ return *rareData.dataset();
}
KURL Element::getURLAttribute(const QualifiedName& name) const
@@ -2869,12 +2845,12 @@
void Element::webkitRequestFullscreen()
{
- FullscreenElementStack::from(&document())->requestFullScreenForElement(this, ALLOW_KEYBOARD_INPUT, FullscreenElementStack::EnforceIFrameAllowFullScreenRequirement);
+ FullscreenElementStack::from(document()).requestFullScreenForElement(this, ALLOW_KEYBOARD_INPUT, FullscreenElementStack::EnforceIFrameAllowFullScreenRequirement);
}
void Element::webkitRequestFullScreen(unsigned short flags)
{
- FullscreenElementStack::from(&document())->requestFullScreenForElement(this, (flags | LEGACY_MOZILLA_REQUEST), FullscreenElementStack::EnforceIFrameAllowFullScreenRequirement);
+ FullscreenElementStack::from(document()).requestFullScreenForElement(this, (flags | LEGACY_MOZILLA_REQUEST), FullscreenElementStack::EnforceIFrameAllowFullScreenRequirement);
}
bool Element::containsFullScreenElement() const
@@ -3011,7 +2987,7 @@
void Element::updateLabel(TreeScope& scope, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue)
{
- ASSERT(hasTagName(labelTag));
+ ASSERT(isHTMLLabelElement(this));
if (!inDocument())
return;
@@ -3027,16 +3003,16 @@
static bool hasSelectorForAttribute(Document* document, const AtomicString& localName)
{
- return document->ensureStyleResolver().ensureRuleFeatureSet().hasSelectorForAttribute(localName);
+ return document->ensureStyleResolver().ensureUpdatedRuleFeatureSet().hasSelectorForAttribute(localName);
}
void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
{
- if (isIdAttributeName(name))
+ if (isIdAttributeName(name)) {
updateId(oldValue, newValue);
- else if (name == HTMLNames::nameAttr)
+ } else if (name == HTMLNames::nameAttr) {
updateName(oldValue, newValue);
- else if (name == HTMLNames::forAttr && hasTagName(labelTag)) {
+ } else if (name == HTMLNames::forAttr && isHTMLLabelElement(*this)) {
TreeScope& scope = treeScope();
if (scope.shouldCacheLabelsByForAttribute())
updateLabel(scope, oldValue, newValue);
@@ -3077,6 +3053,33 @@
dispatchSubtreeModifiedEvent();
}
+static bool needsURLResolutionForInlineStyle(const Element& element, const Document& oldDocument, const Document& newDocument)
+{
+ if (oldDocument == newDocument)
+ return false;
+ if (oldDocument.baseURL() == newDocument.baseURL())
+ return false;
+ const StylePropertySet* style = element.inlineStyle();
+ if (!style)
+ return false;
+ for (unsigned i = 0; i < style->propertyCount(); ++i) {
+ // FIXME: Should handle all URL-based properties: CSSImageSetValue, CSSCursorImageValue, etc.
+ if (style->propertyAt(i).value()->isImageValue())
+ return true;
+ }
+ return false;
+}
+
+static void reResolveURLsInInlineStyle(const Document& document, MutableStylePropertySet& style)
+{
+ for (unsigned i = 0; i < style.propertyCount(); ++i) {
+ StylePropertySet::PropertyReference property = style.propertyAt(i);
+ // FIXME: Should handle all URL-based properties: CSSImageSetValue, CSSCursorImageValue, etc.
+ if (property.value()->isImageValue())
+ toCSSImageValue(property.value())->reResolveURL(document);
+ }
+}
+
void Element::didMoveToNewDocument(Document& oldDocument)
{
Node::didMoveToNewDocument(oldDocument);
@@ -3090,6 +3093,9 @@
if (hasClass())
setAttribute(HTMLNames::classAttr, getClassAttribute());
}
+
+ if (needsURLResolutionForInlineStyle(*this, oldDocument, document()))
+ reResolveURLsInInlineStyle(document(), ensureMutableInlineStyle());
}
void Element::updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName)
@@ -3122,16 +3128,16 @@
return collection;
if (type == TableRows) {
- ASSERT(hasTagName(tableTag));
- return ensureRareData().ensureNodeLists().addCache<HTMLTableRowsCollection>(this, type);
+ ASSERT(isHTMLTableElement(this));
+ return ensureRareData().ensureNodeLists().addCache<HTMLTableRowsCollection>(*this, type);
} else if (type == SelectOptions) {
- ASSERT(hasTagName(selectTag));
- return ensureRareData().ensureNodeLists().addCache<HTMLOptionsCollection>(this, type);
+ ASSERT(isHTMLSelectElement(this));
+ return ensureRareData().ensureNodeLists().addCache<HTMLOptionsCollection>(*this, type);
} else if (type == FormControls) {
- ASSERT(hasTagName(formTag) || hasTagName(fieldsetTag));
- return ensureRareData().ensureNodeLists().addCache<HTMLFormControlsCollection>(this, type);
+ ASSERT(isHTMLFormElement(this) || isHTMLFieldSetElement(this));
+ return ensureRareData().ensureNodeLists().addCache<HTMLFormControlsCollection>(*this, type);
}
- return ensureRareData().ensureNodeLists().addCache<HTMLCollection>(this, type);
+ return ensureRareData().ensureNodeLists().addCache<HTMLCollection>(*this, type);
}
static void scheduleLayerUpdateCallback(Node* node)
@@ -3170,7 +3176,7 @@
{
if (AttrNodeList* attrNodeList = attrNodeListForElement(this))
return findAttrNodeInList(*attrNodeList, name);
- return 0;
+ return nullptr;
}
PassRefPtr<Attr> Element::ensureAttr(const QualifiedName& name)
@@ -3207,10 +3213,11 @@
AttrNodeList* attrNodeList = attrNodeListForElement(this);
ASSERT(attrNodeList);
- for (unsigned i = 0; i < attributeCount(); ++i) {
- const Attribute* attribute = attributeItem(i);
- if (RefPtr<Attr> attrNode = findAttrNodeInList(*attrNodeList, attribute->name()))
- attrNode->detachFromElementWithValue(attribute->value());
+ unsigned attributeCount = this->attributeCount();
+ for (unsigned i = 0; i < attributeCount; ++i) {
+ const Attribute& attribute = attributeItem(i);
+ if (RefPtr<Attr> attrNode = findAttrNodeInList(*attrNodeList, attribute.name()))
+ attrNode->detachFromElementWithValue(attribute.value());
}
removeAttrNodeListForElement(this);
@@ -3230,7 +3237,7 @@
PassRefPtr<RenderStyle> Element::customStyleForRenderer()
{
ASSERT(hasCustomStyleCallbacks());
- return 0;
+ return nullptr;
}
void Element::cloneAttributesFromElement(const Element& other)
@@ -3269,14 +3276,15 @@
&& !other.m_elementData->presentationAttributeStyle())
const_cast<Element&>(other).m_elementData = static_cast<const UniqueElementData*>(other.m_elementData.get())->makeShareableCopy();
- if (!other.m_elementData->isUnique() && !ownerDocumentsHaveDifferentCaseSensitivity)
+ if (!other.m_elementData->isUnique() && !ownerDocumentsHaveDifferentCaseSensitivity && !needsURLResolutionForInlineStyle(other, other.document(), document()))
m_elementData = other.m_elementData;
else
m_elementData = other.m_elementData->makeUniqueCopy();
- for (unsigned i = 0; i < m_elementData->length(); ++i) {
- const Attribute* attribute = const_cast<const ElementData*>(m_elementData.get())->attributeItem(i);
- attributeChangedFromParserOrByCloning(attribute->name(), attribute->value(), ModifiedByCloning);
+ unsigned length = m_elementData->length();
+ for (unsigned i = 0; i < length; ++i) {
+ const Attribute& attribute = m_elementData->attributeItem(i);
+ attributeChangedFromParserOrByCloning(attribute.name(), attribute.value(), ModifiedByCloning);
}
}
@@ -3296,7 +3304,7 @@
}
}
-InputMethodContext* Element::inputMethodContext()
+InputMethodContext& Element::inputMethodContext()
{
return ensureElementRareData().ensureInputMethodContext(toHTMLElement(this));
}
@@ -3336,26 +3344,26 @@
{
if (!isStyledElement())
return 0;
- return ensureElementRareData().ensureInlineCSSStyleDeclaration(this);
+ return &ensureElementRareData().ensureInlineCSSStyleDeclaration(this);
}
-MutableStylePropertySet* Element::ensureMutableInlineStyle()
+MutableStylePropertySet& Element::ensureMutableInlineStyle()
{
ASSERT(isStyledElement());
- RefPtr<StylePropertySet>& inlineStyle = ensureUniqueElementData()->m_inlineStyle;
+ RefPtr<StylePropertySet>& inlineStyle = ensureUniqueElementData().m_inlineStyle;
if (!inlineStyle) {
CSSParserMode mode = (!isHTMLElement() || document().inQuirksMode()) ? HTMLQuirksMode : HTMLStandardMode;
inlineStyle = MutableStylePropertySet::create(mode);
} else if (!inlineStyle->isMutable()) {
inlineStyle = inlineStyle->mutableCopy();
}
- return toMutableStylePropertySet(inlineStyle);
+ return *toMutableStylePropertySet(inlineStyle);
}
void Element::clearMutableInlineStyleIfEmpty()
{
- if (ensureMutableInlineStyle()->isEmpty()) {
- ensureUniqueElementData()->m_inlineStyle.clear();
+ if (ensureMutableInlineStyle().isEmpty()) {
+ ensureUniqueElementData().m_inlineStyle.clear();
}
}
@@ -3377,7 +3385,7 @@
inlineStyle = BisonCSSParser::parseInlineStyleDeclaration(newStyleString, this);
} else {
ASSERT(inlineStyle->isMutable());
- static_pointer_cast<MutableStylePropertySet>(inlineStyle)->parseDeclaration(newStyleString, document().elementSheet()->contents());
+ static_pointer_cast<MutableStylePropertySet>(inlineStyle)->parseDeclaration(newStyleString, document().elementSheet().contents());
}
}
@@ -3389,7 +3397,7 @@
startLineNumber = document().scriptableDocumentParser()->lineNumber();
if (newStyleString.isNull()) {
- ensureUniqueElementData()->m_inlineStyle.clear();
+ ensureUniqueElementData().m_inlineStyle.clear();
} else if (modificationReason == ModifiedByCloning || document().contentSecurityPolicy()->allowInlineStyle(document().url(), startLineNumber)) {
setInlineStyleFromString(newStyleString);
}
@@ -3412,7 +3420,7 @@
bool Element::setInlineStyleProperty(CSSPropertyID propertyID, CSSValueID identifier, bool important)
{
ASSERT(isStyledElement());
- ensureMutableInlineStyle()->setProperty(propertyID, cssValuePool().createIdentifierValue(identifier), important);
+ ensureMutableInlineStyle().setProperty(propertyID, cssValuePool().createIdentifierValue(identifier), important);
inlineStyleChanged();
return true;
}
@@ -3420,7 +3428,7 @@
bool Element::setInlineStyleProperty(CSSPropertyID propertyID, CSSPropertyID identifier, bool important)
{
ASSERT(isStyledElement());
- ensureMutableInlineStyle()->setProperty(propertyID, cssValuePool().createIdentifierValue(identifier), important);
+ ensureMutableInlineStyle().setProperty(propertyID, cssValuePool().createIdentifierValue(identifier), important);
inlineStyleChanged();
return true;
}
@@ -3428,7 +3436,7 @@
bool Element::setInlineStyleProperty(CSSPropertyID propertyID, double value, CSSPrimitiveValue::UnitTypes unit, bool important)
{
ASSERT(isStyledElement());
- ensureMutableInlineStyle()->setProperty(propertyID, cssValuePool().createValue(value, unit), important);
+ ensureMutableInlineStyle().setProperty(propertyID, cssValuePool().createValue(value, unit), important);
inlineStyleChanged();
return true;
}
@@ -3436,7 +3444,7 @@
bool Element::setInlineStyleProperty(CSSPropertyID propertyID, const String& value, bool important)
{
ASSERT(isStyledElement());
- bool changes = ensureMutableInlineStyle()->setProperty(propertyID, value, important, document().elementSheet()->contents());
+ bool changes = ensureMutableInlineStyle().setProperty(propertyID, value, important, document().elementSheet().contents());
if (changes)
inlineStyleChanged();
return changes;
@@ -3447,7 +3455,7 @@
ASSERT(isStyledElement());
if (!inlineStyle())
return false;
- bool changes = ensureMutableInlineStyle()->removeProperty(propertyID);
+ bool changes = ensureMutableInlineStyle().removeProperty(propertyID);
if (changes)
inlineStyleChanged();
return changes;
@@ -3458,16 +3466,16 @@
ASSERT(isStyledElement());
if (!inlineStyle())
return;
- ensureMutableInlineStyle()->clear();
+ ensureMutableInlineStyle().clear();
inlineStyleChanged();
}
void Element::updatePresentationAttributeStyle()
{
// ShareableElementData doesn't store presentation attribute style, so make sure we have a UniqueElementData.
- UniqueElementData* elementData = ensureUniqueElementData();
- elementData->m_presentationAttributeStyleIsDirty = false;
- elementData->m_presentationAttributeStyle = computePresentationAttributeStyle(*this);
+ UniqueElementData& elementData = ensureUniqueElementData();
+ elementData.m_presentationAttributeStyleIsDirty = false;
+ elementData.m_presentationAttributeStyle = computePresentationAttributeStyle(*this);
}
void Element::addPropertyToPresentationAttributeStyle(MutableStylePropertySet* style, CSSPropertyID propertyID, CSSValueID identifier)
@@ -3521,17 +3529,17 @@
// Turn off style sharing for elements that can gain layers for reasons outside of the style system.
// See comments in RenderObject::setStyle().
// FIXME: Why does gaining a layer from outside the style system require disabling sharing?
- if (hasTagName(iframeTag)
- || hasTagName(frameTag)
- || hasTagName(embedTag)
- || hasTagName(objectTag)
- || hasTagName(appletTag)
- || hasTagName(canvasTag))
+ if (isHTMLIFrameElement(*this)
+ || isHTMLFrameElement(*this)
+ || isHTMLEmbedElement(*this)
+ || isHTMLObjectElement(*this)
+ || isHTMLAppletElement(*this)
+ || isHTMLCanvasElement(*this))
return false;
// FIXME: We should share style for option and optgroup whenever possible.
// Before doing so, we need to resolve issues in HTMLSelectElement::recalcListItems
// and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cgi?id=88405
- if (hasTagName(optionTag) || hasTagName(optgroupTag))
+ if (isHTMLOptionElement(*this) || isHTMLOptGroupElement(*this))
return false;
if (FullscreenElementStack::isActiveFullScreenElement(this))
return false;
diff --git a/Source/core/dom/Element.h b/Source/core/dom/Element.h
index 742ebf4..ff846f4 100644
--- a/Source/core/dom/Element.h
+++ b/Source/core/dom/Element.h
@@ -154,9 +154,10 @@
const AtomicString& idForStyleResolution() const;
// Internal methods that assume the existence of attribute storage, one should use hasAttributes()
- // before calling them.
+ // before calling them. This is not a trivial getter and its return value should be cached for
+ // performance.
size_t attributeCount() const;
- const Attribute* attributeItem(unsigned index) const;
+ const Attribute& attributeItem(unsigned index) const;
const Attribute* getAttributeItem(const QualifiedName&) const;
size_t getAttributeItemIndex(const QualifiedName& name) const { return elementData()->getAttributeItemIndex(name); }
size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const { return elementData()->getAttributeItemIndex(name, shouldIgnoreAttributeCase); }
@@ -284,7 +285,7 @@
void stripScriptingAttributes(Vector<Attribute>&) const;
const ElementData* elementData() const { return m_elementData.get(); }
- UniqueElementData* ensureUniqueElementData();
+ UniqueElementData& ensureUniqueElementData();
void synchronizeAllAttributes() const;
@@ -403,6 +404,8 @@
virtual String title() const { return String(); }
+ virtual const AtomicString& pseudo() const { return shadowPseudoId(); }
+ void setPseudo(const AtomicString& value) { setShadowPseudoId(value); }
virtual const AtomicString& shadowPseudoId() const;
void setShadowPseudoId(const AtomicString&);
@@ -432,11 +435,9 @@
bool matches(const String& selectors, ExceptionState&);
virtual bool shouldAppearIndeterminate() const { return false; }
- DOMTokenList* classList();
+ DOMTokenList& classList();
- DOMStringMap* dataset();
-
- virtual bool isMediaElement() const { return false; }
+ DOMStringMap& dataset();
#if ENABLE(INPUT_SPEECH)
virtual bool isInputFieldSpeechButtonElement() const { return false; }
@@ -503,17 +504,17 @@
void setSavedLayerScrollOffset(const IntSize&);
ActiveAnimations* activeAnimations() const;
- ActiveAnimations* ensureActiveAnimations();
+ ActiveAnimations& ensureActiveAnimations();
bool hasActiveAnimations() const;
- InputMethodContext* inputMethodContext();
+ InputMethodContext& inputMethodContext();
bool hasInputMethodContext() const;
void setPrefix(const AtomicString&, ExceptionState&);
void synchronizeAttribute(const AtomicString& localName) const;
- MutableStylePropertySet* ensureMutableInlineStyle();
+ MutableStylePropertySet& ensureMutableInlineStyle();
void clearMutableInlineStyleIfEmpty();
protected:
@@ -575,7 +576,6 @@
// FIXME: These methods should all be renamed to something better than "check",
// since it's not clear that they alter the style bits of siblings and children.
- void checkForChildrenAdjacentRuleChanges();
void checkForSiblingStyleChanges(bool finishedParsingCallback, Node* beforeChange, Node* afterChange, int childCountDelta);
inline void checkForEmptyStyleChange(RenderStyle*);
@@ -669,6 +669,32 @@
};
DEFINE_NODE_TYPE_CASTS(Element, isElementNode());
+template <typename T> bool isElementOfType(const Element&);
+template <typename T> inline bool isElementOfType(const Node& node) { return node.isElementNode() && isElementOfType<const T>(toElement(node)); }
+template <> inline bool isElementOfType<const Element>(const Element&) { return true; }
+
+// Type casting.
+template<typename T> inline T& toElement(Node& node)
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(isElementOfType<const T>(node));
+ return static_cast<T&>(node);
+}
+template<typename T> inline T* toElement(Node* node)
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(!node || isElementOfType<const T>(*node));
+ return static_cast<T*>(node);
+}
+template<typename T> inline const T& toElement(const Node& node)
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(isElementOfType<const T>(node));
+ return static_cast<const T&>(node);
+}
+template<typename T> inline const T* toElement(const Node* node)
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(!node || isElementOfType<const T>(*node));
+ return static_cast<const T*>(node);
+}
+template<typename T, typename U> inline T* toElement(const RefPtr<U>& node) { return toElement<T>(node.get()); }
inline bool isDisabledFormControl(const Node* node)
{
@@ -764,7 +790,7 @@
return elementData()->length();
}
-inline const Attribute* Element::attributeItem(unsigned index) const
+inline const Attribute& Element::attributeItem(unsigned index) const
{
ASSERT(elementData());
return elementData()->attributeItem(index);
@@ -786,11 +812,11 @@
return elementData() && elementData()->hasClass();
}
-inline UniqueElementData* Element::ensureUniqueElementData()
+inline UniqueElementData& Element::ensureUniqueElementData()
{
if (!elementData() || !elementData()->isUnique())
createUniqueElementData();
- return static_cast<UniqueElementData*>(m_elementData.get());
+ return static_cast<UniqueElementData&>(*m_elementData);
}
// Put here to make them inline.
@@ -860,6 +886,16 @@
return element && element->shadow();
}
+// These macros do the same as their NODE equivalents but additionally provide a template specialization
+// for isElementOfType<>() so that the Traversal<> API works for these Element types.
+#define DEFINE_ELEMENT_TYPE_CASTS(thisType, predicate) \
+ template <> inline bool isElementOfType<const thisType>(const Element& element) { return element.predicate; } \
+ DEFINE_NODE_TYPE_CASTS(thisType, predicate)
+
+#define DEFINE_ELEMENT_TYPE_CASTS_WITH_FUNCTION(thisType) \
+ template <> inline bool isElementOfType<const thisType>(const Element& element) { return is##thisType(element); } \
+ DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(thisType)
+
} // namespace
#endif
diff --git a/Source/core/dom/Element.idl b/Source/core/dom/Element.idl
index a715874..4a3c23b 100644
--- a/Source/core/dom/Element.idl
+++ b/Source/core/dom/Element.idl
@@ -96,7 +96,7 @@
[RaisesException, CustomElementCallbacks, MeasureAs=InsertAdjacentElement] Element insertAdjacentElement(DOMString where, Element element);
[RaisesException, MeasureAs=InsertAdjacentText] void insertAdjacentText(DOMString where, DOMString text);
- [CustomElementCallbacks, RaisesException] void insertAdjacentHTML(DOMString where, DOMString html);
+ [CustomElementCallbacks, RaisesException, MeasureAs=InsertAdjacentHTML] void insertAdjacentHTML(DOMString where, DOMString html);
[Reflect=class, PerWorldBindings] attribute DOMString className;
[PerWorldBindings] readonly attribute DOMTokenList classList;
@@ -111,6 +111,7 @@
[RaisesException, ImplementedAs=matches, MeasureAs=ElementPrefixedMatchesSelector] boolean webkitMatchesSelector(DOMString selectors);
// Shadow DOM API
+ [RuntimeEnabled=ShadowDOM, Reflect, TreatNullAs=NullString, PerWorldBindings] attribute DOMString pseudo;
[RuntimeEnabled=ShadowDOM, RaisesException] ShadowRoot createShadowRoot();
[RuntimeEnabled=ShadowDOM, PerWorldBindings] readonly attribute ShadowRoot shadowRoot;
[RuntimeEnabled=ShadowDOM, PerWorldBindings] NodeList getDestinationInsertionPoints();
@@ -125,10 +126,10 @@
// Mozilla version
const unsigned short ALLOW_KEYBOARD_INPUT = 1;
- [RuntimeEnabled=Fullscreen, PerWorldBindings, ActivityLogging=ForAllWorlds, MeasureAs=PrefixedElementRequestFullScreen] void webkitRequestFullScreen([Default=Undefined] optional unsigned short flags);
+ [PerWorldBindings, ActivityLogging=ForAllWorlds, MeasureAs=PrefixedElementRequestFullScreen] void webkitRequestFullScreen([Default=Undefined] optional unsigned short flags);
// W3C version
- [RuntimeEnabled=Fullscreen, PerWorldBindings, ActivityLogging=ForAllWorlds, MeasureAs=PrefixedElementRequestFullscreen] void webkitRequestFullscreen();
+ [PerWorldBindings, ActivityLogging=ForAllWorlds, MeasureAs=PrefixedElementRequestFullscreen] void webkitRequestFullscreen();
void webkitRequestPointerLock();
diff --git a/Source/core/dom/ElementData.cpp b/Source/core/dom/ElementData.cpp
index 82c7712..dbd47f0 100644
--- a/Source/core/dom/ElementData.cpp
+++ b/Source/core/dom/ElementData.cpp
@@ -100,14 +100,14 @@
if (!other)
return isEmpty();
- unsigned len = length();
- if (len != other->length())
+ unsigned length = this->length();
+ if (length != other->length())
return false;
- for (unsigned i = 0; i < len; i++) {
- const Attribute* attribute = attributeItem(i);
- const Attribute* otherAttr = other->getAttributeItem(attribute->name());
- if (!otherAttr || attribute->value() != otherAttr->value())
+ for (unsigned i = 0; i < length; ++i) {
+ const Attribute& attribute = attributeItem(i);
+ const Attribute* otherAttr = other->getAttributeItem(attribute.name());
+ if (!otherAttr || attribute.value() != otherAttr->value())
return false;
}
@@ -117,8 +117,9 @@
size_t ElementData::getAttrIndex(Attr* attr) const
{
// This relies on the fact that Attr's QualifiedName == the Attribute's name.
- for (unsigned i = 0; i < length(); ++i) {
- if (attributeItem(i)->name() == attr->qualifiedName())
+ unsigned length = this->length();
+ for (unsigned i = 0; i < length; ++i) {
+ if (attributeItem(i).name() == attr->qualifiedName())
return i;
}
return kNotFound;
@@ -127,18 +128,19 @@
size_t ElementData::getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const
{
// Continue to checking case-insensitively and/or full namespaced names if necessary:
- for (unsigned i = 0; i < length(); ++i) {
- const Attribute* attribute = attributeItem(i);
+ unsigned length = this->length();
+ for (unsigned i = 0; i < length; ++i) {
+ const Attribute& attribute = attributeItem(i);
// FIXME: Why check the prefix? Namespace is all that should matter
// and all HTML/SVG attributes have a null namespace!
- if (!attribute->name().hasPrefix()) {
- if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attribute->localName()))
+ if (!attribute.name().hasPrefix()) {
+ if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attribute.localName()))
return i;
} else {
// FIXME: Would be faster to do this comparison without calling toString, which
// generates a temporary string by concatenation. But this branch is only reached
// if the attribute name has a prefix, which is rare in HTML.
- if (equalPossiblyIgnoringCase(name, attribute->name().toString(), shouldIgnoreAttributeCase))
+ if (equalPossiblyIgnoringCase(name, attribute.name().toString(), shouldIgnoreAttributeCase))
return i;
}
}
@@ -186,7 +188,7 @@
, m_presentationAttributeStyle(other.m_presentationAttributeStyle)
, m_attributeVector(other.m_attributeVector)
{
- m_inlineStyle = other.m_inlineStyle ? other.m_inlineStyle->mutableCopy() : 0;
+ m_inlineStyle = other.m_inlineStyle ? other.m_inlineStyle->mutableCopy() : nullptr;
}
UniqueElementData::UniqueElementData(const ShareableElementData& other)
@@ -196,8 +198,9 @@
ASSERT(!other.m_inlineStyle || !other.m_inlineStyle->isMutable());
m_inlineStyle = other.m_inlineStyle;
- m_attributeVector.reserveCapacity(other.length());
- for (unsigned i = 0; i < other.length(); ++i)
+ unsigned length = other.length();
+ m_attributeVector.reserveCapacity(length);
+ for (unsigned i = 0; i < length; ++i)
m_attributeVector.uncheckedAppend(other.m_attributeArray[i]);
}
@@ -214,7 +217,8 @@
Attribute* UniqueElementData::getAttributeItem(const QualifiedName& name)
{
- for (unsigned i = 0; i < length(); ++i) {
+ unsigned length = this->length();
+ for (unsigned i = 0; i < length; ++i) {
if (m_attributeVector.at(i).name().matches(name))
return &m_attributeVector.at(i);
}
diff --git a/Source/core/dom/ElementData.h b/Source/core/dom/ElementData.h
index 76451f8..e209f7f 100644
--- a/Source/core/dom/ElementData.h
+++ b/Source/core/dom/ElementData.h
@@ -62,10 +62,11 @@
const StylePropertySet* presentationAttributeStyle() const;
+ // This is not a trivial getter and its return value should be cached for performance.
size_t length() const;
bool isEmpty() const { return !length(); }
- const Attribute* attributeItem(unsigned index) const;
+ const Attribute& attributeItem(unsigned index) const;
const Attribute* getAttributeItem(const QualifiedName&) const;
size_t getAttributeItemIndex(const QualifiedName&, bool shouldIgnoreCase = false) const;
size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
@@ -148,7 +149,7 @@
void addAttribute(const QualifiedName&, const AtomicString&);
void removeAttribute(size_t index);
- Attribute* attributeItem(unsigned index);
+ Attribute& attributeItem(unsigned index);
Attribute* getAttributeItem(const QualifiedName&);
UniqueElementData();
@@ -188,7 +189,7 @@
{
size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase);
if (index != kNotFound)
- return attributeItem(index);
+ return &attributeItem(index);
return 0;
}
@@ -203,8 +204,8 @@
{
const Attribute* begin = attributeBase();
// Cache length for performance as ElementData::length() contains a conditional branch.
- unsigned len = length();
- for (unsigned i = 0; i < len; ++i) {
+ unsigned length = this->length();
+ for (unsigned i = 0; i < length; ++i) {
const Attribute& attribute = begin[i];
if (attribute.name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase))
return i;
@@ -217,12 +218,12 @@
inline size_t ElementData::getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const
{
// Cache length for performance as ElementData::length() contains a conditional branch.
- unsigned len = length();
+ unsigned length = this->length();
bool doSlowCheck = shouldIgnoreAttributeCase;
// Optimize for the case where the attribute exists and its name exactly matches.
const Attribute* begin = attributeBase();
- for (unsigned i = 0; i < len; ++i) {
+ for (unsigned i = 0; i < length; ++i) {
const Attribute& attribute = begin[i];
// FIXME: Why check the prefix? Namespaces should be all that matter.
// Most attributes (all of HTML and CSS) have no namespace.
@@ -242,7 +243,8 @@
inline const Attribute* ElementData::getAttributeItem(const QualifiedName& name) const
{
const Attribute* begin = attributeBase();
- for (unsigned i = 0; i < length(); ++i) {
+ unsigned length = this->length();
+ for (unsigned i = 0; i < length; ++i) {
const Attribute& attribute = begin[i];
if (attribute.name().matches(name))
return &attribute;
@@ -250,10 +252,11 @@
return 0;
}
-inline const Attribute* ElementData::attributeItem(unsigned index) const
+inline const Attribute& ElementData::attributeItem(unsigned index) const
{
RELEASE_ASSERT(index < length());
- return attributeBase() + index;
+ ASSERT(attributeBase() + index);
+ return *(attributeBase() + index);
}
inline void UniqueElementData::addAttribute(const QualifiedName& attributeName, const AtomicString& value)
@@ -266,9 +269,9 @@
m_attributeVector.remove(index);
}
-inline Attribute* UniqueElementData::attributeItem(unsigned index)
+inline Attribute& UniqueElementData::attributeItem(unsigned index)
{
- return &m_attributeVector.at(index);
+ return m_attributeVector.at(index);
}
} // namespace WebCore
diff --git a/Source/core/dom/ElementDataCache.cpp b/Source/core/dom/ElementDataCache.cpp
index 1b3cf32..8bdbf92 100644
--- a/Source/core/dom/ElementDataCache.cpp
+++ b/Source/core/dom/ElementDataCache.cpp
@@ -47,7 +47,7 @@
{
ASSERT(!attributes.isEmpty());
- ShareableElementDataCache::ValueType* it = m_shareableElementDataCache.add(attributeHash(attributes), 0).storedValue;
+ ShareableElementDataCache::ValueType* it = m_shareableElementDataCache.add(attributeHash(attributes), nullptr).storedValue;
// FIXME: This prevents sharing when there's a hash collision.
if (it->value && !hasSameAttributes(attributes, *it->value))
diff --git a/Source/core/dom/ElementRareData.cpp b/Source/core/dom/ElementRareData.cpp
index 85889c3..8512151 100644
--- a/Source/core/dom/ElementRareData.cpp
+++ b/Source/core/dom/ElementRareData.cpp
@@ -43,11 +43,11 @@
void* pointers[11];
};
-CSSStyleDeclaration* ElementRareData::ensureInlineCSSStyleDeclaration(Element* ownerElement)
+CSSStyleDeclaration& ElementRareData::ensureInlineCSSStyleDeclaration(Element* ownerElement)
{
if (!m_cssomWrapper)
m_cssomWrapper = adoptPtr(new InlineCSSStyleDeclaration(ownerElement));
- return m_cssomWrapper.get();
+ return *m_cssomWrapper;
}
diff --git a/Source/core/dom/ElementRareData.h b/Source/core/dom/ElementRareData.h
index a492285..40942a5 100644
--- a/Source/core/dom/ElementRareData.h
+++ b/Source/core/dom/ElementRareData.h
@@ -91,7 +91,7 @@
unsigned childIndex() const { return m_childIndex; }
void setChildIndex(unsigned index) { m_childIndex = index; }
- CSSStyleDeclaration* ensureInlineCSSStyleDeclaration(Element* ownerElement);
+ CSSStyleDeclaration& ensureInlineCSSStyleDeclaration(Element* ownerElement);
void clearShadow() { m_shadow = nullptr; }
ElementShadow* shadow() const { return m_shadow.get(); }
@@ -107,7 +107,7 @@
RenderStyle* computedStyle() const { return m_computedStyle.get(); }
void setComputedStyle(PassRefPtr<RenderStyle> computedStyle) { m_computedStyle = computedStyle; }
- void clearComputedStyle() { m_computedStyle = 0; }
+ void clearComputedStyle() { m_computedStyle = nullptr; }
ClassList* classList() const { return m_classList.get(); }
void setClassList(PassOwnPtr<ClassList> classList) { m_classList = classList; }
@@ -137,11 +137,11 @@
void setHasPendingResources(bool has) { m_hasPendingResources = has; }
bool hasInputMethodContext() const { return m_inputMethodContext; }
- InputMethodContext* ensureInputMethodContext(HTMLElement* element)
+ InputMethodContext& ensureInputMethodContext(HTMLElement* element)
{
if (!m_inputMethodContext)
m_inputMethodContext = InputMethodContext::create(element);
- return m_inputMethodContext.get();
+ return *m_inputMethodContext;
}
bool hasPseudoElements() const;
@@ -233,9 +233,9 @@
inline void ElementRareData::clearPseudoElements()
{
- setPseudoElement(BEFORE, 0);
- setPseudoElement(AFTER, 0);
- setPseudoElement(BACKDROP, 0);
+ setPseudoElement(BEFORE, nullptr);
+ setPseudoElement(AFTER, nullptr);
+ setPseudoElement(BACKDROP, nullptr);
}
inline void ElementRareData::setPseudoElement(PseudoId pseudoId, PassRefPtr<PseudoElement> element)
diff --git a/Source/core/dom/ElementTraversal.h b/Source/core/dom/ElementTraversal.h
index 6bcf1d1..6705f04 100644
--- a/Source/core/dom/ElementTraversal.h
+++ b/Source/core/dom/ElementTraversal.h
@@ -2,8 +2,9 @@
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2001 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2014 Samsung Electronics. 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
@@ -30,155 +31,285 @@
namespace WebCore {
-namespace ElementTraversal {
+template <class ElementType>
+class Traversal {
+public:
+ // First or last ElementType child of the node.
+ static ElementType* firstChild(const ContainerNode& current) { return firstChildTemplate(current); }
+ static ElementType* firstChild(const Node& current) { return firstChildTemplate(current); }
+ static ElementType* lastChild(const ContainerNode& current) { return lastChildTemplate(current); }
+ static ElementType* lastChild(const Node& current) { return lastChildTemplate(current); }
-// First / Last element child of the node.
-Element* firstWithin(const Node&);
-Element* firstWithin(const ContainerNode&);
-Element* lastWithin(const Node&);
-Element* lastWithin(const ContainerNode&);
+ // First or last ElementType descendant of the node.
+ // For Elements firstWithin() is always the same as firstChild().
+ static ElementType* firstWithin(const ContainerNode& current) { return firstWithinTemplate(current); }
+ static ElementType* firstWithin(const Node& current) { return firstWithinTemplate(current); }
+ static ElementType* lastWithin(const ContainerNode& current) { return lastWithinTemplate(current); }
+ static ElementType* lastWithin(const Node& current) { return lastWithinTemplate(current); }
-// Pre-order traversal skipping non-element nodes.
-Element* next(const Node&);
-Element* next(const Node&, const Node* stayWithin);
-Element* next(const ContainerNode&);
-Element* next(const ContainerNode&, const Node* stayWithin);
+ // Pre-order traversal skipping non-element nodes.
+ static ElementType* next(const ContainerNode& current) { return nextTemplate(current); }
+ static ElementType* next(const Node& current) { return nextTemplate(current); }
+ static ElementType* next(const ContainerNode& current, const Node* stayWithin) { return nextTemplate(current, stayWithin); }
+ static ElementType* next(const Node& current, const Node* stayWithin) { return nextTemplate(current, stayWithin); }
+ static ElementType* previous(const ContainerNode& current) { return previousTemplate(current); }
+ static ElementType* previous(const Node& current) { return previousTemplate(current); }
+ static ElementType* previous(const ContainerNode& current, const Node* stayWithin) { return previousTemplate(current, stayWithin); }
+ static ElementType* previous(const Node& current, const Node* stayWithin) { return previousTemplate(current, stayWithin); }
-// Like next, but skips children.
-Element* nextSkippingChildren(const Node&);
-Element* nextSkippingChildren(const Node&, const Node* stayWithin);
-Element* nextSkippingChildren(const ContainerNode&);
-Element* nextSkippingChildren(const ContainerNode&, const Node* stayWithin);
+ // Like next, but skips children.
+ static ElementType* nextSkippingChildren(const ContainerNode& current) { return nextSkippingChildrenTemplate(current); }
+ static ElementType* nextSkippingChildren(const Node& current) { return nextSkippingChildrenTemplate(current); }
+ static ElementType* nextSkippingChildren(const ContainerNode& current, const Node* stayWithin) { return nextSkippingChildrenTemplate(current, stayWithin); }
+ static ElementType* nextSkippingChildren(const Node& current, const Node* stayWithin) { return nextSkippingChildrenTemplate(current, stayWithin); }
-// Pre-order traversal including the pseudo-elements.
-Element* previousIncludingPseudo(const Node&, const Node* stayWithin = 0);
-Element* nextIncludingPseudo(const Node&, const Node* stayWithin = 0);
-Element* nextIncludingPseudoSkippingChildren(const Node&, const Node* stayWithin = 0);
+ // Pre-order traversal including the pseudo-elements.
+ static ElementType* previousIncludingPseudo(const Node&, const Node* stayWithin = 0);
+ static ElementType* nextIncludingPseudo(const Node&, const Node* stayWithin = 0);
+ static ElementType* nextIncludingPseudoSkippingChildren(const Node&, const Node* stayWithin = 0);
-// Utility function to traverse only the element and pseudo-element siblings of a node.
-Element* pseudoAwarePreviousSibling(const Node&);
+ // Utility function to traverse only the element and pseudo-element siblings of a node.
+ static ElementType* pseudoAwarePreviousSibling(const Node&);
-// Previous / Next sibling.
-Element* previousSibling(const Node&);
-Element* nextSibling(const Node&);
+ // Previous / Next sibling.
+ static ElementType* previousSibling(const Node&);
+ static ElementType* nextSibling(const Node&);
+private:
+ template <class NodeType>
+ static ElementType* firstChildTemplate(NodeType&);
+ template <class NodeType>
+ static ElementType* lastChildTemplate(NodeType&);
+ template <class NodeType>
+ static ElementType* firstWithinTemplate(NodeType&);
+ template <class NodeType>
+ static ElementType* lastWithinTemplate(NodeType&);
+ template <class NodeType>
+ static ElementType* nextTemplate(NodeType&);
+ template <class NodeType>
+ static ElementType* nextTemplate(NodeType&, const Node* stayWithin);
+ template <class NodeType>
+ static ElementType* previousTemplate(NodeType&);
+ template <class NodeType>
+ static ElementType* previousTemplate(NodeType&, const Node* stayWithin);
+ template <class NodeType>
+ static ElementType* nextSkippingChildrenTemplate(NodeType&);
+ template <class NodeType>
+ static ElementType* nextSkippingChildrenTemplate(NodeType&, const Node* stayWithin);
+};
+
+typedef Traversal<Element> ElementTraversal;
+
+// Specialized for pure Element to exploit the fact that Elements parent is always either another Element or the root.
+template <>
template <class NodeType>
-inline Element* firstElementWithinTemplate(NodeType& current)
+inline Element* Traversal<Element>::firstWithinTemplate(NodeType& current)
{
- // Except for the root containers, only elements can have element children.
- Node* node = current.firstChild();
- while (node && !node->isElementNode())
- node = node->nextSibling();
- return toElement(node);
+ return firstChildTemplate(current);
}
-inline Element* firstWithin(const ContainerNode& current) { return firstElementWithinTemplate(current); }
-inline Element* firstWithin(const Node& current) { return firstElementWithinTemplate(current); }
+template <>
template <class NodeType>
-inline Element* lastWithinTemplate(NodeType& current)
+inline Element* Traversal<Element>::lastWithinTemplate(NodeType& current)
{
- Node* node = current.lastChild();
- while (node && !node->isElementNode())
- node = node->previousSibling();
- return toElement(node);
+ return lastChildTemplate(current);
}
-inline Element* lastWithin(const ContainerNode& current) { return lastWithinTemplate(current); }
-inline Element* lastWithin(const Node& current) { return lastWithinTemplate(current); }
+template <>
template <class NodeType>
-inline Element* traverseNextElementTemplate(NodeType& current)
+inline Element* Traversal<Element>::nextTemplate(NodeType& current)
{
Node* node = NodeTraversal::next(current);
while (node && !node->isElementNode())
node = NodeTraversal::nextSkippingChildren(*node);
return toElement(node);
}
-inline Element* next(const ContainerNode& current) { return traverseNextElementTemplate(current); }
-inline Element* next(const Node& current) { return traverseNextElementTemplate(current); }
+template <>
template <class NodeType>
-inline Element* traverseNextElementTemplate(NodeType& current, const Node* stayWithin)
+inline Element* Traversal<Element>::nextTemplate(NodeType& current, const Node* stayWithin)
{
Node* node = NodeTraversal::next(current, stayWithin);
while (node && !node->isElementNode())
node = NodeTraversal::nextSkippingChildren(*node, stayWithin);
return toElement(node);
}
-inline Element* next(const ContainerNode& current, const Node* stayWithin) { return traverseNextElementTemplate(current, stayWithin); }
-inline Element* next(const Node& current, const Node* stayWithin) { return traverseNextElementTemplate(current, stayWithin); }
+template <>
template <class NodeType>
-inline Element* traverseNextElementSkippingChildrenTemplate(NodeType& current)
+inline Element* Traversal<Element>::previousTemplate(NodeType& current)
+{
+ Node* node = NodeTraversal::previous(current);
+ while (node && !node->isElementNode())
+ node = NodeTraversal::previous(*node);
+ return toElement(node);
+}
+
+template <>
+template <class NodeType>
+inline Element* Traversal<Element>::previousTemplate(NodeType& current, const Node* stayWithin)
+{
+ Node* node = NodeTraversal::previous(current, stayWithin);
+ while (node && !node->isElementNode())
+ node = NodeTraversal::previous(*node, stayWithin);
+ return toElement(node);
+}
+
+// Generic versions.
+template <class ElementType>
+template <class NodeType>
+inline ElementType* Traversal<ElementType>::firstChildTemplate(NodeType& current)
+{
+ Node* node = current.firstChild();
+ while (node && !isElementOfType<const ElementType>(*node))
+ node = node->nextSibling();
+ return toElement<ElementType>(node);
+}
+
+template <class ElementType>
+template <class NodeType>
+inline ElementType* Traversal<ElementType>::lastChildTemplate(NodeType& current)
+{
+ Node* node = current.lastChild();
+ while (node && !isElementOfType<const ElementType>(*node))
+ node = node->previousSibling();
+ return toElement<ElementType>(node);
+}
+
+template <class ElementType>
+template <class NodeType>
+inline ElementType* Traversal<ElementType>::firstWithinTemplate(NodeType& current)
+{
+ Element* element = Traversal<Element>::firstWithin(current);
+ while (element && !isElementOfType<const ElementType>(*element))
+ element = Traversal<Element>::next(*element, ¤t);
+ return toElement<ElementType>(element);
+}
+
+template <class ElementType>
+template <class NodeType>
+inline ElementType* Traversal<ElementType>::lastWithinTemplate(NodeType& current)
+{
+ Element* element = Traversal<Element>::lastWithin(current);
+ while (element && !isElementOfType<const ElementType>(*element))
+ element = Traversal<Element>::previous(element, ¤t);
+ return toElement<ElementType>(element);
+}
+
+template <class ElementType>
+template <class NodeType>
+inline ElementType* Traversal<ElementType>::nextTemplate(NodeType& current)
+{
+ Element* element = Traversal<Element>::next(current);
+ while (element && !isElementOfType<const ElementType>(*element))
+ element = Traversal<Element>::next(*element);
+ return toElement<ElementType>(element);
+}
+
+template <class ElementType>
+template <class NodeType>
+inline ElementType* Traversal<ElementType>::nextTemplate(NodeType& current, const Node* stayWithin)
+{
+ Element* element = Traversal<Element>::next(current, stayWithin);
+ while (element && !isElementOfType<const ElementType>(*element))
+ element = Traversal<Element>::next(*element, stayWithin);
+ return toElement<ElementType>(element);
+}
+
+template <class ElementType>
+template <class NodeType>
+inline ElementType* Traversal<ElementType>::previousTemplate(NodeType& current)
+{
+ Element* element = Traversal<Element>::previous(current);
+ while (element && !isElementOfType<const ElementType>(*element))
+ element = Traversal<Element>::previous(*element);
+ return toElement<ElementType>(element);
+}
+
+template <class ElementType>
+template <class NodeType>
+inline ElementType* Traversal<ElementType>::previousTemplate(NodeType& current, const Node* stayWithin)
+{
+ Element* element = Traversal<Element>::previous(current, stayWithin);
+ while (element && !isElementOfType<const ElementType>(*element))
+ element = Traversal<Element>::previous(*element, stayWithin);
+ return toElement<ElementType>(element);
+}
+
+template <class ElementType>
+template <class NodeType>
+inline ElementType* Traversal<ElementType>::nextSkippingChildrenTemplate(NodeType& current)
{
Node* node = NodeTraversal::nextSkippingChildren(current);
- while (node && !node->isElementNode())
+ while (node && !isElementOfType<const ElementType>(*node))
node = NodeTraversal::nextSkippingChildren(*node);
- return toElement(node);
+ return toElement<ElementType>(node);
}
-inline Element* nextSkippingChildren(const ContainerNode& current) { return traverseNextElementSkippingChildrenTemplate(current); }
-inline Element* nextSkippingChildren(const Node& current) { return traverseNextElementSkippingChildrenTemplate(current); }
+template <class ElementType>
template <class NodeType>
-inline Element* traverseNextElementSkippingChildrenTemplate(NodeType& current, const Node* stayWithin)
+inline ElementType* Traversal<ElementType>::nextSkippingChildrenTemplate(NodeType& current, const Node* stayWithin)
{
Node* node = NodeTraversal::nextSkippingChildren(current, stayWithin);
- while (node && !node->isElementNode())
+ while (node && !isElementOfType<const ElementType>(*node))
node = NodeTraversal::nextSkippingChildren(*node, stayWithin);
- return toElement(node);
+ return toElement<ElementType>(node);
}
-inline Element* nextSkippingChildren(const ContainerNode& current, const Node* stayWithin) { return traverseNextElementSkippingChildrenTemplate(current, stayWithin); }
-inline Element* nextSkippingChildren(const Node& current, const Node* stayWithin) { return traverseNextElementSkippingChildrenTemplate(current, stayWithin); }
-inline Element* previousIncludingPseudo(const Node& current, const Node* stayWithin)
+template <class ElementType>
+inline ElementType* Traversal<ElementType>::previousIncludingPseudo(const Node& current, const Node* stayWithin)
{
Node* node = NodeTraversal::previousIncludingPseudo(current, stayWithin);
- while (node && !node->isElementNode())
+ while (node && !isElementOfType<const ElementType>(*node))
node = NodeTraversal::previousIncludingPseudo(*node, stayWithin);
- return toElement(node);
+ return toElement<ElementType>(node);
}
-inline Element* nextIncludingPseudo(const Node& current, const Node* stayWithin)
+template <class ElementType>
+inline ElementType* Traversal<ElementType>::nextIncludingPseudo(const Node& current, const Node* stayWithin)
{
Node* node = NodeTraversal::nextIncludingPseudo(current, stayWithin);
- while (node && !node->isElementNode())
+ while (node && !isElementOfType<const ElementType>(*node))
node = NodeTraversal::nextIncludingPseudo(*node, stayWithin);
- return toElement(node);
+ return toElement<ElementType>(node);
}
-inline Element* nextIncludingPseudoSkippingChildren(const Node& current, const Node* stayWithin)
+template <class ElementType>
+inline ElementType* Traversal<ElementType>::nextIncludingPseudoSkippingChildren(const Node& current, const Node* stayWithin)
{
Node* node = NodeTraversal::nextIncludingPseudoSkippingChildren(current, stayWithin);
- while (node && !node->isElementNode())
+ while (node && !isElementOfType<const ElementType>(*node))
node = NodeTraversal::nextIncludingPseudoSkippingChildren(*node, stayWithin);
- return toElement(node);
+ return toElement<ElementType>(node);
}
-inline Element* pseudoAwarePreviousSibling(const Node& current)
+template <class ElementType>
+inline ElementType* Traversal<ElementType>::pseudoAwarePreviousSibling(const Node& current)
{
Node* node = current.pseudoAwarePreviousSibling();
- while (node && !node->isElementNode())
+ while (node && !isElementOfType<const ElementType>(*node))
node = node->pseudoAwarePreviousSibling();
- return toElement(node);
+ return toElement<ElementType>(node);
}
-inline Element* previousSibling(const Node& current)
+template <class ElementType>
+inline ElementType* Traversal<ElementType>::previousSibling(const Node& current)
{
Node* node = current.previousSibling();
- while (node && !node->isElementNode())
+ while (node && !isElementOfType<const ElementType>(*node))
node = node->previousSibling();
- return toElement(node);
+ return toElement<ElementType>(node);
}
-inline Element* nextSibling(const Node& current)
+template <class ElementType>
+inline ElementType* Traversal<ElementType>::nextSibling(const Node& current)
{
Node* node = current.nextSibling();
- while (node && !node->isElementNode())
+ while (node && !isElementOfType<const ElementType>(*node))
node = node->nextSibling();
- return toElement(node);
+ return toElement<ElementType>(node);
}
-}
-
-}
+} // namespace WebCore
#endif
diff --git a/Source/core/dom/EmptyNodeList.cpp b/Source/core/dom/EmptyNodeList.cpp
index 8705936..26104fb 100644
--- a/Source/core/dom/EmptyNodeList.cpp
+++ b/Source/core/dom/EmptyNodeList.cpp
@@ -44,7 +44,7 @@
Node* EmptyNodeList::virtualOwnerNode() const
{
- return ownerNode();
+ return &ownerNode();
}
} // namespace WebCore
diff --git a/Source/core/dom/EmptyNodeList.h b/Source/core/dom/EmptyNodeList.h
index 06f895f..fd7c5a6 100644
--- a/Source/core/dom/EmptyNodeList.h
+++ b/Source/core/dom/EmptyNodeList.h
@@ -33,21 +33,22 @@
#define EmptyNodeList_h
#include "core/dom/NodeList.h"
+#include "wtf/RefPtr.h"
namespace WebCore {
class EmptyNodeList FINAL : public NodeList {
public:
- static PassRefPtr<EmptyNodeList> create(Node* rootNode)
+ static PassRefPtr<EmptyNodeList> create(Node& rootNode)
{
return adoptRef(new EmptyNodeList(rootNode));
}
virtual ~EmptyNodeList();
- Node* ownerNode() const { return m_owner.get(); }
+ Node& ownerNode() const { return *m_owner; }
private:
- explicit EmptyNodeList(Node* rootNode) : m_owner(rootNode) { }
+ explicit EmptyNodeList(Node& rootNode) : m_owner(rootNode) { }
virtual unsigned length() const OVERRIDE { return 0; }
virtual Node* item(unsigned) const OVERRIDE { return 0; }
diff --git a/Source/core/dom/ExecutionContext.cpp b/Source/core/dom/ExecutionContext.cpp
index 0740d82..a0b8914 100644
--- a/Source/core/dom/ExecutionContext.cpp
+++ b/Source/core/dom/ExecutionContext.cpp
@@ -96,6 +96,11 @@
lifecycleNotifier().notifyStoppingActiveDOMObjects();
}
+unsigned ExecutionContext::activeDOMObjectCount()
+{
+ return lifecycleNotifier().activeDOMObjects().size();
+}
+
void ExecutionContext::suspendScheduledTasks()
{
suspendActiveDOMObjects();
diff --git a/Source/core/dom/ExecutionContext.h b/Source/core/dom/ExecutionContext.h
index 3fb01bb..9cc3926 100644
--- a/Source/core/dom/ExecutionContext.h
+++ b/Source/core/dom/ExecutionContext.h
@@ -95,6 +95,7 @@
void suspendActiveDOMObjects();
void resumeActiveDOMObjects();
void stopActiveDOMObjects();
+ unsigned activeDOMObjectCount();
virtual void suspendScheduledTasks();
virtual void resumeScheduledTasks();
diff --git a/Source/core/dom/ExecutionContextTask.cpp b/Source/core/dom/ExecutionContextTask.cpp
deleted file mode 100644
index 124a5ac..0000000
--- a/Source/core/dom/ExecutionContextTask.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ExecutionContextTask_h
-#define ExecutionContextTask_h
-
-#include "config.h"
-#include "core/dom/ExecutionContextTask.h"
-
-namespace WebCore {
-
-
-} // namespace
-
-#endif
diff --git a/Source/core/dom/FullscreenElementStack.cpp b/Source/core/dom/FullscreenElementStack.cpp
index 635639b..fc56e7b 100644
--- a/Source/core/dom/FullscreenElementStack.cpp
+++ b/Source/core/dom/FullscreenElementStack.cpp
@@ -31,10 +31,11 @@
#include "HTMLNames.h"
#include "core/dom/Document.h"
#include "core/events/Event.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameHost.h"
+#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/html/HTMLMediaElement.h"
#include "core/page/Chrome.h"
#include "core/page/ChromeClient.h"
#include "core/rendering/RenderFullScreen.h"
@@ -60,7 +61,7 @@
return "FullscreenElementStack";
}
-FullscreenElementStack* FullscreenElementStack::from(Document* document)
+FullscreenElementStack& FullscreenElementStack::from(Document& document)
{
FullscreenElementStack* fullscreen = fromIfExists(document);
if (!fullscreen) {
@@ -68,42 +69,42 @@
DocumentSupplement::provideTo(document, supplementName(), adoptPtr(fullscreen));
}
- return fullscreen;
+ return *fullscreen;
}
-FullscreenElementStack* FullscreenElementStack::fromIfExistsSlow(Document* document)
+FullscreenElementStack* FullscreenElementStack::fromIfExistsSlow(Document& document)
{
return static_cast<FullscreenElementStack*>(DocumentSupplement::from(document, supplementName()));
}
-Element* FullscreenElementStack::fullscreenElementFrom(Document* document)
+Element* FullscreenElementStack::fullscreenElementFrom(Document& document)
{
if (FullscreenElementStack* found = fromIfExists(document))
return found->webkitFullscreenElement();
return 0;
}
-Element* FullscreenElementStack::currentFullScreenElementFrom(Document* document)
+Element* FullscreenElementStack::currentFullScreenElementFrom(Document& document)
{
if (FullscreenElementStack* found = fromIfExists(document))
return found->webkitCurrentFullScreenElement();
return 0;
}
-bool FullscreenElementStack::isFullScreen(Document* document)
+bool FullscreenElementStack::isFullScreen(Document& document)
{
if (FullscreenElementStack* found = fromIfExists(document))
return found->webkitIsFullScreen();
return false;
}
-FullscreenElementStack::FullscreenElementStack(Document* document)
- : DocumentLifecycleObserver(document)
+FullscreenElementStack::FullscreenElementStack(Document& document)
+ : DocumentLifecycleObserver(&document)
, m_areKeysEnabledInFullScreen(false)
, m_fullScreenRenderer(0)
, m_fullScreenChangeDelayTimer(this, &FullscreenElementStack::fullScreenChangeDelayTimerFired)
{
- document->setHasFullscreenElementStack();
+ document.setHasFullscreenElementStack();
}
FullscreenElementStack::~FullscreenElementStack()
@@ -126,7 +127,7 @@
void FullscreenElementStack::documentWasDisposed()
{
- m_fullScreenElement = 0;
+ m_fullScreenElement = nullptr;
m_fullScreenElementStack.clear();
}
@@ -138,6 +139,10 @@
void FullscreenElementStack::requestFullScreenForElement(Element* element, unsigned short flags, FullScreenCheckType checkType)
{
+ // Ignore this request if the document is not in a live frame.
+ if (!document()->isActive())
+ return;
+
// The Mozilla Full Screen API <https://wiki.mozilla.org/Gecko:FullScreenAPI> has different requirements
// for full screen mode, and do not have the concept of a full screen element stack.
bool inLegacyMozillaMode = (flags & Element::LEGACY_MOZILLA_REQUEST);
@@ -170,8 +175,9 @@
// A descendant browsing context's document has a non-empty fullscreen element stack.
bool descendentHasNonEmptyStack = false;
- for (Frame* descendant = document()->frame() ? document()->frame()->tree().traverseNext() : 0; descendant; descendant = descendant->tree().traverseNext()) {
- if (fullscreenElementFrom(descendant->document())) {
+ for (LocalFrame* descendant = document()->frame() ? document()->frame()->tree().traverseNext() : 0; descendant; descendant = descendant->tree().traverseNext()) {
+ ASSERT(descendant->document());
+ if (fullscreenElementFrom(*descendant->document())) {
descendentHasNonEmptyStack = true;
break;
}
@@ -184,7 +190,7 @@
// - an activation behavior is currently being processed whose click event was trusted, or
// - the event listener for a trusted click event is being handled.
// FIXME: Does this need to null-check settings()?
- if (!UserGestureIndicator::processingUserGesture() && (!element->isMediaElement() || document()->settings()->mediaFullscreenRequiresUserGesture()))
+ if (!UserGestureIndicator::processingUserGesture() && (!isHTMLMediaElement(*element) || document()->settings()->mediaFullscreenRequiresUserGesture()))
break;
// There is a previously-established user preference, security risk, or platform limitation.
@@ -217,19 +223,19 @@
// stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute
// set to true on the document.
if (!followingDoc) {
- from(currentDoc)->pushFullscreenElementStack(element);
+ from(*currentDoc).pushFullscreenElementStack(element);
addDocumentToFullScreenChangeEventQueue(currentDoc);
continue;
}
// 3. Otherwise, if document's fullscreen element stack is either empty or its top element
// is not following document's browsing context container,
- Element* topElement = fullscreenElementFrom(currentDoc);
+ Element* topElement = fullscreenElementFrom(*currentDoc);
if (!topElement || topElement != followingDoc->ownerElement()) {
// ...push following document's browsing context container on document's fullscreen element
// stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute
// set to true on document.
- from(currentDoc)->pushFullscreenElementStack(followingDoc->ownerElement());
+ from(*currentDoc).pushFullscreenElementStack(followingDoc->ownerElement());
addDocumentToFullScreenChangeEventQueue(currentDoc);
continue;
}
@@ -247,7 +253,7 @@
} while (0);
m_fullScreenErrorEventTargetQueue.append(element ? element : document()->documentElement());
- m_fullScreenChangeDelayTimer.startOneShot(0);
+ m_fullScreenChangeDelayTimer.startOneShot(0, FROM_HERE);
}
void FullscreenElementStack::webkitCancelFullScreen()
@@ -263,9 +269,9 @@
// calling webkitExitFullscreen():
Vector<RefPtr<Element> > replacementFullscreenElementStack;
replacementFullscreenElementStack.append(fullscreenElementFrom(document()->topDocument()));
- FullscreenElementStack* topFullscreenElementStack = from(document()->topDocument());
- topFullscreenElementStack->m_fullScreenElementStack.swap(replacementFullscreenElementStack);
- topFullscreenElementStack->webkitExitFullscreen();
+ FullscreenElementStack& topFullscreenElementStack = from(document()->topDocument());
+ topFullscreenElementStack.m_fullScreenElementStack.swap(replacementFullscreenElementStack);
+ topFullscreenElementStack.webkitExitFullscreen();
}
void FullscreenElementStack::webkitExitFullscreen()
@@ -284,15 +290,17 @@
// element stack (if any), ordered so that the child of the doc is last and the document furthest
// away from the doc is first.
Deque<RefPtr<Document> > descendants;
- for (Frame* descendant = document()->frame() ? document()->frame()->tree().traverseNext() : 0; descendant; descendant = descendant->tree().traverseNext()) {
- if (fullscreenElementFrom(descendant->document()))
+ for (LocalFrame* descendant = document()->frame() ? document()->frame()->tree().traverseNext() : 0; descendant; descendant = descendant->tree().traverseNext()) {
+ ASSERT(descendant->document());
+ if (fullscreenElementFrom(*descendant->document()))
descendants.prepend(descendant->document());
}
// 4. For each descendant in descendants, empty descendant's fullscreen element stack, and queue a
// task to fire an event named fullscreenchange with its bubbles attribute set to true on descendant.
for (Deque<RefPtr<Document> >::iterator i = descendants.begin(); i != descendants.end(); ++i) {
- from(i->get())->clearFullscreenElementStack();
+ ASSERT(*i);
+ from(**i).clearFullscreenElementStack();
addDocumentToFullScreenChangeEventQueue(i->get());
}
@@ -300,11 +308,11 @@
Element* newTop = 0;
while (currentDoc) {
// 1. Pop the top element of doc's fullscreen element stack.
- from(currentDoc)->popFullscreenElementStack();
+ from(*currentDoc).popFullscreenElementStack();
// If doc's fullscreen element stack is non-empty and the element now at the top is either
// not in a document or its node document is not doc, repeat this substep.
- newTop = fullscreenElementFrom(currentDoc);
+ newTop = fullscreenElementFrom(*currentDoc);
if (newTop && (!newTop->inDocument() || newTop->document() != currentDoc))
continue;
@@ -345,13 +353,13 @@
host->chrome().client().enterFullScreenForElement(newTop);
}
-bool FullscreenElementStack::webkitFullscreenEnabled(Document* document)
+bool FullscreenElementStack::webkitFullscreenEnabled(Document& document)
{
// 4. The fullscreenEnabled attribute must return true if the context object and all ancestor
// browsing context's documents have their fullscreen enabled flag set, or false otherwise.
// Top-level browsing contexts are implied to have their allowFullScreen attribute set.
- return isAttributeOnAllOwners(allowfullscreenAttr, webkitallowfullscreenAttr, document->ownerElement());
+ return isAttributeOnAllOwners(allowfullscreenAttr, webkitallowfullscreenAttr, document.ownerElement());
}
@@ -400,7 +408,7 @@
m_fullScreenElement->didBecomeFullscreenElement();
- m_fullScreenChangeDelayTimer.startOneShot(0);
+ m_fullScreenChangeDelayTimer.startOneShot(0, FROM_HERE);
}
void FullscreenElementStack::webkitWillExitFullScreenForElement(Element*)
@@ -429,7 +437,7 @@
if (m_fullScreenRenderer)
m_fullScreenRenderer->unwrapRenderer();
- m_fullScreenElement = 0;
+ m_fullScreenElement = nullptr;
document()->setNeedsStyleRecalc(SubtreeStyleChange);
// When webkitCancelFullScreen is called, we call webkitExitFullScreen on the topDocument(). That
@@ -437,8 +445,9 @@
// the exiting document.
Document* exitingDocument = document();
if (m_fullScreenChangeEventTargetQueue.isEmpty() && m_fullScreenErrorEventTargetQueue.isEmpty())
- exitingDocument = document()->topDocument();
- from(exitingDocument)->m_fullScreenChangeDelayTimer.startOneShot(0);
+ exitingDocument = &document()->topDocument();
+ ASSERT(exitingDocument);
+ from(*exitingDocument).m_fullScreenChangeDelayTimer.startOneShot(0, FROM_HERE);
}
void FullscreenElementStack::setFullScreenRenderer(RenderFullScreen* renderer)
@@ -557,7 +566,7 @@
ASSERT(doc);
Node* target = 0;
- if (FullscreenElementStack* fullscreen = fromIfExists(doc)) {
+ if (FullscreenElementStack* fullscreen = fromIfExists(*doc)) {
target = fullscreen->webkitFullscreenElement();
if (!target)
target = fullscreen->webkitCurrentFullScreenElement();
diff --git a/Source/core/dom/FullscreenElementStack.h b/Source/core/dom/FullscreenElementStack.h
index 346ea1e..71ac402 100644
--- a/Source/core/dom/FullscreenElementStack.h
+++ b/Source/core/dom/FullscreenElementStack.h
@@ -52,11 +52,11 @@
public:
virtual ~FullscreenElementStack();
static const char* supplementName();
- static FullscreenElementStack* from(Document*);
- static FullscreenElementStack* fromIfExists(Document*);
- static Element* fullscreenElementFrom(Document*);
- static Element* currentFullScreenElementFrom(Document*);
- static bool isFullScreen(Document*);
+ static FullscreenElementStack& from(Document&);
+ static FullscreenElementStack* fromIfExists(Document&);
+ static Element* fullscreenElementFrom(Document&);
+ static Element* currentFullScreenElementFrom(Document&);
+ static bool isFullScreen(Document&);
static bool isActiveFullScreenElement(const Element*);
enum FullScreenCheckType {
@@ -86,7 +86,7 @@
void removeFullScreenElementOfSubtree(Node*, bool amongChildrenOnly = false);
// W3C API
- static bool webkitFullscreenEnabled(Document*);
+ static bool webkitFullscreenEnabled(Document&);
Element* webkitFullscreenElement() const { return !m_fullScreenElementStack.isEmpty() ? m_fullScreenElementStack.last().get() : 0; }
void webkitExitFullscreen();
@@ -98,9 +98,9 @@
virtual void documentWasDisposed() OVERRIDE;
private:
- static FullscreenElementStack* fromIfExistsSlow(Document*);
+ static FullscreenElementStack* fromIfExistsSlow(Document&);
- explicit FullscreenElementStack(Document*);
+ explicit FullscreenElementStack(Document&);
Document* document();
void fullScreenChangeDelayTimerFired(Timer<FullscreenElementStack>*);
@@ -118,15 +118,15 @@
inline bool FullscreenElementStack::isActiveFullScreenElement(const Element* element)
{
- FullscreenElementStack* controller = fromIfExists(&element->document());
+ FullscreenElementStack* controller = fromIfExists(element->document());
if (!controller)
return false;
return controller->webkitIsFullScreen() && controller->webkitCurrentFullScreenElement() == element;
}
-inline FullscreenElementStack* FullscreenElementStack::fromIfExists(Document* document)
+inline FullscreenElementStack* FullscreenElementStack::fromIfExists(Document& document)
{
- if (!document->hasFullscreenElementStack())
+ if (!document.hasFullscreenElementStack())
return 0;
return fromIfExistsSlow(document);
}
diff --git a/Source/core/dom/IdTargetObserver.cpp b/Source/core/dom/IdTargetObserver.cpp
index 6957995..af185a0 100644
--- a/Source/core/dom/IdTargetObserver.cpp
+++ b/Source/core/dom/IdTargetObserver.cpp
@@ -31,16 +31,15 @@
namespace WebCore {
IdTargetObserver::IdTargetObserver(IdTargetObserverRegistry& registry, const AtomicString& id)
- : m_registry(®istry)
+ : m_registry(registry)
, m_id(id)
{
- m_registry->addObserver(m_id, this);
+ m_registry.addObserver(m_id, this);
}
IdTargetObserver::~IdTargetObserver()
{
- if (m_registry)
- m_registry->removeObserver(m_id, this);
+ m_registry.removeObserver(m_id, this);
}
} // namespace WebCore
diff --git a/Source/core/dom/IdTargetObserver.h b/Source/core/dom/IdTargetObserver.h
index e76b8a5..22f26bf 100644
--- a/Source/core/dom/IdTargetObserver.h
+++ b/Source/core/dom/IdTargetObserver.h
@@ -41,7 +41,7 @@
IdTargetObserver(IdTargetObserverRegistry&, const AtomicString& id);
private:
- IdTargetObserverRegistry* m_registry;
+ IdTargetObserverRegistry& m_registry;
AtomicString m_id;
};
diff --git a/Source/core/dom/IdTargetObserverRegistry.h b/Source/core/dom/IdTargetObserverRegistry.h
index b60af69..2f047ec 100644
--- a/Source/core/dom/IdTargetObserverRegistry.h
+++ b/Source/core/dom/IdTargetObserverRegistry.h
@@ -37,7 +37,7 @@
class IdTargetObserver;
class IdTargetObserverRegistry {
- WTF_MAKE_FAST_ALLOCATED;
+ WTF_MAKE_NONCOPYABLE(IdTargetObserverRegistry); WTF_MAKE_FAST_ALLOCATED;
friend class IdTargetObserver;
public:
static PassOwnPtr<IdTargetObserverRegistry> create();
diff --git a/Source/core/dom/LiveNodeList.cpp b/Source/core/dom/LiveNodeList.cpp
index d43ce2f..d079fb0 100644
--- a/Source/core/dom/LiveNodeList.cpp
+++ b/Source/core/dom/LiveNodeList.cpp
@@ -23,34 +23,16 @@
#include "config.h"
#include "core/dom/LiveNodeList.h"
-#include "core/dom/Element.h"
-#include "core/html/HTMLCollection.h"
-
namespace WebCore {
-ContainerNode& LiveNodeListBase::rootNode() const
+static inline bool isMatchingElement(const LiveNodeList& nodeList, const Element& element)
{
- if (isRootedAtDocument() && m_ownerNode->inDocument())
- return m_ownerNode->document();
- return *m_ownerNode;
-}
-
-void LiveNodeListBase::didMoveToDocument(Document& oldDocument, Document& newDocument)
-{
- invalidateCache(&oldDocument);
- oldDocument.unregisterNodeList(this);
- newDocument.registerNodeList(this);
-}
-
-void LiveNodeListBase::invalidateIdNameCacheMaps() const
-{
- ASSERT(hasIdNameCache());
- static_cast<const HTMLCollection*>(this)->invalidateIdNameCacheMaps();
+ return nodeList.elementMatches(element);
}
Node* LiveNodeList::virtualOwnerNode() const
{
- return ownerNode();
+ return &ownerNode();
}
void LiveNodeList::invalidateCache(Document*) const
@@ -58,4 +40,19 @@
m_collectionIndexCache.invalidate();
}
+Element* LiveNodeList::itemBefore(const Element* previous) const
+{
+ return LiveNodeListBase::itemBefore(*this, previous);
+}
+
+Element* LiveNodeList::traverseToFirstElement(const ContainerNode& root) const
+{
+ return firstMatchingElement(*this, root);
+}
+
+Element* LiveNodeList::traverseForwardToOffset(unsigned offset, Element& currentNode, unsigned& currentOffset, const ContainerNode& root) const
+{
+ return traverseMatchingElementsForwardToOffset(*this, offset, currentNode, currentOffset, root);
+}
+
} // namespace WebCore
diff --git a/Source/core/dom/LiveNodeList.h b/Source/core/dom/LiveNodeList.h
index 422e6bc..b9128e4 100644
--- a/Source/core/dom/LiveNodeList.h
+++ b/Source/core/dom/LiveNodeList.h
@@ -24,118 +24,26 @@
#ifndef LiveNodeList_h
#define LiveNodeList_h
-#include "HTMLNames.h"
-#include "core/dom/Document.h"
+#include "core/dom/LiveNodeListBase.h"
#include "core/dom/NodeList.h"
#include "core/html/CollectionIndexCache.h"
#include "core/html/CollectionType.h"
-#include "wtf/Forward.h"
-#include "wtf/RefPtr.h"
+#include "wtf/PassRefPtr.h"
namespace WebCore {
class Element;
-enum NodeListRootType {
- NodeListIsRootedAtNode,
- NodeListIsRootedAtDocument,
- NodeListIsRootedAtDocumentIfOwnerHasItemrefAttr,
-};
-
-class LiveNodeListBase {
-public:
- LiveNodeListBase(ContainerNode* ownerNode, NodeListRootType rootType, NodeListInvalidationType invalidationType,
- CollectionType collectionType)
- : m_ownerNode(ownerNode)
- , m_rootType(rootType)
- , m_invalidationType(invalidationType)
- , m_collectionType(collectionType)
- {
- ASSERT(m_ownerNode);
- ASSERT(m_rootType == static_cast<unsigned>(rootType));
- ASSERT(m_invalidationType == static_cast<unsigned>(invalidationType));
- ASSERT(m_collectionType == static_cast<unsigned>(collectionType));
-
- document().registerNodeList(this);
- }
-
- virtual ~LiveNodeListBase()
- {
- document().unregisterNodeList(this);
- }
-
- ContainerNode& rootNode() const;
-
- void didMoveToDocument(Document& oldDocument, Document& newDocument);
- ALWAYS_INLINE bool hasIdNameCache() const { return !isLiveNodeListType(type()); }
- ALWAYS_INLINE bool isRootedAtDocument() const { return m_rootType == NodeListIsRootedAtDocument || m_rootType == NodeListIsRootedAtDocumentIfOwnerHasItemrefAttr; }
- ALWAYS_INLINE NodeListInvalidationType invalidationType() const { return static_cast<NodeListInvalidationType>(m_invalidationType); }
- ALWAYS_INLINE CollectionType type() const { return static_cast<CollectionType>(m_collectionType); }
- ContainerNode* ownerNode() const { return m_ownerNode.get(); }
- ALWAYS_INLINE void invalidateCache(const QualifiedName* attrName) const
- {
- if (!attrName || shouldInvalidateTypeOnAttributeChange(invalidationType(), *attrName))
- invalidateCache();
- else if (hasIdNameCache() && (*attrName == HTMLNames::idAttr || *attrName == HTMLNames::nameAttr))
- invalidateIdNameCacheMaps();
- }
- virtual void invalidateCache(Document* oldDocument = 0) const = 0;
-
- static bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType, const QualifiedName&);
-
-protected:
- Document& document() const { return m_ownerNode->document(); }
-
- ALWAYS_INLINE NodeListRootType rootType() const { return static_cast<NodeListRootType>(m_rootType); }
-
- template <typename Collection>
- static Element* iterateForPreviousNode(const Collection&, Node* current);
- template <typename Collection>
- static Element* itemBefore(const Collection&, const Element* previousItem);
-
-private:
- void invalidateIdNameCacheMaps() const;
-
- RefPtr<ContainerNode> m_ownerNode; // Cannot be null.
- const unsigned m_rootType : 2;
- const unsigned m_invalidationType : 4;
- const unsigned m_collectionType : 5;
-};
-
-ALWAYS_INLINE bool LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType type, const QualifiedName& attrName)
-{
- switch (type) {
- case InvalidateOnClassAttrChange:
- return attrName == HTMLNames::classAttr;
- case InvalidateOnNameAttrChange:
- return attrName == HTMLNames::nameAttr;
- case InvalidateOnIdNameAttrChange:
- return attrName == HTMLNames::idAttr || attrName == HTMLNames::nameAttr;
- case InvalidateOnForAttrChange:
- return attrName == HTMLNames::forAttr;
- case InvalidateForFormControls:
- return attrName == HTMLNames::nameAttr || attrName == HTMLNames::idAttr || attrName == HTMLNames::forAttr
- || attrName == HTMLNames::formAttr || attrName == HTMLNames::typeAttr;
- case InvalidateOnHRefAttrChange:
- return attrName == HTMLNames::hrefAttr;
- case DoNotInvalidateOnAttributeChanges:
- return false;
- case InvalidateOnAnyAttrChange:
- return true;
- }
- return false;
-}
-
class LiveNodeList : public NodeList, public LiveNodeListBase {
public:
- LiveNodeList(PassRefPtr<ContainerNode> ownerNode, CollectionType collectionType, NodeListInvalidationType invalidationType, NodeListRootType rootType = NodeListIsRootedAtNode)
- : LiveNodeListBase(ownerNode.get(), rootType, invalidationType,
+ LiveNodeList(ContainerNode& ownerNode, CollectionType collectionType, NodeListInvalidationType invalidationType, NodeListRootType rootType = NodeListIsRootedAtNode)
+ : LiveNodeListBase(ownerNode, rootType, invalidationType,
collectionType)
{ }
virtual unsigned length() const OVERRIDE FINAL { return m_collectionIndexCache.nodeCount(*this); }
virtual Node* item(unsigned offset) const OVERRIDE FINAL { return m_collectionIndexCache.nodeAt(*this, offset); }
- virtual bool nodeMatches(const Element&) const = 0;
+ virtual bool elementMatches(const Element&) const = 0;
virtual void invalidateCache(Document* oldDocument) const OVERRIDE FINAL;
bool shouldOnlyIncludeDirectChildren() const { return false; }
diff --git a/Source/core/dom/LiveNodeListBase.cpp b/Source/core/dom/LiveNodeListBase.cpp
new file mode 100644
index 0000000..a4b1202
--- /dev/null
+++ b/Source/core/dom/LiveNodeListBase.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 Samsung Electronics. 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.
+ */
+
+#include "config.h"
+#include "core/dom/LiveNodeListBase.h"
+
+#include "core/html/HTMLCollection.h"
+
+namespace WebCore {
+
+ContainerNode& LiveNodeListBase::rootNode() const
+{
+ if (isRootedAtDocument() && m_ownerNode->inDocument())
+ return m_ownerNode->document();
+ return *m_ownerNode;
+}
+
+void LiveNodeListBase::didMoveToDocument(Document& oldDocument, Document& newDocument)
+{
+ invalidateCache(&oldDocument);
+ oldDocument.unregisterNodeList(this);
+ newDocument.registerNodeList(this);
+}
+
+void LiveNodeListBase::invalidateIdNameCacheMaps() const
+{
+ ASSERT(hasIdNameCache());
+ static_cast<const HTMLCollection*>(this)->invalidateIdNameCacheMaps();
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/LiveNodeListBase.h b/Source/core/dom/LiveNodeListBase.h
new file mode 100644
index 0000000..ecc1730
--- /dev/null
+++ b/Source/core/dom/LiveNodeListBase.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 Samsung Electronics. 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.
+ *
+ */
+
+#ifndef LiveNodeListBase_h
+#define LiveNodeListBase_h
+
+#include "HTMLNames.h"
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/ElementTraversal.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/html/CollectionType.h"
+
+namespace WebCore {
+
+enum NodeListRootType {
+ NodeListIsRootedAtNode,
+ NodeListIsRootedAtDocument
+};
+
+class LiveNodeListBase {
+public:
+ LiveNodeListBase(ContainerNode& ownerNode, NodeListRootType rootType, NodeListInvalidationType invalidationType,
+ CollectionType collectionType)
+ : m_ownerNode(ownerNode)
+ , m_rootType(rootType)
+ , m_invalidationType(invalidationType)
+ , m_collectionType(collectionType)
+ {
+ ASSERT(m_rootType == static_cast<unsigned>(rootType));
+ ASSERT(m_invalidationType == static_cast<unsigned>(invalidationType));
+ ASSERT(m_collectionType == static_cast<unsigned>(collectionType));
+
+ document().registerNodeList(this);
+ }
+
+ virtual ~LiveNodeListBase()
+ {
+ document().unregisterNodeList(this);
+ }
+
+ ContainerNode& rootNode() const;
+
+ void didMoveToDocument(Document& oldDocument, Document& newDocument);
+ ALWAYS_INLINE bool hasIdNameCache() const { return !isLiveNodeListType(type()); }
+ ALWAYS_INLINE bool isRootedAtDocument() const { return m_rootType == NodeListIsRootedAtDocument; }
+ ALWAYS_INLINE NodeListInvalidationType invalidationType() const { return static_cast<NodeListInvalidationType>(m_invalidationType); }
+ ALWAYS_INLINE CollectionType type() const { return static_cast<CollectionType>(m_collectionType); }
+ ContainerNode& ownerNode() const { return *m_ownerNode; }
+ ALWAYS_INLINE void invalidateCache(const QualifiedName* attrName) const
+ {
+ if (!attrName || shouldInvalidateTypeOnAttributeChange(invalidationType(), *attrName))
+ invalidateCache();
+ else if (hasIdNameCache() && (*attrName == HTMLNames::idAttr || *attrName == HTMLNames::nameAttr))
+ invalidateIdNameCacheMaps();
+ }
+ virtual void invalidateCache(Document* oldDocument = 0) const = 0;
+
+ static bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType, const QualifiedName&);
+
+protected:
+ Document& document() const { return m_ownerNode->document(); }
+
+ ALWAYS_INLINE NodeListRootType rootType() const { return static_cast<NodeListRootType>(m_rootType); }
+
+ template <typename Collection>
+ static Element* itemBefore(const Collection&, const Element* previousItem);
+ template <class NodeListType>
+ static Element* firstMatchingElement(const NodeListType&, const ContainerNode&);
+ template <class NodeListType>
+ static Element* nextMatchingElement(const NodeListType&, Element& current, const ContainerNode& root);
+ template <class NodeListType>
+ static Element* traverseMatchingElementsForwardToOffset(const NodeListType&, unsigned offset, Element& currentElement, unsigned& currentOffset, const ContainerNode& root);
+
+private:
+ void invalidateIdNameCacheMaps() const;
+ template <typename Collection>
+ static Element* iterateForPreviousNode(const Collection&, Node* current);
+ static Node* previousNode(const ContainerNode&, const Node& previous, bool onlyIncludeDirectChildren);
+ static Node* lastDescendant(const ContainerNode&);
+ static Node* lastNode(const ContainerNode&, bool onlyIncludeDirectChildren);
+
+ RefPtr<ContainerNode> m_ownerNode; // Cannot be null.
+ const unsigned m_rootType : 1;
+ const unsigned m_invalidationType : 4;
+ const unsigned m_collectionType : 5;
+};
+
+ALWAYS_INLINE bool LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType type, const QualifiedName& attrName)
+{
+ switch (type) {
+ case InvalidateOnClassAttrChange:
+ return attrName == HTMLNames::classAttr;
+ case InvalidateOnNameAttrChange:
+ return attrName == HTMLNames::nameAttr;
+ case InvalidateOnIdNameAttrChange:
+ return attrName == HTMLNames::idAttr || attrName == HTMLNames::nameAttr;
+ case InvalidateOnForAttrChange:
+ return attrName == HTMLNames::forAttr;
+ case InvalidateForFormControls:
+ return attrName == HTMLNames::nameAttr || attrName == HTMLNames::idAttr || attrName == HTMLNames::forAttr
+ || attrName == HTMLNames::formAttr || attrName == HTMLNames::typeAttr;
+ case InvalidateOnHRefAttrChange:
+ return attrName == HTMLNames::hrefAttr;
+ case DoNotInvalidateOnAttributeChanges:
+ return false;
+ case InvalidateOnAnyAttrChange:
+ return true;
+ }
+ return false;
+}
+
+inline Node* LiveNodeListBase::previousNode(const ContainerNode& base, const Node& previous, bool onlyIncludeDirectChildren)
+{
+ return onlyIncludeDirectChildren ? previous.previousSibling() : NodeTraversal::previous(previous, &base);
+}
+
+inline Node* LiveNodeListBase::lastDescendant(const ContainerNode& node)
+{
+ Node* descendant = node.lastChild();
+ for (Node* current = descendant; current; current = current->lastChild())
+ descendant = current;
+ return descendant;
+}
+
+inline Node* LiveNodeListBase::lastNode(const ContainerNode& rootNode, bool onlyIncludeDirectChildren)
+{
+ return onlyIncludeDirectChildren ? rootNode.lastChild() : lastDescendant(rootNode);
+}
+
+template <typename Collection>
+Element* LiveNodeListBase::iterateForPreviousNode(const Collection& collection, Node* current)
+{
+ bool onlyIncludeDirectChildren = collection.shouldOnlyIncludeDirectChildren();
+ ContainerNode& rootNode = collection.rootNode();
+ for (; current; current = previousNode(rootNode, *current, onlyIncludeDirectChildren)) {
+ if (current->isElementNode() && isMatchingElement(collection, toElement(*current)))
+ return toElement(current);
+ }
+ return 0;
+}
+
+template <typename Collection>
+Element* LiveNodeListBase::itemBefore(const Collection& collection, const Element* previous)
+{
+ Node* current;
+ if (LIKELY(!!previous)) // Without this LIKELY, length() and item() can be 10% slower.
+ current = previousNode(collection.rootNode(), *previous, collection.shouldOnlyIncludeDirectChildren());
+ else
+ current = lastNode(collection.rootNode(), collection.shouldOnlyIncludeDirectChildren());
+
+ return iterateForPreviousNode(collection, current);
+}
+
+template <class NodeListType>
+Element* LiveNodeListBase::firstMatchingElement(const NodeListType& nodeList, const ContainerNode& root)
+{
+ Element* element = ElementTraversal::firstWithin(root);
+ while (element && !isMatchingElement(nodeList, *element))
+ element = ElementTraversal::next(*element, &root);
+ return element;
+}
+
+template <class NodeListType>
+Element* LiveNodeListBase::nextMatchingElement(const NodeListType& nodeList, Element& current, const ContainerNode& root)
+{
+ Element* next = ¤t;
+ do {
+ next = ElementTraversal::next(*next, &root);
+ } while (next && !isMatchingElement(nodeList, *next));
+ return next;
+}
+
+template <class NodeListType>
+Element* LiveNodeListBase::traverseMatchingElementsForwardToOffset(const NodeListType& nodeList, unsigned offset, Element& currentElement, unsigned& currentOffset, const ContainerNode& root)
+{
+ ASSERT(currentOffset < offset);
+ Element* next = ¤tElement;
+ while ((next = nextMatchingElement(nodeList, *next, root))) {
+ if (++currentOffset == offset)
+ return next;
+ }
+ return 0;
+}
+
+} // namespace WebCore
+
+#endif // LiveNodeListBase_h
diff --git a/Source/core/dom/MainThreadTaskRunner.cpp b/Source/core/dom/MainThreadTaskRunner.cpp
index 976d971..d8b5310 100644
--- a/Source/core/dom/MainThreadTaskRunner.cpp
+++ b/Source/core/dom/MainThreadTaskRunner.cpp
@@ -99,7 +99,7 @@
{
ASSERT(m_suspended);
if (!m_pendingTasks.isEmpty())
- m_pendingTasksTimer.startOneShot(0);
+ m_pendingTasksTimer.startOneShot(0, FROM_HERE);
m_suspended = false;
}
diff --git a/Source/core/dom/MessagePort.cpp b/Source/core/dom/MessagePort.cpp
index 769a4ef..b5e1714 100644
--- a/Source/core/dom/MessagePort.cpp
+++ b/Source/core/dom/MessagePort.cpp
@@ -188,9 +188,7 @@
{
// The spec says that entangled message ports should always be treated as if they have a strong reference.
// We'll also stipulate that the queue needs to be open (if the app drops its reference to the port before start()-ing it, then it's not really entangled as it's unreachable).
- if (m_started && m_entangledChannel)
- return true;
- return isEntangled();
+ return m_started && isEntangled();
}
PassOwnPtr<MessagePortChannelArray> MessagePort::disentanglePorts(const MessagePortArray* ports, ExceptionState& exceptionState)
diff --git a/Source/core/dom/MessagePort.h b/Source/core/dom/MessagePort.h
index 65e0cba..8c4ab2a 100644
--- a/Source/core/dom/MessagePort.h
+++ b/Source/core/dom/MessagePort.h
@@ -45,7 +45,7 @@
class Event;
class ExceptionState;
-class Frame;
+class LocalFrame;
class MessagePort;
class ExecutionContext;
class SerializedScriptValue;
diff --git a/Source/core/dom/MutationObserver.cpp b/Source/core/dom/MutationObserver.cpp
index 21bdd69..6f4fb9e 100644
--- a/Source/core/dom/MutationObserver.cpp
+++ b/Source/core/dom/MutationObserver.cpp
@@ -119,25 +119,25 @@
if (!(options & Attributes)) {
if (options & AttributeOldValue) {
- exceptionState.throwDOMException(TypeError, "The options object may only set 'attributeOldValue' to true when 'attributes' is true or not present.");
+ exceptionState.throwTypeError("The options object may only set 'attributeOldValue' to true when 'attributes' is true or not present.");
return;
}
if (options & AttributeFilter) {
- exceptionState.throwDOMException(TypeError, "The options object may only set 'attributeFilter' when 'attributes' is true or not present.");
+ exceptionState.throwTypeError("The options object may only set 'attributeFilter' when 'attributes' is true or not present.");
return;
}
}
if (!((options & CharacterData) || !(options & CharacterDataOldValue))) {
- exceptionState.throwDOMException(TypeError, "The options object may only set 'characterDataOldValue' to true when 'characterData' is true or not present.");
+ exceptionState.throwTypeError("The options object may only set 'characterDataOldValue' to true when 'characterData' is true or not present.");
return;
}
if (!(options & (Attributes | CharacterData | ChildList))) {
- exceptionState.throwDOMException(TypeError, "The options object must set at least one of 'attributes', 'characterData', or 'childList' to true.");
+ exceptionState.throwTypeError("The options object must set at least one of 'attributes', 'characterData', or 'childList' to true.");
return;
}
- node->registerMutationObserver(this, options, attributeFilter);
+ node->registerMutationObserver(*this, options, attributeFilter);
}
Vector<RefPtr<MutationRecord> > MutationObserver::takeRecords()
diff --git a/Source/core/dom/MutationObserver.h b/Source/core/dom/MutationObserver.h
index a5f3aa3..086e600 100644
--- a/Source/core/dom/MutationObserver.h
+++ b/Source/core/dom/MutationObserver.h
@@ -33,6 +33,7 @@
#include "bindings/v8/ScriptWrappable.h"
#include "wtf/HashSet.h"
+#include "wtf/PassOwnPtr.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefCounted.h"
#include "wtf/RefPtr.h"
diff --git a/Source/core/dom/MutationObserverRegistration.cpp b/Source/core/dom/MutationObserverRegistration.cpp
index 1ece4d1..2680bb7 100644
--- a/Source/core/dom/MutationObserverRegistration.cpp
+++ b/Source/core/dom/MutationObserverRegistration.cpp
@@ -37,12 +37,12 @@
namespace WebCore {
-PassOwnPtr<MutationObserverRegistration> MutationObserverRegistration::create(PassRefPtr<MutationObserver> observer, Node* registrationNode, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter)
+PassOwnPtr<MutationObserverRegistration> MutationObserverRegistration::create(MutationObserver& observer, Node& registrationNode, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter)
{
return adoptPtr(new MutationObserverRegistration(observer, registrationNode, options, attributeFilter));
}
-MutationObserverRegistration::MutationObserverRegistration(PassRefPtr<MutationObserver> observer, Node* registrationNode, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter)
+MutationObserverRegistration::MutationObserverRegistration(MutationObserver& observer, Node& registrationNode, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter)
: m_observer(observer)
, m_registrationNode(registrationNode)
, m_options(options)
@@ -64,21 +64,21 @@
m_attributeFilter = attributeFilter;
}
-void MutationObserverRegistration::observedSubtreeNodeWillDetach(Node* node)
+void MutationObserverRegistration::observedSubtreeNodeWillDetach(Node& node)
{
if (!isSubtree())
return;
- node->registerTransientMutationObserver(this);
+ node.registerTransientMutationObserver(this);
m_observer->setHasTransientRegistration();
if (!m_transientRegistrationNodes) {
m_transientRegistrationNodes = adoptPtr(new NodeHashSet);
ASSERT(!m_registrationNodeKeepAlive);
- m_registrationNodeKeepAlive = m_registrationNode; // Balanced in clearTransientRegistrations.
+ m_registrationNodeKeepAlive = PassRefPtr<Node>(m_registrationNode); // Balanced in clearTransientRegistrations.
}
- m_transientRegistrationNodes->add(node);
+ m_transientRegistrationNodes->add(&node);
}
void MutationObserverRegistration::clearTransientRegistrations()
@@ -94,16 +94,16 @@
m_transientRegistrationNodes.clear();
ASSERT(m_registrationNodeKeepAlive);
- m_registrationNodeKeepAlive = 0; // Balanced in observeSubtreeNodeWillDetach.
+ m_registrationNodeKeepAlive = nullptr; // Balanced in observeSubtreeNodeWillDetach.
}
void MutationObserverRegistration::unregister()
{
- m_registrationNode->unregisterMutationObserver(this);
+ m_registrationNode.unregisterMutationObserver(this);
// The above line will cause this object to be deleted, so don't do any more in this function.
}
-bool MutationObserverRegistration::shouldReceiveMutationFrom(Node* node, MutationObserver::MutationType type, const QualifiedName* attributeName) const
+bool MutationObserverRegistration::shouldReceiveMutationFrom(Node& node, MutationObserver::MutationType type, const QualifiedName* attributeName) const
{
ASSERT((type == MutationObserver::Attributes && attributeName) || !attributeName);
if (!(m_options & type))
@@ -123,7 +123,7 @@
void MutationObserverRegistration::addRegistrationNodesToSet(HashSet<Node*>& nodes) const
{
- nodes.add(m_registrationNode);
+ nodes.add(&m_registrationNode);
if (!m_transientRegistrationNodes)
return;
for (NodeHashSet::const_iterator iter = m_transientRegistrationNodes->begin(); iter != m_transientRegistrationNodes->end(); ++iter)
diff --git a/Source/core/dom/MutationObserverRegistration.h b/Source/core/dom/MutationObserverRegistration.h
index 7c0fb52..8bc80d4 100644
--- a/Source/core/dom/MutationObserverRegistration.h
+++ b/Source/core/dom/MutationObserverRegistration.h
@@ -42,29 +42,29 @@
class MutationObserverRegistration {
public:
- static PassOwnPtr<MutationObserverRegistration> create(PassRefPtr<MutationObserver>, Node*, MutationObserverOptions, const HashSet<AtomicString>& attributeFilter);
+ static PassOwnPtr<MutationObserverRegistration> create(MutationObserver&, Node&, MutationObserverOptions, const HashSet<AtomicString>& attributeFilter);
~MutationObserverRegistration();
void resetObservation(MutationObserverOptions, const HashSet<AtomicString>& attributeFilter);
- void observedSubtreeNodeWillDetach(Node*);
+ void observedSubtreeNodeWillDetach(Node&);
void clearTransientRegistrations();
bool hasTransientRegistrations() const { return m_transientRegistrationNodes && !m_transientRegistrationNodes->isEmpty(); }
void unregister();
- bool shouldReceiveMutationFrom(Node*, MutationObserver::MutationType, const QualifiedName* attributeName) const;
+ bool shouldReceiveMutationFrom(Node&, MutationObserver::MutationType, const QualifiedName* attributeName) const;
bool isSubtree() const { return m_options & MutationObserver::Subtree; }
- MutationObserver* observer() const { return m_observer.get(); }
+ MutationObserver& observer() const { return *m_observer; }
MutationRecordDeliveryOptions deliveryOptions() const { return m_options & (MutationObserver::AttributeOldValue | MutationObserver::CharacterDataOldValue); }
MutationObserverOptions mutationTypes() const { return m_options & MutationObserver::AllMutationTypes; }
void addRegistrationNodesToSet(HashSet<Node*>&) const;
private:
- MutationObserverRegistration(PassRefPtr<MutationObserver>, Node*, MutationObserverOptions, const HashSet<AtomicString>& attributeFilter);
+ MutationObserverRegistration(MutationObserver&, Node&, MutationObserverOptions, const HashSet<AtomicString>& attributeFilter);
RefPtr<MutationObserver> m_observer;
- Node* m_registrationNode;
+ Node& m_registrationNode;
RefPtr<Node> m_registrationNodeKeepAlive;
typedef HashSet<RefPtr<Node> > NodeHashSet;
OwnPtr<NodeHashSet> m_transientRegistrationNodes;
diff --git a/Source/core/dom/NameNodeList.cpp b/Source/core/dom/NameNodeList.cpp
index 6393eba..0c0e385 100644
--- a/Source/core/dom/NameNodeList.cpp
+++ b/Source/core/dom/NameNodeList.cpp
@@ -31,7 +31,7 @@
using namespace HTMLNames;
-NameNodeList::NameNodeList(PassRefPtr<ContainerNode> rootNode, const AtomicString& name)
+NameNodeList::NameNodeList(ContainerNode& rootNode, const AtomicString& name)
: LiveNodeList(rootNode, NameNodeListType, InvalidateOnNameAttrChange)
, m_name(name)
{
@@ -39,12 +39,12 @@
NameNodeList::~NameNodeList()
{
- ownerNode()->nodeLists()->removeCache(this, NameNodeListType, m_name);
+ ownerNode().nodeLists()->removeCache(this, NameNodeListType, m_name);
}
-bool NameNodeList::nodeMatches(const Element& testNode) const
+bool NameNodeList::elementMatches(const Element& element) const
{
- return testNode.getNameAttribute() == m_name;
+ return element.getNameAttribute() == m_name;
}
} // namespace WebCore
diff --git a/Source/core/dom/NameNodeList.h b/Source/core/dom/NameNodeList.h
index 2212fb1..438a164 100644
--- a/Source/core/dom/NameNodeList.h
+++ b/Source/core/dom/NameNodeList.h
@@ -33,7 +33,7 @@
// NodeList which lists all Nodes in a Element with a given "name" attribute
class NameNodeList FINAL : public LiveNodeList {
public:
- static PassRefPtr<NameNodeList> create(PassRefPtr<ContainerNode> rootNode, CollectionType type, const AtomicString& name)
+ static PassRefPtr<NameNodeList> create(ContainerNode& rootNode, CollectionType type, const AtomicString& name)
{
ASSERT_UNUSED(type, type == NameNodeListType);
return adoptRef(new NameNodeList(rootNode, name));
@@ -42,9 +42,9 @@
virtual ~NameNodeList();
private:
- NameNodeList(PassRefPtr<ContainerNode> rootNode, const AtomicString& name);
+ NameNodeList(ContainerNode& rootNode, const AtomicString& name);
- virtual bool nodeMatches(const Element&) const OVERRIDE;
+ virtual bool elementMatches(const Element&) const OVERRIDE;
AtomicString m_name;
};
diff --git a/Source/core/dom/NamedNodeMap.cpp b/Source/core/dom/NamedNodeMap.cpp
index 499f7b6..00280fa 100644
--- a/Source/core/dom/NamedNodeMap.cpp
+++ b/Source/core/dom/NamedNodeMap.cpp
@@ -60,7 +60,7 @@
size_t index = m_element->hasAttributes() ? m_element->getAttributeItemIndex(name, m_element->shouldIgnoreAttributeCase()) : kNotFound;
if (index == kNotFound) {
exceptionState.throwDOMException(NotFoundError, "No item with name '" + name + "' was found.");
- return 0;
+ return nullptr;
}
return m_element->detachAttribute(index);
}
@@ -70,7 +70,7 @@
size_t index = m_element->hasAttributes() ? m_element->getAttributeItemIndex(QualifiedName(nullAtom, localName, namespaceURI)) : kNotFound;
if (index == kNotFound) {
exceptionState.throwDOMException(NotFoundError, "No item with name '" + namespaceURI + "::" + localName + "' was found.");
- return 0;
+ return nullptr;
}
return m_element->detachAttribute(index);
}
@@ -79,13 +79,13 @@
{
if (!node) {
exceptionState.throwDOMException(NotFoundError, "The node provided was null.");
- return 0;
+ return nullptr;
}
// Not mentioned in spec: throw a HIERARCHY_REQUEST_ERROR if the user passes in a non-attribute node
if (!node->isAttributeNode()) {
exceptionState.throwDOMException(HierarchyRequestError, "The node provided is not an attribute node.");
- return 0;
+ return nullptr;
}
return m_element->setAttributeNode(toAttr(node), exceptionState);
@@ -99,8 +99,8 @@
PassRefPtr<Node> NamedNodeMap::item(unsigned index) const
{
if (index >= length())
- return 0;
- return m_element->ensureAttr(m_element->attributeItem(index)->name());
+ return nullptr;
+ return m_element->ensureAttr(m_element->attributeItem(index).name());
}
size_t NamedNodeMap::length() const
diff --git a/Source/core/dom/Node.cpp b/Source/core/dom/Node.cpp
index 1671ca9..59a60dc 100644
--- a/Source/core/dom/Node.cpp
+++ b/Source/core/dom/Node.cpp
@@ -73,13 +73,13 @@
#include "core/events/TouchEvent.h"
#include "core/events/UIEvent.h"
#include "core/events/WheelEvent.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLAnchorElement.h"
#include "core/html/HTMLDialogElement.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/HTMLStyleElement.h"
#include "core/page/ContextMenuController.h"
#include "core/page/EventHandler.h"
-#include "core/frame/Frame.h"
#include "core/page/Page.h"
#include "core/frame/Settings.h"
#include "core/rendering/FlowThreadController.h"
@@ -295,7 +295,7 @@
if (AXObjectCache* cache = document.existingAXObjectCache())
cache->remove(this);
- document.markers()->removeMarkers(this);
+ document.markers().removeMarkers(this);
}
NodeRareData* Node::rareData() const
@@ -358,8 +358,8 @@
PassRefPtr<NodeList> Node::childNodes()
{
if (isContainerNode())
- return ensureRareData().ensureNodeLists().ensureChildNodeList(toContainerNode(this));
- return ensureRareData().ensureNodeLists().ensureEmptyChildNodeList(this);
+ return ensureRareData().ensureNodeLists().ensureChildNodeList(toContainerNode(*this));
+ return ensureRareData().ensureNodeLists().ensureEmptyChildNodeList(*this);
}
Node& Node::lastDescendant() const
@@ -648,7 +648,8 @@
void Node::markAncestorsWithChildNeedsStyleInvalidation()
{
- for (Node* node = this; node && !node->childNeedsStyleInvalidation(); node = node->parentOrShadowHostNode())
+ Node* node = this;
+ for (; node && !node->childNeedsStyleInvalidation(); node = node->parentOrShadowHostNode())
node->setChildNeedsStyleInvalidation();
if (document().childNeedsStyleInvalidation())
document().scheduleStyleRecalc();
@@ -814,40 +815,6 @@
return count;
}
-template<unsigned type>
-bool shouldInvalidateNodeListCachesForAttr(const unsigned nodeListCounts[], const QualifiedName& attrName)
-{
- if (nodeListCounts[type] && LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(static_cast<NodeListInvalidationType>(type), attrName))
- return true;
- return shouldInvalidateNodeListCachesForAttr<type + 1>(nodeListCounts, attrName);
-}
-
-template<>
-bool shouldInvalidateNodeListCachesForAttr<numNodeListInvalidationTypes>(const unsigned[], const QualifiedName&)
-{
- return false;
-}
-
-bool Document::shouldInvalidateNodeListCaches(const QualifiedName* attrName) const
-{
- if (attrName)
- return shouldInvalidateNodeListCachesForAttr<DoNotInvalidateOnAttributeChanges + 1>(m_nodeListCounts, *attrName);
-
- for (int type = 0; type < numNodeListInvalidationTypes; type++) {
- if (m_nodeListCounts[type])
- return true;
- }
-
- return false;
-}
-
-void Document::invalidateNodeListCaches(const QualifiedName* attrName)
-{
- HashSet<LiveNodeListBase*>::iterator end = m_listsInvalidatedAtDocument.end();
- for (HashSet<LiveNodeListBase*>::iterator it = m_listsInvalidatedAtDocument.begin(); it != end; ++it)
- (*it)->invalidateCache(attrName);
-}
-
void Node::invalidateNodeListCachesInAncestors(const QualifiedName* attrName, Element* attributeOwnerElement)
{
if (hasRareData() && (!attrName || isAttributeNode())) {
@@ -883,7 +850,7 @@
bool Node::isDescendantOf(const Node *other) const
{
// Return true if other is an ancestor of this, otherwise false
- if (!other || !other->hasChildNodes() || inDocument() != other->inDocument())
+ if (!other || !other->hasChildren() || inDocument() != other->inDocument())
return false;
if (other->treeScope() != treeScope())
return false;
@@ -917,7 +884,7 @@
if (inDocument() != node->inDocument())
return false;
- bool hasChildren = isContainerNode() && toContainerNode(this)->hasChildNodes();
+ bool hasChildren = isContainerNode() && toContainerNode(this)->hasChildren();
bool hasShadow = isElementNode() && toElement(this)->shadow();
if (!hasChildren && !hasShadow)
return false;
@@ -1039,6 +1006,8 @@
setStyleChange(NeedsReattachStyleChange);
setChildNeedsStyleRecalc();
+ if (StyleResolver* resolver = document().styleResolver())
+ resolver->ruleFeatureSet().clearStyleInvalidation(this);
#ifndef NDEBUG
detachingNode = 0;
@@ -1222,7 +1191,7 @@
n = n->parentNode();
if (!n)
break;
- if (n->isBlockFlowElement() || n->hasTagName(bodyTag))
+ if (n->isBlockFlowElement() || isHTMLBodyElement(*n))
return toElement(n);
}
return 0;
@@ -1231,7 +1200,7 @@
bool Node::isRootEditableElement() const
{
return rendererIsEditable() && isElementNode() && (!parentNode() || !parentNode()->rendererIsEditable()
- || !parentNode()->isElementNode() || hasTagName(bodyTag));
+ || !parentNode()->isElementNode() || isHTMLBodyElement((*this)));
}
Element* Node::rootEditableElement(EditableType editableType) const
@@ -1250,7 +1219,7 @@
for (Node* n = const_cast<Node*>(this); n && n->rendererIsEditable(); n = n->parentNode()) {
if (n->isElementNode())
result = toElement(n);
- if (n->hasTagName(bodyTag))
+ if (isHTMLBodyElement(*n))
break;
}
return result;
@@ -1341,11 +1310,12 @@
return elem->namespaceURI() == namespaceURI;
if (elem->hasAttributes()) {
- for (unsigned i = 0; i < elem->attributeCount(); i++) {
- const Attribute* attr = elem->attributeItem(i);
+ unsigned attributeCount = elem->attributeCount();
+ for (unsigned i = 0; i < attributeCount; ++i) {
+ const Attribute& attr = elem->attributeItem(i);
- if (attr->localName() == xmlnsAtom)
- return attr->value() == namespaceURI;
+ if (attr.localName() == xmlnsAtom)
+ return attr.value() == namespaceURI;
}
}
@@ -1426,17 +1396,19 @@
return elem->namespaceURI();
if (elem->hasAttributes()) {
- for (unsigned i = 0; i < elem->attributeCount(); i++) {
- const Attribute* attr = elem->attributeItem(i);
+ unsigned attributeCount = elem->attributeCount();
+ for (unsigned i = 0; i < attributeCount; ++i) {
+ const Attribute& attr = elem->attributeItem(i);
- if (attr->prefix() == xmlnsAtom && attr->localName() == prefix) {
- if (!attr->value().isEmpty())
- return attr->value();
+ if (attr.prefix() == xmlnsAtom && attr.localName() == prefix) {
+ if (!attr.value().isEmpty())
+ return attr.value();
return nullAtom;
- } else if (attr->localName() == xmlnsAtom && prefix.isNull()) {
- if (!attr->value().isEmpty())
- return attr->value();
+ }
+ if (attr.localName() == xmlnsAtom && prefix.isNull()) {
+ if (!attr.value().isEmpty())
+ return attr.value();
return nullAtom;
}
@@ -1483,7 +1455,7 @@
break;
case Node::ELEMENT_NODE:
- if (node->hasTagName(brTag) && convertBRsToNewlines) {
+ if (isHTMLBRElement(*node) && convertBRsToNewlines) {
isNullString = false;
content.append('\n');
break;
@@ -1590,10 +1562,10 @@
// the same nodeType are inserted into or removed from the direct container. This would be the case, for example,
// when comparing two attributes of the same element, and inserting or removing additional attributes might change
// the order between existing attributes.
- const Attribute* attribute = owner1->attributeItem(i);
- if (attr1->qualifiedName() == attribute->name())
+ const Attribute& attribute = owner1->attributeItem(i);
+ if (attr1->qualifiedName() == attribute.name())
return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_FOLLOWING;
- if (attr2->qualifiedName() == attribute->name())
+ if (attr2->qualifiedName() == attribute.name())
return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_PRECEDING;
}
@@ -1737,7 +1709,9 @@
return;
stringBuilder.append(attrDesc);
+ stringBuilder.append("=\"");
stringBuilder.append(attr);
+ stringBuilder.append("\"");
}
void Node::showNode(const char* prefix) const
@@ -1751,8 +1725,9 @@
fprintf(stderr, "%s%s\t%p \"%s\"\n", prefix, nodeName().utf8().data(), this, value.utf8().data());
} else {
StringBuilder attrs;
- appendAttributeDesc(this, attrs, classAttr, " CLASS=");
- appendAttributeDesc(this, attrs, styleAttr, " STYLE=");
+ appendAttributeDesc(this, attrs, idAttr, " ID");
+ appendAttributeDesc(this, attrs, classAttr, " CLASS");
+ appendAttributeDesc(this, attrs, styleAttr, " STYLE");
fprintf(stderr, "%s%s\t%p%s\n", prefix, nodeName().utf8().data(), this, attrs.toString().utf8().data());
}
}
@@ -1841,7 +1816,7 @@
{
const Node* rootNode;
const Node* node = this;
- while (node->parentOrShadowHostNode() && !node->hasTagName(bodyTag))
+ while (node->parentOrShadowHostNode() && !isHTMLBodyElement(*node))
node = node->parentOrShadowHostNode();
rootNode = node;
@@ -1908,7 +1883,7 @@
// For imagemaps, the enclosing link node is the associated area element not the image itself.
// So we don't let images be the enclosingLinkNode, even though isLink sometimes returns true
// for them.
- if (node->isLink() && !node->hasTagName(imgTag))
+ if (node->isLink() && !isHTMLImageElement(*node))
return node;
}
@@ -1944,17 +1919,17 @@
}
const EventListenerVector& mousewheelListeners = getEventListeners(EventTypeNames::mousewheel);
- WheelController* oldController = WheelController::from(&oldDocument);
- WheelController* newController = WheelController::from(&document());
+ WheelController* oldController = WheelController::from(oldDocument);
+ WheelController* newController = WheelController::from(document());
for (size_t i = 0; i < mousewheelListeners.size(); ++i) {
- oldController->didRemoveWheelEventHandler(&oldDocument);
- newController->didAddWheelEventHandler(&document());
+ oldController->didRemoveWheelEventHandler(oldDocument);
+ newController->didAddWheelEventHandler(document());
}
const EventListenerVector& wheelListeners = getEventListeners(EventTypeNames::wheel);
for (size_t i = 0; i < wheelListeners.size(); ++i) {
- oldController->didRemoveWheelEventHandler(&oldDocument);
- newController->didAddWheelEventHandler(&document());
+ oldController->didRemoveWheelEventHandler(oldDocument);
+ newController->didAddWheelEventHandler(document());
}
if (const TouchEventTargetSet* touchHandlers = oldDocument.touchEventTargets()) {
@@ -1985,7 +1960,7 @@
Document& document = targetNode->document();
document.addListenerTypeIfNeeded(eventType);
if (eventType == EventTypeNames::wheel || eventType == EventTypeNames::mousewheel)
- WheelController::from(&document)->didAddWheelEventHandler(&document);
+ WheelController::from(document)->didAddWheelEventHandler(document);
else if (isTouchEventType(eventType))
document.didAddTouchEventHandler(targetNode);
@@ -2006,7 +1981,7 @@
// listeners for each type, not just a bool - see https://bugs.webkit.org/show_bug.cgi?id=33861
Document& document = targetNode->document();
if (eventType == EventTypeNames::wheel || eventType == EventTypeNames::mousewheel)
- WheelController::from(&document)->didAddWheelEventHandler(&document);
+ WheelController::from(document)->didRemoveWheelEventHandler(document);
else if (isTouchEventType(eventType))
document.didRemoveTouchEventHandler(targetNode);
@@ -2073,7 +2048,7 @@
}
template<typename Registry>
-static inline void collectMatchingObserversForMutation(HashMap<MutationObserver*, MutationRecordDeliveryOptions>& observers, Registry* registry, Node* target, MutationObserver::MutationType type, const QualifiedName* attributeName)
+static inline void collectMatchingObserversForMutation(HashMap<MutationObserver*, MutationRecordDeliveryOptions>& observers, Registry* registry, Node& target, MutationObserver::MutationType type, const QualifiedName* attributeName)
{
if (!registry)
return;
@@ -2081,7 +2056,7 @@
const MutationObserverRegistration& registration = **iter;
if (registration.shouldReceiveMutationFrom(target, type, attributeName)) {
MutationRecordDeliveryOptions deliveryOptions = registration.deliveryOptions();
- HashMap<MutationObserver*, MutationRecordDeliveryOptions>::AddResult result = observers.add(registration.observer(), deliveryOptions);
+ HashMap<MutationObserver*, MutationRecordDeliveryOptions>::AddResult result = observers.add(®istration.observer(), deliveryOptions);
if (!result.isNewEntry)
result.storedValue->value |= deliveryOptions;
}
@@ -2091,27 +2066,27 @@
void Node::getRegisteredMutationObserversOfType(HashMap<MutationObserver*, MutationRecordDeliveryOptions>& observers, MutationObserver::MutationType type, const QualifiedName* attributeName)
{
ASSERT((type == MutationObserver::Attributes && attributeName) || !attributeName);
- collectMatchingObserversForMutation(observers, mutationObserverRegistry(), this, type, attributeName);
- collectMatchingObserversForMutation(observers, transientMutationObserverRegistry(), this, type, attributeName);
+ collectMatchingObserversForMutation(observers, mutationObserverRegistry(), *this, type, attributeName);
+ collectMatchingObserversForMutation(observers, transientMutationObserverRegistry(), *this, type, attributeName);
for (Node* node = parentNode(); node; node = node->parentNode()) {
- collectMatchingObserversForMutation(observers, node->mutationObserverRegistry(), this, type, attributeName);
- collectMatchingObserversForMutation(observers, node->transientMutationObserverRegistry(), this, type, attributeName);
+ collectMatchingObserversForMutation(observers, node->mutationObserverRegistry(), *this, type, attributeName);
+ collectMatchingObserversForMutation(observers, node->transientMutationObserverRegistry(), *this, type, attributeName);
}
}
-void Node::registerMutationObserver(MutationObserver* observer, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter)
+void Node::registerMutationObserver(MutationObserver& observer, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter)
{
MutationObserverRegistration* registration = 0;
Vector<OwnPtr<MutationObserverRegistration> >& registry = ensureRareData().ensureMutationObserverData().registry;
for (size_t i = 0; i < registry.size(); ++i) {
- if (registry[i]->observer() == observer) {
+ if (®istry[i]->observer() == &observer) {
registration = registry[i].get();
registration->resetObservation(options, attributeFilter);
}
}
if (!registration) {
- registry.append(MutationObserverRegistration::create(observer, this, options, attributeFilter));
+ registry.append(MutationObserverRegistration::create(observer, *this, options, attributeFilter));
registration = registry.last().get();
}
@@ -2162,12 +2137,12 @@
if (Vector<OwnPtr<MutationObserverRegistration> >* registry = node->mutationObserverRegistry()) {
const size_t size = registry->size();
for (size_t i = 0; i < size; ++i)
- registry->at(i)->observedSubtreeNodeWillDetach(this);
+ registry->at(i)->observedSubtreeNodeWillDetach(*this);
}
if (HashSet<MutationObserverRegistration*>* transientRegistry = node->transientMutationObserverRegistry()) {
for (HashSet<MutationObserverRegistration*>::iterator iter = transientRegistry->begin(); iter != transientRegistry->end(); ++iter)
- (*iter)->observedSubtreeNodeWillDetach(this);
+ (*iter)->observedSubtreeNodeWillDetach(*this);
}
}
}
@@ -2284,7 +2259,7 @@
const AtomicString& eventType = event->type();
if (eventType == EventTypeNames::keydown || eventType == EventTypeNames::keypress) {
if (event->isKeyboardEvent()) {
- if (Frame* frame = document().frame())
+ if (LocalFrame* frame = document().frame())
frame->eventHandler().defaultKeyboardEventHandler(toKeyboardEvent(event));
}
} else if (eventType == EventTypeNames::click) {
@@ -2296,7 +2271,7 @@
page->contextMenuController().handleContextMenuEvent(event);
} else if (eventType == EventTypeNames::textInput) {
if (event->hasInterface(EventNames::TextEvent)) {
- if (Frame* frame = document().frame())
+ if (LocalFrame* frame = document().frame())
frame->eventHandler().defaultTextInputEventHandler(toTextEvent(event));
}
#if OS(WIN)
@@ -2311,7 +2286,7 @@
renderer = renderer->parent();
if (renderer) {
- if (Frame* frame = document().frame())
+ if (LocalFrame* frame = document().frame())
frame->eventHandler().startPanScrolling(renderer);
}
}
@@ -2326,7 +2301,7 @@
startNode = startNode->parentOrShadowHostNode();
if (startNode && startNode->renderer()) {
- if (Frame* frame = document().frame())
+ if (LocalFrame* frame = document().frame())
frame->eventHandler().defaultWheelEventHandler(startNode, wheelEvent);
}
} else if (event->type() == EventTypeNames::webkitEditableContentChanged) {
@@ -2471,9 +2446,9 @@
size_t Node::numberOfScopedHTMLStyleChildren() const
{
size_t count = 0;
- for (Node* child = firstChild(); child; child = child->nextSibling()) {
- if (child->hasTagName(HTMLNames::styleTag) && toHTMLStyleElement(child)->isRegisteredAsScoped())
- count++;
+ for (HTMLStyleElement* style = Traversal<HTMLStyleElement>::firstChild(*this); style; style = Traversal<HTMLStyleElement>::nextSibling(*style)) {
+ if (style->isRegisteredAsScoped())
+ ++count;
}
return count;
@@ -2548,6 +2523,12 @@
#ifndef NDEBUG
+void showNode(const WebCore::Node* node)
+{
+ if (node)
+ node->showNode("");
+}
+
void showTree(const WebCore::Node* node)
{
if (node)
diff --git a/Source/core/dom/Node.h b/Source/core/dom/Node.h
index 3ee5488..33d1ff2 100644
--- a/Source/core/dom/Node.h
+++ b/Source/core/dom/Node.h
@@ -57,7 +57,7 @@
class EventListener;
class ExceptionState;
class FloatPoint;
-class Frame;
+class LocalFrame;
class HTMLInputElement;
class IntRect;
class KeyboardEvent;
@@ -172,6 +172,7 @@
virtual NodeType nodeType() const = 0;
ContainerNode* parentNode() const;
Element* parentElement() const;
+ Node* parentElementOrShadowRoot() const;
Node* previousSibling() const { return m_previous; }
Node* nextSibling() const { return m_next; }
PassRefPtr<NodeList> childNodes();
@@ -194,7 +195,7 @@
void removeChild(Node* child, ExceptionState&);
void appendChild(PassRefPtr<Node> newChild, ExceptionState& = ASSERT_NO_EXCEPTION);
- bool hasChildNodes() const { return firstChild(); }
+ bool hasChildren() const { return firstChild(); }
virtual PassRefPtr<Node> cloneNode(bool deep = false) = 0;
virtual const AtomicString& localName() const;
virtual const AtomicString& namespaceURI() const;
@@ -282,7 +283,7 @@
ContainerNode* parentOrShadowHostNode() const;
Element* parentOrShadowHostElement() const;
void setParentOrShadowHostNode(ContainerNode*);
- Node* highestAncestor() const;
+ Node& highestAncestor() const;
// Knows about all kinds of hosts.
ContainerNode* parentOrShadowHostOrTemplateHostNode() const;
@@ -370,6 +371,7 @@
void clearChildNeedsStyleInvalidation() { clearFlag(ChildNeedsStyleInvalidation); }
void markAncestorsWithChildNeedsStyleInvalidation();
bool needsStyleInvalidation() { return getFlag(NeedsStyleInvalidation); }
+ void clearNeedsStyleInvalidation() { clearFlag(NeedsStyleInvalidation); }
void setNeedsStyleInvalidation();
void recalcDistribution();
@@ -473,8 +475,8 @@
bool isDocumentTypeNode() const { return nodeType() == DOCUMENT_TYPE_NODE; }
virtual bool childTypeAllowed(NodeType) const { return false; }
- unsigned childNodeCount() const;
- Node* childNode(unsigned index) const;
+ unsigned countChildren() const;
+ Node* traverseToChildAt(unsigned index) const;
bool isDescendantOf(const Node*) const;
bool contains(const Node*) const;
@@ -560,7 +562,7 @@
//
// There are another callback named didNotifySubtreeInsertionsToDocument(), which is called after all the descendant is notified,
// if this node was inserted into the document tree. Only a few subclasses actually need this. To utilize this, the node should
- // return InsertionShouldCallDidNotifySubtreeInsertions from insrtedInto().
+ // return InsertionShouldCallDidNotifySubtreeInsertions from insertedInto().
//
enum InsertionNotificationRequest {
InsertionDone,
@@ -650,7 +652,7 @@
virtual EventTargetData& ensureEventTargetData() OVERRIDE;
void getRegisteredMutationObserversOfType(HashMap<MutationObserver*, MutationRecordDeliveryOptions>&, MutationObserver::MutationType, const QualifiedName* attributeName);
- void registerMutationObserver(MutationObserver*, MutationObserverOptions, const HashSet<AtomicString>& attributeFilter);
+ void registerMutationObserver(MutationObserver&, MutationObserverOptions, const HashSet<AtomicString>& attributeFilter);
void unregisterMutationObserver(MutationObserverRegistration*);
void registerTransientMutationObserver(MutationObserverRegistration*);
void unregisterTransientMutationObserver(MutationObserverRegistration*);
@@ -907,6 +909,7 @@
#ifndef NDEBUG
// Outside the WebCore namespace for ease of invocation from gdb.
+void showNode(const WebCore::Node*);
void showTree(const WebCore::Node*);
void showNodePath(const WebCore::Node*);
#endif
diff --git a/Source/core/dom/Node.idl b/Source/core/dom/Node.idl
index 690190d..ed2c8aa 100644
--- a/Source/core/dom/Node.idl
+++ b/Source/core/dom/Node.idl
@@ -54,7 +54,7 @@
[Custom, CustomElementCallbacks, PerWorldBindings, RaisesException] Node removeChild(Node oldChild);
[Custom, CustomElementCallbacks, PerWorldBindings, ActivityLogging=ForIsolatedWorlds, RaisesException] Node appendChild(Node newChild);
- boolean hasChildNodes();
+ [ImplementedAs=hasChildren] boolean hasChildNodes();
[CustomElementCallbacks, PerWorldBindings]
Node cloneNode(optional boolean deep);
[CustomElementCallbacks] void normalize();
@@ -85,7 +85,7 @@
unsigned short compareDocumentPosition(Node other);
// Introduced in DOM4
- [ImplementedAs=containsIncludingShadowDOM] boolean contains(Node other);
+ boolean contains(Node other);
// IE extensions
[PerWorldBindings] readonly attribute Element parentElement;
diff --git a/Source/core/dom/NodeFilter.idl b/Source/core/dom/NodeFilter.idl
index 58ac22e..36d5e82 100644
--- a/Source/core/dom/NodeFilter.idl
+++ b/Source/core/dom/NodeFilter.idl
@@ -19,7 +19,7 @@
*/
[
- DependentLifetime
+ DependentLifetime,
] interface NodeFilter {
// Constants returned by acceptNode
const short FILTER_ACCEPT = 1;
@@ -44,4 +44,3 @@
[CallWith=ScriptState] short acceptNode([Default=Undefined] optional Node n);
};
-
diff --git a/Source/core/dom/NodeIterator.cpp b/Source/core/dom/NodeIterator.cpp
index 35c912f..6127231 100644
--- a/Source/core/dom/NodeIterator.cpp
+++ b/Source/core/dom/NodeIterator.cpp
@@ -73,7 +73,7 @@
}
NodeIterator::NodeIterator(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter)
- : Traversal(rootNode, whatToShow, filter)
+ : NodeIteratorBase(rootNode, whatToShow, filter)
, m_referenceNode(root(), true)
, m_detached(false)
{
@@ -90,7 +90,7 @@
{
if (m_detached) {
exceptionState.throwDOMException(InvalidStateError, "The iterator is detached.");
- return 0;
+ return nullptr;
}
RefPtr<Node> result;
@@ -119,7 +119,7 @@
{
if (m_detached) {
exceptionState.throwDOMException(InvalidStateError, "The iterator is detached.");
- return 0;
+ return nullptr;
}
RefPtr<Node> result;
diff --git a/Source/core/dom/NodeIterator.h b/Source/core/dom/NodeIterator.h
index 1f06a57..fcbe77b 100644
--- a/Source/core/dom/NodeIterator.h
+++ b/Source/core/dom/NodeIterator.h
@@ -27,7 +27,7 @@
#include "bindings/v8/ScriptWrappable.h"
#include "core/dom/NodeFilter.h"
-#include "core/dom/Traversal.h"
+#include "core/dom/NodeIteratorBase.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefCounted.h"
@@ -35,7 +35,7 @@
class ExceptionState;
-class NodeIterator : public ScriptWrappable, public RefCounted<NodeIterator>, public Traversal {
+class NodeIterator : public ScriptWrappable, public RefCounted<NodeIterator>, public NodeIteratorBase {
public:
static PassRefPtr<NodeIterator> create(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter)
{
diff --git a/Source/core/dom/NodeIterator.idl b/Source/core/dom/NodeIterator.idl
index c47c809..8da36f6 100644
--- a/Source/core/dom/NodeIterator.idl
+++ b/Source/core/dom/NodeIterator.idl
@@ -18,9 +18,9 @@
* Boston, MA 02110-1301, USA.
*/
-// Introduced in DOM Level 2:
+// Introduced in DOM Level 2
[
- SetWrapperReferenceTo(NodeFilter filter)
+ SetWrapperReferenceTo(NodeFilter filter),
] interface NodeIterator {
readonly attribute Node root;
readonly attribute unsigned long whatToShow;
@@ -33,4 +33,3 @@
[CallWith=ScriptState, RaisesException] Node previousNode();
void detach();
};
-
diff --git a/Source/core/dom/Traversal.cpp b/Source/core/dom/NodeIteratorBase.cpp
similarity index 87%
rename from Source/core/dom/Traversal.cpp
rename to Source/core/dom/NodeIteratorBase.cpp
index a9262cc..aa450fe 100644
--- a/Source/core/dom/Traversal.cpp
+++ b/Source/core/dom/NodeIteratorBase.cpp
@@ -23,21 +23,21 @@
*/
#include "config.h"
-#include "core/dom/Traversal.h"
+#include "core/dom/NodeIteratorBase.h"
#include "core/dom/Node.h"
#include "core/dom/NodeFilter.h"
namespace WebCore {
-Traversal::Traversal(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> nodeFilter)
+NodeIteratorBase::NodeIteratorBase(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> nodeFilter)
: m_root(rootNode)
, m_whatToShow(whatToShow)
, m_filter(nodeFilter)
{
}
-short Traversal::acceptNode(ScriptState* state, Node* node) const
+short NodeIteratorBase::acceptNode(ScriptState* state, Node* node) const
{
// The bit twiddling here is done to map DOM node types, which are given as integers from
// 1 through 14, to whatToShow bit masks.
diff --git a/Source/core/dom/NodeIteratorBase.h b/Source/core/dom/NodeIteratorBase.h
new file mode 100644
index 0000000..0118e3e
--- /dev/null
+++ b/Source/core/dom/NodeIteratorBase.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2008 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.
+ *
+ */
+
+#ifndef NodeIteratorBase_h
+#define NodeIteratorBase_h
+
+#include "bindings/v8/ScriptState.h"
+#include "wtf/RefPtr.h"
+
+namespace WebCore {
+
+class Node;
+class NodeFilter;
+
+class NodeIteratorBase {
+public:
+ Node* root() const { return m_root.get(); }
+ unsigned whatToShow() const { return m_whatToShow; }
+ NodeFilter* filter() const { return m_filter.get(); }
+ // |expandEntityReferences| first appeared in "DOM Level 2 Traversal and Range". However, this argument was
+ // never implemented, and, in DOM4, the function argument |expandEntityReferences| is removed from
+ // Document.createNodeIterator() and Document.createTreeWalker().
+ bool expandEntityReferences() const { return false; }
+
+protected:
+ NodeIteratorBase(PassRefPtr<Node>, unsigned whatToShow, PassRefPtr<NodeFilter>);
+ short acceptNode(ScriptState*, Node*) const;
+
+private:
+ RefPtr<Node> m_root;
+ unsigned m_whatToShow;
+ RefPtr<NodeFilter> m_filter;
+};
+
+} // namespace WebCore
+
+#endif // NodeIteratorBase_h
diff --git a/Source/core/dom/NodeRareData.h b/Source/core/dom/NodeRareData.h
index 3572d14..b127e7e 100644
--- a/Source/core/dom/NodeRareData.h
+++ b/Source/core/dom/NodeRareData.h
@@ -50,7 +50,7 @@
toChildNodeList(m_childNodeList)->invalidateCache();
}
- PassRefPtr<ChildNodeList> ensureChildNodeList(ContainerNode* node)
+ PassRefPtr<ChildNodeList> ensureChildNodeList(ContainerNode& node)
{
if (m_childNodeList)
return toChildNodeList(m_childNodeList);
@@ -59,7 +59,7 @@
return list.release();
}
- PassRefPtr<EmptyNodeList> ensureEmptyChildNodeList(Node* node)
+ PassRefPtr<EmptyNodeList> ensureEmptyChildNodeList(Node& node)
{
if (m_childNodeList)
return toEmptyNodeList(m_childNodeList);
@@ -97,7 +97,7 @@
typedef HashMap<QualifiedName, TagCollection*> TagCollectionCacheNS;
template<typename T>
- PassRefPtr<T> addCache(ContainerNode* node, CollectionType collectionType, const AtomicString& name)
+ PassRefPtr<T> addCache(ContainerNode& node, CollectionType collectionType, const AtomicString& name)
{
NodeListAtomicNameCacheMap::AddResult result = m_atomicNameCaches.add(namedNodeListKey(collectionType, name), 0);
if (!result.isNewEntry)
@@ -109,7 +109,7 @@
}
template<typename T>
- PassRefPtr<T> addCache(ContainerNode* node, CollectionType collectionType)
+ PassRefPtr<T> addCache(ContainerNode& node, CollectionType collectionType)
{
NodeListAtomicNameCacheMap::AddResult result = m_atomicNameCaches.add(namedNodeListKey(collectionType, starAtom), 0);
if (!result.isNewEntry)
@@ -126,7 +126,7 @@
return static_cast<T*>(m_atomicNameCaches.get(namedNodeListKey(collectionType, starAtom)));
}
- PassRefPtr<TagCollection> addCache(ContainerNode* node, const AtomicString& namespaceURI, const AtomicString& localName)
+ PassRefPtr<TagCollection> addCache(ContainerNode& node, const AtomicString& namespaceURI, const AtomicString& localName)
{
QualifiedName name(nullAtom, localName, namespaceURI);
TagCollectionCacheNS::AddResult result = m_tagCollectionCacheNS.add(name, 0);
@@ -201,7 +201,7 @@
return std::pair<unsigned char, StringImpl*>(type, name.impl());
}
- bool deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(Node*);
+ bool deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(Node&);
// Can be a ChildNodeList or an EmptyNodeList.
NodeList* m_childNodeList;
@@ -268,13 +268,12 @@
OwnPtr<NodeMutationObserverData> m_mutationObserverData;
};
-inline bool NodeListsNodeData::deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(Node* ownerNode)
+inline bool NodeListsNodeData::deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(Node& ownerNode)
{
- ASSERT(ownerNode);
- ASSERT(ownerNode->nodeLists() == this);
+ ASSERT(ownerNode.nodeLists() == this);
if ((m_childNodeList ? 1 : 0) + m_atomicNameCaches.size() + m_tagCollectionCacheNS.size() != 1)
return false;
- ownerNode->clearNodeLists();
+ ownerNode.clearNodeLists();
return true;
}
diff --git a/Source/core/dom/NodeRenderStyle.h b/Source/core/dom/NodeRenderStyle.h
index deef2fd..96b9fab 100644
--- a/Source/core/dom/NodeRenderStyle.h
+++ b/Source/core/dom/NodeRenderStyle.h
@@ -25,9 +25,9 @@
#ifndef NodeRenderStyle_h
#define NodeRenderStyle_h
-#include "HTMLNames.h"
#include "core/dom/Node.h"
#include "core/dom/NodeRenderingTraversal.h"
+#include "core/html/HTMLOptGroupElement.h"
#include "core/rendering/RenderObject.h"
#include "core/rendering/style/RenderStyle.h"
@@ -40,7 +40,7 @@
// <option> and <optgroup> can be styled even though they never get renderers,
// so they store their style internally and return it through nonRendererStyle().
// We check here explicitly to avoid the virtual call in the common case.
- if (hasTagName(HTMLNames::optgroupTag) || hasTagName(HTMLNames::optionTag))
+ if (isHTMLOptGroupElement(*this) || isHTMLOptionElement(this))
return nonRendererStyle();
return 0;
}
diff --git a/Source/core/dom/NodeRenderingTraversal.cpp b/Source/core/dom/NodeRenderingTraversal.cpp
index b6f1db3..496413e 100644
--- a/Source/core/dom/NodeRenderingTraversal.cpp
+++ b/Source/core/dom/NodeRenderingTraversal.cpp
@@ -118,6 +118,115 @@
return 0;
}
+static Node* lastChild(const Node* node)
+{
+ ComposedTreeWalker walker(node);
+ walker.lastChild();
+ return walker.get();
+}
+
+static Node* pseudoAwarePreviousSibling(const Node* node)
+{
+ Node* previousNode = previousSibling(node);
+ Node* parentNode = parent(node);
+
+ if (parentNode && parentNode->isElementNode() && !previousNode) {
+ if (node->isAfterPseudoElement()) {
+ if (Node* child = lastChild(parentNode))
+ return child;
+ }
+ if (!node->isBeforePseudoElement())
+ return toElement(parentNode)->pseudoElement(BEFORE);
+ }
+ return previousNode;
+}
+
+static Node* pseudoAwareLastChild(const Node* node)
+{
+ if (node->isElementNode()) {
+ const Element* currentElement = toElement(node);
+ Node* last = currentElement->pseudoElement(AFTER);
+ if (last)
+ return last;
+
+ last = lastChild(currentElement);
+ if (!last)
+ last = currentElement->pseudoElement(BEFORE);
+ return last;
+ }
+
+ return lastChild(node);
+}
+
+Node* previous(const Node* node, const Node* stayWithin)
+{
+ if (node == stayWithin)
+ return 0;
+
+ if (Node* previousNode = pseudoAwarePreviousSibling(node)) {
+ while (Node* previousLastChild = pseudoAwareLastChild(previousNode))
+ previousNode = previousLastChild;
+ return previousNode;
+ }
+ return parent(node);
+}
+
+static Node* firstChild(const Node* node)
+{
+ ComposedTreeWalker walker(node);
+ walker.firstChild();
+ return walker.get();
+}
+
+static Node* pseudoAwareNextSibling(const Node* node)
+{
+ Node* parentNode = parent(node);
+ Node* nextNode = nextSibling(node);
+
+ if (parentNode && parentNode->isElementNode() && !nextNode) {
+ if (node->isBeforePseudoElement()) {
+ if (Node* child = firstChild(parentNode))
+ return child;
+ }
+ if (!node->isAfterPseudoElement())
+ return toElement(parentNode)->pseudoElement(AFTER);
+ }
+ return nextNode;
+}
+
+static Node* pseudoAwareFirstChild(const Node* node)
+{
+ if (node->isElementNode()) {
+ const Element* currentElement = toElement(node);
+ Node* first = currentElement->pseudoElement(BEFORE);
+ if (first)
+ return first;
+ first = firstChild(currentElement);
+ if (!first)
+ first = currentElement->pseudoElement(AFTER);
+ return first;
+ }
+
+ return firstChild(node);
+}
+
+Node* next(const Node* node, const Node* stayWithin)
+{
+ if (Node* child = pseudoAwareFirstChild(node))
+ return child;
+ if (node == stayWithin)
+ return 0;
+ if (Node* nextNode = pseudoAwareNextSibling(node))
+ return nextNode;
+ for (Node* parentNode = parent(node); parentNode; parentNode = parent(parentNode)) {
+ if (parentNode == stayWithin)
+ return 0;
+ if (Node* nextNode = pseudoAwareNextSibling(parentNode))
+ return nextNode;
+ }
+ return 0;
+}
+
RenderObject* nextSiblingRenderer(const Node* node)
{
for (Node* sibling = NodeRenderingTraversal::nextSibling(node); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
diff --git a/Source/core/dom/NodeRenderingTraversal.h b/Source/core/dom/NodeRenderingTraversal.h
index fab1bc3..2d96b25 100644
--- a/Source/core/dom/NodeRenderingTraversal.h
+++ b/Source/core/dom/NodeRenderingTraversal.h
@@ -65,6 +65,8 @@
bool contains(const ContainerNode*, const Node*);
Node* nextSibling(const Node*);
Node* previousSibling(const Node*);
+Node* previous(const Node*, const Node* stayWithin);
+Node* next(const Node*, const Node* stayWithin);
RenderObject* nextSiblingRenderer(const Node*);
RenderObject* previousSiblingRenderer(const Node*);
RenderObject* nextInTopLayer(const Element*);
diff --git a/Source/core/dom/NodeTraversal.cpp b/Source/core/dom/NodeTraversal.cpp
index b5eba51..37e37cc 100644
--- a/Source/core/dom/NodeTraversal.cpp
+++ b/Source/core/dom/NodeTraversal.cpp
@@ -28,9 +28,8 @@
#include "core/dom/ContainerNode.h"
namespace WebCore {
-namespace NodeTraversal {
-Node* previousIncludingPseudo(const Node& current, const Node* stayWithin)
+Node* NodeTraversal::previousIncludingPseudo(const Node& current, const Node* stayWithin)
{
if (current == stayWithin)
return 0;
@@ -42,7 +41,7 @@
return current.parentNode();
}
-Node* nextIncludingPseudo(const Node& current, const Node* stayWithin)
+Node* NodeTraversal::nextIncludingPseudo(const Node& current, const Node* stayWithin)
{
if (Node* next = current.pseudoAwareFirstChild())
return next;
@@ -59,7 +58,7 @@
return 0;
}
-Node* nextIncludingPseudoSkippingChildren(const Node& current, const Node* stayWithin)
+Node* NodeTraversal::nextIncludingPseudoSkippingChildren(const Node& current, const Node* stayWithin)
{
if (current == stayWithin)
return 0;
@@ -74,7 +73,7 @@
return 0;
}
-Node* nextAncestorSibling(const Node& current)
+Node* NodeTraversal::nextAncestorSibling(const Node& current)
{
ASSERT(!current.nextSibling());
for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
@@ -84,7 +83,7 @@
return 0;
}
-Node* nextAncestorSibling(const Node& current, const Node* stayWithin)
+Node* NodeTraversal::nextAncestorSibling(const Node& current, const Node* stayWithin)
{
ASSERT(!current.nextSibling());
ASSERT(current != stayWithin);
@@ -97,7 +96,7 @@
return 0;
}
-Node* previous(const Node& current, const Node* stayWithin)
+Node* NodeTraversal::previous(const Node& current, const Node* stayWithin)
{
if (current == stayWithin)
return 0;
@@ -110,7 +109,7 @@
return current.parentNode();
}
-Node* previousSkippingChildren(const Node& current, const Node* stayWithin)
+Node* NodeTraversal::previousSkippingChildren(const Node& current, const Node* stayWithin)
{
if (current == stayWithin)
return 0;
@@ -125,7 +124,7 @@
return 0;
}
-Node* nextPostOrder(const Node& current, const Node* stayWithin)
+Node* NodeTraversal::nextPostOrder(const Node& current, const Node* stayWithin)
{
if (current == stayWithin)
return 0;
@@ -149,7 +148,7 @@
return 0;
}
-Node* previousPostOrder(const Node& current, const Node* stayWithin)
+Node* NodeTraversal::previousPostOrder(const Node& current, const Node* stayWithin)
{
if (current.lastChild())
return current.lastChild();
@@ -160,5 +159,4 @@
return previousAncestorSiblingPostOrder(current, stayWithin);
}
-}
-}
+} // namespace WebCore
diff --git a/Source/core/dom/NodeTraversal.h b/Source/core/dom/NodeTraversal.h
index 995613a..41017f8 100644
--- a/Source/core/dom/NodeTraversal.h
+++ b/Source/core/dom/NodeTraversal.h
@@ -4,6 +4,7 @@
* (C) 2001 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2014 Samsung Electronics. 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
@@ -29,45 +30,56 @@
namespace WebCore {
-namespace NodeTraversal {
+class NodeTraversal {
+public:
+ // Does a pre-order traversal of the tree to find the next node after this one.
+ // This uses the same order that tags appear in the source file. If the stayWithin
+ // argument is non-null, the traversal will stop once the specified node is reached.
+ // This can be used to restrict traversal to a particular sub-tree.
+ static Node* next(const Node& current) { return traverseNextTemplate(current); }
+ static Node* next(const ContainerNode& current) { return traverseNextTemplate(current); }
+ static Node* next(const Node& current, const Node* stayWithin) { return traverseNextTemplate(current, stayWithin); }
+ static Node* next(const ContainerNode& current, const Node* stayWithin) { return traverseNextTemplate(current, stayWithin); }
-// Does a pre-order traversal of the tree to find the next node after this one.
-// This uses the same order that tags appear in the source file. If the stayWithin
-// argument is non-null, the traversal will stop once the specified node is reached.
-// This can be used to restrict traversal to a particular sub-tree.
-Node* next(const Node&);
-Node* next(const Node&, const Node* stayWithin);
-Node* next(const ContainerNode&);
-Node* next(const ContainerNode&, const Node* stayWithin);
+ // Like next, but skips children and starts with the next sibling.
+ static Node* nextSkippingChildren(const Node& current) { return traverseNextSkippingChildrenTemplate(current); }
+ static Node* nextSkippingChildren(const ContainerNode& current) { return traverseNextSkippingChildrenTemplate(current); }
+ static Node* nextSkippingChildren(const Node& current, const Node* stayWithin) { return traverseNextSkippingChildrenTemplate(current, stayWithin); }
+ static Node* nextSkippingChildren(const ContainerNode& current, const Node* stayWithin) { return traverseNextSkippingChildrenTemplate(current, stayWithin); }
-// Like next, but skips children and starts with the next sibling.
-Node* nextSkippingChildren(const Node&);
-Node* nextSkippingChildren(const Node&, const Node* stayWithin);
-Node* nextSkippingChildren(const ContainerNode&);
-Node* nextSkippingChildren(const ContainerNode&, const Node* stayWithin);
+ // Does a reverse pre-order traversal to find the node that comes before the current one in document order
+ static Node* previous(const Node&, const Node* stayWithin = 0);
-// Does a reverse pre-order traversal to find the node that comes before the current one in document order
-Node* previous(const Node&, const Node* stayWithin = 0);
+ // Like previous, but skips children and starts with the next sibling.
+ static Node* previousSkippingChildren(const Node&, const Node* stayWithin = 0);
-// Like previous, but skips children and starts with the next sibling.
-Node* previousSkippingChildren(const Node&, const Node* stayWithin = 0);
+ // Like next, but visits parents after their children.
+ static Node* nextPostOrder(const Node&, const Node* stayWithin = 0);
-// Like next, but visits parents after their children.
-Node* nextPostOrder(const Node&, const Node* stayWithin = 0);
+ // Like previous, but visits parents before their children.
+ static Node* previousPostOrder(const Node&, const Node* stayWithin = 0);
-// Like previous, but visits parents before their children.
-Node* previousPostOrder(const Node&, const Node* stayWithin = 0);
+ // Pre-order traversal including the pseudo-elements.
+ static Node* previousIncludingPseudo(const Node&, const Node* stayWithin = 0);
+ static Node* nextIncludingPseudo(const Node&, const Node* stayWithin = 0);
+ static Node* nextIncludingPseudoSkippingChildren(const Node&, const Node* stayWithin = 0);
-// Pre-order traversal including the pseudo-elements.
-Node* previousIncludingPseudo(const Node&, const Node* stayWithin = 0);
-Node* nextIncludingPseudo(const Node&, const Node* stayWithin = 0);
-Node* nextIncludingPseudoSkippingChildren(const Node&, const Node* stayWithin = 0);
+ static Node* nextAncestorSibling(const Node&);
+ static Node* nextAncestorSibling(const Node&, const Node* stayWithin);
-Node* nextAncestorSibling(const Node&);
-Node* nextAncestorSibling(const Node&, const Node* stayWithin);
+private:
+ template <class NodeType>
+ static Node* traverseNextTemplate(NodeType&);
+ template <class NodeType>
+ static Node* traverseNextTemplate(NodeType&, const Node* stayWithin);
+ template <class NodeType>
+ static Node* traverseNextSkippingChildrenTemplate(NodeType&);
+ template <class NodeType>
+ static Node* traverseNextSkippingChildrenTemplate(NodeType&, const Node* stayWithin);
+};
template <class NodeType>
-inline Node* traverseNextTemplate(NodeType& current)
+inline Node* NodeTraversal::traverseNextTemplate(NodeType& current)
{
if (current.firstChild())
return current.firstChild();
@@ -75,11 +87,9 @@
return current.nextSibling();
return nextAncestorSibling(current);
}
-inline Node* next(const Node& current) { return traverseNextTemplate(current); }
-inline Node* next(const ContainerNode& current) { return traverseNextTemplate(current); }
template <class NodeType>
-inline Node* traverseNextTemplate(NodeType& current, const Node* stayWithin)
+inline Node* NodeTraversal::traverseNextTemplate(NodeType& current, const Node* stayWithin)
{
if (current.firstChild())
return current.firstChild();
@@ -89,21 +99,17 @@
return current.nextSibling();
return nextAncestorSibling(current, stayWithin);
}
-inline Node* next(const Node& current, const Node* stayWithin) { return traverseNextTemplate(current, stayWithin); }
-inline Node* next(const ContainerNode& current, const Node* stayWithin) { return traverseNextTemplate(current, stayWithin); }
template <class NodeType>
-inline Node* traverseNextSkippingChildrenTemplate(NodeType& current)
+inline Node* NodeTraversal::traverseNextSkippingChildrenTemplate(NodeType& current)
{
if (current.nextSibling())
return current.nextSibling();
return nextAncestorSibling(current);
}
-inline Node* nextSkippingChildren(const Node& current) { return traverseNextSkippingChildrenTemplate(current); }
-inline Node* nextSkippingChildren(const ContainerNode& current) { return traverseNextSkippingChildrenTemplate(current); }
template <class NodeType>
-inline Node* traverseNextSkippingChildrenTemplate(NodeType& current, const Node* stayWithin)
+inline Node* NodeTraversal::traverseNextSkippingChildrenTemplate(NodeType& current, const Node* stayWithin)
{
if (current == stayWithin)
return 0;
@@ -111,11 +117,7 @@
return current.nextSibling();
return nextAncestorSibling(current, stayWithin);
}
-inline Node* nextSkippingChildren(const Node& current, const Node* stayWithin) { return traverseNextSkippingChildrenTemplate(current, stayWithin); }
-inline Node* nextSkippingChildren(const ContainerNode& current, const Node* stayWithin) { return traverseNextSkippingChildrenTemplate(current, stayWithin); }
-}
-
-}
+} // namespace WebCore
#endif
diff --git a/Source/core/dom/NodeWithIndex.h b/Source/core/dom/NodeWithIndex.h
index 8c75ccc..02b6d33 100644
--- a/Source/core/dom/NodeWithIndex.h
+++ b/Source/core/dom/NodeWithIndex.h
@@ -34,27 +34,26 @@
// only want to walk the child list to figure out the index once.
class NodeWithIndex {
public:
- explicit NodeWithIndex(Node* node)
+ explicit NodeWithIndex(Node& node)
: m_node(node)
, m_haveIndex(false)
{
- ASSERT(node);
}
- Node* node() const { return m_node; }
+ Node& node() const { return m_node; }
int index() const
{
if (!m_haveIndex) {
- m_index = m_node->nodeIndex();
+ m_index = m_node.nodeIndex();
m_haveIndex = true;
}
- ASSERT(m_index == static_cast<int>(m_node->nodeIndex()));
+ ASSERT(m_index == static_cast<int>(m_node.nodeIndex()));
return m_index;
}
private:
- Node* m_node;
+ Node& m_node;
mutable bool m_haveIndex;
mutable int m_index;
};
diff --git a/Source/core/dom/ParentNode.h b/Source/core/dom/ParentNode.h
index 45f146c..dda6a8a 100644
--- a/Source/core/dom/ParentNode.h
+++ b/Source/core/dom/ParentNode.h
@@ -38,28 +38,25 @@
class ParentNode {
public:
- static PassRefPtr<HTMLCollection> children(ContainerNode* node)
+ static PassRefPtr<HTMLCollection> children(ContainerNode& node)
{
- return node->children();
+ return node.children();
}
- static Element* firstElementChild(ContainerNode* node)
+ static Element* firstElementChild(ContainerNode& node)
{
- ASSERT(node);
- return ElementTraversal::firstWithin(*node);
+ return ElementTraversal::firstWithin(node);
}
- static Element* lastElementChild(ContainerNode* node)
+ static Element* lastElementChild(ContainerNode& node)
{
- ASSERT(node);
- return ElementTraversal::lastWithin(*node);
+ return ElementTraversal::lastWithin(node);
}
- static unsigned childElementCount(ContainerNode* node)
+ static unsigned childElementCount(ContainerNode& node)
{
- ASSERT(node);
unsigned count = 0;
- for (Element* child = ElementTraversal::firstWithin(*node); child; child = ElementTraversal::nextSibling(*child))
+ for (Element* child = ElementTraversal::firstWithin(node); child; child = ElementTraversal::nextSibling(*child))
++count;
return count;
}
diff --git a/Source/core/dom/Position.cpp b/Source/core/dom/Position.cpp
index 91832ed..2bdca34 100644
--- a/Source/core/dom/Position.cpp
+++ b/Source/core/dom/Position.cpp
@@ -35,14 +35,15 @@
#include "core/editing/VisiblePosition.h"
#include "core/editing/VisibleUnits.h"
#include "core/editing/htmlediting.h"
-#include "core/frame/Frame.h"
+#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
-#include "platform/Logging.h"
+#include "core/html/HTMLTableElement.h"
#include "core/rendering/InlineIterator.h"
#include "core/rendering/InlineTextBox.h"
#include "core/rendering/RenderBlock.h"
#include "core/rendering/RenderInline.h"
#include "core/rendering/RenderText.h"
+#include "platform/Logging.h"
#include "wtf/text/CString.h"
#include "wtf/unicode/CharacterNames.h"
@@ -210,14 +211,14 @@
// FIXME: This should only be necessary for legacy positions, but is also needed for positions before and after Tables
if (m_offset <= 0 && (m_anchorType != PositionIsAfterAnchor && m_anchorType != PositionIsAfterChildren)) {
if (m_anchorNode->parentNode() && (editingIgnoresContent(m_anchorNode.get()) || isRenderedTableElement(m_anchorNode.get())))
- return positionInParentBeforeNode(m_anchorNode.get());
+ return positionInParentBeforeNode(*m_anchorNode);
return Position(m_anchorNode.get(), 0, PositionIsOffsetInAnchor);
}
if (!m_anchorNode->offsetInCharacters()
- && (m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAfterChildren || static_cast<unsigned>(m_offset) == m_anchorNode->childNodeCount())
+ && (m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAfterChildren || static_cast<unsigned>(m_offset) == m_anchorNode->countChildren())
&& (editingIgnoresContent(m_anchorNode.get()) || isRenderedTableElement(m_anchorNode.get()))
&& containerNode()) {
- return positionInParentAfterNode(m_anchorNode.get());
+ return positionInParentAfterNode(*m_anchorNode);
}
return Position(containerNode(), computeOffsetInContainerNode(), PositionIsOffsetInAnchor);
@@ -234,7 +235,7 @@
case PositionIsAfterChildren:
return m_anchorNode->lastChild();
case PositionIsOffsetInAnchor:
- return m_anchorNode->childNode(m_offset - 1); // -1 converts to childNode((unsigned)-1) and returns null.
+ return m_anchorNode->traverseToChildAt(m_offset - 1); // -1 converts to traverseToChildAt((unsigned)-1) and returns null.
case PositionIsBeforeAnchor:
return m_anchorNode->previousSibling();
case PositionIsAfterAnchor:
@@ -255,7 +256,7 @@
case PositionIsAfterChildren:
return 0;
case PositionIsOffsetInAnchor:
- return m_anchorNode->childNode(m_offset);
+ return m_anchorNode->traverseToChildAt(m_offset);
case PositionIsBeforeAnchor:
return m_anchorNode.get();
case PositionIsAfterAnchor:
@@ -288,7 +289,7 @@
{
Element* elem = element();
if (!elem)
- return 0;
+ return nullptr;
return CSSComputedStyleDeclaration::create(elem);
}
@@ -303,7 +304,7 @@
ASSERT(offset >= 0);
if (offset > 0) {
- if (Node* child = node->childNode(offset - 1))
+ if (Node* child = node->traverseToChildAt(offset - 1))
return lastPositionInOrAfterNode(child);
// There are two reasons child might be 0:
@@ -338,10 +339,10 @@
// FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.
ASSERT(offset >= 0);
- if (Node* child = node->childNode(offset))
+ if (Node* child = node->traverseToChildAt(offset))
return firstPositionInOrBeforeNode(child);
- if (!node->hasChildNodes() && offset < lastOffsetForEditing(node)) {
+ if (!node->hasChildren() && offset < lastOffsetForEditing(node)) {
// There are two reasons child might be 0:
// 1) The node is node like a text node that is not an element, and therefore has no children.
// Going forward one character at a time is correct.
@@ -544,9 +545,14 @@
return true;
// Don't include inline tables.
- if (node->hasTagName(tableTag))
+ if (isHTMLTableElement(*node))
return false;
+ // A Marquee elements are moving so we should assume their ends are always
+ // visibily distinct.
+ if (isHTMLMarqueeElement(*node))
+ return true;
+
// There is a VisiblePosition inside an empty inline-block container.
return node->renderer()->isReplaced() && canHaveChildrenForEditing(node) && toRenderBox(node->renderer())->height() != 0 && !node->firstChild();
}
@@ -734,7 +740,7 @@
// stop before going above the body, up into the head
// return the last visible streamer position
- if (currentNode->hasTagName(bodyTag) && currentPos.atEndOfNode())
+ if (isHTMLBodyElement(*currentNode) && currentPos.atEndOfNode())
break;
// Do not move to a visually distinct position.
@@ -890,17 +896,17 @@
if (isRenderedTableElement(deprecatedNode()) || editingIgnoresContent(deprecatedNode()))
return (atFirstEditingPositionForNode() || atLastEditingPositionForNode()) && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
- if (m_anchorNode->hasTagName(htmlTag))
+ if (isHTMLHtmlElement(*m_anchorNode))
return false;
if (renderer->isRenderBlockFlow()) {
- if (toRenderBlock(renderer)->logicalHeight() || m_anchorNode->hasTagName(bodyTag)) {
+ if (toRenderBlock(renderer)->logicalHeight() || isHTMLBodyElement(*m_anchorNode)) {
if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer))
return atFirstEditingPositionForNode() && !Position::nodeIsUserSelectNone(deprecatedNode());
return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
}
} else {
- Frame* frame = m_anchorNode->document().frame();
+ LocalFrame* frame = m_anchorNode->document().frame();
bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEnabled();
return (caretBrowsing || m_anchorNode->rendererIsEditable()) && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
}
@@ -975,7 +981,7 @@
return false;
if (deprecatedNode() == pos.deprecatedNode()) {
- if (deprecatedNode()->hasTagName(brTag))
+ if (isHTMLBRElement(*deprecatedNode()))
return false;
if (m_offset == pos.deprecatedEditingOffset())
@@ -987,10 +993,10 @@
}
}
- if (deprecatedNode()->hasTagName(brTag) && pos.isCandidate())
+ if (isHTMLBRElement(*deprecatedNode()) && pos.isCandidate())
return true;
- if (pos.deprecatedNode()->hasTagName(brTag) && isCandidate())
+ if (isHTMLBRElement(*pos.deprecatedNode()) && isCandidate())
return true;
if (deprecatedNode()->enclosingBlockFlowElement() != pos.deprecatedNode()->enclosingBlockFlowElement())
@@ -1050,7 +1056,7 @@
if (isNull())
return Position();
- if (upstream().deprecatedNode()->hasTagName(brTag))
+ if (isHTMLBRElement(*upstream().deprecatedNode()))
return Position();
Position prev = previousCharacterPosition(affinity);
diff --git a/Source/core/dom/Position.h b/Source/core/dom/Position.h
index eea78f6..643ba2b 100644
--- a/Source/core/dom/Position.h
+++ b/Source/core/dom/Position.h
@@ -244,19 +244,19 @@
// These are inline to prevent ref-churn when returning a Position object.
// If we ever add a PassPosition we can make these non-inline.
-inline Position positionInParentBeforeNode(const Node* node)
+inline Position positionInParentBeforeNode(const Node& node)
{
- // FIXME: This should ASSERT(node->parentNode())
+ // FIXME: This should ASSERT(node.parentNode())
// At least one caller currently hits this ASSERT though, which indicates
// that the caller is trying to make a position relative to a disconnected node (which is likely an error)
// Specifically, editing/deleting/delete-ligature-001.html crashes with ASSERT(node->parentNode())
- return Position(node->parentNode(), node->nodeIndex(), Position::PositionIsOffsetInAnchor);
+ return Position(node.parentNode(), node.nodeIndex(), Position::PositionIsOffsetInAnchor);
}
-inline Position positionInParentAfterNode(const Node* node)
+inline Position positionInParentAfterNode(const Node& node)
{
- ASSERT(node->parentNode());
- return Position(node->parentNode(), node->nodeIndex() + 1, Position::PositionIsOffsetInAnchor);
+ ASSERT(node.parentNode());
+ return Position(node.parentNode(), node.nodeIndex() + 1, Position::PositionIsOffsetInAnchor);
}
// positionBeforeNode and positionAfterNode return neighbor-anchored positions, construction is O(1)
@@ -274,10 +274,10 @@
inline int lastOffsetInNode(Node* node)
{
- return node->offsetInCharacters() ? node->maxCharacterOffset() : static_cast<int>(node->childNodeCount());
+ return node->offsetInCharacters() ? node->maxCharacterOffset() : static_cast<int>(node->countChildren());
}
-// firstPositionInNode and lastPositionInNode return parent-anchored positions, lastPositionInNode construction is O(n) due to childNodeCount()
+// firstPositionInNode and lastPositionInNode return parent-anchored positions, lastPositionInNode construction is O(n) due to countChildren()
inline Position firstPositionInNode(Node* anchorNode)
{
if (anchorNode->isTextNode())
diff --git a/Source/core/dom/PositionIterator.cpp b/Source/core/dom/PositionIterator.cpp
index d99beaa..c6a3ca2 100644
--- a/Source/core/dom/PositionIterator.cpp
+++ b/Source/core/dom/PositionIterator.cpp
@@ -26,8 +26,8 @@
#include "config.h"
#include "core/dom/PositionIterator.h"
-#include "HTMLNames.h"
#include "core/editing/htmlediting.h"
+#include "core/html/HTMLHtmlElement.h"
#include "core/rendering/RenderBlock.h"
namespace WebCore {
@@ -41,9 +41,9 @@
// FIXME: This check is inadaquete because any ancestor could be ignored by editing
if (editingIgnoresContent(m_nodeAfterPositionInAnchor->parentNode()))
return positionBeforeNode(m_anchorNode);
- return positionInParentBeforeNode(m_nodeAfterPositionInAnchor);
+ return positionInParentBeforeNode(*m_nodeAfterPositionInAnchor);
}
- if (m_anchorNode->hasChildNodes())
+ if (m_anchorNode->hasChildren())
return lastPositionInOrAfterNode(m_anchorNode);
return createLegacyEditingPosition(m_anchorNode, m_offsetInAnchor);
}
@@ -60,7 +60,7 @@
return;
}
- if (!m_anchorNode->hasChildNodes() && m_offsetInAnchor < lastOffsetForEditing(m_anchorNode))
+ if (!m_anchorNode->hasChildren() && m_offsetInAnchor < lastOffsetForEditing(m_anchorNode))
m_offsetInAnchor = Position::uncheckedNextOffset(m_anchorNode, m_offsetInAnchor);
else {
m_nodeAfterPositionInAnchor = m_anchorNode;
@@ -79,7 +79,7 @@
m_anchorNode = m_nodeAfterPositionInAnchor->previousSibling();
if (m_anchorNode) {
m_nodeAfterPositionInAnchor = 0;
- m_offsetInAnchor = m_anchorNode->hasChildNodes() ? 0 : lastOffsetForEditing(m_anchorNode);
+ m_offsetInAnchor = m_anchorNode->hasChildren() ? 0 : lastOffsetForEditing(m_anchorNode);
} else {
m_nodeAfterPositionInAnchor = m_nodeAfterPositionInAnchor->parentNode();
m_anchorNode = m_nodeAfterPositionInAnchor->parentNode();
@@ -88,9 +88,9 @@
return;
}
- if (m_anchorNode->hasChildNodes()) {
+ if (m_anchorNode->hasChildren()) {
m_anchorNode = m_anchorNode->lastChild();
- m_offsetInAnchor = m_anchorNode->hasChildNodes()? 0: lastOffsetForEditing(m_anchorNode);
+ m_offsetInAnchor = m_anchorNode->hasChildren()? 0: lastOffsetForEditing(m_anchorNode);
} else {
if (m_offsetInAnchor)
m_offsetInAnchor = Position::uncheckedPreviousOffset(m_anchorNode, m_offsetInAnchor);
@@ -107,7 +107,7 @@
return true;
if (m_anchorNode->parentNode())
return false;
- return (!m_anchorNode->hasChildNodes() && !m_offsetInAnchor) || (m_nodeAfterPositionInAnchor && !m_nodeAfterPositionInAnchor->previousSibling());
+ return (!m_anchorNode->hasChildren() && !m_offsetInAnchor) || (m_nodeAfterPositionInAnchor && !m_nodeAfterPositionInAnchor->previousSibling());
}
bool PositionIterator::atEnd() const
@@ -116,7 +116,7 @@
return true;
if (m_nodeAfterPositionInAnchor)
return false;
- return !m_anchorNode->parentNode() && (m_anchorNode->hasChildNodes() || m_offsetInAnchor >= lastOffsetForEditing(m_anchorNode));
+ return !m_anchorNode->parentNode() && (m_anchorNode->hasChildren() || m_offsetInAnchor >= lastOffsetForEditing(m_anchorNode));
}
bool PositionIterator::atStartOfNode() const
@@ -124,7 +124,7 @@
if (!m_anchorNode)
return true;
if (!m_nodeAfterPositionInAnchor)
- return !m_anchorNode->hasChildNodes() && !m_offsetInAnchor;
+ return !m_anchorNode->hasChildren() && !m_offsetInAnchor;
return !m_nodeAfterPositionInAnchor->previousSibling();
}
@@ -134,7 +134,7 @@
return true;
if (m_nodeAfterPositionInAnchor)
return false;
- return m_anchorNode->hasChildNodes() || m_offsetInAnchor >= lastOffsetForEditing(m_anchorNode);
+ return m_anchorNode->hasChildren() || m_offsetInAnchor >= lastOffsetForEditing(m_anchorNode);
}
bool PositionIterator::isCandidate() const
@@ -149,17 +149,27 @@
if (renderer->style()->visibility() != VISIBLE)
return false;
- if (renderer->isBR())
- return !m_offsetInAnchor && !Position::nodeIsUserSelectNone(m_anchorNode->parentNode());
-
+ if (renderer->isBR()) {
+ // For br element, the condition
+ // |(!m_anchorNode->hasChildren() || m_nodeAfterPositionInAnchor)|
+ // corresponds to the condition
+ // |m_anchorType != PositionIsAfterAnchor| in Position.isCandaite.
+ // Both conditions say this position is not in tail of the element.
+ // If conditions lose consitency, VisiblePosition::canonicalPosition
+ // will fail on |canonicalizeCandidate(previousCandidate(position))|,
+ // because previousCandidate returns a Position converted from
+ // a "Candidate" PositionIterator and cannonicalizeCandidate(Position)
+ // assumes the Position is "Candidate".
+ return !m_offsetInAnchor && (!m_anchorNode->hasChildren() || m_nodeAfterPositionInAnchor) && !Position::nodeIsUserSelectNone(m_anchorNode->parentNode());
+ }
if (renderer->isText())
return !Position::nodeIsUserSelectNone(m_anchorNode) && Position(*this).inRenderedText();
if (isRenderedTableElement(m_anchorNode) || editingIgnoresContent(m_anchorNode))
return (atStartOfNode() || atEndOfNode()) && !Position::nodeIsUserSelectNone(m_anchorNode->parentNode());
- if (!m_anchorNode->hasTagName(htmlTag) && renderer->isRenderBlockFlow()) {
- if (toRenderBlock(renderer)->logicalHeight() || m_anchorNode->hasTagName(bodyTag)) {
+ if (!isHTMLHtmlElement(*m_anchorNode) && renderer->isRenderBlockFlow()) {
+ if (toRenderBlock(renderer)->logicalHeight() || isHTMLBodyElement(*m_anchorNode)) {
if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer))
return atStartOfNode() && !Position::nodeIsUserSelectNone(m_anchorNode);
return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSelectNone(m_anchorNode) && Position(*this).atEditingBoundary();
diff --git a/Source/core/dom/PositionIterator.h b/Source/core/dom/PositionIterator.h
index 6587f7e..4d81cd1 100644
--- a/Source/core/dom/PositionIterator.h
+++ b/Source/core/dom/PositionIterator.h
@@ -45,7 +45,7 @@
PositionIterator(const Position& pos)
: m_anchorNode(pos.anchorNode())
- , m_nodeAfterPositionInAnchor(m_anchorNode->childNode(pos.deprecatedEditingOffset()))
+ , m_nodeAfterPositionInAnchor(m_anchorNode->traverseToChildAt(pos.deprecatedEditingOffset()))
, m_offsetInAnchor(m_nodeAfterPositionInAnchor ? 0 : pos.deprecatedEditingOffset())
{
}
diff --git a/Source/core/dom/PresentationAttributeStyle.cpp b/Source/core/dom/PresentationAttributeStyle.cpp
index ce45b4b..3d9a3e3 100644
--- a/Source/core/dom/PresentationAttributeStyle.cpp
+++ b/Source/core/dom/PresentationAttributeStyle.cpp
@@ -31,10 +31,10 @@
#include "config.h"
#include "core/dom/PresentationAttributeStyle.h"
-#include "HTMLNames.h"
#include "core/css/StylePropertySet.h"
#include "core/dom/Attribute.h"
#include "core/dom/Element.h"
+#include "core/html/HTMLInputElement.h"
#include "wtf/HashFunctions.h"
#include "wtf/HashMap.h"
#include "wtf/text/CString.h"
@@ -87,7 +87,7 @@
m_hitCount++;
if (!m_cleanTimer.isActive())
- m_cleanTimer.startOneShot(presentationAttributeCacheCleanTimeInSeconds);
+ m_cleanTimer.startOneShot(presentationAttributeCacheCleanTimeInSeconds, FROM_HERE);
}
private:
@@ -121,19 +121,19 @@
if (!element.isHTMLElement())
return;
// Interpretation of the size attributes on <input> depends on the type attribute.
- if (element.hasTagName(inputTag))
+ if (isHTMLInputElement(element))
return;
unsigned size = element.attributeCount();
for (unsigned i = 0; i < size; ++i) {
- const Attribute* attribute = element.attributeItem(i);
- if (!element.isPresentationAttribute(attribute->name()))
+ const Attribute& attribute = element.attributeItem(i);
+ if (!element.isPresentationAttribute(attribute.name()))
continue;
- if (!attribute->namespaceURI().isNull())
+ if (!attribute.namespaceURI().isNull())
return;
// FIXME: Background URL may depend on the base URL and can't be shared. Disallow caching.
- if (attribute->name() == backgroundAttr)
+ if (attribute.name() == backgroundAttr)
return;
- result.attributesAndValues.append(std::make_pair(attribute->localName().impl(), attribute->value()));
+ result.attributesAndValues.append(std::make_pair(attribute.localName().impl(), attribute.value()));
}
if (result.attributesAndValues.isEmpty())
return;
@@ -180,8 +180,8 @@
style = MutableStylePropertySet::create(element.isSVGElement() ? SVGAttributeMode : HTMLAttributeMode);
unsigned size = element.attributeCount();
for (unsigned i = 0; i < size; ++i) {
- const Attribute* attribute = element.attributeItem(i);
- element.collectStyleForPresentationAttribute(attribute->name(), attribute->value(), toMutableStylePropertySet(style));
+ const Attribute& attribute = element.attributeItem(i);
+ element.collectStyleForPresentationAttribute(attribute.name(), attribute.value(), toMutableStylePropertySet(style));
}
}
diff --git a/Source/core/dom/ProcessingInstruction.cpp b/Source/core/dom/ProcessingInstruction.cpp
index ab493bf..ad3d494 100644
--- a/Source/core/dom/ProcessingInstruction.cpp
+++ b/Source/core/dom/ProcessingInstruction.cpp
@@ -174,7 +174,7 @@
ASSERT(m_isCSS);
CSSParserContext parserContext(document(), 0, baseURL, charset);
- RefPtr<StyleSheetContents> newSheet = StyleSheetContents::create(href, parserContext);
+ RefPtrWillBeRawPtr<StyleSheetContents> newSheet = StyleSheetContents::create(href, parserContext);
RefPtr<CSSStyleSheet> cssSheet = CSSStyleSheet::create(newSheet, this);
cssSheet->setDisabled(m_alternate);
@@ -244,7 +244,7 @@
if (m_sheet) {
ASSERT(m_sheet->ownerNode() == this);
m_sheet->clearOwnerNode();
- m_sheet = 0;
+ m_sheet = nullptr;
}
// If we're in document teardown, then we don't need to do any notification of our sheet's removal.
diff --git a/Source/core/dom/PseudoElement.h b/Source/core/dom/PseudoElement.h
index 8fbd1da..be135ee 100644
--- a/Source/core/dom/PseudoElement.h
+++ b/Source/core/dom/PseudoElement.h
@@ -67,7 +67,7 @@
return style && style->display() != NONE && (style->styleType() == BACKDROP || style->contentData());
}
-DEFINE_NODE_TYPE_CASTS(PseudoElement, isPseudoElement());
+DEFINE_ELEMENT_TYPE_CASTS(PseudoElement, isPseudoElement());
} // namespace
diff --git a/Source/core/dom/Range.cpp b/Source/core/dom/Range.cpp
index 9c9ac34..39bf7d6 100644
--- a/Source/core/dom/Range.cpp
+++ b/Source/core/dom/Range.cpp
@@ -120,15 +120,15 @@
ASSERT(m_ownerDocument);
m_ownerDocument->detachRange(this);
m_ownerDocument = &document;
- m_start.setToStartOfNode(&document);
- m_end.setToStartOfNode(&document);
+ m_start.setToStartOfNode(document);
+ m_end.setToStartOfNode(document);
m_ownerDocument->attachRange(this);
}
Node* Range::startContainer(ExceptionState& exceptionState) const
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return 0;
}
@@ -138,7 +138,7 @@
int Range::startOffset(ExceptionState& exceptionState) const
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return 0;
}
@@ -148,7 +148,7 @@
Node* Range::endContainer(ExceptionState& exceptionState) const
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return 0;
}
@@ -158,7 +158,7 @@
int Range::endOffset(ExceptionState& exceptionState) const
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return 0;
}
@@ -168,7 +168,7 @@
Node* Range::commonAncestorContainer(ExceptionState& exceptionState) const
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return 0;
}
@@ -189,7 +189,7 @@
bool Range::collapsed(ExceptionState& exceptionState) const
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return 0;
}
@@ -211,7 +211,7 @@
void Range::setStart(PassRefPtr<Node> refNode, int offset, ExceptionState& exceptionState)
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return;
}
@@ -239,7 +239,7 @@
void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionState& exceptionState)
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return;
}
@@ -279,7 +279,7 @@
void Range::collapse(bool toStart, ExceptionState& exceptionState)
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return;
}
@@ -292,7 +292,7 @@
bool Range::isPointInRange(Node* refNode, int offset, ExceptionState& exceptionState)
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return false;
}
@@ -320,7 +320,7 @@
// refNode node and an offset within the node is before, same as, or after the range respectively.
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return 0;
}
@@ -408,7 +408,7 @@
short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, ExceptionState& exceptionState) const
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return 0;
}
@@ -575,7 +575,7 @@
// Throw exception if the range is already detached.
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return false;
}
if (!refNode) {
@@ -657,9 +657,10 @@
case Node::ELEMENT_NODE:
case Node::ATTRIBUTE_NODE:
case Node::DOCUMENT_NODE:
- case Node::DOCUMENT_TYPE_NODE:
case Node::DOCUMENT_FRAGMENT_NODE:
- return node->childNodeCount();
+ return toContainerNode(node)->countChildren();
+ case Node::DOCUMENT_TYPE_NODE:
+ return 0;
}
ASSERT_NOT_REACHED();
return 0;
@@ -676,11 +677,11 @@
if (collapsed(exceptionState))
return fragment.release();
if (exceptionState.hadException())
- return 0;
+ return nullptr;
RefPtr<Node> commonRoot = commonAncestorContainer(exceptionState);
if (exceptionState.hadException())
- return 0;
+ return nullptr;
ASSERT(commonRoot);
if (m_start.container() == m_end.container()) {
@@ -718,13 +719,13 @@
RefPtr<Node> leftContents;
if (originalStart.container() != commonRoot && commonRoot->contains(originalStart.container())) {
- leftContents = processContentsBetweenOffsets(action, 0, originalStart.container(), originalStart.offset(), lengthOfContentsInNode(originalStart.container()), exceptionState);
+ leftContents = processContentsBetweenOffsets(action, nullptr, originalStart.container(), originalStart.offset(), lengthOfContentsInNode(originalStart.container()), exceptionState);
leftContents = processAncestorsAndTheirSiblings(action, originalStart.container(), ProcessContentsForward, leftContents, commonRoot.get(), exceptionState);
}
RefPtr<Node> rightContents;
if (m_end.container() != commonRoot && commonRoot->contains(originalEnd.container())) {
- rightContents = processContentsBetweenOffsets(action, 0, originalEnd.container(), 0, originalEnd.offset(), exceptionState);
+ rightContents = processContentsBetweenOffsets(action, nullptr, originalEnd.container(), 0, originalEnd.offset(), exceptionState);
rightContents = processAncestorsAndTheirSiblings(action, originalEnd.container(), ProcessContentsBackward, rightContents, commonRoot.get(), exceptionState);
}
@@ -746,7 +747,7 @@
setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), exceptionState);
}
if (exceptionState.hadException())
- return 0;
+ return nullptr;
m_end = m_start;
}
@@ -900,7 +901,10 @@
Node* child = it->get();
switch (action) {
case DELETE_CONTENTS:
- ancestor->removeChild(child, exceptionState);
+ // Prior call of ancestor->removeChild() may cause a tree change due to DOMSubtreeModified event.
+ // Therefore, we need to make sure |ancestor| is still |child|'s parent.
+ if (ancestor == child->parentNode())
+ ancestor->removeChild(child, exceptionState);
break;
case EXTRACT_CONTENTS: // will remove child from ancestor
if (direction == ProcessContentsForward)
@@ -926,7 +930,7 @@
{
checkDeleteExtract(exceptionState);
if (exceptionState.hadException())
- return 0;
+ return nullptr;
return processContents(EXTRACT_CONTENTS, exceptionState);
}
@@ -934,8 +938,8 @@
PassRefPtr<DocumentFragment> Range::cloneContents(ExceptionState& exceptionState)
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
- return 0;
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
+ return nullptr;
}
return processContents(CLONE_CONTENTS, exceptionState);
@@ -946,7 +950,7 @@
RefPtr<Node> newNode = prpNewNode;
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return;
}
@@ -1042,7 +1046,7 @@
}
container = m_start.container();
- container->insertBefore(newNode.release(), container->childNode(m_start.offset()), exceptionState);
+ container->insertBefore(newNode.release(), container->traverseToChildAt(m_start.offset()), exceptionState);
if (exceptionState.hadException())
return;
@@ -1056,7 +1060,7 @@
String Range::toString(ExceptionState& exceptionState) const
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return String();
}
@@ -1096,19 +1100,19 @@
PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& markup, ExceptionState& exceptionState)
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
- return 0;
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
+ return nullptr;
}
Node* element = m_start.container()->isElementNode() ? m_start.container() : m_start.container()->parentNode();
if (!element || !element->isHTMLElement()) {
exceptionState.throwDOMException(NotSupportedError, "The range's container must be an HTML element.");
- return 0;
+ return nullptr;
}
RefPtr<DocumentFragment> fragment = WebCore::createContextualFragment(markup, toHTMLElement(element), AllowScriptingContentAndDoNotMarkAlreadyStarted, exceptionState);
if (!fragment)
- return 0;
+ return nullptr;
return fragment.release();
}
@@ -1118,7 +1122,7 @@
{
// Check first to see if we've already detached:
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return;
}
@@ -1150,7 +1154,7 @@
case Node::ELEMENT_NODE: {
if (!offset)
return 0;
- Node* childBefore = n->childNode(offset - 1);
+ Node* childBefore = n->traverseToChildAt(offset - 1);
if (!childBefore)
exceptionState.throwDOMException(IndexSizeError, "There is no child at offset " + String::number(offset) + ".");
return childBefore;
@@ -1163,7 +1167,7 @@
void Range::checkNodeBA(Node* n, ExceptionState& exceptionState) const
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return;
}
@@ -1219,8 +1223,8 @@
PassRefPtr<Range> Range::cloneRange(ExceptionState& exceptionState) const
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
- return 0;
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
+ return nullptr;
}
return Range::create(*m_ownerDocument.get(), m_start.container(), m_start.offset(), m_end.container(), m_end.offset());
@@ -1256,7 +1260,7 @@
void Range::selectNode(Node* refNode, ExceptionState& exceptionState)
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return;
}
@@ -1315,7 +1319,7 @@
void Range::selectNodeContents(Node* refNode, ExceptionState& exceptionState)
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return;
}
@@ -1346,8 +1350,8 @@
if (m_ownerDocument != refNode->document())
setDocument(refNode->document());
- m_start.setToStartOfNode(refNode);
- m_end.setToEndOfNode(refNode);
+ m_start.setToStartOfNode(*refNode);
+ m_end.setToEndOfNode(*refNode);
}
void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionState& exceptionState)
@@ -1355,7 +1359,7 @@
RefPtr<Node> newParent = passNewParent;
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return;
}
@@ -1449,10 +1453,12 @@
void Range::checkDeleteExtract(ExceptionState& exceptionState)
{
if (!m_start.container()) {
- exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?");
+ exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detach()' has been invoked on this object?");
return;
}
+ ASSERT(boundaryPointsValid());
+
if (!commonAncestorContainer(exceptionState) || exceptionState.hadException())
return;
@@ -1471,7 +1477,7 @@
return 0;
if (m_start.container()->offsetInCharacters())
return m_start.container();
- if (Node* child = m_start.container()->childNode(m_start.offset()))
+ if (Node* child = m_start.container()->traverseToChildAt(m_start.offset()))
return child;
if (!m_start.offset())
return m_start.container();
@@ -1489,7 +1495,7 @@
return 0;
if (m_end.container()->offsetInCharacters())
return NodeTraversal::nextSkippingChildren(*m_end.container());
- if (Node* child = m_end.container()->childNode(m_end.offset()))
+ if (Node* child = m_end.container()->traverseToChildAt(m_end.offset()))
return child;
return NodeTraversal::nextSkippingChildren(*m_end.container());
}
@@ -1618,7 +1624,7 @@
if (!m_start.container())
return 0;
if (!m_start.container()->offsetInCharacters())
- return m_start.container()->childNodeCount();
+ return m_start.container()->countChildren();
return m_start.container()->maxCharacterOffset();
}
@@ -1627,7 +1633,7 @@
if (!m_end.container())
return 0;
if (!m_end.container()->offsetInCharacters())
- return m_end.container()->childNodeCount();
+ return m_end.container()->countChildren();
return m_end.container()->maxCharacterOffset();
}
@@ -1648,9 +1654,9 @@
boundaryNodeChildrenChanged(m_end, container);
}
-static inline void boundaryNodeChildrenWillBeRemoved(RangeBoundaryPoint& boundary, ContainerNode* container)
+static inline void boundaryNodeChildrenWillBeRemoved(RangeBoundaryPoint& boundary, ContainerNode& container)
{
- for (Node* nodeToBeRemoved = container->firstChild(); nodeToBeRemoved; nodeToBeRemoved = nodeToBeRemoved->nextSibling()) {
+ for (Node* nodeToBeRemoved = container.firstChild(); nodeToBeRemoved; nodeToBeRemoved = nodeToBeRemoved->nextSibling()) {
if (boundary.childBefore() == nodeToBeRemoved) {
boundary.setToStartOfNode(container);
return;
@@ -1665,10 +1671,9 @@
}
}
-void Range::nodeChildrenWillBeRemoved(ContainerNode* container)
+void Range::nodeChildrenWillBeRemoved(ContainerNode& container)
{
- ASSERT(container);
- ASSERT(container->document() == m_ownerDocument);
+ ASSERT(container.document() == m_ownerDocument);
boundaryNodeChildrenWillBeRemoved(m_start, container);
boundaryNodeChildrenWillBeRemoved(m_end, container);
}
@@ -1740,46 +1745,45 @@
boundaryTextRemoved(m_end, text, offset, length);
}
-static inline void boundaryTextNodesMerged(RangeBoundaryPoint& boundary, NodeWithIndex& oldNode, unsigned offset)
+static inline void boundaryTextNodesMerged(RangeBoundaryPoint& boundary, const NodeWithIndex& oldNode, unsigned offset)
{
if (boundary.container() == oldNode.node())
- boundary.set(oldNode.node()->previousSibling(), boundary.offset() + offset, 0);
- else if (boundary.container() == oldNode.node()->parentNode() && boundary.offset() == oldNode.index())
- boundary.set(oldNode.node()->previousSibling(), offset, 0);
+ boundary.set(oldNode.node().previousSibling(), boundary.offset() + offset, 0);
+ else if (boundary.container() == oldNode.node().parentNode() && boundary.offset() == oldNode.index())
+ boundary.set(oldNode.node().previousSibling(), offset, 0);
}
-void Range::didMergeTextNodes(NodeWithIndex& oldNode, unsigned offset)
+void Range::didMergeTextNodes(const NodeWithIndex& oldNode, unsigned offset)
{
- ASSERT(oldNode.node());
- ASSERT(oldNode.node()->document() == m_ownerDocument);
- ASSERT(oldNode.node()->parentNode());
- ASSERT(oldNode.node()->isTextNode());
- ASSERT(oldNode.node()->previousSibling());
- ASSERT(oldNode.node()->previousSibling()->isTextNode());
+ ASSERT(oldNode.node().document() == m_ownerDocument);
+ ASSERT(oldNode.node().parentNode());
+ ASSERT(oldNode.node().isTextNode());
+ ASSERT(oldNode.node().previousSibling());
+ ASSERT(oldNode.node().previousSibling()->isTextNode());
boundaryTextNodesMerged(m_start, oldNode, offset);
boundaryTextNodesMerged(m_end, oldNode, offset);
}
-static inline void boundaryTextNodeSplit(RangeBoundaryPoint& boundary, Text* oldNode)
+static inline void boundaryTextNodeSplit(RangeBoundaryPoint& boundary, Text& oldNode)
{
- if (boundary.container() != oldNode)
- return;
+ Node* boundaryContainer = boundary.container();
unsigned boundaryOffset = boundary.offset();
- if (boundaryOffset <= oldNode->length())
- return;
- boundary.set(oldNode->nextSibling(), boundaryOffset - oldNode->length(), 0);
+ if (boundary.childBefore() == &oldNode)
+ boundary.set(boundaryContainer, boundaryOffset + 1, oldNode.nextSibling());
+ else if (boundary.container() == &oldNode && boundaryOffset > oldNode.length())
+ boundary.set(oldNode.nextSibling(), boundaryOffset - oldNode.length(), 0);
}
-void Range::didSplitTextNode(Text* oldNode)
+void Range::didSplitTextNode(Text& oldNode)
{
- ASSERT(oldNode);
- ASSERT(oldNode->document() == m_ownerDocument);
- ASSERT(oldNode->parentNode());
- ASSERT(oldNode->isTextNode());
- ASSERT(oldNode->nextSibling());
- ASSERT(oldNode->nextSibling()->isTextNode());
+ ASSERT(oldNode.document() == m_ownerDocument);
+ ASSERT(oldNode.parentNode());
+ ASSERT(oldNode.isTextNode());
+ ASSERT(oldNode.nextSibling());
+ ASSERT(oldNode.nextSibling()->isTextNode());
boundaryTextNodeSplit(m_start, oldNode);
boundaryTextNodeSplit(m_end, oldNode);
+ ASSERT(boundaryPointsValid());
}
void Range::expand(const String& unit, ExceptionState& exceptionState)
@@ -1842,7 +1846,7 @@
renderBoxModelObject->absoluteQuads(elementQuads);
m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoom(elementQuads, *renderBoxModelObject);
- quads.append(elementQuads);
+ quads.appendVector(elementQuads);
}
}
} else if (node->isTextNode()) {
@@ -1855,7 +1859,7 @@
renderText.absoluteQuadsForRange(textQuads, startOffset, endOffset);
m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoom(textQuads, renderText);
- quads.append(textQuads);
+ quads.appendVector(textQuads);
}
}
}
diff --git a/Source/core/dom/Range.h b/Source/core/dom/Range.h
index 3a662f1..6f50ba5 100644
--- a/Source/core/dom/Range.h
+++ b/Source/core/dom/Range.h
@@ -129,13 +129,13 @@
FloatRect boundingRect() const;
void nodeChildrenChanged(ContainerNode*);
- void nodeChildrenWillBeRemoved(ContainerNode*);
+ void nodeChildrenWillBeRemoved(ContainerNode&);
void nodeWillBeRemoved(Node&);
void didInsertText(Node*, unsigned offset, unsigned length);
void didRemoveText(Node*, unsigned offset, unsigned length);
- void didMergeTextNodes(NodeWithIndex& oldNode, unsigned offset);
- void didSplitTextNode(Text* oldNode);
+ void didMergeTextNodes(const NodeWithIndex& oldNode, unsigned offset);
+ void didSplitTextNode(Text& oldNode);
// Expand range to a unit (word or sentence or block or document) boundary.
// Please refer to https://bugs.webkit.org/show_bug.cgi?id=27632 comment #5
diff --git a/Source/core/dom/RangeBoundaryPoint.h b/Source/core/dom/RangeBoundaryPoint.h
index 7574a89..2f7235b 100644
--- a/Source/core/dom/RangeBoundaryPoint.h
+++ b/Source/core/dom/RangeBoundaryPoint.h
@@ -49,8 +49,8 @@
void setOffset(int offset);
void setToBeforeChild(Node&);
- void setToStartOfNode(PassRefPtr<Node>);
- void setToEndOfNode(PassRefPtr<Node>);
+ void setToStartOfNode(Node&);
+ void setToEndOfNode(Node&);
void childBeforeWillBeRemoved();
void invalidateOffset() const;
@@ -67,7 +67,7 @@
inline RangeBoundaryPoint::RangeBoundaryPoint(PassRefPtr<Node> container)
: m_containerNode(container)
, m_offsetInContainer(0)
- , m_childBeforeBoundary(0)
+ , m_childBeforeBoundary(nullptr)
{
ASSERT(m_containerNode);
}
@@ -114,14 +114,14 @@
{
m_containerNode.clear();
m_offsetInContainer = 0;
- m_childBeforeBoundary = 0;
+ m_childBeforeBoundary = nullptr;
}
inline void RangeBoundaryPoint::set(PassRefPtr<Node> container, int offset, Node* childBefore)
{
ASSERT(container);
ASSERT(offset >= 0);
- ASSERT(childBefore == (offset ? container->childNode(offset - 1) : 0));
+ ASSERT(childBefore == (offset ? container->traverseToChildAt(offset - 1) : 0));
m_containerNode = container;
m_offsetInContainer = offset;
m_childBeforeBoundary = childBefore;
@@ -144,21 +144,19 @@
m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
}
-inline void RangeBoundaryPoint::setToStartOfNode(PassRefPtr<Node> container)
+inline void RangeBoundaryPoint::setToStartOfNode(Node& container)
{
- ASSERT(container);
- m_containerNode = container;
+ m_containerNode = PassRefPtr<Node>(container);
m_offsetInContainer = 0;
- m_childBeforeBoundary = 0;
+ m_childBeforeBoundary = nullptr;
}
-inline void RangeBoundaryPoint::setToEndOfNode(PassRefPtr<Node> container)
+inline void RangeBoundaryPoint::setToEndOfNode(Node& container)
{
- ASSERT(container);
- m_containerNode = container;
+ m_containerNode = PassRefPtr<Node>(container);
if (m_containerNode->offsetInCharacters()) {
m_offsetInContainer = m_containerNode->maxCharacterOffset();
- m_childBeforeBoundary = 0;
+ m_childBeforeBoundary = nullptr;
} else {
m_childBeforeBoundary = m_containerNode->lastChild();
m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
diff --git a/Source/core/dom/RangeTest.cpp b/Source/core/dom/RangeTest.cpp
new file mode 100644
index 0000000..a4ac883
--- /dev/null
+++ b/Source/core/dom/RangeTest.cpp
@@ -0,0 +1,142 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/dom/Range.h"
+
+#include "bindings/v8/ExceptionStatePlaceholder.h"
+#include "core/dom/Element.h"
+#include "core/dom/Text.h"
+#include "core/html/HTMLBodyElement.h"
+#include "core/html/HTMLDocument.h"
+#include "core/html/HTMLElement.h"
+#include "core/html/HTMLHtmlElement.h"
+#include "wtf/Compiler.h"
+#include "wtf/RefPtr.h"
+#include "wtf/text/AtomicString.h"
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+
+namespace {
+
+class RangeTest : public ::testing::Test {
+protected:
+ virtual void SetUp() OVERRIDE;
+
+ HTMLDocument& document() const;
+
+private:
+ RefPtr<HTMLDocument> m_document;
+};
+
+void RangeTest::SetUp()
+{
+ m_document = HTMLDocument::create();
+ RefPtr<HTMLHtmlElement> html = HTMLHtmlElement::create(*m_document);
+ html->appendChild(HTMLBodyElement::create(*m_document));
+ m_document->appendChild(html.release());
+}
+
+HTMLDocument& RangeTest::document() const
+{
+ return *m_document;
+}
+
+TEST_F(RangeTest, SplitTextNodeRangeWithinText)
+{
+ document().body()->setInnerHTML("1234", ASSERT_NO_EXCEPTION);
+ Text* oldText = toText(document().body()->firstChild());
+
+ RefPtr<Range> range04 = Range::create(document(), oldText, 0, oldText, 4);
+ RefPtr<Range> range02 = Range::create(document(), oldText, 0, oldText, 2);
+ RefPtr<Range> range22 = Range::create(document(), oldText, 2, oldText, 2);
+ RefPtr<Range> range24 = Range::create(document(), oldText, 2, oldText, 4);
+
+ oldText->splitText(2, ASSERT_NO_EXCEPTION);
+ Text* newText = toText(oldText->nextSibling());
+
+ EXPECT_TRUE(range04->boundaryPointsValid());
+ EXPECT_EQ(oldText, range04->startContainer());
+ EXPECT_EQ(0, range04->startOffset());
+ EXPECT_EQ(newText, range04->endContainer());
+ EXPECT_EQ(2, range04->endOffset());
+
+ EXPECT_TRUE(range02->boundaryPointsValid());
+ EXPECT_EQ(oldText, range02->startContainer());
+ EXPECT_EQ(0, range02->startOffset());
+ EXPECT_EQ(oldText, range02->endContainer());
+ EXPECT_EQ(2, range02->endOffset());
+
+ // Our implementation always moves the boundary point at the separation point to the end of the original text node.
+ EXPECT_TRUE(range22->boundaryPointsValid());
+ EXPECT_EQ(oldText, range22->startContainer());
+ EXPECT_EQ(2, range22->startOffset());
+ EXPECT_EQ(oldText, range22->endContainer());
+ EXPECT_EQ(2, range22->endOffset());
+
+ EXPECT_TRUE(range24->boundaryPointsValid());
+ EXPECT_EQ(oldText, range24->startContainer());
+ EXPECT_EQ(2, range24->startOffset());
+ EXPECT_EQ(newText, range24->endContainer());
+ EXPECT_EQ(2, range24->endOffset());
+}
+
+TEST_F(RangeTest, SplitTextNodeRangeOutsideText)
+{
+ document().body()->setInnerHTML("<span id=\"outer\">0<span id=\"inner-left\">1</span>SPLITME<span id=\"inner-right\">2</span>3</span>", ASSERT_NO_EXCEPTION);
+
+ Element* outer = document().getElementById(AtomicString::fromUTF8("outer"));
+ Element* innerLeft = document().getElementById(AtomicString::fromUTF8("inner-left"));
+ Element* innerRight = document().getElementById(AtomicString::fromUTF8("inner-right"));
+ Text* oldText = toText(outer->childNodes()->item(2));
+
+ RefPtr<Range> rangeOuterOutside = Range::create(document(), outer, 0, outer, 5);
+ RefPtr<Range> rangeOuterInside = Range::create(document(), outer, 1, outer, 4);
+ RefPtr<Range> rangeOuterSurroundingText = Range::create(document(), outer, 2, outer, 3);
+ RefPtr<Range> rangeInnerLeft = Range::create(document(), innerLeft, 0, innerLeft, 1);
+ RefPtr<Range> rangeInnerRight = Range::create(document(), innerRight, 0, innerRight, 1);
+ RefPtr<Range> rangeFromTextToMiddleOfElement = Range::create(document(), oldText, 6, outer, 3);
+
+ oldText->splitText(3, ASSERT_NO_EXCEPTION);
+ Text* newText = toText(oldText->nextSibling());
+
+ EXPECT_TRUE(rangeOuterOutside->boundaryPointsValid());
+ EXPECT_EQ(outer, rangeOuterOutside->startContainer());
+ EXPECT_EQ(0, rangeOuterOutside->startOffset());
+ EXPECT_EQ(outer, rangeOuterOutside->endContainer());
+ EXPECT_EQ(6, rangeOuterOutside->endOffset()); // Increased by 1 since a new node is inserted.
+
+ EXPECT_TRUE(rangeOuterInside->boundaryPointsValid());
+ EXPECT_EQ(outer, rangeOuterInside->startContainer());
+ EXPECT_EQ(1, rangeOuterInside->startOffset());
+ EXPECT_EQ(outer, rangeOuterInside->endContainer());
+ EXPECT_EQ(5, rangeOuterInside->endOffset());
+
+ EXPECT_TRUE(rangeOuterSurroundingText->boundaryPointsValid());
+ EXPECT_EQ(outer, rangeOuterSurroundingText->startContainer());
+ EXPECT_EQ(2, rangeOuterSurroundingText->startOffset());
+ EXPECT_EQ(outer, rangeOuterSurroundingText->endContainer());
+ EXPECT_EQ(4, rangeOuterSurroundingText->endOffset());
+
+ EXPECT_TRUE(rangeInnerLeft->boundaryPointsValid());
+ EXPECT_EQ(innerLeft, rangeInnerLeft->startContainer());
+ EXPECT_EQ(0, rangeInnerLeft->startOffset());
+ EXPECT_EQ(innerLeft, rangeInnerLeft->endContainer());
+ EXPECT_EQ(1, rangeInnerLeft->endOffset());
+
+ EXPECT_TRUE(rangeInnerRight->boundaryPointsValid());
+ EXPECT_EQ(innerRight, rangeInnerRight->startContainer());
+ EXPECT_EQ(0, rangeInnerRight->startOffset());
+ EXPECT_EQ(innerRight, rangeInnerRight->endContainer());
+ EXPECT_EQ(1, rangeInnerRight->endOffset());
+
+ EXPECT_TRUE(rangeFromTextToMiddleOfElement->boundaryPointsValid());
+ EXPECT_EQ(newText, rangeFromTextToMiddleOfElement->startContainer());
+ EXPECT_EQ(3, rangeFromTextToMiddleOfElement->startOffset());
+ EXPECT_EQ(outer, rangeFromTextToMiddleOfElement->endContainer());
+ EXPECT_EQ(4, rangeFromTextToMiddleOfElement->endOffset());
+}
+
+}
diff --git a/Source/core/dom/RenderTreeBuilder.cpp b/Source/core/dom/RenderTreeBuilder.cpp
index 168fcce..bb52e93 100644
--- a/Source/core/dom/RenderTreeBuilder.cpp
+++ b/Source/core/dom/RenderTreeBuilder.cpp
@@ -80,7 +80,7 @@
return false;
if (m_node->isSVGElement()) {
// SVG elements only render when inside <svg>, or if the element is an <svg> itself.
- if (!m_node->hasTagName(SVGNames::svgTag) && !m_renderingParent->isSVGElement())
+ if (!isSVGSVGElement(*m_node) && !m_renderingParent->isSVGElement())
return false;
if (!toSVGElement(m_node)->isValid())
return false;
diff --git a/Source/core/dom/ScriptLoader.cpp b/Source/core/dom/ScriptLoader.cpp
index ac91a97..faba258 100644
--- a/Source/core/dom/ScriptLoader.cpp
+++ b/Source/core/dom/ScriptLoader.cpp
@@ -38,11 +38,11 @@
#include "core/fetch/FetchRequest.h"
#include "core/fetch/ResourceFetcher.h"
#include "core/fetch/ScriptResource.h"
-#include "core/html/HTMLImport.h"
#include "core/html/HTMLScriptElement.h"
+#include "core/html/imports/HTMLImport.h"
#include "core/html/parser/HTMLParserIdioms.h"
-#include "core/frame/ContentSecurityPolicy.h"
-#include "core/frame/Frame.h"
+#include "core/frame/LocalFrame.h"
+#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/svg/SVGScriptElement.h"
#include "platform/MIMETypeRegistry.h"
#include "platform/weborigin/SecurityOrigin.h"
@@ -115,7 +115,6 @@
DEFINE_STATIC_LOCAL(LanguageSet, languages, ());
if (languages.isEmpty()) {
languages.add("javascript");
- languages.add("javascript");
languages.add("javascript1.0");
languages.add("javascript1.1");
languages.add("javascript1.2");
@@ -282,12 +281,14 @@
bool isHTMLScriptLoader(Element* element)
{
- return element->hasTagName(HTMLNames::scriptTag);
+ ASSERT(element);
+ return isHTMLScriptElement(*element);
}
bool isSVGScriptLoader(Element* element)
{
- return element->hasTagName(SVGNames::scriptTag);
+ ASSERT(element);
+ return isSVGScriptElement(*element);
}
void ScriptLoader::executeScript(const ScriptSourceCode& sourceCode)
@@ -302,26 +303,32 @@
if (!contextDocument)
return;
- Frame* frame = contextDocument->frame();
+ LocalFrame* frame = contextDocument->frame();
bool shouldBypassMainWorldContentSecurityPolicy = (frame && frame->script().shouldBypassMainWorldContentSecurityPolicy()) || elementDocument->contentSecurityPolicy()->allowScriptNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr)) || elementDocument->contentSecurityPolicy()->allowScriptHash(sourceCode.source());
if (!m_isExternalScript && (!shouldBypassMainWorldContentSecurityPolicy && !elementDocument->contentSecurityPolicy()->allowInlineScript(elementDocument->url(), m_startLineNumber)))
return;
- if (m_isExternalScript && m_resource && !m_resource->mimeTypeAllowedByNosniff()) {
- contextDocument->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Refused to execute script from '" + m_resource->url().elidedString() + "' because its MIME type ('" + m_resource->mimeType() + "') is not executable, and strict MIME type checking is enabled.");
- return;
+ if (m_isExternalScript) {
+ ScriptResource* resource = m_resource ? m_resource.get() : sourceCode.resource();
+ if (resource && !resource->mimeTypeAllowedByNosniff()) {
+ contextDocument->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Refused to execute script from '" + resource->url().elidedString() + "' because its MIME type ('" + resource->mimeType() + "') is not executable, and strict MIME type checking is enabled.");
+ return;
+ }
}
if (frame) {
- IgnoreDestructiveWriteCountIncrementer ignoreDesctructiveWriteCountIncrementer(m_isExternalScript ? contextDocument.get() : 0);
+ const bool isImportedScript = contextDocument != elementDocument;
+ // http://www.whatwg.org/specs/web-apps/current-work/#execute-the-script-block step 2.3
+ // with additional support for HTML imports.
+ IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWriteCountIncrementer(m_isExternalScript || isImportedScript ? contextDocument.get() : 0);
if (isHTMLScriptLoader(m_element))
contextDocument->pushCurrentScript(toHTMLScriptElement(m_element));
AccessControlStatus corsCheck = NotSharableCrossOrigin;
- if (sourceCode.resource() && sourceCode.resource()->passesAccessControlCheck(m_element->document().securityOrigin()))
+ if (!m_isExternalScript || (sourceCode.resource() && sourceCode.resource()->passesAccessControlCheck(m_element->document().securityOrigin())))
corsCheck = SharableCrossOrigin;
// Create a script from the script element node, using the script
diff --git a/Source/core/dom/ScriptRunner.cpp b/Source/core/dom/ScriptRunner.cpp
index 2fbf959..d33ea6e 100644
--- a/Source/core/dom/ScriptRunner.cpp
+++ b/Source/core/dom/ScriptRunner.cpp
@@ -81,7 +81,7 @@
void ScriptRunner::resume()
{
if (hasPendingScripts())
- m_timer.startOneShot(0);
+ m_timer.startOneShot(0, FROM_HERE);
}
void ScriptRunner::notifyScriptReady(ScriptLoader* scriptLoader, ExecutionType executionType)
@@ -96,7 +96,7 @@
ASSERT(!m_scriptsToExecuteInOrder.isEmpty());
break;
}
- m_timer.startOneShot(0);
+ m_timer.startOneShot(0, FROM_HERE);
}
void ScriptRunner::notifyScriptLoadError(ScriptLoader* scriptLoader, ExecutionType executionType)
diff --git a/Source/core/dom/ScriptedAnimationController.cpp b/Source/core/dom/ScriptedAnimationController.cpp
index 27a7f6b..29ed5b8 100644
--- a/Source/core/dom/ScriptedAnimationController.cpp
+++ b/Source/core/dom/ScriptedAnimationController.cpp
@@ -110,7 +110,7 @@
// special casting window.
// FIXME: We should not fire events for nodes that are no longer in the tree.
if (DOMWindow* window = eventTarget->toDOMWindow())
- window->dispatchEvent(events[i], 0);
+ window->dispatchEvent(events[i], nullptr);
else
eventTarget->dispatchEvent(events[i]);
}
diff --git a/Source/core/dom/SecurityContext.cpp b/Source/core/dom/SecurityContext.cpp
index d0c3530..9767bf1 100644
--- a/Source/core/dom/SecurityContext.cpp
+++ b/Source/core/dom/SecurityContext.cpp
@@ -27,7 +27,7 @@
#include "config.h"
#include "core/dom/SecurityContext.h"
-#include "core/frame/ContentSecurityPolicy.h"
+#include "core/frame/csp/ContentSecurityPolicy.h"
#include "platform/weborigin/SecurityOrigin.h"
namespace WebCore {
@@ -47,7 +47,7 @@
m_haveInitializedSecurityOrigin = true;
}
-void SecurityContext::setContentSecurityPolicy(PassOwnPtr<ContentSecurityPolicy> contentSecurityPolicy)
+void SecurityContext::setContentSecurityPolicy(PassRefPtr<ContentSecurityPolicy> contentSecurityPolicy)
{
m_contentSecurityPolicy = contentSecurityPolicy;
}
diff --git a/Source/core/dom/SecurityContext.h b/Source/core/dom/SecurityContext.h
index b47c6f4..07f62ad 100644
--- a/Source/core/dom/SecurityContext.h
+++ b/Source/core/dom/SecurityContext.h
@@ -53,7 +53,7 @@
SecurityContext();
virtual ~SecurityContext();
- void setContentSecurityPolicy(PassOwnPtr<ContentSecurityPolicy>);
+ void setContentSecurityPolicy(PassRefPtr<ContentSecurityPolicy>);
void didFailToInitializeSecurityOrigin() { m_haveInitializedSecurityOrigin = false; }
bool haveInitializedSecurityOrigin() const { return m_haveInitializedSecurityOrigin; }
@@ -61,7 +61,7 @@
private:
bool m_haveInitializedSecurityOrigin;
RefPtr<SecurityOrigin> m_securityOrigin;
- OwnPtr<ContentSecurityPolicy> m_contentSecurityPolicy;
+ RefPtr<ContentSecurityPolicy> m_contentSecurityPolicy;
};
} // namespace WebCore
diff --git a/Source/core/dom/SelectorQuery.cpp b/Source/core/dom/SelectorQuery.cpp
index e43511f..a139843 100644
--- a/Source/core/dom/SelectorQuery.cpp
+++ b/Source/core/dom/SelectorQuery.cpp
@@ -36,6 +36,8 @@
#include "core/dom/ElementTraversal.h"
#include "core/dom/Node.h"
#include "core/dom/StaticNodeList.h"
+#include "core/dom/shadow/ElementShadow.h"
+#include "core/dom/shadow/ShadowRoot.h"
namespace WebCore {
@@ -104,9 +106,13 @@
for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector))
selectorCount++;
+ m_crossesTreeBoundary = false;
m_selectors.reserveInitialCapacity(selectorCount);
- for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector))
+ unsigned index = 0;
+ for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector), ++index) {
m_selectors.uncheckedAppend(SelectorData(*selector, SelectorCheckerFastPath::canUse(*selector)));
+ m_crossesTreeBoundary |= selectorList.hasCombinatorCrossingTreeBoundaryAt(index);
+ }
}
inline bool SelectorDataList::selectorMatches(const SelectorData& selectorData, Element& element, const ContainerNode& rootNode) const
@@ -176,7 +182,7 @@
inline bool SelectorDataList::canUseFastQuery(const ContainerNode& rootNode) const
{
- return m_selectors.size() == 1 && rootNode.inDocument() && !rootNode.document().inQuirksMode();
+ return m_selectors.size() == 1 && !m_crossesTreeBoundary && rootNode.inDocument() && !rootNode.document().inQuirksMode();
}
inline bool ancestorHasClassName(ContainerNode& rootNode, const AtomicString& className)
@@ -312,17 +318,81 @@
}
template <typename SelectorQueryTrait>
+bool SelectorDataList::selectorListMatches(ContainerNode& rootNode, Element& element, typename SelectorQueryTrait::OutputType& output) const
+{
+ for (unsigned i = 0; i < m_selectors.size(); ++i) {
+ if (selectorMatches(m_selectors[i], element, rootNode)) {
+ SelectorQueryTrait::appendElement(output, element);
+ return true;
+ }
+ }
+ return false;
+}
+
+template <typename SelectorQueryTrait>
void SelectorDataList::executeSlow(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const
{
for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(*element, &rootNode)) {
- for (unsigned i = 0; i < m_selectors.size(); ++i) {
- if (selectorMatches(m_selectors[i], *element, rootNode)) {
- SelectorQueryTrait::appendElement(output, *element);
- if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
- return;
- break;
- }
- }
+ if (selectorListMatches<SelectorQueryTrait>(rootNode, *element, output) && SelectorQueryTrait::shouldOnlyMatchFirstElement)
+ return;
+ }
+}
+
+// FIXME: Move the following helper functions, authorShadowRootOf, firstWithinTraversingShadowTree,
+// nextTraversingShadowTree to the best place, e.g. NodeTraversal.
+static ShadowRoot* authorShadowRootOf(const ContainerNode& node)
+{
+ if (!node.isElementNode() || !isShadowHost(&node))
+ return 0;
+
+ ElementShadow* shadow = toElement(node).shadow();
+ ASSERT(shadow);
+ for (ShadowRoot* shadowRoot = shadow->oldestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->youngerShadowRoot()) {
+ if (shadowRoot->type() == ShadowRoot::AuthorShadowRoot)
+ return shadowRoot;
+ }
+ return 0;
+}
+
+static ContainerNode* firstWithinTraversingShadowTree(const ContainerNode& rootNode)
+{
+ if (ShadowRoot* shadowRoot = authorShadowRootOf(rootNode))
+ return shadowRoot;
+ return ElementTraversal::firstWithin(rootNode);
+}
+
+static ContainerNode* nextTraversingShadowTree(const ContainerNode& node, const ContainerNode* rootNode)
+{
+ if (ShadowRoot* shadowRoot = authorShadowRootOf(node))
+ return shadowRoot;
+
+ if (Element* next = ElementTraversal::next(node, rootNode))
+ return next;
+
+ if (!node.isInShadowTree())
+ return 0;
+
+ ShadowRoot* shadowRoot = node.containingShadowRoot();
+ if (shadowRoot == rootNode)
+ return 0;
+ if (ShadowRoot* youngerShadowRoot = shadowRoot->youngerShadowRoot()) {
+ // Should not obtain any elements in user-agent shadow root.
+ ASSERT(youngerShadowRoot->type() == ShadowRoot::AuthorShadowRoot);
+ return youngerShadowRoot;
+ }
+ Element* shadowHost = shadowRoot->host();
+ return ElementTraversal::next(*shadowHost, rootNode);
+}
+
+template <typename SelectorQueryTrait>
+void SelectorDataList::executeSlowTraversingShadowTree(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const
+{
+ for (ContainerNode* node = firstWithinTraversingShadowTree(rootNode); node; node = nextTraversingShadowTree(*node, &rootNode)) {
+ if (!node->isElementNode())
+ continue;
+ Element* element = toElement(node);
+ if (selectorListMatches<SelectorQueryTrait>(rootNode, *element, output) && SelectorQueryTrait::shouldOnlyMatchFirstElement)
+ return;
}
}
@@ -341,7 +411,10 @@
void SelectorDataList::execute(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const
{
if (!canUseFastQuery(rootNode)) {
- executeSlow<SelectorQueryTrait>(rootNode, output);
+ if (m_crossesTreeBoundary)
+ executeSlowTraversingShadowTree<SelectorQueryTrait>(rootNode, output);
+ else
+ executeSlow<SelectorQueryTrait>(rootNode, output);
return;
}
diff --git a/Source/core/dom/SelectorQuery.h b/Source/core/dom/SelectorQuery.h
index c413f3a..726b677 100644
--- a/Source/core/dom/SelectorQuery.h
+++ b/Source/core/dom/SelectorQuery.h
@@ -76,12 +76,17 @@
void executeForTraverseRoots(const SelectorData&, SimpleElementListType& traverseRoots, MatchTraverseRootState, ContainerNode& rootNode, typename SelectorQueryTrait::OutputType&) const;
template <typename SelectorQueryTrait>
+ bool selectorListMatches(ContainerNode& rootNode, Element&, typename SelectorQueryTrait::OutputType&) const;
+ template <typename SelectorQueryTrait>
void executeSlow(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType&) const;
template <typename SelectorQueryTrait>
+ void executeSlowTraversingShadowTree(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType&) const;
+ template <typename SelectorQueryTrait>
void execute(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType&) const;
const CSSSelector* selectorForIdLookup(const CSSSelector&) const;
Vector<SelectorData> m_selectors;
+ bool m_crossesTreeBoundary;
};
class SelectorQuery {
diff --git a/Source/core/dom/ShadowTreeStyleSheetCollection.cpp b/Source/core/dom/ShadowTreeStyleSheetCollection.cpp
index 6a74608..3e81992 100644
--- a/Source/core/dom/ShadowTreeStyleSheetCollection.cpp
+++ b/Source/core/dom/ShadowTreeStyleSheetCollection.cpp
@@ -53,14 +53,14 @@
StyleSheet* sheet = 0;
CSSStyleSheet* activeSheet = 0;
- if (!node->isHTMLElement() || !node->hasTagName(styleTag))
+ if (!isHTMLStyleElement(*node))
continue;
- Element* element = toElement(node);
+ HTMLStyleElement* element = toHTMLStyleElement(node);
const AtomicString& title = element->fastGetAttribute(titleAttr);
bool enabledViaScript = false;
- sheet = toHTMLStyleElement(node)->sheet();
+ sheet = element->sheet();
if (sheet && !sheet->disabled() && sheet->isCSSStyleSheet())
activeSheet = toCSSStyleSheet(sheet);
diff --git a/Source/core/dom/SiblingRuleHelper.cpp b/Source/core/dom/SiblingRuleHelper.cpp
new file mode 100644
index 0000000..7ebc4ca
--- /dev/null
+++ b/Source/core/dom/SiblingRuleHelper.cpp
@@ -0,0 +1,130 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/dom/SiblingRuleHelper.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/StyleEngine.h"
+#include "core/dom/shadow/ShadowRoot.h"
+
+namespace WebCore {
+
+bool SiblingRuleHelper::isFinishedParsingChildren()
+{
+ if (m_node->isElementNode())
+ return toElement(m_node)->isFinishedParsingChildren();
+
+ return toShadowRoot(m_node)->isFinishedParsingChildren();
+}
+
+void SiblingRuleHelper::setChildrenAffectedByDirectAdjacentRules()
+{
+ if (m_node->isElementNode())
+ toElement(m_node)->setChildrenAffectedByDirectAdjacentRules();
+ else
+ toShadowRoot(m_node)->setChildrenAffectedByDirectAdjacentRules();
+}
+
+void SiblingRuleHelper::setChildrenAffectedByForwardPositionalRules()
+{
+ if (m_node->isElementNode())
+ toElement(m_node)->setChildrenAffectedByForwardPositionalRules();
+ else
+ toShadowRoot(m_node)->setChildrenAffectedByForwardPositionalRules();
+}
+
+void SiblingRuleHelper::setChildrenAffectedByBackwardPositionalRules()
+{
+ if (m_node->isElementNode())
+ toElement(m_node)->setChildrenAffectedByBackwardPositionalRules();
+ else
+ toShadowRoot(m_node)->setChildrenAffectedByBackwardPositionalRules();
+}
+
+void SiblingRuleHelper::setChildrenAffectedByFirstChildRules()
+{
+ if (m_node->isElementNode())
+ toElement(m_node)->setChildrenAffectedByFirstChildRules();
+ else
+ toShadowRoot(m_node)->setChildrenAffectedByFirstChildRules();
+}
+
+void SiblingRuleHelper::setChildrenAffectedByLastChildRules()
+{
+ if (m_node->isElementNode())
+ toElement(m_node)->setChildrenAffectedByLastChildRules();
+ else
+ toShadowRoot(m_node)->setChildrenAffectedByLastChildRules();
+}
+
+bool SiblingRuleHelper::childrenAffectedByPositionalRules() const
+{
+ return m_node->isElementNode() ? toElement(m_node)->childrenAffectedByPositionalRules() : toShadowRoot(m_node)->childrenAffectedByPositionalRules();
+}
+
+bool SiblingRuleHelper::childrenAffectedByFirstChildRules() const
+{
+ return m_node->isElementNode() ? toElement(m_node)->childrenAffectedByFirstChildRules() : toShadowRoot(m_node)->childrenAffectedByFirstChildRules();
+}
+
+bool SiblingRuleHelper::childrenAffectedByLastChildRules() const
+{
+ return m_node->isElementNode() ? toElement(m_node)->childrenAffectedByLastChildRules() : toShadowRoot(m_node)->childrenAffectedByLastChildRules();
+}
+
+bool SiblingRuleHelper::childrenAffectedByDirectAdjacentRules() const
+{
+ return m_node->isElementNode() ? toElement(m_node)->childrenAffectedByDirectAdjacentRules() : toShadowRoot(m_node)->childrenAffectedByDirectAdjacentRules();
+}
+
+bool SiblingRuleHelper::childrenAffectedByForwardPositionalRules() const
+{
+ return m_node->isElementNode() ? toElement(m_node)->childrenAffectedByForwardPositionalRules() : toShadowRoot(m_node)->childrenAffectedByForwardPositionalRules();
+}
+
+bool SiblingRuleHelper::childrenAffectedByBackwardPositionalRules() const
+{
+ return m_node->isElementNode() ? toElement(m_node)->childrenAffectedByBackwardPositionalRules() : toShadowRoot(m_node)->childrenAffectedByBackwardPositionalRules();
+}
+
+void SiblingRuleHelper::checkForChildrenAdjacentRuleChanges()
+{
+ bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules();
+ bool hasIndirectAdjacentRules = childrenAffectedByForwardPositionalRules();
+
+ if (!hasDirectAdjacentRules && !hasIndirectAdjacentRules)
+ return;
+
+ unsigned forceCheckOfNextElementCount = 0;
+ bool forceCheckOfAnyElementSibling = false;
+ Document& document = m_node->document();
+
+ for (Node* child = m_node->firstChild(); child; child = child->nextSibling()) {
+ if (!child->isElementNode())
+ continue;
+ Element* element = toElement(child);
+ bool childRulesChanged = element->needsStyleRecalc() && element->styleChangeType() >= SubtreeStyleChange;
+
+ if (forceCheckOfNextElementCount || forceCheckOfAnyElementSibling)
+ element->setNeedsStyleRecalc(SubtreeStyleChange);
+
+ if (forceCheckOfNextElementCount)
+ forceCheckOfNextElementCount--;
+
+ if (childRulesChanged && hasDirectAdjacentRules)
+ forceCheckOfNextElementCount = document.styleEngine()->maxDirectAdjacentSelectors();
+
+ forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);
+ }
+}
+
+bool SiblingRuleHelper::childrenSupportStyleSharing()
+{
+ return m_node->isElementNode() ? toElement(m_node)->childrenSupportStyleSharing() : toShadowRoot(m_node)->childrenSupportStyleSharing();
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/dom/SiblingRuleHelper.h b/Source/core/dom/SiblingRuleHelper.h
new file mode 100644
index 0000000..1ae2d9c
--- /dev/null
+++ b/Source/core/dom/SiblingRuleHelper.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SiblingRuleHelper_h
+#define SiblingRuleHelper_h
+
+#include "core/dom/Node.h"
+
+namespace WebCore {
+
+class SiblingRuleHelper {
+public:
+ SiblingRuleHelper(Node* node) : m_node(node)
+ {
+ ASSERT(node);
+ ASSERT(node->isElementNode() || node->isShadowRoot());
+ }
+
+ void checkForChildrenAdjacentRuleChanges();
+
+ void setChildrenAffectedByDirectAdjacentRules();
+ void setChildrenAffectedByForwardPositionalRules();
+ void setChildrenAffectedByBackwardPositionalRules();
+ void setChildrenAffectedByFirstChildRules();
+ void setChildrenAffectedByLastChildRules();
+
+ bool isFinishedParsingChildren();
+
+ bool childrenSupportStyleSharing();
+
+private:
+ bool childrenAffectedByPositionalRules() const;
+ bool childrenAffectedByFirstChildRules() const;
+ bool childrenAffectedByLastChildRules() const;
+ bool childrenAffectedByDirectAdjacentRules() const;
+ bool childrenAffectedByForwardPositionalRules() const;
+ bool childrenAffectedByBackwardPositionalRules() const;
+
+ Node* m_node;
+};
+
+} // namespace
+
+#endif
diff --git a/Source/core/dom/StyleElement.cpp b/Source/core/dom/StyleElement.cpp
index e744c9b..5d377b8 100644
--- a/Source/core/dom/StyleElement.cpp
+++ b/Source/core/dom/StyleElement.cpp
@@ -28,8 +28,9 @@
#include "core/dom/Element.h"
#include "core/dom/ScriptableDocumentParser.h"
#include "core/dom/StyleEngine.h"
+#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/HTMLStyleElement.h"
-#include "core/frame/ContentSecurityPolicy.h"
+#include "platform/TraceEvent.h"
#include "wtf/text/StringBuilder.h"
namespace WebCore {
@@ -56,6 +57,7 @@
void StyleElement::processStyleSheet(Document& document, Element* element)
{
+ TRACE_EVENT0("webkit", "StyleElement::processStyleSheet");
ASSERT(element);
document.styleEngine()->addStyleSheetCandidateNode(element, m_createdByParser);
if (m_createdByParser)
@@ -64,15 +66,20 @@
process(element);
}
-void StyleElement::removedFromDocument(Document& document, Element* element, ContainerNode* scopingNode)
+void StyleElement::removedFromDocument(Document& document, Element* element)
+{
+ removedFromDocument(document, element, 0, document);
+}
+
+void StyleElement::removedFromDocument(Document& document, Element* element, ContainerNode* scopingNode, TreeScope& treeScope)
{
ASSERT(element);
- document.styleEngine()->removeStyleSheetCandidateNode(element, scopingNode);
+ document.styleEngine()->removeStyleSheetCandidateNode(element, scopingNode, treeScope);
RefPtr<StyleSheet> removedSheet = m_sheet;
if (m_sheet)
- clearSheet();
+ clearSheet(element);
document.removedStyleSheet(removedSheet.get(), RecalcStyleDeferred, AnalyzedStyleUpdate);
}
@@ -82,8 +89,11 @@
if (m_sheet)
m_sheet->clearOwnerNode();
- if (element->inDocument())
- document.styleEngine()->removeStyleSheetCandidateNode(element, element->hasTagName(HTMLNames::styleTag) ? toHTMLStyleElement(element)->scopingNode() : 0);
+ if (element->inDocument()) {
+ ContainerNode* scopingNode = isHTMLStyleElement(element) ? toHTMLStyleElement(element)->scopingNode() : 0;
+ TreeScope& treeScope = scopingNode ? scopingNode->treeScope() : element->treeScope();
+ document.styleEngine()->removeStyleSheetCandidateNode(element, scopingNode, treeScope);
+ }
}
void StyleElement::childrenChanged(Element* element)
@@ -109,9 +119,13 @@
createSheet(element, element->textFromChildren());
}
-void StyleElement::clearSheet()
+void StyleElement::clearSheet(Element* ownerElement)
{
ASSERT(m_sheet);
+
+ if (ownerElement && m_sheet->isLoading())
+ ownerElement->document().styleEngine()->removePendingSheet(ownerElement);
+
m_sheet.release()->clearOwnerNode();
}
@@ -120,17 +134,14 @@
ASSERT(e);
ASSERT(e->inDocument());
Document& document = e->document();
- if (m_sheet) {
- if (m_sheet->isLoading())
- document.styleEngine()->removePendingSheet(e);
- clearSheet();
- }
+ if (m_sheet)
+ clearSheet(e);
// If type is empty or CSS, this is a CSS style sheet.
const AtomicString& type = this->type();
bool passesContentSecurityPolicyChecks = document.contentSecurityPolicy()->allowStyleHash(text) || document.contentSecurityPolicy()->allowStyleNonce(e->fastGetAttribute(HTMLNames::nonceAttr)) || document.contentSecurityPolicy()->allowInlineStyle(e->document().url(), m_startPosition.m_line);
if (isCSS(e, type) && passesContentSecurityPolicyChecks) {
- RefPtr<MediaQuerySet> mediaQueries = MediaQuerySet::create(media());
+ RefPtrWillBeRawPtr<MediaQuerySet> mediaQueries = MediaQuerySet::create(media());
MediaQueryEvaluator screenEval("screen", true);
MediaQueryEvaluator printEval("print", true);
diff --git a/Source/core/dom/StyleElement.h b/Source/core/dom/StyleElement.h
index a26f5a5..b10337e 100644
--- a/Source/core/dom/StyleElement.h
+++ b/Source/core/dom/StyleElement.h
@@ -29,6 +29,7 @@
class ContainerNode;
class Document;
class Element;
+class TreeScope;
class StyleElement {
public:
@@ -46,7 +47,8 @@
void startLoadingDynamicSheet(Document&);
void processStyleSheet(Document&, Element*);
- void removedFromDocument(Document&, Element*, ContainerNode* scopingNode = 0);
+ void removedFromDocument(Document&, Element*);
+ void removedFromDocument(Document&, Element*, ContainerNode* scopingNode, TreeScope&);
void clearDocumentData(Document&, Element*);
void childrenChanged(Element*);
void finishParsingChildren(Element*);
@@ -56,7 +58,7 @@
private:
void createSheet(Element*, const String& text = String());
void process(Element*);
- void clearSheet();
+ void clearSheet(Element* ownerElement = 0);
bool m_createdByParser;
bool m_loading;
diff --git a/Source/core/dom/StyleEngine.cpp b/Source/core/dom/StyleEngine.cpp
index 8f329f8..756d3cc 100644
--- a/Source/core/dom/StyleEngine.cpp
+++ b/Source/core/dom/StyleEngine.cpp
@@ -41,11 +41,11 @@
#include "core/dom/ShadowTreeStyleSheetCollection.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/html/HTMLIFrameElement.h"
-#include "core/html/HTMLImport.h"
#include "core/html/HTMLLinkElement.h"
+#include "core/html/imports/HTMLImport.h"
#include "core/inspector/InspectorInstrumentation.h"
+#include "core/page/InjectedStyleSheets.h"
#include "core/page/Page.h"
-#include "core/page/PageGroup.h"
#include "core/frame/Settings.h"
#include "core/svg/SVGStyleElement.h"
#include "platform/URLPatternMatcher.h"
@@ -54,18 +54,28 @@
using namespace HTMLNames;
-static HashMap<AtomicString, StyleSheetContents*>& textToSheetCache()
+static WillBeHeapHashMap<AtomicString, RawPtrWillBeWeakMember<StyleSheetContents> >& textToSheetCache()
{
- typedef HashMap<AtomicString, StyleSheetContents*> TextToSheetCache;
+ typedef WillBeHeapHashMap<AtomicString, RawPtrWillBeWeakMember<StyleSheetContents> > TextToSheetCache;
+#if ENABLE(OILPAN)
+ DEFINE_STATIC_LOCAL(Persistent<TextToSheetCache>, cache, (new TextToSheetCache));
+ return *cache;
+#else
DEFINE_STATIC_LOCAL(TextToSheetCache, cache, ());
return cache;
+#endif
}
-static HashMap<StyleSheetContents*, AtomicString>& sheetToTextCache()
+static WillBeHeapHashMap<RawPtrWillBeWeakMember<StyleSheetContents>, AtomicString>& sheetToTextCache()
{
- typedef HashMap<StyleSheetContents*, AtomicString> SheetToTextCache;
+ typedef WillBeHeapHashMap<RawPtrWillBeWeakMember<StyleSheetContents>, AtomicString> SheetToTextCache;
+#if ENABLE(OILPAN)
+ DEFINE_STATIC_LOCAL(Persistent<SheetToTextCache>, cache, (new SheetToTextCache));
+ return *cache;
+#else
DEFINE_STATIC_LOCAL(SheetToTextCache, cache, ());
return cache;
+#endif
}
StyleEngine::StyleEngine(Document& document)
@@ -85,12 +95,19 @@
, m_didCalculateResolver(false)
// We don't need to create CSSFontSelector for imported document or
// HTMLTemplateElement's document, because those documents have no frame.
- , m_fontSelector(document.frame() ? CSSFontSelector::create(&document) : 0)
+ , m_fontSelector(document.frame() ? CSSFontSelector::create(&document) : nullptr)
{
}
StyleEngine::~StyleEngine()
{
+}
+
+void StyleEngine::detachFromDocument()
+{
+ // Cleanup is performed eagerly when the StyleEngine is removed from the
+ // document. The StyleEngine is unreachable after this, since only the
+ // document has a reference to it.
for (unsigned i = 0; i < m_injectedAuthorStyleSheets.size(); ++i)
m_injectedAuthorStyleSheets[i]->clearOwnerNode();
for (unsigned i = 0; i < m_authorStyleSheets.size(); ++i)
@@ -101,6 +118,11 @@
if (m_resolver)
m_fontSelector->unregisterForInvalidationCallbacks(m_resolver.get());
}
+
+ // Decrement reference counts for things we could be keeping alive.
+ m_fontSelector.clear();
+ m_resolver.clear();
+ m_styleSheetCollectionMap.clear();
}
inline Document* StyleEngine::master()
@@ -162,7 +184,7 @@
return it->value.get();
}
-const Vector<RefPtr<StyleSheet> >& StyleEngine::styleSheetsForStyleSheetList(TreeScope& treeScope)
+const WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& StyleEngine::styleSheetsForStyleSheetList(TreeScope& treeScope)
{
if (treeScope == m_document)
return m_documentStyleSheetCollection.styleSheetsForStyleSheetList();
@@ -170,7 +192,7 @@
return ensureStyleSheetCollectionFor(treeScope)->styleSheetsForStyleSheetList();
}
-const Vector<RefPtr<CSSStyleSheet> >& StyleEngine::activeAuthorStyleSheets() const
+const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& StyleEngine::activeAuthorStyleSheets() const
{
return m_documentStyleSheetCollection.activeAuthorStyleSheets();
}
@@ -190,7 +212,7 @@
m_maxDirectAdjacentSelectors = features.maxDirectAdjacentSelectors();
}
-const Vector<RefPtr<CSSStyleSheet> >& StyleEngine::injectedAuthorStyleSheets() const
+const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& StyleEngine::injectedAuthorStyleSheets() const
{
updateInjectedStyleSheetCache();
return m_injectedAuthorStyleSheets;
@@ -214,7 +236,7 @@
continue;
if (!URLPatternMatcher::matchesPatterns(m_document.url(), entry->whitelist()))
continue;
- RefPtr<CSSStyleSheet> groupSheet = CSSStyleSheet::createInline(const_cast<Document*>(&m_document), KURL());
+ RefPtrWillBeRawPtr<CSSStyleSheet> groupSheet = CSSStyleSheet::createInline(const_cast<Document*>(&m_document), KURL());
m_injectedAuthorStyleSheets.append(groupSheet);
groupSheet->contents()->parseString(entry->source());
}
@@ -229,7 +251,7 @@
m_document.styleResolverChanged(RecalcStyleDeferred);
}
-void StyleEngine::addAuthorSheet(PassRefPtr<StyleSheetContents> authorSheet)
+void StyleEngine::addAuthorSheet(PassRefPtrWillBeRawPtr<StyleSheetContents> authorSheet)
{
m_authorStyleSheets.append(CSSStyleSheet::create(authorSheet, &m_document));
m_document.addedStyleSheet(m_authorStyleSheets.last().get(), RecalcStyleImmediately);
@@ -238,26 +260,16 @@
void StyleEngine::addPendingSheet()
{
- master()->styleEngine()->notifyPendingStyleSheetAdded();
+ m_pendingStylesheets++;
}
// This method is called whenever a top-level stylesheet has finished loading.
void StyleEngine::removePendingSheet(Node* styleSheetCandidateNode, RemovePendingSheetNotificationType notification)
{
- TreeScope* treeScope = styleSheetCandidateNode->hasTagName(styleTag) ? &styleSheetCandidateNode->treeScope() : &m_document;
+ ASSERT(styleSheetCandidateNode);
+ TreeScope* treeScope = isHTMLStyleElement(*styleSheetCandidateNode) ? &styleSheetCandidateNode->treeScope() : &m_document;
markTreeScopeDirty(*treeScope);
- master()->styleEngine()->notifyPendingStyleSheetRemoved(notification);
-}
-void StyleEngine::notifyPendingStyleSheetAdded()
-{
- ASSERT(isMaster());
- m_pendingStylesheets++;
-}
-
-void StyleEngine::notifyPendingStyleSheetRemoved(RemovePendingSheetNotificationType notification)
-{
- ASSERT(isMaster());
// Make sure we knew this sheet was pending, and that our count isn't out of sync.
ASSERT(m_pendingStylesheets > 0);
@@ -284,8 +296,8 @@
if (!node || !node->inDocument())
return;
- TreeScope& treeScope = node->hasTagName(styleTag) ? node->treeScope() : m_document;
- ASSERT(node->hasTagName(styleTag) || treeScope == m_document);
+ TreeScope& treeScope = isHTMLStyleElement(*node) ? node->treeScope() : m_document;
+ ASSERT(isHTMLStyleElement(node) || treeScope == m_document);
markTreeScopeDirty(treeScope);
}
@@ -295,8 +307,8 @@
if (!node->inDocument())
return;
- TreeScope& treeScope = node->hasTagName(styleTag) ? node->treeScope() : m_document;
- ASSERT(node->hasTagName(styleTag) || treeScope == m_document);
+ TreeScope& treeScope = isHTMLStyleElement(*node) ? node->treeScope() : m_document;
+ ASSERT(isHTMLStyleElement(node) || treeScope == m_document);
TreeScopeStyleSheetCollection* collection = ensureStyleSheetCollectionFor(treeScope);
ASSERT(collection);
@@ -307,10 +319,14 @@
insertTreeScopeInDocumentOrder(m_activeTreeScopes, &treeScope);
}
-void StyleEngine::removeStyleSheetCandidateNode(Node* node, ContainerNode* scopingNode)
+void StyleEngine::removeStyleSheetCandidateNode(Node* node)
{
- TreeScope& treeScope = scopingNode ? scopingNode->treeScope() : m_document;
- ASSERT(node->hasTagName(styleTag) || treeScope == m_document);
+ removeStyleSheetCandidateNode(node, 0, m_document);
+}
+
+void StyleEngine::removeStyleSheetCandidateNode(Node* node, ContainerNode* scopingNode, TreeScope& treeScope)
+{
+ ASSERT(isHTMLStyleElement(node) || treeScope == m_document);
TreeScopeStyleSheetCollection* collection = styleSheetCollectionFor(treeScope);
ASSERT(collection);
@@ -325,8 +341,8 @@
if (!node->inDocument())
return;
- TreeScope& treeScope = node->hasTagName(styleTag) ? node->treeScope() : m_document;
- ASSERT(node->hasTagName(styleTag) || treeScope == m_document);
+ TreeScope& treeScope = isHTMLStyleElement(*node) ? node->treeScope() : m_document;
+ ASSERT(isHTMLStyleElement(node) || treeScope == m_document);
markTreeScopeDirty(treeScope);
}
@@ -356,7 +372,7 @@
void StyleEngine::updateStyleSheetsInImport(DocumentStyleSheetCollector& parentCollector)
{
ASSERT(!isMaster());
- Vector<RefPtr<StyleSheet> > sheetsForList;
+ WillBeHeapVector<RefPtrWillBeMember<StyleSheet> > sheetsForList;
ImportedDocumentStyleSheetCollector subcollector(parentCollector, sheetsForList);
m_documentStyleSheetCollection.collectStyleSheets(this, subcollector);
m_documentStyleSheetCollection.swapSheetsForSheetList(sheetsForList);
@@ -401,20 +417,20 @@
return requiresFullStyleRecalc;
}
-const Vector<RefPtr<StyleSheet> > StyleEngine::activeStyleSheetsForInspector() const
+const WillBeHeapVector<RefPtrWillBeMember<StyleSheet> > StyleEngine::activeStyleSheetsForInspector() const
{
if (m_activeTreeScopes.isEmpty())
return m_documentStyleSheetCollection.styleSheetsForStyleSheetList();
- Vector<RefPtr<StyleSheet> > activeStyleSheets;
+ WillBeHeapVector<RefPtrWillBeMember<StyleSheet> > activeStyleSheets;
- activeStyleSheets.append(m_documentStyleSheetCollection.styleSheetsForStyleSheetList());
+ activeStyleSheets.appendVector(m_documentStyleSheetCollection.styleSheetsForStyleSheetList());
TreeScopeSet::const_iterator begin = m_activeTreeScopes.begin();
TreeScopeSet::const_iterator end = m_activeTreeScopes.end();
for (TreeScopeSet::const_iterator it = begin; it != end; ++it) {
if (TreeScopeStyleSheetCollection* collection = m_styleSheetCollectionMap.get(*it))
- activeStyleSheets.append(collection->styleSheetsForStyleSheetList());
+ activeStyleSheets.appendVector(collection->styleSheetsForStyleSheetList());
}
// FIXME: Inspector needs a vector which has all active stylesheets.
@@ -459,7 +475,7 @@
m_resolver = adoptPtr(new StyleResolver(m_document));
appendActiveAuthorStyleSheets();
m_fontSelector->registerForInvalidationCallbacks(m_resolver.get());
- combineCSSFeatureFlags(m_resolver->ensureRuleFeatureSet());
+ combineCSSFeatureFlags(m_resolver->ensureUpdatedRuleFeatureSet());
}
void StyleEngine::clearResolver()
@@ -467,8 +483,10 @@
ASSERT(!m_document.inStyleRecalc());
ASSERT(isMaster() || !m_resolver);
ASSERT(m_fontSelector || !m_resolver);
- if (m_resolver)
+ if (m_resolver) {
+ m_document.updateStyleInvalidationIfNeeded();
m_fontSelector->unregisterForInvalidationCallbacks(m_resolver.get());
+ }
m_resolver.clear();
}
@@ -539,7 +557,7 @@
m_resolver->invalidateMatchedPropertiesCache();
}
-void StyleEngine::removeFontFaceRules(const Vector<const StyleRuleFontFace*>& fontFaceRules)
+void StyleEngine::removeFontFaceRules(const WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFontFace> >& fontFaceRules)
{
if (!m_fontSelector)
return;
@@ -577,16 +595,16 @@
if (!e->document().inQuirksMode()) {
AtomicString textContent(text);
- HashMap<AtomicString, StyleSheetContents*>::AddResult result = textToSheetCache().add(textContent, 0);
- if (result.isNewEntry || !result.storedValue->value) {
+ WillBeHeapHashMap<AtomicString, RawPtrWillBeWeakMember<StyleSheetContents> >::iterator it = textToSheetCache().find(textContent);
+ if (it == textToSheetCache().end()) {
styleSheet = StyleEngine::parseSheet(e, text, startPosition, createdByParser);
- if (result.isNewEntry && styleSheet->contents()->maybeCacheable()) {
- result.storedValue->value = styleSheet->contents();
+ if (styleSheet->contents()->maybeCacheable()) {
+ textToSheetCache().add(textContent, styleSheet->contents());
sheetToTextCache().add(styleSheet->contents(), textContent);
}
} else {
- ASSERT(result.storedValue->value->maybeCacheable());
- styleSheet = CSSStyleSheet::createInline(result.storedValue->value, e, startPosition);
+ ASSERT(it->value->maybeCacheable());
+ styleSheet = CSSStyleSheet::createInline(it->value, e, startPosition);
}
} else {
// FIXME: currently we don't cache StyleSheetContents inQuirksMode.
@@ -608,7 +626,7 @@
void StyleEngine::removeSheet(StyleSheetContents* contents)
{
- HashMap<StyleSheetContents*, AtomicString>::iterator it = sheetToTextCache().find(contents);
+ WillBeHeapHashMap<RawPtrWillBeWeakMember<StyleSheetContents>, AtomicString>::iterator it = sheetToTextCache().find(contents);
if (it == sheetToTextCache().end())
return;
@@ -616,4 +634,10 @@
sheetToTextCache().remove(contents);
}
+void StyleEngine::trace(Visitor* visitor)
+{
+ visitor->trace(m_injectedAuthorStyleSheets);
+ visitor->trace(m_authorStyleSheets);
+}
+
}
diff --git a/Source/core/dom/StyleEngine.h b/Source/core/dom/StyleEngine.h
index d924848..57daab1 100644
--- a/Source/core/dom/StyleEngine.h
+++ b/Source/core/dom/StyleEngine.h
@@ -71,8 +71,8 @@
bool m_needsStyleRecalc;
};
-class StyleEngine {
- WTF_MAKE_FAST_ALLOCATED;
+class StyleEngine : public NoBaseWillBeGarbageCollectedFinalized<StyleEngine> {
+ WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
public:
class IgnoringPendingStylesheet : public TemporaryChange<bool> {
@@ -85,27 +85,30 @@
friend class IgnoringPendingStylesheet;
- static PassOwnPtr<StyleEngine> create(Document& document) { return adoptPtr(new StyleEngine(document)); }
+ static PassOwnPtrWillBeRawPtr<StyleEngine> create(Document& document) { return adoptPtrWillBeNoop(new StyleEngine(document)); }
~StyleEngine();
- const Vector<RefPtr<StyleSheet> >& styleSheetsForStyleSheetList(TreeScope&);
- const Vector<RefPtr<CSSStyleSheet> >& activeAuthorStyleSheets() const;
+ void detachFromDocument();
- const Vector<RefPtr<CSSStyleSheet> >& documentAuthorStyleSheets() const { return m_authorStyleSheets; }
- const Vector<RefPtr<CSSStyleSheet> >& injectedAuthorStyleSheets() const;
+ const WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& styleSheetsForStyleSheetList(TreeScope&);
+ const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& activeAuthorStyleSheets() const;
- const Vector<RefPtr<StyleSheet> > activeStyleSheetsForInspector() const;
+ const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& documentAuthorStyleSheets() const { return m_authorStyleSheets; }
+ const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& injectedAuthorStyleSheets() const;
+
+ const WillBeHeapVector<RefPtrWillBeMember<StyleSheet> > activeStyleSheetsForInspector() const;
void modifiedStyleSheet(StyleSheet*);
void addStyleSheetCandidateNode(Node*, bool createdByParser);
- void removeStyleSheetCandidateNode(Node*, ContainerNode* scopingNode = 0);
+ void removeStyleSheetCandidateNode(Node*);
+ void removeStyleSheetCandidateNode(Node*, ContainerNode* scopingNode, TreeScope&);
void modifiedStyleSheetCandidateNode(Node*);
void invalidateInjectedStyleSheetCache();
void updateInjectedStyleSheetCache() const;
- void addAuthorSheet(PassRefPtr<StyleSheetContents> authorSheet);
+ void addAuthorSheet(PassRefPtrWillBeRawPtr<StyleSheetContents> authorSheet);
void clearMediaQueryRuleSetStyleSheets();
void updateStyleSheetsInImport(DocumentStyleSheetCollector& parentCollector);
@@ -169,7 +172,7 @@
void clearMasterResolver();
CSSFontSelector* fontSelector() { return m_fontSelector.get(); }
- void removeFontFaceRules(const Vector<const StyleRuleFontFace*>&);
+ void removeFontFaceRules(const WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFontFace> >&);
void clearFontCache();
// updateGenericFontFamilySettings is used from WebSettingsImpl.
void updateGenericFontFamilySettings();
@@ -184,6 +187,8 @@
static PassRefPtr<CSSStyleSheet> createSheet(Element*, const String& text, TextPosition startPosition, bool createdByParser);
static void removeSheet(StyleSheetContents*);
+ void trace(Visitor*);
+
private:
StyleEngine(Document&);
@@ -202,9 +207,6 @@
void createResolver();
- void notifyPendingStyleSheetAdded();
- void notifyPendingStyleSheetRemoved(RemovePendingSheetNotificationType);
-
static PassRefPtr<CSSStyleSheet> parseSheet(Element*, const String& text, TextPosition startPosition, bool createdByParser);
Document& m_document;
@@ -216,10 +218,10 @@
// elements and when it is safe to execute scripts.
int m_pendingStylesheets;
- mutable Vector<RefPtr<CSSStyleSheet> > m_injectedAuthorStyleSheets;
+ mutable WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> > m_injectedAuthorStyleSheets;
mutable bool m_injectedStyleSheetCacheValid;
- Vector<RefPtr<CSSStyleSheet> > m_authorStyleSheets;
+ WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> > m_authorStyleSheets;
DocumentStyleSheetCollection m_documentStyleSheetCollection;
HashMap<TreeScope*, OwnPtr<TreeScopeStyleSheetCollection> > m_styleSheetCollectionMap;
diff --git a/Source/core/dom/StyleSheetCandidate.cpp b/Source/core/dom/StyleSheetCandidate.cpp
index f090e25..e9bad97 100644
--- a/Source/core/dom/StyleSheetCandidate.cpp
+++ b/Source/core/dom/StyleSheetCandidate.cpp
@@ -31,9 +31,9 @@
#include "core/dom/Element.h"
#include "core/dom/ProcessingInstruction.h"
#include "core/dom/StyleEngine.h"
-#include "core/html/HTMLImport.h"
#include "core/html/HTMLLinkElement.h"
#include "core/html/HTMLStyleElement.h"
+#include "core/html/imports/HTMLImport.h"
#include "core/svg/SVGStyleElement.h"
namespace WebCore {
@@ -58,12 +58,7 @@
Document* StyleSheetCandidate::importedDocument() const
{
ASSERT(isImport());
- // The stylesheet update traversal shouldn't go into shared import
- // to prevent it from stepping into cycle.
- HTMLLinkElement& element = toHTMLLinkElement(m_node);
- if (!element.importOwnsLoader())
- return 0;
- return element.import();
+ return toHTMLLinkElement(m_node).import();
}
bool StyleSheetCandidate::isAlternate() const
@@ -109,16 +104,16 @@
return Pi;
if (node.isHTMLElement()) {
- if (node.hasTagName(linkTag))
+ if (isHTMLLinkElement(node))
return HTMLLink;
- if (node.hasTagName(styleTag))
+ if (isHTMLStyleElement(node))
return HTMLStyle;
ASSERT_NOT_REACHED();
return HTMLStyle;
}
- if (node.isSVGElement() && node.hasTagName(SVGNames::styleTag))
+ if (isSVGStyleElement(node))
return SVGStyle;
ASSERT_NOT_REACHED();
diff --git a/Source/core/dom/StyleSheetCollection.cpp b/Source/core/dom/StyleSheetCollection.cpp
index 8603903..9187d67 100644
--- a/Source/core/dom/StyleSheetCollection.cpp
+++ b/Source/core/dom/StyleSheetCollection.cpp
@@ -45,16 +45,16 @@
m_activeAuthorStyleSheets.swap(other.m_activeAuthorStyleSheets);
}
-void StyleSheetCollection::swapSheetsForSheetList(Vector<RefPtr<StyleSheet> >& sheets)
+void StyleSheetCollection::swapSheetsForSheetList(WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& sheets)
{
// Only called for collection of HTML Imports that never has active sheets.
ASSERT(m_activeAuthorStyleSheets.isEmpty());
m_styleSheetsForStyleSheetList.swap(sheets);
}
-void StyleSheetCollection::appendActiveStyleSheets(const Vector<RefPtr<CSSStyleSheet> >& sheets)
+void StyleSheetCollection::appendActiveStyleSheets(const WillBePersistentHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& sheets)
{
- m_activeAuthorStyleSheets.append(sheets);
+ m_activeAuthorStyleSheets.appendVector(sheets);
}
void StyleSheetCollection::appendActiveStyleSheet(CSSStyleSheet* sheet)
diff --git a/Source/core/dom/StyleSheetCollection.h b/Source/core/dom/StyleSheetCollection.h
index 47b89ce..7f0da11 100644
--- a/Source/core/dom/StyleSheetCollection.h
+++ b/Source/core/dom/StyleSheetCollection.h
@@ -28,6 +28,7 @@
#ifndef StyleSheetCollection_h
#define StyleSheetCollection_h
+#include "heap/Handle.h"
#include "wtf/FastAllocBase.h"
#include "wtf/RefPtr.h"
#include "wtf/Vector.h"
@@ -46,20 +47,20 @@
StyleSheetCollection();
~StyleSheetCollection();
- Vector<RefPtr<CSSStyleSheet> >& activeAuthorStyleSheets() { return m_activeAuthorStyleSheets; }
- Vector<RefPtr<StyleSheet> >& styleSheetsForStyleSheetList() { return m_styleSheetsForStyleSheetList; }
- const Vector<RefPtr<CSSStyleSheet> >& activeAuthorStyleSheets() const { return m_activeAuthorStyleSheets; }
- const Vector<RefPtr<StyleSheet> >& styleSheetsForStyleSheetList() const { return m_styleSheetsForStyleSheetList; }
+ WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& activeAuthorStyleSheets() { return m_activeAuthorStyleSheets; }
+ WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& styleSheetsForStyleSheetList() { return m_styleSheetsForStyleSheetList; }
+ const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& activeAuthorStyleSheets() const { return m_activeAuthorStyleSheets; }
+ const WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& styleSheetsForStyleSheetList() const { return m_styleSheetsForStyleSheetList; }
void swap(StyleSheetCollection&);
- void swapSheetsForSheetList(Vector<RefPtr<StyleSheet> >&);
- void appendActiveStyleSheets(const Vector<RefPtr<CSSStyleSheet> >&);
+ void swapSheetsForSheetList(WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >&);
+ void appendActiveStyleSheets(const WillBePersistentHeapVector<RefPtrWillBeMember<CSSStyleSheet> >&);
void appendActiveStyleSheet(CSSStyleSheet*);
void appendSheetForList(StyleSheet*);
protected:
- Vector<RefPtr<StyleSheet> > m_styleSheetsForStyleSheetList;
- Vector<RefPtr<CSSStyleSheet> > m_activeAuthorStyleSheets;
+ WillBePersistentHeapVector<RefPtrWillBeMember<StyleSheet> > m_styleSheetsForStyleSheetList;
+ WillBePersistentHeapVector<RefPtrWillBeMember<CSSStyleSheet> > m_activeAuthorStyleSheets;
};
}
diff --git a/Source/core/dom/TagCollection.cpp b/Source/core/dom/TagCollection.cpp
index 275d942..98bd3e4 100644
--- a/Source/core/dom/TagCollection.cpp
+++ b/Source/core/dom/TagCollection.cpp
@@ -29,7 +29,7 @@
namespace WebCore {
-TagCollection::TagCollection(ContainerNode* rootNode, CollectionType type, const AtomicString& namespaceURI, const AtomicString& localName)
+TagCollection::TagCollection(ContainerNode& rootNode, CollectionType type, const AtomicString& namespaceURI, const AtomicString& localName)
: HTMLCollection(rootNode, type, DoesNotOverrideItemAfter)
, m_namespaceURI(namespaceURI)
, m_localName(localName)
@@ -40,9 +40,9 @@
TagCollection::~TagCollection()
{
if (m_namespaceURI == starAtom)
- ownerNode()->nodeLists()->removeCache(this, type(), m_localName);
+ ownerNode().nodeLists()->removeCache(this, type(), m_localName);
else
- ownerNode()->nodeLists()->removeCache(this, m_namespaceURI, m_localName);
+ ownerNode().nodeLists()->removeCache(this, m_namespaceURI, m_localName);
}
bool TagCollection::elementMatches(const Element& testNode) const
@@ -54,7 +54,7 @@
return m_namespaceURI == starAtom || m_namespaceURI == testNode.namespaceURI();
}
-HTMLTagCollection::HTMLTagCollection(ContainerNode* rootNode, const AtomicString& localName)
+HTMLTagCollection::HTMLTagCollection(ContainerNode& rootNode, const AtomicString& localName)
: TagCollection(rootNode, HTMLTagCollectionType, starAtom, localName)
, m_loweredLocalName(localName.lower())
{
diff --git a/Source/core/dom/TagCollection.h b/Source/core/dom/TagCollection.h
index 393741e..7d4782a 100644
--- a/Source/core/dom/TagCollection.h
+++ b/Source/core/dom/TagCollection.h
@@ -33,13 +33,13 @@
// Collection that limits to a particular tag.
class TagCollection : public HTMLCollection {
public:
- static PassRefPtr<TagCollection> create(ContainerNode* rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
+ static PassRefPtr<TagCollection> create(ContainerNode& rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
{
ASSERT(namespaceURI != starAtom);
return adoptRef(new TagCollection(rootNode, TagCollectionType, namespaceURI, localName));
}
- static PassRefPtr<TagCollection> create(ContainerNode* rootNode, CollectionType type, const AtomicString& localName)
+ static PassRefPtr<TagCollection> create(ContainerNode& rootNode, CollectionType type, const AtomicString& localName)
{
ASSERT_UNUSED(type, type == TagCollectionType);
return adoptRef(new TagCollection(rootNode, TagCollectionType, starAtom, localName));
@@ -50,7 +50,7 @@
bool elementMatches(const Element&) const;
protected:
- TagCollection(ContainerNode* rootNode, CollectionType, const AtomicString& namespaceURI, const AtomicString& localName);
+ TagCollection(ContainerNode& rootNode, CollectionType, const AtomicString& namespaceURI, const AtomicString& localName);
AtomicString m_namespaceURI;
AtomicString m_localName;
@@ -58,7 +58,7 @@
class HTMLTagCollection FINAL : public TagCollection {
public:
- static PassRefPtr<HTMLTagCollection> create(ContainerNode* rootNode, CollectionType type, const AtomicString& localName)
+ static PassRefPtr<HTMLTagCollection> create(ContainerNode& rootNode, CollectionType type, const AtomicString& localName)
{
ASSERT_UNUSED(type, type == HTMLTagCollectionType);
return adoptRef(new HTMLTagCollection(rootNode, localName));
@@ -67,7 +67,7 @@
bool elementMatches(const Element&) const;
private:
- HTMLTagCollection(ContainerNode* rootNode, const AtomicString& localName);
+ HTMLTagCollection(ContainerNode& rootNode, const AtomicString& localName);
AtomicString m_loweredLocalName;
};
diff --git a/Source/core/dom/Text.cpp b/Source/core/dom/Text.cpp
index cf67098..d799418 100644
--- a/Source/core/dom/Text.cpp
+++ b/Source/core/dom/Text.cpp
@@ -36,6 +36,7 @@
#include "core/rendering/RenderCombineText.h"
#include "core/rendering/RenderText.h"
#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/svg/SVGForeignObjectElement.h"
#include "wtf/text/CString.h"
#include "wtf/text/StringBuilder.h"
@@ -89,7 +90,7 @@
nextText->setDataWithoutUpdate(emptyString());
nextText->updateTextRenderer(0, nextTextData.length());
- document().didMergeTextNodes(nextText.get(), offset);
+ document().didMergeTextNodes(*nextText, offset);
// Restore nextText for mutation event.
nextText->setDataWithoutUpdate(nextTextData);
@@ -109,7 +110,7 @@
// the number of 16-bit units in data.
if (offset > length()) {
exceptionState.throwDOMException(IndexSizeError, "The offset " + String::number(offset) + " is larger than the Text node's length.");
- return 0;
+ return nullptr;
}
EventQueueScope scope;
@@ -122,13 +123,13 @@
if (parentNode())
parentNode()->insertBefore(newText.get(), nextSibling(), exceptionState);
if (exceptionState.hadException())
- return 0;
+ return nullptr;
if (renderer())
toRenderText(renderer())->setTextWithOffset(dataImpl(), 0, oldStr.length());
if (parentNode())
- document().didSplitTextNode(this);
+ document().didSplitTextNode(*this);
return newText.release();
}
@@ -218,7 +219,7 @@
if (newText.isEmpty()) {
if (parent && parentNode() == parent)
parent->removeChild(this, IGNORE_EXCEPTION);
- return 0;
+ return nullptr;
}
setData(newText);
@@ -290,7 +291,8 @@
static bool isSVGText(Text* text)
{
Node* parentOrShadowHostNode = text->parentOrShadowHostNode();
- return parentOrShadowHostNode->isSVGElement() && !parentOrShadowHostNode->hasTagName(SVGNames::foreignObjectTag);
+ ASSERT(parentOrShadowHostNode);
+ return parentOrShadowHostNode->isSVGElement() && !isSVGForeignObjectElement(*parentOrShadowHostNode);
}
RenderText* Text::createTextRenderer(RenderStyle* style)
diff --git a/Source/core/dom/Touch.cpp b/Source/core/dom/Touch.cpp
index a955bab..18f2734 100644
--- a/Source/core/dom/Touch.cpp
+++ b/Source/core/dom/Touch.cpp
@@ -27,12 +27,12 @@
#include "core/dom/Touch.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
namespace WebCore {
-static int contentsX(Frame* frame)
+static int contentsX(LocalFrame* frame)
{
if (!frame)
return 0;
@@ -42,7 +42,7 @@
return frameView->scrollX() / frame->pageZoomFactor();
}
-static int contentsY(Frame* frame)
+static int contentsY(LocalFrame* frame)
{
if (!frame)
return 0;
@@ -52,7 +52,7 @@
return frameView->scrollY() / frame->pageZoomFactor();
}
-Touch::Touch(Frame* frame, EventTarget* target, unsigned identifier, int screenX, int screenY, int pageX, int pageY, int radiusX, int radiusY, float rotationAngle, float force)
+Touch::Touch(LocalFrame* frame, EventTarget* target, unsigned identifier, int screenX, int screenY, int pageX, int pageY, int radiusX, int radiusY, float rotationAngle, float force)
: m_target(target)
, m_identifier(identifier)
, m_clientX(pageX - contentsX(frame))
@@ -91,9 +91,9 @@
ScriptWrappable::init(this);
}
-PassRefPtr<Touch> Touch::cloneWithNewTarget(EventTarget* eventTarget) const
+PassRefPtrWillBeRawPtr<Touch> Touch::cloneWithNewTarget(EventTarget* eventTarget) const
{
- return adoptRef(new Touch(eventTarget, m_identifier, m_clientX, m_clientY, m_screenX, m_screenY, m_pageX, m_pageY, m_radiusX, m_radiusY, m_rotationAngle, m_force, m_absoluteLocation));
+ return adoptRefWillBeNoop(new Touch(eventTarget, m_identifier, m_clientX, m_clientY, m_screenX, m_screenY, m_pageX, m_pageY, m_radiusX, m_radiusY, m_rotationAngle, m_force, m_absoluteLocation));
}
} // namespace WebCore
diff --git a/Source/core/dom/Touch.h b/Source/core/dom/Touch.h
index 220d4cf..d4f253b 100644
--- a/Source/core/dom/Touch.h
+++ b/Source/core/dom/Touch.h
@@ -28,6 +28,7 @@
#include "bindings/v8/ScriptWrappable.h"
#include "core/events/EventTarget.h"
+#include "heap/Handle.h"
#include "platform/geometry/LayoutPoint.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefCounted.h"
@@ -35,15 +36,15 @@
namespace WebCore {
-class Frame;
+class LocalFrame;
-class Touch : public RefCounted<Touch>, public ScriptWrappable {
+class Touch : public RefCountedWillBeGarbageCollectedFinalized<Touch>, public ScriptWrappable {
public:
- static PassRefPtr<Touch> create(Frame* frame, EventTarget* target,
+ static PassRefPtrWillBeRawPtr<Touch> create(LocalFrame* frame, EventTarget* target,
unsigned identifier, int screenX, int screenY, int pageX, int pageY,
int radiusX, int radiusY, float rotationAngle, float force)
{
- return adoptRef(new Touch(frame, target, identifier, screenX,
+ return adoptRefWillBeNoop(new Touch(frame, target, identifier, screenX,
screenY, pageX, pageY, radiusX, radiusY, rotationAngle, force));
}
@@ -60,10 +61,12 @@
float webkitRotationAngle() const { return m_rotationAngle; }
float webkitForce() const { return m_force; }
const LayoutPoint& absoluteLocation() const { return m_absoluteLocation; }
- PassRefPtr<Touch> cloneWithNewTarget(EventTarget*) const;
+ PassRefPtrWillBeRawPtr<Touch> cloneWithNewTarget(EventTarget*) const;
+
+ void trace(Visitor*) { }
private:
- Touch(Frame* frame, EventTarget* target, unsigned identifier,
+ Touch(LocalFrame* frame, EventTarget* target, unsigned identifier,
int screenX, int screenY, int pageX, int pageY,
int radiusX, int radiusY, float rotationAngle, float force);
diff --git a/Source/core/dom/Touch.idl b/Source/core/dom/Touch.idl
index c748ec8..06e93d9 100644
--- a/Source/core/dom/Touch.idl
+++ b/Source/core/dom/Touch.idl
@@ -23,7 +23,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-interface Touch {
+[
+ WillBeGarbageCollected,
+] interface Touch {
readonly attribute long clientX;
readonly attribute long clientY;
readonly attribute long screenX;
diff --git a/Source/core/dom/TouchList.cpp b/Source/core/dom/TouchList.cpp
index 3653a2e..b636f20 100644
--- a/Source/core/dom/TouchList.cpp
+++ b/Source/core/dom/TouchList.cpp
@@ -41,4 +41,9 @@
return const_cast<TouchList*>(this)->item(index);
}
+void TouchList::trace(Visitor* visitor)
+{
+ visitor->trace(m_values);
+}
+
} // namespace WebCore
diff --git a/Source/core/dom/TouchList.h b/Source/core/dom/TouchList.h
index 6d5f2bf..68b5341 100644
--- a/Source/core/dom/TouchList.h
+++ b/Source/core/dom/TouchList.h
@@ -28,21 +28,22 @@
#include "bindings/v8/ScriptWrappable.h"
#include "core/dom/Touch.h"
+#include "heap/Handle.h"
#include "wtf/RefCounted.h"
#include "wtf/Vector.h"
namespace WebCore {
-class TouchList : public RefCounted<TouchList>, public ScriptWrappable {
+class TouchList : public RefCountedWillBeGarbageCollectedFinalized<TouchList>, public ScriptWrappable {
public:
- static PassRefPtr<TouchList> create()
+ static PassRefPtrWillBeRawPtr<TouchList> create()
{
- return adoptRef(new TouchList);
+ return adoptRefWillBeNoop(new TouchList);
}
- static PassRefPtr<TouchList> create(Vector<RefPtr<Touch> >& touches)
+ static PassRefPtrWillBeRawPtr<TouchList> create(WillBeHeapVector<RefPtrWillBeMember<Touch> >& touches)
{
- return adoptRef(new TouchList(touches));
+ return adoptRefWillBeNoop(new TouchList(touches));
}
unsigned length() const { return m_values.size(); }
@@ -50,7 +51,9 @@
Touch* item(unsigned);
const Touch* item(unsigned) const;
- void append(const PassRefPtr<Touch> touch) { m_values.append(touch); }
+ void append(const PassRefPtrWillBeRawPtr<Touch> touch) { m_values.append(touch); }
+
+ void trace(Visitor*);
private:
TouchList()
@@ -58,13 +61,13 @@
ScriptWrappable::init(this);
}
- TouchList(Vector<RefPtr<Touch> >& touches)
+ TouchList(WillBeHeapVector<RefPtrWillBeMember<Touch> >& touches)
{
m_values.swap(touches);
ScriptWrappable::init(this);
}
- Vector<RefPtr<Touch> > m_values;
+ WillBeHeapVector<RefPtrWillBeMember<Touch> > m_values;
};
} // namespace WebCore
diff --git a/Source/core/dom/TouchList.idl b/Source/core/dom/TouchList.idl
index 351a59c..516946d 100644
--- a/Source/core/dom/TouchList.idl
+++ b/Source/core/dom/TouchList.idl
@@ -23,7 +23,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-interface TouchList {
+[
+ WillBeGarbageCollected,
+] interface TouchList {
readonly attribute unsigned long length;
getter Touch item(unsigned long index);
diff --git a/Source/core/dom/Traversal.h b/Source/core/dom/Traversal.h
deleted file mode 100644
index 58ef152..0000000
--- a/Source/core/dom/Traversal.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
- * Copyright (C) 2004, 2008 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.
- *
- */
-
-#ifndef Traversal_h
-#define Traversal_h
-
-#include "bindings/v8/ScriptState.h"
-#include "wtf/RefPtr.h"
-
-namespace WebCore {
-
- class Node;
- class NodeFilter;
-
- class Traversal {
- public:
- Node* root() const { return m_root.get(); }
- unsigned whatToShow() const { return m_whatToShow; }
- NodeFilter* filter() const { return m_filter.get(); }
- // |expandEntityReferences| first appeared in "DOM Level 2 Traversal and Range". However, this argument was
- // never implemented, and, in DOM4, the function argument |expandEntityReferences| is removed from
- // Document.createNodeIterator() and Document.createTreeWalker().
- bool expandEntityReferences() const { return false; }
-
- protected:
- Traversal(PassRefPtr<Node>, unsigned whatToShow, PassRefPtr<NodeFilter>);
- short acceptNode(ScriptState*, Node*) const;
-
- private:
- RefPtr<Node> m_root;
- unsigned m_whatToShow;
- RefPtr<NodeFilter> m_filter;
- };
-
-} // namespace WebCore
-
-#endif // Traversal_h
diff --git a/Source/core/dom/TreeScope.cpp b/Source/core/dom/TreeScope.cpp
index bd2bcb4..ed11d7e 100644
--- a/Source/core/dom/TreeScope.cpp
+++ b/Source/core/dom/TreeScope.cpp
@@ -38,14 +38,14 @@
#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/events/EventPath.h"
+#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLAnchorElement.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/HTMLLabelElement.h"
#include "core/html/HTMLMapElement.h"
#include "core/page/DOMSelection.h"
#include "core/page/FocusController.h"
-#include "core/frame/Frame.h"
-#include "core/frame/FrameView.h"
#include "core/page/Page.h"
#include "core/rendering/HitTestResult.h"
#include "core/rendering/RenderView.h"
@@ -84,7 +84,7 @@
if (m_selection) {
m_selection->clearTreeScope();
- m_selection = 0;
+ m_selection = nullptr;
}
if (m_parentTreeScope)
@@ -217,7 +217,7 @@
HitTestResult hitTestInDocument(const Document* document, int x, int y)
{
- Frame* frame = document->frame();
+ LocalFrame* frame = document->frame();
if (!frame)
return HitTestResult();
@@ -272,13 +272,10 @@
if (!m_labelsByForAttribute) {
// Populate the map on first access.
m_labelsByForAttribute = adoptPtr(new DocumentOrderedMap);
- for (Element* element = ElementTraversal::firstWithin(rootNode()); element; element = ElementTraversal::next(*element)) {
- if (element->hasTagName(labelTag)) {
- HTMLLabelElement* label = toHTMLLabelElement(element);
- const AtomicString& forValue = label->fastGetAttribute(forAttr);
- if (!forValue.isEmpty())
- addLabel(forValue, label);
- }
+ for (HTMLLabelElement* label = Traversal<HTMLLabelElement>::firstWithin(rootNode()); label; label = Traversal<HTMLLabelElement>::next(*label)) {
+ const AtomicString& forValue = label->fastGetAttribute(forAttr);
+ if (!forValue.isEmpty())
+ addLabel(forValue, label);
}
}
@@ -306,18 +303,15 @@
return 0;
if (Element* element = getElementById(AtomicString(name)))
return element;
- for (Element* element = ElementTraversal::firstWithin(rootNode()); element; element = ElementTraversal::next(*element)) {
- if (element->hasTagName(aTag)) {
- HTMLAnchorElement* anchor = toHTMLAnchorElement(element);
- if (rootNode().document().inQuirksMode()) {
- // Quirks mode, case insensitive comparison of names.
- if (equalIgnoringCase(anchor->name(), name))
- return anchor;
- } else {
- // Strict mode, names need to match exactly.
- if (anchor->name() == name)
- return anchor;
- }
+ for (HTMLAnchorElement* anchor = Traversal<HTMLAnchorElement>::firstWithin(rootNode()); anchor; anchor = Traversal<HTMLAnchorElement>::next(*anchor)) {
+ if (rootNode().document().inQuirksMode()) {
+ // Quirks mode, case insensitive comparison of names.
+ if (equalIgnoringCase(anchor->name(), name))
+ return anchor;
+ } else {
+ // Strict mode, names need to match exactly.
+ if (anchor->name() == name)
+ return anchor;
}
}
return 0;
@@ -338,7 +332,7 @@
adopter.execute();
}
-static Element* focusedFrameOwnerElement(Frame* focusedFrame, Frame* currentFrame)
+static Element* focusedFrameOwnerElement(LocalFrame* focusedFrame, LocalFrame* currentFrame)
{
for (; focusedFrame; focusedFrame = focusedFrame->tree().parent()) {
if (focusedFrame->tree().parent() == currentFrame)
diff --git a/Source/core/dom/TreeScope.h b/Source/core/dom/TreeScope.h
index 6a7703a..cdb299b 100644
--- a/Source/core/dom/TreeScope.h
+++ b/Source/core/dom/TreeScope.h
@@ -28,6 +28,7 @@
#define TreeScope_h
#include "core/dom/DocumentOrderedMap.h"
+#include "heap/Handle.h"
#include "wtf/Forward.h"
#include "wtf/text/AtomicString.h"
@@ -167,7 +168,7 @@
OwnPtr<IdTargetObserverRegistry> m_idTargetObserverRegistry;
- mutable RefPtr<DOMSelection> m_selection;
+ mutable RefPtrWillBePersistent<DOMSelection> m_selection;
};
inline bool TreeScope::hasElementWithId(StringImpl* id) const
diff --git a/Source/core/dom/TreeScopeStyleSheetCollection.cpp b/Source/core/dom/TreeScopeStyleSheetCollection.cpp
index ea7eef7..2daa165 100644
--- a/Source/core/dom/TreeScopeStyleSheetCollection.cpp
+++ b/Source/core/dom/TreeScopeStyleSheetCollection.cpp
@@ -59,10 +59,10 @@
else
m_styleSheetCandidateNodes.add(node);
- if (!node->hasTagName(HTMLNames::styleTag))
+ if (!isHTMLStyleElement(*node))
return;
- ContainerNode* scopingNode = toHTMLStyleElement(node)->scopingNode();
+ ContainerNode* scopingNode = toHTMLStyleElement(*node).scopingNode();
if (!isTreeScopeRoot(scopingNode))
m_scopingNodesForStyleScoped.add(scopingNode);
}
@@ -75,7 +75,7 @@
m_scopingNodesForStyleScoped.remove(scopingNode);
}
-TreeScopeStyleSheetCollection::StyleResolverUpdateType TreeScopeStyleSheetCollection::compareStyleSheets(const Vector<RefPtr<CSSStyleSheet> >& oldStyleSheets, const Vector<RefPtr<CSSStyleSheet> >& newStylesheets, Vector<StyleSheetContents*>& addedSheets)
+TreeScopeStyleSheetCollection::StyleResolverUpdateType TreeScopeStyleSheetCollection::compareStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& oldStyleSheets, const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& newStylesheets, WillBeHeapVector<RawPtrWillBeMember<StyleSheetContents> >& addedSheets)
{
unsigned newStyleSheetCount = newStylesheets.size();
unsigned oldStyleSheetCount = oldStyleSheets.size();
@@ -104,7 +104,7 @@
return hasInsertions ? Reset : Additive;
}
-bool TreeScopeStyleSheetCollection::activeLoadingStyleSheetLoaded(const Vector<RefPtr<CSSStyleSheet> >& newStyleSheets)
+bool TreeScopeStyleSheetCollection::activeLoadingStyleSheetLoaded(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& newStyleSheets)
{
// StyleSheets of <style> elements that @import stylesheets are active but loading. We need to trigger a full recalc when such loads are done.
bool hasActiveLoadingStylesheet = false;
@@ -121,7 +121,7 @@
return false;
}
-static bool findFontFaceRulesFromStyleSheetContents(Vector<StyleSheetContents*> sheets, Vector<const StyleRuleFontFace*>& fontFaceRules)
+static bool findFontFaceRulesFromStyleSheetContents(const WillBeHeapVector<RawPtrWillBeMember<StyleSheetContents> >& sheets, WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFontFace> >& fontFaceRules)
{
bool hasFontFaceRule = false;
@@ -145,7 +145,7 @@
return;
// Find out which stylesheets are new.
- Vector<StyleSheetContents*> addedSheets;
+ WillBeHeapVector<RawPtrWillBeMember<StyleSheetContents> > addedSheets;
if (m_activeAuthorStyleSheets.size() <= newCollection.activeAuthorStyleSheets().size()) {
change.styleResolverUpdateType = compareStyleSheets(m_activeAuthorStyleSheets, newCollection.activeAuthorStyleSheets(), addedSheets);
} else {
@@ -204,7 +204,7 @@
styleResolver->resetAuthorStyle(toContainerNode(&m_treeScope.rootNode()));
}
-static bool styleSheetsUseRemUnits(const Vector<RefPtr<CSSStyleSheet> >& sheets)
+static bool styleSheetsUseRemUnits(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& sheets)
{
for (unsigned i = 0; i < sheets.size(); ++i) {
if (sheets[i]->contents()->usesRemUnits())
diff --git a/Source/core/dom/TreeScopeStyleSheetCollection.h b/Source/core/dom/TreeScopeStyleSheetCollection.h
index 6d24219..f2141c3 100644
--- a/Source/core/dom/TreeScopeStyleSheetCollection.h
+++ b/Source/core/dom/TreeScopeStyleSheetCollection.h
@@ -76,10 +76,12 @@
Additive
};
- struct StyleSheetChange {
+ class StyleSheetChange {
+ STACK_ALLOCATED();
+ public:
StyleResolverUpdateType styleResolverUpdateType;
bool requiresFullStyleRecalc;
- Vector<const StyleRuleFontFace*> fontFaceRulesToRemove;
+ WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFontFace> > fontFaceRulesToRemove;
StyleSheetChange()
: styleResolverUpdateType(Reconstruct)
@@ -91,8 +93,8 @@
void updateUsesRemUnits();
private:
- static StyleResolverUpdateType compareStyleSheets(const Vector<RefPtr<CSSStyleSheet> >& oldStyleSheets, const Vector<RefPtr<CSSStyleSheet> >& newStylesheets, Vector<StyleSheetContents*>& addedSheets);
- bool activeLoadingStyleSheetLoaded(const Vector<RefPtr<CSSStyleSheet> >& newStyleSheets);
+ static StyleResolverUpdateType compareStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& oldStyleSheets, const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& newStylesheets, WillBeHeapVector<RawPtrWillBeMember<StyleSheetContents> >& addedSheets);
+ bool activeLoadingStyleSheetLoaded(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& newStyleSheets);
protected:
TreeScope& m_treeScope;
diff --git a/Source/core/dom/TreeWalker.cpp b/Source/core/dom/TreeWalker.cpp
index fa09981..0bd000f 100644
--- a/Source/core/dom/TreeWalker.cpp
+++ b/Source/core/dom/TreeWalker.cpp
@@ -25,6 +25,7 @@
#include "config.h"
#include "core/dom/TreeWalker.h"
+#include "bindings/v8/ExceptionMessages.h"
#include "bindings/v8/ExceptionState.h"
#include "bindings/v8/ScriptState.h"
#include "core/dom/ContainerNode.h"
@@ -34,7 +35,7 @@
namespace WebCore {
TreeWalker::TreeWalker(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter)
- : Traversal(rootNode, whatToShow, filter)
+ : NodeIteratorBase(rootNode, whatToShow, filter)
, m_current(root())
{
ScriptWrappable::init(this);
@@ -43,7 +44,7 @@
void TreeWalker::setCurrentNode(PassRefPtr<Node> node, ExceptionState& exceptionState)
{
if (!node) {
- exceptionState.throwDOMException(NotSupportedError, "The Node provided is invalid.");
+ exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node"));
return;
}
m_current = node;
diff --git a/Source/core/dom/TreeWalker.h b/Source/core/dom/TreeWalker.h
index 354e449..e1a512f 100644
--- a/Source/core/dom/TreeWalker.h
+++ b/Source/core/dom/TreeWalker.h
@@ -27,7 +27,7 @@
#include "bindings/v8/ScriptWrappable.h"
#include "core/dom/NodeFilter.h"
-#include "core/dom/Traversal.h"
+#include "core/dom/NodeIteratorBase.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefCounted.h"
@@ -35,7 +35,7 @@
class ExceptionState;
-class TreeWalker : public ScriptWrappable, public RefCounted<TreeWalker>, public Traversal {
+class TreeWalker : public ScriptWrappable, public RefCounted<TreeWalker>, public NodeIteratorBase {
public:
static PassRefPtr<TreeWalker> create(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter)
{
diff --git a/Source/core/dom/TreeWalker.idl b/Source/core/dom/TreeWalker.idl
index eecb1ed..efd5cfb 100644
--- a/Source/core/dom/TreeWalker.idl
+++ b/Source/core/dom/TreeWalker.idl
@@ -18,9 +18,9 @@
* Boston, MA 02110-1301, USA.
*/
-// Introduced in DOM Level 2:
+// Introduced in DOM Level 2
[
- SetWrapperReferenceTo(NodeFilter filter)
+ SetWrapperReferenceTo(NodeFilter filter),
] interface TreeWalker {
readonly attribute Node root;
readonly attribute unsigned long whatToShow;
@@ -36,4 +36,3 @@
[CallWith=ScriptState] Node previousNode();
[CallWith=ScriptState] Node nextNode();
};
-
diff --git a/Source/core/dom/URL.idl b/Source/core/dom/URL.idl
index 67dbb1e..f5bf93f 100644
--- a/Source/core/dom/URL.idl
+++ b/Source/core/dom/URL.idl
@@ -30,9 +30,10 @@
Constructor(DOMString url),
Constructor(DOMString url, URL base),
Constructor(DOMString url, DOMString base),
- ImplementedAs=DOMURL
+ ImplementedAs=DOMURL,
+ WillBeGarbageCollected
] interface URL {
- [CallWith=ExecutionContext,TreatReturnedNullStringAs=Null] static DOMString createObjectURL(Blob? blob);
+ [RaisesException, CallWith=ExecutionContext,TreatReturnedNullStringAs=Null] static DOMString createObjectURL(Blob? blob);
[CallWith=ExecutionContext] static void revokeObjectURL(DOMString url);
};
diff --git a/Source/core/dom/VisitedLinkState.cpp b/Source/core/dom/VisitedLinkState.cpp
index d134243..1973511 100644
--- a/Source/core/dom/VisitedLinkState.cpp
+++ b/Source/core/dom/VisitedLinkState.cpp
@@ -49,7 +49,7 @@
static inline LinkHash linkHashForElement(const Element& element, const AtomicString& attribute = AtomicString())
{
ASSERT(attribute.isNull() || linkAttribute(element) == attribute);
- if (element.hasTagName(HTMLNames::aTag))
+ if (isHTMLAnchorElement(element))
return toHTMLAnchorElement(element).visitedLinkHash();
return visitedLinkHash(element.document().baseURL(), attribute.isNull() ? linkAttribute(element) : attribute);
}
diff --git a/Source/core/dom/WheelController.cpp b/Source/core/dom/WheelController.cpp
index 68d5b18..b241ad5 100644
--- a/Source/core/dom/WheelController.cpp
+++ b/Source/core/dom/WheelController.cpp
@@ -29,14 +29,14 @@
#include "core/dom/Document.h"
#include "core/events/ThreadLocalEventNames.h"
#include "core/events/WheelEvent.h"
-#include "core/frame/Frame.h"
+#include "core/frame/LocalFrame.h"
#include "core/page/Page.h"
#include "core/page/scrolling/ScrollingCoordinator.h"
namespace WebCore {
-WheelController::WheelController(Document* document)
- : DOMWindowLifecycleObserver(document->domWindow())
+WheelController::WheelController(Document& document)
+ : DOMWindowLifecycleObserver(document.domWindow())
, m_wheelEventHandlerCount(0)
{
}
@@ -50,7 +50,7 @@
return "WheelController";
}
-WheelController* WheelController::from(Document* document)
+WheelController* WheelController::from(Document& document)
{
WheelController* controller = static_cast<WheelController*>(DocumentSupplement::from(document, supplementName()));
if (!controller) {
@@ -60,9 +60,9 @@
return controller;
}
-static void wheelEventHandlerCountChanged(Document* document)
+static void wheelEventHandlerCountChanged(Document& document)
{
- Page* page = document->page();
+ Page* page = document.page();
if (!page)
return;
@@ -70,30 +70,30 @@
if (!scrollingCoordinator)
return;
- FrameView* frameView = document->view();
+ FrameView* frameView = document.view();
if (!frameView)
return;
scrollingCoordinator->frameViewWheelEventHandlerCountChanged(frameView);
}
-void WheelController::didAddWheelEventHandler(Document* document)
+void WheelController::didAddWheelEventHandler(Document& document)
{
++m_wheelEventHandlerCount;
- Page* page = document->page();
- Frame* mainFrame = page ? page->mainFrame() : 0;
+ Page* page = document.page();
+ LocalFrame* mainFrame = page ? page->mainFrame() : 0;
if (mainFrame)
mainFrame->notifyChromeClientWheelEventHandlerCountChanged();
wheelEventHandlerCountChanged(document);
}
-void WheelController::didRemoveWheelEventHandler(Document* document)
+void WheelController::didRemoveWheelEventHandler(Document& document)
{
ASSERT(m_wheelEventHandlerCount > 0);
--m_wheelEventHandlerCount;
- Page* page = document->page();
- Frame* mainFrame = page ? page->mainFrame() : 0;
+ Page* page = document.page();
+ LocalFrame* mainFrame = page ? page->mainFrame() : 0;
if (mainFrame)
mainFrame->notifyChromeClientWheelEventHandlerCountChanged();
@@ -106,7 +106,8 @@
return;
Document* document = window->document();
- didAddWheelEventHandler(document);
+ ASSERT(document);
+ didAddWheelEventHandler(*document);
}
void WheelController::didRemoveEventListener(DOMWindow* window, const AtomicString& eventType)
@@ -115,7 +116,8 @@
return;
Document* document = window->document();
- didRemoveWheelEventHandler(document);
+ ASSERT(document);
+ didRemoveWheelEventHandler(*document);
}
} // namespace WebCore
diff --git a/Source/core/dom/WheelController.h b/Source/core/dom/WheelController.h
index 5f25f98..49879f4 100644
--- a/Source/core/dom/WheelController.h
+++ b/Source/core/dom/WheelController.h
@@ -41,19 +41,19 @@
virtual ~WheelController();
static const char* supplementName();
- static WheelController* from(Document*);
+ static WheelController* from(Document&);
unsigned wheelEventHandlerCount() { return m_wheelEventHandlerCount; }
- void didAddWheelEventHandler(Document*);
- void didRemoveWheelEventHandler(Document*);
+ void didAddWheelEventHandler(Document&);
+ void didRemoveWheelEventHandler(Document&);
// Inherited from DOMWindowLifecycleObserver
virtual void didAddEventListener(DOMWindow*, const AtomicString&) OVERRIDE;
virtual void didRemoveEventListener(DOMWindow*, const AtomicString&) OVERRIDE;
private:
- explicit WheelController(Document*);
+ explicit WheelController(Document&);
unsigned m_wheelEventHandlerCount;
};
diff --git a/Source/core/dom/custom/CustomElementMicrotaskDispatcher.cpp b/Source/core/dom/custom/CustomElementMicrotaskDispatcher.cpp
index a569ad2..5337da3 100644
--- a/Source/core/dom/custom/CustomElementMicrotaskDispatcher.cpp
+++ b/Source/core/dom/custom/CustomElementMicrotaskDispatcher.cpp
@@ -10,7 +10,7 @@
#include "core/dom/custom/CustomElementCallbackQueue.h"
#include "core/dom/custom/CustomElementMicrotaskImportStep.h"
#include "core/dom/custom/CustomElementScheduler.h"
-#include "core/html/HTMLImport.h"
+#include "core/html/imports/HTMLImport.h"
#include "wtf/MainThread.h"
namespace WebCore {
diff --git a/Source/core/dom/custom/CustomElementScheduler.cpp b/Source/core/dom/custom/CustomElementScheduler.cpp
index f0ba5cf..40f7235 100644
--- a/Source/core/dom/custom/CustomElementScheduler.cpp
+++ b/Source/core/dom/custom/CustomElementScheduler.cpp
@@ -40,7 +40,7 @@
#include "core/dom/custom/CustomElementMicrotaskImportStep.h"
#include "core/dom/custom/CustomElementMicrotaskResolutionStep.h"
#include "core/dom/custom/CustomElementRegistrationContext.h"
-#include "core/html/HTMLImportChild.h"
+#include "core/html/imports/HTMLImportChild.h"
namespace WebCore {
diff --git a/Source/core/dom/shadow/ComposedTreeWalker.cpp b/Source/core/dom/shadow/ComposedTreeWalker.cpp
index 3ffc70c..55390f6 100644
--- a/Source/core/dom/shadow/ComposedTreeWalker.cpp
+++ b/Source/core/dom/shadow/ComposedTreeWalker.cpp
@@ -30,7 +30,7 @@
#include "core/dom/Element.h"
#include "core/dom/shadow/ElementShadow.h"
-#include "core/html/shadow/HTMLShadowElement.h"
+#include "core/html/HTMLShadowElement.h"
namespace WebCore {
@@ -72,7 +72,7 @@
const InsertionPoint* insertionPoint = toInsertionPoint(node);
if (Node* found = traverseDistributedNodes(direction == TraversalDirectionForward ? insertionPoint->first() : insertionPoint->last(), insertionPoint, direction))
return found;
- ASSERT(node->hasTagName(HTMLNames::shadowTag) || (node->hasTagName(HTMLNames::contentTag) && !node->hasChildNodes()));
+ ASSERT(isHTMLShadowElement(node) || (isHTMLContentElement(node) && !node->hasChildren()));
return 0;
}
diff --git a/Source/core/dom/shadow/ElementShadow.cpp b/Source/core/dom/shadow/ElementShadow.cpp
index 17ee8ba..8c94e95 100644
--- a/Source/core/dom/shadow/ElementShadow.cpp
+++ b/Source/core/dom/shadow/ElementShadow.cpp
@@ -33,8 +33,8 @@
#include "core/dom/ElementTraversal.h"
#include "core/dom/NodeTraversal.h"
#include "core/dom/shadow/ContentDistribution.h"
-#include "core/html/shadow/HTMLContentElement.h"
-#include "core/html/shadow/HTMLShadowElement.h"
+#include "core/html/HTMLContentElement.h"
+#include "core/html/HTMLShadowElement.h"
namespace WebCore {
@@ -88,7 +88,7 @@
if (m_distributed[i])
continue;
- if (insertionPoint->hasTagName(HTMLNames::contentTag) && !toHTMLContentElement(insertionPoint)->canSelectNode(m_nodes, i))
+ if (isHTMLContentElement(*insertionPoint) && !toHTMLContentElement(insertionPoint)->canSelectNode(m_nodes, i))
continue;
Node* node = m_nodes[i];
@@ -302,7 +302,7 @@
InsertionPoint* point = insertionPoints[i].get();
if (!point->isActive())
continue;
- if (point->hasTagName(HTMLNames::shadowTag)) {
+ if (isHTMLShadowElement(*point)) {
ASSERT(!shadowInsertionPoint);
shadowInsertionPoint = toHTMLShadowElement(point);
shadowInsertionPoints.append(shadowInsertionPoint);
@@ -358,9 +358,9 @@
for (Element* element = ElementTraversal::firstWithin(root); element; element = ElementTraversal::next(*element, &root)) {
if (ElementShadow* shadow = element->shadow())
m_selectFeatures.add(shadow->ensureSelectFeatureSet());
- if (!element->hasTagName(HTMLNames::contentTag))
+ if (!isHTMLContentElement(*element))
continue;
- const CSSSelectorList& list = toHTMLContentElement(element)->selectorList();
+ const CSSSelectorList& list = toHTMLContentElement(*element).selectorList();
for (const CSSSelector* selector = list.first(); selector; selector = CSSSelectorList::next(*selector)) {
for (const CSSSelector* component = selector; component; component = component->tagHistory())
m_selectFeatures.collectFeaturesFromSelector(*component);
@@ -389,7 +389,7 @@
m_nodeToInsertionPoints.clear();
for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot())
- root->setShadowInsertionPointOfYoungerShadowRoot(0);
+ root->setShadowInsertionPointOfYoungerShadowRoot(nullptr);
}
} // namespace
diff --git a/Source/core/dom/shadow/InsertionPoint.cpp b/Source/core/dom/shadow/InsertionPoint.cpp
index 4099b88..690cb8e 100644
--- a/Source/core/dom/shadow/InsertionPoint.cpp
+++ b/Source/core/dom/shadow/InsertionPoint.cpp
@@ -148,14 +148,14 @@
ShadowRoot* shadowRoot = containingShadowRoot();
if (!shadowRoot)
return false;
- if (!hasTagName(shadowTag) || shadowRoot->descendantShadowElementCount() <= 1)
+ if (!isHTMLShadowElement(*this) || shadowRoot->descendantShadowElementCount() <= 1)
return true;
// Slow path only when there are more than one shadow elements in a shadow tree. That should be a rare case.
const Vector<RefPtr<InsertionPoint> >& insertionPoints = shadowRoot->descendantInsertionPoints();
for (size_t i = 0; i < insertionPoints.size(); ++i) {
InsertionPoint* point = insertionPoints[i].get();
- if (point->hasTagName(shadowTag))
+ if (isHTMLShadowElement(*point))
return point == this;
}
return true;
@@ -163,12 +163,12 @@
bool InsertionPoint::isShadowInsertionPoint() const
{
- return hasTagName(shadowTag) && isActive();
+ return isHTMLShadowElement(*this) && isActive();
}
bool InsertionPoint::isContentInsertionPoint() const
{
- return hasTagName(contentTag) && isActive();
+ return isHTMLContentElement(*this) && isActive();
}
PassRefPtr<NodeList> InsertionPoint::getDistributedNodes()
diff --git a/Source/core/dom/shadow/InsertionPoint.h b/Source/core/dom/shadow/InsertionPoint.h
index 05f2ac9..75cc3c5 100644
--- a/Source/core/dom/shadow/InsertionPoint.h
+++ b/Source/core/dom/shadow/InsertionPoint.h
@@ -87,7 +87,7 @@
typedef Vector<RefPtr<InsertionPoint> > DestinationInsertionPoints;
-DEFINE_NODE_TYPE_CASTS(InsertionPoint, isInsertionPoint());
+DEFINE_ELEMENT_TYPE_CASTS(InsertionPoint, isInsertionPoint());
inline bool isActiveInsertionPoint(const Node& node)
{
diff --git a/Source/core/dom/shadow/ShadowRoot.cpp b/Source/core/dom/shadow/ShadowRoot.cpp
index 80be155..c781db0 100644
--- a/Source/core/dom/shadow/ShadowRoot.cpp
+++ b/Source/core/dom/shadow/ShadowRoot.cpp
@@ -31,13 +31,14 @@
#include "core/css/StyleSheetList.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/ElementTraversal.h"
+#include "core/dom/SiblingRuleHelper.h"
#include "core/dom/StyleEngine.h"
#include "core/dom/Text.h"
#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/InsertionPoint.h"
#include "core/dom/shadow/ShadowRootRareData.h"
#include "core/editing/markup.h"
-#include "core/html/shadow/HTMLShadowElement.h"
+#include "core/html/HTMLShadowElement.h"
#include "public/platform/Platform.h"
namespace WebCore {
@@ -49,12 +50,6 @@
COMPILE_ASSERT(sizeof(ShadowRoot) == sizeof(SameSizeAsShadowRoot), shadowroot_should_stay_small);
-enum ShadowRootUsageOriginType {
- ShadowRootUsageOriginWeb = 0,
- ShadowRootUsageOriginNotWeb,
- ShadowRootUsageOriginMax
-};
-
ShadowRoot::ShadowRoot(Document& document, ShadowRootType type)
: DocumentFragment(0, CreateShadowRoot)
, TreeScope(*this, document)
@@ -68,11 +63,6 @@
, m_descendantInsertionPointsIsValid(false)
{
ScriptWrappable::init(this);
-
- if (type == ShadowRoot::AuthorShadowRoot) {
- ShadowRootUsageOriginType usageType = document.url().protocolIsInHTTPFamily() ? ShadowRootUsageOriginWeb : ShadowRootUsageOriginNotWeb;
- blink::Platform::current()->histogramEnumeration("WebCore.ShadowRoot.constructor", usageType, ShadowRootUsageOriginMax);
- }
}
ShadowRoot::~ShadowRoot()
@@ -128,7 +118,7 @@
PassRefPtr<Node> ShadowRoot::cloneNode(bool, ExceptionState& exceptionState)
{
exceptionState.throwDOMException(DataCloneError, "ShadowRoot nodes are not clonable.");
- return 0;
+ return nullptr;
}
String ShadowRoot::innerHTML() const
@@ -163,6 +153,9 @@
if (styleChangeType() >= SubtreeStyleChange)
change = Force;
+ if (change < Force && childNeedsStyleRecalc())
+ SiblingRuleHelper(this).checkForChildrenAdjacentRuleChanges();
+
// There's no style to update so just calling recalcStyle means we're updated.
clearNeedsStyleRecalc();
@@ -411,4 +404,70 @@
return m_shadowRootRareData->styleSheets();
}
+bool ShadowRoot::childrenSupportStyleSharing() const
+{
+ if (!m_shadowRootRareData)
+ return false;
+ return !m_shadowRootRareData->childrenAffectedByFirstChildRules()
+ && !m_shadowRootRareData->childrenAffectedByLastChildRules()
+ && !m_shadowRootRareData->childrenAffectedByDirectAdjacentRules()
+ && !m_shadowRootRareData->childrenAffectedByForwardPositionalRules()
+ && !m_shadowRootRareData->childrenAffectedByBackwardPositionalRules();
+}
+
+bool ShadowRoot::childrenAffectedByPositionalRules() const
+{
+ return m_shadowRootRareData && (m_shadowRootRareData->childrenAffectedByForwardPositionalRules() || m_shadowRootRareData->childrenAffectedByBackwardPositionalRules());
+}
+
+bool ShadowRoot::childrenAffectedByFirstChildRules() const
+{
+ return m_shadowRootRareData && m_shadowRootRareData->childrenAffectedByFirstChildRules();
+}
+
+bool ShadowRoot::childrenAffectedByLastChildRules() const
+{
+ return m_shadowRootRareData && m_shadowRootRareData->childrenAffectedByLastChildRules();
+}
+
+bool ShadowRoot::childrenAffectedByDirectAdjacentRules() const
+{
+ return m_shadowRootRareData && m_shadowRootRareData->childrenAffectedByDirectAdjacentRules();
+}
+
+bool ShadowRoot::childrenAffectedByForwardPositionalRules() const
+{
+ return m_shadowRootRareData && m_shadowRootRareData->childrenAffectedByForwardPositionalRules();
+}
+
+bool ShadowRoot::childrenAffectedByBackwardPositionalRules() const
+{
+ return m_shadowRootRareData && m_shadowRootRareData->childrenAffectedByBackwardPositionalRules();
+}
+
+void ShadowRoot::setChildrenAffectedByForwardPositionalRules()
+{
+ ensureShadowRootRareData()->setChildrenAffectedByForwardPositionalRules(true);
+}
+
+void ShadowRoot::setChildrenAffectedByDirectAdjacentRules()
+{
+ ensureShadowRootRareData()->setChildrenAffectedByDirectAdjacentRules(true);
+}
+
+void ShadowRoot::setChildrenAffectedByBackwardPositionalRules()
+{
+ ensureShadowRootRareData()->setChildrenAffectedByBackwardPositionalRules(true);
+}
+
+void ShadowRoot::setChildrenAffectedByFirstChildRules()
+{
+ ensureShadowRootRareData()->setChildrenAffectedByFirstChildRules(true);
+}
+
+void ShadowRoot::setChildrenAffectedByLastChildRules()
+{
+ ensureShadowRootRareData()->setChildrenAffectedByLastChildRules(true);
+}
+
}
diff --git a/Source/core/dom/shadow/ShadowRoot.h b/Source/core/dom/shadow/ShadowRoot.h
index 98ca4ce..43091ff 100644
--- a/Source/core/dom/shadow/ShadowRoot.h
+++ b/Source/core/dom/shadow/ShadowRoot.h
@@ -127,6 +127,22 @@
StyleSheetList* styleSheets();
bool isActiveForStyling() const;
+ bool childrenSupportStyleSharing() const;
+ bool childrenAffectedByPositionalRules() const;
+ bool childrenAffectedByFirstChildRules() const;
+ bool childrenAffectedByLastChildRules() const;
+ bool childrenAffectedByDirectAdjacentRules() const;
+ bool childrenAffectedByForwardPositionalRules() const;
+ bool childrenAffectedByBackwardPositionalRules() const;
+
+ void setChildrenAffectedByFirstChildRules();
+ void setChildrenAffectedByLastChildRules();
+ void setChildrenAffectedByDirectAdjacentRules();
+ void setChildrenAffectedByForwardPositionalRules();
+ void setChildrenAffectedByBackwardPositionalRules();
+
+ using Node::isFinishedParsingChildren; // make public for SelectorChecker
+
private:
ShadowRoot(Document&, ShadowRootType);
virtual ~ShadowRoot();
@@ -141,7 +157,7 @@
void invalidateDescendantInsertionPoints();
// ShadowRoots should never be cloned.
- virtual PassRefPtr<Node> cloneNode(bool) OVERRIDE { return 0; }
+ virtual PassRefPtr<Node> cloneNode(bool) OVERRIDE { return nullptr; }
// FIXME: This shouldn't happen. https://bugs.webkit.org/show_bug.cgi?id=88834
bool isOrphan() const { return !host(); }
diff --git a/Source/core/dom/shadow/ShadowRootRareData.h b/Source/core/dom/shadow/ShadowRootRareData.h
index 7ad8ef6..051579a 100644
--- a/Source/core/dom/shadow/ShadowRootRareData.h
+++ b/Source/core/dom/shadow/ShadowRootRareData.h
@@ -43,6 +43,11 @@
: m_descendantShadowElementCount(0)
, m_descendantContentElementCount(0)
, m_childShadowRootCount(0)
+ , m_childrenAffectedByDirectAdjacentRules(false)
+ , m_childrenAffectedByForwardPositionalRules(false)
+ , m_childrenAffectedByBackwardPositionalRules(false)
+ , m_childrenAffectedByFirstChildRules(false)
+ , m_childrenAffectedByLastChildRules(false)
{
}
@@ -68,7 +73,21 @@
void clearDescendantInsertionPoints() { m_descendantInsertionPoints.clear(); }
StyleSheetList* styleSheets() { return m_styleSheetList.get(); }
- void setStyleSheets(PassRefPtr<StyleSheetList> styleSheetList) { m_styleSheetList = styleSheetList; }
+ void setStyleSheets(PassRefPtrWillBeRawPtr<StyleSheetList> styleSheetList) { m_styleSheetList = styleSheetList; }
+
+ bool childrenAffectedByDirectAdjacentRules() const { return m_childrenAffectedByDirectAdjacentRules; }
+ void setChildrenAffectedByDirectAdjacentRules(bool value) { m_childrenAffectedByDirectAdjacentRules = value; }
+ bool childrenAffectedByForwardPositionalRules() const { return m_childrenAffectedByForwardPositionalRules; }
+ void setChildrenAffectedByForwardPositionalRules(bool value) { m_childrenAffectedByForwardPositionalRules = value; }
+
+ bool childrenAffectedByBackwardPositionalRules() const { return m_childrenAffectedByBackwardPositionalRules; }
+ void setChildrenAffectedByBackwardPositionalRules(bool value) { m_childrenAffectedByBackwardPositionalRules = value; }
+
+ bool childrenAffectedByFirstChildRules() const { return m_childrenAffectedByFirstChildRules; }
+ void setChildrenAffectedByFirstChildRules(bool value) { m_childrenAffectedByFirstChildRules = value; }
+
+ bool childrenAffectedByLastChildRules() const { return m_childrenAffectedByLastChildRules; }
+ void setChildrenAffectedByLastChildRules(bool value) { m_childrenAffectedByLastChildRules = value; }
private:
RefPtr<HTMLShadowElement> m_shadowInsertionPointOfYoungerShadowRoot;
@@ -76,14 +95,21 @@
unsigned m_descendantContentElementCount;
unsigned m_childShadowRootCount;
Vector<RefPtr<InsertionPoint> > m_descendantInsertionPoints;
- RefPtr<StyleSheetList> m_styleSheetList;
+ RefPtrWillBePersistent<StyleSheetList> m_styleSheetList;
+
+ unsigned m_childrenAffectedByDirectAdjacentRules : 1;
+ unsigned m_childrenAffectedByForwardPositionalRules : 1;
+ unsigned m_childrenAffectedByBackwardPositionalRules : 1;
+ unsigned m_childrenAffectedByFirstChildRules : 1;
+ unsigned m_childrenAffectedByLastChildRules : 1;
};
inline void ShadowRootRareData::didAddInsertionPoint(InsertionPoint* point)
{
- if (point->hasTagName(HTMLNames::shadowTag))
+ ASSERT(point);
+ if (isHTMLShadowElement(*point))
++m_descendantShadowElementCount;
- else if (point->hasTagName(HTMLNames::contentTag))
+ else if (isHTMLContentElement(*point))
++m_descendantContentElementCount;
else
ASSERT_NOT_REACHED();
@@ -91,9 +117,10 @@
inline void ShadowRootRareData::didRemoveInsertionPoint(InsertionPoint* point)
{
- if (point->hasTagName(HTMLNames::shadowTag))
+ ASSERT(point);
+ if (isHTMLShadowElement(*point))
--m_descendantShadowElementCount;
- else if (point->hasTagName(HTMLNames::contentTag))
+ else if (isHTMLContentElement(*point))
--m_descendantContentElementCount;
else
ASSERT_NOT_REACHED();