diff options
author | Ben Murdoch <benm@google.com> | 2011-05-05 14:36:32 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-05-10 15:38:30 +0100 |
commit | f05b935882198ccf7d81675736e3aeb089c5113a (patch) | |
tree | 4ea0ca838d9ef1b15cf17ddb3928efb427c7e5a1 /WebCore/dom | |
parent | 60fbdcc62bced8db2cb1fd233cc4d1e4ea17db1b (diff) | |
download | external_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')
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($$); |