diff options
author | Russell Brenner <russellbrenner@google.com> | 2010-11-18 17:33:13 -0800 |
---|---|---|
committer | Russell Brenner <russellbrenner@google.com> | 2010-12-02 13:47:21 -0800 |
commit | 6b70adc33054f8aee8c54d0f460458a9df11b8a5 (patch) | |
tree | 103a13998c33944d6ab3b8318c509a037e639460 /WebCore/dom | |
parent | bdf4ebc8e70b2d221b6ee7a65660918ecb1d33aa (diff) | |
download | external_webkit-6b70adc33054f8aee8c54d0f460458a9df11b8a5.zip external_webkit-6b70adc33054f8aee8c54d0f460458a9df11b8a5.tar.gz external_webkit-6b70adc33054f8aee8c54d0f460458a9df11b8a5.tar.bz2 |
Merge WebKit at r72274: Initial merge by git.
Change-Id: Ie51f0b4a16da82942bd516dce59cfb79ebbe25fb
Diffstat (limited to 'WebCore/dom')
43 files changed, 749 insertions, 315 deletions
diff --git a/WebCore/dom/AsyncScriptRunner.cpp b/WebCore/dom/AsyncScriptRunner.cpp index a72df7c..7f5f1b6 100644 --- a/WebCore/dom/AsyncScriptRunner.cpp +++ b/WebCore/dom/AsyncScriptRunner.cpp @@ -48,7 +48,7 @@ AsyncScriptRunner::~AsyncScriptRunner() } } -void AsyncScriptRunner::executeScriptSoon(ScriptElementData* data, CachedResourceHandle<CachedScript> cachedScript) +void AsyncScriptRunner::executeScriptSoon(ScriptElement* data, CachedResourceHandle<CachedScript> cachedScript) { ASSERT_ARG(data, data); @@ -80,7 +80,7 @@ void AsyncScriptRunner::timerFired(Timer<AsyncScriptRunner>* timer) RefPtr<Document> protect(m_document); - Vector<pair<ScriptElementData*, CachedResourceHandle<CachedScript> > > scripts; + Vector<pair<ScriptElement*, CachedResourceHandle<CachedScript> > > scripts; scripts.swap(m_scriptsToExecuteSoon); size_t size = scripts.size(); for (size_t i = 0; i < size; ++i) { diff --git a/WebCore/dom/AsyncScriptRunner.h b/WebCore/dom/AsyncScriptRunner.h index 57bee84..1a051a8 100644 --- a/WebCore/dom/AsyncScriptRunner.h +++ b/WebCore/dom/AsyncScriptRunner.h @@ -36,14 +36,14 @@ namespace WebCore { class CachedScript; class Document; -class ScriptElementData; +class ScriptElement; class AsyncScriptRunner : public Noncopyable { public: static PassOwnPtr<AsyncScriptRunner> create(Document* document) { return new AsyncScriptRunner(document); } ~AsyncScriptRunner(); - void executeScriptSoon(ScriptElementData*, CachedResourceHandle<CachedScript>); + void executeScriptSoon(ScriptElement*, CachedResourceHandle<CachedScript>); bool hasPendingScripts() const { return !m_scriptsToExecuteSoon.isEmpty(); } void suspend(); void resume(); @@ -54,7 +54,7 @@ private: void timerFired(Timer<AsyncScriptRunner>*); Document* m_document; - Vector<std::pair<ScriptElementData*, CachedResourceHandle<CachedScript> > > m_scriptsToExecuteSoon; + Vector<std::pair<ScriptElement*, CachedResourceHandle<CachedScript> > > m_scriptsToExecuteSoon; Timer<AsyncScriptRunner> m_timer; }; diff --git a/WebCore/dom/Attr.idl b/WebCore/dom/Attr.idl index d959cd1..bff9c7b 100644 --- a/WebCore/dom/Attr.idl +++ b/WebCore/dom/Attr.idl @@ -42,8 +42,10 @@ module core { readonly attribute boolean isId; - // extensions +#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C + // This extension is no longer needed, but it has to remain available in Objective C, as it's public API. readonly attribute CSSStyleDeclaration style; +#endif }; } diff --git a/WebCore/dom/ContainerNode.cpp b/WebCore/dom/ContainerNode.cpp index 79d233a..e158828 100644 --- a/WebCore/dom/ContainerNode.cpp +++ b/WebCore/dom/ContainerNode.cpp @@ -35,11 +35,11 @@ #include "InlineTextBox.h" #include "InspectorInstrumentation.h" #include "MutationEvent.h" +#include "ResourceLoadScheduler.h" #include "Page.h" #include "RenderBox.h" #include "RenderTheme.h" #include "RootInlineBox.h" -#include "loader.h" #include <wtf/CurrentTime.h> #include <wtf/Vector.h> @@ -101,7 +101,7 @@ bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce { // Check that this node is not "floating". // If it is, it can be deleted as a side effect of sending mutation events. - ASSERT(refCount() || parent()); + ASSERT(refCount() || parentNode()); ec = 0; @@ -165,7 +165,7 @@ bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce notifyChildInserted(child); // Add child to the rendering tree. - if (attached() && !child->attached() && child->parent() == this) { + if (attached() && !child->attached() && child->parentNode() == this) { if (shouldLazyAttach) child->lazyAttach(); else @@ -184,7 +184,7 @@ bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce void ContainerNode::insertBeforeCommon(Node* nextChild, Node* newChild) { ASSERT(newChild); - ASSERT(!newChild->parent()); // Use insertBefore if you need to handle reparenting (and want DOM mutation events). + ASSERT(!newChild->parentNode()); // Use insertBefore if you need to handle reparenting (and want DOM mutation events). ASSERT(!newChild->nextSibling()); ASSERT(!newChild->previousSibling()); @@ -240,7 +240,7 @@ bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce { // Check that this node is not "floating". // If it is, it can be deleted as a side effect of sending mutation events. - ASSERT(refCount() || parent()); + ASSERT(refCount() || parentNode()); ec = 0; @@ -334,7 +334,7 @@ bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce notifyChildInserted(child.get()); // Add child to the rendering tree - if (attached() && !child->attached() && child->parent() == this) { + if (attached() && !child->attached() && child->parentNode() == this) { if (shouldLazyAttach) child->lazyAttach(); else @@ -355,8 +355,11 @@ bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce void ContainerNode::willRemove() { - for (Node *n = m_firstChild; n != 0; n = n->nextSibling()) - n->willRemove(); + NodeVector nodes; + for (Node* n = m_lastChild; n; n = n->previousSibling()) + nodes.append(n); + for (; nodes.size(); nodes.removeLast()) + nodes.last().get()->willRemove(); Node::willRemove(); } @@ -388,7 +391,7 @@ bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec) { // Check that this node is not "floating". // If it is, it can be deleted as a side effect of sending mutation events. - ASSERT(refCount() || parent()); + ASSERT(refCount() || parentNode()); ec = 0; @@ -547,7 +550,7 @@ bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bo { // Check that this node is not "floating". // If it is, it can be deleted as a side effect of sending mutation events. - ASSERT(refCount() || parent()); + ASSERT(refCount() || parentNode()); ec = 0; @@ -601,7 +604,7 @@ bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bo notifyChildInserted(child); // Add child to the rendering tree - if (attached() && !child->attached() && child->parent() == this) { + if (attached() && !child->attached() && child->parentNode() == this) { if (shouldLazyAttach) child->lazyAttach(); else @@ -621,7 +624,7 @@ bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bo void ContainerNode::parserAddChild(PassRefPtr<Node> newChild) { ASSERT(newChild); - ASSERT(!newChild->parent()); // Use appendChild if you need to handle reparenting (and want DOM mutation events). + ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events). #if ENABLE(INSPECTOR) InspectorInstrumentation::willInsertDOMNode(document(), newChild.get(), this); @@ -655,7 +658,7 @@ void ContainerNode::suspendPostAttachCallbacks() s_shouldReEnableMemoryCacheCallsAfterAttach = true; } } - cache()->loader()->suspendPendingRequests(); + resourceLoadScheduler()->suspendPendingRequests(); } ++s_attachDepth; } @@ -670,7 +673,7 @@ void ContainerNode::resumePostAttachCallbacks() if (Page* page = document()->page()) page->setMemoryCacheClientCallsEnabled(true); } - cache()->loader()->resumePendingRequests(); + resourceLoadScheduler()->resumePendingRequests(); } --s_attachDepth; } @@ -873,6 +876,8 @@ bool ContainerNode::getLowerRightCorner(FloatPoint& point) const if (o->isText()) { RenderText* text = toRenderText(o); IntRect linesBox = text->linesBoundingBox(); + if (!linesBox.x() && !linesBox.width() && !linesBox.y() && !linesBox.height()) + continue; point.move(linesBox.x() + linesBox.width(), linesBox.y() + linesBox.height()); } else { RenderBox* box = toRenderBox(o); @@ -1005,7 +1010,8 @@ static void notifyChildInserted(Node* child) RefPtr<Node> c = child; RefPtr<Document> document = child->document(); - if (c->parentNode() && c->parentNode()->inDocument()) + Node* parentOrHostNode = c->parentOrHostNode(); + if (parentOrHostNode && parentOrHostNode->inDocument()) c->insertedIntoDocument(); else c->insertedIntoTree(true); diff --git a/WebCore/dom/DOMAllInOne.cpp b/WebCore/dom/DOMAllInOne.cpp index c1d536a..2f3510d 100644 --- a/WebCore/dom/DOMAllInOne.cpp +++ b/WebCore/dom/DOMAllInOne.cpp @@ -69,6 +69,7 @@ #include "EntityReference.cpp" #include "ErrorEvent.cpp" #include "Event.cpp" +#include "EventContext.cpp" #include "EventNames.cpp" #include "EventTarget.cpp" #include "ExceptionBase.cpp" @@ -126,5 +127,6 @@ #include "WebKitAnimationEvent.cpp" #include "WebKitTransitionEvent.cpp" #include "WheelEvent.cpp" +#include "WindowEventContext.cpp" #include "XMLDocumentParser.cpp" #include "XMLDocumentParserScope.cpp" diff --git a/WebCore/dom/DOMTimeStamp.h b/WebCore/dom/DOMTimeStamp.h new file mode 100644 index 0000000..ff61520 --- /dev/null +++ b/WebCore/dom/DOMTimeStamp.h @@ -0,0 +1,50 @@ +/* + * 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 DOMTimeStamp_h +#define DOMTimeStamp_h + +namespace WebCore { + +typedef unsigned long long DOMTimeStamp; + +inline DOMTimeStamp convertSecondsToDOMTimeStamp(double seconds) +{ + return static_cast<DOMTimeStamp>(seconds * 1000.0); +} + +inline double convertDOMTimeStampToSeconds(DOMTimeStamp milliseconds) +{ + return milliseconds / 1000.0; +} + +} // namespace WebCore + +#endif // DOMTimeStamp_h diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp index 978ca44..e0f3944 100644 --- a/WebCore/dom/Document.cpp +++ b/WebCore/dom/Document.cpp @@ -594,6 +594,17 @@ Document::~Document() if (m_styleSheets) m_styleSheets->documentDestroyed(); + if (m_elemSheet) + m_elemSheet->clearOwnerNode(); + if (m_mappedElementSheet) + m_mappedElementSheet->clearOwnerNode(); + if (m_pageUserSheet) + m_pageUserSheet->clearOwnerNode(); + if (m_pageGroupUserSheets) { + for (size_t i = 0; i < m_pageGroupUserSheets->size(); ++i) + (*m_pageGroupUserSheets)[i]->clearOwnerNode(); + } + m_weakReference->clear(); } @@ -1524,6 +1535,11 @@ void Document::unscheduleStyleRecalc() m_pendingStyleRecalcShouldForce = false; } +bool Document::isPendingStyleRecalc() const +{ + return m_styleRecalcTimer.isActive() && !m_inStyleRecalc; +} + void Document::styleRecalcTimerFired(Timer<Document>*) { updateStyleIfNeeded(); @@ -3010,7 +3026,8 @@ void Document::recalcStyleSelector() StyleSheet* sheet = 0; if (n->nodeType() == PROCESSING_INSTRUCTION_NODE) { - // Processing instruction (XML documents only) + // Processing instruction (XML documents only). + // We don't support linking to embedded CSS stylesheets, see <https://bugs.webkit.org/show_bug.cgi?id=49281> for discussion. ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(n); sheet = pi->sheet(); #if ENABLE(XSLT) @@ -3022,25 +3039,6 @@ void Document::recalcStyleSelector() return; } #endif - if (!sheet && !pi->localHref().isEmpty()) { - // Processing instruction with reference to an element in this document - e.g. - // <?xml-stylesheet href="#mystyle">, with the element - // <foo id="mystyle">heading { color: red; }</foo> at some location in - // the document - Element* elem = getElementById(pi->localHref().impl()); - if (elem) { - String sheetText(""); - for (Node* c = elem->firstChild(); c; c = c->nextSibling()) { - if (c->nodeType() == TEXT_NODE || c->nodeType() == CDATA_SECTION_NODE) - sheetText += c->nodeValue(); - } - - RefPtr<CSSStyleSheet> cssSheet = CSSStyleSheet::create(this); - cssSheet->parseString(sheetText); - pi->setCSSStyleSheet(cssSheet); - sheet = cssSheet.get(); - } - } } else if ((n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag))) #if ENABLE(SVG) || (n->isSVGElement() && n->hasTagName(SVGNames::styleTag)) @@ -4253,9 +4251,11 @@ void Document::finishedParsing() ASSERT(!scriptableDocumentParser() || !m_parser->isParsing()); ASSERT(!scriptableDocumentParser() || m_readyState != Loading); setParsing(false); - if (!m_documentTiming.domContentLoaded) - m_documentTiming.domContentLoaded = currentTime(); + if (!m_documentTiming.domContentLoadedStart) + m_documentTiming.domContentLoadedStart = currentTime(); dispatchEvent(Event::create(eventNames().DOMContentLoadedEvent, true, false)); + if (!m_documentTiming.domContentLoadedEnd) + m_documentTiming.domContentLoadedEnd = currentTime(); if (Frame* f = frame()) { // FrameLoader::finishedParsing() might end up calling Document::implicitClose() if all @@ -4432,6 +4432,25 @@ void Document::setIconURL(const String& iconURL, const String& type) f->loader()->setIconURL(m_iconURL); } +void Document::registerFormElementWithFormAttribute(Element* control) +{ + ASSERT(control->fastHasAttribute(formAttr)); + m_formElementsWithFormAttribute.add(control); +} + +void Document::unregisterFormElementWithFormAttribute(Element* control) +{ + m_formElementsWithFormAttribute.remove(control); +} + +void Document::resetFormElementsOwner(HTMLFormElement* form) +{ + typedef FormElementListHashSet::iterator Iterator; + Iterator end = m_formElementsWithFormAttribute.end(); + for (Iterator it = m_formElementsWithFormAttribute.begin(); it != end; ++it) + static_cast<HTMLFormControlElement*>(*it)->resetFormOwner(form); +} + void Document::setUseSecureKeyboardEntryWhenActive(bool usesSecureKeyboard) { if (m_useSecureKeyboardEntryWhenActive == usesSecureKeyboard) diff --git a/WebCore/dom/Document.h b/WebCore/dom/Document.h index b4af55d..ef1dbf2 100644 --- a/WebCore/dom/Document.h +++ b/WebCore/dom/Document.h @@ -319,8 +319,10 @@ public: * * @param centerX x reference for the rectangle in CSS pixels * @param centerY y reference for the rectangle in CSS pixels - * @param hPadding How much to expand the rectangle horizontally - * @param vPadding How much to expand the rectangle vertically + * @param topPadding How much to expand the top of the rectangle + * @param rightPadding How much to expand the right of the rectangle + * @param bottomPadding How much to expand the bottom of the rectangle + * @param leftPadding How much to expand the left of the rectangle * @param ignoreClipping whether or not to ignore the root scroll frame when retrieving the element. * If false, this method returns null for coordinates outside of the viewport. */ @@ -483,6 +485,10 @@ public: bool hasStateForNewFormElements() const; bool takeStateForFormElement(AtomicStringImpl* name, AtomicStringImpl* type, String& state); + void registerFormElementWithFormAttribute(Element*); + void unregisterFormElementWithFormAttribute(Element*); + void resetFormElementsOwner(HTMLFormElement*); + FrameView* view() const; // can be NULL Frame* frame() const { return m_frame; } // can be NULL Page* page() const; // can be NULL @@ -667,6 +673,7 @@ public: void scheduleForcedStyleRecalc(); void scheduleStyleRecalc(); void unscheduleStyleRecalc(); + bool isPendingStyleRecalc() const; void styleRecalcTimerFired(Timer<Document>*); void attachNodeIterator(NodeIterator*); @@ -1214,6 +1221,7 @@ private: typedef ListHashSet<Element*, 64> FormElementListHashSet; FormElementListHashSet m_formElementsWithState; + FormElementListHashSet m_formElementsWithFormAttribute; typedef HashMap<FormElementKey, Vector<String>, FormElementKeyHash, FormElementKeyHashTraits> FormElementStateMap; FormElementStateMap m_stateForNewFormElements; diff --git a/WebCore/dom/Document.idl b/WebCore/dom/Document.idl index 4a37acc..138757f 100644 --- a/WebCore/dom/Document.idl +++ b/WebCore/dom/Document.idl @@ -325,15 +325,15 @@ module core { #endif #if defined(ENABLE_TOUCH_EVENTS) && ENABLE_TOUCH_EVENTS - [ReturnsNew] Touch createTouch(in DOMWindow window, - in EventTarget target, - in long identifier, - in long pageX, - in long pageY, - in long ScreenX, - in long screenY) + [ReturnsNew, EnabledAtRuntime] Touch createTouch(in DOMWindow window, + in EventTarget target, + in long identifier, + in long pageX, + in long pageY, + in long ScreenX, + in long screenY) raises (DOMException); - [ReturnsNew] TouchList createTouchList() + [ReturnsNew, EnabledAtRuntime] TouchList createTouchList() raises (DOMException); #endif diff --git a/WebCore/dom/DocumentTiming.h b/WebCore/dom/DocumentTiming.h index a0bbb8c..7abc219 100644 --- a/WebCore/dom/DocumentTiming.h +++ b/WebCore/dom/DocumentTiming.h @@ -32,14 +32,16 @@ struct DocumentTiming { DocumentTiming() : domLoading(0.0) , domInteractive(0.0) - , domContentLoaded(0.0) + , domContentLoadedStart(0.0) + , domContentLoadedEnd(0.0) , domComplete(0.0) { } double domLoading; double domInteractive; - double domContentLoaded; + double domContentLoadedStart; + double domContentLoadedEnd; double domComplete; }; diff --git a/WebCore/dom/DocumentType.cpp b/WebCore/dom/DocumentType.cpp index 9012b68..ed4b96c 100644 --- a/WebCore/dom/DocumentType.cpp +++ b/WebCore/dom/DocumentType.cpp @@ -59,9 +59,9 @@ PassRefPtr<Node> DocumentType::cloneNode(bool /*deep*/) void DocumentType::insertedIntoDocument() { // Our document node can be null if we were created by a DOMImplementation. We use the parent() instead. - ASSERT(parent() && parent()->isDocumentNode()); - if (parent() && parent()->isDocumentNode()) { - Document* doc = static_cast<Document*>(parent()); + ASSERT(parentNode() && parentNode()->isDocumentNode()); + if (parentNode() && parentNode()->isDocumentNode()) { + Document* doc = static_cast<Document*>(parentNode()); if (!doc->doctype()) doc->setDocType(this); } diff --git a/WebCore/dom/Element.cpp b/WebCore/dom/Element.cpp index 9afde07..5497465 100644 --- a/WebCore/dom/Element.cpp +++ b/WebCore/dom/Element.cpp @@ -159,7 +159,7 @@ PassRefPtr<Element> Element::cloneElementWithChildren() PassRefPtr<Element> Element::cloneElementWithoutChildren() { - RefPtr<Element> clone = document()->createElement(tagQName(), false); + RefPtr<Element> clone = cloneElementWithoutAttributesAndChildren(); // This will catch HTML elements in the wrong namespace that are not correctly copied. // This is a sanity check as HTML overloads some of the DOM methods. ASSERT(isHTMLElement() == clone->isHTMLElement()); @@ -173,6 +173,11 @@ PassRefPtr<Element> Element::cloneElementWithoutChildren() return clone.release(); } +PassRefPtr<Element> Element::cloneElementWithoutAttributesAndChildren() const +{ + return document()->createElement(tagQName(), false); +} + void Element::removeAttribute(const QualifiedName& name, ExceptionCode& ec) { if (m_attributeMap) { @@ -1518,7 +1523,7 @@ AtomicString Element::computeInheritedLanguage() const value = static_cast<const Document*>(n)->contentLanguage(); } - n = n->parent(); + n = n->parentNode(); } return value; diff --git a/WebCore/dom/Element.h b/WebCore/dom/Element.h index 1a85650..7d4b94c 100644 --- a/WebCore/dom/Element.h +++ b/WebCore/dom/Element.h @@ -377,6 +377,7 @@ private: // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren // are used instead. virtual PassRefPtr<Node> cloneNode(bool deep); + virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren() const; QualifiedName m_tagName; virtual NodeRareData* createRareData(); diff --git a/WebCore/dom/Event.cpp b/WebCore/dom/Event.cpp index 9293a9a..c8da461 100644 --- a/WebCore/dom/Event.cpp +++ b/WebCore/dom/Event.cpp @@ -39,7 +39,7 @@ Event::Event() , m_cancelBubble(false) , m_eventPhase(0) , m_currentTarget(0) - , m_createTime(static_cast<DOMTimeStamp>(currentTime() * 1000.0)) + , m_createTime(convertSecondsToDOMTimeStamp(currentTime())) { } @@ -54,7 +54,7 @@ Event::Event(const AtomicString& eventType, bool canBubbleArg, bool cancelableAr , m_cancelBubble(false) , m_eventPhase(0) , m_currentTarget(0) - , m_createTime(static_cast<DOMTimeStamp>(currentTime() * 1000.0)) + , m_createTime(convertSecondsToDOMTimeStamp(currentTime())) { } @@ -229,6 +229,13 @@ bool Event::isDeviceOrientationEvent() const } #endif +#if ENABLE(WEB_AUDIO) +bool Event::isAudioProcessingEvent() const +{ + return false; +} +#endif + bool Event::fromUserGesture() { if (!UserGestureIndicator::processingUserGesture()) diff --git a/WebCore/dom/Event.h b/WebCore/dom/Event.h index 82ac8ec..0d2f2b9 100644 --- a/WebCore/dom/Event.h +++ b/WebCore/dom/Event.h @@ -24,6 +24,7 @@ #ifndef Event_h #define Event_h +#include "DOMTimeStamp.h" #include "EventTarget.h" #include <wtf/RefCounted.h> #include <wtf/text/AtomicString.h> @@ -32,9 +33,6 @@ namespace WebCore { class Clipboard; - // FIXME: this should probably defined elsewhere. - typedef unsigned long long DOMTimeStamp; - class Event : public RefCounted<Event> { public: enum PhaseType { @@ -131,6 +129,9 @@ namespace WebCore { virtual bool isIDBErrorEvent() const; virtual bool isIDBSuccessEvent() const; #endif +#if ENABLE(WEB_AUDIO) + virtual bool isAudioProcessingEvent() const; +#endif #if ENABLE(WORKERS) virtual bool isErrorEvent() const; #endif diff --git a/WebCore/dom/EventContext.cpp b/WebCore/dom/EventContext.cpp new file mode 100644 index 0000000..2a5c521 --- /dev/null +++ b/WebCore/dom/EventContext.cpp @@ -0,0 +1,51 @@ +/* + * 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 "EventContext.h" + +#include "DOMWindow.h" +#include "Document.h" +#include "Event.h" +#include "Node.h" + +namespace WebCore { + +EventContext::EventContext(PassRefPtr<Node> node, PassRefPtr<EventTarget> currentTarget, PassRefPtr<EventTarget> target) + : m_node(node) + , m_currentTarget(currentTarget) + , m_target(target) +{ +} + +void EventContext::handleLocalEvents(Event* event) const +{ + event->setTarget(m_target.get()); + event->setCurrentTarget(m_currentTarget.get()); + m_node->handleLocalEvents(event); +} + +} diff --git a/WebCore/dom/EventContext.h b/WebCore/dom/EventContext.h new file mode 100644 index 0000000..9bab9d4 --- /dev/null +++ b/WebCore/dom/EventContext.h @@ -0,0 +1,65 @@ +/* + * 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 EventContext_h +#define EventContext_h + +#include <wtf/RefPtr.h> + +namespace WebCore { + +class EventTarget; +class Event; +class Node; + +class EventContext { +public: + // FIXME: Use ContainerNode instead of Node. + EventContext(PassRefPtr<Node>, PassRefPtr<EventTarget> currentTarget, PassRefPtr<EventTarget> target); + + Node* node() const; + EventTarget* target() const; + void handleLocalEvents(Event*) const; + +private: + RefPtr<Node> m_node; + RefPtr<EventTarget> m_currentTarget; + RefPtr<EventTarget> m_target; +}; + +inline Node* EventContext::node() const +{ + return m_node.get(); +} + +inline EventTarget* EventContext::target() const +{ + return m_target.get(); +} + +} + +#endif // EventContext_h diff --git a/WebCore/dom/EventNames.h b/WebCore/dom/EventNames.h index 4d39acf..d19f043 100644 --- a/WebCore/dom/EventNames.h +++ b/WebCore/dom/EventNames.h @@ -178,6 +178,8 @@ namespace WebCore { macro(webglcontextrestored) \ macro(webglcontextcreationerror) \ \ + macro(audioprocess) \ + \ // end of DOM_EVENT_NAMES_FOR_EACH class EventNames : public Noncopyable { diff --git a/WebCore/dom/EventTarget.cpp b/WebCore/dom/EventTarget.cpp index 42cbb32..5f2f8a7 100644 --- a/WebCore/dom/EventTarget.cpp +++ b/WebCore/dom/EventTarget.cpp @@ -118,6 +118,13 @@ SVGElementInstance* EventTarget::toSVGElementInstance() } #endif +#if ENABLE(WEB_AUDIO) +JavaScriptAudioNode* EventTarget::toJavaScriptAudioNode() +{ + return 0; +} +#endif + #if ENABLE(WEB_SOCKETS) WebSocket* EventTarget::toWebSocket() { diff --git a/WebCore/dom/EventTarget.h b/WebCore/dom/EventTarget.h index feff4ae..ddcb663 100644 --- a/WebCore/dom/EventTarget.h +++ b/WebCore/dom/EventTarget.h @@ -51,6 +51,7 @@ namespace WebCore { class FileWriter; class IDBRequest; class IDBTransaction; + class JavaScriptAudioNode; class MessagePort; class Node; class Notification; @@ -115,6 +116,11 @@ namespace WebCore { virtual SharedWorker* toSharedWorker(); virtual SharedWorkerContext* toSharedWorkerContext(); #endif + +#if ENABLE(WEB_AUDIO) + virtual JavaScriptAudioNode* toJavaScriptAudioNode(); +#endif + #if ENABLE(WEB_SOCKETS) virtual WebSocket* toWebSocket(); #endif diff --git a/WebCore/dom/KeyboardEvent.h b/WebCore/dom/KeyboardEvent.h index 30a2ef0..02f9f63 100644 --- a/WebCore/dom/KeyboardEvent.h +++ b/WebCore/dom/KeyboardEvent.h @@ -73,7 +73,7 @@ namespace WebCore { const String& keyIdentifier, unsigned keyLocation, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool altGraphKey = false); - String keyIdentifier() const { return m_keyIdentifier; } + const String& keyIdentifier() const { return m_keyIdentifier; } unsigned keyLocation() const { return m_keyLocation; } bool getModifierState(const String& keyIdentifier) const; diff --git a/WebCore/dom/MouseRelatedEvent.cpp b/WebCore/dom/MouseRelatedEvent.cpp index 61c35e8..072656e 100644 --- a/WebCore/dom/MouseRelatedEvent.cpp +++ b/WebCore/dom/MouseRelatedEvent.cpp @@ -168,7 +168,7 @@ void MouseRelatedEvent::receivedTarget() // we should test and fix this. Node* n = targ; while (n && !n->renderer()) - n = n->parent(); + n = n->parentNode(); if (n) { RenderLayer* layer = n->renderer()->enclosingLayer(); layer->updateLayerPosition(); diff --git a/WebCore/dom/Node.cpp b/WebCore/dom/Node.cpp index cea2e07..3c0deb6 100644 --- a/WebCore/dom/Node.cpp +++ b/WebCore/dom/Node.cpp @@ -50,6 +50,7 @@ #include "DynamicNodeList.h" #include "Element.h" #include "Event.h" +#include "EventContext.h" #include "EventException.h" #include "EventHandler.h" #include "EventListener.h" @@ -85,6 +86,7 @@ #include "WebKitAnimationEvent.h" #include "WebKitTransitionEvent.h" #include "WheelEvent.h" +#include "WindowEventContext.h" #include "XMLNames.h" #include "htmlediting.h" #include <wtf/HashSet.h> @@ -739,9 +741,9 @@ inline void Node::setStyleChange(StyleChangeType changeType) inline void Node::markAncestorsWithChildNeedsStyleRecalc() { - for (ContainerNode* p = parentNode(); p && !p->childNeedsStyleRecalc(); p = p->parentNode()) + for (ContainerNode* p = parentOrHostNode(); p && !p->childNeedsStyleRecalc(); p = p->parentOrHostNode()) p->setChildNeedsStyleRecalc(); - + if (document()->childNeedsStyleRecalc()) document()->scheduleStyleRecalc(); } @@ -1326,7 +1328,7 @@ void Node::createRendererIfNeeded() ASSERT(!renderer()); - ContainerNode* parent = parentNode(); + ContainerNode* parent = parentOrHostNode(); ASSERT(parent); RenderObject* parentRenderer = parent->renderer(); @@ -2280,14 +2282,9 @@ void Node::getSubresourceURLs(ListHashSet<KURL>& urls) const addSubresourceAttributeURLs(urls); } -ContainerNode* Node::eventParentNode() -{ - return parentNode(); -} - Node* Node::enclosingLinkEventParentOrSelf() { - for (Node* node = this; node; node = node->eventParentNode()) { + for (Node* node = this; node; node = node->parentOrHostNode()) { // For imagemaps, the enclosing link node is the associated area element not the image itself. // So we don't let images be the enclosingLinkNode, even though isLink sometimes returns true // for them. @@ -2558,12 +2555,13 @@ void Node::handleLocalEvents(Event* event) fireEventListeners(event); } -#if ENABLE(SVG) -static inline SVGElementInstance* eventTargetAsSVGElementInstance(Node* referenceNode) +static inline EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode) { ASSERT(referenceNode); + +#if ENABLE(SVG) if (!referenceNode->isSVGElement()) - return 0; + return referenceNode; // 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 @@ -2577,36 +2575,41 @@ static inline SVGElementInstance* eventTargetAsSVGElementInstance(Node* referenc if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode)) return instance; } +#endif - return 0; + return referenceNode; } -#endif -static inline EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode) +void Node::getEventAncestors(Vector<EventContext>& ancestors, EventTarget* originalTarget, EventDispatchBehavior behavior) { - ASSERT(referenceNode); + if (!inDocument()) + return; -#if ENABLE(SVG) - if (SVGElementInstance* instance = eventTargetAsSVGElementInstance(referenceNode)) { - ASSERT(instance->shadowTreeElement() == referenceNode); - return instance; - } -#endif + EventTarget* target = originalTarget; + Node* ancestor = this; + bool shouldSkipNextAncestor = false; + while (true) { + if (ancestor->isShadowNode()) { + if (behavior == StayInsideShadowDOM) + return; + ancestor = ancestor->shadowParentNode(); + if (!shouldSkipNextAncestor) + target = ancestor; + } else + ancestor = ancestor->parentNode(); - return referenceNode; -} + if (!ancestor) + return; -void Node::eventAncestors(Vector<RefPtr<ContainerNode> > &ancestors) -{ - if (inDocument()) { - for (ContainerNode* ancestor = eventParentNode(); ancestor; ancestor = ancestor->eventParentNode()) { #if ENABLE(SVG) - // Skip <use> shadow tree elements. - if (ancestor->isSVGElement() && ancestor->isShadowNode()) - continue; + // Skip SVGShadowTreeRootElement. + shouldSkipNextAncestor = ancestor->isSVGElement() && ancestor->isShadowNode(); + if (shouldSkipNextAncestor) + continue; #endif - ancestors.append(ancestor); - } + // FIXME: Unroll the extra loop inside eventTargetRespectingSVGTargetRules into this loop. + ancestors.append(EventContext(ancestor, eventTargetRespectingSVGTargetRules(ancestor), target)); + } } @@ -2621,6 +2624,11 @@ bool Node::dispatchEvent(PassRefPtr<Event> prpEvent) return dispatchGenericEvent(event.release()); } +static const EventContext* topEventContext(const Vector<EventContext>& ancestors) +{ + return ancestors.isEmpty() ? 0 : &ancestors.last(); +} + bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) { RefPtr<Event> event(prpEvent); @@ -2633,20 +2641,13 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) // If the node is not in a document just send the event to it. // Be sure to ref all of nodes since event handlers could result in the last reference going away. RefPtr<Node> thisNode(this); - Vector<RefPtr<ContainerNode> > ancestors; - eventAncestors(ancestors); + RefPtr<EventTarget> originalTarget = event->target(); + Vector<EventContext> ancestors; + getEventAncestors(ancestors, originalTarget.get(), event->isMutationEvent() ? StayInsideShadowDOM : RetargetEvent); - // Set up a pointer to indicate whether / where to dispatch window events. - // We don't dispatch load events to the window. That quirk was originally - // added because Mozilla doesn't propagate load events to the window object. - DOMWindow* targetForWindowEvents = 0; - if (event->type() != eventNames().loadEvent) { - Node* topLevelContainer = ancestors.isEmpty() ? this : ancestors.last().get(); - if (topLevelContainer->isDocumentNode()) - targetForWindowEvents = static_cast<Document*>(topLevelContainer)->domWindow(); - } + WindowEventContext windowContext(event.get(), this, topEventContext(ancestors)); - InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(document(), *event, targetForWindowEvents, this, ancestors); + InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(document(), *event, windowContext.window(), this, ancestors); // Give the target node a chance to do some work before DOM event handlers get a crack. void* data = preDispatchEventHandler(event.get()); @@ -2656,22 +2657,17 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) // Trigger capturing event handlers, starting at the top and working our way down. event->setEventPhase(Event::CAPTURING_PHASE); - if (targetForWindowEvents) { - event->setCurrentTarget(targetForWindowEvents); - targetForWindowEvents->fireEventListeners(event.get()); - if (event->propagationStopped()) - goto doneDispatching; - } + if (windowContext.handleLocalEvents(event.get()) && event->propagationStopped()) + goto doneDispatching; + for (size_t i = ancestors.size(); i; --i) { - ContainerNode* ancestor = ancestors[i - 1].get(); - event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor)); - ancestor->handleLocalEvents(event.get()); + ancestors[i - 1].handleLocalEvents(event.get()); if (event->propagationStopped()) goto doneDispatching; } event->setEventPhase(Event::AT_TARGET); - + event->setTarget(originalTarget.get()); event->setCurrentTarget(eventTargetRespectingSVGTargetRules(this)); handleLocalEvents(event.get()); if (event->propagationStopped()) @@ -2683,21 +2679,15 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) size_t size = ancestors.size(); for (size_t i = 0; i < size; ++i) { - ContainerNode* ancestor = ancestors[i].get(); - event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor)); - ancestor->handleLocalEvents(event.get()); - if (event->propagationStopped() || event->cancelBubble()) - goto doneDispatching; - } - if (targetForWindowEvents) { - event->setCurrentTarget(targetForWindowEvents); - targetForWindowEvents->fireEventListeners(event.get()); + ancestors[i].handleLocalEvents(event.get()); if (event->propagationStopped() || event->cancelBubble()) goto doneDispatching; } + windowContext.handleLocalEvents(event.get()); } doneDispatching: + event->setTarget(originalTarget.get()); event->setCurrentTarget(0); event->setEventPhase(0); @@ -2718,8 +2708,7 @@ doneDispatching: if (event->bubbles()) { size_t size = ancestors.size(); for (size_t i = 0; i < size; ++i) { - ContainerNode* ancestor = ancestors[i].get(); - ancestor->defaultEventHandler(event.get()); + ancestors[i].node()->defaultEventHandler(event.get()); ASSERT(!event->defaultPrevented()); if (event->defaultHandled()) goto doneWithDefault; @@ -2729,6 +2718,10 @@ doneDispatching: doneWithDefault: + // Ensure that after event dispatch, the event's target object is the + // outermost shadow DOM boundary. + event->setTarget(windowContext.target()); + event->setCurrentTarget(0); InspectorInstrumentation::didDispatchEvent(cookie); return !event->defaultPrevented(); diff --git a/WebCore/dom/Node.h b/WebCore/dom/Node.h index 3e5a444..17c1580 100644 --- a/WebCore/dom/Node.h +++ b/WebCore/dom/Node.h @@ -49,6 +49,7 @@ class Document; class DynamicNodeList; class Element; class Event; +class EventContext; class EventListener; class FloatPoint; class Frame; @@ -85,6 +86,11 @@ enum StyleChangeType { SyntheticStyleChange = 3 << nodeStyleChangeShift }; +enum EventDispatchBehavior { + RetargetEvent, + StayInsideShadowDOM +}; + class Node : public EventTarget, public TreeShared<ContainerNode>, public ScriptWrappable { friend class Document; public: @@ -204,16 +210,14 @@ public: Node* shadowAncestorNode(); Node* shadowTreeRootNode(); bool isInShadowTree(); - - // The node's parent for the purpose of event capture and bubbling. - virtual ContainerNode* eventParentNode(); + // Node's parent or shadow tree host. + ContainerNode* parentOrHostNode(); // Returns the enclosing event parent node (or self) that, when clicked, would trigger a navigation. Node* enclosingLinkEventParentOrSelf(); // Node ancestors when concerned about event flow. - // FIXME: Should be named getEventAncestors. - void eventAncestors(Vector<RefPtr<ContainerNode> > &ancestors); + void getEventAncestors(Vector<EventContext>& ancestors, EventTarget*, EventDispatchBehavior = RetargetEvent); bool isBlockFlow() const; bool isBlockFlowOrBlockTable() const; @@ -705,6 +709,13 @@ inline void addSubresourceURL(ListHashSet<KURL>& urls, const KURL& url) urls.add(url); } +inline ContainerNode* Node::parentOrHostNode() +{ + if (ContainerNode* parent = parentNode()) + return parent; + return shadowParentNode(); +} + } //namespace #ifndef NDEBUG diff --git a/WebCore/dom/PendingScript.cpp b/WebCore/dom/PendingScript.cpp index 42e225a..18f6071 100644 --- a/WebCore/dom/PendingScript.cpp +++ b/WebCore/dom/PendingScript.cpp @@ -40,7 +40,7 @@ PendingScript::~PendingScript() PassRefPtr<Element> PendingScript::releaseElementAndClear() { setCachedScript(0); - m_startingLineNumber = 0; + m_startingPosition = TextPosition1::belowRangePosition(); m_watchingForLoad = false; return m_element.release(); } diff --git a/WebCore/dom/PendingScript.h b/WebCore/dom/PendingScript.h index 44e1e49..083507a 100644 --- a/WebCore/dom/PendingScript.h +++ b/WebCore/dom/PendingScript.h @@ -28,6 +28,7 @@ #include "CachedResourceClient.h" #include "CachedResourceHandle.h" +#include <wtf/text/TextPosition.h> #include <wtf/PassRefPtr.h> namespace WebCore { @@ -43,14 +44,14 @@ class Element; class PendingScript : public CachedResourceClient { public: PendingScript() - : m_startingLineNumber(0) + : m_startingPosition(TextPosition1::belowRangePosition()) , m_watchingForLoad(false) { } PendingScript(const PendingScript& other) : CachedResourceClient(other) - , m_startingLineNumber(other.m_startingLineNumber) + , m_startingPosition(other.m_startingPosition) , m_watchingForLoad(other.m_watchingForLoad) , m_element(other.m_element) { @@ -64,7 +65,7 @@ public: if (this == &other) return *this; - m_startingLineNumber = other.m_startingLineNumber; + m_startingPosition = other.m_startingPosition; m_watchingForLoad = other.m_watchingForLoad; m_element = other.m_element; setCachedScript(other.cachedScript()); @@ -74,7 +75,7 @@ public: // FIXME: No setter means this is never set to anything other than 0. // This is either unnecessary or incorrect. - int startingLineNumber() const { return m_startingLineNumber; } + TextPosition1 startingPosition() const { return m_startingPosition; } bool watchingForLoad() const { return m_watchingForLoad; } void setWatchingForLoad(bool b) { m_watchingForLoad = b; } @@ -89,7 +90,7 @@ public: virtual void notifyFinished(CachedResource*); private: - int m_startingLineNumber; // Only used for inline script tags. + TextPosition1 m_startingPosition; // Only used for inline script tags. bool m_watchingForLoad; RefPtr<Element> m_element; CachedResourceHandle<CachedScript> m_cachedScript; diff --git a/WebCore/dom/Position.cpp b/WebCore/dom/Position.cpp index 8c03224..d56613e 100644 --- a/WebCore/dom/Position.cpp +++ b/WebCore/dom/Position.cpp @@ -751,13 +751,13 @@ bool Position::isCandidate() const return false; if (renderer->isBR()) - return m_offset == 0 && !nodeIsUserSelectNone(node()->parent()); + return !m_offset && !nodeIsUserSelectNone(node()->parentNode()); if (renderer->isText()) return !nodeIsUserSelectNone(node()) && inRenderedText(); if (isTableElement(node()) || editingIgnoresContent(node())) - return (atFirstEditingPositionForNode() || atLastEditingPositionForNode()) && !nodeIsUserSelectNone(node()->parent()); + return (atFirstEditingPositionForNode() || atLastEditingPositionForNode()) && !nodeIsUserSelectNone(node()->parentNode()); if (m_anchorNode->hasTagName(htmlTag)) return false; diff --git a/WebCore/dom/PositionIterator.cpp b/WebCore/dom/PositionIterator.cpp index d2c3a3f..767e705 100644 --- a/WebCore/dom/PositionIterator.cpp +++ b/WebCore/dom/PositionIterator.cpp @@ -147,13 +147,13 @@ bool PositionIterator::isCandidate() const return false; if (renderer->isBR()) - return !m_offsetInAnchor && !Position::nodeIsUserSelectNone(m_anchorNode->parent()); + return !m_offsetInAnchor && !Position::nodeIsUserSelectNone(m_anchorNode->parentNode()); if (renderer->isText()) return !Position::nodeIsUserSelectNone(m_anchorNode) && Position(*this).inRenderedText(); if (isTableElement(m_anchorNode) || editingIgnoresContent(m_anchorNode)) - return (atStartOfNode() || atEndOfNode()) && !Position::nodeIsUserSelectNone(m_anchorNode->parent()); + return (atStartOfNode() || atEndOfNode()) && !Position::nodeIsUserSelectNone(m_anchorNode->parentNode()); if (!m_anchorNode->hasTagName(htmlTag) && renderer->isBlockFlow()) { if (toRenderBlock(renderer)->height() || m_anchorNode->hasTagName(bodyTag)) { diff --git a/WebCore/dom/ProcessingInstruction.cpp b/WebCore/dom/ProcessingInstruction.cpp index 38a49a0..80c58f3 100644 --- a/WebCore/dom/ProcessingInstruction.cpp +++ b/WebCore/dom/ProcessingInstruction.cpp @@ -56,6 +56,9 @@ PassRefPtr<ProcessingInstruction> ProcessingInstruction::create(Document* docume ProcessingInstruction::~ProcessingInstruction() { + if (m_sheet) + m_sheet->clearOwnerNode(); + if (m_cachedSheet) m_cachedSheet->removeClient(this); } @@ -200,6 +203,11 @@ bool ProcessingInstruction::sheetLoaded() void ProcessingInstruction::setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet* sheet) { + if (!inDocument()) { + ASSERT(!m_sheet); + return; + } + #if ENABLE(XSLT) ASSERT(!m_isXSL); #endif @@ -274,6 +282,12 @@ void ProcessingInstruction::removedFromDocument() document()->removeStyleSheetCandidateNode(this); + if (m_sheet) { + ASSERT(m_sheet->ownerNode() == this); + m_sheet->clearOwnerNode(); + m_sheet = 0; + } + if (m_cachedSheet) document()->styleSelectorChanged(DeferRecalcStyle); } diff --git a/WebCore/dom/ScriptElement.cpp b/WebCore/dom/ScriptElement.cpp index 28c7594..6c8441d 100644 --- a/WebCore/dom/ScriptElement.cpp +++ b/WebCore/dom/ScriptElement.cpp @@ -51,58 +51,72 @@ namespace WebCore { -void ScriptElement::insertedIntoDocument(ScriptElementData& data, const String& sourceUrl) +ScriptElement::ScriptElement(Element* element, bool createdByParser, bool isEvaluated) + : m_element(element) + , m_cachedScript(0) + , m_createdByParser(createdByParser) + , m_requested(false) + , m_isEvaluated(isEvaluated) + , m_firedLoad(false) { - if (data.createdByParser() && !data.isAsynchronous()) + ASSERT(m_element); +} + +ScriptElement::~ScriptElement() +{ + stopLoadRequest(); +} + +void ScriptElement::insertedIntoDocument(const String& sourceUrl) +{ + if (createdByParser() && !isAsynchronous()) return; // http://www.whatwg.org/specs/web-apps/current-work/#script if (!sourceUrl.isEmpty()) { - data.requestScript(sourceUrl); + requestScript(sourceUrl); return; } // If there's an empty script node, we shouldn't evaluate the script // because if a script is inserted afterwards (by setting text or innerText) // it should be evaluated, and evaluateScript only evaluates a script once. - data.evaluateScript(ScriptSourceCode(data.scriptContent(), data.element()->document()->url())); // FIXME: Provide a real starting line number here. + evaluateScript(ScriptSourceCode(scriptContent(), element()->document()->url())); // FIXME: Provide a real starting line number here. } -void ScriptElement::removedFromDocument(ScriptElementData& data) +void ScriptElement::removedFromDocument() { // Eventually stop loading any not-yet-finished content - data.stopLoadRequest(); + stopLoadRequest(); } -void ScriptElement::childrenChanged(ScriptElementData& data) +void ScriptElement::childrenChanged() { - if (data.createdByParser()) + if (createdByParser()) return; - Element* element = data.element(); - // If a node is inserted as a child of the script element // and the script element has been inserted in the document // we evaluate the script. - if (element->inDocument() && element->firstChild()) - data.evaluateScript(ScriptSourceCode(data.scriptContent(), element->document()->url())); // FIXME: Provide a real starting line number here + if (m_element->inDocument() && m_element->firstChild()) + evaluateScript(ScriptSourceCode(scriptContent(), m_element->document()->url())); // FIXME: Provide a real starting line number here } -void ScriptElement::finishParsingChildren(ScriptElementData& data, const String& sourceUrl) +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() && data.scriptContent().isEmpty()) - data.setCreatedByParser(false); + if (sourceUrl.isEmpty() && scriptContent().isEmpty()) + m_createdByParser = false; } -void ScriptElement::handleSourceAttribute(ScriptElementData& data, const String& sourceUrl) +void ScriptElement::handleSourceAttribute(const String& sourceUrl) { - if (data.ignoresLoadRequest() || sourceUrl.isEmpty()) + if (ignoresLoadRequest() || sourceUrl.isEmpty()) return; - data.requestScript(sourceUrl); + requestScript(sourceUrl); } // Helper function @@ -129,26 +143,7 @@ static bool isSupportedJavaScriptLanguage(const String& language) return languages.contains(language); } -// ScriptElementData -ScriptElementData::ScriptElementData(ScriptElement* scriptElement, Element* element) - : m_scriptElement(scriptElement) - , m_element(element) - , m_cachedScript(0) - , m_createdByParser(false) - , m_requested(false) - , m_evaluated(false) - , m_firedLoad(false) -{ - ASSERT(m_scriptElement); - ASSERT(m_element); -} - -ScriptElementData::~ScriptElementData() -{ - stopLoadRequest(); -} - -void ScriptElementData::requestScript(const String& sourceUrl) +void ScriptElement::requestScript(const String& sourceUrl) { Document* document = m_element->document(); @@ -175,12 +170,12 @@ void ScriptElementData::requestScript(const String& sourceUrl) return; } - m_scriptElement->dispatchErrorEvent(); + dispatchErrorEvent(); } -void ScriptElementData::evaluateScript(const ScriptSourceCode& sourceCode) +void ScriptElement::evaluateScript(const ScriptSourceCode& sourceCode) { - if (m_evaluated || sourceCode.isEmpty() || !shouldExecuteAsJavaScript()) + if (m_isEvaluated || sourceCode.isEmpty() || !shouldExecuteAsJavaScript()) return; RefPtr<Document> document = m_element->document(); @@ -189,7 +184,7 @@ void ScriptElementData::evaluateScript(const ScriptSourceCode& sourceCode) if (!frame->script()->canExecuteScripts(AboutToExecuteScript)) return; - m_evaluated = true; + m_isEvaluated = true; // http://www.whatwg.org/specs/web-apps/current-work/#script @@ -205,7 +200,22 @@ void ScriptElementData::evaluateScript(const ScriptSourceCode& sourceCode) } } -void ScriptElementData::stopLoadRequest() +void ScriptElement::executeScript(const ScriptSourceCode& sourceCode) +{ + if (m_isEvaluated || sourceCode.isEmpty()) + return; + RefPtr<Document> document = m_element->document(); + ASSERT(document); + Frame* frame = document->frame(); + if (!frame) + return; + + m_isEvaluated = true; + + frame->script()->executeScript(sourceCode); +} + +void ScriptElement::stopLoadRequest() { if (m_cachedScript) { m_cachedScript->removeClient(this); @@ -213,31 +223,31 @@ void ScriptElementData::stopLoadRequest() } } -void ScriptElementData::execute(CachedScript* cachedScript) +void ScriptElement::execute(CachedScript* cachedScript) { ASSERT(cachedScript); if (cachedScript->errorOccurred()) - m_scriptElement->dispatchErrorEvent(); + dispatchErrorEvent(); else { evaluateScript(ScriptSourceCode(cachedScript)); - m_scriptElement->dispatchLoadEvent(); + dispatchLoadEvent(); } cachedScript->removeClient(this); } -void ScriptElementData::notifyFinished(CachedResource* o) +void ScriptElement::notifyFinished(CachedResource* o) { ASSERT_UNUSED(o, o == m_cachedScript); m_element->document()->asyncScriptRunner()->executeScriptSoon(this, m_cachedScript); m_cachedScript = 0; } -bool ScriptElementData::ignoresLoadRequest() const +bool ScriptElement::ignoresLoadRequest() const { - return m_evaluated || m_requested || m_createdByParser || !m_element->inDocument(); + return m_isEvaluated || m_requested || m_createdByParser || !m_element->inDocument(); } -bool ScriptElementData::shouldExecuteAsJavaScript() const +bool ScriptElement::shouldExecuteAsJavaScript() const { /* Mozilla 1.8 accepts javascript1.0 - javascript1.7, but WinIE 7 accepts only javascript1.1 - javascript1.3. @@ -248,20 +258,20 @@ bool ScriptElementData::shouldExecuteAsJavaScript() const FIXME: Is this HTML5 compliant? */ - String type = m_scriptElement->typeAttributeValue(); + String type = typeAttributeValue(); if (!type.isEmpty()) { if (!MIMETypeRegistry::isSupportedJavaScriptMIMEType(type.stripWhiteSpace().lower())) return false; } else { - String language = m_scriptElement->languageAttributeValue(); + String language = languageAttributeValue(); if (!language.isEmpty() && !isSupportedJavaScriptLanguage(language)) return false; } // No type or language is specified, so we assume the script to be JavaScript. - String forAttribute = m_scriptElement->forAttributeValue(); - String eventAttribute = m_scriptElement->eventAttributeValue(); + String forAttribute = forAttributeValue(); + String eventAttribute = eventAttributeValue(); if (!forAttribute.isEmpty() && !eventAttribute.isEmpty()) { forAttribute = forAttribute.stripWhiteSpace(); if (!equalIgnoringCase(forAttribute, "window")) @@ -275,10 +285,10 @@ bool ScriptElementData::shouldExecuteAsJavaScript() const return true; } -String ScriptElementData::scriptCharset() const +String ScriptElement::scriptCharset() const { // First we try to get encoding from charset attribute. - String charset = m_scriptElement->charsetAttributeValue().stripWhiteSpace(); + String charset = charsetAttributeValue().stripWhiteSpace(); // If charset has not been declared in script tag, fall back to frame encoding. if (charset.isEmpty()) { @@ -289,7 +299,7 @@ String ScriptElementData::scriptCharset() const return charset; } -String ScriptElementData::scriptContent() const +String ScriptElement::scriptContent() const { Vector<UChar> val; Text* firstTextNode = 0; @@ -316,18 +326,18 @@ String ScriptElementData::scriptContent() const return String::adopt(val); } -bool ScriptElementData::isAsynchronous() const +bool ScriptElement::isAsynchronous() const { // Only external scripts may be asynchronous. // See: http://dev.w3.org/html5/spec/Overview.html#attr-script-async - return !m_scriptElement->sourceAttributeValue().isEmpty() && m_scriptElement->asyncAttributeValue(); + return !sourceAttributeValue().isEmpty() && asyncAttributeValue(); } -bool ScriptElementData::isDeferred() const +bool ScriptElement::isDeferred() const { // Only external scripts may be deferred and async trumps defer to allow for backward compatibility. // See: http://dev.w3.org/html5/spec/Overview.html#attr-script-defer - return !m_scriptElement->sourceAttributeValue().isEmpty() && !m_scriptElement->asyncAttributeValue() && m_scriptElement->deferAttributeValue(); + return !sourceAttributeValue().isEmpty() && !asyncAttributeValue() && deferAttributeValue(); } ScriptElement* toScriptElement(Element* element) diff --git a/WebCore/dom/ScriptElement.h b/WebCore/dom/ScriptElement.h index c663e43..b6beb6e 100644 --- a/WebCore/dom/ScriptElement.h +++ b/WebCore/dom/ScriptElement.h @@ -28,79 +28,66 @@ namespace WebCore { class CachedScript; class Element; -class ScriptElementData; +class ScriptElement; class ScriptSourceCode; -class ScriptElement { +class ScriptElement : private CachedResourceClient { public: - ScriptElement() { } - virtual ~ScriptElement() { } + ScriptElement(Element*, bool createdByParser, bool isEvaluated); + virtual ~ScriptElement(); + + Element* element() const { return m_element; } - virtual String scriptContent() const = 0; + // A charset for loading the script (may be overridden by HTTP headers or a BOM). + String scriptCharset() const; - virtual String sourceAttributeValue() const = 0; - virtual String charsetAttributeValue() const = 0; - virtual String typeAttributeValue() const = 0; - virtual String languageAttributeValue() const = 0; - virtual String forAttributeValue() const = 0; - virtual String eventAttributeValue() const = 0; - virtual bool asyncAttributeValue() const = 0; - virtual bool deferAttributeValue() const = 0; + String scriptContent() const; + bool shouldExecuteAsJavaScript() const; + void executeScript(const ScriptSourceCode&); + void execute(CachedScript*); + // XML parser calls these + virtual String sourceAttributeValue() const = 0; virtual void dispatchLoadEvent() = 0; virtual void dispatchErrorEvent() = 0; - // A charset for loading the script (may be overridden by HTTP headers or a BOM). - virtual String scriptCharset() const = 0; - - virtual bool shouldExecuteAsJavaScript() const = 0; - protected: - // Helper functions used by our parent classes. - static void insertedIntoDocument(ScriptElementData&, const String& sourceUrl); - static void removedFromDocument(ScriptElementData&); - static void childrenChanged(ScriptElementData&); - static void finishParsingChildren(ScriptElementData&, const String& sourceUrl); - static void handleSourceAttribute(ScriptElementData&, const String& sourceUrl); -}; + 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; } -// HTML/SVGScriptElement hold this struct as member variable -// and pass it to the static helper functions in ScriptElement -class ScriptElementData : private CachedResourceClient { -public: - ScriptElementData(ScriptElement*, Element*); - virtual ~ScriptElementData(); + // Helper functions used by our parent classes. + void insertedIntoDocument(const String& sourceUrl); + void removedFromDocument(); + void childrenChanged(); + void finishParsingChildren(const String& sourceUrl); + void handleSourceAttribute(const String& sourceUrl); +private: bool ignoresLoadRequest() const; - bool shouldExecuteAsJavaScript() const; - - String scriptContent() const; - String scriptCharset() const; bool isAsynchronous() const; bool isDeferred() const; - Element* element() const { return m_element; } - bool createdByParser() const { return m_createdByParser; } - void setCreatedByParser(bool value) { m_createdByParser = value; } - bool haveFiredLoadEvent() const { return m_firedLoad; } - void setHaveFiredLoadEvent(bool firedLoad) { m_firedLoad = firedLoad; } - void requestScript(const String& sourceUrl); void evaluateScript(const ScriptSourceCode&); void stopLoadRequest(); - void execute(CachedScript*); - -private: virtual void notifyFinished(CachedResource*); -private: - ScriptElement* m_scriptElement; + virtual String charsetAttributeValue() const = 0; + virtual String typeAttributeValue() const = 0; + virtual String languageAttributeValue() const = 0; + virtual String forAttributeValue() const = 0; + virtual String eventAttributeValue() const = 0; + virtual bool asyncAttributeValue() const = 0; + virtual bool deferAttributeValue() const = 0; + Element* m_element; CachedResourceHandle<CachedScript> m_cachedScript; bool m_createdByParser; // HTML5: "parser-inserted" bool m_requested; - bool m_evaluated; // HTML5: "already started" + bool m_isEvaluated; // HTML5: "already started" bool m_firedLoad; }; diff --git a/WebCore/dom/ScriptableDocumentParser.h b/WebCore/dom/ScriptableDocumentParser.h index 8b16304..d9bf85c 100644 --- a/WebCore/dom/ScriptableDocumentParser.h +++ b/WebCore/dom/ScriptableDocumentParser.h @@ -27,10 +27,10 @@ #define ScriptableDocumentParser_h #include "DecodedDataDocumentParser.h" +#include <wtf/text/TextPosition.h> namespace WebCore { -class SegmentedString; class XSSAuditor; class ScriptableDocumentParser : public DecodedDataDocumentParser { @@ -47,7 +47,7 @@ public: // These are used to expose the current line/column to the scripting system. virtual int lineNumber() const = 0; - virtual int columnNumber() const = 0; + virtual TextPosition0 textPosition() const = 0; XSSAuditor* xssAuditor() const { return m_xssAuditor; } void setXSSAuditor(XSSAuditor* auditor) { m_xssAuditor = auditor; } diff --git a/WebCore/dom/SelectElement.cpp b/WebCore/dom/SelectElement.cpp index 886eee7..34a4961 100644 --- a/WebCore/dom/SelectElement.cpp +++ b/WebCore/dom/SelectElement.cpp @@ -512,7 +512,6 @@ void SelectElement::reset(SelectElementData& data, Element* element) element->setNeedsStyleRecalc(); } -#if !ARROW_KEYS_POP_MENU enum SkipDirection { SkipBackwards = -1, SkipForwards = 1 @@ -533,7 +532,6 @@ static int nextValidIndex(const Vector<Element*>& listItems, int listIndex, Skip } return lastGoodIndex; } -#endif void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element* element, Event* event, HTMLFormElement* htmlForm) { @@ -541,24 +539,28 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element if (!element->renderer() || !event->isKeyboardEvent()) return; - String keyIdentifier = static_cast<KeyboardEvent*>(event)->keyIdentifier(); + const String& keyIdentifier = static_cast<KeyboardEvent*>(event)->keyIdentifier(); bool handled = false; #if ARROW_KEYS_POP_MENU - if (keyIdentifier == "Down" || keyIdentifier == "Up") { - element->focus(); + if (!isSpatialNavigationEnabled(element->document()->frame())) { + if (keyIdentifier == "Down" || keyIdentifier == "Up") { + element->focus(); - if (!element->renderer()) // Calling focus() may cause us to lose our renderer, in which case do not want to handle the event. - return; + if (!element->renderer()) // Calling focus() may cause us to lose our renderer, in which case do not want to handle the event. + return; - // Save the selection so it can be compared to the new selection when dispatching change events during setSelectedIndex, - // which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu. - saveLastSelection(data, element); - if (RenderMenuList* menuList = toRenderMenuList(element->renderer())) - menuList->showPopup(); - handled = true; + // Save the selection so it can be compared to the new selection when dispatching change events during setSelectedIndex, + // which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu. + saveLastSelection(data, element); + if (RenderMenuList* menuList = toRenderMenuList(element->renderer())) + menuList->showPopup(); + + event->setDefaultHandled(); + } + return; } -#else +#endif // When using spatial navigation, we want to be able to navigate away from the select element // when the user hits any of the arrow keys, instead of changing the selection. if (isSpatialNavigationEnabled(element->document()->frame())) @@ -591,7 +593,7 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element if (handled && listIndex >= 0 && (unsigned)listIndex < listItems.size()) setSelectedIndex(data, element, listToOptionIndex(data, element, listIndex)); -#endif + if (handled) event->setDefaultHandled(); } @@ -605,6 +607,13 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element int keyCode = static_cast<KeyboardEvent*>(event)->keyCode(); bool handled = false; + if (keyCode == ' ' && isSpatialNavigationEnabled(element->document()->frame())) { + // Use space to toggle arrow key handling for selection change or spatial navigation. + data.setActiveSelectionState(!data.activeSelectionState()); + event->setDefaultHandled(); + return; + } + #if SPACE_OR_RETURN_POP_MENU if (keyCode == ' ' || keyCode == '\r') { element->focus(); @@ -644,10 +653,6 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element // listIndex should already be selected, but this will fire the onchange handler. setSelectedIndex(data, element, listToOptionIndex(data, element, listIndex), true, true); handled = true; - } else if (keyCode == ' ' && isSpatialNavigationEnabled(element->document()->frame())) { - // Use space to trigger arrow key handling for selection change or spatial navigation. - data.setActiveSelectionState(!data.activeSelectionState()); - handled = true; } #endif if (handled) @@ -743,13 +748,13 @@ void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element* event->setDefaultHandled(); } - } else if (event->type() == eventNames().mouseupEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton && element->document()->frame()->eventHandler()->autoscrollRenderer() != element->renderer()) + } else if (event->type() == eventNames().mouseupEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton && element->document()->frame()->eventHandler()->autoscrollRenderer() != element->renderer()) { // This makes sure we fire dispatchFormControlChangeEvent for a single click. For drag selection, onChange will fire when the autoscroll timer stops. listBoxOnChange(data, element); - else if (event->type() == eventNames().keydownEvent) { + } else if (event->type() == eventNames().keydownEvent) { if (!event->isKeyboardEvent()) return; - String keyIdentifier = static_cast<KeyboardEvent*>(event)->keyIdentifier(); + const String& keyIdentifier = static_cast<KeyboardEvent*>(event)->keyIdentifier(); int endIndex = 0; if (data.activeSelectionEndIndex() < 0) { diff --git a/WebCore/dom/StyleElement.cpp b/WebCore/dom/StyleElement.cpp index f318326..157e8f9 100644 --- a/WebCore/dom/StyleElement.cpp +++ b/WebCore/dom/StyleElement.cpp @@ -43,13 +43,6 @@ StyleElement::~StyleElement() { } -StyleSheet* StyleElement::sheet(Element* e) -{ - if (!m_sheet) - createSheet(e, 0); - return m_sheet.get(); -} - void StyleElement::insertedIntoDocument(Document* document, Element* element) { ASSERT(document); @@ -67,11 +60,14 @@ void StyleElement::removedFromDocument(Document* document, Element* element) ASSERT(element); document->removeStyleSheetCandidateNode(element); - // If we're in document teardown, then we don't need to do any notification of our sheet's removal. - if (!document->renderer()) - return; + if (m_sheet) { + ASSERT(m_sheet->ownerNode() == element); + m_sheet->clearOwnerNode(); + m_sheet = 0; + } - if (m_sheet) + // If we're in document teardown, then we don't need to do any notification of our sheet's removal. + if (document->renderer()) document->styleSelectorChanged(DeferRecalcStyle); } @@ -88,7 +84,6 @@ void StyleElement::finishParsingChildren(Element* element) { ASSERT(element); process(element); - sheet(element); m_createdByParser = false; } @@ -124,6 +119,7 @@ void StyleElement::process(Element* e) void StyleElement::createSheet(Element* e, int startLineNumber, const String& text) { ASSERT(e); + ASSERT(e->inDocument()); Document* document = e->document(); if (m_sheet) { if (m_sheet->isLoading()) diff --git a/WebCore/dom/StyleElement.h b/WebCore/dom/StyleElement.h index 65f6310..05c07c5 100644 --- a/WebCore/dom/StyleElement.h +++ b/WebCore/dom/StyleElement.h @@ -37,7 +37,7 @@ protected: virtual const AtomicString& type() const = 0; virtual const AtomicString& media() const = 0; - StyleSheet* sheet(Element*); + StyleSheet* sheet() { return m_sheet.get(); } bool isLoading() const; bool sheetLoaded(Document*); diff --git a/WebCore/dom/StyledElement.cpp b/WebCore/dom/StyledElement.cpp index 7384c0b..9a7c9c8 100644 --- a/WebCore/dom/StyledElement.cpp +++ b/WebCore/dom/StyledElement.cpp @@ -267,22 +267,25 @@ CSSStyleDeclaration* StyledElement::style() return getInlineStyleDecl(); } -void StyledElement::addCSSProperty(Attribute* attr, int id, const String &value) +void StyledElement::addCSSProperty(Attribute* attribute, int id, const String &value) { - if (!attr->decl()) createMappedDecl(attr); - attr->decl()->setProperty(id, value, false); + if (!attribute->decl()) + createMappedDecl(attribute); + attribute->decl()->setProperty(id, value, false); } -void StyledElement::addCSSProperty(Attribute* attr, int id, int value) +void StyledElement::addCSSProperty(Attribute* attribute, int id, int value) { - if (!attr->decl()) createMappedDecl(attr); - attr->decl()->setProperty(id, value, false); + if (!attribute->decl()) + createMappedDecl(attribute); + attribute->decl()->setProperty(id, value, false); } -void StyledElement::addCSSImageProperty(Attribute* attr, int id, const String& url) +void StyledElement::addCSSImageProperty(Attribute* attribute, int id, const String& url) { - if (!attr->decl()) createMappedDecl(attr); - attr->decl()->setImageProperty(id, url, false); + if (!attribute->decl()) + createMappedDecl(attribute); + attribute->decl()->setImageProperty(id, url, false); } void StyledElement::addCSSLength(Attribute* attr, int id, const String &value) diff --git a/WebCore/dom/Text.cpp b/WebCore/dom/Text.cpp index 6271f11..47c532e 100644 --- a/WebCore/dom/Text.cpp +++ b/WebCore/dom/Text.cpp @@ -240,9 +240,10 @@ bool Text::rendererIsNeeded(RenderStyle *style) RenderObject* Text::createRenderer(RenderArena* arena, RenderStyle*) { #if ENABLE(SVG) - if (parentNode()->isSVGElement() + Node* parentOrHost = parentOrHostNode(); + if (parentOrHost->isSVGElement() #if ENABLE(SVG_FOREIGN_OBJECT) - && !parentNode()->hasTagName(SVGNames::foreignObjectTag) + && !parentOrHost->hasTagName(SVGNames::foreignObjectTag) #endif ) return new (arena) RenderSVGInlineText(this, dataImpl()); diff --git a/WebCore/dom/ViewportArguments.cpp b/WebCore/dom/ViewportArguments.cpp index d2e6684..c3d1fc4 100644 --- a/WebCore/dom/ViewportArguments.cpp +++ b/WebCore/dom/ViewportArguments.cpp @@ -78,6 +78,8 @@ ViewportAttributes computeViewportAttributes(ViewportArguments args, int desktop // Resolve non-'auto' width and height to pixel values. if (deviceDPI != 1.0) { + availableWidth /= result.devicePixelRatio; + availableHeight /= result.devicePixelRatio; deviceWidth /= result.devicePixelRatio; deviceHeight /= result.devicePixelRatio; diff --git a/WebCore/dom/WindowEventContext.cpp b/WebCore/dom/WindowEventContext.cpp new file mode 100644 index 0000000..0709330 --- /dev/null +++ b/WebCore/dom/WindowEventContext.cpp @@ -0,0 +1,64 @@ +/* + * 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 "WindowEventContext.h" + +#include "DOMWindow.h" +#include "Document.h" +#include "Event.h" +#include "EventContext.h" +#include "Node.h" + +namespace WebCore { + +WindowEventContext::WindowEventContext(Event* event, PassRefPtr<Node> node, const EventContext* topEventContext) +{ + // We don't dispatch load events to the window. This quirk was originally + // added because Mozilla doesn't propagate load events to the window object. + if (event->type() == eventNames().loadEvent) + return; + + Node* topLevelContainer = topEventContext ? topEventContext->node() : node.get(); + if (!topLevelContainer->isDocumentNode()) + return; + + m_window = static_cast<Document*>(topLevelContainer)->domWindow(); + m_target = topEventContext ? topEventContext->target() : node.get(); +} + +bool WindowEventContext::handleLocalEvents(Event* event) +{ + if (!m_window) + return false; + + event->setTarget(target()); + event->setCurrentTarget(window()); + m_window->fireEventListeners(event); + return true; +} + +} diff --git a/WebCore/dom/WindowEventContext.h b/WebCore/dom/WindowEventContext.h new file mode 100644 index 0000000..a19e04d --- /dev/null +++ b/WebCore/dom/WindowEventContext.h @@ -0,0 +1,65 @@ +/* + * 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 WindowEventContext_h +#define WindowEventContext_h + +#include <wtf/RefPtr.h> + +namespace WebCore { + +class DOMWindow; +class EventTarget; +class EventContext; +class Event; +class Node; + +class WindowEventContext { +public: + WindowEventContext(Event*, PassRefPtr<Node>, const EventContext*); + + DOMWindow* window() const; + EventTarget* target() const; + bool handleLocalEvents(Event* event); + +private: + RefPtr<DOMWindow> m_window; + RefPtr<EventTarget> m_target; +}; + +inline DOMWindow* WindowEventContext::window() const +{ + return m_window.get(); +} + +inline EventTarget* WindowEventContext::target() const +{ + return m_target.get(); +} + +} + +#endif // WindowEventContext_h diff --git a/WebCore/dom/XMLDocumentParser.h b/WebCore/dom/XMLDocumentParser.h index 358be1f..0bf60a3 100644 --- a/WebCore/dom/XMLDocumentParser.h +++ b/WebCore/dom/XMLDocumentParser.h @@ -211,7 +211,7 @@ namespace WebCore { // WMLErrorHandling uses these functions. virtual bool wellFormed() const { return !m_sawError; } virtual int lineNumber() const; - virtual int columnNumber() const; + TextPosition0 textPosition() const; static bool supportsXMLVersion(const String&); @@ -238,6 +238,14 @@ 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 + // eventually becomes one-based. + // FIXME: Investigate and get rid of this method. + TextPosition1 textPositionOneBased() const; + #if USE(QXMLSTREAM) private: void parse(); @@ -317,7 +325,7 @@ public: CachedResourceHandle<CachedScript> m_pendingScript; RefPtr<Element> m_scriptElement; - int m_scriptStartLine; + TextPosition1 m_scriptStartPosition; bool m_parsingFragment; AtomicString m_defaultNamespaceURI; diff --git a/WebCore/dom/XMLDocumentParserLibxml2.cpp b/WebCore/dom/XMLDocumentParserLibxml2.cpp index 77b0af6..7a3285f 100644 --- a/WebCore/dom/XMLDocumentParserLibxml2.cpp +++ b/WebCore/dom/XMLDocumentParserLibxml2.cpp @@ -560,7 +560,7 @@ XMLDocumentParser::XMLDocumentParser(Document* document, FrameView* frameView) , m_lastErrorLine(0) , m_lastErrorColumn(0) , m_pendingScript(0) - , m_scriptStartLine(0) + , m_scriptStartPosition(TextPosition1::belowRangePosition()) , m_parsingFragment(false) , m_scriptingPermission(FragmentScriptingAllowed) { @@ -587,7 +587,7 @@ XMLDocumentParser::XMLDocumentParser(DocumentFragment* fragment, Element* parent , m_lastErrorLine(0) , m_lastErrorColumn(0) , m_pendingScript(0) - , m_scriptStartLine(0) + , m_scriptStartPosition(TextPosition1::belowRangePosition()) , m_parsingFragment(true) , m_scriptingPermission(scriptingPermission) { @@ -819,7 +819,7 @@ void XMLDocumentParser::startElementNs(const xmlChar* xmlLocalName, const xmlCha ScriptElement* scriptElement = toScriptElement(newElement.get()); if (scriptElement) - m_scriptStartLine = lineNumber(); + m_scriptStartPosition = textPositionOneBased(); m_currentNode->deprecatedParserAddChild(newElement.get()); @@ -910,7 +910,7 @@ void XMLDocumentParser::endElementNs() } else m_scriptElement = 0; } else - m_view->frame()->script()->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartLine)); + scriptElement->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartPosition)); // JavaScript may have detached the parser if (isDetached()) @@ -1376,14 +1376,39 @@ void* xmlDocPtrForString(CachedResourceLoader* cachedResourceLoader, const Strin int XMLDocumentParser::lineNumber() const { + // FIXME: The implementation probably returns 1-based int, but method should return 0-based. return context() ? context()->input->line : 1; } int XMLDocumentParser::columnNumber() const { + // FIXME: The implementation probably returns 1-based int, but method should return 0-based. return context() ? context()->input->col : 1; } +TextPosition0 XMLDocumentParser::textPosition() const +{ + xmlParserCtxtPtr context = this->context(); + if (!context) + return TextPosition0::minimumPosition(); + // FIXME: The context probably contains 1-based numbers, but we treat them as 0-based, + // to be consistent with fixme's in lineNumber() and columnNumber + // methods. + return TextPosition0(WTF::ZeroBasedNumber::fromZeroBasedInt(context->input->line), + WTF::ZeroBasedNumber::fromZeroBasedInt(context->input->col)); +} + +// This method has a correct implementation, in contrast to textPosition() method. +// It should replace textPosition(). +TextPosition1 XMLDocumentParser::textPositionOneBased() const +{ + xmlParserCtxtPtr context = this->context(); + if (!context) + return TextPosition1::minimumPosition(); + return TextPosition1(WTF::OneBasedNumber::fromOneBasedInt(context->input->line), + WTF::OneBasedNumber::fromOneBasedInt(context->input->col)); +} + void XMLDocumentParser::stopParsing() { DocumentParser::stopParsing(); diff --git a/WebCore/dom/XMLDocumentParserQt.cpp b/WebCore/dom/XMLDocumentParserQt.cpp index 03b083e..e905e31 100644 --- a/WebCore/dom/XMLDocumentParserQt.cpp +++ b/WebCore/dom/XMLDocumentParserQt.cpp @@ -105,7 +105,7 @@ XMLDocumentParser::XMLDocumentParser(Document* document, FrameView* frameView) , m_lastErrorLine(0) , m_lastErrorColumn(0) , m_pendingScript(0) - , m_scriptStartLine(0) + , m_scriptStartPosition(TextPosition1::belowRangePosition()) , m_parsingFragment(false) , m_scriptingPermission(FragmentScriptingAllowed) { @@ -132,7 +132,7 @@ XMLDocumentParser::XMLDocumentParser(DocumentFragment* fragment, Element* parent , m_lastErrorLine(0) , m_lastErrorColumn(0) , m_pendingScript(0) - , m_scriptStartLine(0) + , m_scriptStartPosition(TextPosition1::belowRangePosition()) , m_parsingFragment(true) , m_scriptingPermission(permission) { @@ -192,6 +192,10 @@ void XMLDocumentParser::doWrite(const String& parseString) QString data(parseString); if (!data.isEmpty()) { + // JavaScript may cause the parser to detach, + // keep this alive until this function is done. + RefPtr<XMLDocumentParser> protect(this); + m_stream.addData(data); parse(); } @@ -234,6 +238,18 @@ int XMLDocumentParser::columnNumber() const return m_stream.columnNumber(); } +TextPosition0 XMLDocumentParser::textPosition() const +{ + return TextPosition0(WTF::ZeroBasedNumber::fromZeroBasedInt(lineNumber()), WTF::ZeroBasedNumber::fromZeroBasedInt(columnNumber())); +} + +// This method incorrectly reinterprets zero-base lineNumber method as one-based number. +// FIXME: This error is kept for compatibility. We should fix it eventually. +TextPosition1 XMLDocumentParser::textPositionOneBased() const +{ + return TextPosition1(WTF::OneBasedNumber::fromOneBasedInt(lineNumber()), WTF::OneBasedNumber::fromOneBasedInt(columnNumber())); +} + void XMLDocumentParser::stopParsing() { ScriptableDocumentParser::stopParsing(); @@ -518,7 +534,7 @@ void XMLDocumentParser::parseStartElement() ScriptElement* scriptElement = toScriptElement(newElement.get()); if (scriptElement) - m_scriptStartLine = lineNumber(); + m_scriptStartPosition = textPositionOneBased(); m_currentNode->deprecatedParserAddChild(newElement.get()); @@ -595,7 +611,7 @@ void XMLDocumentParser::parseEndElement() } else m_scriptElement = 0; } else - m_view->frame()->script()->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartLine)); + scriptElement->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartPosition)); } m_requestingScript = false; popCurrentNode(); @@ -716,4 +732,3 @@ void XMLDocumentParser::parseDtd() } } - |