diff options
Diffstat (limited to 'WebCore/dom')
73 files changed, 1643 insertions, 899 deletions
diff --git a/WebCore/dom/ClassNames.h b/WebCore/dom/ClassNames.h index 8f4852f..a836606 100644 --- a/WebCore/dom/ClassNames.h +++ b/WebCore/dom/ClassNames.h @@ -27,7 +27,7 @@ namespace WebCore { - class ClassNamesData : Noncopyable { + class ClassNamesData : public Noncopyable { public: ClassNamesData(const String& string, bool shouldFoldCase) : m_string(string), m_shouldFoldCase(shouldFoldCase), m_createdVector(false) diff --git a/WebCore/dom/Clipboard.h b/WebCore/dom/Clipboard.h index 59ae026..0fea604 100644 --- a/WebCore/dom/Clipboard.h +++ b/WebCore/dom/Clipboard.h @@ -33,6 +33,8 @@ namespace WebCore { + class FileList; + // State available during IE's events for drag and drop and copy/paste class Clipboard : public RefCounted<Clipboard> { public: @@ -53,11 +55,12 @@ namespace WebCore { // extensions beyond IE's API virtual HashSet<String> types() const = 0; - + virtual PassRefPtr<FileList> files() const = 0; + IntPoint dragLocation() const { return m_dragLoc; } CachedImage* dragImage() const { return m_dragImage.get(); } virtual void setDragImage(CachedImage*, const IntPoint&) = 0; - Node* dragImageElement() { return m_dragImageElement.get(); } + Node* dragImageElement() const { return m_dragImageElement.get(); } virtual void setDragImageElement(Node*, const IntPoint&) = 0; virtual DragImageRef createDragImage(IntPoint& dragLocation) const = 0; diff --git a/WebCore/dom/Clipboard.idl b/WebCore/dom/Clipboard.idl index 6fe83f7..dc8677e 100644 --- a/WebCore/dom/Clipboard.idl +++ b/WebCore/dom/Clipboard.idl @@ -34,6 +34,7 @@ module core { attribute [ConvertNullStringTo=Undefined] DOMString dropEffect; attribute [ConvertNullStringTo=Undefined] DOMString effectAllowed; readonly attribute [CustomGetter] Array types; + readonly attribute FileList files; [Custom] void clearData(in [Optional] DOMString type) raises(DOMException); diff --git a/WebCore/dom/Comment.h b/WebCore/dom/Comment.h index f5f1810..d00ba62 100644 --- a/WebCore/dom/Comment.h +++ b/WebCore/dom/Comment.h @@ -29,8 +29,7 @@ namespace WebCore { -class Comment : public CharacterData -{ +class Comment : public CharacterData { public: Comment(Document*, const String &_text); Comment(Document*); diff --git a/WebCore/dom/ContainerNode.cpp b/WebCore/dom/ContainerNode.cpp index 2573908..2d79156 100644 --- a/WebCore/dom/ContainerNode.cpp +++ b/WebCore/dom/ContainerNode.cpp @@ -600,6 +600,8 @@ void ContainerNode::insertedIntoDocument() void ContainerNode::removedFromDocument() { Node::removedFromDocument(); + if (document()->cssTarget() == this) + document()->setCSSTarget(0); setInDocument(false); removedFromTree(false); for (Node* child = m_firstChild; child; child = child->nextSibling()) @@ -798,7 +800,7 @@ void ContainerNode::setActive(bool down, bool pause) if (reactsToPress) setNeedsStyleRecalc(); if (renderer() && renderer()->style()->hasAppearance()) { - if (theme()->stateChanged(renderer(), PressedState)) + if (renderer()->theme()->stateChanged(renderer(), PressedState)) reactsToPress = true; } if (reactsToPress && pause) { @@ -840,7 +842,7 @@ void ContainerNode::setHovered(bool over) if (renderer()->style()->affectedByHoverRules()) setNeedsStyleRecalc(); if (renderer() && renderer()->style()->hasAppearance()) - theme()->stateChanged(renderer(), HoverState); + renderer()->theme()->stateChanged(renderer(), HoverState); } } diff --git a/WebCore/dom/DOMImplementation.cpp b/WebCore/dom/DOMImplementation.cpp index 783c629..065f708 100644 --- a/WebCore/dom/DOMImplementation.cpp +++ b/WebCore/dom/DOMImplementation.cpp @@ -314,14 +314,8 @@ PassRefPtr<HTMLDocument> DOMImplementation::createHTMLDocument(const String& tit PassRefPtr<Document> DOMImplementation::createDocument(const String& type, Frame* frame, bool inViewSourceMode) { - if (inViewSourceMode) { - if (type == "text/html" || type == "application/xhtml+xml" || type == "image/svg+xml" || isTextMIMEType(type) || isXMLMIMEType(type) -#if ENABLE(XHTMLMP) - || type == "application/vnd.wap.xhtml+xml" -#endif - ) - return HTMLViewSourceDocument::create(frame, type); - } + if (inViewSourceMode) + return HTMLViewSourceDocument::create(frame, type); // Plugins cannot take HTML and XHTML from us, and we don't even need to initialize the plugin database for those. if (type == "text/html") diff --git a/WebCore/dom/DOMStringList.cpp b/WebCore/dom/DOMStringList.cpp deleted file mode 100644 index f89702b..0000000 --- a/WebCore/dom/DOMStringList.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2009 Apple 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 "DOMStringList.h" - -namespace WebCore { - -DOMStringList::~DOMStringList() -{ -} - -} // namespace WebCore diff --git a/WebCore/dom/DOMStringList.h b/WebCore/dom/DOMStringList.h deleted file mode 100644 index 630e33e..0000000 --- a/WebCore/dom/DOMStringList.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2009 Apple 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 DOMStringList_h -#define DOMStringList_h - -#include "PlatformString.h" -#include <wtf/RefCounted.h> - -namespace WebCore { - - class DOMStringList : public RefCounted<DOMStringList> { - public: - virtual ~DOMStringList(); - - virtual unsigned length() const = 0; - virtual String item(unsigned) const = 0; - virtual bool contains(const String&) const = 0; - }; - -} // namespace WebCore - -#endif // DOMStringList_h diff --git a/WebCore/dom/DOMStringList.idl b/WebCore/dom/DOMStringList.idl deleted file mode 100644 index 16d4e12..0000000 --- a/WebCore/dom/DOMStringList.idl +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2009 Apple 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. - * - */ - -module core { - - interface [ - GenerateConstructor, - HasCustomIndexGetter - ] DOMStringList { - - // Unlike the index getter, item() never raises exceptions, and returns null for out of bounds indices. - [Custom] DOMString item(in unsigned long index); - - readonly attribute unsigned long length; - boolean contains(in DOMString str); - }; - -} diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp index ec8dfee..cd216bd 100644 --- a/WebCore/dom/Document.cpp +++ b/WebCore/dom/Document.cpp @@ -5,7 +5,7 @@ * (C) 2006 Alexey Proskuryakov (ap@webkit.org) * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * Copyright (C) 2008 David Levin (levin@chromium.org) + * Copyright (C) 2008, 2009 Google Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -286,7 +286,7 @@ static Widget* widgetForNode(Node* focusedNode) RenderObject* renderer = focusedNode->renderer(); if (!renderer || !renderer->isWidget()) return 0; - return static_cast<RenderWidget*>(renderer)->widget(); + return toRenderWidget(renderer)->widget(); } static bool acceptsEditingFocus(Node *node) @@ -354,9 +354,15 @@ Document::Document(Frame* frame, bool isXHTML) , m_hasOpenDatabases(false) #endif , m_usingGeolocation(false) +#ifdef MANUAL_MERGE_REQUIRED #ifdef ANDROID_MOBILE , mExtraLayoutDelay(0) #endif +#else // MANUAL_MERGE_REQUIRED +#if ENABLE(WML) + , m_containsWMLContent(false) +#endif +#endif // MANUAL_MERGE_REQUIRED { m_document.resetSkippingRef(this); @@ -383,11 +389,14 @@ Document::Document(Frame* frame, bool isXHTML) m_inDocument = true; m_inStyleRecalc = false; m_closeAfterStyleRecalc = false; + m_usesDescendantRules = false; m_usesSiblingRules = false; m_usesFirstLineRules = false; m_usesFirstLetterRules = false; m_usesBeforeAfterRules = false; + m_usesRemUnits = false; + m_gotoAnchorNeededAfterStylesheetsLoad = false; m_styleSelector = 0; @@ -1154,6 +1163,11 @@ void Document::styleRecalcTimerFired(Timer<Document>*) updateStyleIfNeeded(); } +bool Document::childNeedsAndNotInStyleRecalc() +{ + return childNeedsStyleRecalc() && !m_inStyleRecalc; +} + void Document::recalcStyle(StyleChange change) { // we should not enter style recalc while painting @@ -1369,6 +1383,12 @@ void Document::detach() // in order to stop media elements documentWillBecomeInactive(); + if (m_frame) { + FrameView* view = m_frame->view(); + if (view) + view->detachCustomScrollbars(); + } + // indicate destruction mode, i.e. attached() but renderer == 0 setRenderer(0); @@ -1516,7 +1536,7 @@ void Document::open(Document* ownerDocument) if (m_frame->loader()->state() == FrameStateProvisional) m_frame->loader()->stopAllLoaders(); } - + implicitOpen(); if (m_frame) @@ -1544,6 +1564,9 @@ void Document::implicitOpen() m_tokenizer = createTokenizer(); setParsing(true); + if (m_frame) + m_tokenizer->setXSSAuditor(m_frame->script()->xssAuditor()); + // If we reload, the animation controller sticks around and has // a stale animation time. We need to update it here. if (m_frame && m_frame->animation()) @@ -1693,7 +1716,8 @@ void Document::implicitClose() } frame()->loader()->checkCallImplicitClose(); - + RenderObject* renderObject = renderer(); + // We used to force a synchronous display and flush here. This really isn't // necessary and can in fact be actively harmful if pages are loading at a rate of > 60fps // (if your platform is syncing flushes and limiting them to 60fps). @@ -1702,13 +1726,19 @@ void Document::implicitClose() updateStyleIfNeeded(); // Always do a layout after loading if needed. - if (view() && renderer() && (!renderer()->firstChild() || renderer()->needsLayout())) + if (view() && renderObject && (!renderObject->firstChild() || renderObject->needsLayout())) view()->layout(); } #if PLATFORM(MAC) - if (f && renderer() && this == topDocument() && AXObjectCache::accessibilityEnabled()) - axObjectCache()->postNotification(renderer(), "AXLoadComplete", true); + if (f && renderObject && this == topDocument() && AXObjectCache::accessibilityEnabled()) { + // The AX cache may have been cleared at this point, but we need to make sure it contains an + // AX object to send the notification to. getOrCreate will make sure that an valid AX object + // exists in the cache (we ignore the return value because we don't need it here). This is + // only safe to call when a layout is not in progress, so it can not be used in postNotification. + axObjectCache()->getOrCreate(renderObject); + axObjectCache()->postNotification(renderObject, "AXLoadComplete", true); + } #endif #if ENABLE(SVG) @@ -2611,13 +2641,12 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) oldFocusedNode->setFocus(false); // Dispatch a change event for text fields or textareas that have been edited - RenderObject* r = static_cast<RenderObject*>(oldFocusedNode.get()->renderer()); + RenderObject* r = oldFocusedNode->renderer(); if (r && r->isTextControl() && toRenderTextControl(r)->isEdited()) { oldFocusedNode->dispatchEvent(eventNames().changeEvent, true, false); - if ((r = static_cast<RenderObject*>(oldFocusedNode.get()->renderer()))) { - if (r->isTextControl()) - toRenderTextControl(r)->setEdited(false); - } + r = oldFocusedNode->renderer(); + if (r && r->isTextControl()) + toRenderTextControl(r)->setEdited(false); } // Dispatch the blur event and let the node do any other blur related activities (important for text fields) @@ -2628,7 +2657,7 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) focusChangeBlocked = true; newFocusedNode = 0; } - oldFocusedNode->dispatchUIEvent(eventNames().DOMFocusOutEvent); + oldFocusedNode->dispatchUIEvent(eventNames().DOMFocusOutEvent, 0, 0); if (m_focusedNode) { // handler shifted focus focusChangeBlocked = true; @@ -2658,7 +2687,7 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) focusChangeBlocked = true; goto SetFocusedNodeDone; } - m_focusedNode->dispatchUIEvent(eventNames().DOMFocusInEvent); + m_focusedNode->dispatchUIEvent(eventNames().DOMFocusInEvent, 0, 0); if (m_focusedNode != newFocusedNode) { // handler shifted focus focusChangeBlocked = true; @@ -2686,7 +2715,7 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) else view()->setFocus(); } - } + } #if PLATFORM(MAC) && !PLATFORM(CHROMIUM) if (!focusChangeBlocked && m_focusedNode && AXObjectCache::accessibilityEnabled()) @@ -2836,6 +2865,14 @@ void Document::setWindowAttributeEventListener(const AtomicString& eventType, Pa domWindow->setAttributeEventListener(eventType, listener); } +EventListener* Document::getWindowAttributeEventListener(const AtomicString& eventType) +{ + DOMWindow* domWindow = this->domWindow(); + if (!domWindow) + return 0; + return domWindow->getAttributeEventListener(eventType); +} + void Document::dispatchWindowEvent(PassRefPtr<Event> event) { ASSERT(!eventDispatchForbidden()); @@ -4388,7 +4425,8 @@ void Document::attachRange(Range* range) void Document::detachRange(Range* range) { - ASSERT(m_ranges.contains(range)); + // We don't ASSERT m_ranges.contains(range) to allow us to call this + // unconditionally to fix: https://bugs.webkit.org/show_bug.cgi?id=26044 m_ranges.remove(range); } @@ -4469,19 +4507,19 @@ void Document::removeTouchEventListener(Node* node) void Document::reportException(const String& errorMessage, int lineNumber, const String& sourceURL) { if (DOMWindow* window = domWindow()) - window->console()->addMessage(JSMessageSource, ErrorMessageLevel, errorMessage, lineNumber, sourceURL); + window->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, errorMessage, lineNumber, sourceURL); } -void Document::addMessage(MessageDestination destination, MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL) +void Document::addMessage(MessageDestination destination, MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL) { switch (destination) { case InspectorControllerDestination: if (page()) - page()->inspectorController()->addMessageToConsole(source, level, message, lineNumber, sourceURL); + page()->inspectorController()->addMessageToConsole(source, type, level, message, lineNumber, sourceURL); return; case ConsoleDestination: if (DOMWindow* window = domWindow()) - window->console()->addMessage(source, level, message, lineNumber, sourceURL); + window->console()->addMessage(source, type, level, message, lineNumber, sourceURL); return; } ASSERT_NOT_REACHED(); diff --git a/WebCore/dom/Document.h b/WebCore/dom/Document.h index 70bc225..5d91e3d 100644 --- a/WebCore/dom/Document.h +++ b/WebCore/dom/Document.h @@ -224,7 +224,7 @@ public: } virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&); - PassRefPtr<DocumentFragment> createDocumentFragment (); + PassRefPtr<DocumentFragment> createDocumentFragment(); PassRefPtr<Text> createTextNode(const String& data); PassRefPtr<Comment> createComment(const String& data); PassRefPtr<CDATASection> createCDATASection(const String& data, ExceptionCode&); @@ -377,6 +377,8 @@ public: void setUsesFirstLetterRules(bool b) { m_usesFirstLetterRules = b; } bool usesBeforeAfterRules() const { return m_usesBeforeAfterRules; } void setUsesBeforeAfterRules(bool b) { m_usesBeforeAfterRules = b; } + bool usesRemUnits() const { return m_usesRemUnits; } + void setUsesRemUnits(bool b) { m_usesRemUnits = b; } // Machinery for saving and restoring state when you leave and then go back to a page. void registerFormElementWithState(Element* e) { m_formElementsWithState.add(e); } @@ -403,7 +405,8 @@ public: PassRefPtr<CSSStyleDeclaration> createCSSStyleDeclaration(); PassRefPtr<EditingText> createEditingTextNode(const String&); - virtual void recalcStyle( StyleChange = NoChange ); + virtual void recalcStyle(StyleChange = NoChange); + bool childNeedsAndNotInStyleRecalc(); virtual void updateStyleIfNeeded(); void updateLayout(); void updateLayoutIgnorePendingStylesheets(); @@ -566,6 +569,7 @@ public: // Helper functions for forwarding DOMWindow event related tasks to the DOMWindow if it exists. void setWindowAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener>); + EventListener* getWindowAttributeEventListener(const AtomicString& eventType); void dispatchWindowEvent(PassRefPtr<Event>); void dispatchWindowEvent(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg); void dispatchLoadEvent(); @@ -799,7 +803,7 @@ public: void parseDNSPrefetchControlHeader(const String&); virtual void reportException(const String& errorMessage, int lineNumber, const String& sourceURL); - virtual void addMessage(MessageDestination, MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL); + virtual void addMessage(MessageDestination, MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL); virtual void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString); virtual void scriptImported(unsigned long, const String&); virtual void postTask(PassRefPtr<Task>); // Executes the task on context's thread asynchronously. @@ -807,6 +811,7 @@ public: protected: Document(Frame*, bool isXHTML); +#ifdef MANUAL_MERGE_REQUIRED #if ENABLE(TOUCH_EVENTS) // Android public: typedef HashMap<Node*, unsigned > TouchListenerMap; @@ -819,6 +824,10 @@ private: TouchListenerMap m_touchEventListeners; #endif +#else // MANUAL_MERGE_REQUIRED + void setStyleSelector(CSSStyleSelector* styleSelector) { m_styleSelector = styleSelector; } + +#endif // MANUAL_MERGE_REQUIRED private: virtual void refScriptExecutionContext() { ref(); } virtual void derefScriptExecutionContext() { deref(); } @@ -927,6 +936,7 @@ private: bool m_usesFirstLineRules; bool m_usesFirstLetterRules; bool m_usesBeforeAfterRules; + bool m_usesRemUnits; bool m_gotoAnchorNeededAfterStylesheetsLoad; bool m_isDNSPrefetchEnabled; bool m_haveExplicitlyDisabledDNSPrefetch; @@ -1014,7 +1024,7 @@ public: void setDashboardRegionsDirty(bool f) { m_dashboardRegionsDirty = f; } bool dashboardRegionsDirty() const { return m_dashboardRegionsDirty; } bool hasDashboardRegions () const { return m_hasDashboardRegions; } - void setHasDashboardRegions (bool f) { m_hasDashboardRegions = f; } + void setHasDashboardRegions(bool f) { m_hasDashboardRegions = f; } const Vector<DashboardRegionValue>& dashboardRegions() const; void setDashboardRegions(const Vector<DashboardRegionValue>&); #endif @@ -1053,6 +1063,9 @@ public: bool usingGeolocation() const { return m_usingGeolocation; }; #if ENABLE(WML) + void setContainsWMLContent(bool value) { m_containsWMLContent = value; } + bool containsWMLContent() const { return m_containsWMLContent; } + void resetWMLPageState(); void initializeWMLPageState(); #endif @@ -1135,9 +1148,16 @@ private: #endif bool m_usingGeolocation; +#ifdef MANUAL_MERGE_REQUIRED #ifdef ANDROID_MOBILE int mExtraLayoutDelay; #endif +#else // MANUAL_MERGE_REQUIRED + +#if ENABLE(WML) + bool m_containsWMLContent; +#endif +#endif // MANUAL_MERGE_REQUIRED }; inline bool Document::hasElementWithId(AtomicStringImpl* id) const diff --git a/WebCore/dom/Document.idl b/WebCore/dom/Document.idl index 232ceb4..44966cc 100644 --- a/WebCore/dom/Document.idl +++ b/WebCore/dom/Document.idl @@ -21,8 +21,8 @@ module core { interface [ + CustomToJS, GenerateConstructor, - GenerateToJS, GenerateNativeConverter, CustomMarkFunction, InlineGetOwnPropertySlot, @@ -64,7 +64,7 @@ module core { raises (DOMException); [OldStyleObjC] NodeList getElementsByTagNameNS(in [ConvertNullToNullString] DOMString namespaceURI, in DOMString localName); - Element getElementById(in DOMString elementId); + Element getElementById(in [V8Custom=HintAtomic] DOMString elementId); // DOM Level 3 Core @@ -241,8 +241,80 @@ module core { #if defined(ENABLE_WML) && ENABLE_WML // Only used from within WML layout tests, WML doesn't have JS support at all. - void resetWMLPageState(); - void initializeWMLPageState(); + [DontEnum] void resetWMLPageState(); + [DontEnum] void initializeWMLPageState(); +#endif + +#if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C +#if !defined(LANGUAGE_COM) || !LANGUAGE_COM + // Event handler DOM attributes + attribute [DontEnum] EventListener onabort; + attribute [DontEnum] EventListener onblur; + attribute [DontEnum] EventListener onchange; + attribute [DontEnum] EventListener onclick; + attribute [DontEnum] EventListener oncontextmenu; + attribute [DontEnum] EventListener ondblclick; + attribute [DontEnum] EventListener ondrag; + attribute [DontEnum] EventListener ondragend; + attribute [DontEnum] EventListener ondragenter; + attribute [DontEnum] EventListener ondragleave; + attribute [DontEnum] EventListener ondragover; + attribute [DontEnum] EventListener ondragstart; + attribute [DontEnum] EventListener ondrop; + attribute [DontEnum] EventListener onerror; + attribute [DontEnum] EventListener onfocus; + attribute [DontEnum] EventListener oninput; + attribute [DontEnum] EventListener onkeydown; + attribute [DontEnum] EventListener onkeypress; + attribute [DontEnum] EventListener onkeyup; + attribute [DontEnum] EventListener onload; + attribute [DontEnum] EventListener onmousedown; + attribute [DontEnum] EventListener onmousemove; + attribute [DontEnum] EventListener onmouseout; + attribute [DontEnum] EventListener onmouseover; + attribute [DontEnum] EventListener onmouseup; + attribute [DontEnum] EventListener onmousewheel; + attribute [DontEnum] EventListener onscroll; + attribute [DontEnum] EventListener onselect; + attribute [DontEnum] EventListener onsubmit; + + // attribute [DontEnum] EventListener oncanplay; + // attribute [DontEnum] EventListener oncanplaythrough; + // attribute [DontEnum] EventListener ondurationchange; + // attribute [DontEnum] EventListener onemptied; + // attribute [DontEnum] EventListener onended; + // attribute [DontEnum] EventListener onformchange; + // attribute [DontEnum] EventListener onforminput; + // attribute [DontEnum] EventListener oninvalid; + // attribute [DontEnum] EventListener onloadeddata; + // attribute [DontEnum] EventListener onloadedmetadata; + // attribute [DontEnum] EventListener onloadstart; + // attribute [DontEnum] EventListener onpause; + // attribute [DontEnum] EventListener onplay; + // attribute [DontEnum] EventListener onplaying; + // attribute [DontEnum] EventListener onprogress; + // attribute [DontEnum] EventListener onratechange; + // attribute [DontEnum] EventListener onreadystatechange; + // attribute [DontEnum] EventListener onseeked; + // attribute [DontEnum] EventListener onseeking; + // attribute [DontEnum] EventListener onshow; + // attribute [DontEnum] EventListener onstalled; + // attribute [DontEnum] EventListener onsuspend; + // attribute [DontEnum] EventListener ontimeupdate; + // attribute [DontEnum] EventListener onvolumechange; + // attribute [DontEnum] EventListener onwaiting; + + // WebKit extensions + attribute [DontEnum] EventListener onbeforecut; + attribute [DontEnum] EventListener oncut; + attribute [DontEnum] EventListener onbeforecopy; + attribute [DontEnum] EventListener oncopy; + attribute [DontEnum] EventListener onbeforepaste; + attribute [DontEnum] EventListener onpaste; + attribute [DontEnum] EventListener onreset; + attribute [DontEnum] EventListener onsearch; + attribute [DontEnum] EventListener onselectstart; +#endif #endif }; diff --git a/WebCore/dom/DocumentFragment.cpp b/WebCore/dom/DocumentFragment.cpp index 40be64d..7a6174f 100644 --- a/WebCore/dom/DocumentFragment.cpp +++ b/WebCore/dom/DocumentFragment.cpp @@ -34,7 +34,7 @@ DocumentFragment::DocumentFragment(Document *doc) : ContainerNode(doc) String DocumentFragment::nodeName() const { - return "#document-fragment"; + return "#document-fragment"; } Node::NodeType DocumentFragment::nodeType() const diff --git a/WebCore/dom/DocumentFragment.h b/WebCore/dom/DocumentFragment.h index 33a62be..46d8ecd 100644 --- a/WebCore/dom/DocumentFragment.h +++ b/WebCore/dom/DocumentFragment.h @@ -30,8 +30,7 @@ namespace WebCore { -class DocumentFragment : public ContainerNode -{ +class DocumentFragment : public ContainerNode { public: DocumentFragment(Document*); diff --git a/WebCore/dom/DynamicNodeList.cpp b/WebCore/dom/DynamicNodeList.cpp index eeb9833..892a5e7 100644 --- a/WebCore/dom/DynamicNodeList.cpp +++ b/WebCore/dom/DynamicNodeList.cpp @@ -30,7 +30,7 @@ namespace WebCore { DynamicNodeList::DynamicNodeList(PassRefPtr<Node> rootNode) : m_rootNode(rootNode) - , m_caches(new Caches) + , m_caches(Caches::create()) , m_ownsCaches(true) { m_rootNode->registerDynamicNodeList(this); @@ -42,16 +42,11 @@ DynamicNodeList::DynamicNodeList(PassRefPtr<Node> rootNode, DynamicNodeList::Cac , m_ownsCaches(false) { m_rootNode->registerDynamicNodeList(this); - ++caches->refCount; } DynamicNodeList::~DynamicNodeList() { m_rootNode->unregisterDynamicNodeList(this); - if (m_ownsCaches) - delete m_caches; - else - --m_caches->refCount; } unsigned DynamicNodeList::length() const @@ -158,10 +153,14 @@ DynamicNodeList::Caches::Caches() : lastItem(0) , isLengthCacheValid(false) , isItemCacheValid(false) - , refCount(0) { } +PassRefPtr<DynamicNodeList::Caches> DynamicNodeList::Caches::create() +{ + return adoptRef(new Caches()); +} + void DynamicNodeList::Caches::reset() { lastItem = 0; diff --git a/WebCore/dom/DynamicNodeList.h b/WebCore/dom/DynamicNodeList.h index ee9832d..f97c38f 100644 --- a/WebCore/dom/DynamicNodeList.h +++ b/WebCore/dom/DynamicNodeList.h @@ -37,8 +37,8 @@ namespace WebCore { class DynamicNodeList : public NodeList { public: - struct Caches { - Caches(); + struct Caches : RefCounted<Caches> { + static PassRefPtr<Caches> create(); void reset(); unsigned cachedLength; @@ -46,7 +46,8 @@ namespace WebCore { unsigned lastItemOffset; bool isLengthCacheValid : 1; bool isItemCacheValid : 1; - unsigned refCount; + protected: + Caches(); }; virtual ~DynamicNodeList(); @@ -68,7 +69,7 @@ namespace WebCore { virtual bool nodeMatches(Element*) const = 0; RefPtr<Node> m_rootNode; - mutable Caches* m_caches; + mutable RefPtr<Caches> m_caches; bool m_ownsCaches; private: diff --git a/WebCore/dom/EditingText.h b/WebCore/dom/EditingText.h index 3dcd8c1..e114786 100644 --- a/WebCore/dom/EditingText.h +++ b/WebCore/dom/EditingText.h @@ -29,8 +29,7 @@ namespace WebCore { -class EditingText : public Text -{ +class EditingText : public Text { public: EditingText(Document *impl, const String &text); EditingText(Document *impl); diff --git a/WebCore/dom/Element.cpp b/WebCore/dom/Element.cpp index 4cf49bb..1956be4 100644 --- a/WebCore/dom/Element.cpp +++ b/WebCore/dom/Element.cpp @@ -33,7 +33,6 @@ #include "ClientRect.h" #include "ClientRectList.h" #include "Document.h" -#include "Editor.h" #include "ElementRareData.h" #include "ExceptionCode.h" #include "FocusController.h" @@ -45,9 +44,7 @@ #include "NodeList.h" #include "NodeRenderStyle.h" #include "Page.h" -#include "PlatformString.h" -#include "RenderBlock.h" -#include "SelectionController.h" +#include "RenderView.h" #include "TextIterator.h" #include "XMLNames.h" @@ -382,8 +379,10 @@ int Element::clientWidth() bool inCompatMode = document()->inCompatMode(); if ((!inCompatMode && document()->documentElement() == this) || (inCompatMode && isHTMLElement() && document()->body() == this)) { - if (FrameView* view = document()->view()) - return adjustForAbsoluteZoom(view->layoutWidth(), document()->renderer()); + if (FrameView* view = document()->view()) { + if (RenderView* renderView = document()->renderView()) + return adjustForAbsoluteZoom(view->layoutWidth(), renderView); + } } if (RenderBox* rend = renderBox()) @@ -401,8 +400,10 @@ int Element::clientHeight() if ((!inCompatMode && document()->documentElement() == this) || (inCompatMode && isHTMLElement() && document()->body() == this)) { - if (FrameView* view = document()->view()) - return adjustForAbsoluteZoom(view->layoutHeight(), document()->renderer()); + if (FrameView* view = document()->view()) { + if (RenderView* renderView = document()->renderView()) + return adjustForAbsoluteZoom(view->layoutHeight(), renderView); + } } if (RenderBox* rend = renderBox()) @@ -590,6 +591,12 @@ PassRefPtr<Attribute> Element::createAttribute(const QualifiedName& name, const void Element::attributeChanged(Attribute* attr, bool) { + recalcStyleIfNeededAfterAttributeChanged(attr); + updateAfterAttributeChanged(attr); +} + +void Element::updateAfterAttributeChanged(Attribute* attr) +{ if (!document()->axObjectCache()->accessibilityEnabled()) return; @@ -602,7 +609,13 @@ void Element::attributeChanged(Attribute* attr, bool) document()->axObjectCache()->handleAriaRoleChanged(renderer()); } } - + +void Element::recalcStyleIfNeededAfterAttributeChanged(Attribute* attr) +{ + if (document()->attached() && document()->styleSelector()->hasSelectorForAttribute(attr->name().localName())) + setNeedsStyleRecalc(); +} + void Element::setAttributeMap(PassRefPtr<NamedNodeMap> list) { document()->incDOMTreeVersion(); @@ -761,6 +774,34 @@ void Element::detach() ContainerNode::detach(); } +bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle) +{ + ASSERT(currentStyle = renderStyle()); + + if (!renderer() || !currentStyle) + return false; + + RenderStyle::PseudoStyleCache pseudoStyleCache; + currentStyle->getPseudoStyleCache(pseudoStyleCache); + size_t cacheSize = pseudoStyleCache.size(); + for (size_t i = 0; i < cacheSize; ++i) { + RefPtr<RenderStyle> newPseudoStyle; + PseudoId pseudoId = pseudoStyleCache[i]->styleType(); + if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) + newPseudoStyle = renderer()->uncachedFirstLineStyle(newStyle); + else + newPseudoStyle = renderer()->getUncachedPseudoStyle(pseudoId, newStyle, newStyle); + + if (*newPseudoStyle != *pseudoStyleCache[i]) { + if (pseudoId < FIRST_INTERNAL_PSEUDOID) + newStyle->setHasPseudoStyle(pseudoId); + newStyle->addCachedPseudoStyle(newPseudoStyle); + return true; + } + } + return false; +} + void Element::recalcStyle(StyleChange change) { RenderStyle* currentStyle = renderStyle(); @@ -811,7 +852,7 @@ void Element::recalcStyle(StyleChange change) newStyle->setChildrenAffectedByDirectAdjacentRules(); } - if (ch != NoChange) { + if (ch != NoChange || pseudoStyleCacheIsInvalid(currentStyle, newStyle.get())) { setRenderStyle(newStyle); } else if (needsStyleRecalc() && (styleChangeType() != AnimationStyleChange) && (document()->usesSiblingRules() || document()->usesDescendantRules())) { // Although no change occurred, we use the new style so that the cousin style sharing code won't get @@ -826,7 +867,11 @@ void Element::recalcStyle(StyleChange change) setRenderStyle(newStyle); if (change != Force) { - if ((document()->usesDescendantRules() || hasPositionalRules) && styleChangeType() >= FullStyleChange) + // If "rem" units are used anywhere in the document, and if the document element's font size changes, then go ahead and force font updating + // all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway). + if (document()->usesRemUnits() && ch != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize() && document()->documentElement() == this) + change = Force; + else if ((document()->usesDescendantRules() || hasPositionalRules) && styleChangeType() >= FullStyleChange) change = Force; else change = ch; @@ -981,7 +1026,7 @@ void Element::dispatchAttrAdditionEvent(Attribute*) return; ExceptionCode ec = 0; dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(), - attr->value(),document()->attrName(attr->id()), MutationEvent::ADDITION), ec); + attr->value(), document()->attrName(attr->id()), MutationEvent::ADDITION), ec); #endif } @@ -1341,4 +1386,15 @@ unsigned Element::childElementCount() const return count; } +KURL Element::getURLAttribute(const QualifiedName& name) const +{ +#ifndef NDEBUG + if (namedAttrMap) { + if (Attribute* attribute = namedAttrMap->getAttributeItem(name)) + ASSERT(isURLAttribute(attribute)); + } +#endif + return document()->completeURL(getAttribute(name)); +} + } // namespace WebCore diff --git a/WebCore/dom/Element.h b/WebCore/dom/Element.h index 025de1d..223c26a 100644 --- a/WebCore/dom/Element.h +++ b/WebCore/dom/Element.h @@ -61,7 +61,7 @@ public: void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&); void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&); - void scrollIntoView (bool alignToTop = true); + void scrollIntoView(bool alignToTop = true); void scrollIntoViewIfNeeded(bool centerIfNeeded = true); void scrollByUnits(int units, ScrollGranularity); @@ -136,6 +136,11 @@ public: // This method is called whenever an attribute is added, changed or removed. virtual void attributeChanged(Attribute*, bool preserveDecls = false); + // The implementation of Element::attributeChanged() calls the following two functions. + // They are separated to allow a different flow of control in StyledElement::attributeChanged(). + void recalcStyleIfNeededAfterAttributeChanged(Attribute*); + void updateAfterAttributeChanged(Attribute*); + // not part of the DOM void setAttributeMap(PassRefPtr<NamedNodeMap>); @@ -158,6 +163,7 @@ public: virtual void accessKeyAction(bool /*sendToAnyEvent*/) { } virtual bool isURLAttribute(Attribute*) const; + KURL getURLAttribute(const QualifiedName&) const; virtual const QualifiedName& imageSourceAttributeName() const; virtual String target() const { return String(); } virtual void focus(bool restorePreviousSelection = true); @@ -168,6 +174,8 @@ public: virtual void formatForDebugger(char* buffer, unsigned length) const; #endif + bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle); + String innerText() const; String outerText() const; @@ -203,6 +211,8 @@ public: virtual bool isEnabledFormControl() const { return true; } virtual bool isReadOnlyFormControl() const { return false; } virtual bool isTextFormControl() const { return false; } + virtual bool isOptionalFormControl() const { return false; } + virtual bool isRequiredFormControl() const { return false; } virtual bool formControlValueMatchesRenderer() const { return false; } virtual void setFormControlValueMatchesRenderer(bool) { } diff --git a/WebCore/dom/Element.idl b/WebCore/dom/Element.idl index 6e16bfe..53711e9 100644 --- a/WebCore/dom/Element.idl +++ b/WebCore/dom/Element.idl @@ -129,6 +129,77 @@ module core { readonly attribute DOMString innerText; #endif +#if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C +#if !defined(LANGUAGE_COM) || !LANGUAGE_COM + // Event handler DOM attributes + attribute [DontEnum] EventListener onabort; + attribute [DontEnum] EventListener onblur; + attribute [DontEnum] EventListener onchange; + attribute [DontEnum] EventListener onclick; + attribute [DontEnum] EventListener oncontextmenu; + attribute [DontEnum] EventListener ondblclick; + attribute [DontEnum] EventListener ondrag; + attribute [DontEnum] EventListener ondragend; + attribute [DontEnum] EventListener ondragenter; + attribute [DontEnum] EventListener ondragleave; + attribute [DontEnum] EventListener ondragover; + attribute [DontEnum] EventListener ondragstart; + attribute [DontEnum] EventListener ondrop; + attribute [DontEnum] EventListener onerror; + attribute [DontEnum] EventListener onfocus; + attribute [DontEnum] EventListener oninput; + attribute [DontEnum] EventListener onkeydown; + attribute [DontEnum] EventListener onkeypress; + attribute [DontEnum] EventListener onkeyup; + attribute [DontEnum] EventListener onload; + attribute [DontEnum] EventListener onmousedown; + attribute [DontEnum] EventListener onmousemove; + attribute [DontEnum] EventListener onmouseout; + attribute [DontEnum] EventListener onmouseover; + attribute [DontEnum] EventListener onmouseup; + attribute [DontEnum] EventListener onmousewheel; + attribute [DontEnum] EventListener onscroll; + attribute [DontEnum] EventListener onselect; + attribute [DontEnum] EventListener onsubmit; + + // attribute [DontEnum] EventListener oncanplay; + // attribute [DontEnum] EventListener oncanplaythrough; + // attribute [DontEnum] EventListener ondurationchange; + // attribute [DontEnum] EventListener onemptied; + // attribute [DontEnum] EventListener onended; + // attribute [DontEnum] EventListener onformchange; + // attribute [DontEnum] EventListener onforminput; + // attribute [DontEnum] EventListener oninvalid; + // attribute [DontEnum] EventListener onloadeddata; + // attribute [DontEnum] EventListener onloadedmetadata; + // attribute [DontEnum] EventListener onloadstart; + // attribute [DontEnum] EventListener onpause; + // attribute [DontEnum] EventListener onplay; + // attribute [DontEnum] EventListener onplaying; + // attribute [DontEnum] EventListener onprogress; + // attribute [DontEnum] EventListener onratechange; + // attribute [DontEnum] EventListener onreadystatechange; + // attribute [DontEnum] EventListener onseeked; + // attribute [DontEnum] EventListener onseeking; + // attribute [DontEnum] EventListener onshow; + // attribute [DontEnum] EventListener onstalled; + // attribute [DontEnum] EventListener onsuspend; + // attribute [DontEnum] EventListener ontimeupdate; + // attribute [DontEnum] EventListener onvolumechange; + // attribute [DontEnum] EventListener onwaiting; + + // WebKit extensions + attribute [DontEnum] EventListener onbeforecut; + attribute [DontEnum] EventListener oncut; + attribute [DontEnum] EventListener onbeforecopy; + attribute [DontEnum] EventListener oncopy; + attribute [DontEnum] EventListener onbeforepaste; + attribute [DontEnum] EventListener onpaste; + attribute [DontEnum] EventListener onreset; + attribute [DontEnum] EventListener onsearch; + attribute [DontEnum] EventListener onselectstart; +#endif +#endif }; } diff --git a/WebCore/dom/ErrorEvent.cpp b/WebCore/dom/ErrorEvent.cpp new file mode 100644 index 0000000..2627d01 --- /dev/null +++ b/WebCore/dom/ErrorEvent.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009 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" + +#if ENABLE(WORKERS) + +#include "ErrorEvent.h" + +#include "EventNames.h" + +namespace WebCore { + +ErrorEvent::ErrorEvent() +{ +} + +ErrorEvent::ErrorEvent(const String& message, const String& fileName, unsigned lineNumber) + : Event(eventNames().errorEvent, false, true) + , m_message(message) + , m_fileName(fileName) + , m_lineNumber(lineNumber) +{ +} + +ErrorEvent::~ErrorEvent() +{ +} + +void ErrorEvent::initErrorEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& message, const String& fileName, unsigned lineNumber) +{ + if (dispatched()) + return; + + initEvent(type, canBubble, cancelable); + + m_message = message; + m_fileName = fileName; + m_lineNumber = lineNumber; +} + +bool ErrorEvent::isErrorEvent() const +{ + return true; +} + +} // namespace WebCore + +#endif // ENABLE(WORKERS) diff --git a/WebCore/dom/ErrorEvent.h b/WebCore/dom/ErrorEvent.h new file mode 100644 index 0000000..f81530a --- /dev/null +++ b/WebCore/dom/ErrorEvent.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2009 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 ErrorEvent_h +#define ErrorEvent_h + +#if ENABLE(WORKERS) + +#include "Event.h" +#include "PlatformString.h" + +namespace WebCore { + + class ErrorEvent : public Event { + public: + static PassRefPtr<ErrorEvent> create() + { + return adoptRef(new ErrorEvent); + } + static PassRefPtr<ErrorEvent> create(const String& message, const String& fileName, unsigned lineNumber) + { + return adoptRef(new ErrorEvent(message, fileName, lineNumber)); + } + virtual ~ErrorEvent(); + + void initErrorEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& message, const String& fileName, unsigned lineNumber); + + const String& message() const { return m_message; } + const String& filename() const { return m_fileName; } + unsigned lineno() const { return m_lineNumber; } + + virtual bool isErrorEvent() const; + + private: + ErrorEvent(); + ErrorEvent(const String& message, const String& fileName, unsigned lineNumber); + + String m_message; + String m_fileName; + unsigned m_lineNumber; + }; + +} // namespace WebCore + +#endif // ENABLE(WORKERS) + +#endif // ErrorEvent_h diff --git a/WebCore/dom/ErrorEvent.idl b/WebCore/dom/ErrorEvent.idl new file mode 100644 index 0000000..6125e1e --- /dev/null +++ b/WebCore/dom/ErrorEvent.idl @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2009 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. + */ + +module events { + + interface [ + Conditional=WORKERS, + GenerateConstructor, + NoStaticTables + ] ErrorEvent : Event { + + readonly attribute DOMString message; + readonly attribute DOMString filename; + readonly attribute unsigned long lineno; + + void initErrorEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString messageArg, in DOMString filenameArg, in unsigned long linenoArg); + }; + +} diff --git a/WebCore/dom/Event.cpp b/WebCore/dom/Event.cpp index 53242b6..2feef9a 100644 --- a/WebCore/dom/Event.cpp +++ b/WebCore/dom/Event.cpp @@ -158,6 +158,7 @@ bool Event::isStorageEvent() const } #endif +#ifdef MANUAL_MERGE_REQUIRED #if ENABLE(TOUCH_EVENTS) // Android bool Event::isTouchEvent() const { @@ -165,6 +166,15 @@ bool Event::isTouchEvent() const } #endif +#else // MANUAL_MERGE_REQUIRED +#if ENABLE(WORKERS) +bool Event::isErrorEvent() const +{ + return false; +} +#endif + +#endif // MANUAL_MERGE_REQUIRED bool Event::storesResultAsString() const { return false; diff --git a/WebCore/dom/Event.h b/WebCore/dom/Event.h index 2e7f376..85d4cb2 100644 --- a/WebCore/dom/Event.h +++ b/WebCore/dom/Event.h @@ -119,10 +119,17 @@ namespace WebCore { #if ENABLE(DOM_STORAGE) virtual bool isStorageEvent() const; #endif +#ifdef MANUAL_MERGE_REQUIRED #if ENABLE(TOUCH_EVENTS) // Android virtual bool isTouchEvent() const; #endif +#else // MANUAL_MERGE_REQUIRED +#if ENABLE(WORKERS) + virtual bool isErrorEvent() const; +#endif + +#endif // MANUAL_MERGE_REQUIRED bool propagationStopped() const { return m_propagationStopped; } bool defaultPrevented() const { return m_defaultPrevented; } diff --git a/WebCore/dom/Event.idl b/WebCore/dom/Event.idl index 5ac9e0c..75b6b5f 100644 --- a/WebCore/dom/Event.idl +++ b/WebCore/dom/Event.idl @@ -22,6 +22,7 @@ module events { // Introduced in DOM Level 2: interface [ + CustomToJS, GenerateConstructor, NoStaticTables, Polymorphic, diff --git a/WebCore/dom/EventListener.h b/WebCore/dom/EventListener.h index dbc41b2..7c4812f 100644 --- a/WebCore/dom/EventListener.h +++ b/WebCore/dom/EventListener.h @@ -21,10 +21,12 @@ #ifndef EventListener_h #define EventListener_h +#include "PlatformString.h" #include <wtf/RefCounted.h> namespace JSC { class JSObject; + class MarkStack; } namespace WebCore { @@ -35,11 +37,13 @@ namespace WebCore { public: virtual ~EventListener() { } virtual void handleEvent(Event*, bool isWindowEvent = false) = 0; + // Return true to indicate that the error is handled. + virtual bool reportError(const String& /*message*/, const String& /*url*/, int /*lineNumber*/) { return false; } virtual bool wasCreatedFromMarkup() const { return false; } #if USE(JSC) virtual JSC::JSObject* jsFunction() const { return 0; } - virtual void markJSFunction() { } + virtual void markJSFunction(JSC::MarkStack&) { } #endif bool isAttribute() const { return virtualisAttribute(); } @@ -49,7 +53,7 @@ namespace WebCore { }; #if USE(JSC) - inline void markIfNotNull(EventListener* listener) { if (listener) listener->markJSFunction(); } + inline void markIfNotNull(JSC::MarkStack& markStack, EventListener* listener) { if (listener) listener->markJSFunction(markStack); } #endif } diff --git a/WebCore/dom/EventNames.h b/WebCore/dom/EventNames.h index 28a66bc..d28b154 100644 --- a/WebCore/dom/EventNames.h +++ b/WebCore/dom/EventNames.h @@ -40,6 +40,7 @@ namespace WebCore { macro(checking) \ macro(click) \ macro(close) \ + macro(connect) \ macro(contextmenu) \ macro(copy) \ macro(cut) \ @@ -54,6 +55,7 @@ namespace WebCore { macro(drop) \ macro(error) \ macro(focus) \ + macro(hashchange) \ macro(input) \ macro(keydown) \ macro(keypress) \ diff --git a/WebCore/dom/EventTarget.cpp b/WebCore/dom/EventTarget.cpp index 06cea07..7ba0584 100644 --- a/WebCore/dom/EventTarget.cpp +++ b/WebCore/dom/EventTarget.cpp @@ -89,7 +89,18 @@ Worker* EventTarget::toWorker() return 0; } -WorkerContext* EventTarget::toWorkerContext() +DedicatedWorkerContext* EventTarget::toDedicatedWorkerContext() +{ + return 0; +} +#endif + +#if ENABLE(SHARED_WORKERS) +SharedWorker* EventTarget::toSharedWorker() +{ + return 0; +} +SharedWorkerContext* EventTarget::toSharedWorkerContext() { return 0; } diff --git a/WebCore/dom/EventTarget.h b/WebCore/dom/EventTarget.h index 662902e..2ededda 100644 --- a/WebCore/dom/EventTarget.h +++ b/WebCore/dom/EventTarget.h @@ -36,7 +36,9 @@ namespace WebCore { + class AbstractWorker; class AtomicString; + class DedicatedWorkerContext; class DOMApplicationCache; class DOMWindow; class Event; @@ -45,8 +47,9 @@ namespace WebCore { class Node; class SVGElementInstance; class ScriptExecutionContext; + class SharedWorker; + class SharedWorkerContext; class Worker; - class WorkerContext; class XMLHttpRequest; class XMLHttpRequestUpload; @@ -67,7 +70,12 @@ namespace WebCore { #endif #if ENABLE(WORKERS) virtual Worker* toWorker(); - virtual WorkerContext* toWorkerContext(); + virtual DedicatedWorkerContext* toDedicatedWorkerContext(); +#endif + +#if ENABLE(SHARED_WORKERS) + virtual SharedWorker* toSharedWorker(); + virtual SharedWorkerContext* toSharedWorkerContext(); #endif virtual ScriptExecutionContext* scriptExecutionContext() const = 0; diff --git a/WebCore/dom/HTMLAllCollection.idl b/WebCore/dom/HTMLAllCollection.idl new file mode 100644 index 0000000..dee365f --- /dev/null +++ b/WebCore/dom/HTMLAllCollection.idl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2008, 2009 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. + */ + +module html { + + // This interface is used for undetectable HTMLCollections. + // An undetectable HTMLCollection behaves like an HTMLCollection + // when used, but the 'typeof' operator returns undefined and + // ToBoolean returns false. + interface HTMLAllCollection : HTMLCollection { + }; + +} diff --git a/WebCore/dom/InputElement.cpp b/WebCore/dom/InputElement.cpp index 108d17e..0e2456d 100644 --- a/WebCore/dom/InputElement.cpp +++ b/WebCore/dom/InputElement.cpp @@ -93,7 +93,7 @@ void InputElement::updatePlaceholderVisibility(InputElementData& data, InputElem && !inputElement->placeholder().isEmpty()); if ((oldPlaceholderShouldBeVisible != data.placeholderShouldBeVisible() || placeholderValueChanged) && element->renderer()) - static_cast<RenderTextControlSingleLine*>(element->renderer())->updatePlaceholderVisibility(); + toRenderTextControlSingleLine(element->renderer())->updatePlaceholderVisibility(); } void InputElement::updateFocusAppearance(InputElementData& data, InputElement* inputElement, Element* element, bool restorePreviousSelection) @@ -116,6 +116,8 @@ void InputElement::updateSelectionRange(InputElement* inputElement, Element* ele if (!inputElement->isTextField()) return; + element->document()->updateLayoutIgnorePendingStylesheets(); + if (RenderTextControl* renderer = toRenderTextControl(element->renderer())) renderer->setSelectionRange(start, end); } diff --git a/WebCore/dom/MessageChannel.cpp b/WebCore/dom/MessageChannel.cpp index 3a90913..73c016f 100644 --- a/WebCore/dom/MessageChannel.cpp +++ b/WebCore/dom/MessageChannel.cpp @@ -28,14 +28,15 @@ #include "MessageChannel.h" #include "MessagePort.h" +#include "MessagePortChannel.h" namespace WebCore { MessageChannel::MessageChannel(ScriptExecutionContext* context) - : m_port1(MessagePort::create(context)) - , m_port2(MessagePort::create(context)) + : m_port1(MessagePort::create(*context)) + , m_port2(MessagePort::create(*context)) { - MessagePort::entangle(m_port1.get(), m_port2.get()); + MessagePortChannel::createChannel(m_port1.get(), m_port2.get()); } MessageChannel::~MessageChannel() diff --git a/WebCore/dom/MessagePort.cpp b/WebCore/dom/MessagePort.cpp index efd89e7..9f3e4d2 100644 --- a/WebCore/dom/MessagePort.cpp +++ b/WebCore/dom/MessagePort.cpp @@ -38,89 +38,23 @@ namespace WebCore { -class MessagePortCloseEventTask : public ScriptExecutionContext::Task { -public: - static PassRefPtr<MessagePortCloseEventTask> create(PassRefPtr<MessagePort> port) - { - return adoptRef(new MessagePortCloseEventTask(port)); - } - -private: - MessagePortCloseEventTask(PassRefPtr<MessagePort> port) - : m_port(port) - { - ASSERT(m_port); - } - - virtual void performTask(ScriptExecutionContext* unusedContext) - { - ASSERT_UNUSED(unusedContext, unusedContext == m_port->scriptExecutionContext()); - ASSERT(!m_port->active()); - - // Closing may destroy the port, dispatch any remaining messages now. - if (m_port->queueIsOpen()) - m_port->dispatchMessages(); - - m_port->dispatchCloseEvent(); - } - - RefPtr<MessagePort> m_port; -}; - -PassRefPtr<MessagePort::EventData> MessagePort::EventData::create(const String& message, PassRefPtr<MessagePort> port) -{ - return adoptRef(new EventData(message, port)); -} - -MessagePort::EventData::EventData(const String& message, PassRefPtr<MessagePort> messagePort) - : message(message.copy()) - , messagePort(messagePort) -{ -} - -MessagePort::EventData::~EventData() +MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext) + : m_entangledChannel(0) + , m_started(false) + , m_scriptExecutionContext(&scriptExecutionContext) { -} + m_scriptExecutionContext->createdMessagePort(this); -MessagePort::MessagePort(ScriptExecutionContext* scriptExecutionContext) - : m_entangledPort(0) - , m_queueIsOpen(false) - , m_scriptExecutionContext(scriptExecutionContext) - , m_pendingCloseEvent(false) -{ - if (scriptExecutionContext) - scriptExecutionContext->createdMessagePort(this); + // Don't need to call processMessagePortMessagesSoon() here, because the port will not be opened until start() is invoked. } MessagePort::~MessagePort() { - if (m_entangledPort) - unentangle(); - + close(); if (m_scriptExecutionContext) m_scriptExecutionContext->destroyedMessagePort(this); } -PassRefPtr<MessagePort> MessagePort::clone(ExceptionCode& ec) -{ - if (!m_entangledPort) { - ec = INVALID_STATE_ERR; - return 0; - } - - RefPtr<MessagePortProxy> remotePort = m_entangledPort; - RefPtr<MessagePort> newPort = MessagePort::create(0); - - // Move all the events in the port message queue of original port to the port message queue of new port, if any, leaving the new port's port message queue in its initial closed state. - // If events are posted (e.g. from a worker thread) while this code is executing, there is no guarantee whether they end up in the original or new port's message queue. - RefPtr<EventData> eventData; - while (m_messageQueue.tryGetMessage(eventData)) - newPort->m_messageQueue.append(eventData); - - entangle(remotePort.get(), newPort.get()); // The port object will be unentangled. - return newPort; -} - void MessagePort::postMessage(const String& message, ExceptionCode& ec) { postMessage(message, 0, ec); @@ -128,112 +62,86 @@ void MessagePort::postMessage(const String& message, ExceptionCode& ec) void MessagePort::postMessage(const String& message, MessagePort* dataPort, ExceptionCode& ec) { - if (!m_entangledPort || !m_scriptExecutionContext) + if (!m_entangledChannel) return; + ASSERT(m_scriptExecutionContext); - RefPtr<MessagePort> newMessagePort; + OwnPtr<MessagePortChannel> channel; if (dataPort) { - if (dataPort == this || dataPort == m_entangledPort) { - ec = INVALID_ACCESS_ERR; + if (dataPort == this || m_entangledChannel->isConnectedTo(dataPort)) { + ec = INVALID_STATE_ERR; return; } - ec = 0; - newMessagePort = dataPort->clone(ec); + channel = dataPort->disentangle(ec); if (ec) return; } - - m_entangledPort->deliverMessage(message, newMessagePort); + m_entangledChannel->postMessageToRemote(MessagePortChannel::EventData::create(message, channel.release())); } -void MessagePort::deliverMessage(const String& message, PassRefPtr<MessagePort> dataPort) +PassOwnPtr<MessagePortChannel> MessagePort::disentangle(ExceptionCode& ec) { - m_messageQueue.append(EventData::create(message, dataPort)); - if (m_queueIsOpen && m_scriptExecutionContext) - m_scriptExecutionContext->processMessagePortMessagesSoon(); + if (!m_entangledChannel) + ec = INVALID_STATE_ERR; + else { + m_entangledChannel->disentangle(); + + // We can't receive any messages or generate any events, so remove ourselves from the list of active ports. + ASSERT(m_scriptExecutionContext); + m_scriptExecutionContext->destroyedMessagePort(this); + m_scriptExecutionContext = 0; + } + return m_entangledChannel.release(); } -PassRefPtr<MessagePort> MessagePort::startConversation(ScriptExecutionContext* scriptExecutionContext, const String& message) +// Invoked to notify us that there are messages available for this port. +// This code may be called from another thread, and so should not call any non-threadsafe APIs (i.e. should not call into the entangled channel or access mutable variables). +void MessagePort::messageAvailable() { - RefPtr<MessagePort> port1 = MessagePort::create(scriptExecutionContext); - if (!m_entangledPort || !m_scriptExecutionContext) - return port1; - RefPtr<MessagePort> port2 = MessagePort::create(0); - - entangle(port1.get(), port2.get()); - - m_entangledPort->deliverMessage(message, port2); - return port1; + ASSERT(m_scriptExecutionContext); + m_scriptExecutionContext->processMessagePortMessagesSoon(); } void MessagePort::start() { - if (m_queueIsOpen || !m_scriptExecutionContext) + // Do nothing if we've been cloned + if (!m_entangledChannel) + return; + + ASSERT(m_scriptExecutionContext); + if (m_started) return; - m_queueIsOpen = true; + m_started = true; m_scriptExecutionContext->processMessagePortMessagesSoon(); } void MessagePort::close() { - if (!m_entangledPort) + if (!m_entangledChannel) return; - - MessagePortProxy* otherPort = m_entangledPort; - unentangle(); - - queueCloseEvent(); - otherPort->queueCloseEvent(); -} - -void MessagePort::entangle(MessagePortProxy* port1, MessagePortProxy* port2) -{ - port1->entangle(port2); - port2->entangle(port1); + m_entangledChannel->close(); } -void MessagePort::entangle(MessagePortProxy* remote) +void MessagePort::entangle(PassOwnPtr<MessagePortChannel> remote) { - // Unentangle from our current port first. - if (m_entangledPort) { - ASSERT(m_entangledPort != remote); - unentangle(); - } - m_entangledPort = remote; -} + // Only invoked to set our initial entanglement. + ASSERT(!m_entangledChannel); + ASSERT(m_scriptExecutionContext); -void MessagePort::unentangle() -{ - // Unentangle our end before unentangling the other end. - if (m_entangledPort) { - MessagePortProxy* remote = m_entangledPort; - m_entangledPort = 0; - remote->unentangle(); - } + // Don't entangle the ports if the channel is closed. + if (remote->entangleIfOpen(this)) + m_entangledChannel = remote; } void MessagePort::contextDestroyed() { ASSERT(m_scriptExecutionContext); - - if (m_entangledPort) - unentangle(); - + // Must close port before blowing away the cached context, to ensure that we get no more calls to messageAvailable(). + close(); m_scriptExecutionContext = 0; } -void MessagePort::attachToContext(ScriptExecutionContext* scriptExecutionContext) -{ - ASSERT(!m_scriptExecutionContext); - ASSERT(!m_queueIsOpen); - - m_scriptExecutionContext = scriptExecutionContext; - m_scriptExecutionContext->createdMessagePort(this); - - // FIXME: Need to call processMessagePortMessagesSoon()? -} - ScriptExecutionContext* MessagePort::scriptExecutionContext() const { return m_scriptExecutionContext; @@ -242,17 +150,19 @@ ScriptExecutionContext* MessagePort::scriptExecutionContext() const void MessagePort::dispatchMessages() { // Messages for contexts that are not fully active get dispatched too, but JSAbstractEventListener::handleEvent() doesn't call handlers for these. - // FIXME: Such messages should be dispatched if the document returns from page cache. They are only allowed to be lost if the document is discarded. - ASSERT(queueIsOpen()); - - RefPtr<EventData> eventData; - while (m_messageQueue.tryGetMessage(eventData)) { - - ASSERT(!eventData->messagePort || !eventData->messagePort->m_scriptExecutionContext); - if (eventData->messagePort) - eventData->messagePort->attachToContext(m_scriptExecutionContext); - - RefPtr<Event> evt = MessageEvent::create(eventData->message, "", "", 0, eventData->messagePort); + // The HTML5 spec specifies that any messages sent to a document that is not fully active should be dropped, so this behavior is OK. + ASSERT(started()); + + OwnPtr<MessagePortChannel::EventData> eventData; + while (m_entangledChannel && m_entangledChannel->tryGetMessageFromRemote(eventData)) { + RefPtr<MessagePort> port; + OwnPtr<MessagePortChannel> channel = eventData->channel(); + if (channel) { + // The remote side sent over a MessagePortChannel, so create a MessagePort to wrap it. + port = MessagePort::create(*m_scriptExecutionContext); + port->entangle(channel.release()); + } + RefPtr<Event> evt = MessageEvent::create(eventData->message(), "", "", 0, port.release()); if (m_onMessageListener) { evt->setTarget(this); @@ -266,31 +176,6 @@ void MessagePort::dispatchMessages() } } -void MessagePort::queueCloseEvent() -{ - ASSERT(!m_pendingCloseEvent); - m_pendingCloseEvent = true; - - m_scriptExecutionContext->postTask(MessagePortCloseEventTask::create(this)); -} - -void MessagePort::dispatchCloseEvent() -{ - ASSERT(m_pendingCloseEvent); - m_pendingCloseEvent = false; - - RefPtr<Event> evt = Event::create(eventNames().closeEvent, false, true); - if (m_onCloseListener) { - evt->setTarget(this); - evt->setCurrentTarget(this); - m_onCloseListener->handleEvent(evt.get(), false); - } - - ExceptionCode ec = 0; - dispatchEvent(evt.release(), ec); - ASSERT(!ec); -} - void MessagePort::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool) { EventListenersMap::iterator iter = m_eventListeners.find(eventType); @@ -342,9 +227,22 @@ bool MessagePort::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec) return !event->defaultPrevented(); } +void MessagePort::setOnmessage(PassRefPtr<EventListener> eventListener) +{ + m_onMessageListener = eventListener; + start(); +} + bool MessagePort::hasPendingActivity() { - return m_pendingCloseEvent || (m_queueIsOpen && !m_messageQueue.isEmpty()); + // The spec says that entangled message ports should always be treated as if they have a strong reference. + // We'll also stipulate that the queue needs to be open (if the app drops its reference to the port before start()-ing it, then it's not really entangled as it's unreachable). + return m_started && m_entangledChannel && m_entangledChannel->hasPendingActivity(); +} + +MessagePort* MessagePort::locallyEntangledPort() +{ + return m_entangledChannel ? m_entangledChannel->locallyEntangledPort(m_scriptExecutionContext) : 0; } } // namespace WebCore diff --git a/WebCore/dom/MessagePort.h b/WebCore/dom/MessagePort.h index 054ae41..f416b9b 100644 --- a/WebCore/dom/MessagePort.h +++ b/WebCore/dom/MessagePort.h @@ -30,10 +30,11 @@ #include "AtomicStringHash.h" #include "EventListener.h" #include "EventTarget.h" -#include "MessagePortProxy.h" +#include "MessagePortChannel.h" #include <wtf/HashMap.h> -#include <wtf/MessageQueue.h> +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> #include <wtf/Vector.h> @@ -45,35 +46,25 @@ namespace WebCore { class Frame; class ScriptExecutionContext; class String; - class WorkerContext; - class MessagePort : public MessagePortProxy, public EventTarget { + class MessagePort : public RefCounted<MessagePort>, public EventTarget { public: - static PassRefPtr<MessagePort> create(ScriptExecutionContext* scriptExecutionContext) { return adoptRef(new MessagePort(scriptExecutionContext)); } + static PassRefPtr<MessagePort> create(ScriptExecutionContext& scriptExecutionContext) { return adoptRef(new MessagePort(scriptExecutionContext)); } ~MessagePort(); - PassRefPtr<MessagePort> clone(ExceptionCode&); // Returns a port that isn't attached to any context. - - bool active() const { return m_entangledPort; } void postMessage(const String& message, ExceptionCode&); void postMessage(const String& message, MessagePort*, ExceptionCode&); - PassRefPtr<MessagePort> startConversation(ScriptExecutionContext*, const String& message); void start(); void close(); - // Implementations of MessagePortProxy APIs - virtual void entangle(MessagePortProxy*); - virtual void unentangle(); - virtual void deliverMessage(const String& message, PassRefPtr<MessagePort>); - virtual void queueCloseEvent(); - - bool queueIsOpen() const { return m_queueIsOpen; } + void entangle(PassOwnPtr<MessagePortChannel>); + PassOwnPtr<MessagePortChannel> disentangle(ExceptionCode&); - MessagePortProxy* entangledPort() { return m_entangledPort; } - static void entangle(MessagePortProxy*, MessagePortProxy*); + void messageAvailable(); + bool started() const { return m_started; } void contextDestroyed(); - void attachToContext(ScriptExecutionContext*); + virtual ScriptExecutionContext* scriptExecutionContext() const; virtual MessagePort* toMessagePort() { return this; } @@ -88,52 +79,35 @@ namespace WebCore { typedef HashMap<AtomicString, ListenerVector> EventListenersMap; EventListenersMap& eventListeners() { return m_eventListeners; } - using RefCounted<MessagePortProxy>::ref; - using RefCounted<MessagePortProxy>::deref; + using RefCounted<MessagePort>::ref; + using RefCounted<MessagePort>::deref; bool hasPendingActivity(); - // FIXME: Per current spec, setting onmessage should automagically start the port (unlike addEventListener("message", ...)). - void setOnmessage(PassRefPtr<EventListener> eventListener) { m_onMessageListener = eventListener; } + void setOnmessage(PassRefPtr<EventListener>); EventListener* onmessage() const { return m_onMessageListener.get(); } - void setOnclose(PassRefPtr<EventListener> eventListener) { m_onCloseListener = eventListener; } - EventListener* onclose() const { return m_onCloseListener.get(); } + // Returns null if there is no entangled port, or if the entangled port is run by a different thread. + // Returns null otherwise. + // NOTE: This is used solely to enable a GC optimization. Some platforms may not be able to determine ownership of the remote port (since it may live cross-process) - those platforms may always return null. + MessagePort* locallyEntangledPort(); + bool isEntangled() { return m_entangledChannel; } private: - friend class MessagePortCloseEventTask; - - MessagePort(ScriptExecutionContext*); + MessagePort(ScriptExecutionContext&); virtual void refEventTarget() { ref(); } virtual void derefEventTarget() { deref(); } - void dispatchCloseEvent(); + OwnPtr<MessagePortChannel> m_entangledChannel; - MessagePortProxy* m_entangledPort; - - // FIXME: EventData is necessary to pass messages to other threads. In single threaded case, we can just queue a created event. - struct EventData : public RefCounted<EventData> { - static PassRefPtr<EventData> create(const String& message, PassRefPtr<MessagePort>); - ~EventData(); - - String message; - RefPtr<MessagePort> messagePort; - - private: - EventData(const String& message, PassRefPtr<MessagePort>); - }; - MessageQueue<RefPtr<EventData> > m_messageQueue; // FIXME: No need to use MessageQueue in single threaded case. - bool m_queueIsOpen; + bool m_started; ScriptExecutionContext* m_scriptExecutionContext; RefPtr<EventListener> m_onMessageListener; - RefPtr<EventListener> m_onCloseListener; EventListenersMap m_eventListeners; - - bool m_pendingCloseEvent; // The port is GC protected while waiting for a close event to be dispatched. }; } // namespace WebCore diff --git a/WebCore/dom/MessagePort.idl b/WebCore/dom/MessagePort.idl index 03c6bab..e5f9ad1 100644 --- a/WebCore/dom/MessagePort.idl +++ b/WebCore/dom/MessagePort.idl @@ -34,16 +34,13 @@ module events { // We need to have something as an ObjC binding, because MessagePort is used in MessageEvent, which already has one, // but we don't want to actually expose the API while it is in flux. #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT - readonly attribute boolean active; void postMessage(in DOMString message, in [Optional] MessagePort messagePort) raises(DOMException); - [Custom] MessagePort startConversation(in DOMString message); void start(); void close(); // event handler attributes attribute EventListener onmessage; - attribute EventListener onclose; // EventTarget interface [Custom] void addEventListener(in DOMString type, diff --git a/WebCore/dom/MessagePortProxy.h b/WebCore/dom/MessagePortChannel.cpp index d024f3d..05134c0 100644 --- a/WebCore/dom/MessagePortProxy.h +++ b/WebCore/dom/MessagePortChannel.cpp @@ -1,54 +1,47 @@ -/*
- * Copyright (C) 2009 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 MessagePortProxy_h
-#define MessagePortProxy_h
-
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
-
-namespace WebCore {
-
- class MessagePort;
- class String;
-
- class MessagePortProxy : public RefCounted<MessagePortProxy> {
- public:
- virtual ~MessagePortProxy() { }
-
- virtual void entangle(MessagePortProxy*) = 0;
- virtual void unentangle() = 0;
- virtual void deliverMessage(const String& message, PassRefPtr<MessagePort>) = 0;
- virtual void queueCloseEvent() = 0;
- };
-
-} // namespace WebCore
-
-#endif // MessagePortProxy_h
+/* + * Copyright (C) 2009 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 "MessagePortChannel.h" + +namespace WebCore { + + +PassOwnPtr<MessagePortChannel::EventData> MessagePortChannel::EventData::create(const String& message, PassOwnPtr<MessagePortChannel> channel) +{ + return new EventData(message, channel); +} + +MessagePortChannel::EventData::EventData(const String& message, PassOwnPtr<MessagePortChannel> channel) + : m_message(message.copy()) + , m_channel(channel) +{ +} + +} // namespace WebCore diff --git a/WebCore/dom/MessagePortChannel.h b/WebCore/dom/MessagePortChannel.h new file mode 100644 index 0000000..93b224b --- /dev/null +++ b/WebCore/dom/MessagePortChannel.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2009 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 MessagePortChannel_h +#define MessagePortChannel_h + +#include "PlatformString.h" + +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + + class MessagePort; + class PlatformMessagePortChannel; + class ScriptExecutionContext; + class String; + + // MessagePortChannel is a platform-independent interface to the remote side of a message channel. + // It acts as a wrapper around the platform-dependent PlatformMessagePortChannel implementation which ensures that the platform-dependent close() method is invoked before destruction. + class MessagePortChannel : public Noncopyable { + public: + static void createChannel(PassRefPtr<MessagePort>, PassRefPtr<MessagePort>); + + // Creates a new wrapper for the passed channel. + static PassOwnPtr<MessagePortChannel> create(PassRefPtr<PlatformMessagePortChannel>); + + // Entangles the channel with a port (called when a port has been cloned, after the clone has been marshalled to its new owning thread and is ready to receive messages). + // Returns false if the entanglement failed because the port was closed. + bool entangleIfOpen(MessagePort*); + + // Disentangles the channel from a given port so it no longer forwards messages to the port. Called when the port is being cloned and no new owning thread has yet been established. + void disentangle(); + + // Closes the port (ensures that no further messages can be added to either queue). + void close(); + + // Used by MessagePort.postMessage() to prevent callers from passing a port's own entangled port. + bool isConnectedTo(MessagePort*); + + // Returns true if the proxy currently contains messages for this port. + bool hasPendingActivity(); + + class EventData { + public: + static PassOwnPtr<EventData> create(const String&, PassOwnPtr<MessagePortChannel>); + + const String& message() { return m_message; } + PassOwnPtr<MessagePortChannel> channel() { return m_channel.release(); } + + private: + EventData(const String& message, PassOwnPtr<MessagePortChannel>); + String m_message; + OwnPtr<MessagePortChannel> m_channel; + }; + + // Sends a message and optional cloned port to the remote port. + void postMessageToRemote(PassOwnPtr<EventData>); + + // Extracts a message from the message queue for this port. + bool tryGetMessageFromRemote(OwnPtr<EventData>&); + + // Returns the entangled port if run by the same thread (see MessagePort::locallyEntangledPort() for more details). + MessagePort* locallyEntangledPort(const ScriptExecutionContext*); + + ~MessagePortChannel(); + + PlatformMessagePortChannel* channel() const { return m_channel.get(); } + + private: + MessagePortChannel(PassRefPtr<PlatformMessagePortChannel>); + RefPtr<PlatformMessagePortChannel> m_channel; + }; + +} // namespace WebCore + +#endif // MessagePortChannel_h diff --git a/WebCore/dom/NamedAttrMap.cpp b/WebCore/dom/NamedAttrMap.cpp index f3e9bb2..fe631c8 100644 --- a/WebCore/dom/NamedAttrMap.cpp +++ b/WebCore/dom/NamedAttrMap.cpp @@ -164,7 +164,7 @@ PassRefPtr<Node> NamedNodeMap::removeNamedItem(const QualifiedName& name, Except return r.release(); } -PassRefPtr<Node> NamedNodeMap::item (unsigned index) const +PassRefPtr<Node> NamedNodeMap::item(unsigned index) const { if (index >= length()) return 0; diff --git a/WebCore/dom/Node.cpp b/WebCore/dom/Node.cpp index 5fbebb9..c475958 100644 --- a/WebCore/dom/Node.cpp +++ b/WebCore/dom/Node.cpp @@ -287,7 +287,7 @@ void Node::stopIgnoringLeaks() #endif } -Node::StyleChange Node::diff( RenderStyle *s1, RenderStyle *s2 ) +Node::StyleChange Node::diff(const RenderStyle* s1, const RenderStyle* s2) { // FIXME: The behavior of this function is just totally wrong. It doesn't handle // explicit inheritance of non-inherited properties and so you end up not re-resolving @@ -307,6 +307,12 @@ Node::StyleChange Node::diff( RenderStyle *s1, RenderStyle *s2 ) else if (s1->inheritedNotEqual(s2)) ch = Inherit; + // For nth-child and other positional rules, treat styles as different if they have + // changed positionally in the DOM. This way subsequent sibling resolutions won't be confused + // by the wrong child index and evaluate to incorrect results. + if (ch == NoChange && s1->childIndex() != s2->childIndex()) + ch = NoInherit; + // If the pseudoStyles have changed, we want any StyleChange that is not NoChange // because setStyle will do the right thing with anything else. if (ch == NoChange && s1->hasPseudoStyle(BEFORE)) { @@ -494,7 +500,7 @@ void Node::setTabIndexExplicitly(short i) String Node::nodeValue() const { - return String(); + return String(); } void Node::setNodeValue(const String& /*nodeValue*/, ExceptionCode& ec) @@ -516,7 +522,7 @@ PassRefPtr<NodeList> Node::childNodes() document()->addNodeListCache(); } - return ChildNodeList::create(this, &data->nodeLists()->m_childNodeListCaches); + return ChildNodeList::create(this, data->nodeLists()->m_childNodeListCaches.get()); } Node *Node::lastDescendant() const @@ -776,7 +782,7 @@ unsigned Node::nodeIndex() const { Node *_tempNode = previousSibling(); unsigned count=0; - for( count=0; _tempNode; count++ ) + for ( count=0; _tempNode; count++ ) _tempNode = _tempNode->previousSibling(); return count; } @@ -1358,6 +1364,14 @@ bool Node::canStartSelection() const { if (isContentEditable()) return true; + + if (renderer()) { + RenderStyle* style = renderer()->style(); + // We allow selections to begin within an element that has -webkit-user-select: none set, + // but if the element is draggable then dragging should take priority over selection. + if (style->userDrag() == DRAG_ELEMENT && style->userSelect() == SELECT_NONE) + return false; + } return parent() ? parent()->canStartSelection() : true; } @@ -1491,9 +1505,9 @@ PassRefPtr<NodeList> Node::getElementsByTagNameNS(const AtomicString& namespaceU pair<NodeListsNodeData::TagCacheMap::iterator, bool> result = data->nodeLists()->m_tagNodeListCaches.add(QualifiedName(nullAtom, localNameAtom, namespaceURI), 0); if (result.second) - result.first->second = new DynamicNodeList::Caches; + result.first->second = DynamicNodeList::Caches::create(); - return TagNodeList::create(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localNameAtom, result.first->second); + return TagNodeList::create(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localNameAtom, result.first->second.get()); } PassRefPtr<NodeList> Node::getElementsByName(const String& elementName) @@ -1506,9 +1520,9 @@ PassRefPtr<NodeList> Node::getElementsByName(const String& elementName) pair<NodeListsNodeData::CacheMap::iterator, bool> result = data->nodeLists()->m_nameNodeListCaches.add(elementName, 0); if (result.second) - result.first->second = new DynamicNodeList::Caches; + result.first->second = DynamicNodeList::Caches::create(); - return NameNodeList::create(this, elementName, result.first->second); + return NameNodeList::create(this, elementName, result.first->second.get()); } PassRefPtr<NodeList> Node::getElementsByClassName(const String& classNames) @@ -1521,9 +1535,9 @@ PassRefPtr<NodeList> Node::getElementsByClassName(const String& classNames) pair<NodeListsNodeData::CacheMap::iterator, bool> result = data->nodeLists()->m_classNodeListCaches.add(classNames, 0); if (result.second) - result.first->second = new DynamicNodeList::Caches; + result.first->second = DynamicNodeList::Caches::create(); - return ClassNodeList::create(this, classNames, result.first->second); + return ClassNodeList::create(this, classNames, result.first->second.get()); } template <typename Functor> @@ -2212,7 +2226,7 @@ void Node::formatForDebugger(char* buffer, unsigned length) const void NodeListsNodeData::invalidateCaches() { - m_childNodeListCaches.reset(); + m_childNodeListCaches->reset(); TagCacheMap::const_iterator tagCachesEnd = m_tagNodeListCaches.end(); for (TagCacheMap::const_iterator it = m_tagNodeListCaches.begin(); it != tagCachesEnd; ++it) it->second->reset(); @@ -2235,24 +2249,24 @@ bool NodeListsNodeData::isEmpty() const if (!m_listsWithCaches.isEmpty()) return false; - if (m_childNodeListCaches.refCount) + if (m_childNodeListCaches->refCount()) return false; TagCacheMap::const_iterator tagCachesEnd = m_tagNodeListCaches.end(); for (TagCacheMap::const_iterator it = m_tagNodeListCaches.begin(); it != tagCachesEnd; ++it) { - if (it->second->refCount) + if (it->second->refCount()) return false; } CacheMap::const_iterator classCachesEnd = m_classNodeListCaches.end(); for (CacheMap::const_iterator it = m_classNodeListCaches.begin(); it != classCachesEnd; ++it) { - if (it->second->refCount) + if (it->second->refCount()) return false; } CacheMap::const_iterator nameCachesEnd = m_nameNodeListCaches.end(); for (CacheMap::const_iterator it = m_nameNodeListCaches.begin(); it != nameCachesEnd; ++it) { - if (it->second->refCount) + if (it->second->refCount()) return false; } @@ -2559,7 +2573,7 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) event->setEventPhase(Event::CAPTURING_PHASE); if (targetForWindowEvents) { - event->setCurrentTarget(targetForWindowEvents->document()); // FIXME: targetForWindowEvents should be the event target. + event->setCurrentTarget(targetForWindowEvents); targetForWindowEvents->handleEvent(event.get(), true); if (event->propagationStopped()) goto doneDispatching; @@ -2597,7 +2611,7 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) goto doneDispatching; } if (targetForWindowEvents) { - event->setCurrentTarget(targetForWindowEvents->document()); // FIXME: targetForWindowEvents should be the event target. + event->setCurrentTarget(targetForWindowEvents); targetForWindowEvents->handleEvent(event.get(), false); if (event->propagationStopped() || event->cancelBubble()) goto doneDispatching; @@ -2700,7 +2714,7 @@ bool Node::dispatchMouseEvent(const PlatformMouseEvent& event, const AtomicStrin return dispatchMouseEvent(eventType, button, detail, contentsPos.x(), contentsPos.y(), event.globalX(), event.globalY(), event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), - false, relatedTarget); + false, relatedTarget, 0); } void Node::dispatchSimulatedMouseEvent(const AtomicString& eventType, @@ -3164,184 +3178,184 @@ void Node::setOnmousewheel(PassRefPtr<EventListener> eventListener) setAttributeEventListener(eventNames().mousewheelEvent, eventListener); } -EventListener* Node::onbeforecut() const +EventListener* Node::ondragenter() const { - return getAttributeEventListener(eventNames().beforecutEvent); + return getAttributeEventListener(eventNames().dragenterEvent); } -void Node::setOnbeforecut(PassRefPtr<EventListener> eventListener) +void Node::setOndragenter(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().beforecutEvent, eventListener); + setAttributeEventListener(eventNames().dragenterEvent, eventListener); } -EventListener* Node::oncut() const +EventListener* Node::ondragover() const { - return getAttributeEventListener(eventNames().cutEvent); + return getAttributeEventListener(eventNames().dragoverEvent); } -void Node::setOncut(PassRefPtr<EventListener> eventListener) +void Node::setOndragover(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().cutEvent, eventListener); + setAttributeEventListener(eventNames().dragoverEvent, eventListener); } -EventListener* Node::onbeforecopy() const +EventListener* Node::ondragleave() const { - return getAttributeEventListener(eventNames().beforecopyEvent); + return getAttributeEventListener(eventNames().dragleaveEvent); } -void Node::setOnbeforecopy(PassRefPtr<EventListener> eventListener) +void Node::setOndragleave(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().beforecopyEvent, eventListener); + setAttributeEventListener(eventNames().dragleaveEvent, eventListener); } -EventListener* Node::oncopy() const +EventListener* Node::ondrop() const { - return getAttributeEventListener(eventNames().copyEvent); + return getAttributeEventListener(eventNames().dropEvent); } -void Node::setOncopy(PassRefPtr<EventListener> eventListener) +void Node::setOndrop(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().copyEvent, eventListener); + setAttributeEventListener(eventNames().dropEvent, eventListener); } -EventListener* Node::onbeforepaste() const +EventListener* Node::ondragstart() const { - return getAttributeEventListener(eventNames().beforepasteEvent); + return getAttributeEventListener(eventNames().dragstartEvent); } -void Node::setOnbeforepaste(PassRefPtr<EventListener> eventListener) +void Node::setOndragstart(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().beforepasteEvent, eventListener); + setAttributeEventListener(eventNames().dragstartEvent, eventListener); } -EventListener* Node::onpaste() const +EventListener* Node::ondrag() const { - return getAttributeEventListener(eventNames().pasteEvent); + return getAttributeEventListener(eventNames().dragEvent); } -void Node::setOnpaste(PassRefPtr<EventListener> eventListener) +void Node::setOndrag(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().pasteEvent, eventListener); + setAttributeEventListener(eventNames().dragEvent, eventListener); } -EventListener* Node::ondragenter() const +EventListener* Node::ondragend() const { - return getAttributeEventListener(eventNames().dragenterEvent); + return getAttributeEventListener(eventNames().dragendEvent); } -void Node::setOndragenter(PassRefPtr<EventListener> eventListener) +void Node::setOndragend(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().dragenterEvent, eventListener); + setAttributeEventListener(eventNames().dragendEvent, eventListener); } -EventListener* Node::ondragover() const +EventListener* Node::onscroll() const { - return getAttributeEventListener(eventNames().dragoverEvent); + return getAttributeEventListener(eventNames().scrollEvent); } -void Node::setOndragover(PassRefPtr<EventListener> eventListener) +void Node::setOnscroll(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().dragoverEvent, eventListener); + setAttributeEventListener(eventNames().scrollEvent, eventListener); } -EventListener* Node::ondragleave() const +EventListener* Node::onselect() const { - return getAttributeEventListener(eventNames().dragleaveEvent); + return getAttributeEventListener(eventNames().selectEvent); } -void Node::setOndragleave(PassRefPtr<EventListener> eventListener) +void Node::setOnselect(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().dragleaveEvent, eventListener); + setAttributeEventListener(eventNames().selectEvent, eventListener); } -EventListener* Node::ondrop() const +EventListener* Node::onsubmit() const { - return getAttributeEventListener(eventNames().dropEvent); + return getAttributeEventListener(eventNames().submitEvent); } -void Node::setOndrop(PassRefPtr<EventListener> eventListener) +void Node::setOnsubmit(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().dropEvent, eventListener); + setAttributeEventListener(eventNames().submitEvent, eventListener); } -EventListener* Node::ondragstart() const +EventListener* Node::onbeforecut() const { - return getAttributeEventListener(eventNames().dragstartEvent); + return getAttributeEventListener(eventNames().beforecutEvent); } -void Node::setOndragstart(PassRefPtr<EventListener> eventListener) +void Node::setOnbeforecut(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().dragstartEvent, eventListener); + setAttributeEventListener(eventNames().beforecutEvent, eventListener); } -EventListener* Node::ondrag() const +EventListener* Node::oncut() const { - return getAttributeEventListener(eventNames().dragEvent); + return getAttributeEventListener(eventNames().cutEvent); } -void Node::setOndrag(PassRefPtr<EventListener> eventListener) +void Node::setOncut(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().dragEvent, eventListener); + setAttributeEventListener(eventNames().cutEvent, eventListener); } -EventListener* Node::ondragend() const +EventListener* Node::onbeforecopy() const { - return getAttributeEventListener(eventNames().dragendEvent); + return getAttributeEventListener(eventNames().beforecopyEvent); } -void Node::setOndragend(PassRefPtr<EventListener> eventListener) +void Node::setOnbeforecopy(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().dragendEvent, eventListener); + setAttributeEventListener(eventNames().beforecopyEvent, eventListener); } -EventListener* Node::onreset() const +EventListener* Node::oncopy() const { - return getAttributeEventListener(eventNames().resetEvent); + return getAttributeEventListener(eventNames().copyEvent); } -void Node::setOnreset(PassRefPtr<EventListener> eventListener) +void Node::setOncopy(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().resetEvent, eventListener); + setAttributeEventListener(eventNames().copyEvent, eventListener); } -EventListener* Node::onresize() const +EventListener* Node::onbeforepaste() const { - return getAttributeEventListener(eventNames().resizeEvent); + return getAttributeEventListener(eventNames().beforepasteEvent); } -void Node::setOnresize(PassRefPtr<EventListener> eventListener) +void Node::setOnbeforepaste(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().resizeEvent, eventListener); + setAttributeEventListener(eventNames().beforepasteEvent, eventListener); } -EventListener* Node::onscroll() const +EventListener* Node::onpaste() const { - return getAttributeEventListener(eventNames().scrollEvent); + return getAttributeEventListener(eventNames().pasteEvent); } -void Node::setOnscroll(PassRefPtr<EventListener> eventListener) +void Node::setOnpaste(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().scrollEvent, eventListener); + setAttributeEventListener(eventNames().pasteEvent, eventListener); } -EventListener* Node::onsearch() const +EventListener* Node::onreset() const { - return getAttributeEventListener(eventNames().searchEvent); + return getAttributeEventListener(eventNames().resetEvent); } -void Node::setOnsearch(PassRefPtr<EventListener> eventListener) +void Node::setOnreset(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().searchEvent, eventListener); + setAttributeEventListener(eventNames().resetEvent, eventListener); } -EventListener* Node::onselect() const +EventListener* Node::onsearch() const { - return getAttributeEventListener(eventNames().selectEvent); + return getAttributeEventListener(eventNames().searchEvent); } -void Node::setOnselect(PassRefPtr<EventListener> eventListener) +void Node::setOnsearch(PassRefPtr<EventListener> eventListener) { - setAttributeEventListener(eventNames().selectEvent, eventListener); + setAttributeEventListener(eventNames().searchEvent, eventListener); } EventListener* Node::onselectstart() const @@ -3354,6 +3368,7 @@ void Node::setOnselectstart(PassRefPtr<EventListener> eventListener) setAttributeEventListener(eventNames().selectstartEvent, eventListener); } +#ifdef MANUAL_MERGE_REQUIRED EventListener* Node::onsubmit() const { return getAttributeEventListener(eventNames().submitEvent); @@ -3416,6 +3431,8 @@ void Node::setOntouchcancel(PassRefPtr<EventListener> eventListener) } #endif // ENABLE(TOUCH_EVENT) +#else // MANUAL_MERGE_REQUIRED +#endif // MANUAL_MERGE_REQUIRED } // namespace WebCore #ifndef NDEBUG diff --git a/WebCore/dom/Node.h b/WebCore/dom/Node.h index 43f5f76..22eb848 100644 --- a/WebCore/dom/Node.h +++ b/WebCore/dom/Node.h @@ -106,7 +106,7 @@ public: static void dumpStatistics(); enum StyleChange { NoChange, NoInherit, Inherit, Detach, Force }; - static StyleChange diff(RenderStyle*, RenderStyle*); + static StyleChange diff(const RenderStyle*, const RenderStyle*); Node(Document*, bool isElement = false, bool isContainer = false, bool isText = false); virtual ~Node(); @@ -541,7 +541,7 @@ public: void removeAllEventListeners() { if (hasRareData()) removeAllEventListenersSlowCase(); } void dispatchSubtreeModifiedEvent(); - void dispatchUIEvent(const AtomicString& eventType, int detail = 0, PassRefPtr<Event> underlyingEvent = 0); + void dispatchUIEvent(const AtomicString& eventType, int detail, PassRefPtr<Event> underlyingEvent); bool dispatchKeyEvent(const PlatformKeyboardEvent&); void dispatchWheelEvent(PlatformWheelEvent&); bool dispatchMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType, @@ -549,8 +549,8 @@ public: bool dispatchMouseEvent(const AtomicString& eventType, int button, int clickCount, int pageX, int pageY, int screenX, int screenY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, - bool isSimulated = false, Node* relatedTarget = 0, PassRefPtr<Event> underlyingEvent = 0); - void dispatchSimulatedMouseEvent(const AtomicString& eventType, PassRefPtr<Event> underlyingEvent = 0); + bool isSimulated, Node* relatedTarget, PassRefPtr<Event> underlyingEvent); + void dispatchSimulatedMouseEvent(const AtomicString& eventType, PassRefPtr<Event> underlyingEvent); void dispatchSimulatedClick(PassRefPtr<Event> underlyingEvent, bool sendMouseEvents = false, bool showPressedLook = true); void dispatchProgressEvent(const AtomicString& eventType, bool lengthComputableArg, unsigned loadedArg, unsigned totalArg); void dispatchWebKitAnimationEvent(const AtomicString& eventType, const String& animationName, double elapsedTime); @@ -577,10 +577,19 @@ public: const RegisteredEventListenerVector& eventListeners() const; + // These 4 attribute event handler attributes are overrided by HTMLBodyElement + // and HTMLFrameSetElement to forward to the DOMWindow. + virtual EventListener* onblur() const; + virtual void setOnblur(PassRefPtr<EventListener>); + virtual EventListener* onerror() const; + virtual void setOnerror(PassRefPtr<EventListener>); + virtual EventListener* onfocus() const; + virtual void setOnfocus(PassRefPtr<EventListener>); + virtual EventListener* onload() const; + virtual void setOnload(PassRefPtr<EventListener>); + EventListener* onabort() const; void setOnabort(PassRefPtr<EventListener>); - EventListener* onblur() const; - void setOnblur(PassRefPtr<EventListener>); EventListener* onchange() const; void setOnchange(PassRefPtr<EventListener>); EventListener* onclick() const; @@ -589,10 +598,6 @@ public: void setOncontextmenu(PassRefPtr<EventListener>); EventListener* ondblclick() const; void setOndblclick(PassRefPtr<EventListener>); - EventListener* onerror() const; - void setOnerror(PassRefPtr<EventListener>); - EventListener* onfocus() const; - void setOnfocus(PassRefPtr<EventListener>); EventListener* oninput() const; void setOninput(PassRefPtr<EventListener>); EventListener* onkeydown() const; @@ -601,8 +606,6 @@ public: void setOnkeypress(PassRefPtr<EventListener>); EventListener* onkeyup() const; void setOnkeyup(PassRefPtr<EventListener>); - EventListener* onload() const; - void setOnload(PassRefPtr<EventListener>); EventListener* onmousedown() const; void setOnmousedown(PassRefPtr<EventListener>); EventListener* onmousemove() const; @@ -615,18 +618,6 @@ public: void setOnmouseup(PassRefPtr<EventListener>); EventListener* onmousewheel() const; void setOnmousewheel(PassRefPtr<EventListener>); - EventListener* onbeforecut() const; - void setOnbeforecut(PassRefPtr<EventListener>); - EventListener* oncut() const; - void setOncut(PassRefPtr<EventListener>); - EventListener* onbeforecopy() const; - void setOnbeforecopy(PassRefPtr<EventListener>); - EventListener* oncopy() const; - void setOncopy(PassRefPtr<EventListener>); - EventListener* onbeforepaste() const; - void setOnbeforepaste(PassRefPtr<EventListener>); - EventListener* onpaste() const; - void setOnpaste(PassRefPtr<EventListener>); EventListener* ondragenter() const; void setOndragenter(PassRefPtr<EventListener>); EventListener* ondragover() const; @@ -641,18 +632,33 @@ public: void setOndrag(PassRefPtr<EventListener>); EventListener* ondragend() const; void setOndragend(PassRefPtr<EventListener>); - EventListener* onreset() const; - void setOnreset(PassRefPtr<EventListener>); - EventListener* onresize() const; - void setOnresize(PassRefPtr<EventListener>); EventListener* onscroll() const; void setOnscroll(PassRefPtr<EventListener>); - EventListener* onsearch() const; - void setOnsearch(PassRefPtr<EventListener>); EventListener* onselect() const; void setOnselect(PassRefPtr<EventListener>); + EventListener* onsubmit() const; + void setOnsubmit(PassRefPtr<EventListener>); + + // WebKit extensions + EventListener* onbeforecut() const; + void setOnbeforecut(PassRefPtr<EventListener>); + EventListener* oncut() const; + void setOncut(PassRefPtr<EventListener>); + EventListener* onbeforecopy() const; + void setOnbeforecopy(PassRefPtr<EventListener>); + EventListener* oncopy() const; + void setOncopy(PassRefPtr<EventListener>); + EventListener* onbeforepaste() const; + void setOnbeforepaste(PassRefPtr<EventListener>); + EventListener* onpaste() const; + void setOnpaste(PassRefPtr<EventListener>); + EventListener* onreset() const; + void setOnreset(PassRefPtr<EventListener>); + EventListener* onsearch() const; + void setOnsearch(PassRefPtr<EventListener>); EventListener* onselectstart() const; void setOnselectstart(PassRefPtr<EventListener>); +#ifdef MANUAL_MERGE_REQUIRED EventListener* onsubmit() const; void setOnsubmit(PassRefPtr<EventListener>); EventListener* onunload() const; @@ -667,6 +673,8 @@ public: EventListener* ontouchcancel() const; void setOntouchcancel(PassRefPtr<EventListener>); #endif +#else // MANUAL_MERGE_REQUIRED +#endif // MANUAL_MERGE_REQUIRED using TreeShared<Node>::ref; using TreeShared<Node>::deref; diff --git a/WebCore/dom/Node.idl b/WebCore/dom/Node.idl index dbbb499..b9c91dc 100644 --- a/WebCore/dom/Node.idl +++ b/WebCore/dom/Node.idl @@ -23,9 +23,9 @@ module core { interface [ CustomMarkFunction, CustomPushEventHandlerScope, + CustomToJS, GenerateConstructor, GenerateNativeConverter, - GenerateToJS, InlineGetOwnPropertySlot, Polymorphic, InterfaceUUID=84BA0D7A-7E3E-4a7b-B6FB-7653E8FB54ED, @@ -135,6 +135,7 @@ module core { #if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C #if !defined(LANGUAGE_COM) || !LANGUAGE_COM +#ifdef MANUAL_MERGE_REQUIRED attribute [DontEnum] EventListener onabort; attribute [DontEnum] EventListener onblur; attribute [DontEnum] EventListener onchange; @@ -182,6 +183,8 @@ module core { attribute [DontEnum] EventListener ontouchcancel; #endif +#else // MANUAL_MERGE_REQUIRED +#endif // MANUAL_MERGE_REQUIRED [Custom] void addEventListener(in DOMString type, in EventListener listener, in boolean useCapture); diff --git a/WebCore/dom/NodeFilter.h b/WebCore/dom/NodeFilter.h index 94c87e3..5a542ad 100644 --- a/WebCore/dom/NodeFilter.h +++ b/WebCore/dom/NodeFilter.h @@ -3,7 +3,7 @@ * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no) * Copyright (C) 2001 Peter Kelly (pmk@post.com) * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) - * Copyright (C) 2004, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -71,7 +71,7 @@ namespace WebCore { } short acceptNode(ScriptState*, Node*) const; - void mark() { m_condition->mark(); }; + void markAggregate(JSC::MarkStack& markStack) { m_condition->markAggregate(markStack); }; // For non-JS bindings. Silently ignores the JavaScript exception if any. short acceptNode(Node* node) const { return acceptNode(scriptStateFromNode(node), node); } diff --git a/WebCore/dom/NodeFilterCondition.h b/WebCore/dom/NodeFilterCondition.h index c94cc9a..0d6313f 100644 --- a/WebCore/dom/NodeFilterCondition.h +++ b/WebCore/dom/NodeFilterCondition.h @@ -3,7 +3,7 @@ * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no) * Copyright (C) 2001 Peter Kelly (pmk@post.com) * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) - * Copyright (C) 2004, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -28,6 +28,10 @@ #include "ScriptState.h" #include <wtf/RefCounted.h> +namespace JSC { + class MarkStack; +} + namespace WebCore { class Node; @@ -36,7 +40,7 @@ namespace WebCore { public: virtual ~NodeFilterCondition() { } virtual short acceptNode(ScriptState*, Node*) const = 0; - virtual void mark() { } + virtual void markAggregate(JSC::MarkStack&) { } }; } // namespace WebCore diff --git a/WebCore/dom/NodeRareData.h b/WebCore/dom/NodeRareData.h index ae0e516..7740344 100644 --- a/WebCore/dom/NodeRareData.h +++ b/WebCore/dom/NodeRareData.h @@ -37,24 +37,18 @@ struct NodeListsNodeData { typedef HashSet<DynamicNodeList*> NodeListSet; NodeListSet m_listsWithCaches; - DynamicNodeList::Caches m_childNodeListCaches; + RefPtr<DynamicNodeList::Caches> m_childNodeListCaches; - typedef HashMap<String, DynamicNodeList::Caches*> CacheMap; + typedef HashMap<String, RefPtr<DynamicNodeList::Caches> > CacheMap; CacheMap m_classNodeListCaches; CacheMap m_nameNodeListCaches; - typedef HashMap<QualifiedName, DynamicNodeList::Caches*> TagCacheMap; + typedef HashMap<QualifiedName, RefPtr<DynamicNodeList::Caches> > TagCacheMap; TagCacheMap m_tagNodeListCaches; - static PassOwnPtr<NodeListsNodeData> create() { - return new NodeListsNodeData; - } - - ~NodeListsNodeData() + static PassOwnPtr<NodeListsNodeData> create() { - deleteAllValues(m_classNodeListCaches); - deleteAllValues(m_nameNodeListCaches); - deleteAllValues(m_tagNodeListCaches); + return new NodeListsNodeData; } void invalidateCaches(); @@ -62,7 +56,10 @@ struct NodeListsNodeData { bool isEmpty() const; private: - NodeListsNodeData() { } + NodeListsNodeData() + : m_childNodeListCaches(DynamicNodeList::Caches::create()) + { + } }; class NodeRareData { diff --git a/WebCore/dom/Notation.h b/WebCore/dom/Notation.h index 6f5bf3f..2bd5363 100644 --- a/WebCore/dom/Notation.h +++ b/WebCore/dom/Notation.h @@ -29,8 +29,7 @@ namespace WebCore { -class Notation : public ContainerNode -{ +class Notation : public ContainerNode { public: Notation(Document*); Notation(Document*, const String& name, const String& publicId, const String& systemId); diff --git a/WebCore/dom/OptionElement.cpp b/WebCore/dom/OptionElement.cpp index 581c070..1de5fa4 100644 --- a/WebCore/dom/OptionElement.cpp +++ b/WebCore/dom/OptionElement.cpp @@ -67,7 +67,7 @@ int OptionElement::optionIndex(SelectElement* selectElement, const Element* elem return 0; } -String OptionElement::collectOptionText(const OptionElementData& data, const Element* element) +String OptionElement::collectOptionLabelOrText(const OptionElementData& data, const Element* element) { Document* document = element->document(); String text; @@ -75,22 +75,31 @@ String OptionElement::collectOptionText(const OptionElementData& data, const Ele // WinIE does not use the label attribute, so as a quirk, we ignore it. if (!document->inCompatMode()) text = data.label(); + if (text.isEmpty()) + text = collectOptionInnerText(element); + return normalizeText(document, text); +} - if (text.isEmpty()) { - Node* n = element->firstChild(); - while (n) { - if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SECTION_NODE) - text += n->nodeValue(); - - // skip script content - if (n->isElementNode() && toScriptElement(static_cast<Element*>(n))) - n = n->traverseNextSibling(element); - else - n = n->traverseNextNode(element); - } +String OptionElement::collectOptionInnerText(const Element* element) +{ + String text; + Node* n = element->firstChild(); + while (n) { + if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SECTION_NODE) + text += n->nodeValue(); + + // skip script content + if (n->isElementNode() && toScriptElement(static_cast<Element*>(n))) + n = n->traverseNextSibling(element); + else + n = n->traverseNextNode(element); } + return text; +} - text = document->displayStringModifiedByEncoding(text); +String OptionElement::normalizeText(const Document* document, const String& src) +{ + String text = document->displayStringModifiedByEncoding(src); // In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior. text = text.stripWhiteSpace(); @@ -104,9 +113,9 @@ String OptionElement::collectOptionTextRespectingGroupLabel(const OptionElementD { Element* parentElement = static_cast<Element*>(element->parentNode()); if (parentElement && toOptionGroupElement(parentElement)) - return " " + collectOptionText(data, element); + return " " + collectOptionLabelOrText(data, element); - return collectOptionText(data, element); + return collectOptionLabelOrText(data, element); } String OptionElement::collectOptionValue(const OptionElementData& data, const Element* element) @@ -116,7 +125,7 @@ String OptionElement::collectOptionValue(const OptionElementData& data, const El return value; // Use the text if the value wasn't set. - return collectOptionText(data, element).stripWhiteSpace(); + return collectOptionInnerText(element).stripWhiteSpace(); } // OptionElementData diff --git a/WebCore/dom/OptionElement.h b/WebCore/dom/OptionElement.h index c6b9778..a765d53 100644 --- a/WebCore/dom/OptionElement.h +++ b/WebCore/dom/OptionElement.h @@ -44,9 +44,12 @@ public: protected: static void setSelectedState(OptionElementData&, Element*, bool selected); static int optionIndex(SelectElement*, const Element*); - static String collectOptionText(const OptionElementData&, const Element*); + static String collectOptionLabelOrText(const OptionElementData&, const Element*); static String collectOptionTextRespectingGroupLabel(const OptionElementData&, const Element*); static String collectOptionValue(const OptionElementData&, const Element*); +private: + static String collectOptionInnerText(const Element*); + static String normalizeText(const Document*, const String&); }; // HTML/WMLOptionElement hold this struct as member variable diff --git a/WebCore/dom/Position.cpp b/WebCore/dom/Position.cpp index 0dd48d4..3b4c3e8 100644 --- a/WebCore/dom/Position.cpp +++ b/WebCore/dom/Position.cpp @@ -922,18 +922,18 @@ static bool isNonTextLeafChild(RenderObject* object) static InlineTextBox* searchAheadForBetterMatch(RenderObject* renderer) { - InlineTextBox* match = 0; - int minOffset = INT_MAX; RenderBlock* container = renderer->containingBlock(); RenderObject* next = renderer; while ((next = next->nextInPreOrder(container))) { if (next->isRenderBlock()) - break; + return 0; if (next->isBR()) - break; + return 0; if (isNonTextLeafChild(next)) - break; + return 0; if (next->isText()) { + InlineTextBox* match = 0; + int minOffset = INT_MAX; for (InlineTextBox* box = toRenderText(next)->firstTextBox(); box; box = box->nextTextBox()) { int caretMinOffset = box->caretMinOffset(); if (caretMinOffset < minOffset) { @@ -941,9 +941,11 @@ static InlineTextBox* searchAheadForBetterMatch(RenderObject* renderer) minOffset = caretMinOffset; } } + if (match) + return match; } } - return match; + return 0; } void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const diff --git a/WebCore/dom/Position.h b/WebCore/dom/Position.h index 57f73ec..b434ec9 100644 --- a/WebCore/dom/Position.h +++ b/WebCore/dom/Position.h @@ -70,7 +70,7 @@ public: // For creating offset positions: Position(PassRefPtr<Node> anchorNode, int offset, AnchorType); - AnchorType anchorType() const { return m_anchorType; } + AnchorType anchorType() const { return static_cast<AnchorType>(m_anchorType); } void clear() { m_anchorNode.clear(); m_offset = 0; m_anchorType = PositionIsOffsetInAnchor; m_isLegacyEditingPosition = false; } @@ -172,7 +172,7 @@ private: // returns true, then other places in editing will treat m_offset == 0 as "before the anchor" // and m_offset > 0 as "after the anchor node". See rangeCompliantEquivalent for more info. int m_offset; - AnchorType m_anchorType : 2; + unsigned m_anchorType : 2; bool m_isLegacyEditingPosition : 1; }; diff --git a/WebCore/dom/ProcessingInstruction.cpp b/WebCore/dom/ProcessingInstruction.cpp index 906902a..806bf92 100644 --- a/WebCore/dom/ProcessingInstruction.cpp +++ b/WebCore/dom/ProcessingInstruction.cpp @@ -123,7 +123,7 @@ void ProcessingInstruction::checkStyleSheet() bool isCSS = type.isEmpty() || type == "text/css"; #if ENABLE(XSLT) m_isXSL = (type == "text/xml" || type == "text/xsl" || type == "application/xml" || - type == "application/xhtml+xml" || type == "application/rss+xml" || type == "application/atom=xml"); + type == "application/xhtml+xml" || type == "application/rss+xml" || type == "application/atom+xml"); if (!isCSS && !m_isXSL) #else if (!isCSS) @@ -258,8 +258,7 @@ void ProcessingInstruction::removedFromDocument() { ContainerNode::removedFromDocument(); - if (document()->renderer()) - document()->removeStyleSheetCandidateNode(this); + document()->removeStyleSheetCandidateNode(this); // FIXME: It's terrible to do a synchronous update of the style selector just because a <style> or <link> element got removed. if (m_cachedSheet) diff --git a/WebCore/dom/ProcessingInstruction.h b/WebCore/dom/ProcessingInstruction.h index 3f42ed4..d133019 100644 --- a/WebCore/dom/ProcessingInstruction.h +++ b/WebCore/dom/ProcessingInstruction.h @@ -33,8 +33,7 @@ namespace WebCore { class StyleSheet; class CSSStyleSheet; -class ProcessingInstruction : public ContainerNode, private CachedResourceClient -{ +class ProcessingInstruction : public ContainerNode, private CachedResourceClient { public: ProcessingInstruction(Document*); ProcessingInstruction(Document*, const String& target, const String& data); diff --git a/WebCore/dom/Range.cpp b/WebCore/dom/Range.cpp index 8a3ca8f..edee305 100644 --- a/WebCore/dom/Range.cpp +++ b/WebCore/dom/Range.cpp @@ -90,13 +90,14 @@ PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument, PassRefPtr<N PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument, const Position& start, const Position& end) { + // FIXME: we shouldn't be using deprecatedEditingOffset here return adoptRef(new Range(ownerDocument, start.node(), start.deprecatedEditingOffset(), end.node(), end.deprecatedEditingOffset())); } Range::~Range() { - if (m_start.container()) - m_ownerDocument->detachRange(this); + // Always detach (even if we've already detached) to fix https://bugs.webkit.org/show_bug.cgi?id=26044 + m_ownerDocument->detachRange(this); #ifndef NDEBUG rangeCounter.decrement(); @@ -294,7 +295,7 @@ bool Range::isPointInRange(Node* refNode, int offset, ExceptionCode& ec) && compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset()) <= 0; } -short Range::comparePoint(Node* refNode, int offset, ExceptionCode& ec) +short Range::comparePoint(Node* refNode, int offset, ExceptionCode& ec) const { // http://developer.mozilla.org/en/docs/DOM:range.comparePoint // This method returns -1, 0 or 1 depending on if the point described by the @@ -332,7 +333,7 @@ short Range::comparePoint(Node* refNode, int offset, ExceptionCode& ec) return 0; } -Range::CompareResults Range::compareNode(Node* refNode, ExceptionCode& ec) +Range::CompareResults Range::compareNode(Node* refNode, ExceptionCode& ec) const { // http://developer.mozilla.org/en/docs/DOM:range.compareNode // This method returns 0, 1, 2, or 3 based on if the node is before, after, @@ -379,7 +380,6 @@ Range::CompareResults Range::compareNode(Node* refNode, ExceptionCode& ec) } } - short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, ExceptionCode& ec) const { if (!m_start.container()) { @@ -726,7 +726,7 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception for (; leftParent != commonRoot; leftParent = leftParent->parentNode()) { if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { RefPtr<Node> leftContentsParent = leftParent->cloneNode(false); - leftContentsParent->appendChild(leftContents,ec); + leftContentsParent->appendChild(leftContents, ec); leftContents = leftContentsParent; } @@ -734,11 +734,11 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception for (; n; n = next) { next = n->nextSibling(); if (action == EXTRACT_CONTENTS) - leftContents->appendChild(n,ec); // will remove n from leftParent + leftContents->appendChild(n, ec); // will remove n from leftParent else if (action == CLONE_CONTENTS) - leftContents->appendChild(n->cloneNode(true),ec); + leftContents->appendChild(n->cloneNode(true), ec); else - leftParent->removeChild(n,ec); + leftParent->removeChild(n, ec); } n = leftParent->nextSibling(); } @@ -796,7 +796,7 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception for (; rightParent != commonRoot; rightParent = rightParent->parentNode()) { if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { RefPtr<Node> rightContentsParent = rightParent->cloneNode(false); - rightContentsParent->appendChild(rightContents,ec); + rightContentsParent->appendChild(rightContents, ec); rightContents = rightContentsParent; } Node* prev; @@ -1070,6 +1070,7 @@ PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& marku void Range::detach(ExceptionCode& ec) { + // Check first to see if we've already detached: if (!m_start.container()) { ec = INVALID_STATE_ERR; return; diff --git a/WebCore/dom/Range.h b/WebCore/dom/Range.h index 115f442..1487a7c 100644 --- a/WebCore/dom/Range.h +++ b/WebCore/dom/Range.h @@ -59,10 +59,10 @@ public: void setStart(PassRefPtr<Node> container, int offset, ExceptionCode&); void setEnd(PassRefPtr<Node> container, int offset, ExceptionCode&); void collapse(bool toStart, ExceptionCode&); - bool isPointInRange(Node* refNode, int offset, ExceptionCode& ec); - short comparePoint(Node* refNode, int offset, ExceptionCode& ec); + bool isPointInRange(Node* refNode, int offset, ExceptionCode&); + short comparePoint(Node* refNode, int offset, ExceptionCode&) const; enum CompareResults { NODE_BEFORE, NODE_AFTER, NODE_BEFORE_AND_AFTER, NODE_INSIDE }; - CompareResults compareNode(Node* refNode, ExceptionCode&); + CompareResults compareNode(Node* refNode, ExceptionCode&) const; enum CompareHow { START_TO_START, START_TO_END, END_TO_END, END_TO_START }; short compareBoundaryPoints(CompareHow, const Range* sourceRange, ExceptionCode&) const; static short compareBoundaryPoints(Node* containerA, int offsetA, Node* containerB, int offsetB); diff --git a/WebCore/dom/RangeBoundaryPoint.h b/WebCore/dom/RangeBoundaryPoint.h index 2fda51f..1bbbe1a 100644 --- a/WebCore/dom/RangeBoundaryPoint.h +++ b/WebCore/dom/RangeBoundaryPoint.h @@ -33,7 +33,6 @@ namespace WebCore { class RangeBoundaryPoint { public: - RangeBoundaryPoint(); explicit RangeBoundaryPoint(PassRefPtr<Node> container); const Position toPosition() const; @@ -63,17 +62,12 @@ private: Node* m_childBeforeBoundary; }; -inline RangeBoundaryPoint::RangeBoundaryPoint() - : m_offsetInContainer(0) - , m_childBeforeBoundary(0) -{ -} - inline RangeBoundaryPoint::RangeBoundaryPoint(PassRefPtr<Node> container) : m_containerNode(container) , m_offsetInContainer(0) , m_childBeforeBoundary(0) { + ASSERT(m_containerNode); } inline Node* RangeBoundaryPoint::container() const @@ -116,6 +110,7 @@ inline void RangeBoundaryPoint::clear() inline void RangeBoundaryPoint::set(PassRefPtr<Node> container, int offset, Node* childBefore) { + ASSERT(container); ASSERT(offset >= 0); ASSERT(childBefore == (offset ? container->childNode(offset - 1) : 0)); m_containerNode = container; diff --git a/WebCore/dom/RegisteredEventListener.h b/WebCore/dom/RegisteredEventListener.h index 479c2ff..034f6c3 100644 --- a/WebCore/dom/RegisteredEventListener.h +++ b/WebCore/dom/RegisteredEventListener.h @@ -2,7 +2,7 @@ * Copyright (C) 2001 Peter Kelly (pmk@post.com) * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de) * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -55,10 +55,10 @@ namespace WebCore { typedef Vector<RefPtr<RegisteredEventListener> > RegisteredEventListenerVector; #if USE(JSC) - inline void markEventListeners(const RegisteredEventListenerVector& listeners) + inline void markEventListeners(JSC::MarkStack& markStack, const RegisteredEventListenerVector& listeners) { for (size_t i = 0; i < listeners.size(); ++i) - listeners[i]->listener()->markJSFunction(); + listeners[i]->listener()->markJSFunction(markStack); } inline void invalidateEventListeners(const RegisteredEventListenerVector& listeners) diff --git a/WebCore/dom/ScriptElement.cpp b/WebCore/dom/ScriptElement.cpp index 55b15e5..fe38b46 100644 --- a/WebCore/dom/ScriptElement.cpp +++ b/WebCore/dom/ScriptElement.cpp @@ -201,13 +201,14 @@ void ScriptElementData::execute(CachedScript* cachedScript) evaluateScript(ScriptSourceCode(cachedScript)); m_scriptElement->dispatchLoadEvent(); } + cachedScript->removeClient(this); } void ScriptElementData::notifyFinished(CachedResource* o) { ASSERT_UNUSED(o, o == m_cachedScript); m_element->document()->executeScriptSoon(this, m_cachedScript); - stopLoadRequest(); + m_cachedScript = 0; } bool ScriptElementData::ignoresLoadRequest() const diff --git a/WebCore/dom/ScriptExecutionContext.cpp b/WebCore/dom/ScriptExecutionContext.cpp index c518734..45d4e23 100644 --- a/WebCore/dom/ScriptExecutionContext.cpp +++ b/WebCore/dom/ScriptExecutionContext.cpp @@ -88,7 +88,7 @@ void ScriptExecutionContext::dispatchMessagePortEvents() MessagePort* port = ports[i]; // The port may be destroyed, and another one created at the same address, but this is safe, as the worst that can happen // as a result is that dispatchMessages() will be called needlessly. - if (m_messagePorts.contains(port) && port->queueIsOpen()) + if (m_messagePorts.contains(port) && port->started()) port->dispatchMessages(); } } diff --git a/WebCore/dom/ScriptExecutionContext.h b/WebCore/dom/ScriptExecutionContext.h index 7b2f36a..3f8febc 100644 --- a/WebCore/dom/ScriptExecutionContext.h +++ b/WebCore/dom/ScriptExecutionContext.h @@ -64,7 +64,7 @@ namespace WebCore { SecurityOrigin* securityOrigin() const { return m_securityOrigin.get(); } virtual void reportException(const String& errorMessage, int lineNumber, const String& sourceURL) = 0; - virtual void addMessage(MessageDestination, MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL) = 0; + virtual void addMessage(MessageDestination, MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL) = 0; virtual void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString) = 0; virtual void scriptImported(unsigned long, const String&) = 0; diff --git a/WebCore/dom/SelectElement.cpp b/WebCore/dom/SelectElement.cpp index ff8f1c3..1eb001e 100644 --- a/WebCore/dom/SelectElement.cpp +++ b/WebCore/dom/SelectElement.cpp @@ -47,10 +47,17 @@ #include "WMLSelectElement.h" #endif -#if PLATFORM(MAC) +// Configure platform-specific behavior when focused pop-up receives arrow/space/return keystroke. +// (PLATFORM(MAC) is always false in Chromium, hence the extra test.) +#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) #define ARROW_KEYS_POP_MENU 1 +#define SPACE_OR_RETURN_POP_MENU 0 +#elif PLATFORM(GTK) +#define ARROW_KEYS_POP_MENU 0 +#define SPACE_OR_RETURN_POP_MENU 1 #else #define ARROW_KEYS_POP_MENU 0 +#define SPACE_OR_RETURN_POP_MENU 0 #endif using std::min; @@ -198,8 +205,9 @@ void SelectElement::menuListOnChange(SelectElementData& data, Element* element) ASSERT(data.usesMenuList()); int selected = selectedIndex(data, element); - if (data.lastOnChangeIndex() != selected) { + if (data.lastOnChangeIndex() != selected && data.userDrivenChange()) { data.setLastOnChangeIndex(selected); + data.setUserDrivenChange(false); element->dispatchFormControlChangeEvent(); } } @@ -210,7 +218,7 @@ void SelectElement::scrollToSelection(SelectElementData& data, Element* element) return; if (RenderObject* renderer = element->renderer()) - static_cast<RenderListBox*>(renderer)->selectionChanged(); + toRenderListBox(renderer)->selectionChanged(); } void SelectElement::recalcStyle(SelectElementData& data, Element* element) @@ -218,9 +226,9 @@ void SelectElement::recalcStyle(SelectElementData& data, Element* element) RenderObject* renderer = element->renderer(); if (element->childNeedsStyleRecalc() && renderer) { if (data.usesMenuList()) - static_cast<RenderMenuList*>(renderer)->setOptionsChanged(true); + toRenderMenuList(renderer)->setOptionsChanged(true); else - static_cast<RenderListBox*>(renderer)->setOptionsChanged(true); + toRenderListBox(renderer)->setOptionsChanged(true); } else if (data.shouldRecalcListItems()) recalcListItems(data, element); } @@ -231,9 +239,9 @@ void SelectElement::setRecalcListItems(SelectElementData& data, Element* element data.setActiveSelectionAnchorIndex(-1); // Manual selection anchor is reset when manipulating the select programmatically. if (RenderObject* renderer = element->renderer()) { if (data.usesMenuList()) - static_cast<RenderMenuList*>(renderer)->setOptionsChanged(true); + toRenderMenuList(renderer)->setOptionsChanged(true); else - static_cast<RenderListBox*>(renderer)->setOptionsChanged(true); + toRenderListBox(renderer)->setOptionsChanged(true); } element->setNeedsStyleRecalc(); } @@ -309,7 +317,7 @@ int SelectElement::selectedIndex(const SelectElementData& data, const Element* e return -1; } -void SelectElement::setSelectedIndex(SelectElementData& data, Element* element, int optionIndex, bool deselect, bool fireOnChange) +void SelectElement::setSelectedIndex(SelectElementData& data, Element* element, int optionIndex, bool deselect, bool fireOnChangeNow, bool userDrivenChange) { const Vector<Element*>& items = data.listItems(element); int listIndex = optionToListIndex(data, element, optionIndex); @@ -335,9 +343,12 @@ void SelectElement::setSelectedIndex(SelectElementData& data, Element* element, scrollToSelection(data, element); - // This only gets called with fireOnChange for menu lists. - if (fireOnChange && data.usesMenuList()) - menuListOnChange(data, element); + // This only gets called with fireOnChangeNow for menu lists. + if (data.usesMenuList()) { + data.setUserDrivenChange(userDrivenChange); + if (fireOnChangeNow) + menuListOnChange(data, element); + } if (Frame* frame = element->document()->frame()) frame->page()->chrome()->client()->formStateDidChange(element); @@ -481,8 +492,8 @@ bool SelectElement::appendFormData(SelectElementData& data, Element* element, Fo void SelectElement::reset(SelectElementData& data, Element* element) { - bool optionSelected = false; OptionElement* firstOption = 0; + OptionElement* selectedOption = 0; const Vector<Element*>& items = data.listItems(element); for (unsigned i = 0; i < items.size(); ++i) { @@ -491,8 +502,10 @@ void SelectElement::reset(SelectElementData& data, Element* element) continue; if (!items[i]->getAttribute(HTMLNames::selectedAttr).isNull()) { + if (selectedOption && !data.multiple()) + selectedOption->setSelectedState(false); optionElement->setSelectedState(true); - optionSelected = true; + selectedOption = optionElement; } else optionElement->setSelectedState(false); @@ -500,11 +513,34 @@ void SelectElement::reset(SelectElementData& data, Element* element) firstOption = optionElement; } - if (!optionSelected && firstOption && data.usesMenuList()) + if (!selectedOption && firstOption && data.usesMenuList()) firstOption->setSelectedState(true); element->setNeedsStyleRecalc(); } + +#if !ARROW_KEYS_POP_MENU +enum SkipDirection { + SkipBackwards = -1, + SkipForwards = 1 +}; + +// Returns the index of the next valid list item |skip| items past |listIndex| in direction |direction|. +static int nextValidIndex(const Vector<Element*>& listItems, int listIndex, SkipDirection direction, int skip) +{ + int lastGoodIndex = listIndex; + int size = listItems.size(); + for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex += direction) { + --skip; + if (!listItems[listIndex]->disabled() && isOptionElement(listItems[listIndex])) { + lastGoodIndex = listIndex; + if (skip <= 0) + break; + } + } + return lastGoodIndex; +} +#endif void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element* element, Event* event, HTMLFormElement* htmlForm) { @@ -525,30 +561,36 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element // 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 = static_cast<RenderMenuList*>(element->renderer())) + if (RenderMenuList* menuList = toRenderMenuList(element->renderer())) menuList->showPopup(); handled = true; } #else const Vector<Element*>& listItems = data.listItems(element); - int size = listItems.size(); int listIndex = optionToListIndex(data, element, selectedIndex(data, element)); if (keyIdentifier == "Down" || keyIdentifier == "Right") { - for (listIndex += 1; - listIndex >= 0 && listIndex < size && (listItems[listIndex]->disabled() || !isOptionElement(listItems[listIndex])); - ++listIndex) { } - if (listIndex >= 0 && listIndex < size) - setSelectedIndex(data, element, listToOptionIndex(data, element, listIndex)); + listIndex = nextValidIndex(listItems, listIndex, SkipForwards, 1); handled = true; } else if (keyIdentifier == "Up" || keyIdentifier == "Left") { - for (listIndex -= 1; - listIndex >= 0 && listIndex < size && (listItems[listIndex]->disabled() || !isOptionElement(listItems[listIndex])); - --listIndex) { } - if (listIndex >= 0 && listIndex < size) - setSelectedIndex(data, element, listToOptionIndex(data, element, listIndex)); + listIndex = nextValidIndex(listItems, listIndex, SkipBackwards, 1); + handled = true; + } else if (keyIdentifier == "PageDown") { + listIndex = nextValidIndex(listItems, listIndex, SkipForwards, 3); + handled = true; + } else if (keyIdentifier == "PageUp") { + listIndex = nextValidIndex(listItems, listIndex, SkipBackwards, 3); + handled = true; + } else if (keyIdentifier == "Home") { + listIndex = nextValidIndex(listItems, -1, SkipForwards, 1); + handled = true; + } else if (keyIdentifier == "End") { + listIndex = nextValidIndex(listItems, listItems.size(), SkipBackwards, 1); handled = true; } + + if (handled && listIndex >= 0 && (unsigned)listIndex < listItems.size()) + setSelectedIndex(data, element, listToOptionIndex(data, element, listIndex)); #endif if (handled) event->setDefaultHandled(); @@ -563,13 +605,23 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element int keyCode = static_cast<KeyboardEvent*>(event)->keyCode(); bool handled = false; -#if ARROW_KEYS_POP_MENU +#if SPACE_OR_RETURN_POP_MENU + if (keyCode == ' ' || keyCode == '\r') { + element->focus(); + // 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; + } +#elif ARROW_KEYS_POP_MENU if (keyCode == ' ') { element->focus(); // 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 = static_cast<RenderMenuList*>(element->renderer())) + if (RenderMenuList* menuList = toRenderMenuList(element->renderer())) menuList->showPopup(); handled = true; } else if (keyCode == '\r') { @@ -592,7 +644,7 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) { element->focus(); - if (RenderMenuList* menuList = static_cast<RenderMenuList*>(element->renderer())) { + if (RenderMenuList* menuList = toRenderMenuList(element->renderer())) { if (menuList->popupIsVisible()) menuList->hidePopup(); else { @@ -616,7 +668,7 @@ void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element* // Convert to coords relative to the list box if needed. MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); IntPoint localOffset = roundedIntPoint(element->renderer()->absoluteToLocal(mouseEvent->absoluteLocation(), false, true)); - int listIndex = static_cast<RenderListBox*>(element->renderer())->listIndexAtOffset(localOffset.x(), localOffset.y()); + int listIndex = toRenderListBox(element->renderer())->listIndexAtOffset(localOffset.x(), localOffset.y()); if (listIndex >= 0) { // Save the selection so it can be compared to the new selection when dispatching change events during mouseup, or after autoscroll finishes. saveLastSelection(data, element); @@ -709,7 +761,7 @@ void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element* setActiveSelectionAnchorIndex(data, element, data.activeSelectionEndIndex()); } - static_cast<RenderListBox*>(element->renderer())->scrollToRevealElementAtListIndex(endIndex); + toRenderListBox(element->renderer())->scrollToRevealElementAtListIndex(endIndex); updateListBoxSelection(data, element, deselectOthers); listBoxOnChange(data, element); event->setDefaultHandled(); @@ -863,6 +915,19 @@ void SelectElement::accessKeySetSelectedIndex(SelectElementData& data, Element* scrollToSelection(data, element); } +unsigned SelectElement::optionCount(const SelectElementData& data, const Element* element) +{ + unsigned options = 0; + + const Vector<Element*>& items = data.listItems(element); + for (unsigned i = 0; i < items.size(); ++i) { + if (isOptionElement(items[i])) + ++options; + } + + return options; +} + // SelectElementData SelectElementData::SelectElementData() : m_multiple(false) diff --git a/WebCore/dom/SelectElement.h b/WebCore/dom/SelectElement.h index bad9b79..4cc76a0 100644 --- a/WebCore/dom/SelectElement.h +++ b/WebCore/dom/SelectElement.h @@ -57,7 +57,8 @@ public: virtual int optionToListIndex(int optionIndex) const = 0; virtual int selectedIndex() const = 0; - virtual void setSelectedIndex(int index, bool deselect = true, bool fireOnChange = false) = 0; + virtual void setSelectedIndex(int index, bool deselect = true) = 0; + virtual void setSelectedIndexByUser(int index, bool deselect = true, bool fireOnChangeNow = false) = 0; protected: virtual ~SelectElement() { } @@ -78,7 +79,7 @@ protected: static void setRecalcListItems(SelectElementData&, Element*); static void recalcListItems(SelectElementData&, const Element*, bool updateSelectedStates = true); static int selectedIndex(const SelectElementData&, const Element*); - static void setSelectedIndex(SelectElementData&, Element*, int optionIndex, bool deselect = true, bool fireOnChange = false); + static void setSelectedIndex(SelectElementData&, Element*, int optionIndex, bool deselect = true, bool fireOnChangeNow = false, bool userDrivenChange = true); static int optionToListIndex(const SelectElementData&, const Element*, int optionIndex); static int listToOptionIndex(const SelectElementData&, const Element*, int listIndex); static void dispatchFocusEvent(SelectElementData&, Element*); @@ -94,7 +95,8 @@ protected: static void typeAheadFind(SelectElementData&, Element*, KeyboardEvent*); static void insertedIntoTree(SelectElementData&, Element*); static void accessKeySetSelectedIndex(SelectElementData&, Element*, int index); - + static unsigned optionCount(const SelectElementData&, const Element*); + private: static void menuListDefaultEventHandler(SelectElementData&, Element*, Event*, HTMLFormElement*); static void listBoxDefaultEventHandler(SelectElementData&, Element*, Event*, HTMLFormElement*); @@ -117,6 +119,9 @@ public: int lastOnChangeIndex() const { return m_lastOnChangeIndex; } void setLastOnChangeIndex(int value) { m_lastOnChangeIndex = value; } + bool userDrivenChange() const { return m_userDrivenChange; } + void setUserDrivenChange(bool value) { m_userDrivenChange = value; } + Vector<bool>& lastOnChangeSelection() { return m_lastOnChangeSelection; } bool activeSelectionState() const { return m_activeSelectionState; } @@ -154,6 +159,7 @@ private: int m_lastOnChangeIndex; Vector<bool> m_lastOnChangeSelection; + bool m_userDrivenChange; bool m_activeSelectionState; int m_activeSelectionAnchorIndex; diff --git a/WebCore/dom/StaticStringList.cpp b/WebCore/dom/StaticStringList.cpp deleted file mode 100644 index a6de92a..0000000 --- a/WebCore/dom/StaticStringList.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2009 Apple 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 "StaticStringList.h" - -namespace WebCore { - -StaticStringList::StaticStringList(const Vector<String>& strings) - : m_strings(strings) -{ -} - -StaticStringList::StaticStringList() -{ -} - -StaticStringList::~StaticStringList() -{ -} - -unsigned StaticStringList::length() const -{ - return m_strings.size(); -} - -String StaticStringList::item(unsigned index) const -{ - if (index >= m_strings.size()) - return ""; - return m_strings[index]; -} - -bool StaticStringList::contains(const String& str) const -{ - size_t count = m_strings.size(); - for (size_t i = 0; i < count; ++i) { - if (m_strings[i] == str) - return true; - } - return false; -} - -} // namespace WebCore diff --git a/WebCore/dom/StaticStringList.h b/WebCore/dom/StaticStringList.h deleted file mode 100644 index 5b13e87..0000000 --- a/WebCore/dom/StaticStringList.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2009 Apple 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 StaticStringList_h -#define StaticStringList_h - -#include "DOMStringList.h" - -namespace WebCore { - - class StaticStringList : public DOMStringList { - public: - static PassRefPtr<StaticStringList> create(const Vector<String>& strings) - { - return adoptRef(new StaticStringList(strings)); - } - static PassRefPtr<StaticStringList> adopt(Vector<String>& strings) - { - StaticStringList* newList = new StaticStringList; - newList->m_strings.swap(strings); - return adoptRef(newList); - } - virtual ~StaticStringList(); - - virtual unsigned length() const; - virtual String item(unsigned) const; - virtual bool contains(const String&) const; - - private: - StaticStringList(const Vector<String>&); - StaticStringList(); - - Vector<String> m_strings; - }; - -} // namespace WebCore - -#endif // StaticStringList diff --git a/WebCore/dom/StyledElement.cpp b/WebCore/dom/StyledElement.cpp index 8ddfd31..456cc52 100644 --- a/WebCore/dom/StyledElement.cpp +++ b/WebCore/dom/StyledElement.cpp @@ -194,8 +194,8 @@ void StyledElement::attributeChanged(Attribute* attr, bool preserveDecls) if (needToParse) parseMappedAttribute(mappedAttr); - if (entry == eNone && ownerDocument()->attached() && ownerDocument()->styleSelector()->hasSelectorForAttribute(attr->name().localName())) - setNeedsStyleRecalc(); + if (entry == eNone) + recalcStyleIfNeededAfterAttributeChanged(attr); if (checkDecl && mappedAttr->decl()) { // Add the decl to the table in the appropriate spot. @@ -206,7 +206,7 @@ void StyledElement::attributeChanged(Attribute* attr, bool preserveDecls) if (namedAttrMap) mappedAttributes()->declAdded(); } - Element::attributeChanged(attr, preserveDecls); + updateAfterAttributeChanged(attr); } bool StyledElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const @@ -280,10 +280,11 @@ CSSStyleDeclaration* StyledElement::style() return getInlineStyleDecl(); } -static inline int toHex(UChar c) { +static inline int toHex(UChar c) +{ return ((c >= '0' && c <= '9') ? (c - '0') : ((c >= 'a' && c <= 'f') ? (c - 'a' + 10) - : (( c >= 'A' && c <= 'F') ? (c - 'A' + 10) + : ((c >= 'A' && c <= 'F') ? (c - 'A' + 10) : -1))); } diff --git a/WebCore/dom/Text.cpp b/WebCore/dom/Text.cpp index 04e499a..bbd926b 100644 --- a/WebCore/dom/Text.cpp +++ b/WebCore/dom/Text.cpp @@ -260,6 +260,19 @@ RenderObject *Text::createRenderer(RenderArena* arena, RenderStyle*) void Text::attach() { +#if ENABLE(WML) + if (document()->isWMLDocument() && !containsOnlyWhitespace()) { + String text = m_data; + ASSERT(!text.isEmpty()); + + text = substituteVariableReferences(text, document()); + + ExceptionCode code = 0; + setData(text, code); + ASSERT(!code); + } +#endif + createRendererIfNeeded(); CharacterData::attach(); } @@ -319,29 +332,6 @@ PassRefPtr<Text> Text::createWithLengthLimit(Document* doc, const String& text, return new Text(doc, nodeText); } -#if ENABLE(WML) -void Text::insertedIntoDocument() -{ - CharacterData::insertedIntoDocument(); - - if (!parentNode()->isWMLElement() || !length()) - return; - - WMLPageState* pageState = wmlPageStateForDocument(document()); - if (!pageState->hasVariables()) - return; - - String text = data(); - if (!text.impl() || text.impl()->containsOnlyWhitespace()) - return; - - text = substituteVariableReferences(text, document()); - - ExceptionCode ec; - setData(text, ec); -} -#endif - #ifndef NDEBUG void Text::formatForDebugger(char *buffer, unsigned length) const { diff --git a/WebCore/dom/Text.h b/WebCore/dom/Text.h index 5e711d0..e5a6e69 100644 --- a/WebCore/dom/Text.h +++ b/WebCore/dom/Text.h @@ -59,10 +59,6 @@ public: static PassRefPtr<Text> createWithLengthLimit(Document*, const String&, unsigned& charsLeft, unsigned maxChars = cTextNodeLengthLimit); -#if ENABLE(WML) - virtual void insertedIntoDocument(); -#endif - #ifndef NDEBUG virtual void formatForDebugger(char* buffer, unsigned length) const; #endif diff --git a/WebCore/dom/Tokenizer.h b/WebCore/dom/Tokenizer.h index f9c6dc4..ea303f9 100644 --- a/WebCore/dom/Tokenizer.h +++ b/WebCore/dom/Tokenizer.h @@ -28,6 +28,7 @@ namespace WebCore { class SegmentedString; + class XSSAuditor; class Tokenizer { public: @@ -58,11 +59,15 @@ namespace WebCore { virtual void executeScriptsWaitingForStylesheets() {} virtual bool isHTMLTokenizer() const { return false; } + + XSSAuditor* xssAuditor() const { return m_XSSAuditor; } + void setXSSAuditor(XSSAuditor* auditor) { m_XSSAuditor = auditor; } protected: Tokenizer(bool viewSourceMode = false) : m_parserStopped(false) , m_inViewSourceMode(viewSourceMode) + , m_XSSAuditor(0) { } @@ -71,6 +76,9 @@ namespace WebCore { // even when it has buffered data. bool m_parserStopped; bool m_inViewSourceMode; + + // The XSSAuditor associated with this tokenizer. + XSSAuditor* m_XSSAuditor; }; } // namespace WebCore diff --git a/WebCore/dom/XMLTokenizerLibxml2.cpp b/WebCore/dom/XMLTokenizerLibxml2.cpp index 4098eaa..4387a66 100644 --- a/WebCore/dom/XMLTokenizerLibxml2.cpp +++ b/WebCore/dom/XMLTokenizerLibxml2.cpp @@ -72,7 +72,7 @@ using namespace std; namespace WebCore { -class PendingCallbacks : Noncopyable { +class PendingCallbacks : public Noncopyable { public: ~PendingCallbacks() { @@ -195,7 +195,8 @@ private: }; struct PendingStartElementNSCallback : public PendingCallback { - virtual ~PendingStartElementNSCallback() { + virtual ~PendingStartElementNSCallback() + { xmlFree(xmlLocalName); xmlFree(xmlPrefix); xmlFree(xmlURI); @@ -208,7 +209,8 @@ private: xmlFree(attributes); } - virtual void call(XMLTokenizer* tokenizer) { + virtual void call(XMLTokenizer* tokenizer) + { tokenizer->startElementNs(xmlLocalName, xmlPrefix, xmlURI, nb_namespaces, const_cast<const xmlChar**>(namespaces), nb_attributes, nb_defaulted, const_cast<const xmlChar**>(attributes)); @@ -312,7 +314,7 @@ private: struct PendingErrorCallback: public PendingCallback { virtual ~PendingErrorCallback() { - free (message); + free(message); } virtual void call(XMLTokenizer* tokenizer) @@ -344,7 +346,8 @@ class OffsetBuffer { public: OffsetBuffer(const Vector<char>& b) : m_buffer(b), m_currentOffset(0) { } - int readOutBytes(char* outputBuffer, unsigned askedToRead) { + int readOutBytes(char* outputBuffer, unsigned askedToRead) + { unsigned bytesLeft = m_buffer.size() - m_currentOffset; unsigned lenToCopy = min(askedToRead, bytesLeft); if (lenToCopy) { @@ -668,7 +671,7 @@ typedef struct _xmlSAX2Namespace xmlSAX2Namespace; static inline void handleElementNamespaces(Element* newElement, const xmlChar** libxmlNamespaces, int nb_namespaces, ExceptionCode& ec) { xmlSAX2Namespace* namespaces = reinterpret_cast<xmlSAX2Namespace*>(libxmlNamespaces); - for(int i = 0; i < nb_namespaces; i++) { + for (int i = 0; i < nb_namespaces; i++) { String namespaceQName = "xmlns"; String namespaceURI = toString(namespaces[i].uri); if (namespaces[i].prefix) @@ -691,7 +694,7 @@ typedef struct _xmlSAX2Attributes xmlSAX2Attributes; static inline void handleElementAttributes(Element* newElement, const xmlChar** libxmlAttributes, int nb_attributes, ExceptionCode& ec) { xmlSAX2Attributes* attributes = reinterpret_cast<xmlSAX2Attributes*>(libxmlAttributes); - for(int i = 0; i < nb_attributes; i++) { + for (int i = 0; i < nb_attributes; i++) { String attrLocalName = toString(attributes[i].localname); int valueLength = (int) (attributes[i].end - attributes[i].value); String attrValue = toString(attributes[i].value, valueLength); @@ -1407,7 +1410,7 @@ static void attributesStartElementNsHandler(void* closure, const xmlChar* xmlLoc state->gotAttributes = true; xmlSAX2Attributes* attributes = reinterpret_cast<xmlSAX2Attributes*>(libxmlAttributes); - for(int i = 0; i < nb_attributes; i++) { + for (int i = 0; i < nb_attributes; i++) { String attrLocalName = toString(attributes[i].localname); int valueLength = (int) (attributes[i].end - attributes[i].value); String attrValue = toString(attributes[i].value, valueLength); diff --git a/WebCore/dom/XMLTokenizerQt.cpp b/WebCore/dom/XMLTokenizerQt.cpp index 3173708..16c637f 100644 --- a/WebCore/dom/XMLTokenizerQt.cpp +++ b/WebCore/dom/XMLTokenizerQt.cpp @@ -66,8 +66,7 @@ using namespace std; namespace WebCore { #if QT_VERSION >= 0x040400 -class EntityResolver : public QXmlStreamEntityResolver -{ +class EntityResolver : public QXmlStreamEntityResolver { virtual QString resolveUndeclaredEntity(const QString &name); }; @@ -354,7 +353,7 @@ static void attributesStartElementNsHandler(AttributeParseState* state, const QX state->gotAttributes = true; - for(int i = 0; i < attrs.count(); i++) { + for (int i = 0; i < attrs.count(); i++) { const QXmlStreamAttribute& attr = attrs[i]; String attrLocalName = attr.name(); String attrValue = attr.value(); @@ -540,7 +539,7 @@ void XMLTokenizer::parseStartElement() String prefix = prefixFromQName(m_stream.qualifiedName().toString()); if (m_parsingFragment && uri.isNull()) { - Q_ASSERT (prefix.isNull()); + Q_ASSERT(prefix.isNull()); uri = m_defaultNamespaceURI; } diff --git a/WebCore/dom/XMLTokenizerScope.h b/WebCore/dom/XMLTokenizerScope.h index a3c1188..c29b796 100644 --- a/WebCore/dom/XMLTokenizerScope.h +++ b/WebCore/dom/XMLTokenizerScope.h @@ -36,7 +36,7 @@ namespace WebCore { class DocLoader; - class XMLTokenizerScope : Noncopyable { + class XMLTokenizerScope : public Noncopyable { public: XMLTokenizerScope(DocLoader* docLoader); ~XMLTokenizerScope(); diff --git a/WebCore/dom/default/PlatformMessagePortChannel.cpp b/WebCore/dom/default/PlatformMessagePortChannel.cpp new file mode 100644 index 0000000..d668703 --- /dev/null +++ b/WebCore/dom/default/PlatformMessagePortChannel.cpp @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2009 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 "PlatformMessagePortChannel.h" + +#include "MessagePort.h" +#include "ScriptExecutionContext.h" + +namespace WebCore { + +// MessagePortChannel implementations - just delegate to the PlatformMessagePortChannel. +void MessagePortChannel::createChannel(PassRefPtr<MessagePort> port1, PassRefPtr<MessagePort> port2) +{ + PlatformMessagePortChannel::createChannel(port1, port2); +} + +PassOwnPtr<MessagePortChannel> MessagePortChannel::create(PassRefPtr<PlatformMessagePortChannel> channel) +{ + return new MessagePortChannel(channel); +} + +MessagePortChannel::MessagePortChannel(PassRefPtr<PlatformMessagePortChannel> channel) + : m_channel(channel) +{ +} + +MessagePortChannel::~MessagePortChannel() +{ + // Make sure we close our platform channel when the base is freed, to keep the channel objects from leaking. + m_channel->close(); +} + +bool MessagePortChannel::entangleIfOpen(MessagePort* port) +{ + return m_channel->entangleIfOpen(port); +} + +void MessagePortChannel::disentangle() +{ + m_channel->disentangle(); +} + +void MessagePortChannel::postMessageToRemote(PassOwnPtr<MessagePortChannel::EventData> message) +{ + m_channel->postMessageToRemote(message); +} + +bool MessagePortChannel::tryGetMessageFromRemote(OwnPtr<MessagePortChannel::EventData>& result) +{ + return m_channel->tryGetMessageFromRemote(result); +} + +void MessagePortChannel::close() +{ + m_channel->close(); +} + +bool MessagePortChannel::isConnectedTo(MessagePort* port) +{ + return m_channel->isConnectedTo(port); +} + +bool MessagePortChannel::hasPendingActivity() +{ + return m_channel->hasPendingActivity(); +} + +MessagePort* MessagePortChannel::locallyEntangledPort(const ScriptExecutionContext* context) +{ + return m_channel->locallyEntangledPort(context); +} + +PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::create(PassRefPtr<MessagePortQueue> incoming, PassRefPtr<MessagePortQueue> outgoing) +{ + return adoptRef(new PlatformMessagePortChannel(incoming, outgoing)); +} + +PlatformMessagePortChannel::PlatformMessagePortChannel(PassRefPtr<MessagePortQueue> incoming, PassRefPtr<MessagePortQueue> outgoing) + : m_entangledChannel(0) + , m_incomingQueue(incoming) + , m_outgoingQueue(outgoing) + , m_remotePort(0) +{ +} + +PlatformMessagePortChannel::~PlatformMessagePortChannel() +{ +} + +void PlatformMessagePortChannel::createChannel(PassRefPtr<MessagePort> port1, PassRefPtr<MessagePort> port2) +{ + // Create incoming/outgoing queues. + RefPtr<PlatformMessagePortChannel::MessagePortQueue> queue1 = PlatformMessagePortChannel::MessagePortQueue::create(); + RefPtr<PlatformMessagePortChannel::MessagePortQueue> queue2 = PlatformMessagePortChannel::MessagePortQueue::create(); + + // Create proxies for each endpoint. + RefPtr<PlatformMessagePortChannel> channel1 = PlatformMessagePortChannel::create(queue1, queue2); + RefPtr<PlatformMessagePortChannel> channel2 = PlatformMessagePortChannel::create(queue2, queue1); + + // Entangle the two endpoints. + channel1->setEntangledChannel(channel2); + channel2->setEntangledChannel(channel1); + + // Now entangle the proxies with the appropriate local ports. + port1->entangle(MessagePortChannel::create(channel2)); + port2->entangle(MessagePortChannel::create(channel1)); +} + +bool PlatformMessagePortChannel::entangleIfOpen(MessagePort* port) +{ + // We can't call member functions on our remote pair while holding our mutex or we'll deadlock, but we need to guard against the remote port getting closed/freed, so create a standalone reference. + RefPtr<PlatformMessagePortChannel> remote = entangledChannel(); + if (!remote) + return false; + remote->setRemotePort(port); + return true; +} + +void PlatformMessagePortChannel::disentangle() +{ + RefPtr<PlatformMessagePortChannel> remote = entangledChannel(); + if (remote) + remote->setRemotePort(0); +} + +void PlatformMessagePortChannel::setRemotePort(MessagePort* port) +{ + MutexLocker lock(m_mutex); + // Should never set port if it is already set. + ASSERT(!port || !m_remotePort); + m_remotePort = port; +} + +MessagePort* PlatformMessagePortChannel::remotePort() +{ + MutexLocker lock(m_mutex); + return m_remotePort; +} + +PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::entangledChannel() +{ + MutexLocker lock(m_mutex); + return m_entangledChannel; +} + +void PlatformMessagePortChannel::setEntangledChannel(PassRefPtr<PlatformMessagePortChannel> remote) +{ + MutexLocker lock(m_mutex); + // Should only be set as part of initial creation/entanglement. + if (remote) + ASSERT(!m_entangledChannel.get()); + m_entangledChannel = remote; +} + +void PlatformMessagePortChannel::postMessageToRemote(PassOwnPtr<MessagePortChannel::EventData> message) +{ + MutexLocker lock(m_mutex); + if (!m_outgoingQueue) + return; + bool wasEmpty = m_outgoingQueue->appendAndCheckEmpty(message); + if (wasEmpty && m_remotePort) + m_remotePort->messageAvailable(); +} + +bool PlatformMessagePortChannel::tryGetMessageFromRemote(OwnPtr<MessagePortChannel::EventData>& result) +{ + MutexLocker lock(m_mutex); + return m_incomingQueue->tryGetMessage(result); +} + +bool PlatformMessagePortChannel::isConnectedTo(MessagePort* port) +{ + MutexLocker lock(m_mutex); + return m_remotePort == port; +} + +// Closes the port so no further messages can be sent from either end. +void PlatformMessagePortChannel::close() +{ + RefPtr<PlatformMessagePortChannel> remote = entangledChannel(); + if (!remote) + return; + closeInternal(); + remote->closeInternal(); +} + +void PlatformMessagePortChannel::closeInternal() +{ + MutexLocker lock(m_mutex); + // Disentangle ourselves from the other end. We still maintain a reference to our incoming queue, since previously-existing messages should still be delivered. + m_remotePort = 0; + m_entangledChannel = 0; + m_outgoingQueue = 0; +} + +bool PlatformMessagePortChannel::hasPendingActivity() +{ + MutexLocker lock(m_mutex); + return !m_incomingQueue->isEmpty(); +} + +MessagePort* PlatformMessagePortChannel::locallyEntangledPort(const ScriptExecutionContext* context) +{ + MutexLocker lock(m_mutex); + // See if both contexts are run by the same thread (are the same context, or are both documents). + if (m_remotePort) { + // The remote port's ScriptExecutionContext is guaranteed not to change here - MessagePort::contextDestroyed() will close the port before the context goes away, and close() will block because we are holding the mutex. + ScriptExecutionContext* remoteContext = m_remotePort->scriptExecutionContext(); + if (remoteContext == context || (remoteContext && remoteContext->isDocument() && context->isDocument())) + return m_remotePort; + } + return 0; +} + +} // namespace WebCore diff --git a/WebCore/dom/default/PlatformMessagePortChannel.h b/WebCore/dom/default/PlatformMessagePortChannel.h new file mode 100644 index 0000000..0ce2d13 --- /dev/null +++ b/WebCore/dom/default/PlatformMessagePortChannel.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2009 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 PlatformMessagePortChannel_h +#define PlatformMessagePortChannel_h + +#include "MessagePortChannel.h" + +#include <wtf/MessageQueue.h> +#include <wtf/PassRefPtr.h> +#include <wtf/Threading.h> + +namespace WebCore { + + class MessagePort; + + // PlatformMessagePortChannel is a platform-dependent interface to the remote side of a message channel. + // This default implementation supports multiple threads running within a single process. Implementations for multi-process platforms should define these public APIs in their own platform-specific PlatformMessagePortChannel file. + // The goal of this implementation is to eliminate contention except when cloning or closing the port, so each side of the channel has its own separate mutex. + class PlatformMessagePortChannel : public ThreadSafeShared<PlatformMessagePortChannel> { + public: + static void createChannel(PassRefPtr<MessagePort>, PassRefPtr<MessagePort>); + + // APIs delegated from MessagePortChannel.h + bool entangleIfOpen(MessagePort*); + void disentangle(); + void postMessageToRemote(PassOwnPtr<MessagePortChannel::EventData>); + bool tryGetMessageFromRemote(OwnPtr<MessagePortChannel::EventData>&); + void close(); + bool isConnectedTo(MessagePort*); + bool hasPendingActivity(); + MessagePort* locallyEntangledPort(const ScriptExecutionContext*); + + // Wrapper for MessageQueue that allows us to do thread safe sharing by two proxies. + class MessagePortQueue : public ThreadSafeShared<MessagePortQueue> { + public: + static PassRefPtr<MessagePortQueue> create() { return adoptRef(new MessagePortQueue()); } + + bool tryGetMessage(OwnPtr<MessagePortChannel::EventData>& message) + { + MessagePortChannel::EventData* holder = 0; + bool messageAvailable = m_queue.tryGetMessage(holder); + if (messageAvailable) + message.set(holder); + return messageAvailable; + } + + bool appendAndCheckEmpty(PassOwnPtr<MessagePortChannel::EventData> message) + { + return m_queue.appendAndCheckEmpty(message.release()); + } + + bool isEmpty() + { + return m_queue.isEmpty(); + } + + ~MessagePortQueue() + { + // Manually free any items left in the queue, since we can't use OwnPtr internally. + MessagePortChannel::EventData* data = 0; + while (m_queue.tryGetMessage(data)) + delete data; + } + private: + MessagePortQueue() { } + + // OwnPtr is Noncopyable, so we can't use it as the template type in a MessageQueue. So we just store a pointer to EventData and manually free it in the destructor. + // FIXME: Use a lock-free queue implementation to completely eliminate contention when sending/receiving messages. + MessageQueue<MessagePortChannel::EventData*> m_queue; + }; + + ~PlatformMessagePortChannel(); + + private: + static PassRefPtr<PlatformMessagePortChannel> create(PassRefPtr<MessagePortQueue> incoming, PassRefPtr<MessagePortQueue> outgoing); + PlatformMessagePortChannel(PassRefPtr<MessagePortQueue> incoming, PassRefPtr<MessagePortQueue> outgoing); + + PassRefPtr<PlatformMessagePortChannel> entangledChannel(); + void setEntangledChannel(PassRefPtr<PlatformMessagePortChannel>); + + void setRemotePort(MessagePort*); + MessagePort* remotePort(); + void closeInternal(); + + // Mutex used to ensure exclusive access to the object internals. + Mutex m_mutex; + + // Pointer to our entangled pair - cleared when close() is called. + RefPtr<PlatformMessagePortChannel> m_entangledChannel; + + // Reference to the message queue for the (local) entangled port. + RefPtr<MessagePortQueue> m_incomingQueue; + RefPtr<MessagePortQueue> m_outgoingQueue; + + // The port we are connected to (the remote port) - this is the port that is notified when new messages arrive. + MessagePort* m_remotePort; + }; + +} // namespace WebCore + +#endif // PlatformMessagePortChannel_h diff --git a/WebCore/dom/make_names.pl b/WebCore/dom/make_names.pl index 12f0ec7..e6d59a0 100755 --- a/WebCore/dom/make_names.pl +++ b/WebCore/dom/make_names.pl @@ -875,22 +875,23 @@ sub printWrapperFunctions } # Hack for the media tags + # FIXME: This should have been done via a CustomWrapper attribute and a separate *Custom file. if ($tags{$tagName}{"wrapperOnlyIfMediaIsAvailable"}) { print F <<END -static JSNode* create${JSInterfaceName}Wrapper(ExecState* exec, PassRefPtr<$parameters{'namespace'}Element> element) +static JSNode* create${JSInterfaceName}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{'namespace'}Element> element) { if (!MediaPlayer::isAvailable()) - return CREATE_DOM_NODE_WRAPPER(exec, $parameters{'namespace'}Element, element.get()); - return CREATE_DOM_NODE_WRAPPER(exec, ${JSInterfaceName}, element.get()); + return CREATE_DOM_NODE_WRAPPER(exec, globalObject, $parameters{'namespace'}Element, element.get()); + return CREATE_DOM_NODE_WRAPPER(exec, globalObject, ${JSInterfaceName}, element.get()); } END ; } else { print F <<END -static JSNode* create${JSInterfaceName}Wrapper(ExecState* exec, PassRefPtr<$parameters{'namespace'}Element> element) +static JSNode* create${JSInterfaceName}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{'namespace'}Element> element) { - return CREATE_DOM_NODE_WRAPPER(exec, ${JSInterfaceName}, element.get()); + return CREATE_DOM_NODE_WRAPPER(exec, globalObject, ${JSInterfaceName}, element.get()); } END @@ -931,7 +932,7 @@ namespace WebCore { using namespace $parameters{'namespace'}Names; -typedef JSNode* (*Create$parameters{'namespace'}ElementWrapperFunction)(ExecState*, PassRefPtr<$parameters{'namespace'}Element>); +typedef JSNode* (*Create$parameters{'namespace'}ElementWrapperFunction)(ExecState*, JSDOMGlobalObject*, PassRefPtr<$parameters{'namespace'}Element>); END ; @@ -939,7 +940,7 @@ END printWrapperFunctions($F); print F <<END -JSNode* createJS$parameters{'namespace'}Wrapper(ExecState* exec, PassRefPtr<$parameters{'namespace'}Element> element) +JSNode* createJS$parameters{'namespace'}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{'namespace'}Element> element) { typedef HashMap<WebCore::AtomicStringImpl*, Create$parameters{'namespace'}ElementWrapperFunction> FunctionMap; DEFINE_STATIC_LOCAL(FunctionMap, map, ()); @@ -969,8 +970,8 @@ END } Create$parameters{'namespace'}ElementWrapperFunction createWrapperFunction = map.get(element->localName().impl()); if (createWrapperFunction) - return createWrapperFunction(exec, element); - return CREATE_DOM_NODE_WRAPPER(exec, $parameters{'namespace'}Element, element.get()); + return createWrapperFunction(exec, globalObject, element); + return CREATE_DOM_NODE_WRAPPER(exec, globalObject, $parameters{'namespace'}Element, element.get()); } } @@ -1006,9 +1007,10 @@ namespace JSC { namespace WebCore { class JSNode; + class JSDOMGlobalObject; class $parameters{'namespace'}Element; - JSNode* createJS$parameters{'namespace'}Wrapper(JSC::ExecState*, PassRefPtr<$parameters{'namespace'}Element>); + JSNode* createJS$parameters{'namespace'}Wrapper(JSC::ExecState*, JSDOMGlobalObject*, PassRefPtr<$parameters{'namespace'}Element>); } |