summaryrefslogtreecommitdiffstats
path: root/WebCore/dom
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-05-05 14:36:32 +0100
committerBen Murdoch <benm@google.com>2011-05-10 15:38:30 +0100
commitf05b935882198ccf7d81675736e3aeb089c5113a (patch)
tree4ea0ca838d9ef1b15cf17ddb3928efb427c7e5a1 /WebCore/dom
parent60fbdcc62bced8db2cb1fd233cc4d1e4ea17db1b (diff)
downloadexternal_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.zip
external_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.tar.gz
external_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.tar.bz2
Merge WebKit at r74534: Initial merge by git.
Change-Id: I6ccd1154fa1b19c2ec2a66878eb675738735f1eb
Diffstat (limited to 'WebCore/dom')
-rw-r--r--WebCore/dom/CharacterData.cpp92
-rw-r--r--WebCore/dom/CharacterData.h4
-rw-r--r--WebCore/dom/CheckedRadioButtons.h2
-rw-r--r--WebCore/dom/ClientRect.cpp5
-rw-r--r--WebCore/dom/ClientRect.h2
-rw-r--r--WebCore/dom/ContainerNode.cpp18
-rw-r--r--WebCore/dom/DOMAllInOne.cpp2
-rw-r--r--WebCore/dom/DeviceMotionController.cpp4
-rw-r--r--WebCore/dom/DeviceMotionController.h4
-rw-r--r--WebCore/dom/DeviceOrientationController.cpp4
-rw-r--r--WebCore/dom/DeviceOrientationController.h4
-rw-r--r--WebCore/dom/Document.cpp72
-rw-r--r--WebCore/dom/Document.h31
-rw-r--r--WebCore/dom/DocumentMarkerController.cpp27
-rw-r--r--WebCore/dom/DocumentMarkerController.h8
-rw-r--r--WebCore/dom/DocumentTiming.h8
-rw-r--r--WebCore/dom/Element.cpp77
-rw-r--r--WebCore/dom/Element.h6
-rw-r--r--WebCore/dom/ElementRareData.h1
-rw-r--r--WebCore/dom/EventQueue.cpp73
-rw-r--r--WebCore/dom/EventQueue.h58
-rw-r--r--WebCore/dom/KeyboardEvent.h2
-rw-r--r--WebCore/dom/Node.cpp75
-rw-r--r--WebCore/dom/Node.h62
-rw-r--r--WebCore/dom/PositionIterator.cpp7
-rw-r--r--WebCore/dom/PositionIterator.h1
-rw-r--r--WebCore/dom/ProgressEvent.cpp10
-rw-r--r--WebCore/dom/ProgressEvent.h59
-rw-r--r--WebCore/dom/ProgressEvent.idl15
-rw-r--r--WebCore/dom/Range.cpp12
-rw-r--r--WebCore/dom/ScopedEventQueue.cpp103
-rw-r--r--WebCore/dom/ScopedEventQueue.h77
-rw-r--r--WebCore/dom/ScriptElement.cpp36
-rw-r--r--WebCore/dom/ScriptElement.h17
-rw-r--r--WebCore/dom/ScriptExecutionContext.h2
-rw-r--r--WebCore/dom/SelectElement.cpp4
-rw-r--r--WebCore/dom/SelectElement.h2
-rw-r--r--WebCore/dom/XMLDocumentParser.h4
-rw-r--r--WebCore/dom/XMLDocumentParserLibxml2.cpp6
-rwxr-xr-xWebCore/dom/make_names.pl1
40 files changed, 707 insertions, 290 deletions
diff --git a/WebCore/dom/CharacterData.cpp b/WebCore/dom/CharacterData.cpp
index 0cb2847..3372c4c 100644
--- a/WebCore/dom/CharacterData.cpp
+++ b/WebCore/dom/CharacterData.cpp
@@ -36,18 +36,9 @@ void CharacterData::setData(const String& data, ExceptionCode&)
if (equal(m_data.get(), dataImpl))
return;
- int oldLength = length();
- RefPtr<StringImpl> oldStr = m_data;
- m_data = dataImpl;
-
- if ((!renderer() || !rendererIsNeeded(renderer()->style())) && attached()) {
- detach();
- attach();
- } else if (renderer())
- toRenderText(renderer())->setTextWithOffset(m_data, 0, oldLength);
-
- dispatchModifiedEvent(oldStr.get());
+ unsigned oldLength = length();
+ setDataAndUpdate(dataImpl, 0, oldLength);
document()->textRemoved(this, 0, oldLength);
}
@@ -60,26 +51,15 @@ String CharacterData::substringData(unsigned offset, unsigned count, ExceptionCo
return m_data->substring(offset, count);
}
-PassRefPtr<StringImpl> CharacterData::appendDataCommon(const String& data)
+void CharacterData::parserAppendData(const String& data)
{
String newStr = m_data;
newStr.append(data);
- RefPtr<StringImpl> oldStr = m_data;
+ int oldLength = m_data->length();
m_data = newStr.impl();
- if ((!renderer() || !rendererIsNeeded(renderer()->style())) && attached()) {
- detach();
- attach();
- } else if (renderer())
- toRenderText(renderer())->setTextWithOffset(m_data, oldStr->length(), 0);
-
- return oldStr.release();
-}
-
-void CharacterData::parserAppendData(const String& data)
-{
- appendDataCommon(data);
+ updateRenderer(oldLength, 0);
// We don't call dispatchModifiedEvent here because we don't want the
// parser to dispatch DOM mutation events.
if (parentNode())
@@ -88,8 +68,12 @@ void CharacterData::parserAppendData(const String& data)
void CharacterData::appendData(const String& data, ExceptionCode&)
{
- RefPtr<StringImpl> oldStr = appendDataCommon(data);
- dispatchModifiedEvent(oldStr.get());
+ String newStr = m_data;
+ newStr.append(data);
+
+ setDataAndUpdate(newStr.impl(), m_data->length(), 0);
+
+ // FIXME: Should we call textInserted here?
}
void CharacterData::insertData(unsigned offset, const String& data, ExceptionCode& ec)
@@ -101,17 +85,8 @@ void CharacterData::insertData(unsigned offset, const String& data, ExceptionCod
String newStr = m_data;
newStr.insert(data, offset);
- RefPtr<StringImpl> oldStr = m_data;
- m_data = newStr.impl();
+ setDataAndUpdate(newStr.impl(), offset, 0);
- if ((!renderer() || !rendererIsNeeded(renderer()->style())) && attached()) {
- detach();
- attach();
- } else if (renderer())
- toRenderText(renderer())->setTextWithOffset(m_data, offset, 0);
-
- dispatchModifiedEvent(oldStr.get());
-
document()->textInserted(this, offset, data.length());
}
@@ -130,16 +105,7 @@ void CharacterData::deleteData(unsigned offset, unsigned count, ExceptionCode& e
String newStr = m_data;
newStr.remove(offset, realCount);
- RefPtr<StringImpl> oldStr = m_data;
- m_data = newStr.impl();
-
- if ((!renderer() || !rendererIsNeeded(renderer()->style())) && attached()) {
- detach();
- attach();
- } else if (renderer())
- toRenderText(renderer())->setTextWithOffset(m_data, offset, count);
-
- dispatchModifiedEvent(oldStr.get());
+ setDataAndUpdate(newStr.impl(), offset, count);
document()->textRemoved(this, offset, realCount);
}
@@ -160,17 +126,8 @@ void CharacterData::replaceData(unsigned offset, unsigned count, const String& d
newStr.remove(offset, realCount);
newStr.insert(data, offset);
- RefPtr<StringImpl> oldStr = m_data;
- m_data = newStr.impl();
+ setDataAndUpdate(newStr.impl(), offset, count);
- if ((!renderer() || !rendererIsNeeded(renderer()->style())) && attached()) {
- detach();
- attach();
- } else if (renderer())
- toRenderText(renderer())->setTextWithOffset(m_data, offset, count);
-
- dispatchModifiedEvent(oldStr.get());
-
// update the markers for spell checking and grammar checking
document()->textRemoved(this, offset, realCount);
document()->textInserted(this, offset, data.length());
@@ -191,12 +148,29 @@ void CharacterData::setNodeValue(const String& nodeValue, ExceptionCode& ec)
setData(nodeValue, ec);
}
-void CharacterData::dispatchModifiedEvent(StringImpl* prevValue)
+void CharacterData::setDataAndUpdate(PassRefPtr<StringImpl> newData, unsigned offsetOfReplacedData, unsigned lengthOfReplacedData)
+{
+ RefPtr<StringImpl> oldData = m_data;
+ m_data = newData;
+ updateRenderer(offsetOfReplacedData, lengthOfReplacedData);
+ dispatchModifiedEvent(oldData.get());
+}
+
+void CharacterData::updateRenderer(unsigned offsetOfReplacedData, unsigned lengthOfReplacedData)
+{
+ if ((!renderer() || !rendererIsNeeded(renderer()->style())) && attached()) {
+ detach();
+ attach();
+ } else if (renderer())
+ toRenderText(renderer())->setTextWithOffset(m_data, offsetOfReplacedData, lengthOfReplacedData);
+}
+
+void CharacterData::dispatchModifiedEvent(StringImpl* oldData)
{
if (parentNode())
parentNode()->childrenChanged();
if (document()->hasListenerType(Document::DOMCHARACTERDATAMODIFIED_LISTENER))
- dispatchEvent(MutationEvent::create(eventNames().DOMCharacterDataModifiedEvent, true, 0, prevValue, m_data));
+ dispatchEvent(MutationEvent::create(eventNames().DOMCharacterDataModifiedEvent, true, 0, oldData, m_data));
dispatchSubtreeModifiedEvent();
#if ENABLE(INSPECTOR)
InspectorInstrumentation::characterDataModified(document(), this);
diff --git a/WebCore/dom/CharacterData.h b/WebCore/dom/CharacterData.h
index 94e812b..32856d1 100644
--- a/WebCore/dom/CharacterData.h
+++ b/WebCore/dom/CharacterData.h
@@ -64,9 +64,9 @@ private:
virtual bool isCharacterDataNode() const { return true; }
virtual int maxCharacterOffset() const;
virtual bool offsetInCharacters() const;
-
+ void setDataAndUpdate(PassRefPtr<StringImpl>, unsigned offsetOfReplacedData, unsigned lengthOfReplacedData);
+ void updateRenderer(unsigned offsetOfReplacedData, unsigned lengthOfReplacedData);
void checkCharDataOperation(unsigned offset, ExceptionCode&);
- PassRefPtr<StringImpl> appendDataCommon(const String&);
RefPtr<StringImpl> m_data;
};
diff --git a/WebCore/dom/CheckedRadioButtons.h b/WebCore/dom/CheckedRadioButtons.h
index de7b712..0fa457a 100644
--- a/WebCore/dom/CheckedRadioButtons.h
+++ b/WebCore/dom/CheckedRadioButtons.h
@@ -27,8 +27,8 @@
namespace WebCore {
-class HTMLInputElement;
class HTMLFormControlElement;
+class HTMLInputElement;
class CheckedRadioButtons {
public:
diff --git a/WebCore/dom/ClientRect.cpp b/WebCore/dom/ClientRect.cpp
index c69a2ab..b132222 100644
--- a/WebCore/dom/ClientRect.cpp
+++ b/WebCore/dom/ClientRect.cpp
@@ -38,4 +38,9 @@ ClientRect::ClientRect(const IntRect& rect)
{
}
+ClientRect::ClientRect(const FloatRect& rect)
+ : m_rect(rect)
+{
+}
+
} // namespace WebCore
diff --git a/WebCore/dom/ClientRect.h b/WebCore/dom/ClientRect.h
index 349ea85..f9acef0 100644
--- a/WebCore/dom/ClientRect.h
+++ b/WebCore/dom/ClientRect.h
@@ -39,6 +39,7 @@ namespace WebCore {
public:
static PassRefPtr<ClientRect> create() { return adoptRef(new ClientRect); }
static PassRefPtr<ClientRect> create(const IntRect& rect) { return adoptRef(new ClientRect(rect)); }
+ static PassRefPtr<ClientRect> create(const FloatRect& rect) { return adoptRef(new ClientRect(rect)); }
float top() const { return m_rect.y(); }
float right() const { return m_rect.right(); }
@@ -50,6 +51,7 @@ namespace WebCore {
private:
ClientRect();
ClientRect(const IntRect&);
+ ClientRect(const FloatRect&);
FloatRect m_rect;
};
diff --git a/WebCore/dom/ContainerNode.cpp b/WebCore/dom/ContainerNode.cpp
index e158828..bc881c6 100644
--- a/WebCore/dom/ContainerNode.cpp
+++ b/WebCore/dom/ContainerNode.cpp
@@ -379,10 +379,14 @@ static void willRemoveChildren(ContainerNode* container)
container->document()->nodeChildrenWillBeRemoved(container);
container->document()->incDOMTreeVersion();
- // FIXME: Adding new children from event handlers can cause an infinite loop here.
- for (RefPtr<Node> child = container->firstChild(); child; child = child->nextSibling()) {
+ NodeVector children;
+ for (Node* n = container->firstChild(); n; n = n->nextSibling())
+ children.append(n);
+
+ for (NodeVector::const_iterator it = children.begin(); it != children.end(); it++) {
+ Node* child = it->get();
// fire removed from document mutation events.
- dispatchChildRemovalEvents(child.get());
+ dispatchChildRemovalEvents(child);
child->willRemove();
}
}
@@ -1027,12 +1031,12 @@ static void dispatchChildInsertionEvents(Node* child)
RefPtr<Document> document = child->document();
if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
- c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
+ c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
// dispatch the DOMNodeInsertedIntoDocument event to all descendants
if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) {
for (; c; c = c->traverseNextNode(child))
- c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false));
+ c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false));
}
}
@@ -1049,12 +1053,12 @@ static void dispatchChildRemovalEvents(Node* child)
// dispatch pre-removal mutation events
if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER))
- c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode()));
+ c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode()));
// dispatch the DOMNodeRemovedFromDocument event to all descendants
if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) {
for (; c; c = c->traverseNextNode(child))
- c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false));
+ c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false));
}
}
diff --git a/WebCore/dom/DOMAllInOne.cpp b/WebCore/dom/DOMAllInOne.cpp
index 2f3510d..aefc27a 100644
--- a/WebCore/dom/DOMAllInOne.cpp
+++ b/WebCore/dom/DOMAllInOne.cpp
@@ -71,6 +71,7 @@
#include "Event.cpp"
#include "EventContext.cpp"
#include "EventNames.cpp"
+#include "EventQueue.cpp"
#include "EventTarget.cpp"
#include "ExceptionBase.cpp"
#include "ExceptionCode.cpp"
@@ -100,6 +101,7 @@
#include "ProgressEvent.cpp"
#include "Range.cpp"
#include "RegisteredEventListener.cpp"
+#include "ScopedEventQueue.cpp"
#include "ScriptElement.cpp"
#include "ScriptExecutionContext.cpp"
#include "ScriptableDocumentParser.cpp"
diff --git a/WebCore/dom/DeviceMotionController.cpp b/WebCore/dom/DeviceMotionController.cpp
index 28e201e..3385167 100644
--- a/WebCore/dom/DeviceMotionController.cpp
+++ b/WebCore/dom/DeviceMotionController.cpp
@@ -54,7 +54,7 @@ void DeviceMotionController::timerFired(Timer<DeviceMotionController>* timer)
RefPtr<DeviceMotionData> deviceMotionData = m_client ? m_client->currentDeviceMotion() : DeviceMotionData::create();
RefPtr<DeviceMotionEvent> event = DeviceMotionEvent::create(eventNames().devicemotionEvent, deviceMotionData.get());
- Vector<RefPtr<DOMWindow> > listenersVector;
+ Vector<DOMWindow*> listenersVector;
copyToVector(m_newListeners, listenersVector);
m_newListeners.clear();
for (size_t i = 0; i < listenersVector.size(); ++i)
@@ -100,7 +100,7 @@ void DeviceMotionController::removeAllListeners(DOMWindow* window)
void DeviceMotionController::didChangeDeviceMotion(DeviceMotionData* deviceMotionData)
{
RefPtr<DeviceMotionEvent> event = DeviceMotionEvent::create(eventNames().devicemotionEvent, deviceMotionData);
- Vector<RefPtr<DOMWindow> > listenersVector;
+ Vector<DOMWindow*> listenersVector;
copyToVector(m_listeners, listenersVector);
for (size_t i = 0; i < listenersVector.size(); ++i)
listenersVector[i]->dispatchEvent(event);
diff --git a/WebCore/dom/DeviceMotionController.h b/WebCore/dom/DeviceMotionController.h
index 80c9d94..70c948e 100644
--- a/WebCore/dom/DeviceMotionController.h
+++ b/WebCore/dom/DeviceMotionController.h
@@ -52,9 +52,9 @@ private:
void timerFired(Timer<DeviceMotionController>*);
DeviceMotionClient* m_client;
- typedef HashCountedSet<RefPtr<DOMWindow> > ListenersCountedSet;
+ typedef HashCountedSet<DOMWindow*> ListenersCountedSet;
ListenersCountedSet m_listeners;
- typedef HashSet<RefPtr<DOMWindow> > ListenersSet;
+ typedef HashSet<DOMWindow*> ListenersSet;
ListenersSet m_newListeners;
Timer<DeviceMotionController> m_timer;
};
diff --git a/WebCore/dom/DeviceOrientationController.cpp b/WebCore/dom/DeviceOrientationController.cpp
index da42bec..60fcf13 100644
--- a/WebCore/dom/DeviceOrientationController.cpp
+++ b/WebCore/dom/DeviceOrientationController.cpp
@@ -54,7 +54,7 @@ void DeviceOrientationController::timerFired(Timer<DeviceOrientationController>*
RefPtr<DeviceOrientation> orientation = m_client->lastOrientation();
RefPtr<DeviceOrientationEvent> event = DeviceOrientationEvent::create(eventNames().deviceorientationEvent, orientation.get());
- Vector<RefPtr<DOMWindow> > listenersVector;
+ Vector<DOMWindow*> listenersVector;
copyToVector(m_newListeners, listenersVector);
m_newListeners.clear();
for (size_t i = 0; i < listenersVector.size(); ++i)
@@ -102,7 +102,7 @@ void DeviceOrientationController::removeAllListeners(DOMWindow* window)
void DeviceOrientationController::didChangeDeviceOrientation(DeviceOrientation* orientation)
{
RefPtr<DeviceOrientationEvent> event = DeviceOrientationEvent::create(eventNames().deviceorientationEvent, orientation);
- Vector<RefPtr<DOMWindow> > listenersVector;
+ Vector<DOMWindow*> listenersVector;
copyToVector(m_listeners, listenersVector);
for (size_t i = 0; i < listenersVector.size(); ++i)
listenersVector[i]->dispatchEvent(event);
diff --git a/WebCore/dom/DeviceOrientationController.h b/WebCore/dom/DeviceOrientationController.h
index 5e06771..4fa9006 100644
--- a/WebCore/dom/DeviceOrientationController.h
+++ b/WebCore/dom/DeviceOrientationController.h
@@ -55,9 +55,9 @@ private:
Page* m_page;
DeviceOrientationClient* m_client;
- typedef HashCountedSet<RefPtr<DOMWindow> > ListenersCountedSet;
+ typedef HashCountedSet<DOMWindow*> ListenersCountedSet;
ListenersCountedSet m_listeners;
- typedef HashSet<RefPtr<DOMWindow> > ListenersSet;
+ typedef HashSet<DOMWindow*> ListenersSet;
ListenersSet m_newListeners;
Timer<DeviceOrientationController> m_timer;
};
diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp
index f01ae32..3c749f2 100644
--- a/WebCore/dom/Document.cpp
+++ b/WebCore/dom/Document.cpp
@@ -59,8 +59,10 @@
#include "EventHandler.h"
#include "EventListener.h"
#include "EventNames.h"
+#include "EventQueue.h"
#include "ExceptionCode.h"
#include "FocusController.h"
+#include "FormAssociatedElement.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameLoaderClient.h"
@@ -419,7 +421,7 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML, con
, m_normalWorldWrapperCache(0)
#endif
, m_usingGeolocation(false)
- , m_pendingEventTimer(this, &Document::pendingEventTimerFired)
+ , m_eventQueue(adoptPtr(new EventQueue))
#if ENABLE(WML)
, m_containsWMLContent(false)
#endif
@@ -1724,7 +1726,7 @@ PassRefPtr<RenderStyle> Document::styleForElementIgnoringPendingStylesheets(Elem
bool oldIgnore = m_ignorePendingStylesheets;
m_ignorePendingStylesheets = true;
- RefPtr<RenderStyle> style = styleSelector()->styleForElement(element, element->parent() ? element->parent()->computedStyle() : 0);
+ RefPtr<RenderStyle> style = styleSelector()->styleForElement(element, element->parentNode() ? element->parentNode()->computedStyle() : 0);
m_ignorePendingStylesheets = oldIgnore;
return style.release();
}
@@ -2671,7 +2673,7 @@ void Document::processHttpEquiv(const String& equiv, const String& content)
FrameLoader* frameLoader = frame->loader();
if (frameLoader->shouldInterruptLoadForXFrameOptions(content, url())) {
frameLoader->stopAllLoaders();
- frame->navigationScheduler()->scheduleLocationChange(blankURL(), String());
+ frame->navigationScheduler()->scheduleLocationChange(securityOrigin(), blankURL(), String());
DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to display document because display forbidden by X-Frame-Options.\n"));
frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
@@ -2990,9 +2992,6 @@ void Document::styleSelectorChanged(StyleSelectorUpdateFlag updateFlag)
void Document::addStyleSheetCandidateNode(Node* node, bool createdByParser)
{
- if (!node->inDocument())
- return;
-
// Until the <body> exists, we have no choice but to compare document positions,
// since styles outside of the body and head continue to be shunted into the head
// (and thus can shift to end up before dynamically added DOM content that is also
@@ -3164,24 +3163,24 @@ void Document::removeFocusedNodeOfSubtree(Node* node, bool amongChildrenOnly)
void Document::hoveredNodeDetached(Node* node)
{
- if (!m_hoverNode || (node != m_hoverNode && (!m_hoverNode->isTextNode() || node != m_hoverNode->parent())))
+ if (!m_hoverNode || (node != m_hoverNode && (!m_hoverNode->isTextNode() || node != m_hoverNode->parentNode())))
return;
- m_hoverNode = node->parent();
+ m_hoverNode = node->parentNode();
while (m_hoverNode && !m_hoverNode->renderer())
- m_hoverNode = m_hoverNode->parent();
+ m_hoverNode = m_hoverNode->parentNode();
if (frame())
frame()->eventHandler()->scheduleHoverStateUpdate();
}
void Document::activeChainNodeDetached(Node* node)
{
- if (!m_activeNode || (node != m_activeNode && (!m_activeNode->isTextNode() || node != m_activeNode->parent())))
+ if (!m_activeNode || (node != m_activeNode && (!m_activeNode->isTextNode() || node != m_activeNode->parentNode())))
return;
- m_activeNode = node->parent();
+ m_activeNode = node->parentNode();
while (m_activeNode && !m_activeNode->renderer())
- m_activeNode = m_activeNode->parent();
+ m_activeNode = m_activeNode->parentNode();
}
#if ENABLE(DASHBOARD_SUPPORT)
@@ -3537,23 +3536,10 @@ void Document::dispatchWindowLoadEvent()
domWindow->dispatchLoadEvent();
}
-void Document::enqueueEvent(PassRefPtr<Event> event)
-{
- m_pendingEventQueue.append(event);
- if (!m_pendingEventTimer.isActive())
- m_pendingEventTimer.startOneShot(0);
-}
-
-void Document::pendingEventTimerFired(Timer<Document>*)
+void Document::enqueueWindowEvent(PassRefPtr<Event> event)
{
- ASSERT(!m_pendingEventTimer.isActive());
- Vector<RefPtr<Event> > eventQueue;
- eventQueue.swap(m_pendingEventQueue);
-
- typedef Vector<RefPtr<Event> >::const_iterator Iterator;
- Iterator end = eventQueue.end();
- for (Iterator it = eventQueue.begin(); it != end; ++it)
- dispatchWindowEvent(*it);
+ event->setTarget(domWindow());
+ m_eventQueue->enqueueEvent(event);
}
PassRefPtr<Event> Document::createEvent(const String& eventType, ExceptionCode& ec)
@@ -4284,11 +4270,11 @@ void Document::finishedParsing()
ASSERT(!scriptableDocumentParser() || !m_parser->isParsing());
ASSERT(!scriptableDocumentParser() || m_readyState != Loading);
setParsing(false);
- if (!m_documentTiming.domContentLoadedStart)
- m_documentTiming.domContentLoadedStart = currentTime();
+ if (!m_documentTiming.domContentLoadedEventStart)
+ m_documentTiming.domContentLoadedEventStart = currentTime();
dispatchEvent(Event::create(eventNames().DOMContentLoadedEvent, true, false));
- if (!m_documentTiming.domContentLoadedEnd)
- m_documentTiming.domContentLoadedEnd = currentTime();
+ if (!m_documentTiming.domContentLoadedEventEnd)
+ m_documentTiming.domContentLoadedEventEnd = currentTime();
if (Frame* f = frame()) {
// FrameLoader::finishedParsing() might end up calling Document::implicitClose() if all
@@ -4465,23 +4451,23 @@ void Document::setIconURL(const String& iconURL, const String& type)
f->loader()->setIconURL(m_iconURL);
}
-void Document::registerFormElementWithFormAttribute(Element* control)
+void Document::registerFormElementWithFormAttribute(FormAssociatedElement* element)
{
- ASSERT(control->fastHasAttribute(formAttr));
- m_formElementsWithFormAttribute.add(control);
+ ASSERT(toHTMLElement(element)->fastHasAttribute(formAttr));
+ m_formElementsWithFormAttribute.add(element);
}
-void Document::unregisterFormElementWithFormAttribute(Element* control)
+void Document::unregisterFormElementWithFormAttribute(FormAssociatedElement* element)
{
- m_formElementsWithFormAttribute.remove(control);
+ m_formElementsWithFormAttribute.remove(element);
}
void Document::resetFormElementsOwner(HTMLFormElement* form)
{
- typedef FormElementListHashSet::iterator Iterator;
+ typedef FormAssociatedElementListHashSet::iterator Iterator;
Iterator end = m_formElementsWithFormAttribute.end();
for (Iterator it = m_formElementsWithFormAttribute.begin(); it != end; ++it)
- static_cast<HTMLFormControlElement*>(*it)->resetFormOwner(form);
+ (*it)->resetFormOwner(form);
}
void Document::setUseSecureKeyboardEntryWhenActive(bool usesSecureKeyboard)
@@ -4572,11 +4558,11 @@ void Document::setSecurityOrigin(SecurityOrigin* securityOrigin)
#if ENABLE(DATABASE)
-bool Document::isDatabaseReadOnly() const
+bool Document::allowDatabaseAccess() const
{
if (!page() || page()->settings()->privateBrowsingEnabled())
- return true;
- return false;
+ return false;
+ return true;
}
void Document::databaseExceededQuota(const String& name)
@@ -4815,7 +4801,7 @@ void Document::enqueuePageshowEvent(PageshowEventPersistence persisted)
void Document::enqueueHashchangeEvent(const String& oldURL, const String& newURL)
{
- enqueueEvent(HashChangeEvent::create(oldURL, newURL));
+ enqueueWindowEvent(HashChangeEvent::create(oldURL, newURL));
}
void Document::enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject)
diff --git a/WebCore/dom/Document.h b/WebCore/dom/Document.h
index 0aba06c..7f6c9d7 100644
--- a/WebCore/dom/Document.h
+++ b/WebCore/dom/Document.h
@@ -76,6 +76,8 @@ class Element;
class EntityReference;
class Event;
class EventListener;
+class EventQueue;
+class FormAssociatedElement;
class Frame;
class FrameView;
class HTMLCanvasElement;
@@ -490,8 +492,8 @@ public:
bool hasStateForNewFormElements() const;
bool takeStateForFormElement(AtomicStringImpl* name, AtomicStringImpl* type, String& state);
- void registerFormElementWithFormAttribute(Element*);
- void unregisterFormElementWithFormAttribute(Element*);
+ void registerFormElementWithFormAttribute(FormAssociatedElement*);
+ void unregisterFormElementWithFormAttribute(FormAssociatedElement*);
void resetFormElementsOwner(HTMLFormElement*);
FrameView* view() const; // can be NULL
@@ -1017,7 +1019,7 @@ public:
bool processingLoadEvent() const { return m_processingLoadEvent; }
#if ENABLE(DATABASE)
- virtual bool isDatabaseReadOnly() const;
+ virtual bool allowDatabaseAccess() const;
virtual void databaseExceededQuota(const String& name);
#endif
@@ -1038,10 +1040,11 @@ public:
bool containsValidityStyleRules() const { return m_containsValidityStyleRules; }
void setContainsValidityStyleRules() { m_containsValidityStyleRules = true; }
- void enqueueEvent(PassRefPtr<Event>);
+ void enqueueWindowEvent(PassRefPtr<Event>);
void enqueuePageshowEvent(PageshowEventPersistence);
void enqueueHashchangeEvent(const String& oldURL, const String& newURL);
void enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject);
+ EventQueue* eventQueue() const { return m_eventQueue.get(); }
void addMediaCanStartListener(MediaCanStartListener*);
void removeMediaCanStartListener(MediaCanStartListener*);
@@ -1076,6 +1079,8 @@ public:
bool mayCauseFlashOfUnstyledContent() const;
+ void initDNSPrefetch();
+
protected:
Document(Frame*, const KURL& url, bool isXHTML, bool isHTML, const KURL& baseURL = KURL());
@@ -1129,8 +1134,6 @@ private:
virtual const KURL& virtualURL() const; // Same as url(), but needed for ScriptExecutionContext to implement it without a performance loss for direct calls.
virtual KURL virtualCompleteURL(const String&) const; // Same as completeURL() for the same reason as above.
- void initDNSPrefetch();
-
String encoding() const;
void updateTitle();
@@ -1141,8 +1144,6 @@ private:
void createStyleSelector();
- void pendingEventTimerFired(Timer<Document>*);
-
PassRefPtr<NodeList> handleZeroPadding(const HitTestRequest&, HitTestResult&) const;
void loadEventDelayTimerFired(Timer<Document>*);
@@ -1174,10 +1175,10 @@ private:
RefPtr<DocumentType> m_docType;
mutable RefPtr<DOMImplementation> m_implementation;
- // Track the number of currently loading top-level stylesheets. Sheets
- // loaded using the @import directive are not included in this count.
+ // Track the number of currently loading top-level stylesheets needed for rendering.
+ // Sheets loaded using the @import directive are not included in this count.
// We use this count of pending sheets to detect when we can begin attaching
- // elements.
+ // elements and when it is safe to execute scripts.
int m_pendingStylesheets;
// But sometimes you need to ignore pending stylesheet count to
@@ -1229,7 +1230,8 @@ private:
typedef ListHashSet<Element*, 64> FormElementListHashSet;
FormElementListHashSet m_formElementsWithState;
- FormElementListHashSet m_formElementsWithFormAttribute;
+ typedef ListHashSet<FormAssociatedElement*, 32> FormAssociatedElementListHashSet;
+ FormAssociatedElementListHashSet m_formElementsWithFormAttribute;
typedef HashMap<FormElementKey, Vector<String>, FormElementKeyHash, FormElementKeyHashTraits> FormElementStateMap;
FormElementStateMap m_stateForNewFormElements;
@@ -1369,9 +1371,8 @@ private:
#endif
bool m_usingGeolocation;
-
- Timer<Document> m_pendingEventTimer;
- Vector<RefPtr<Event> > m_pendingEventQueue;
+
+ OwnPtr<EventQueue> m_eventQueue;
#if ENABLE(WML)
bool m_containsWMLContent;
diff --git a/WebCore/dom/DocumentMarkerController.cpp b/WebCore/dom/DocumentMarkerController.cpp
index 3b7abcc..5f88631 100644
--- a/WebCore/dom/DocumentMarkerController.cpp
+++ b/WebCore/dom/DocumentMarkerController.cpp
@@ -567,4 +567,31 @@ bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTy
return false;
}
+#ifndef NDEBUG
+void DocumentMarkerController::showMarkers() const
+{
+ fprintf(stderr, "%d nodes have markers:\n", m_markers.size());
+ MarkerMap::const_iterator end = m_markers.end();
+ for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
+ Node* node = nodeIterator->first.get();
+ fprintf(stderr, "%p", node);
+ MarkerMapVectorPair* vectorPair = nodeIterator->second;
+ Vector<DocumentMarker>& markers = vectorPair->first;
+ unsigned markerCount = markers.size();
+ for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex)
+ fprintf(stderr, " %d:[%d:%d](%d)", markers[markerIndex].type, markers[markerIndex].startOffset, markers[markerIndex].endOffset, markers[markerIndex].activeMatch);
+ fprintf(stderr, "\n");
+ }
+}
+#endif
+
} // namespace WebCore
+
+
+#ifndef NDEBUG
+void showDocumentMarkers(const WebCore::DocumentMarkerController* controller)
+{
+ if (controller)
+ controller->showMarkers();
+}
+#endif
diff --git a/WebCore/dom/DocumentMarkerController.h b/WebCore/dom/DocumentMarkerController.h
index 96fb7f3..83177fc 100644
--- a/WebCore/dom/DocumentMarkerController.h
+++ b/WebCore/dom/DocumentMarkerController.h
@@ -62,6 +62,10 @@ public:
Vector<DocumentMarker> markersForNode(Node*);
Vector<IntRect> renderedRectsForMarkers(DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
+#ifndef NDEBUG
+ void showMarkers() const;
+#endif
+
private:
typedef std::pair<Vector<DocumentMarker>, Vector<IntRect> > MarkerMapVectorPair;
typedef HashMap<RefPtr<Node>, MarkerMapVectorPair*> MarkerMap;
@@ -71,4 +75,8 @@ private:
} // namespace WebCore
+#ifndef NDEBUG
+void showDocumentMarkers(const WebCore::DocumentMarkerController*);
+#endif
+
#endif // DocumentMarkerController_h
diff --git a/WebCore/dom/DocumentTiming.h b/WebCore/dom/DocumentTiming.h
index 7abc219..89e2fb9 100644
--- a/WebCore/dom/DocumentTiming.h
+++ b/WebCore/dom/DocumentTiming.h
@@ -32,16 +32,16 @@ struct DocumentTiming {
DocumentTiming()
: domLoading(0.0)
, domInteractive(0.0)
- , domContentLoadedStart(0.0)
- , domContentLoadedEnd(0.0)
+ , domContentLoadedEventStart(0.0)
+ , domContentLoadedEventEnd(0.0)
, domComplete(0.0)
{
}
double domLoading;
double domInteractive;
- double domContentLoadedStart;
- double domContentLoadedEnd;
+ double domContentLoadedEventStart;
+ double domContentLoadedEventEnd;
double domComplete;
};
diff --git a/WebCore/dom/Element.cpp b/WebCore/dom/Element.cpp
index 6c0e291..68c6b1d 100644
--- a/WebCore/dom/Element.cpp
+++ b/WebCore/dom/Element.cpp
@@ -546,16 +546,16 @@ PassRefPtr<ClientRect> Element::getBoundingClientRect() const
if (quads.isEmpty())
return ClientRect::create();
- IntRect result = quads[0].enclosingBoundingBox();
+ FloatRect result = quads[0].boundingBox();
for (size_t i = 1; i < quads.size(); ++i)
- result.unite(quads[i].enclosingBoundingBox());
+ result.unite(quads[i].boundingBox());
if (FrameView* view = document()->view()) {
IntRect visibleContentRect = view->visibleContentRect();
result.move(-visibleContentRect.x(), -visibleContentRect.y());
}
- adjustIntRectForAbsoluteZoom(result, renderer());
+ adjustFloatRectForAbsoluteZoom(result, renderer());
return ClientRect::create(result);
}
@@ -703,6 +703,8 @@ void Element::updateAfterAttributeChanged(Attribute* attr)
document()->axObjectCache()->handleAriaExpandedChange(renderer());
else if (attrName == aria_hiddenAttr)
document()->axObjectCache()->childrenChanged(renderer());
+ else if (attrName == aria_invalidAttr)
+ document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXInvalidStatusChanged, true);
}
void Element::recalcStyleIfNeededAfterAttributeChanged(Attribute* attr)
@@ -856,6 +858,8 @@ void Element::insertedIntoDocument()
// need to do superclass processing first so inDocument() is true
// by the time we reach updateId
ContainerNode::insertedIntoDocument();
+ if (Node* shadow = shadowRoot())
+ shadow->insertedIntoDocument();
if (hasID()) {
if (m_attributeMap) {
@@ -877,6 +881,26 @@ void Element::removedFromDocument()
}
ContainerNode::removedFromDocument();
+ if (Node* shadow = shadowRoot())
+ shadow->removedFromDocument();
+}
+
+void Element::insertedIntoTree(bool deep)
+{
+ ContainerNode::insertedIntoTree(deep);
+ if (!deep)
+ return;
+ if (Node* shadow = shadowRoot())
+ shadow->insertedIntoTree(true);
+}
+
+void Element::removedFromTree(bool deep)
+{
+ ContainerNode::removedFromTree(deep);
+ if (!deep)
+ return;
+ if (Node* shadow = shadowRoot())
+ shadow->removedFromTree(true);
}
void Element::attach()
@@ -886,6 +910,8 @@ void Element::attach()
createRendererIfNeeded();
ContainerNode::attach();
+ if (Node* shadow = shadowRoot())
+ shadow->attach();
if (hasRareData()) {
ElementRareData* data = rareData();
if (data->needsFocusAppearanceUpdateSoonAfterAttach()) {
@@ -907,6 +933,8 @@ void Element::detach()
if (hasRareData())
rareData()->resetComputedStyle();
ContainerNode::detach();
+ if (Node* shadow = shadowRoot())
+ shadow->detach();
RenderWidget::resumeWidgetHierarchyUpdates();
}
@@ -967,15 +995,10 @@ void Element::recalcStyle(StyleChange change)
{
// Ref currentStyle in case it would otherwise be deleted when setRenderStyle() is called.
RefPtr<RenderStyle> currentStyle(renderStyle());
- bool hasParentStyle = parentNode() ? parentNode()->renderStyle() : false;
+ bool hasParentStyle = parentOrHostNode() ? parentOrHostNode()->renderStyle() : false;
bool hasPositionalRules = needsStyleRecalc() && currentStyle && currentStyle->childrenAffectedByPositionalRules();
bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules();
-#if ENABLE(SVG)
- if (!hasParentStyle && isShadowNode() && isSVGElement())
- hasParentStyle = true;
-#endif
-
if ((change > NoChange || needsStyleRecalc())) {
#ifdef ANDROID_STYLE_VERSION
RefPtr<RenderStyle> newStyle = document()->styleForElementIgnoringPendingStylesheets(this);
@@ -1058,11 +1081,43 @@ void Element::recalcStyle(StyleChange change)
if (n->isElementNode())
forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
}
+ // FIXME: This does not care about sibling combinators. Will be necessary in XBL2 world.
+ if (Node* shadow = shadowRoot()) {
+ if (change >= Inherit || shadow->isTextNode() || shadow->childNeedsStyleRecalc() || shadow->needsStyleRecalc())
+ shadow->recalcStyle(change);
+ }
clearNeedsStyleRecalc();
clearChildNeedsStyleRecalc();
}
+Node* Element::shadowRoot()
+{
+ return hasRareData() ? rareData()->m_shadowRoot.get() : 0;
+}
+
+void Element::setShadowRoot(PassRefPtr<Node> node)
+{
+ ASSERT(node);
+
+ // FIXME: Once all instances of shadow DOM are converted to use this code, add setting of shadow host (shadowParent) on node.
+ ensureRareData()->m_shadowRoot = node;
+}
+
+void Element::clearShadowRoot()
+{
+ if (!hasRareData())
+ return;
+
+ RefPtr<Node> shadowRoot = rareData()->m_shadowRoot.release();
+ document()->removeFocusedNodeOfSubtree(shadowRoot.get());
+ // FIXME: Once all instances of shadow DOM are converted to use this code, add clearing of shadow host (shadowParent).
+ if (shadowRoot->inDocument())
+ shadowRoot->removedFromDocument();
+ else
+ shadowRoot->removedFromTree(true);
+}
+
bool Element::childTypeAllowed(NodeType type)
{
switch (type) {
@@ -1181,7 +1236,7 @@ void Element::dispatchAttrRemovalEvent(Attribute*)
if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
return;
ExceptionCode ec = 0;
- dispatchEvent(MutationEvent::create(DOMAttrModifiedEvent, true, attr, attr->value(),
+ dispatchScopedEvent(MutationEvent::create(DOMAttrModifiedEvent, true, attr, attr->value(),
attr->value(), document()->attrName(attr->id()), MutationEvent::REMOVAL), ec);
#endif
}
@@ -1194,7 +1249,7 @@ void Element::dispatchAttrAdditionEvent(Attribute*)
if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
return;
ExceptionCode ec = 0;
- dispatchEvent(MutationEvent::create(DOMAttrModifiedEvent, true, attr, attr->value(),
+ dispatchScopedEvent(MutationEvent::create(DOMAttrModifiedEvent, true, attr, attr->value(),
attr->value(), document()->attrName(attr->id()), MutationEvent::ADDITION), ec);
#endif
}
diff --git a/WebCore/dom/Element.h b/WebCore/dom/Element.h
index 7d4b94c..8432f82 100644
--- a/WebCore/dom/Element.h
+++ b/WebCore/dom/Element.h
@@ -225,6 +225,10 @@ public:
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
virtual void recalcStyle(StyleChange = NoChange);
+ Node* shadowRoot();
+ void setShadowRoot(PassRefPtr<Node>);
+ void clearShadowRoot();
+
RenderStyle* computedStyle(PseudoId = NOPSEUDO);
AtomicString computeInheritedLanguage() const;
@@ -337,6 +341,8 @@ protected:
virtual void insertedIntoDocument();
virtual void removedFromDocument();
+ virtual void insertedIntoTree(bool);
+ virtual void removedFromTree(bool);
virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
// The implementation of Element::attributeChanged() calls the following two functions.
diff --git a/WebCore/dom/ElementRareData.h b/WebCore/dom/ElementRareData.h
index 06bfe0c..f7f30bb 100644
--- a/WebCore/dom/ElementRareData.h
+++ b/WebCore/dom/ElementRareData.h
@@ -41,6 +41,7 @@ public:
IntSize m_minimumSizeForResizing;
RefPtr<RenderStyle> m_computedStyle;
+ RefPtr<Node> m_shadowRoot;
OwnPtr<DatasetDOMStringMap> m_datasetDOMStringMap;
OwnPtr<ClassList> m_classList;
diff --git a/WebCore/dom/EventQueue.cpp b/WebCore/dom/EventQueue.cpp
new file mode 100644
index 0000000..27cd802
--- /dev/null
+++ b/WebCore/dom/EventQueue.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "EventQueue.h"
+
+#include "DOMWindow.h"
+#include "Document.h"
+#include "Event.h"
+#include "EventNames.h"
+
+namespace WebCore {
+
+EventQueue::EventQueue()
+ : m_pendingEventTimer(this, &EventQueue::pendingEventTimerFired)
+{
+}
+
+void EventQueue::enqueueEvent(PassRefPtr<Event> event)
+{
+ ASSERT(event->target()->toNode() || event->target()->toDOMWindow());
+ m_queuedEvents.append(event);
+
+ if (!m_pendingEventTimer.isActive())
+ m_pendingEventTimer.startOneShot(0);
+}
+
+void EventQueue::pendingEventTimerFired(Timer<EventQueue>*)
+{
+ ASSERT(!m_pendingEventTimer.isActive());
+
+ Vector<RefPtr<Event> > queuedEvents;
+ queuedEvents.swap(m_queuedEvents);
+
+ for (size_t i = 0; i < queuedEvents.size(); i++)
+ dispatchEvent(queuedEvents[i].release());
+}
+
+void EventQueue::dispatchEvent(PassRefPtr<Event> event)
+{
+ EventTarget* eventTarget = event->target();
+ if (eventTarget->toNode())
+ eventTarget->dispatchEvent(event);
+ else if (eventTarget->toDOMWindow())
+ eventTarget->toDOMWindow()->dispatchEvent(event, 0);
+ else
+ ASSERT_NOT_REACHED();
+}
+
+}
diff --git a/WebCore/dom/EventQueue.h b/WebCore/dom/EventQueue.h
new file mode 100644
index 0000000..8dd7ec9
--- /dev/null
+++ b/WebCore/dom/EventQueue.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 EventQueue_h
+#define EventQueue_h
+
+#include "Timer.h"
+#include <wtf/Noncopyable.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Event;
+class Node;
+
+class EventQueue {
+ WTF_MAKE_NONCOPYABLE(EventQueue);
+
+public:
+ EventQueue();
+
+ void enqueueEvent(PassRefPtr<Event>);
+
+private:
+ void pendingEventTimerFired(Timer<EventQueue>*);
+ void dispatchEvent(PassRefPtr<Event>);
+
+ Timer<EventQueue> m_pendingEventTimer;
+ Vector<RefPtr<Event> > m_queuedEvents;
+};
+
+}
+
+#endif // EventQueue_h
diff --git a/WebCore/dom/KeyboardEvent.h b/WebCore/dom/KeyboardEvent.h
index 02f9f63..eeaef80 100644
--- a/WebCore/dom/KeyboardEvent.h
+++ b/WebCore/dom/KeyboardEvent.h
@@ -35,7 +35,7 @@ namespace WebCore {
struct KeypressCommand {
KeypressCommand() { }
KeypressCommand(const String& commandName) : commandName(commandName) { }
- KeypressCommand(const String& commandName, const String& text) : commandName(commandName), text(text) { ASSERT(commandName == "insertText:" || commandName == "insertText"); }
+ KeypressCommand(const String& commandName, const String& text) : commandName(commandName), text(text) { }
String commandName;
String text;
diff --git a/WebCore/dom/Node.cpp b/WebCore/dom/Node.cpp
index 23096df..65d09ae 100644
--- a/WebCore/dom/Node.cpp
+++ b/WebCore/dom/Node.cpp
@@ -75,6 +75,7 @@
#include "ProgressEvent.h"
#include "RegisteredEventListener.h"
#include "RenderBox.h"
+#include "ScopedEventQueue.h"
#include "ScriptController.h"
#include "SelectorNodeList.h"
#include "StaticNodeList.h"
@@ -102,6 +103,7 @@
#if ENABLE(SVG)
#include "SVGElementInstance.h"
+#include "SVGNames.h"
#include "SVGUseElement.h"
#endif
@@ -484,7 +486,22 @@ NodeRareData* Node::createRareData()
{
return new NodeRareData;
}
-
+
+Element* Node::shadowHost() const
+{
+ return toElement(shadowParentNode());
+}
+
+void Node::setShadowHost(Element* host)
+{
+ if (host)
+ setFlag(IsShadowRootFlag);
+ else
+ clearFlag(IsShadowRootFlag);
+
+ setParent(host);
+}
+
short Node::tabIndex() const
{
return hasRareData() ? rareData()->tabIndex() : 0;
@@ -670,12 +687,12 @@ void Node::deprecatedParserAddChild(PassRefPtr<Node>)
bool Node::isContentEditable() const
{
- return parent() && parent()->isContentEditable();
+ return parentOrHostNode() && parentOrHostNode()->isContentEditable();
}
bool Node::isContentRichlyEditable() const
{
- return parent() && parent()->isContentRichlyEditable();
+ return parentOrHostNode() && parentOrHostNode()->isContentRichlyEditable();
}
bool Node::shouldUseInputMethod() const
@@ -1271,7 +1288,7 @@ RenderObject * Node::nextRenderer()
{
// Avoid an O(n^2) problem with this function by not checking for nextRenderer() when the parent element hasn't even
// been attached yet.
- if (parent() && !parent()->attached())
+ if (parentOrHostNode() && !parentOrHostNode()->attached())
return 0;
for (Node *n = nextSibling(); n; n = n->nextSibling()) {
@@ -1398,7 +1415,7 @@ void Node::setRenderStyle(PassRefPtr<RenderStyle> s)
RenderStyle* Node::virtualComputedStyle(PseudoId pseudoElementSpecifier)
{
- return parent() ? parent()->computedStyle(pseudoElementSpecifier) : 0;
+ return parentOrHostNode() ? parentOrHostNode()->computedStyle(pseudoElementSpecifier) : 0;
}
int Node::maxCharacterOffset() const
@@ -1421,7 +1438,7 @@ bool Node::canStartSelection() const
if (style->userDrag() == DRAG_ELEMENT && style->userSelect() == SELECT_NONE)
return false;
}
- return parent() ? parent()->canStartSelection() : true;
+ return parentOrHostNode() ? parentOrHostNode()->canStartSelection() : true;
}
Node* Node::shadowAncestorNode()
@@ -1445,9 +1462,9 @@ Node* Node::shadowTreeRootNode()
{
Node* root = this;
while (root) {
- if (root->isShadowNode())
+ if (root->isShadowRoot())
return root;
- root = root->parentNode();
+ root = root->parentNodeGuaranteedHostFree();
}
return 0;
}
@@ -1455,7 +1472,7 @@ Node* Node::shadowTreeRootNode()
bool Node::isInShadowTree()
{
for (Node* n = this; n; n = n->parentNode())
- if (n->isShadowNode())
+ if (n->isShadowRoot())
return true;
return false;
}
@@ -2579,7 +2596,7 @@ static inline EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNo
// Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
// as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
for (Node* n = referenceNode; n; n = n->parentNode()) {
- if (!n->isShadowNode() || !n->isSVGElement())
+ if (!n->isShadowRoot() || !n->isSVGElement())
continue;
ContainerNode* shadowTreeParentElement = n->shadowParentNode();
@@ -2602,21 +2619,21 @@ void Node::getEventAncestors(Vector<EventContext>& ancestors, EventTarget* origi
Node* ancestor = this;
bool shouldSkipNextAncestor = false;
while (true) {
- if (ancestor->isShadowNode()) {
+ if (ancestor->isShadowRoot()) {
if (behavior == StayInsideShadowDOM)
return;
ancestor = ancestor->shadowParentNode();
if (!shouldSkipNextAncestor)
target = ancestor;
} else
- ancestor = ancestor->parentNode();
+ ancestor = ancestor->parentNodeGuaranteedHostFree();
if (!ancestor)
return;
#if ENABLE(SVG)
// Skip SVGShadowTreeRootElement.
- shouldSkipNextAncestor = ancestor->isSVGElement() && ancestor->isShadowNode();
+ shouldSkipNextAncestor = ancestor->isSVGElement() && ancestor->isShadowRoot();
if (shouldSkipNextAncestor)
continue;
#endif
@@ -2637,25 +2654,17 @@ bool Node::dispatchEvent(PassRefPtr<Event> prpEvent)
return dispatchGenericEvent(event.release());
}
-static const EventContext* topEventContext(const Vector<EventContext>& ancestors)
+void Node::dispatchScopedEvent(PassRefPtr<Event> event)
{
- return ancestors.isEmpty() ? 0 : &ancestors.last();
+ // We need to set the target here because it can go away by the time we actually fire the event.
+ event->setTarget(eventTargetRespectingSVGTargetRules(this));
+
+ ScopedEventQueue::instance()->enqueueEvent(event);
}
-static EventDispatchBehavior determineDispatchBehavior(Event* event)
+static const EventContext* topEventContext(const Vector<EventContext>& ancestors)
{
- // Per XBL 2.0 spec, mutation events should never cross shadow DOM boundary:
- // http://dev.w3.org/2006/xbl2/#event-flow-and-targeting-across-shadow-s
- if (event->isMutationEvent())
- return StayInsideShadowDOM;
-
- // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
- // Changing this breaks existing sites.
- // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
- if (event->type() == eventNames().selectstartEvent)
- return StayInsideShadowDOM;
-
- return RetargetEvent;
+ return ancestors.isEmpty() ? 0 : &ancestors.last();
}
bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent)
@@ -2672,7 +2681,7 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent)
RefPtr<Node> thisNode(this);
RefPtr<EventTarget> originalTarget = event->target();
Vector<EventContext> ancestors;
- getEventAncestors(ancestors, originalTarget.get(), determineDispatchBehavior(event.get()));
+ getEventAncestors(ancestors, originalTarget.get(), event->isMutationEvent() ? StayInsideShadowDOM : RetargetEvent);
WindowEventContext windowContext(event.get(), this, topEventContext(ancestors));
@@ -2767,7 +2776,7 @@ void Node::dispatchSubtreeModifiedEvent()
if (!document()->hasListenerType(Document::DOMSUBTREEMODIFIED_LISTENER))
return;
- dispatchEvent(MutationEvent::create(eventNames().DOMSubtreeModifiedEvent, true));
+ dispatchScopedEvent(MutationEvent::create(eventNames().DOMSubtreeModifiedEvent, true));
}
void Node::dispatchUIEvent(const AtomicString& eventType, int detail, PassRefPtr<Event> underlyingEvent)
@@ -2777,10 +2786,10 @@ void Node::dispatchUIEvent(const AtomicString& eventType, int detail, PassRefPtr
eventType == eventNames().DOMFocusInEvent || eventType == eventNames().DOMFocusOutEvent || eventType == eventNames().DOMActivateEvent);
bool cancelable = eventType == eventNames().DOMActivateEvent;
-
+
RefPtr<UIEvent> event = UIEvent::create(eventType, true, cancelable, document()->defaultView(), detail);
event->setUnderlyingEvent(underlyingEvent);
- dispatchEvent(event.release());
+ dispatchScopedEvent(event.release());
}
bool Node::dispatchKeyEvent(const PlatformKeyboardEvent& key)
@@ -3037,7 +3046,7 @@ void Node::defaultEventHandler(Event* event)
// This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll.
Node* startNode = this;
while (startNode && !startNode->renderer())
- startNode = startNode->parent();
+ startNode = startNode->parentOrHostNode();
if (startNode && startNode->renderer())
if (Frame* frame = document()->frame())
diff --git a/WebCore/dom/Node.h b/WebCore/dom/Node.h
index 45a8488..bd5a7c4 100644
--- a/WebCore/dom/Node.h
+++ b/WebCore/dom/Node.h
@@ -74,7 +74,7 @@ class TagNodeList;
typedef int ExceptionCode;
-const int nodeStyleChangeShift = 24;
+const int nodeStyleChangeShift = 25;
// SyntheticStyleChange means that we need to go through the entire style change logic even though
// no style property has actually changed. It is used to restructure the tree when, for instance,
@@ -138,7 +138,7 @@ public:
virtual String nodeValue() const;
virtual void setNodeValue(const String&, ExceptionCode&);
virtual NodeType nodeType() const = 0;
- ContainerNode* parentNode() const { return parent(); }
+ ContainerNode* parentNode() const;
Element* parentElement() const;
Node* previousSibling() const { return m_previous; }
Node* nextSibling() const { return m_next; }
@@ -205,13 +205,16 @@ public:
bool isCommentNode() const { return getFlag(IsCommentFlag); }
virtual bool isCharacterDataNode() const { return false; }
bool isDocumentNode() const;
- virtual bool isShadowNode() const { return false; }
- virtual ContainerNode* shadowParentNode() { return 0; }
+ bool isShadowRoot() const { return getFlag(IsShadowRootFlag); }
+ // FIXME: Eliminate all uses, fold into shadowHost.
+ ContainerNode* shadowParentNode() const;
Node* shadowAncestorNode();
Node* shadowTreeRootNode();
bool isInShadowTree();
// Node's parent or shadow tree host.
- ContainerNode* parentOrHostNode();
+ ContainerNode* parentOrHostNode() const;
+ // Use when it's guaranteed to that shadowParentNode is 0.
+ ContainerNode* parentNodeGuaranteedHostFree() const;
// Returns the enclosing event parent node (or self) that, when clicked, would trigger a navigation.
Node* enclosingLinkEventParentOrSelf();
@@ -529,7 +532,8 @@ public:
virtual void postDispatchEventHandler(Event*, void* /*dataFromPreDispatch*/) { }
using EventTarget::dispatchEvent;
- virtual bool dispatchEvent(PassRefPtr<Event>);
+ bool dispatchEvent(PassRefPtr<Event>);
+ void dispatchScopedEvent(PassRefPtr<Event>);
bool dispatchGenericEvent(PassRefPtr<Event>);
virtual void handleLocalEvents(Event*);
@@ -593,17 +597,19 @@ private:
InActiveChainFlag = 1 << 15,
InDetachFlag = 1 << 16,
HasRareDataFlag = 1 << 17,
+ IsShadowRootFlag = 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.
- IsParsingChildrenFinishedFlag = 1 << 18, // Element
- IsStyleAttributeValidFlag = 1 << 19, // StyledElement
- IsSynchronizingStyleAttributeFlag = 1 << 20, // StyledElement
+ IsParsingChildrenFinishedFlag = 1 << 19, // Element
+ IsStyleAttributeValidFlag = 1 << 20, // StyledElement
+ IsSynchronizingStyleAttributeFlag = 1 << 21, // StyledElement
#if ENABLE(SVG)
- AreSVGAttributesValidFlag = 1 << 21, // Element
- IsSynchronizingSVGAttributesFlag = 1 << 22, // SVGElement
- HasSVGRareDataFlag = 1 << 23, // SVGElement
+ AreSVGAttributesValidFlag = 1 << 22, // Element
+ IsSynchronizingSVGAttributesFlag = 1 << 23, // SVGElement
+ HasSVGRareDataFlag = 1 << 24, // SVGElement
#endif
+
StyleChangeMask = 1 << nodeStyleChangeShift | 1 << (nodeStyleChangeShift + 1),
#if ENABLE(SVG)
@@ -613,7 +619,7 @@ private:
#endif
};
- // 5 bits remaining
+ // 4 bits remaining
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); }
@@ -644,6 +650,9 @@ protected:
NodeRareData* rareData() const;
NodeRareData* ensureRareData();
+ Element* shadowHost() const;
+ void setShadowHost(Element*);
+
private:
#if USE(JSC)
void markCachedNodeListsSlow(JSC::MarkStack&, JSC::JSGlobalData&);
@@ -669,6 +678,11 @@ private:
Element* ancestorElement() const;
+ // Use Node::parentNode as the consistent way of querying a parent node.
+ // This method is made private to ensure a compiler error on call sites that
+ // don't follow this rule.
+ using TreeShared<ContainerNode>::parent;
+
void trackForDebugging();
Document* m_document;
@@ -710,11 +724,25 @@ inline void addSubresourceURL(ListHashSet<KURL>& urls, const KURL& url)
urls.add(url);
}
-inline ContainerNode* Node::parentOrHostNode()
+inline ContainerNode* Node::parentNode() const
+{
+ return getFlag(IsShadowRootFlag) ? 0 : parent();
+}
+
+inline ContainerNode* Node::parentOrHostNode() const
+{
+ return parent();
+}
+
+inline ContainerNode* Node::parentNodeGuaranteedHostFree() const
+{
+ ASSERT(!getFlag(IsShadowRootFlag));
+ return parentOrHostNode();
+}
+
+inline ContainerNode* Node::shadowParentNode() const
{
- if (ContainerNode* parent = parentNode())
- return parent;
- return shadowParentNode();
+ return getFlag(IsShadowRootFlag) ? parent() : 0;
}
} //namespace
diff --git a/WebCore/dom/PositionIterator.cpp b/WebCore/dom/PositionIterator.cpp
index 767e705..5de9d9d 100644
--- a/WebCore/dom/PositionIterator.cpp
+++ b/WebCore/dom/PositionIterator.cpp
@@ -98,6 +98,13 @@ void PositionIterator::decrement()
}
}
+void PositionIterator::setOffsetInLeafNode(int offset)
+{
+ ASSERT(!m_anchorNode->hasChildNodes());
+ ASSERT(0 <= offset && offset <= lastOffsetForEditing(m_anchorNode));
+ m_offsetInAnchor = offset;
+}
+
bool PositionIterator::atStart() const
{
if (!m_anchorNode)
diff --git a/WebCore/dom/PositionIterator.h b/WebCore/dom/PositionIterator.h
index 7af8977..08329bb 100644
--- a/WebCore/dom/PositionIterator.h
+++ b/WebCore/dom/PositionIterator.h
@@ -56,6 +56,7 @@ public:
Node* node() const { return m_anchorNode; }
int offsetInLeafNode() const { return m_offsetInAnchor; }
+ void setOffsetInLeafNode(int offset);
bool atStart() const;
bool atEnd() const;
diff --git a/WebCore/dom/ProgressEvent.cpp b/WebCore/dom/ProgressEvent.cpp
index 99de500..c85eeff 100644
--- a/WebCore/dom/ProgressEvent.cpp
+++ b/WebCore/dom/ProgressEvent.cpp
@@ -35,7 +35,7 @@ ProgressEvent::ProgressEvent()
{
}
-ProgressEvent::ProgressEvent(const AtomicString& type, bool lengthComputable, unsigned loaded, unsigned total)
+ProgressEvent::ProgressEvent(const AtomicString& type, bool lengthComputable, unsigned long long loaded, unsigned long long total)
: Event(type, false, true)
, m_lengthComputable(lengthComputable)
, m_loaded(loaded)
@@ -43,12 +43,8 @@ ProgressEvent::ProgressEvent(const AtomicString& type, bool lengthComputable, un
{
}
-void ProgressEvent::initProgressEvent(const AtomicString& typeArg,
- bool canBubbleArg,
- bool cancelableArg,
- bool lengthComputableArg,
- unsigned loadedArg,
- unsigned totalArg)
+void ProgressEvent::initProgressEvent(const AtomicString& typeArg, bool canBubbleArg, bool cancelableArg,
+ bool lengthComputableArg, unsigned long long loadedArg, unsigned long long totalArg)
{
if (dispatched())
return;
diff --git a/WebCore/dom/ProgressEvent.h b/WebCore/dom/ProgressEvent.h
index e30cb1b..3e295c6 100644
--- a/WebCore/dom/ProgressEvent.h
+++ b/WebCore/dom/ProgressEvent.h
@@ -30,40 +30,35 @@
namespace WebCore {
- class ProgressEvent : public Event {
- public:
- static PassRefPtr<ProgressEvent> create()
- {
- return adoptRef(new ProgressEvent);
- }
- static PassRefPtr<ProgressEvent> create(const AtomicString& type, bool lengthComputable, unsigned loaded, unsigned total)
- {
- return adoptRef(new ProgressEvent(type, lengthComputable, loaded, total));
- }
+class ProgressEvent : public Event {
+public:
+ static PassRefPtr<ProgressEvent> create()
+ {
+ return adoptRef(new ProgressEvent);
+ }
+ static PassRefPtr<ProgressEvent> create(const AtomicString& type, bool lengthComputable, unsigned long long loaded, unsigned long long total)
+ {
+ return adoptRef(new ProgressEvent(type, lengthComputable, loaded, total));
+ }
- void initProgressEvent(const AtomicString& typeArg,
- bool canBubbleArg,
- bool cancelableArg,
- bool lengthComputableArg,
- unsigned loadedArg,
- unsigned totalArg);
-
- bool lengthComputable() const { return m_lengthComputable; }
- unsigned loaded() const { return m_loaded; }
- unsigned total() const { return m_total; }
-
- virtual bool isProgressEvent() const { return true; }
-
- protected:
- ProgressEvent();
- ProgressEvent(const AtomicString& type, bool lengthComputable, unsigned loaded, unsigned total);
+ void initProgressEvent(const AtomicString& typeArg, bool canBubbleArg, bool cancelableArg,
+ bool lengthComputableArg, unsigned long long loadedArg, unsigned long long totalArg);
- private:
- bool m_lengthComputable;
- unsigned m_loaded;
- unsigned m_total;
- };
+ bool lengthComputable() const { return m_lengthComputable; }
+ unsigned long long loaded() const { return m_loaded; }
+ unsigned long long total() const { return m_total; }
+
+protected:
+ ProgressEvent();
+ ProgressEvent(const AtomicString& type, bool lengthComputable, unsigned long long loaded, unsigned long long total);
+
+private:
+ virtual bool isProgressEvent() const { return true; }
+
+ bool m_lengthComputable;
+ unsigned long long m_loaded;
+ unsigned long long m_total;
+};
}
#endif // ProgressEvent_h
-
diff --git a/WebCore/dom/ProgressEvent.idl b/WebCore/dom/ProgressEvent.idl
index afdf3a2..e832def 100644
--- a/WebCore/dom/ProgressEvent.idl
+++ b/WebCore/dom/ProgressEvent.idl
@@ -26,15 +26,12 @@
module events {
interface ProgressEvent : Event {
- readonly attribute boolean lengthComputable;
- readonly attribute unsigned long loaded;
- readonly attribute unsigned long total;
- void initProgressEvent(in DOMString typeArg,
- in boolean canBubbleArg,
- in boolean cancelableArg,
- in boolean lengthComputableArg,
- in unsigned long loadedArg,
- in unsigned long totalArg);
+ readonly attribute boolean lengthComputable;
+ readonly attribute unsigned long long loaded;
+ readonly attribute unsigned long long total;
+
+ void initProgressEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg,
+ in boolean lengthComputableArg, in unsigned long long loadedArg, in unsigned long long totalArg);
};
}
diff --git a/WebCore/dom/Range.cpp b/WebCore/dom/Range.cpp
index 71bf08e..1f15f26 100644
--- a/WebCore/dom/Range.cpp
+++ b/WebCore/dom/Range.cpp
@@ -45,8 +45,6 @@
namespace WebCore {
-typedef Vector<RefPtr<Node> > NodeVector;
-
using namespace std;
#ifndef NDEBUG
@@ -598,6 +596,8 @@ bool Range::intersectsNode(Node* refNode, ExceptionCode& ec)
PassRefPtr<DocumentFragment> Range::processContents(ActionType action, ExceptionCode& ec)
{
+ typedef Vector<RefPtr<Node> > NodeVector;
+
RefPtr<DocumentFragment> fragment;
if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
fragment = DocumentFragment::create(m_ownerDocument.get());
@@ -668,7 +668,7 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception
else if (action == CLONE_CONTENTS)
fragment->appendChild(n->cloneNode(true), ec);
else
- m_start.container()->removeChild(n.get(), ec);
+ toContainerNode(m_start.container())->removeChild(n.get(), ec);
}
}
return fragment.release();
@@ -1188,7 +1188,7 @@ void Range::checkNodeBA(Node* n, ExceptionCode& ec) const
case Node::PROCESSING_INSTRUCTION_NODE:
case Node::TEXT_NODE:
case Node::XPATH_NAMESPACE_NODE:
- if (root->isShadowNode())
+ if (root->isShadowRoot())
break;
ec = RangeException::INVALID_NODE_TYPE_ERR;
return;
@@ -1921,9 +1921,9 @@ PassRefPtr<ClientRect> Range::getBoundingClientRect() const
if (quads.isEmpty())
return ClientRect::create();
- IntRect result;
+ FloatRect result;
for (size_t i = 0; i < quads.size(); ++i)
- result.unite(quads[i].enclosingBoundingBox());
+ result.unite(quads[i].boundingBox());
return ClientRect::create(result);
}
diff --git a/WebCore/dom/ScopedEventQueue.cpp b/WebCore/dom/ScopedEventQueue.cpp
new file mode 100644
index 0000000..680d82d
--- /dev/null
+++ b/WebCore/dom/ScopedEventQueue.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2010 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 "ScopedEventQueue.h"
+
+#include "Event.h"
+#include "EventTarget.h"
+
+namespace WebCore {
+
+ScopedEventQueue* ScopedEventQueue::s_instance = 0;
+
+ScopedEventQueue::ScopedEventQueue()
+ : m_scopingLevel(0)
+{
+}
+
+ScopedEventQueue::~ScopedEventQueue()
+{
+ ASSERT(!m_scopingLevel);
+ ASSERT(!m_queuedEvents.size());
+}
+
+void ScopedEventQueue::initialize()
+{
+ ASSERT(!s_instance);
+ OwnPtr<ScopedEventQueue> instance = adoptPtr(new ScopedEventQueue);
+ s_instance = instance.leakPtr();
+}
+
+void ScopedEventQueue::enqueueEvent(PassRefPtr<Event> event)
+{
+ if (m_scopingLevel)
+ m_queuedEvents.append(event);
+ else
+ dispatchEvent(event);
+}
+
+void ScopedEventQueue::dispatchAllEvents()
+{
+ Vector<RefPtr<Event> > queuedEvents;
+ queuedEvents.swap(m_queuedEvents);
+
+ for (size_t i = 0; i < queuedEvents.size(); i++)
+ dispatchEvent(queuedEvents[i].release());
+}
+
+void ScopedEventQueue::dispatchEvent(PassRefPtr<Event> event) const
+{
+ RefPtr<EventTarget> eventTarget = event->target();
+ eventTarget->dispatchEvent(event);
+}
+
+ScopedEventQueue* ScopedEventQueue::instance()
+{
+ if (!s_instance)
+ initialize();
+
+ return s_instance;
+}
+
+void ScopedEventQueue::incrementScopingLevel()
+{
+ m_scopingLevel++;
+}
+
+void ScopedEventQueue::decrementScopingLevel()
+{
+ ASSERT(m_scopingLevel);
+ m_scopingLevel--;
+ if (!m_scopingLevel)
+ dispatchAllEvents();
+}
+
+}
diff --git a/WebCore/dom/ScopedEventQueue.h b/WebCore/dom/ScopedEventQueue.h
new file mode 100644
index 0000000..52415d4
--- /dev/null
+++ b/WebCore/dom/ScopedEventQueue.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef ScopedEventQueue_h
+#define ScopedEventQueue_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Event;
+
+class ScopedEventQueue {
+ WTF_MAKE_NONCOPYABLE(ScopedEventQueue);
+
+public:
+ ~ScopedEventQueue();
+
+ void enqueueEvent(PassRefPtr<Event>);
+ void dispatchAllEvents();
+ static ScopedEventQueue* instance();
+
+ void incrementScopingLevel();
+ void decrementScopingLevel();
+
+private:
+ ScopedEventQueue();
+ static void initialize();
+ void dispatchEvent(PassRefPtr<Event>) const;
+
+ Vector<RefPtr<Event> > m_queuedEvents;
+ unsigned m_scopingLevel;
+
+ static ScopedEventQueue* s_instance;
+};
+
+class EventQueueScope {
+ WTF_MAKE_NONCOPYABLE(EventQueueScope);
+
+public:
+ EventQueueScope() { ScopedEventQueue::instance()->incrementScopingLevel(); }
+ ~EventQueueScope() { ScopedEventQueue::instance()->decrementScopingLevel(); }
+};
+
+}
+
+#endif // ScopedEventQueue_h
diff --git a/WebCore/dom/ScriptElement.cpp b/WebCore/dom/ScriptElement.cpp
index 6c8441d..74f2580 100644
--- a/WebCore/dom/ScriptElement.cpp
+++ b/WebCore/dom/ScriptElement.cpp
@@ -51,13 +51,13 @@
namespace WebCore {
-ScriptElement::ScriptElement(Element* element, bool createdByParser, bool isEvaluated)
+ScriptElement::ScriptElement(Element* element, bool wasInsertedByParser, bool wasAlreadyStarted)
: m_element(element)
, m_cachedScript(0)
- , m_createdByParser(createdByParser)
- , m_requested(false)
- , m_isEvaluated(isEvaluated)
- , m_firedLoad(false)
+ , m_wasInsertedByParser(wasInsertedByParser)
+ , m_isExternalScript(false)
+ , m_wasAlreadyStarted(wasAlreadyStarted)
+ , m_haveFiredLoad(false)
{
ASSERT(m_element);
}
@@ -69,7 +69,7 @@ ScriptElement::~ScriptElement()
void ScriptElement::insertedIntoDocument(const String& sourceUrl)
{
- if (createdByParser() && !isAsynchronous())
+ if (wasInsertedByParser() && !isAsynchronous())
return;
// http://www.whatwg.org/specs/web-apps/current-work/#script
@@ -93,7 +93,7 @@ void ScriptElement::removedFromDocument()
void ScriptElement::childrenChanged()
{
- if (createdByParser())
+ if (wasInsertedByParser())
return;
// If a node is inserted as a child of the script element
@@ -108,7 +108,7 @@ void ScriptElement::finishParsingChildren(const String& sourceUrl)
// The parser just reached </script>. If we have no src and no text,
// allow dynamic loading later.
if (sourceUrl.isEmpty() && scriptContent().isEmpty())
- m_createdByParser = false;
+ m_wasInsertedByParser = false;
}
void ScriptElement::handleSourceAttribute(const String& sourceUrl)
@@ -158,12 +158,12 @@ void ScriptElement::requestScript(const String& sourceUrl)
ASSERT(!m_cachedScript);
m_cachedScript = document->cachedResourceLoader()->requestScript(sourceUrl, scriptCharset());
- m_requested = true;
+ m_isExternalScript = true;
- // m_createdByParser is never reset - always resied at the initial value set while parsing.
- // m_evaluated is left untouched as well to avoid script reexecution, if a <script> element
+ // m_wasInsertedByParser is never reset - always resied at the initial value set while parsing.
+ // m_wasAlreadyStarted is left untouched as well to avoid script reexecution, if a <script> element
// is removed and reappended to the document.
- m_firedLoad = false;
+ m_haveFiredLoad = false;
if (m_cachedScript) {
m_cachedScript->addClient(this);
@@ -175,7 +175,7 @@ void ScriptElement::requestScript(const String& sourceUrl)
void ScriptElement::evaluateScript(const ScriptSourceCode& sourceCode)
{
- if (m_isEvaluated || sourceCode.isEmpty() || !shouldExecuteAsJavaScript())
+ if (wasAlreadyStarted() || sourceCode.isEmpty() || !shouldExecuteAsJavaScript())
return;
RefPtr<Document> document = m_element->document();
@@ -184,12 +184,12 @@ void ScriptElement::evaluateScript(const ScriptSourceCode& sourceCode)
if (!frame->script()->canExecuteScripts(AboutToExecuteScript))
return;
- m_isEvaluated = true;
+ m_wasAlreadyStarted = true;
// http://www.whatwg.org/specs/web-apps/current-work/#script
{
- IgnoreDestructiveWriteCountIncrementer ignoreDesctructiveWriteCountIncrementer(m_requested ? document.get() : 0);
+ IgnoreDestructiveWriteCountIncrementer ignoreDesctructiveWriteCountIncrementer(m_isExternalScript ? document.get() : 0);
// Create a script from the script element node, using the script
// block's source and the script block's type.
// Note: This is where the script is compiled and actually executed.
@@ -202,7 +202,7 @@ void ScriptElement::evaluateScript(const ScriptSourceCode& sourceCode)
void ScriptElement::executeScript(const ScriptSourceCode& sourceCode)
{
- if (m_isEvaluated || sourceCode.isEmpty())
+ if (wasAlreadyStarted() || sourceCode.isEmpty())
return;
RefPtr<Document> document = m_element->document();
ASSERT(document);
@@ -210,7 +210,7 @@ void ScriptElement::executeScript(const ScriptSourceCode& sourceCode)
if (!frame)
return;
- m_isEvaluated = true;
+ m_wasAlreadyStarted = true;
frame->script()->executeScript(sourceCode);
}
@@ -244,7 +244,7 @@ void ScriptElement::notifyFinished(CachedResource* o)
bool ScriptElement::ignoresLoadRequest() const
{
- return m_isEvaluated || m_requested || m_createdByParser || !m_element->inDocument();
+ return wasAlreadyStarted() || m_isExternalScript || wasInsertedByParser() || !m_element->inDocument();
}
bool ScriptElement::shouldExecuteAsJavaScript() const
diff --git a/WebCore/dom/ScriptElement.h b/WebCore/dom/ScriptElement.h
index b6beb6e..07c59db 100644
--- a/WebCore/dom/ScriptElement.h
+++ b/WebCore/dom/ScriptElement.h
@@ -51,11 +51,12 @@ public:
virtual void dispatchLoadEvent() = 0;
virtual void dispatchErrorEvent() = 0;
+ bool haveFiredLoadEvent() const { return m_haveFiredLoad; }
+
protected:
- bool haveFiredLoadEvent() const { return m_firedLoad; }
- void setHaveFiredLoadEvent(bool firedLoad) { m_firedLoad = firedLoad; }
- bool createdByParser() const { return m_createdByParser; }
- bool isEvaluated() const { return m_isEvaluated; }
+ void setHaveFiredLoadEvent(bool haveFiredLoad) { m_haveFiredLoad = haveFiredLoad; }
+ bool wasInsertedByParser() const { return m_wasInsertedByParser; }
+ bool wasAlreadyStarted() const { return m_wasAlreadyStarted; }
// Helper functions used by our parent classes.
void insertedIntoDocument(const String& sourceUrl);
@@ -85,10 +86,10 @@ private:
Element* m_element;
CachedResourceHandle<CachedScript> m_cachedScript;
- bool m_createdByParser; // HTML5: "parser-inserted"
- bool m_requested;
- bool m_isEvaluated; // HTML5: "already started"
- bool m_firedLoad;
+ bool m_wasInsertedByParser;
+ bool m_isExternalScript;
+ bool m_wasAlreadyStarted;
+ bool m_haveFiredLoad;
};
ScriptElement* toScriptElement(Element*);
diff --git a/WebCore/dom/ScriptExecutionContext.h b/WebCore/dom/ScriptExecutionContext.h
index b46a0f4..12eb776 100644
--- a/WebCore/dom/ScriptExecutionContext.h
+++ b/WebCore/dom/ScriptExecutionContext.h
@@ -70,7 +70,7 @@ namespace WebCore {
virtual bool isWorkerContext() const { return false; }
#if ENABLE(DATABASE)
- virtual bool isDatabaseReadOnly() const = 0;
+ virtual bool allowDatabaseAccess() const = 0;
virtual void databaseExceededQuota(const String& name) = 0;
DatabaseThread* databaseThread();
void setHasOpenDatabases() { m_hasOpenDatabases = true; }
diff --git a/WebCore/dom/SelectElement.cpp b/WebCore/dom/SelectElement.cpp
index d236c96..661ba88 100644
--- a/WebCore/dom/SelectElement.cpp
+++ b/WebCore/dom/SelectElement.cpp
@@ -172,6 +172,7 @@ void SelectElement::updateListBoxSelection(SelectElementData& data, Element* ele
optionElement->setSelectedState(cachedStateForActiveSelection[i]);
}
+ toSelectElement(element)->updateValidity();
scrollToSelection(data, element);
}
@@ -453,6 +454,7 @@ void SelectElement::parseMultipleAttribute(SelectElementData& data, Element* ele
{
bool oldUsesMenuList = data.usesMenuList();
data.setMultiple(!attribute->isNull());
+ toSelectElement(element)->updateValidity();
if (oldUsesMenuList != data.usesMenuList() && element->attached()) {
element->detach();
element->attach();
@@ -493,7 +495,7 @@ void SelectElement::reset(SelectElementData& data, Element* element)
if (!optionElement)
continue;
- if (!items[i]->getAttribute(HTMLNames::selectedAttr).isNull()) {
+ if (items[i]->fastHasAttribute(HTMLNames::selectedAttr)) {
if (selectedOption && !data.multiple())
selectedOption->setSelectedState(false);
optionElement->setSelectedState(true);
diff --git a/WebCore/dom/SelectElement.h b/WebCore/dom/SelectElement.h
index 53815f2..222a1bb 100644
--- a/WebCore/dom/SelectElement.h
+++ b/WebCore/dom/SelectElement.h
@@ -63,6 +63,8 @@ public:
virtual void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true) = 0;
+ virtual void updateValidity() = 0;
+
protected:
virtual ~SelectElement() { }
diff --git a/WebCore/dom/XMLDocumentParser.h b/WebCore/dom/XMLDocumentParser.h
index 0bf60a3..e22b189 100644
--- a/WebCore/dom/XMLDocumentParser.h
+++ b/WebCore/dom/XMLDocumentParser.h
@@ -210,7 +210,6 @@ namespace WebCore {
// WMLErrorHandling uses these functions.
virtual bool wellFormed() const { return !m_sawError; }
- virtual int lineNumber() const;
TextPosition0 textPosition() const;
static bool supportsXMLVersion(const String&);
@@ -227,6 +226,8 @@ namespace WebCore {
virtual bool isWaitingForScripts() const;
virtual void stopParsing();
virtual void detach();
+ virtual int lineNumber() const;
+ int columnNumber() const;
// from CachedResourceClient
virtual void notifyFinished(CachedResource*);
@@ -238,7 +239,6 @@ namespace WebCore {
bool appendFragmentSource(const String&);
- int columnNumber() const;
// This method is introduced to temporary legalize existing line/column
// coordinate bug: it is believed that numbers that originally were zero-based
diff --git a/WebCore/dom/XMLDocumentParserLibxml2.cpp b/WebCore/dom/XMLDocumentParserLibxml2.cpp
index 7a3285f..23f9883 100644
--- a/WebCore/dom/XMLDocumentParserLibxml2.cpp
+++ b/WebCore/dom/XMLDocumentParserLibxml2.cpp
@@ -686,14 +686,12 @@ static inline String toString(const xmlChar* string)
static inline AtomicString toAtomicString(const xmlChar* string, size_t size)
{
- // FIXME: Use AtomicString::fromUTF8.
- return AtomicString(toString(string, size));
+ return AtomicString::fromUTF8(reinterpret_cast<const char*>(string), size);
}
static inline AtomicString toAtomicString(const xmlChar* string)
{
- // FIXME: Use AtomicString::fromUTF8.
- return AtomicString(toString(string));
+ return AtomicString::fromUTF8(reinterpret_cast<const char*>(string));
}
struct _xmlSAX2Namespace {
diff --git a/WebCore/dom/make_names.pl b/WebCore/dom/make_names.pl
index a3b71b8..836137e 100755
--- a/WebCore/dom/make_names.pl
+++ b/WebCore/dom/make_names.pl
@@ -35,7 +35,6 @@ use Getopt::Long;
use File::Path;
use IO::File;
use InFilesParser;
-use Switch;
sub readTags($$);
sub readAttrs($$);