summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/dom
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/dom')
-rw-r--r--Source/WebCore/dom/Attr.cpp2
-rw-r--r--Source/WebCore/dom/CharacterData.cpp1
-rw-r--r--Source/WebCore/dom/ContainerNode.cpp47
-rw-r--r--Source/WebCore/dom/ContainerNode.h11
-rw-r--r--Source/WebCore/dom/Document.cpp55
-rw-r--r--Source/WebCore/dom/Document.h33
-rw-r--r--Source/WebCore/dom/DocumentOrderedMap.cpp2
-rw-r--r--Source/WebCore/dom/DynamicNodeList.cpp46
-rw-r--r--Source/WebCore/dom/DynamicNodeList.h8
-rw-r--r--Source/WebCore/dom/Element.cpp22
-rw-r--r--Source/WebCore/dom/Element.h23
-rw-r--r--Source/WebCore/dom/NamedNodeMap.cpp10
-rw-r--r--Source/WebCore/dom/NamedNodeMap.h14
-rw-r--r--Source/WebCore/dom/Node.cpp250
-rw-r--r--Source/WebCore/dom/Node.h84
-rw-r--r--Source/WebCore/dom/NodeRareData.h16
-rw-r--r--Source/WebCore/dom/ProcessingInstruction.cpp5
-rw-r--r--Source/WebCore/dom/RequestAnimationFrameCallback.h4
-rw-r--r--Source/WebCore/dom/ScriptElement.cpp3
-rw-r--r--Source/WebCore/dom/ScriptedAnimationController.cpp78
-rw-r--r--Source/WebCore/dom/ScriptedAnimationController.h15
-rw-r--r--Source/WebCore/dom/SelectorNodeList.cpp16
-rw-r--r--Source/WebCore/dom/TagNodeList.cpp35
-rw-r--r--Source/WebCore/dom/TagNodeList.h49
-rw-r--r--Source/WebCore/dom/Text.cpp2
-rw-r--r--Source/WebCore/dom/Text.h5
-rw-r--r--Source/WebCore/dom/TreeScope.cpp4
27 files changed, 611 insertions, 229 deletions
diff --git a/Source/WebCore/dom/Attr.cpp b/Source/WebCore/dom/Attr.cpp
index e3ae348..346a819 100644
--- a/Source/WebCore/dom/Attr.cpp
+++ b/Source/WebCore/dom/Attr.cpp
@@ -69,6 +69,8 @@ void Attr::createTextChild()
textNode->setParent(this);
setFirstChild(textNode.get());
setLastChild(textNode.get());
+ textNode->updateNextNode();
+ textNode->updatePreviousNode();
}
}
diff --git a/Source/WebCore/dom/CharacterData.cpp b/Source/WebCore/dom/CharacterData.cpp
index b4af02d..78f57d0 100644
--- a/Source/WebCore/dom/CharacterData.cpp
+++ b/Source/WebCore/dom/CharacterData.cpp
@@ -189,6 +189,7 @@ void CharacterData::updateRenderer(unsigned offsetOfReplacedData, unsigned lengt
void CharacterData::dispatchModifiedEvent(StringImpl* oldData)
{
+ updatePrevNextNodesInSubtree();
if (parentNode())
parentNode()->childrenChanged();
if (document()->hasListenerType(Document::DOMCHARACTERDATAMODIFIED_LISTENER))
diff --git a/Source/WebCore/dom/ContainerNode.cpp b/Source/WebCore/dom/ContainerNode.cpp
index 2d22fa9..5574aa5 100644
--- a/Source/WebCore/dom/ContainerNode.cpp
+++ b/Source/WebCore/dom/ContainerNode.cpp
@@ -3,6 +3,7 @@
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2001 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 The Linux Foundation 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
@@ -74,6 +75,7 @@ static void collectTargetNodes(Node* node, NodeVector& nodes)
void ContainerNode::removeAllChildren()
{
removeAllChildrenInContainer<Node, ContainerNode>(this);
+ updateNextNode();
}
void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent)
@@ -208,6 +210,8 @@ void ContainerNode::insertBeforeCommon(Node* nextChild, Node* newChild)
newChild->setParent(this);
newChild->setPreviousSibling(prev);
newChild->setNextSibling(nextChild);
+ newChild->updatePreviousNode();
+ newChild->lastDescendantNode(true)->updateNextNode();
allowEventDispatch();
}
@@ -335,6 +339,9 @@ bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce
child->setParent(this);
child->setPreviousSibling(prev.get());
child->setNextSibling(next);
+ child->updatePreviousNode();
+ child->lastDescendantNode(true)->updateNextNode();
+
allowEventDispatch();
childrenChanged(false, prev.get(), next, 1);
@@ -362,12 +369,13 @@ bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce
void ContainerNode::willRemove()
{
- Vector<RefPtr<Node>, 10> nodes;
- nodes.reserveInitialCapacity(childNodeCount());
- for (Node* n = m_lastChild; n; n = n->previousSibling())
- nodes.append(n);
- for (; nodes.size(); nodes.removeLast())
- nodes.last().get()->willRemove();
+ Node* next;
+ Node* child = m_firstChild;
+ while (child) {
+ next = child->nextSibling();
+ child->willRemove();
+ child = next;
+ }
Node::willRemove();
}
@@ -468,6 +476,8 @@ void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node* ol
if (oldChild->attached())
oldChild->detach();
+ Node* previousNode = oldChild->traversePreviousNodeFastPath();
+
if (nextChild)
nextChild->setPreviousSibling(previousChild);
if (previousChild)
@@ -480,6 +490,10 @@ void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node* ol
oldChild->setPreviousSibling(0);
oldChild->setNextSibling(0);
oldChild->setParent(0);
+ oldChild->setPreviousNode(0);
+ oldChild->lastDescendantNode(true)->setNextNode(0);
+ if (previousNode)
+ previousNode->updateNextNode();
allowEventDispatch();
}
@@ -530,6 +544,8 @@ void ContainerNode::removeChildren()
n->setPreviousSibling(0);
n->setNextSibling(0);
n->setParent(0);
+ n->lastDescendantNode(true)->setNextNode(0);
+ n->setPreviousNode(0);
m_firstChild = next;
if (n == m_lastChild)
@@ -552,6 +568,7 @@ void ContainerNode::removeChildren()
removedChild->detach();
}
+ updateNextNode();
allowEventDispatch();
// Dispatch a single post-removal mutation event denoting a modified subtree.
@@ -621,6 +638,8 @@ bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bo
} else
m_firstChild = child;
m_lastChild = child;
+ child->updatePreviousNode();
+ child->lastDescendantNode(true)->updateNextNode();
allowEventDispatch();
// Send notification about the children change.
@@ -658,6 +677,10 @@ void ContainerNode::parserAddChild(PassRefPtr<Node> newChild)
Node* last = m_lastChild;
// FIXME: This method should take a PassRefPtr.
appendChildToContainer<Node, ContainerNode>(newChild.get(), this);
+ if (last)
+ last->updateNextNode();
+ newChild->updatePreviousNode();
+ newChild->lastDescendantNode(true)->updateNextNode();
allowEventDispatch();
// FIXME: Why doesn't this use notifyChildInserted(newChild) instead?
@@ -1070,8 +1093,12 @@ static void dispatchChildInsertionEvents(Node* child)
// dispatch the DOMNodeInsertedIntoDocument event to all descendants
if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) {
- for (; c; c = c->traverseNextNode(child))
+ Node* last = child->lastDescendantNode(true);
+ for (; c; c = c->traverseNextNodeFastPath()) {
c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false));
+ if (last == c)
+ break;
+ }
}
}
@@ -1092,8 +1119,12 @@ static void dispatchChildRemovalEvents(Node* child)
// dispatch the DOMNodeRemovedFromDocument event to all descendants
if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) {
- for (; c; c = c->traverseNextNode(child))
+ Node* last = c->lastDescendantNode(true);
+ for (; c; c = c->traverseNextNodeFastPath()) {
c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false));
+ if (last == c)
+ break;
+ }
}
}
diff --git a/Source/WebCore/dom/ContainerNode.h b/Source/WebCore/dom/ContainerNode.h
index 76eb1bd..ee8252e 100644
--- a/Source/WebCore/dom/ContainerNode.h
+++ b/Source/WebCore/dom/ContainerNode.h
@@ -170,6 +170,17 @@ inline Node* Node::lastChild() const
return toContainerNode(this)->lastChild();
}
+inline RenderObject* Node::previousRenderer()
+{
+ // FIXME: We should have the same O(N^2) avoidance as nextRenderer does
+ // however, when I tried adding it, several tests failed.
+ for (Node* n = previousSibling(); n; n = n->previousSibling()) {
+ if (n->renderer())
+ return n->renderer();
+ }
+ return 0;
+}
+
} // namespace WebCore
#endif // ContainerNode_h
diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp
index 063b8a2..f319cac 100644
--- a/Source/WebCore/dom/Document.cpp
+++ b/Source/WebCore/dom/Document.cpp
@@ -7,6 +7,9 @@
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
* Copyright (C) 2008, 2009 Google Inc. All rights reserved.
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (c) 2011, 2012 The Linux Foundation All rights reserved
+ * Copyright (C) 2011, 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communcations AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -107,6 +110,7 @@
#include "NestingLevelIncrementer.h"
#include "NodeFilter.h"
#include "NodeIterator.h"
+#include "NodeRareData.h"
#include "NodeWithIndex.h"
#include "OverflowEvent.h"
#include "Page.h"
@@ -421,9 +425,13 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
, m_sawElementsInKnownNamespaces(false)
, m_usingGeolocation(false)
, m_eventQueue(EventQueue::create(this))
+ , m_documentRareData(0)
#if ENABLE(WML)
, m_containsWMLContent(false)
#endif
+#if ENABLE(WEBGL) && PLATFORM(ANDROID)
+ , m_containsWebGLContent(false)
+#endif
, m_weakReference(DocumentWeakReference::create(this))
, m_idAttributeName(idAttr)
#if ENABLE(FULLSCREEN_API)
@@ -567,6 +575,13 @@ Document::~Document()
if (m_implementation)
m_implementation->ownerDocumentDestroyed();
+
+ if (hasRareData()) {
+ ASSERT(m_documentRareData);
+ delete m_documentRareData;
+ m_documentRareData = 0;
+ clearFlag(HasRareDataFlag);
+ }
}
void Document::removedLastRef()
@@ -1810,7 +1825,7 @@ void Document::removeAllEventListeners()
if (DOMWindow* domWindow = this->domWindow())
domWindow->removeAllEventListeners();
- for (Node* node = firstChild(); node; node = node->traverseNextNode())
+ for (Node* node = firstChild(); node; node = node->traverseNextNodeFastPath())
node->removeAllEventListeners();
}
@@ -3842,11 +3857,12 @@ static inline bool isValidNameASCII(const UChar* characters, unsigned length)
bool Document::isValidName(const String& name)
{
- unsigned length = name.length();
- if (!length)
+ if (name.isEmpty())
return false;
- const UChar* characters = name.characters();
+ StringImpl* impl = name.impl();
+ const UChar* characters = impl->characters();
+ unsigned length = impl->length();
return isValidNameASCII(characters, length) || isValidNameNonASCII(characters, length);
}
@@ -5026,15 +5042,15 @@ void Document::loadEventDelayTimerFired(Timer<Document>*)
}
#if ENABLE(REQUEST_ANIMATION_FRAME)
-int Document::webkitRequestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback> callback, Element* animationElement)
+int Document::webkitRequestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback> callback)
{
if (!m_scriptedAnimationController)
m_scriptedAnimationController = ScriptedAnimationController::create(this);
- return m_scriptedAnimationController->registerCallback(callback, animationElement);
+ return m_scriptedAnimationController->registerCallback(callback);
}
-void Document::webkitCancelRequestAnimationFrame(int id)
+void Document::webkitCancelAnimationFrame(int id)
{
if (!m_scriptedAnimationController)
return;
@@ -5082,4 +5098,29 @@ DocumentLoader* Document::loader() const
return loader;
}
+#if ENABLE(WEBGL) && PLATFORM(ANDROID)
+void Document::suspendDocument()
+{
+ HashSet<Element*>::iterator end = m_documentSuspendCallbackElements.end();
+ for (HashSet<Element*>::iterator i = m_documentSuspendCallbackElements.begin(); i != end; ++i)
+ (*i)->documentWasSuspended();
+}
+
+void Document::resumeDocument()
+{
+ HashSet<Element*>::iterator end = m_documentSuspendCallbackElements.end();
+ for (HashSet<Element*>::iterator i = m_documentSuspendCallbackElements.begin(); i != end; ++i)
+ (*i)->documentWillResume();
+}
+
+void Document::registerForDocumentSuspendCallbacks(Element* e)
+{
+ m_documentSuspendCallbackElements.add(e);
+}
+
+void Document::unregisterForDocumentSuspendCallbacks(Element* e)
+{
+ m_documentSuspendCallbackElements.remove(e);
+}
+#endif
} // namespace WebCore
diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h
index c4ccb9c..a51861b 100644
--- a/Source/WebCore/dom/Document.h
+++ b/Source/WebCore/dom/Document.h
@@ -6,6 +6,9 @@
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (c) 2011, 2012 The Linux Foundation All rights reserved
+ * Copyright (C) 2011, 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communcations AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -101,6 +104,7 @@ class MediaQueryMatcher;
class MouseEventWithHitTestResults;
class NodeFilter;
class NodeIterator;
+class NodeRareData;
class Page;
class PlatformMouseEvent;
class ProcessingInstruction;
@@ -1035,6 +1039,15 @@ public:
void initializeWMLPageState();
#endif
+#if ENABLE(WEBGL) && PLATFORM(ANDROID)
+ void setContainsWebGLContent(bool value) { m_containsWebGLContent = value; }
+ bool containsWebGLContent() const { return m_containsWebGLContent; }
+ void suspendDocument();
+ void resumeDocument();
+ void registerForDocumentSuspendCallbacks(Element*);
+ void unregisterForDocumentSuspendCallbacks(Element*);
+#endif
+
bool containsValidityStyleRules() const { return m_containsValidityStyleRules; }
void setContainsValidityStyleRules() { m_containsValidityStyleRules = true; }
@@ -1085,8 +1098,8 @@ public:
const DocumentTiming* timing() const { return &m_documentTiming; }
#if ENABLE(REQUEST_ANIMATION_FRAME)
- int webkitRequestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback>, Element*);
- void webkitCancelRequestAnimationFrame(int id);
+ int webkitRequestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback>);
+ void webkitCancelAnimationFrame(int id);
void serviceScriptedAnimations(DOMTimeStamp);
#endif
@@ -1097,12 +1110,14 @@ public:
ContentSecurityPolicy* contentSecurityPolicy() { return m_contentSecurityPolicy.get(); }
+ NodeRareData* documentRareData() const { return m_documentRareData; };
+ void setDocumentRareData(NodeRareData* rareData) { m_documentRareData = rareData; }
+
protected:
Document(Frame*, const KURL&, bool isXHTML, bool isHTML);
void clearXMLVersion() { m_xmlVersion = String(); }
-
private:
friend class IgnoreDestructiveWriteCountIncrementer;
@@ -1364,10 +1379,17 @@ private:
RefPtr<EventQueue> m_eventQueue;
+ NodeRareData* m_documentRareData;
+
#if ENABLE(WML)
bool m_containsWMLContent;
#endif
+#if ENABLE(WEBGL) && PLATFORM(ANDROID)
+ bool m_containsWebGLContent;
+ HashSet<Element*> m_documentSuspendCallbackElements;
+#endif
+
RefPtr<DocumentWeakReference> m_weakReference;
HashSet<MediaCanStartListener*> m_mediaCanStartListeners;
@@ -1412,8 +1434,13 @@ inline Node::Node(Document* document, ConstructionType type)
: m_document(document)
, m_previous(0)
, m_next(0)
+#ifdef __ARM_USE_PLD
+ , m_prefetch(0)
+#endif
, m_renderer(0)
, m_nodeFlags(type)
+ , m_previousNode(0)
+ , m_nextNode(0)
{
if (m_document)
m_document->guardRef();
diff --git a/Source/WebCore/dom/DocumentOrderedMap.cpp b/Source/WebCore/dom/DocumentOrderedMap.cpp
index 47268c4..73a0843 100644
--- a/Source/WebCore/dom/DocumentOrderedMap.cpp
+++ b/Source/WebCore/dom/DocumentOrderedMap.cpp
@@ -117,7 +117,7 @@ inline Element* DocumentOrderedMap::get(AtomicStringImpl* key, const TreeScope*
if (m_duplicateCounts.contains(key)) {
// We know there's at least one node that matches; iterate to find the first one.
- for (Node* node = scope->firstChild(); node; node = node->traverseNextNode()) {
+ for (Node* node = scope->firstChild(); node; node = node->traverseNextNodeFastPath()) {
if (!node->isElementNode())
continue;
element = static_cast<Element*>(node);
diff --git a/Source/WebCore/dom/DynamicNodeList.cpp b/Source/WebCore/dom/DynamicNodeList.cpp
index 23664e8..bba1678 100644
--- a/Source/WebCore/dom/DynamicNodeList.cpp
+++ b/Source/WebCore/dom/DynamicNodeList.cpp
@@ -3,6 +3,7 @@
* (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) 2012 The Linux Foundation 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
@@ -56,8 +57,18 @@ unsigned DynamicNodeList::length() const
unsigned length = 0;
- for (Node* n = m_rootNode->firstChild(); n; n = n->traverseNextNode(m_rootNode.get()))
- length += n->isElementNode() && nodeMatches(static_cast<Element*>(n));
+ Node* lastNode = m_rootNode->lastDescendantNode();
+ Vector<Node* >& cachedNodes = m_caches->cachedNodes;
+ for (Node* n = m_rootNode->firstChild(); n; n = n->traverseNextNodeFastPath()) {
+ if (n->isElementNode() && nodeMatches(static_cast<Element*>(n))) {
+ if (length >= cachedNodes.size())
+ cachedNodes.resize(length + 1);
+ cachedNodes.data()[length] = n;
+ length ++;
+ }
+ if (n == lastNode)
+ break;
+ }
m_caches->cachedLength = length;
m_caches->isLengthCacheValid = true;
@@ -68,7 +79,9 @@ unsigned DynamicNodeList::length() const
Node* DynamicNodeList::itemForwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const
{
ASSERT(remainingOffset >= 0);
- for (Node* n = start; n; n = n->traverseNextNode(m_rootNode.get())) {
+ if (!m_caches->lastDecendantOfRoot)
+ m_caches->lastDecendantOfRoot = m_rootNode->lastDescendantNode();
+ for (Node* n = start; n; n = n->traverseNextNodeFastPath()) {
if (n->isElementNode() && nodeMatches(static_cast<Element*>(n))) {
if (!remainingOffset) {
m_caches->lastItem = n;
@@ -78,6 +91,8 @@ Node* DynamicNodeList::itemForwardsFromCurrent(Node* start, unsigned offset, int
}
--remainingOffset;
}
+ if (n == m_caches->lastDecendantOfRoot)
+ break;
}
return 0; // no matching node in this subtree
@@ -103,6 +118,14 @@ Node* DynamicNodeList::itemBackwardsFromCurrent(Node* start, unsigned offset, in
Node* DynamicNodeList::item(unsigned offset) const
{
+ Node* result;
+ Vector<Node* >& cachedNodes = m_caches->cachedNodes;
+ if (offset < cachedNodes.size()) {
+ result = cachedNodes[offset];
+ if (result)
+ return result;
+ }
+
int remainingOffset = offset;
Node* start = m_rootNode->firstChild();
if (m_caches->isItemCacheValid) {
@@ -115,8 +138,16 @@ Node* DynamicNodeList::item(unsigned offset) const
}
if (remainingOffset < 0)
- return itemBackwardsFromCurrent(start, offset, remainingOffset);
- return itemForwardsFromCurrent(start, offset, remainingOffset);
+ result = itemBackwardsFromCurrent(start, offset, remainingOffset);
+ else
+ result = itemForwardsFromCurrent(start, offset, remainingOffset);
+
+ if (result) {
+ if (offset >= cachedNodes.size())
+ cachedNodes.resize(offset + 1);
+ cachedNodes.data()[offset] = result;
+ }
+ return result;
}
Node* DynamicNodeList::itemWithName(const AtomicString& elementId) const
@@ -159,6 +190,7 @@ void DynamicNodeList::invalidateCache()
DynamicNodeList::Caches::Caches()
: lastItem(0)
+ , lastDecendantOfRoot(0)
, isLengthCacheValid(false)
, isItemCacheValid(false)
{
@@ -172,8 +204,10 @@ PassRefPtr<DynamicNodeList::Caches> DynamicNodeList::Caches::create()
void DynamicNodeList::Caches::reset()
{
lastItem = 0;
+ lastDecendantOfRoot = 0;
isLengthCacheValid = false;
- isItemCacheValid = false;
+ isItemCacheValid = false;
+ cachedNodes.clear();
}
} // namespace WebCore
diff --git a/Source/WebCore/dom/DynamicNodeList.h b/Source/WebCore/dom/DynamicNodeList.h
index 9c8f3cc..c8b6ca2 100644
--- a/Source/WebCore/dom/DynamicNodeList.h
+++ b/Source/WebCore/dom/DynamicNodeList.h
@@ -28,6 +28,12 @@
#include <wtf/RefCounted.h>
#include <wtf/Forward.h>
#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WTF {
+ // Properties in Vector can be initialized with memset and moved using memcpy.
+ template<> struct VectorTraits<WebCore::Node*> : SimpleClassVectorTraits { };
+}
namespace WebCore {
@@ -42,9 +48,11 @@ namespace WebCore {
unsigned cachedLength;
Node* lastItem;
+ Node* lastDecendantOfRoot;
unsigned lastItemOffset;
bool isLengthCacheValid : 1;
bool isItemCacheValid : 1;
+ Vector<Node* > cachedNodes;
protected:
Caches();
};
diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp
index 5fb6cdc..4b9de49 100644
--- a/Source/WebCore/dom/Element.cpp
+++ b/Source/WebCore/dom/Element.cpp
@@ -622,7 +622,7 @@ static inline bool shouldIgnoreAttributeCase(const Element* e)
return e && e->document()->isHTMLDocument() && e->isHTMLElement();
}
-const AtomicString& Element::getAttribute(const String& name) const
+const AtomicString& Element::getAttribute(const AtomicString& name) const
{
bool ignoreCase = shouldIgnoreAttributeCase(this);
@@ -645,7 +645,7 @@ const AtomicString& Element::getAttribute(const String& name) const
return nullAtom;
}
-const AtomicString& Element::getAttributeNS(const String& namespaceURI, const String& localName) const
+const AtomicString& Element::getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const
{
return getAttribute(QualifiedName(nullAtom, localName, namespaceURI));
}
@@ -1471,11 +1471,11 @@ void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicStrin
setAttribute(qName, value, ec);
}
-void Element::removeAttribute(const String& name, ExceptionCode& ec)
+void Element::removeAttribute(const AtomicString& name, ExceptionCode& ec)
{
InspectorInstrumentation::willModifyDOMAttr(document(), this);
- String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
+ AtomicString localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
if (m_attributeMap) {
m_attributeMap->removeNamedItem(localName, ec);
@@ -1486,21 +1486,21 @@ void Element::removeAttribute(const String& name, ExceptionCode& ec)
InspectorInstrumentation::didModifyDOMAttr(document(), this);
}
-void Element::removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode& ec)
+void Element::removeAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName, ExceptionCode& ec)
{
removeAttribute(QualifiedName(nullAtom, localName, namespaceURI), ec);
}
-PassRefPtr<Attr> Element::getAttributeNode(const String& name)
+PassRefPtr<Attr> Element::getAttributeNode(const AtomicString& name)
{
NamedNodeMap* attrs = attributes(true);
if (!attrs)
return 0;
- String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
+ AtomicString localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
return static_pointer_cast<Attr>(attrs->getNamedItem(localName));
}
-PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
+PassRefPtr<Attr> Element::getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName)
{
NamedNodeMap* attrs = attributes(true);
if (!attrs)
@@ -1508,7 +1508,7 @@ PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const S
return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName, namespaceURI)));
}
-bool Element::hasAttribute(const String& name) const
+bool Element::hasAttribute(const AtomicString& name) const
{
NamedNodeMap* attrs = attributes(true);
if (!attrs)
@@ -1516,11 +1516,11 @@ bool Element::hasAttribute(const String& name) const
// This call to String::lower() seems to be required but
// there may be a way to remove it.
- String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
+ AtomicString localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
return attrs->getAttributeItem(localName, false);
}
-bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
+bool Element::hasAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const
{
NamedNodeMap* attrs = attributes(true);
if (!attrs)
diff --git a/Source/WebCore/dom/Element.h b/Source/WebCore/dom/Element.h
index d269dbe..79815dd 100644
--- a/Source/WebCore/dom/Element.h
+++ b/Source/WebCore/dom/Element.h
@@ -4,6 +4,8 @@
* (C) 2001 Peter Kelly (pmk@post.com)
* (C) 2001 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Sony Ericsson Mobile Communications AB
+ * Copyright (C) 2012 Sony Mobile Communications AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -126,11 +128,11 @@ public:
bool hasAttributes() const;
- bool hasAttribute(const String& name) const;
- bool hasAttributeNS(const String& namespaceURI, const String& localName) const;
+ bool hasAttribute(const AtomicString& name) const;
+ bool hasAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const;
- const AtomicString& getAttribute(const String& name) const;
- const AtomicString& getAttributeNS(const String& namespaceURI, const String& localName) const;
+ const AtomicString& getAttribute(const AtomicString& name) const;
+ const AtomicString& getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const;
void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&, FragmentScriptingPermission = FragmentScriptingAllowed);
@@ -174,11 +176,11 @@ public:
// Returns the absolute bounding box translated into screen coordinates:
IntRect screenRect() const;
- void removeAttribute(const String& name, ExceptionCode&);
- void removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode&);
+ void removeAttribute(const AtomicString& name, ExceptionCode&);
+ void removeAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName, ExceptionCode&);
- PassRefPtr<Attr> getAttributeNode(const String& name);
- PassRefPtr<Attr> getAttributeNodeNS(const String& namespaceURI, const String& localName);
+ PassRefPtr<Attr> getAttributeNode(const AtomicString& name);
+ PassRefPtr<Attr> getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName);
PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&);
PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&);
PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&);
@@ -351,6 +353,11 @@ public:
PassRefPtr<WebKitAnimationList> webkitGetAnimations() const;
+#if ENABLE(WEBGL) && PLATFORM(ANDROID)
+ virtual void documentWasSuspended() {}
+ virtual void documentWillResume() {}
+#endif
+
protected:
Element(const QualifiedName& tagName, Document* document, ConstructionType type)
: ContainerNode(document, type)
diff --git a/Source/WebCore/dom/NamedNodeMap.cpp b/Source/WebCore/dom/NamedNodeMap.cpp
index 6fa30bf..253bc53 100644
--- a/Source/WebCore/dom/NamedNodeMap.cpp
+++ b/Source/WebCore/dom/NamedNodeMap.cpp
@@ -54,7 +54,7 @@ NamedNodeMap::~NamedNodeMap()
detachAttributesFromElement();
}
-PassRefPtr<Node> NamedNodeMap::getNamedItem(const String& name) const
+PassRefPtr<Node> NamedNodeMap::getNamedItem(const AtomicString& name) const
{
Attribute* a = getAttributeItem(name, shouldIgnoreAttributeCase(m_element));
if (!a)
@@ -63,12 +63,12 @@ PassRefPtr<Node> NamedNodeMap::getNamedItem(const String& name) const
return a->createAttrIfNeeded(m_element);
}
-PassRefPtr<Node> NamedNodeMap::getNamedItemNS(const String& namespaceURI, const String& localName) const
+PassRefPtr<Node> NamedNodeMap::getNamedItemNS(const AtomicString& namespaceURI, const AtomicString& localName) const
{
return getNamedItem(QualifiedName(nullAtom, localName, namespaceURI));
}
-PassRefPtr<Node> NamedNodeMap::removeNamedItem(const String& name, ExceptionCode& ec)
+PassRefPtr<Node> NamedNodeMap::removeNamedItem(const AtomicString& name, ExceptionCode& ec)
{
Attribute* a = getAttributeItem(name, shouldIgnoreAttributeCase(m_element));
if (!a) {
@@ -79,7 +79,7 @@ PassRefPtr<Node> NamedNodeMap::removeNamedItem(const String& name, ExceptionCode
return removeNamedItem(a->name(), ec);
}
-PassRefPtr<Node> NamedNodeMap::removeNamedItemNS(const String& namespaceURI, const String& localName, ExceptionCode& ec)
+PassRefPtr<Node> NamedNodeMap::removeNamedItemNS(const AtomicString& namespaceURI, const AtomicString& localName, ExceptionCode& ec)
{
return removeNamedItem(QualifiedName(nullAtom, localName, namespaceURI), ec);
}
@@ -171,7 +171,7 @@ void NamedNodeMap::copyAttributesToVector(Vector<RefPtr<Attribute> >& copy)
copy = m_attributes;
}
-Attribute* NamedNodeMap::getAttributeItemSlowCase(const String& name, bool shouldIgnoreAttributeCase) const
+Attribute* NamedNodeMap::getAttributeItemSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const
{
unsigned len = length();
diff --git a/Source/WebCore/dom/NamedNodeMap.h b/Source/WebCore/dom/NamedNodeMap.h
index c3c2cd9..f4aedb0 100644
--- a/Source/WebCore/dom/NamedNodeMap.h
+++ b/Source/WebCore/dom/NamedNodeMap.h
@@ -46,11 +46,11 @@ public:
// Public DOM interface.
- PassRefPtr<Node> getNamedItem(const String& name) const;
- PassRefPtr<Node> removeNamedItem(const String& name, ExceptionCode&);
+ PassRefPtr<Node> getNamedItem(const AtomicString& name) const;
+ PassRefPtr<Node> removeNamedItem(const AtomicString& name, ExceptionCode&);
- PassRefPtr<Node> getNamedItemNS(const String& namespaceURI, const String& localName) const;
- PassRefPtr<Node> removeNamedItemNS(const String& namespaceURI, const String& localName, ExceptionCode&);
+ PassRefPtr<Node> getNamedItemNS(const AtomicString& namespaceURI, const AtomicString& localName) const;
+ PassRefPtr<Node> removeNamedItemNS(const AtomicString& namespaceURI, const AtomicString& localName, ExceptionCode&);
PassRefPtr<Node> getNamedItem(const QualifiedName& name) const;
PassRefPtr<Node> removeNamedItem(const QualifiedName& name, ExceptionCode&);
@@ -111,8 +111,8 @@ private:
void detachAttributesFromElement();
void detachFromElement();
- Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const;
- Attribute* getAttributeItemSlowCase(const String& name, bool shouldIgnoreAttributeCase) const;
+ Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
+ Attribute* getAttributeItemSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
void clearAttributes();
int declCount() const;
@@ -135,7 +135,7 @@ inline Attribute* NamedNodeMap::getAttributeItem(const QualifiedName& name) cons
// We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller
// can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not).
-inline Attribute* NamedNodeMap::getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const
+inline Attribute* NamedNodeMap::getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const
{
unsigned len = length();
bool doSlowCheck = shouldIgnoreAttributeCase;
diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp
index da4312c..facb694 100644
--- a/Source/WebCore/dom/Node.cpp
+++ b/Source/WebCore/dom/Node.cpp
@@ -5,6 +5,7 @@
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
* Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2012 The Linux Foundation 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
@@ -130,6 +131,8 @@ namespace WebCore {
using namespace HTMLNames;
+const int Node::cPrefetchTargetDepth = 7;
+
bool Node::isSupported(const String& feature, const String& version)
{
return DOMImplementation::hasFeature(feature, version);
@@ -391,7 +394,7 @@ Node::~Node()
else {
if (m_document && rareData()->nodeLists())
m_document->removeNodeListCache();
-
+
NodeRareData::NodeRareDataMap& dataMap = NodeRareData::rareDataMap();
NodeRareData::NodeRareDataMap::iterator it = dataMap.find(this);
ASSERT(it != dataMap.end());
@@ -409,6 +412,8 @@ Node::~Node()
m_previous->setNextSibling(0);
if (m_next)
m_next->setPreviousSibling(0);
+ m_nextNode = 0;
+ m_previousNode = 0;
if (m_document)
m_document->guardDeref();
@@ -517,16 +522,21 @@ void Node::setTreeScopeRecursively(TreeScope* newTreeScope)
if (currentDocument && currentDocument != newDocument)
currentDocument->incDOMTreeVersion();
- for (Node* node = this; node; node = node->traverseNextNode(this)) {
+ Node* last = this->lastDescendantNode(true);
+ for (Node* node = this; node; node = node->traverseNextNodeFastPath()) {
node->setTreeScope(newTreeScope);
// FIXME: Once shadow scopes are landed, update parent scope, etc.
+ if (last == node)
+ break;
}
}
NodeRareData* Node::rareData() const
{
ASSERT(hasRareData());
- return NodeRareData::rareDataFromMap(this);
+ NodeRareData* data = isDocumentNode() ? static_cast<const Document*>(this)->documentRareData() : NodeRareData::rareDataFromMap(this);
+ ASSERT(data);
+ return data;
}
NodeRareData* Node::ensureRareData()
@@ -534,9 +544,15 @@ NodeRareData* Node::ensureRareData()
if (hasRareData())
return rareData();
- ASSERT(!NodeRareData::rareDataMap().contains(this));
NodeRareData* data = createRareData();
- NodeRareData::rareDataMap().set(this, data);
+ if (isDocumentNode()) {
+ // Fast path for a Document. A Document knows a pointer to NodeRareData.
+ ASSERT(!static_cast<Document*>(this)->documentRareData());
+ static_cast<Document*>(this)->setDocumentRareData(data);
+ } else {
+ ASSERT(!NodeRareData::rareDataMap().contains(this));
+ NodeRareData::rareDataMap().set(this, data);
+ }
setFlag(HasRareDataFlag);
return data;
}
@@ -548,18 +564,22 @@ NodeRareData* Node::createRareData()
Element* Node::shadowHost() const
{
- return toElement(getFlag(IsShadowRootFlag) ? parent() : 0);
+ return toElement(isShadowRoot() ? parent() : 0);
}
void Node::setShadowHost(Element* host)
{
ASSERT(!parentNode() && !isSVGShadowRoot());
if (host)
- setFlag(IsShadowRootFlag);
+ setFlag(IsShadowRootOrSVGShadowRootFlag);
else
- clearFlag(IsShadowRootFlag);
+ clearFlag(IsShadowRootOrSVGShadowRootFlag);
setParent(host);
+ updatePreviousNode();
+ lastDescendantNode(true)->updateNextNode();
+ if (host)
+ host->updateNextNode();
}
InputElement* Node::toInputElement()
@@ -607,14 +627,9 @@ void Node::setNodeValue(const String& /*nodeValue*/, ExceptionCode& ec)
PassRefPtr<NodeList> Node::childNodes()
{
- NodeRareData* data = ensureRareData();
- if (!data->nodeLists()) {
- data->setNodeLists(NodeListsNodeData::create());
- if (document())
- document()->addNodeListCache();
- }
+ NodeListsNodeData* data = ensureRareData()->ensureNodeLists(this);
- return ChildNodeList::create(this, data->nodeLists()->m_childNodeListCaches.get());
+ return ChildNodeList::create(this, data->m_childNodeListCaches.get());
}
Node *Node::lastDescendant() const
@@ -862,12 +877,15 @@ void Node::setDocumentRecursively(Document* newDocument)
{
ASSERT(document() != newDocument);
- for (Node* node = this; node; node = node->traverseNextNode(this)) {
+ Node* last = this->lastDescendantNode(true);
+ for (Node* node = this; node; node = node->traverseNextNodeFastPath()) {
node->setDocument(newDocument);
- if (!node->isElementNode())
- continue;
- if (Node* shadow = shadowRoot(node))
- shadow->setDocumentRecursively(newDocument);
+ if (node->isElementNode()) {
+ if (Node* shadow = shadowRoot(node))
+ shadow->setDocumentRecursively(newDocument);
+ }
+ if (node == last)
+ break;
}
}
@@ -911,12 +929,15 @@ void Node::setNeedsStyleRecalc(StyleChangeType changeType)
void Node::lazyAttach(ShouldSetAttached shouldSetAttached)
{
- for (Node* n = this; n; n = n->traverseNextNode(this)) {
+ Node* last = this->lastDescendantNode(true);
+ for (Node* n = this; n; n = n->traverseNextNodeFastPath()) {
if (n->firstChild())
n->setChildNeedsStyleRecalc();
n->setStyleChange(FullStyleChange);
if (shouldSetAttached == SetAttached)
n->setAttached();
+ if (n == last)
+ break;
}
markAncestorsWithChildNeedsStyleRecalc();
}
@@ -1092,7 +1113,7 @@ void Node::removeCachedNameNodeList(NameNodeList* list, const String& nodeName)
data->m_nameNodeListCache.remove(nodeName);
}
-void Node::removeCachedTagNodeList(TagNodeList* list, const QualifiedName& name)
+void Node::removeCachedTagNodeList(TagNodeList* list, const AtomicString& name)
{
ASSERT(rareData());
ASSERT(rareData()->nodeLists());
@@ -1103,6 +1124,17 @@ void Node::removeCachedTagNodeList(TagNodeList* list, const QualifiedName& name)
data->m_tagNodeListCache.remove(name.impl());
}
+void Node::removeCachedTagNodeListNS(TagNodeListNS* list, const QualifiedName& name)
+{
+ ASSERT(rareData());
+ ASSERT(rareData()->nodeLists());
+ ASSERT_UNUSED(list, list->hasOwnCaches());
+
+ NodeListsNodeData* data = rareData()->nodeLists();
+ ASSERT_UNUSED(list, list == data->m_tagNodeListCacheNS.get(name.impl()));
+ data->m_tagNodeListCacheNS.remove(name.impl());
+}
+
void Node::removeCachedLabelsNodeList(DynamicNodeList* list)
{
ASSERT(rareData());
@@ -1115,12 +1147,15 @@ void Node::removeCachedLabelsNodeList(DynamicNodeList* list)
Node* Node::traverseNextNode(const Node* stayWithin) const
{
- if (firstChild())
- return firstChild();
+ prefetchTarget();
+ Node* fc = firstChild();
+ if (fc)
+ return fc;
if (this == stayWithin)
return 0;
- if (nextSibling())
- return nextSibling();
+ Node* ns = nextSibling();
+ if (ns)
+ return ns;
const Node *n = this;
while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
n = n->parentNode();
@@ -1129,15 +1164,54 @@ Node* Node::traverseNextNode(const Node* stayWithin) const
return 0;
}
+Node* Node::lastDescendantNode(bool includeThis) const
+{
+ Node* n = lastChild();
+ if (!n && includeThis)
+ return const_cast<Node*>(this);
+
+ Node* p = n;
+ while(n) {
+ p = n;
+ n = n->lastChild();
+ }
+ return p;
+}
+
+void Node::updatePrevNextNodesInSubtree()
+{
+ Node* n = firstChild();
+ Node* next;
+ while(n) {
+ next = n->traverseNextNode(this);
+ if (next) {
+ n->setNextNode(next);
+ next->setPreviousNode(n);
+ } else {
+ next = n->traverseNextNode();
+ n->setNextNode(next);
+ if (next)
+ next->setPreviousNode(n);
+ break;
+ }
+ n = next;
+ }
+ updateNextNode();
+}
+
Node* Node::traverseNextSibling(const Node* stayWithin) const
{
if (this == stayWithin)
return 0;
- if (nextSibling())
- return nextSibling();
+ prefetchTarget();
+ Node* ns = nextSibling();
+ if (ns)
+ return ns;
const Node *n = this;
- while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
+ while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin)) {
+ n->prefetchTarget();
n = n->parentNode();
+ }
if (n)
return n->nextSibling();
return 0;
@@ -1157,10 +1231,11 @@ Node* Node::traversePreviousNode(const Node* stayWithin) const
{
if (this == stayWithin)
return 0;
- if (previousSibling()) {
- Node *n = previousSibling();
- while (n->lastChild())
- n = n->lastChild();
+ Node *n = previousSibling();
+ if (n) {
+ Node* lastChild;
+ while ((lastChild = n->lastChild()))
+ n = lastChild;
return n;
}
return parentNode();
@@ -1168,12 +1243,12 @@ Node* Node::traversePreviousNode(const Node* stayWithin) const
Node* Node::traversePreviousNodePostOrder(const Node* stayWithin) const
{
- if (lastChild())
- return lastChild();
+ if (Node* lc = lastChild())
+ return lc;
if (this == stayWithin)
return 0;
- if (previousSibling())
- return previousSibling();
+ if (Node* ps = previousSibling())
+ return ps;
const Node *n = this;
while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin))
n = n->parentNode();
@@ -1186,8 +1261,8 @@ Node* Node::traversePreviousSiblingPostOrder(const Node* stayWithin) const
{
if (this == stayWithin)
return 0;
- if (previousSibling())
- return previousSibling();
+ if (Node* ps = previousSibling())
+ return ps;
const Node *n = this;
while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin))
n = n->parentNode();
@@ -1333,14 +1408,20 @@ void Node::attach()
// FIXME: This is O(N^2) for the innerHTML case, where all children are replaced at once (and not attached).
// If this node got a renderer it may be the previousRenderer() of sibling text nodes and thus affect the
// result of Text::rendererIsNeeded() for those nodes.
- if (renderer()) {
+ RenderObject* renderer = this->renderer();
+ if (renderer) {
for (Node* next = nextSibling(); next; next = next->nextSibling()) {
if (next->renderer())
break;
if (!next->attached())
break; // Assume this means none of the following siblings are attached.
- if (next->isTextNode())
+ if (next->isTextNode()) {
+ static_cast<Text*>(next)->setPreviousRenderer(renderer);
next->createRendererIfNeeded();
+ if (next->renderer())
+ renderer = next->renderer();
+ static_cast<Text*>(next)->setPreviousRenderer(0);
+ }
}
}
@@ -1366,23 +1447,7 @@ void Node::detach()
if (inActiveChain())
doc->activeChainNodeDetached(this);
- clearFlag(IsActiveFlag);
- clearFlag(IsHoveredFlag);
- clearFlag(InActiveChainFlag);
- clearFlag(IsAttachedFlag);
-
- clearFlag(InDetachFlag);
-}
-
-RenderObject* Node::previousRenderer()
-{
- // FIXME: We should have the same O(N^2) avoidance as nextRenderer does
- // however, when I tried adding it, several tests failed.
- for (Node* n = previousSibling(); n; n = n->previousSibling()) {
- if (n->renderer())
- return n->renderer();
- }
- return 0;
+ clearFlag(NodeDetachClearFlags);
}
RenderObject* Node::nextRenderer()
@@ -1697,44 +1762,45 @@ bool Node::inSameContainingBlockFlowElement(Node *n)
PassRefPtr<NodeList> Node::getElementsByTagName(const AtomicString& name)
{
- return getElementsByTagNameNS(starAtom, name);
+ if (name.isNull())
+ return 0;
+
+ NodeListsNodeData* data = ensureRareData()->ensureNodeLists(this);
+
+ AtomicString localNameAtom = document()->isHTMLDocument() ? name.lower() : name;
+
+ pair<NodeListsNodeData::TagNodeListCache::iterator, bool> result = data->m_tagNodeListCache.add(localNameAtom.impl(), 0);
+ if (!result.second)
+ return PassRefPtr<TagNodeList>(result.first->second);
+
+ RefPtr<TagNodeList> list = TagNodeList::create(this, localNameAtom);
+ result.first->second = list.get();
+ return list.release();
}
PassRefPtr<NodeList> Node::getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName)
{
if (localName.isNull())
return 0;
-
- NodeRareData* data = ensureRareData();
- if (!data->nodeLists()) {
- data->setNodeLists(NodeListsNodeData::create());
- document()->addNodeListCache();
- }
- String name = localName;
- if (document()->isHTMLDocument())
- name = localName.lower();
-
- AtomicString localNameAtom = name;
-
- pair<NodeListsNodeData::TagNodeListCache::iterator, bool> result = data->nodeLists()->m_tagNodeListCache.add(QualifiedName(nullAtom, localNameAtom, namespaceURI).impl(), 0);
+ NodeListsNodeData* data = ensureRareData()->ensureNodeLists(this);
+
+ AtomicString localNameAtom = document()->isHTMLDocument() ? localName.lower() : localName;
+
+ pair<NodeListsNodeData::TagNodeListCacheNS::iterator, bool> result = data->m_tagNodeListCacheNS.add(QualifiedName(nullAtom, localNameAtom, namespaceURI).impl(), 0);
if (!result.second)
- return PassRefPtr<TagNodeList>(result.first->second);
-
- RefPtr<TagNodeList> list = TagNodeList::create(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localNameAtom);
+ return PassRefPtr<TagNodeListNS>(result.first->second);
+
+ RefPtr<TagNodeListNS> list = TagNodeListNS::create(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localNameAtom);
result.first->second = list.get();
return list.release();
}
PassRefPtr<NodeList> Node::getElementsByName(const String& elementName)
{
- NodeRareData* data = ensureRareData();
- if (!data->nodeLists()) {
- data->setNodeLists(NodeListsNodeData::create());
- document()->addNodeListCache();
- }
+ NodeListsNodeData* data = ensureRareData()->ensureNodeLists(this);
- pair<NodeListsNodeData::NameNodeListCache::iterator, bool> result = data->nodeLists()->m_nameNodeListCache.add(elementName, 0);
+ pair<NodeListsNodeData::NameNodeListCache::iterator, bool> result = data->m_nameNodeListCache.add(elementName, 0);
if (!result.second)
return PassRefPtr<NodeList>(result.first->second);
@@ -1745,13 +1811,9 @@ PassRefPtr<NodeList> Node::getElementsByName(const String& elementName)
PassRefPtr<NodeList> Node::getElementsByClassName(const String& classNames)
{
- NodeRareData* data = ensureRareData();
- if (!data->nodeLists()) {
- data->setNodeLists(NodeListsNodeData::create());
- document()->addNodeListCache();
- }
+ NodeListsNodeData* data = ensureRareData()->ensureNodeLists(this);
- pair<NodeListsNodeData::ClassNodeListCache::iterator, bool> result = data->nodeLists()->m_classNodeListCache.add(classNames, 0);
+ pair<NodeListsNodeData::ClassNodeListCache::iterator, bool> result = data->m_classNodeListCache.add(classNames, 0);
if (!result.second)
return PassRefPtr<NodeList>(result.first->second);
@@ -1794,7 +1856,8 @@ PassRefPtr<Element> Node::querySelector(const String& selectors, ExceptionCode&
}
// FIXME: We can speed this up by implementing caching similar to the one use by getElementById
- for (Node* n = firstChild(); n; n = n->traverseNextNode(this)) {
+ Node* last = lastDescendantNode();
+ for (Node* n = firstChild(); n; n = n->traverseNextNodeFastPath()) {
if (n->isElementNode()) {
Element* element = static_cast<Element*>(n);
for (CSSSelector* selector = querySelectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
@@ -1802,6 +1865,8 @@ PassRefPtr<Element> Node::querySelector(const String& selectors, ExceptionCode&
return element;
}
}
+ if (n == last)
+ break;
}
return 0;
@@ -2429,6 +2494,9 @@ void NodeListsNodeData::invalidateCaches()
if (m_labelsNodeListCache)
m_labelsNodeListCache->invalidateCache();
+ TagNodeListCacheNS::const_iterator tagCacheEndNS = m_tagNodeListCacheNS.end();
+ for (TagNodeListCacheNS::const_iterator it = m_tagNodeListCacheNS.begin(); it != tagCacheEndNS; ++it)
+ it->second->invalidateCache();
TagNodeListCache::const_iterator tagCacheEnd = m_tagNodeListCache.end();
for (TagNodeListCache::const_iterator it = m_tagNodeListCache.begin(); it != tagCacheEnd; ++it)
it->second->invalidateCache();
@@ -2456,6 +2524,12 @@ bool NodeListsNodeData::isEmpty() const
if (m_childNodeListCaches->refCount())
return false;
+ TagNodeListCacheNS::const_iterator tagCacheEndNS = m_tagNodeListCacheNS.end();
+ for (TagNodeListCacheNS::const_iterator it = m_tagNodeListCacheNS.begin(); it != tagCacheEndNS; ++it) {
+ if (it->second->refCount())
+ return false;
+ }
+
TagNodeListCache::const_iterator tagCacheEnd = m_tagNodeListCache.end();
for (TagNodeListCache::const_iterator it = m_tagNodeListCache.begin(); it != tagCacheEnd; ++it) {
if (it->second->refCount())
diff --git a/Source/WebCore/dom/Node.h b/Source/WebCore/dom/Node.h
index 76355c3..d75d064 100644
--- a/Source/WebCore/dom/Node.h
+++ b/Source/WebCore/dom/Node.h
@@ -4,6 +4,7 @@
* (C) 2001 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2012 The Linux Foundation 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
@@ -75,6 +76,7 @@ class RenderStyle;
class SVGUseElement;
#endif
class TagNodeList;
+class TagNodeListNS;
class TreeScope;
typedef int ExceptionCode;
@@ -121,6 +123,8 @@ public:
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20,
};
+ static const int cPrefetchTargetDepth;
+
static bool isSupported(const String& feature, const String& version);
static void startIgnoringLeaks();
@@ -143,8 +147,8 @@ public:
virtual NodeType nodeType() const = 0;
ContainerNode* parentNode() const;
Element* parentElement() const;
- Node* previousSibling() const { return m_previous; }
- Node* nextSibling() const { return m_next; }
+ ALWAYS_INLINE Node* previousSibling() const { return m_previous; }
+ ALWAYS_INLINE Node* nextSibling() const { return m_next; }
PassRefPtr<NodeList> childNodes();
Node* firstChild() const;
Node* lastChild() const;
@@ -187,14 +191,14 @@ public:
// Other methods (not part of DOM)
- bool isElementNode() const { return getFlag(IsElementFlag); }
- bool isContainerNode() const { return getFlag(IsContainerFlag); }
+ ALWAYS_INLINE bool isElementNode() const { return getFlag(IsElementFlag); }
+ ALWAYS_INLINE bool isContainerNode() const { return getFlag(IsContainerFlag); }
bool isTextNode() const { return getFlag(IsTextFlag); }
bool isHTMLElement() const { return getFlag(IsHTMLFlag); }
- bool isSVGElement() const { return getFlag(IsSVGFlag); }
- virtual bool isSVGShadowRoot() const { return false; }
+ ALWAYS_INLINE bool isSVGElement() const { return getFlag(IsSVGFlag); }
+ ALWAYS_INLINE bool isSVGShadowRoot() const { return getFlag(IsShadowRootOrSVGShadowRootFlag) && isSVGElement(); }
#if ENABLE(SVG)
SVGUseElement* svgShadowHost() const;
#endif
@@ -213,7 +217,7 @@ public:
bool isCommentNode() const { return getFlag(IsCommentFlag); }
virtual bool isCharacterDataNode() const { return false; }
bool isDocumentNode() const;
- bool isShadowRoot() const { return getFlag(IsShadowRootFlag); }
+ bool isShadowRoot() const { return getFlag(IsShadowRootOrSVGShadowRootFlag) && !isSVGElement(); }
// FIXME: Remove this when all shadow roots are ShadowRoots.
virtual bool isShadowBoundary() const { return false; }
virtual bool canHaveLightChildRendererWithShadow() const { return false; }
@@ -240,7 +244,30 @@ public:
// These low-level calls give the caller responsibility for maintaining the integrity of the tree.
void setPreviousSibling(Node* previous) { m_previous = previous; }
+#ifdef __ARM_USE_PLD
+ ALWAYS_INLINE void updatePrefetchTarget() {
+ if (m_next) {
+ int skew;
+ Node* from = this;
+ Node* n = from->traversePreviousNodePostOrder();
+ for (skew = cPrefetchTargetDepth - 1; skew && n; skew--) {
+ from = n;
+ n = n->traversePreviousNodePostOrder();
+ }
+ from->setPrefetchTarget(m_next);
+ }
+ }
+ void setPrefetchTarget(Node *prefetch) { m_prefetch = prefetch; }
+ void setNextSibling(Node* next) { m_next = next; updatePrefetchTarget(); }
+#else
void setNextSibling(Node* next) { m_next = next; }
+#endif
+ void updatePreviousNode() { m_previousNode = traversePreviousNode(); if (m_previousNode) m_previousNode->setNextNode(this); }
+ void updateNextNode() { m_nextNode = traverseNextNode(); if (m_nextNode) m_nextNode->setPreviousNode(this); }
+ void updatePrevNextNodesInSubtree();
+
+ void setPreviousNode(Node* previous) { m_previousNode = previous; }
+ void setNextNode(Node* next) { m_nextNode = next; }
// FIXME: These two functions belong in editing -- "atomic node" is an editing concept.
Node* previousNodeConsideringAtomicNodes() const;
@@ -314,6 +341,9 @@ public:
void setIsLink() { setFlag(IsLinkFlag); }
void clearIsLink() { clearFlag(IsLinkFlag); }
+ void setIeForbidsInsertHTML() { setFlag(IeForbidsInsertHTML); }
+ bool ieForbidsInsertHTML() const { return getFlag(IeForbidsInsertHTML); }
+
enum ShouldSetAttached {
SetAttached,
DoNotSetAttached
@@ -392,12 +422,27 @@ public:
// This can be used to restrict traversal to a particular sub-tree.
Node* traverseNextNode(const Node* stayWithin = 0) const;
+ Node* traverseNextNodeFastPath() const { prefetchTarget(); return m_nextNode; }
+
+ ALWAYS_INLINE void prefetchTarget() const {
+#ifdef __ARM_USE_PLD
+ if (m_prefetch) {
+ __builtin_prefetch(((char *) m_prefetch));
+ __builtin_prefetch(((char *) m_prefetch) + 64);
+ }
+#endif
+ }
+
+ Node* lastDescendantNode(bool includeThis = false) const;
+
// Like traverseNextNode, but skips children and starts with the next sibling.
Node* traverseNextSibling(const Node* stayWithin = 0) const;
// Does a reverse pre-order traversal to find the node that comes before the current one in document order
Node* traversePreviousNode(const Node* stayWithin = 0) const;
+ Node* traversePreviousNodeFastPath() const { return m_previousNode; }
+
// Like traverseNextNode, but visits parents after their children.
Node* traverseNextNodePostOrder() const;
@@ -515,9 +560,10 @@ public:
void notifyLocalNodeListsLabelChanged();
void removeCachedClassNodeList(ClassNodeList*, const String&);
void removeCachedNameNodeList(NameNodeList*, const String&);
- void removeCachedTagNodeList(TagNodeList*, const QualifiedName&);
+ void removeCachedTagNodeList(TagNodeList*, const AtomicString&);
+ void removeCachedTagNodeListNS(TagNodeListNS*, const QualifiedName&);
void removeCachedLabelsNodeList(DynamicNodeList*);
-
+
PassRefPtr<NodeList> getElementsByTagName(const AtomicString&);
PassRefPtr<NodeList> getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName);
PassRefPtr<NodeList> getElementsByName(const String& elementName);
@@ -593,7 +639,7 @@ private:
InActiveChainFlag = 1 << 15,
InDetachFlag = 1 << 16,
HasRareDataFlag = 1 << 17,
- IsShadowRootFlag = 1 << 18,
+ IsShadowRootOrSVGShadowRootFlag = 1 << 18,
// These bits are used by derived classes, pulled up here so they can
// be stored in the same memory word as the Node bits above.
@@ -605,11 +651,14 @@ private:
IsSynchronizingSVGAttributesFlag = 1 << 23, // SVGElement
HasSVGRareDataFlag = 1 << 24, // SVGElement
#endif
-
StyleChangeMask = 1 << nodeStyleChangeShift | 1 << (nodeStyleChangeShift + 1),
SelfOrAncestorHasDirAutoFlag = 1 << 27,
+ IeForbidsInsertHTML = 1 << 28,
+
+ NodeDetachClearFlags = IsActiveFlag | IsHoveredFlag | InActiveChainFlag | IsAttachedFlag | InDetachFlag,
+
#if ENABLE(SVG)
DefaultNodeFlags = IsParsingChildrenFinishedFlag | IsStyleAttributeValidFlag | AreSVGAttributesValidFlag
#else
@@ -619,7 +668,7 @@ private:
// 4 bits remaining
- bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; }
+ ALWAYS_INLINE bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; }
void setFlag(bool f, NodeFlags mask) const { m_nodeFlags = (m_nodeFlags & ~mask) | (-(int32_t)f & mask); }
void setFlag(NodeFlags mask) const { m_nodeFlags |= mask; }
void clearFlag(NodeFlags mask) const { m_nodeFlags &= ~mask; }
@@ -631,9 +680,11 @@ protected:
CreateComment = DefaultNodeFlags | IsCommentFlag,
CreateContainer = DefaultNodeFlags | IsContainerFlag,
CreateElement = CreateContainer | IsElementFlag,
+ CreateShadowRoot = CreateContainer | IsShadowRootOrSVGShadowRootFlag,
CreateStyledElement = CreateElement | IsStyledElementFlag,
CreateHTMLElement = CreateStyledElement | IsHTMLFlag,
CreateSVGElement = CreateStyledElement | IsSVGFlag,
+ CreateSVGShadowRoot = CreateSVGElement | IsShadowRootOrSVGShadowRootFlag,
};
Node(Document*, ConstructionType);
@@ -690,8 +741,13 @@ private:
Document* m_document;
Node* m_previous;
Node* m_next;
+#ifdef __ARM_USE_PLD
+ Node* m_prefetch;
+#endif
RenderObject* m_renderer;
mutable uint32_t m_nodeFlags;
+ Node* m_previousNode;
+ Node* m_nextNode;
protected:
bool isParsingChildrenFinished() const { return getFlag(IsParsingChildrenFinishedFlag); }
@@ -728,7 +784,7 @@ inline void addSubresourceURL(ListHashSet<KURL>& urls, const KURL& url)
inline ContainerNode* Node::parentNode() const
{
- return getFlag(IsShadowRootFlag) || isSVGShadowRoot() ? 0 : parent();
+ return getFlag(IsShadowRootOrSVGShadowRootFlag) ? 0 : parent();
}
inline ContainerNode* Node::parentOrHostNode() const
@@ -738,7 +794,7 @@ inline ContainerNode* Node::parentOrHostNode() const
inline ContainerNode* Node::parentNodeGuaranteedHostFree() const
{
- ASSERT(!getFlag(IsShadowRootFlag) && !isSVGShadowRoot());
+ ASSERT(!getFlag(IsShadowRootOrSVGShadowRootFlag));
return parentOrHostNode();
}
diff --git a/Source/WebCore/dom/NodeRareData.h b/Source/WebCore/dom/NodeRareData.h
index ac05d3e..7bbd0c1 100644
--- a/Source/WebCore/dom/NodeRareData.h
+++ b/Source/WebCore/dom/NodeRareData.h
@@ -49,10 +49,13 @@ public:
typedef HashMap<String, NameNodeList*> NameNodeListCache;
NameNodeListCache m_nameNodeListCache;
-
- typedef HashMap<RefPtr<QualifiedName::QualifiedNameImpl>, TagNodeList*> TagNodeListCache;
+
+ typedef HashMap<AtomicStringImpl*, TagNodeList*> TagNodeListCache;
TagNodeListCache m_tagNodeListCache;
+ typedef HashMap<RefPtr<QualifiedName::QualifiedNameImpl>, TagNodeListNS*> TagNodeListCacheNS;
+ TagNodeListCacheNS m_tagNodeListCacheNS;
+
RefPtr<DynamicNodeList> m_labelsNodeListCache;
static PassOwnPtr<NodeListsNodeData> create()
@@ -106,6 +109,15 @@ public:
void clearNodeLists() { m_nodeLists.clear(); }
void setNodeLists(PassOwnPtr<NodeListsNodeData> lists) { m_nodeLists = lists; }
NodeListsNodeData* nodeLists() const { return m_nodeLists.get(); }
+ NodeListsNodeData* ensureNodeLists(Node* n)
+ {
+ if (!m_nodeLists) {
+ m_nodeLists = NodeListsNodeData::create();
+ if (n->document())
+ n->document()->addNodeListCache();
+ }
+ return m_nodeLists.get();
+ }
short tabIndex() const { return m_tabIndex; }
void setTabIndexExplicitly(short index) { m_tabIndex = index; m_tabIndexWasSetExplicitly = true; }
diff --git a/Source/WebCore/dom/ProcessingInstruction.cpp b/Source/WebCore/dom/ProcessingInstruction.cpp
index 30111d8..3feb0ab 100644
--- a/Source/WebCore/dom/ProcessingInstruction.cpp
+++ b/Source/WebCore/dom/ProcessingInstruction.cpp
@@ -161,9 +161,10 @@ void ProcessingInstruction::checkStyleSheet()
m_loading = true;
document()->addPendingSheet();
+ ResourceRequest request(document()->completeURL(href));
#if ENABLE(XSLT)
if (m_isXSL)
- m_cachedSheet = document()->cachedResourceLoader()->requestXSLStyleSheet(url);
+ m_cachedSheet = document()->cachedResourceLoader()->requestXSLStyleSheet(request);
else
#endif
{
@@ -171,7 +172,7 @@ void ProcessingInstruction::checkStyleSheet()
if (charset.isEmpty())
charset = document()->charset();
- m_cachedSheet = document()->cachedResourceLoader()->requestCSSStyleSheet(url, charset);
+ m_cachedSheet = document()->cachedResourceLoader()->requestCSSStyleSheet(request, charset);
}
if (m_cachedSheet)
m_cachedSheet->addClient(this);
diff --git a/Source/WebCore/dom/RequestAnimationFrameCallback.h b/Source/WebCore/dom/RequestAnimationFrameCallback.h
index 3edeb9e..a867922 100644
--- a/Source/WebCore/dom/RequestAnimationFrameCallback.h
+++ b/Source/WebCore/dom/RequestAnimationFrameCallback.h
@@ -31,8 +31,7 @@
#ifndef RequestAnimationFrameCallback_h
#define RequestAnimationFrameCallback_h
-#include "Element.h"
-#include <wtf/PassRefPtr.h>
+#include "DOMTimeStamp.h"
#include <wtf/RefCounted.h>
namespace WebCore {
@@ -42,7 +41,6 @@ public:
virtual ~RequestAnimationFrameCallback() { }
virtual bool handleEvent(DOMTimeStamp) = 0;
- RefPtr<Element> m_element;
int m_id;
bool m_firedOrCancelled;
};
diff --git a/Source/WebCore/dom/ScriptElement.cpp b/Source/WebCore/dom/ScriptElement.cpp
index 55a7949..dc075ae 100644
--- a/Source/WebCore/dom/ScriptElement.cpp
+++ b/Source/WebCore/dom/ScriptElement.cpp
@@ -248,7 +248,8 @@ bool ScriptElement::requestScript(const String& sourceUrl)
ASSERT(!m_cachedScript);
// FIXME: If sourceUrl is empty, we should dispatchErrorEvent().
- m_cachedScript = m_element->document()->cachedResourceLoader()->requestScript(sourceUrl, scriptCharset());
+ ResourceRequest request(m_element->document()->completeURL(sourceUrl));
+ m_cachedScript = m_element->document()->cachedResourceLoader()->requestScript(request, scriptCharset());
m_isExternalScript = true;
if (m_cachedScript)
diff --git a/Source/WebCore/dom/ScriptedAnimationController.cpp b/Source/WebCore/dom/ScriptedAnimationController.cpp
index 0c70359..4fbf6d9 100644
--- a/Source/WebCore/dom/ScriptedAnimationController.cpp
+++ b/Source/WebCore/dom/ScriptedAnimationController.cpp
@@ -29,16 +29,29 @@
#if ENABLE(REQUEST_ANIMATION_FRAME)
#include "Document.h"
-#include "Element.h"
#include "FrameView.h"
#include "RequestAnimationFrameCallback.h"
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+#include <algorithm>
+#include <wtf/CurrentTime.h>
+
+using namespace std;
+
+// Allow a little more than 60fps to make sure we can at least hit that frame rate.
+#define MinimumAnimationInterval 0.015
+#endif
+
namespace WebCore {
ScriptedAnimationController::ScriptedAnimationController(Document* document)
: m_document(document)
, m_nextCallbackId(0)
, m_suspendCount(0)
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+ , m_animationTimer(this, &ScriptedAnimationController::animationTimerFired)
+ , m_lastAnimationFrameTime(0)
+#endif
{
}
@@ -51,20 +64,17 @@ void ScriptedAnimationController::resume()
{
--m_suspendCount;
if (!m_suspendCount && m_callbacks.size())
- if (FrameView* fv = m_document->view())
- fv->scheduleAnimation();
+ scheduleAnimation();
}
-ScriptedAnimationController::CallbackId ScriptedAnimationController::registerCallback(PassRefPtr<RequestAnimationFrameCallback> callback, Element* animationElement)
+ScriptedAnimationController::CallbackId ScriptedAnimationController::registerCallback(PassRefPtr<RequestAnimationFrameCallback> callback)
{
ScriptedAnimationController::CallbackId id = m_nextCallbackId++;
callback->m_firedOrCancelled = false;
callback->m_id = id;
- callback->m_element = animationElement;
m_callbacks.append(callback);
if (!m_suspendCount)
- if (FrameView* view = m_document->view())
- view->scheduleAnimation();
+ scheduleAnimation();
return id;
}
@@ -83,37 +93,19 @@ void ScriptedAnimationController::serviceScriptedAnimations(DOMTimeStamp time)
{
if (!m_callbacks.size() || m_suspendCount)
return;
- // We want to run the callback for all elements in the document that have registered
- // for a callback and that are visible. Running the callbacks can cause new callbacks
- // to be registered, existing callbacks to be cancelled, and elements to gain or lose
- // visibility so this code has to iterate carefully.
-
- // FIXME: Currently, this code doesn't do any visibility tests beyond checking display:
// First, generate a list of callbacks to consider. Callbacks registered from this point
// on are considered only for the "next" frame, not this one.
CallbackList callbacks(m_callbacks);
- // Firing the callback may cause the visibility of other elements to change. To avoid
- // missing any callbacks, we keep iterating through the list of candiate callbacks and firing
- // them until nothing new becomes visible.
- bool firedCallback;
- do {
- firedCallback = false;
- // A previous iteration may have invalidated style (or layout). Update styles for each iteration
- // for now since all we check is the existence of a renderer.
- m_document->updateStyleIfNeeded();
- for (size_t i = 0; i < callbacks.size(); ++i) {
- RequestAnimationFrameCallback* callback = callbacks[i].get();
- if (!callback->m_firedOrCancelled && (!callback->m_element || callback->m_element->renderer())) {
- callback->m_firedOrCancelled = true;
- callback->handleEvent(time);
- firedCallback = true;
- callbacks.remove(i);
- break;
- }
+ for (size_t i = 0; i < callbacks.size(); ++i) {
+ RequestAnimationFrameCallback* callback = callbacks[i].get();
+ if (!callback->m_firedOrCancelled) {
+ callback->m_firedOrCancelled = true;
+ callback->handleEvent(time);
}
- } while (firedCallback);
+ }
+ m_document->updateStyleIfNeeded();
// Remove any callbacks we fired from the list of pending callbacks.
for (size_t i = 0; i < m_callbacks.size();) {
@@ -124,10 +116,28 @@ void ScriptedAnimationController::serviceScriptedAnimations(DOMTimeStamp time)
}
if (m_callbacks.size())
- if (FrameView* view = m_document->view())
- view->scheduleAnimation();
+ scheduleAnimation();
}
+void ScriptedAnimationController::scheduleAnimation()
+{
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+ double scheduleDelay = max<double>(MinimumAnimationInterval - (currentTime() - m_lastAnimationFrameTime), 0);
+ m_animationTimer.startOneShot(scheduleDelay);
+#else
+ if (FrameView* frameView = m_document->view())
+ frameView->scheduleAnimation();
+#endif
+}
+
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+void ScriptedAnimationController::animationTimerFired(Timer<ScriptedAnimationController>*)
+{
+ m_lastAnimationFrameTime = currentTime();
+ serviceScriptedAnimations(convertSecondsToDOMTimeStamp(m_lastAnimationFrameTime));
+}
+#endif
+
}
#endif
diff --git a/Source/WebCore/dom/ScriptedAnimationController.h b/Source/WebCore/dom/ScriptedAnimationController.h
index 7141968..f6f06a9 100644
--- a/Source/WebCore/dom/ScriptedAnimationController.h
+++ b/Source/WebCore/dom/ScriptedAnimationController.h
@@ -28,6 +28,9 @@
#if ENABLE(REQUEST_ANIMATION_FRAME)
#include "DOMTimeStamp.h"
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+#include "Timer.h"
+#endif
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/RefPtr.h>
@@ -36,7 +39,6 @@
namespace WebCore {
class Document;
-class Element;
class RequestAnimationFrameCallback;
class ScriptedAnimationController {
@@ -49,7 +51,7 @@ public:
typedef int CallbackId;
- CallbackId registerCallback(PassRefPtr<RequestAnimationFrameCallback>, Element*);
+ CallbackId registerCallback(PassRefPtr<RequestAnimationFrameCallback>);
void cancelCallback(CallbackId);
void serviceScriptedAnimations(DOMTimeStamp);
@@ -58,12 +60,21 @@ public:
private:
explicit ScriptedAnimationController(Document*);
+
typedef Vector<RefPtr<RequestAnimationFrameCallback> > CallbackList;
CallbackList m_callbacks;
Document* m_document;
CallbackId m_nextCallbackId;
int m_suspendCount;
+
+ void scheduleAnimation();
+
+#if USE(REQUEST_ANIMATION_FRAME_TIMER)
+ void animationTimerFired(Timer<ScriptedAnimationController>*);
+ Timer<ScriptedAnimationController> m_animationTimer;
+ double m_lastAnimationFrameTime;
+#endif
};
}
diff --git a/Source/WebCore/dom/SelectorNodeList.cpp b/Source/WebCore/dom/SelectorNodeList.cpp
index 7611488..82f1103 100644
--- a/Source/WebCore/dom/SelectorNodeList.cpp
+++ b/Source/WebCore/dom/SelectorNodeList.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 The Linux Foundation All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -55,16 +56,25 @@ PassRefPtr<StaticNodeList> createSelectorNodeList(Node* rootNode, const CSSSelec
if (element && (rootNode->isDocumentNode() || element->isDescendantOf(rootNode)) && selectorChecker.checkSelector(onlySelector, element))
nodes.append(element);
} else {
- for (Node* n = rootNode->firstChild(); n; n = n->traverseNextNode(rootNode)) {
+ Vector<CSSSelector*> querySelectors;
+ querySelectors.reserveInitialCapacity(16);
+ for (CSSSelector* selector = querySelectorList.first(); selector; selector = CSSSelectorList::next(selector))
+ querySelectors.append(selector);
+ int querySelectorsCount = querySelectors.size();
+
+ Node* lastNode = rootNode->lastDescendantNode();
+ for (Node* n = rootNode->firstChild(); n; n = n->traverseNextNodeFastPath()) {
if (n->isElementNode()) {
Element* element = static_cast<Element*>(n);
- for (CSSSelector* selector = querySelectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
- if (selectorChecker.checkSelector(selector, element)) {
+ for (int i = 0; i < querySelectorsCount; i++) {
+ if (selectorChecker.checkSelector(querySelectors[i], element)) {
nodes.append(n);
break;
}
}
}
+ if (n == lastNode)
+ break;
}
}
diff --git a/Source/WebCore/dom/TagNodeList.cpp b/Source/WebCore/dom/TagNodeList.cpp
index 4914e09..df51fe1 100644
--- a/Source/WebCore/dom/TagNodeList.cpp
+++ b/Source/WebCore/dom/TagNodeList.cpp
@@ -4,6 +4,7 @@
* (C) 2001 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2012 The Linux Foundation 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,25 +30,45 @@
namespace WebCore {
-TagNodeList::TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
+TagNodeListNS::TagNodeListNS(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
: DynamicNodeList(rootNode)
, m_namespaceURI(namespaceURI)
, m_localName(localName)
+ , m_isStarAtomNamespaceURI(m_namespaceURI == starAtom)
+ , m_isStarAtomlocalName(m_localName == starAtom)
{
ASSERT(m_namespaceURI.isNull() || !m_namespaceURI.isEmpty());
}
-TagNodeList::~TagNodeList()
+TagNodeListNS::~TagNodeListNS()
{
- m_rootNode->removeCachedTagNodeList(this, QualifiedName(nullAtom, m_localName, m_namespaceURI));
-}
+ m_rootNode->removeCachedTagNodeListNS(this, QualifiedName(nullAtom, m_localName, m_namespaceURI));
+}
-bool TagNodeList::nodeMatches(Element* testNode) const
+bool TagNodeListNS::nodeMatches(Element* testNode) const
{
- if (m_namespaceURI != starAtom && m_namespaceURI != testNode->namespaceURI())
+ if (!m_isStarAtomNamespaceURI && m_namespaceURI != testNode->namespaceURI())
return false;
- return m_localName == starAtom || m_localName == testNode->localName();
+ return m_isStarAtomlocalName || m_localName == testNode->localName();
}
+TagNodeList::TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& localName)
+ : DynamicNodeList(rootNode)
+ , m_localName(localName)
+ , m_isStarAtomlocalName(m_localName == starAtom)
+{
+}
+
+TagNodeList::~TagNodeList()
+{
+ m_rootNode->removeCachedTagNodeList(this, m_localName);
+}
+
+bool TagNodeList::nodeMatches(Element* testNode) const
+{
+ return m_isStarAtomlocalName || m_localName == testNode->localName();
+}
+
+
} // namespace WebCore
diff --git a/Source/WebCore/dom/TagNodeList.h b/Source/WebCore/dom/TagNodeList.h
index 9053b53..f255532 100644
--- a/Source/WebCore/dom/TagNodeList.h
+++ b/Source/WebCore/dom/TagNodeList.h
@@ -29,24 +29,45 @@
namespace WebCore {
- // NodeList that limits to a particular tag.
- class TagNodeList : public DynamicNodeList {
- public:
- static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
- {
- return adoptRef(new TagNodeList(rootNode, namespaceURI, localName));
- }
+// NodeList with namespace that limits to a particular tag.
+class TagNodeListNS : public DynamicNodeList {
+public:
+ static PassRefPtr<TagNodeListNS> create(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
+ {
+ return adoptRef(new TagNodeListNS(rootNode, namespaceURI, localName));
+ }
- virtual ~TagNodeList();
+ virtual ~TagNodeListNS();
- private:
- TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName);
+private:
+ TagNodeListNS(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName);
- virtual bool nodeMatches(Element*) const;
+ virtual bool nodeMatches(Element*) const;
- AtomicString m_namespaceURI;
- AtomicString m_localName;
- };
+ AtomicString m_namespaceURI;
+ AtomicString m_localName;
+ bool m_isStarAtomNamespaceURI : 1;
+ bool m_isStarAtomlocalName : 1;
+};
+
+// NodeList that limits to a particular tag.
+class TagNodeList : public DynamicNodeList {
+public:
+ static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& localName)
+ {
+ return adoptRef(new TagNodeList(rootNode, localName));
+ }
+
+ virtual ~TagNodeList();
+
+private:
+ TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& localName);
+
+ virtual bool nodeMatches(Element*) const;
+
+ AtomicString m_localName;
+ bool m_isStarAtomlocalName;
+};
} // namespace WebCore
diff --git a/Source/WebCore/dom/Text.cpp b/Source/WebCore/dom/Text.cpp
index c4ea0a6..01a454d 100644
--- a/Source/WebCore/dom/Text.cpp
+++ b/Source/WebCore/dom/Text.cpp
@@ -213,7 +213,7 @@ bool Text::rendererIsNeeded(RenderStyle *style)
if (style->preserveNewline()) // pre/pre-wrap/pre-line always make renderers.
return true;
- RenderObject *prev = previousRenderer();
+ RenderObject* prev = m_previousRenderer ? m_previousRenderer : previousRenderer();
if (prev && prev->isBR()) // <span><br/> <br/></span>
return false;
diff --git a/Source/WebCore/dom/Text.h b/Source/WebCore/dom/Text.h
index 5995f1f..4db3bb3 100644
--- a/Source/WebCore/dom/Text.h
+++ b/Source/WebCore/dom/Text.h
@@ -43,9 +43,12 @@ public:
virtual void attach();
+ void setPreviousRenderer(RenderObject* renderer) { m_previousRenderer = renderer; }
+
protected:
Text(Document* document, const String& data)
: CharacterData(document, data, CreateText)
+ , m_previousRenderer(0)
{
}
@@ -63,6 +66,8 @@ private:
#ifndef NDEBUG
virtual void formatForDebugger(char* buffer, unsigned length) const;
#endif
+
+ RenderObject* m_previousRenderer;
};
} // namespace WebCore
diff --git a/Source/WebCore/dom/TreeScope.cpp b/Source/WebCore/dom/TreeScope.cpp
index a995a2d..45c7a8f 100644
--- a/Source/WebCore/dom/TreeScope.cpp
+++ b/Source/WebCore/dom/TreeScope.cpp
@@ -97,7 +97,7 @@ Element* TreeScope::getElementByAccessKey(const String& key) const
if (key.isEmpty())
return 0;
if (!m_accessKeyMapValid) {
- for (Node* n = firstChild(); n; n = n->traverseNextNode()) {
+ for (Node* n = firstChild(); n; n = n->traverseNextNodeFastPath()) {
if (!n->isElementNode())
continue;
Element* element = static_cast<Element*>(n);
@@ -149,7 +149,7 @@ Element* TreeScope::findAnchor(const String& name)
return 0;
if (Element* element = getElementById(name))
return element;
- for (Node* node = this; node; node = node->traverseNextNode()) {
+ for (Node* node = this; node; node = node->traverseNextNodeFastPath()) {
if (node->hasTagName(aTag)) {
HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(node);
if (document()->inQuirksMode()) {