diff options
author | Steve Block <steveblock@google.com> | 2009-12-15 10:12:09 +0000 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2009-12-17 17:41:10 +0000 |
commit | 643ca7872b450ea4efacab6188849e5aac2ba161 (patch) | |
tree | 6982576c228bcd1a7efe98afed544d840751094c /WebCore/dom | |
parent | d026980fde6eb3b01c1fe49441174e89cd1be298 (diff) | |
download | external_webkit-643ca7872b450ea4efacab6188849e5aac2ba161.zip external_webkit-643ca7872b450ea4efacab6188849e5aac2ba161.tar.gz external_webkit-643ca7872b450ea4efacab6188849e5aac2ba161.tar.bz2 |
Merge webkit.org at r51976 : Initial merge by git.
Change-Id: Ib0e7e2f0fb4bee5a186610272edf3186f0986b43
Diffstat (limited to 'WebCore/dom')
63 files changed, 852 insertions, 376 deletions
diff --git a/WebCore/dom/BeforeUnloadEvent.cpp b/WebCore/dom/BeforeUnloadEvent.cpp index 2521aa1..97d7f97 100644 --- a/WebCore/dom/BeforeUnloadEvent.cpp +++ b/WebCore/dom/BeforeUnloadEvent.cpp @@ -1,6 +1,4 @@ /** - * This file is part of the DOM implementation for KDE. - * * 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) diff --git a/WebCore/dom/BeforeUnloadEvent.h b/WebCore/dom/BeforeUnloadEvent.h index 39c96fd..2644693 100644 --- a/WebCore/dom/BeforeUnloadEvent.h +++ b/WebCore/dom/BeforeUnloadEvent.h @@ -1,6 +1,4 @@ /* - * This file is part of the DOM implementation for KDE. - * * 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) diff --git a/WebCore/dom/CSSMappedAttributeDeclaration.cpp b/WebCore/dom/CSSMappedAttributeDeclaration.cpp index 7fe0915..9ee6474 100644 --- a/WebCore/dom/CSSMappedAttributeDeclaration.cpp +++ b/WebCore/dom/CSSMappedAttributeDeclaration.cpp @@ -1,6 +1,4 @@ /** - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Peter Kelly (pmk@post.com) diff --git a/WebCore/dom/ClassNodeList.h b/WebCore/dom/ClassNodeList.h index d40ee19..c519b3e 100644 --- a/WebCore/dom/ClassNodeList.h +++ b/WebCore/dom/ClassNodeList.h @@ -30,8 +30,8 @@ #ifndef ClassNodeList_h #define ClassNodeList_h -#include "ClassNames.h" #include "DynamicNodeList.h" +#include "SpaceSplitString.h" namespace WebCore { @@ -47,7 +47,7 @@ namespace WebCore { virtual bool nodeMatches(Element*) const; - ClassNames m_classNames; + SpaceSplitString m_classNames; }; } // namespace WebCore diff --git a/WebCore/dom/Clipboard.cpp b/WebCore/dom/Clipboard.cpp index 6d1bc15..2aea90a 100644 --- a/WebCore/dom/Clipboard.cpp +++ b/WebCore/dom/Clipboard.cpp @@ -55,6 +55,8 @@ void Clipboard::setAccessPolicy(ClipboardAccessPolicy policy) static DragOperation dragOpFromIEOp(const String& op) { // yep, it's really just this fixed set + if (op == "uninitialized") + return DragOperationEvery; if (op == "none") return DragOperationNone; if (op == "copy") diff --git a/WebCore/dom/CompositionEvent.cpp b/WebCore/dom/CompositionEvent.cpp new file mode 100644 index 0000000..508d5e6 --- /dev/null +++ b/WebCore/dom/CompositionEvent.cpp @@ -0,0 +1,63 @@ +/* + * 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 "CompositionEvent.h" + +#include "EventNames.h" + +namespace WebCore { + +CompositionEvent::CompositionEvent() +{ +} + +CompositionEvent::CompositionEvent(const AtomicString& type, PassRefPtr<AbstractView> view, const String& data) + : UIEvent(type, true, true, view, 0) + , m_data(data) +{ +} + +CompositionEvent::~CompositionEvent() +{ +} + +void CompositionEvent::initCompositionEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView> view, const String& data) +{ + if (dispatched()) + return; + + initUIEvent(type, canBubble, cancelable, view, 0); + + m_data = data; +} + +bool CompositionEvent::isCompositionEvent() const +{ + return true; +} + +} // namespace WebCore diff --git a/WebCore/dom/CompositionEvent.h b/WebCore/dom/CompositionEvent.h new file mode 100644 index 0000000..4ff01ae --- /dev/null +++ b/WebCore/dom/CompositionEvent.h @@ -0,0 +1,61 @@ +/* + * 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 CompositionEvent_h +#define CompositionEvent_h + +#include "UIEvent.h" + +namespace WebCore { + + class CompositionEvent : public UIEvent { + public: + static PassRefPtr<CompositionEvent> create() + { + return adoptRef(new CompositionEvent); + } + static PassRefPtr<CompositionEvent> create(const AtomicString& type, PassRefPtr<AbstractView> view, const String& data) + { + return adoptRef(new CompositionEvent(type, view, data)); + } + virtual ~CompositionEvent(); + + void initCompositionEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>, const String& data); + + String data() const { return m_data; } + + virtual bool isCompositionEvent() const; + + private: + CompositionEvent(); + CompositionEvent(const AtomicString& type, PassRefPtr<AbstractView> view, const String& data); + + String m_data; + }; + +} // namespace WebCore + +#endif // CompositionEvent_h diff --git a/WebCore/dom/CompositionEvent.idl b/WebCore/dom/CompositionEvent.idl new file mode 100644 index 0000000..3752091 --- /dev/null +++ b/WebCore/dom/CompositionEvent.idl @@ -0,0 +1,43 @@ +/* + * 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 events { + + // Introduced in DOM Level 3: + interface [ + GenerateConstructor + ] CompositionEvent : UIEvent { + + readonly attribute DOMString data; + + void initCompositionEvent(in DOMString typeArg, + in boolean canBubbleArg, + in boolean cancelableArg, + in DOMWindow viewArg, + in DOMString dataArg); + + }; + +} diff --git a/WebCore/dom/DOMImplementation.cpp b/WebCore/dom/DOMImplementation.cpp index 59b9703..f7c8242 100644 --- a/WebCore/dom/DOMImplementation.cpp +++ b/WebCore/dom/DOMImplementation.cpp @@ -305,7 +305,8 @@ PassRefPtr<HTMLDocument> DOMImplementation::createHTMLDocument(const String& tit { RefPtr<HTMLDocument> d = HTMLDocument::create(0); d->open(); - d->write("<!doctype html><html><head><title>" + title + "</title></head><body></body></html>"); + d->write("<!doctype html><html><body></body></html>"); + d->setTitle(title); return d.release(); } diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp index 174e58d..ba6dc97 100644 --- a/WebCore/dom/Document.cpp +++ b/WebCore/dom/Document.cpp @@ -98,6 +98,7 @@ #include "PageGroup.h" #include "PageTransitionEvent.h" #include "PlatformKeyboardEvent.h" +#include "PopStateEvent.h" #include "ProcessingInstruction.h" #include "ProgressEvent.h" #include "RegisteredEventListener.h" @@ -386,15 +387,18 @@ Document::Document(Frame* frame, bool isXHTML) m_ignoreAutofocus = false; m_frame = frame; +<<<<<<< HEAD:WebCore/dom/Document.cpp m_renderArena = 0; #if !PLATFORM(ANDROID) +======= + +>>>>>>> webkit.org at r51976:WebCore/dom/Document.cpp m_axObjectCache = 0; #endif m_docLoader = new DocLoader(this); visuallyOrdered = false; m_bParsing = false; - m_tokenizer = 0; m_wellFormed = false; setParseMode(Strict); @@ -465,8 +469,7 @@ void Document::removedLastRef() deleteAllValues(m_markers); m_markers.clear(); - delete m_tokenizer; - m_tokenizer = 0; + m_tokenizer.clear(); m_cssCanvasElements.clear(); @@ -500,18 +503,15 @@ Document::~Document() forgetAllDOMNodesForDocument(this); #endif - delete m_tokenizer; + m_tokenizer.clear(); m_document = 0; delete m_styleSelector; - delete m_docLoader; - - if (m_renderArena) { - delete m_renderArena; - m_renderArena = 0; - } + m_docLoader.clear(); + + m_renderArena.clear(); #if ENABLE(XBL) - delete m_bindingManager; + m_bindingManager.clear(); #endif deleteAllValues(m_markers); @@ -1264,13 +1264,13 @@ void Document::recalcStyle(StyleChange change) return; // Guard against re-entrancy. -dwh #if ENABLE(INSPECTOR) - InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent(); - if (timelineAgent) + if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent()) timelineAgent->willRecalculateStyle(); #endif m_inStyleRecalc = true; suspendPostAttachCallbacks(); + RenderWidget::suspendWidgetHierarchyUpdates(); if (view()) view()->pauseScheduledEvents(); @@ -1341,6 +1341,7 @@ bail_out: if (view()) view()->resumeScheduledEvents(); + RenderWidget::resumeWidgetHierarchyUpdates(); resumePostAttachCallbacks(); m_inStyleRecalc = false; @@ -1351,7 +1352,7 @@ bail_out: } #if ENABLE(INSPECTOR) - if (timelineAgent) + if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent()) timelineAgent->didRecalculateStyle(); #endif } @@ -1442,7 +1443,7 @@ void Document::attach() m_renderArena = new RenderArena(); // Create the rendering tree - setRenderer(new (m_renderArena) RenderView(this, view())); + setRenderer(new (m_renderArena.get()) RenderView(this, view())); #if USE(ACCELERATED_COMPOSITING) renderView()->didMoveOnscreen(); #endif @@ -1514,17 +1515,19 @@ void Document::detach() if (render) render->destroy(); + HashSet<RefPtr<HistoryItem> > associatedHistoryItems; + associatedHistoryItems.swap(m_associatedHistoryItems); + HashSet<RefPtr<HistoryItem> >::iterator end = associatedHistoryItems.end(); + for (HashSet<RefPtr<HistoryItem> >::iterator i = associatedHistoryItems.begin(); i != end; ++i) + (*i)->documentDetached(this); + // This is required, as our Frame might delete itself as soon as it detaches // us. However, this violates Node::detach() symantics, as it's never // possible to re-attach. Eventually Document::detach() should be renamed, // or this setting of the frame to 0 could be made explicit in each of the // callers of Document::detach(). m_frame = 0; - - if (m_renderArena) { - delete m_renderArena; - m_renderArena = 0; - } + m_renderArena.clear(); } void Document::removeAllEventListeners() @@ -1647,8 +1650,7 @@ void Document::cancelParsing() // the onload handler when closing as a side effect of a cancel-style // change, such as opening a new document or closing the window while // still parsing - delete m_tokenizer; - m_tokenizer = 0; + m_tokenizer.clear(); close(); } } @@ -1657,8 +1659,7 @@ void Document::implicitOpen() { cancelParsing(); - delete m_tokenizer; - m_tokenizer = 0; + m_tokenizer.clear(); removeChildren(); @@ -1755,8 +1756,7 @@ void Document::implicitClose() // We have to clear the tokenizer, in case someone document.write()s from the // onLoad event handler, as in Radar 3206524. - delete m_tokenizer; - m_tokenizer = 0; + m_tokenizer.clear(); // Parser should have picked up all preloads by now m_docLoader->clearPreloads(); @@ -1793,6 +1793,9 @@ void Document::implicitClose() ImageLoader::dispatchPendingEvents(); dispatchWindowLoadEvent(); dispatchWindowEvent(PageTransitionEvent::create(eventNames().pageshowEvent, false), this); + if (m_pendingStateObject) + dispatchWindowEvent(PopStateEvent::create(m_pendingStateObject.release())); + if (f) f->loader()->handledOnloadEvents(); #ifdef INSTRUMENT_LAYOUT_SCHEDULING @@ -2291,8 +2294,10 @@ void Document::processHttpEquiv(const String& equiv, const String& content) } } else if (equalIgnoringCase(equiv, "set-cookie")) { // FIXME: make setCookie work on XML documents too; e.g. in case of <html:meta .....> - if (isHTMLDocument()) - static_cast<HTMLDocument*>(this)->setCookie(content); + if (isHTMLDocument()) { + ExceptionCode ec; // Exception (for sandboxed documents) ignored. + static_cast<HTMLDocument*>(this)->setCookie(content, ec); + } } else if (equalIgnoringCase(equiv, "content-language")) setContentLanguage(content); else if (equalIgnoringCase(equiv, "x-dns-prefetch-control")) @@ -2608,7 +2613,7 @@ void Document::recalcStyleSelector() sheet = cssSheet.get(); } } - } else if (n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag)) + } else if ((n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag))) #if ENABLE(SVG) || (n->isSVGElement() && n->hasTagName(SVGNames::styleTag)) #endif @@ -2770,14 +2775,14 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) oldFocusedNode->setActive(false); oldFocusedNode->setFocus(false); - + // Dispatch a change event for text fields or textareas that have been edited RenderObject* r = oldFocusedNode->renderer(); - if (r && r->isTextControl() && toRenderTextControl(r)->isEdited()) { - oldFocusedNode->dispatchEvent(Event::create(eventNames().changeEvent, true, false)); + if (r && r->isTextControl() && toRenderTextControl(r)->wasChangedSinceLastChangeEvent()) { + static_cast<Element*>(oldFocusedNode.get())->dispatchFormControlChangeEvent(); r = oldFocusedNode->renderer(); if (r && r->isTextControl()) - toRenderTextControl(r)->setEdited(false); + toRenderTextControl(r)->setChangedSinceLastChangeEvent(false); } // Dispatch the blur event and let the node do any other blur related activities (important for text fields) @@ -2861,6 +2866,8 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) axObjectCache()->handleFocusedUIElementChanged(oldFocusedRenderer, newFocusedRenderer); } #endif + if (!focusChangeBlocked) + page()->chrome()->focusedNodeChanged(m_focusedNode.get()); SetFocusedNodeDone: updateStyleIfNeeded(); @@ -3112,11 +3119,20 @@ Element* Document::ownerElement() const return frame()->ownerElement(); } -String Document::cookie() const +String Document::cookie(ExceptionCode& ec) const { if (page() && !page()->cookieEnabled()) return String(); + // FIXME: The HTML5 DOM spec states that this attribute can raise an + // INVALID_STATE_ERR exception on getting if the Document has no + // browsing context. + + if (securityOrigin()->isSandboxed(SandboxOrigin)) { + ec = SECURITY_ERR; + return String(); + } + KURL cookieURL = this->cookieURL(); if (cookieURL.isEmpty()) return String(); @@ -3124,11 +3140,20 @@ String Document::cookie() const return cookies(this, cookieURL); } -void Document::setCookie(const String& value) +void Document::setCookie(const String& value, ExceptionCode& ec) { if (page() && !page()->cookieEnabled()) return; + // FIXME: The HTML5 DOM spec states that this attribute can raise an + // INVALID_STATE_ERR exception on setting if the Document has no + // browsing context. + + if (securityOrigin()->isSandboxed(SandboxOrigin)) { + ec = SECURITY_ERR; + return; + } + KURL cookieURL = this->cookieURL(); if (cookieURL.isEmpty()) return; @@ -3855,7 +3880,7 @@ void Document::repaintMarkers(DocumentMarker::MarkerType markerType) } } -void Document::setRenderedRectForMarker(Node* node, DocumentMarker marker, const IntRect& r) +void Document::setRenderedRectForMarker(Node* node, const DocumentMarker& marker, const IntRect& r) { MarkerMapVectorPair* vectorPair = m_markers.get(node); if (!vectorPair) { @@ -4377,6 +4402,8 @@ void Document::initSecurityContext() m_cookieURL = url; ScriptExecutionContext::setSecurityOrigin(SecurityOrigin::create(url)); + updateSandboxFlags(); + if (SecurityOrigin::allowSubstituteDataAccessToLocal()) { // If this document was loaded with substituteData, then the document can // load local resources. See https://bugs.webkit.org/show_bug.cgi?id=16756 @@ -4427,6 +4454,46 @@ void Document::setSecurityOrigin(SecurityOrigin* securityOrigin) initDNSPrefetch(); } +void Document::updateURLForPushOrReplaceState(const KURL& url) +{ + Frame* f = frame(); + if (!f) + return; + + setURL(url); + f->loader()->documentLoader()->replaceRequestURLForSameDocumentNavigation(url); +} + +void Document::statePopped(SerializedScriptValue* stateObject) +{ + Frame* f = frame(); + if (!f) + return; + + if (f->loader()->isComplete()) + dispatchWindowEvent(PopStateEvent::create(stateObject)); + else + m_pendingStateObject = stateObject; +} + +void Document::registerHistoryItem(HistoryItem* item) +{ + ASSERT(!m_associatedHistoryItems.contains(item)); + m_associatedHistoryItems.add(item); +} + +void Document::unregisterHistoryItem(HistoryItem* item) +{ + ASSERT(m_associatedHistoryItems.contains(item) || m_associatedHistoryItems.isEmpty()); + m_associatedHistoryItems.remove(item); +} + +void Document::updateSandboxFlags() +{ + if (m_frame && securityOrigin()) + securityOrigin()->setSandboxFlags(m_frame->loader()->sandboxFlags()); +} + void Document::updateFocusAppearanceSoon() { if (!m_updateFocusAppearanceTimer.isActive()) @@ -4690,7 +4757,7 @@ void Document::scriptImported(unsigned long identifier, const String& sourceStri class ScriptExecutionContextTaskTimer : public TimerBase { public: - ScriptExecutionContextTaskTimer(PassRefPtr<Document> context, PassRefPtr<ScriptExecutionContext::Task> task) + ScriptExecutionContextTaskTimer(PassRefPtr<Document> context, PassOwnPtr<ScriptExecutionContext::Task> task) : m_context(context) , m_task(task) { @@ -4704,18 +4771,18 @@ private: } RefPtr<Document> m_context; - RefPtr<ScriptExecutionContext::Task> m_task; + OwnPtr<ScriptExecutionContext::Task> m_task; }; -struct PerformTaskContext { - PerformTaskContext(ScriptExecutionContext* scriptExecutionContext, PassRefPtr<ScriptExecutionContext::Task> task) +struct PerformTaskContext : Noncopyable { + PerformTaskContext(ScriptExecutionContext* scriptExecutionContext, PassOwnPtr<ScriptExecutionContext::Task> task) : scriptExecutionContext(scriptExecutionContext) , task(task) { } ScriptExecutionContext* scriptExecutionContext; // The context should exist until task execution. - RefPtr<ScriptExecutionContext::Task> task; + OwnPtr<ScriptExecutionContext::Task> task; }; static void performTask(void* ctx) @@ -4725,7 +4792,7 @@ static void performTask(void* ctx) delete ptctx; } -void Document::postTask(PassRefPtr<Task> task) +void Document::postTask(PassOwnPtr<Task> task) { if (isMainThread()) { ScriptExecutionContextTaskTimer* timer = new ScriptExecutionContextTaskTimer(static_cast<Document*>(this), task); @@ -4790,4 +4857,11 @@ bool Document::isXHTMLMPDocument() const } #endif +#if ENABLE(INSPECTOR) +InspectorTimelineAgent* Document::inspectorTimelineAgent() const +{ + return page() ? page()->inspectorTimelineAgent() : 0; +} +#endif + } // namespace WebCore diff --git a/WebCore/dom/Document.h b/WebCore/dom/Document.h index 9f5785e..3d0582c 100644 --- a/WebCore/dom/Document.h +++ b/WebCore/dom/Document.h @@ -33,7 +33,6 @@ #include "CollectionType.h" #include "Color.h" #include "DocumentMarker.h" -#include "Page.h" #include "ScriptExecutionContext.h" #include "Timer.h" #include <wtf/HashCountedSet.h> @@ -68,7 +67,6 @@ namespace WebCore { class EventListener; class Frame; class FrameView; - class HitTestRequest; class HTMLCanvasElement; class HTMLCollection; class HTMLAllCollection; @@ -78,6 +76,8 @@ namespace WebCore { class HTMLHeadElement; class HTMLInputElement; class HTMLMapElement; + class HistoryItem; + class HitTestRequest; class InspectorTimelineAgent; class IntPoint; class DOMWrapperWorld; @@ -85,6 +85,7 @@ namespace WebCore { class MouseEventWithHitTestResults; class NodeFilter; class NodeIterator; + class Page; class PlatformMouseEvent; class ProcessingInstruction; class Range; @@ -93,6 +94,7 @@ namespace WebCore { class RenderView; class ScriptElementData; class SecurityOrigin; + class SerializedScriptValue; class SegmentedString; class Settings; class StyleSheet; @@ -451,12 +453,12 @@ public: void updateLayout(); void updateLayoutIgnorePendingStylesheets(); static void updateStyleForAllDocuments(); // FIXME: Try to reduce the # of calls to this function. - DocLoader* docLoader() { return m_docLoader; } + DocLoader* docLoader() { return m_docLoader.get(); } virtual void attach(); virtual void detach(); - RenderArena* renderArena() { return m_renderArena; } + RenderArena* renderArena() { return m_renderArena.get(); } RenderView* renderView() const; @@ -504,7 +506,7 @@ public: CSSStyleSheet* mappedElementSheet(); virtual Tokenizer* createTokenizer(); - Tokenizer* tokenizer() { return m_tokenizer; } + Tokenizer* tokenizer() { return m_tokenizer.get(); } bool printing() const { return m_printing; } void setPrinting(bool p) { m_printing = p; } @@ -683,8 +685,8 @@ public: void setTitle(const String&, Element* titleElement = 0); void removeTitle(Element* titleElement); - String cookie() const; - void setCookie(const String&); + String cookie(ExceptionCode&) const; + void setCookie(const String&, ExceptionCode&); String referrer() const; @@ -738,7 +740,7 @@ public: void removeMarkers(DocumentMarker::MarkerType = DocumentMarker::AllMarkers); void removeMarkers(Node*); void repaintMarkers(DocumentMarker::MarkerType = DocumentMarker::AllMarkers); - void setRenderedRectForMarker(Node*, DocumentMarker, const IntRect&); + void setRenderedRectForMarker(Node*, const DocumentMarker&, const IntRect&); void invalidateRenderedRectsForMarkersInRect(const IntRect&); void shiftMarkers(Node*, unsigned startOffset, int delta, DocumentMarker::MarkerType = DocumentMarker::AllMarkers); void setMarkersActive(Range*, bool); @@ -772,7 +774,7 @@ public: #if ENABLE(XBL) // XBL methods - XBLBindingManager* bindingManager() const { return m_bindingManager; } + XBLBindingManager* bindingManager() const { return m_bindingManager.get(); } #endif void incDOMTreeVersion() { ++m_domtree_version; } @@ -832,7 +834,7 @@ public: 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. + virtual void postTask(PassOwnPtr<Task>); // Executes the task on context's thread asynchronously. typedef HashMap<WebCore::Node*, JSNode*> JSWrapperCache; typedef HashMap<DOMWrapperWorld*, JSWrapperCache*> JSWrapperCacheMap; @@ -900,6 +902,13 @@ public: // that already contains content. void setSecurityOrigin(SecurityOrigin*); + void updateURLForPushOrReplaceState(const KURL&); + void statePopped(SerializedScriptValue*); + void registerHistoryItem(HistoryItem* item); + void unregisterHistoryItem(HistoryItem* item); + + void updateSandboxFlags(); // Set sandbox flags as determined by the frame. + bool processingLoadEvent() const { return m_processingLoadEvent; } #if ENABLE(DATABASE) @@ -976,8 +985,8 @@ private: bool m_didCalculateStyleSelector; Frame* m_frame; - DocLoader* m_docLoader; - Tokenizer* m_tokenizer; + OwnPtr<DocLoader> m_docLoader; + OwnPtr<Tokenizer> m_tokenizer; bool m_wellFormed; // Document URLs. @@ -1076,8 +1085,8 @@ private: String m_title; bool m_titleSetExplicitly; RefPtr<Element> m_titleElement; - - RenderArena* m_renderArena; + + OwnPtr<RenderArena> m_renderArena; typedef std::pair<Vector<DocumentMarker>, Vector<IntRect> > MarkerMapVectorPair; typedef HashMap<RefPtr<Node>, MarkerMapVectorPair*> MarkerMap; @@ -1090,6 +1099,8 @@ private: Element* m_cssTarget; bool m_processingLoadEvent; + RefPtr<SerializedScriptValue> m_pendingStateObject; + HashSet<RefPtr<HistoryItem> > m_associatedHistoryItems; double m_startTime; bool m_overMinimumLayoutThreshold; @@ -1102,7 +1113,7 @@ private: #endif #if ENABLE(XBL) - XBLBindingManager* m_bindingManager; // The access point through which documents and elements communicate with XBL. + OwnPtr<XBLBindingManager> m_bindingManager; // The access point through which documents and elements communicate with XBL. #endif typedef HashMap<AtomicStringImpl*, HTMLMapElement*> ImageMapsByName; @@ -1204,12 +1215,6 @@ inline bool Node::isDocumentNode() const return this == m_document; } -#if ENABLE(INSPECTOR) -inline InspectorTimelineAgent* Document::inspectorTimelineAgent() const { - return page() ? page()->inspectorTimelineAgent() : 0; -} -#endif - } // namespace WebCore #endif // Document_h diff --git a/WebCore/dom/Document.idl b/WebCore/dom/Document.idl index ce7010a..e54add0 100644 --- a/WebCore/dom/Document.idl +++ b/WebCore/dom/Document.idl @@ -35,7 +35,7 @@ module core { readonly attribute [V8Custom] DOMImplementation implementation; readonly attribute Element documentElement; - [ReturnsNew] Element createElement(in [ConvertNullToNullString, HintAtomic] DOMString tagName) + [ReturnsNew] Element createElement(in [ConvertNullToNullString] DOMString tagName) raises (DOMException); DocumentFragment createDocumentFragment(); [ReturnsNew] Text createTextNode(in DOMString data); @@ -64,7 +64,7 @@ module core { raises (DOMException); [OldStyleObjC] NodeList getElementsByTagNameNS(in [ConvertNullToNullString] DOMString namespaceURI, in DOMString localName); - Element getElementById(in [HintAtomic] DOMString elementId); + Element getElementById(in DOMString elementId); // DOM Level 3 Core @@ -162,10 +162,9 @@ module core { #endif readonly attribute DOMString URL; - // FIXME: the DOM spec states that this attribute can - // raise an exception on setting. attribute [ConvertNullToNullString] DOMString cookie - /*setter raises (DOMException)*/; + setter raises (DOMException), + getter raises (DOMException); // FIXME: the DOM spec does NOT have this attribute // raising an exception. diff --git a/WebCore/dom/DynamicNodeList.cpp b/WebCore/dom/DynamicNodeList.cpp index 892a5e7..3f0744b 100644 --- a/WebCore/dom/DynamicNodeList.cpp +++ b/WebCore/dom/DynamicNodeList.cpp @@ -129,7 +129,9 @@ Node* DynamicNodeList::itemWithName(const AtomicString& elementId) const return node; } } - return 0; + if (!node) + return 0; + // In the case of multiple nodes with the same name, just fall through. } unsigned length = this->length(); diff --git a/WebCore/dom/Element.cpp b/WebCore/dom/Element.cpp index 9edde25..d7f1b11 100644 --- a/WebCore/dom/Element.cpp +++ b/WebCore/dom/Element.cpp @@ -47,6 +47,7 @@ #include "NodeRenderStyle.h" #include "Page.h" #include "RenderView.h" +#include "RenderWidget.h" #include "TextIterator.h" #include "XMLNames.h" @@ -135,6 +136,12 @@ void Element::setAttribute(const QualifiedName& name, const AtomicString& value) ExceptionCode ec; setAttribute(name, value, ec); } + +void Element::setCStringAttribute(const QualifiedName& name, const char* cStringValue) +{ + ExceptionCode ec; + setAttribute(name, AtomicString(cStringValue), ec); +} void Element::setBooleanAttribute(const QualifiedName& name, bool b) { @@ -488,8 +495,10 @@ static inline bool shouldIgnoreAttributeCase(const Element* e) const AtomicString& Element::getAttribute(const String& name) const { - String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name; - if (localName == styleAttr.localName() && !m_isStyleAttributeValid) + bool ignoreCase = shouldIgnoreAttributeCase(this); + + // Update the 'style' attribute if it's invalid and being requested: + if (!m_isStyleAttributeValid && equalPossiblyIgnoringCase(name, styleAttr.localName(), ignoreCase)) updateStyleAttribute(); #if ENABLE(SVG) @@ -498,8 +507,8 @@ const AtomicString& Element::getAttribute(const String& name) const #endif if (namedAttrMap) - if (Attribute* a = namedAttrMap->getAttributeItem(name, shouldIgnoreAttributeCase(this))) - return a->value(); + if (Attribute* attribute = namedAttrMap->getAttributeItem(name, ignoreCase)) + return attribute->value(); return nullAtom; } @@ -727,6 +736,7 @@ void Element::removedFromDocument() void Element::attach() { suspendPostAttachCallbacks(); + RenderWidget::suspendWidgetHierarchyUpdates(); createRendererIfNeeded(); ContainerNode::attach(); @@ -739,20 +749,25 @@ void Element::attach() } } + RenderWidget::resumeWidgetHierarchyUpdates(); resumePostAttachCallbacks(); } void Element::detach() { + RenderWidget::suspendWidgetHierarchyUpdates(); + cancelFocusAppearanceUpdate(); if (hasRareData()) rareData()->resetComputedStyle(); ContainerNode::detach(); + + RenderWidget::resumeWidgetHierarchyUpdates(); } bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle) { - ASSERT(currentStyle = renderStyle()); + ASSERT(currentStyle == renderStyle()); if (!renderer() || !currentStyle) return false; diff --git a/WebCore/dom/Element.h b/WebCore/dom/Element.h index d27976a..97d3eb4 100644 --- a/WebCore/dom/Element.h +++ b/WebCore/dom/Element.h @@ -167,6 +167,9 @@ public: // convenience methods which ignore exceptions void setAttribute(const QualifiedName&, const AtomicString& value); void setBooleanAttribute(const QualifiedName& name, bool); + // Please don't use setCStringAttribute in performance-sensitive code; + // use a static AtomicString value instead to avoid the conversion overhead. + void setCStringAttribute(const QualifiedName&, const char* cStringValue); virtual NamedNodeMap* attributes() const; NamedNodeMap* attributes(bool readonly) const; diff --git a/WebCore/dom/Event.cpp b/WebCore/dom/Event.cpp index 5d8eaaa..eda44b0 100644 --- a/WebCore/dom/Event.cpp +++ b/WebCore/dom/Event.cpp @@ -96,6 +96,11 @@ bool Event::isTextEvent() const return false; } +bool Event::isCompositionEvent() const +{ + return false; +} + bool Event::isDragEvent() const { return false; @@ -131,6 +136,11 @@ bool Event::isPageTransitionEvent() const return false; } +bool Event::isPopStateEvent() const +{ + return false; +} + bool Event::isProgressEvent() const { return false; diff --git a/WebCore/dom/Event.h b/WebCore/dom/Event.h index b391985..7ec85a7 100644 --- a/WebCore/dom/Event.h +++ b/WebCore/dom/Event.h @@ -103,6 +103,7 @@ namespace WebCore { virtual bool isMutationEvent() const; virtual bool isKeyboardEvent() const; virtual bool isTextEvent() const; + virtual bool isCompositionEvent() const; virtual bool isDragEvent() const; // a subset of mouse events virtual bool isClipboardEvent() const; virtual bool isMessageEvent() const; @@ -110,6 +111,7 @@ namespace WebCore { virtual bool isBeforeTextInsertedEvent() const; virtual bool isOverflowEvent() const; virtual bool isPageTransitionEvent() const; + virtual bool isPopStateEvent() const; virtual bool isProgressEvent() const; virtual bool isXMLHttpRequestProgressEvent() const; virtual bool isWebKitAnimationEvent() const; diff --git a/WebCore/dom/EventNames.cpp b/WebCore/dom/EventNames.cpp index 00191ab..900b8ef 100644 --- a/WebCore/dom/EventNames.cpp +++ b/WebCore/dom/EventNames.cpp @@ -1,6 +1,4 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 2005 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or diff --git a/WebCore/dom/EventNames.h b/WebCore/dom/EventNames.h index b2db177..63460a5 100644 --- a/WebCore/dom/EventNames.h +++ b/WebCore/dom/EventNames.h @@ -41,6 +41,9 @@ namespace WebCore { macro(checking) \ macro(click) \ macro(close) \ + macro(compositionend) \ + macro(compositionstart) \ + macro(compositionupdate) \ macro(connect) \ macro(contextmenu) \ macro(copy) \ @@ -81,6 +84,7 @@ namespace WebCore { macro(pagehide) \ macro(pageshow) \ macro(paste) \ + macro(popstate) \ macro(readystatechange) \ macro(reset) \ macro(resize) \ @@ -135,6 +139,9 @@ namespace WebCore { macro(volumechange) \ macro(waiting) \ \ + macro(webkitbeginfullscreen) \ + macro(webkitendfullscreen) \ + \ macro(progress) \ macro(stalled) \ macro(suspend) \ @@ -149,7 +156,7 @@ namespace WebCore { \ // end of DOM_EVENT_NAMES_FOR_EACH - class EventNames { + class EventNames : public Noncopyable { int dummy; // Needed to make initialization macro work. // Private to prevent accidental call to EventNames() instead of eventNames() EventNames(); diff --git a/WebCore/dom/EventTarget.cpp b/WebCore/dom/EventTarget.cpp index 694e78a..65d751a 100644 --- a/WebCore/dom/EventTarget.cpp +++ b/WebCore/dom/EventTarget.cpp @@ -1,6 +1,4 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) @@ -68,6 +66,11 @@ bool eventDispatchForbidden() } #endif // NDEBUG +EventTargetData::~EventTargetData() +{ + deleteAllValues(eventListenerMap); +} + EventTarget::~EventTarget() { } @@ -157,16 +160,19 @@ bool EventTarget::addEventListener(const AtomicString& eventType, PassRefPtr<Eve { EventTargetData* d = ensureEventTargetData(); - pair<EventListenerMap::iterator, bool> result = d->eventListenerMap.add(eventType, EventListenerVector()); - EventListenerVector& entry = result.first->second; + pair<EventListenerMap::iterator, bool> result = d->eventListenerMap.add(eventType, 0); + EventListenerVector*& entry = result.first->second; + const bool isNewEntry = result.second; + if (isNewEntry) + entry = new EventListenerVector(); RegisteredEventListener registeredListener(listener, useCapture); - if (!result.second) { // pre-existing entry - if (entry.find(registeredListener) != notFound) // duplicate listener + if (!isNewEntry) { + if (entry->find(registeredListener) != notFound) // duplicate listener return false; } - entry.append(registeredListener); + entry->append(registeredListener); return true; } @@ -179,16 +185,18 @@ bool EventTarget::removeEventListener(const AtomicString& eventType, EventListen EventListenerMap::iterator result = d->eventListenerMap.find(eventType); if (result == d->eventListenerMap.end()) return false; - EventListenerVector& entry = result->second; + EventListenerVector* entry = result->second; RegisteredEventListener registeredListener(listener, useCapture); - size_t index = entry.find(registeredListener); + size_t index = entry->find(registeredListener); if (index == notFound) return false; - entry.remove(index); - if (!entry.size()) + entry->remove(index); + if (entry->isEmpty()) { + delete entry; d->eventListenerMap.remove(result); + } // Notify firing events planning to invoke the listener at 'index' that // they have one less listener to invoke. @@ -266,7 +274,7 @@ bool EventTarget::fireEventListeners(Event* event) EventListenerMap::iterator result = d->eventListenerMap.find(event->type()); if (result == d->eventListenerMap.end()) return false; - EventListenerVector& entry = result->second; + EventListenerVector& entry = *result->second; RefPtr<EventTarget> protect = this; @@ -303,7 +311,7 @@ const EventListenerVector& EventTarget::getEventListeners(const AtomicString& ev EventListenerMap::iterator it = d->eventListenerMap.find(eventType); if (it == d->eventListenerMap.end()) return emptyVector; - return it->second; + return *it->second; } void EventTarget::removeAllEventListeners() @@ -311,6 +319,7 @@ void EventTarget::removeAllEventListeners() EventTargetData* d = eventTargetData(); if (!d) return; + deleteAllValues(d->eventListenerMap); d->eventListenerMap.clear(); // Notify firing events planning to invoke the listener at 'index' that diff --git a/WebCore/dom/EventTarget.h b/WebCore/dom/EventTarget.h index 9a1975c..2d77c87 100644 --- a/WebCore/dom/EventTarget.h +++ b/WebCore/dom/EventTarget.h @@ -76,9 +76,11 @@ namespace WebCore { typedef Vector<FiringEventIterator, 1> FiringEventIteratorVector; typedef Vector<RegisteredEventListener, 1> EventListenerVector; - typedef HashMap<AtomicString, EventListenerVector> EventListenerMap; + typedef HashMap<AtomicString, EventListenerVector*> EventListenerMap; + + struct EventTargetData : Noncopyable { + ~EventTargetData(); - struct EventTargetData { EventListenerMap eventListenerMap; FiringEventIteratorVector firingEventIterators; }; @@ -190,7 +192,7 @@ namespace WebCore { EventListenerMap::iterator end = d->eventListenerMap.end(); for (EventListenerMap::iterator it = d->eventListenerMap.begin(); it != end; ++it) { - EventListenerVector& entry = it->second; + EventListenerVector& entry = *it->second; for (size_t i = 0; i < entry.size(); ++i) entry[i].listener->markJSFunction(markStack); } @@ -202,6 +204,7 @@ namespace WebCore { if (!d) return; + deleteAllValues(d->eventListenerMap); d->eventListenerMap.clear(); } #endif diff --git a/WebCore/dom/InputElement.h b/WebCore/dom/InputElement.h index e0e7110..2ae0312 100644 --- a/WebCore/dom/InputElement.h +++ b/WebCore/dom/InputElement.h @@ -48,7 +48,8 @@ public: virtual int size() const = 0; virtual String value() const = 0; - virtual void setValue(const String&) = 0; + virtual void setValue(const String&, bool sendChangeEvent = false) = 0; + virtual void setValueForUser(const String&) = 0; virtual String sanitizeValue(const String&) const = 0; virtual void setValueFromRenderer(const String&) = 0; diff --git a/WebCore/dom/KeyboardEvent.cpp b/WebCore/dom/KeyboardEvent.cpp index 6bc825f..99c9220 100644 --- a/WebCore/dom/KeyboardEvent.cpp +++ b/WebCore/dom/KeyboardEvent.cpp @@ -80,7 +80,6 @@ KeyboardEvent::KeyboardEvent(const AtomicString& eventType, bool canBubble, bool KeyboardEvent::~KeyboardEvent() { - delete m_keyEvent; } void KeyboardEvent::initKeyboardEvent(const AtomicString& type, bool canBubble, bool cancelable, AbstractView* view, diff --git a/WebCore/dom/KeyboardEvent.h b/WebCore/dom/KeyboardEvent.h index 2b0a131..793ac41 100644 --- a/WebCore/dom/KeyboardEvent.h +++ b/WebCore/dom/KeyboardEvent.h @@ -79,7 +79,7 @@ namespace WebCore { bool altGraphKey() const { return m_altGraphKey; } - const PlatformKeyboardEvent* keyEvent() const { return m_keyEvent; } + const PlatformKeyboardEvent* keyEvent() const { return m_keyEvent.get(); } int keyCode() const; // key code for keydown and keyup, character for keypress int charCode() const; // character code for keypress, 0 for keydown and keyup @@ -99,7 +99,7 @@ namespace WebCore { const String& keyIdentifier, unsigned keyLocation, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool altGraphKey); - PlatformKeyboardEvent* m_keyEvent; + OwnPtr<PlatformKeyboardEvent> m_keyEvent; String m_keyIdentifier; unsigned m_keyLocation; bool m_altGraphKey : 1; diff --git a/WebCore/dom/MappedAttributeEntry.h b/WebCore/dom/MappedAttributeEntry.h index 745ad23..842e7a8 100644 --- a/WebCore/dom/MappedAttributeEntry.h +++ b/WebCore/dom/MappedAttributeEntry.h @@ -1,6 +1,4 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Peter Kelly (pmk@post.com) diff --git a/WebCore/dom/MessagePort.cpp b/WebCore/dom/MessagePort.cpp index 9f6e649..1051920 100644 --- a/WebCore/dom/MessagePort.cpp +++ b/WebCore/dom/MessagePort.cpp @@ -41,6 +41,7 @@ namespace WebCore { MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext) : m_entangledChannel(0) , m_started(false) + , m_closed(false) , m_scriptExecutionContext(&scriptExecutionContext) { m_scriptExecutionContext->createdMessagePort(this); @@ -131,6 +132,7 @@ void MessagePort::start() void MessagePort::close() { + m_closed = true; if (!m_entangledChannel) return; m_entangledChannel->close(); @@ -200,7 +202,7 @@ PassOwnPtr<MessagePortChannelArray> MessagePort::disentanglePorts(const MessageP // Walk the incoming array - if there are any duplicate ports, or null ports or cloned ports, throw an error (per section 8.3.3 of the HTML5 spec). for (unsigned int i = 0; i < ports->size(); ++i) { MessagePort* port = (*ports)[i].get(); - if (!port || !port->isEntangled() || portSet.contains(port)) { + if (!port || port->isCloned() || portSet.contains(port)) { ec = INVALID_STATE_ERR; return 0; } diff --git a/WebCore/dom/MessagePort.h b/WebCore/dom/MessagePort.h index 0ab0f50..ae1eb22 100644 --- a/WebCore/dom/MessagePort.h +++ b/WebCore/dom/MessagePort.h @@ -103,7 +103,10 @@ namespace WebCore { // 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; } + // A port starts out its life entangled, and remains entangled until it is closed or is cloned. + bool isEntangled() { return !m_closed && !isCloned(); } + // A port is cloned if its entangled channel has been removed and sent to a new owner via postMessage(). + bool isCloned() { return !m_entangledChannel; } private: MessagePort(ScriptExecutionContext&); @@ -116,6 +119,7 @@ namespace WebCore { OwnPtr<MessagePortChannel> m_entangledChannel; bool m_started; + bool m_closed; ScriptExecutionContext* m_scriptExecutionContext; EventTargetData m_eventTargetData; diff --git a/WebCore/dom/MessagePortChannel.h b/WebCore/dom/MessagePortChannel.h index 2321b1f..90cb0d9 100644 --- a/WebCore/dom/MessagePortChannel.h +++ b/WebCore/dom/MessagePortChannel.h @@ -78,7 +78,7 @@ namespace WebCore { // Returns true if the proxy currently contains messages for this port. bool hasPendingActivity(); - class EventData { + class EventData : public Noncopyable { public: static PassOwnPtr<EventData> create(PassRefPtr<SerializedScriptValue>, PassOwnPtr<MessagePortChannelArray>); diff --git a/WebCore/dom/MouseRelatedEvent.h b/WebCore/dom/MouseRelatedEvent.h index 7649aa9..fc494d1 100644 --- a/WebCore/dom/MouseRelatedEvent.h +++ b/WebCore/dom/MouseRelatedEvent.h @@ -1,6 +1,4 @@ /* - * This file is part of the DOM implementation for KDE. - * * 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) diff --git a/WebCore/dom/NamedAttrMap.cpp b/WebCore/dom/NamedAttrMap.cpp index d4ec598..56b40b9 100644 --- a/WebCore/dom/NamedAttrMap.cpp +++ b/WebCore/dom/NamedAttrMap.cpp @@ -177,11 +177,33 @@ PassRefPtr<Node> NamedNodeMap::item(unsigned index) const Attribute* NamedNodeMap::getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const { unsigned len = length(); + bool doSlowCheck = shouldIgnoreAttributeCase; + + // Optimize for the case where the attribute exists and its name exactly matches. for (unsigned i = 0; i < len; ++i) { - if (!m_attributes[i]->name().hasPrefix() && m_attributes[i]->name().localName() == name) - return m_attributes[i].get(); - if (shouldIgnoreAttributeCase ? equalIgnoringCase(m_attributes[i]->name().toString(), name) : name == m_attributes[i]->name().toString()) - return m_attributes[i].get(); + const QualifiedName& attrName = m_attributes[i]->name(); + if (!attrName.hasPrefix()) { + if (name == attrName.localName()) + return m_attributes[i].get(); + } else + doSlowCheck = true; + } + + // Continue to checking case-insensitively and/or full namespaced names if necessary: + if (doSlowCheck) { + for (unsigned i = 0; i < len; ++i) { + const QualifiedName& attrName = m_attributes[i]->name(); + if (!attrName.hasPrefix()) { + if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attrName.localName())) + return m_attributes[i].get(); + } else { + // FIXME: Would be faster to do this comparison without calling toString, which + // generates a temporary string by concatenation. But this branch is only reached + // if the attribute name has a prefix, which is rare in HTML. + if (equalPossiblyIgnoringCase(name, attrName.toString(), shouldIgnoreAttributeCase)) + return m_attributes[i].get(); + } + } } return 0; } diff --git a/WebCore/dom/NamedMappedAttrMap.h b/WebCore/dom/NamedMappedAttrMap.h index 0afa278..a288685 100644 --- a/WebCore/dom/NamedMappedAttrMap.h +++ b/WebCore/dom/NamedMappedAttrMap.h @@ -26,8 +26,8 @@ #ifndef NamedMappedAttrMap_h #define NamedMappedAttrMap_h -#include "ClassNames.h" #include "NamedNodeMap.h" +#include "SpaceSplitString.h" namespace WebCore { @@ -37,7 +37,7 @@ public: void clearClass() { m_classNames.clear(); } void setClass(const String&); - const ClassNames& classNames() const { return m_classNames; } + const SpaceSplitString& classNames() const { return m_classNames; } bool hasMappedAttributes() const { return m_mappedAttributeCount > 0; } void declRemoved() { m_mappedAttributeCount--; } @@ -53,7 +53,7 @@ private: int declCount() const; - ClassNames m_classNames; + SpaceSplitString m_classNames; int m_mappedAttributeCount; }; diff --git a/WebCore/dom/Node.cpp b/WebCore/dom/Node.cpp index 446efda..4ae83de 100644 --- a/WebCore/dom/Node.cpp +++ b/WebCore/dom/Node.cpp @@ -415,7 +415,6 @@ Node::Node(Document* document, ConstructionType type) , m_hovered(false) , m_inActiveChain(false) , m_inDetach(false) - , m_inSubtreeMark(false) , m_hasRareData(false) , m_isElement(isElement(type)) , m_isContainer(isContainer(type)) @@ -1768,23 +1767,22 @@ bool Node::isEqualNode(Node *other) const return true; } -bool Node::isDefaultNamespace(const AtomicString &namespaceURI) const +bool Node::isDefaultNamespace(const AtomicString& namespaceURIMaybeEmpty) const { - // Implemented according to - // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#isDefaultNamespaceAlgo - + const AtomicString& namespaceURI = namespaceURIMaybeEmpty.isEmpty() ? nullAtom : namespaceURIMaybeEmpty; + switch (nodeType()) { case ELEMENT_NODE: { - const Element *elem = static_cast<const Element *>(this); + const Element* elem = static_cast<const Element*>(this); if (elem->prefix().isNull()) return elem->namespaceURI() == namespaceURI; if (elem->hasAttributes()) { - NamedNodeMap *attrs = elem->attributes(); + NamedNodeMap* attrs = elem->attributes(); for (unsigned i = 0; i < attrs->length(); i++) { - Attribute *attr = attrs->attributeItem(i); + Attribute* attr = attrs->attributeItem(i); if (attr->localName() == "xmlns") return attr->value() == namespaceURI; @@ -1806,7 +1804,7 @@ bool Node::isDefaultNamespace(const AtomicString &namespaceURI) const case DOCUMENT_FRAGMENT_NODE: return false; case ATTRIBUTE_NODE: { - const Attr *attr = static_cast<const Attr *>(this); + const Attr* attr = static_cast<const Attr*>(this); if (attr->ownerElement()) return attr->ownerElement()->isDefaultNamespace(namespaceURI); return false; @@ -2539,6 +2537,23 @@ bool Node::dispatchEvent(PassRefPtr<Event> prpEvent) return dispatchGenericEvent(event.release()); } +static bool eventHasListeners(const AtomicString& eventType, DOMWindow* window, Node* node, Vector<RefPtr<ContainerNode> >& ancestors) +{ + if (window && window->hasEventListeners(eventType)) + return true; + + if (node->hasEventListeners(eventType)) + return true; + + for (size_t i = 0; i < ancestors.size(); i++) { + ContainerNode* ancestor = ancestors[i].get(); + if (ancestor->hasEventListeners(eventType)) + return true; + } + + return false; +} + bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) { RefPtr<Event> event(prpEvent); @@ -2547,12 +2562,6 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) ASSERT(event->target()); ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null. -#if ENABLE(INSPECTOR) - InspectorTimelineAgent* timelineAgent = document()->inspectorTimelineAgent(); - if (timelineAgent) - timelineAgent->willDispatchDOMEvent(*event); -#endif - // Make a vector of ancestors to send the event to. // If the node is not in a document just send the event to it. // Be sure to ref all of nodes since event handlers could result in the last reference going away. @@ -2570,6 +2579,13 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) targetForWindowEvents = static_cast<Document*>(topLevelContainer)->domWindow(); } +#if ENABLE(INSPECTOR) + InspectorTimelineAgent* timelineAgent = document()->inspectorTimelineAgent(); + bool timelineAgentIsActive = timelineAgent && eventHasListeners(event->type(), targetForWindowEvents, this, ancestors); + if (timelineAgentIsActive) + timelineAgent->willDispatchEvent(*event); +#endif + // Give the target node a chance to do some work before DOM event handlers get a crack. void* data = preDispatchEventHandler(event.get()); if (event->propagationStopped()) @@ -2651,8 +2667,8 @@ doneDispatching: doneWithDefault: #if ENABLE(INSPECTOR) - if (timelineAgent) - timelineAgent->didDispatchDOMEvent(); + if (timelineAgentIsActive && (timelineAgent = document()->inspectorTimelineAgent())) + timelineAgent->didDispatchEvent(); #endif Document::updateStyleForAllDocuments(); diff --git a/WebCore/dom/Node.h b/WebCore/dom/Node.h index 082ab16..7da8634 100644 --- a/WebCore/dom/Node.h +++ b/WebCore/dom/Node.h @@ -289,9 +289,6 @@ public: void setNeedsStyleRecalc(StyleChangeType changeType = FullStyleChange); void setIsLink(bool b = true) { m_isLink = b; } - bool inSubtreeMark() const { return m_inSubtreeMark; } - void setInSubtreeMark(bool b = true) { m_inSubtreeMark = b; } - void lazyAttach(); virtual bool canLazyAttach(); @@ -642,7 +639,6 @@ private: bool m_hovered : 1; bool m_inActiveChain : 1; bool m_inDetach : 1; - bool m_inSubtreeMark : 1; bool m_hasRareData : 1; const bool m_isElement : 1; const bool m_isContainer : 1; diff --git a/WebCore/dom/NodeFilter.h b/WebCore/dom/NodeFilter.h index 5a542ad..53b32e1 100644 --- a/WebCore/dom/NodeFilter.h +++ b/WebCore/dom/NodeFilter.h @@ -73,8 +73,9 @@ namespace WebCore { short acceptNode(ScriptState*, Node*) const; 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); } + // Do not call these functions. They are just scaffolding to support the Objective-C bindings. + // They operate in the main thread normal world, and they swallow JS exceptions. + short acceptNode(Node* node) const { return acceptNode(scriptStateFromNode(mainThreadNormalWorld(), node), node); } private: NodeFilter(PassRefPtr<NodeFilterCondition> condition) : m_condition(condition) { } diff --git a/WebCore/dom/NodeIterator.h b/WebCore/dom/NodeIterator.h index 2a992d3..3eec49a 100644 --- a/WebCore/dom/NodeIterator.h +++ b/WebCore/dom/NodeIterator.h @@ -52,9 +52,10 @@ namespace WebCore { // This function is called before any node is removed from the document tree. void nodeWillBeRemoved(Node*); - // For non-JS bindings. Silently ignores the JavaScript exception if any. - PassRefPtr<Node> nextNode(ExceptionCode& ec) { return nextNode(scriptStateFromNode(referenceNode()), ec); } - PassRefPtr<Node> previousNode(ExceptionCode& ec) { return previousNode(scriptStateFromNode(referenceNode()), ec); } + // Do not call these functions. They are just scaffolding to support the Objective-C bindings. + // They operate in the main thread normal world, and they swallow JS exceptions. + PassRefPtr<Node> nextNode(ExceptionCode& ec) { return nextNode(scriptStateFromNode(mainThreadNormalWorld(), referenceNode()), ec); } + PassRefPtr<Node> previousNode(ExceptionCode& ec) { return previousNode(scriptStateFromNode(mainThreadNormalWorld(), referenceNode()), ec); } private: NodeIterator(PassRefPtr<Node>, unsigned whatToShow, PassRefPtr<NodeFilter>, bool expandEntityReferences); diff --git a/WebCore/dom/NodeRareData.h b/WebCore/dom/NodeRareData.h index 8b9e1bf..6e9d0e4 100644 --- a/WebCore/dom/NodeRareData.h +++ b/WebCore/dom/NodeRareData.h @@ -33,7 +33,7 @@ namespace WebCore { -struct NodeListsNodeData { +struct NodeListsNodeData : Noncopyable { typedef HashSet<DynamicNodeList*> NodeListSet; NodeListSet m_listsWithCaches; @@ -62,7 +62,7 @@ private: } }; -class NodeRareData { +class NodeRareData : public Noncopyable { public: NodeRareData() : m_tabIndex(0) diff --git a/WebCore/dom/PopStateEvent.cpp b/WebCore/dom/PopStateEvent.cpp new file mode 100644 index 0000000..b9ad862 --- /dev/null +++ b/WebCore/dom/PopStateEvent.cpp @@ -0,0 +1,50 @@ +/* + * 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, 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 "PopStateEvent.h" + +#include "EventNames.h" + +namespace WebCore { + +PopStateEvent::PopStateEvent(PassRefPtr<SerializedScriptValue> stateObject) + : Event(eventNames().popstateEvent, false, true) + , m_stateObject(stateObject) +{ +} + +void PopStateEvent::initPopStateEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> stateObject) +{ + if (dispatched()) + return; + + initEvent(type, canBubble, cancelable); + + m_stateObject = stateObject; +} + +} // namespace WebCore diff --git a/WebCore/dom/PopStateEvent.h b/WebCore/dom/PopStateEvent.h new file mode 100644 index 0000000..2fb8d06 --- /dev/null +++ b/WebCore/dom/PopStateEvent.h @@ -0,0 +1,57 @@ +/* + * 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, 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 PopStateEvent_h +#define PopStateEvent_h + +#include "Event.h" +#include "SerializedScriptValue.h" + +namespace WebCore { + +class SerializedScriptValue; + +class PopStateEvent : public Event { +public: + static PassRefPtr<PopStateEvent> create(PassRefPtr<SerializedScriptValue> stateObject) + { + return adoptRef(new PopStateEvent(stateObject)); + } + + void initPopStateEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue>); + bool isPopStateEvent() const { return true; } + + SerializedScriptValue* state() const { return m_stateObject.get(); } + +private: + PopStateEvent(PassRefPtr<SerializedScriptValue>); + + RefPtr<SerializedScriptValue> m_stateObject; +}; + +} // namespace WebCore + +#endif // PopStateEvent_h diff --git a/WebCore/dom/PopStateEvent.idl b/WebCore/dom/PopStateEvent.idl new file mode 100644 index 0000000..c6775ec --- /dev/null +++ b/WebCore/dom/PopStateEvent.idl @@ -0,0 +1,40 @@ +/* + * 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, 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 events { + + interface [ + GenerateConstructor + ] PopStateEvent : Event { + [Custom] void initPopStateEvent(in DOMString typeArg, + in boolean canBubbleArg, + in boolean cancelableArg, + in any stateArg); + + readonly attribute [CustomGetter] any state; + }; + +} diff --git a/WebCore/dom/Position.cpp b/WebCore/dom/Position.cpp index 060b28c..0ff8262 100644 --- a/WebCore/dom/Position.cpp +++ b/WebCore/dom/Position.cpp @@ -307,6 +307,27 @@ bool Position::atLastEditingPositionForNode() const return m_offset >= lastOffsetForEditing(node()); } +// A position is considered at editing boundary if one of the following is true: +// 1. It is the first position in the node and the next visually equivalent position +// is non editable. +// 2. It is the last position in the node and the previous visually equivalent position +// is non editable. +// 3. It is an editable position and both the next and previous visually equivalent +// positions are both non editable. +bool Position::atEditingBoundary() const +{ + Position nextPosition = downstream(CanCrossEditingBoundary); + if (atFirstEditingPositionForNode() && nextPosition.isNotNull() && !nextPosition.node()->isContentEditable()) + return true; + + Position prevPosition = upstream(CanCrossEditingBoundary); + if (atLastEditingPositionForNode() && prevPosition.isNotNull() && !prevPosition.node()->isContentEditable()) + return true; + + return nextPosition.isNotNull() && !nextPosition.node()->isContentEditable() + && prevPosition.isNotNull() && !prevPosition.node()->isContentEditable(); +} + bool Position::atStartOfTree() const { if (isNull()) @@ -448,7 +469,7 @@ static bool isStreamer(const PositionIterator& pos) // and downstream() will return the right one. // Also, upstream() will return [boundary, 0] for any of the positions from [boundary, 0] to the first candidate // in boundary, where endsOfNodeAreVisuallyDistinctPositions(boundary) is true. -Position Position::upstream() const +Position Position::upstream(EditingBoundaryCrossingRule rule) const { Node* startNode = node(); if (!startNode) @@ -460,6 +481,7 @@ Position Position::upstream() const PositionIterator currentPos = lastVisible; bool startEditable = startNode->isContentEditable(); Node* lastNode = startNode; + bool boundaryCrossed = false; for (; !currentPos.atStart(); currentPos.decrement()) { Node* currentNode = currentPos.node(); @@ -468,8 +490,11 @@ Position Position::upstream() const if (currentNode != lastNode) { // Don't change editability. bool currentEditable = currentNode->isContentEditable(); - if (startEditable != currentEditable) - break; + if (startEditable != currentEditable) { + if (rule == CannotCrossEditingBoundary) + break; + boundaryCrossed = true; + } lastNode = currentNode; } @@ -483,6 +508,11 @@ Position Position::upstream() const if (!renderer || renderer->style()->visibility() != VISIBLE) continue; + if (rule == CanCrossEditingBoundary && boundaryCrossed) { + lastVisible = currentPos; + break; + } + // track last visible streamer position if (isStreamer(currentPos)) lastVisible = currentPos; @@ -560,7 +590,7 @@ Position Position::upstream() const // and upstream() will return the left one. // Also, downstream() will return the last position in the last atomic node in boundary for all of the positions // in boundary after the last candidate, where endsOfNodeAreVisuallyDistinctPositions(boundary). -Position Position::downstream() const +Position Position::downstream(EditingBoundaryCrossingRule rule) const { Node* startNode = node(); if (!startNode) @@ -572,6 +602,7 @@ Position Position::downstream() const PositionIterator currentPos = lastVisible; bool startEditable = startNode->isContentEditable(); Node* lastNode = startNode; + bool boundaryCrossed = false; for (; !currentPos.atEnd(); currentPos.increment()) { Node* currentNode = currentPos.node(); @@ -580,8 +611,12 @@ Position Position::downstream() const if (currentNode != lastNode) { // Don't change editability. bool currentEditable = currentNode->isContentEditable(); - if (startEditable != currentEditable) - break; + if (startEditable != currentEditable) { + if (rule == CannotCrossEditingBoundary) + break; + boundaryCrossed = true; + } + lastNode = currentNode; } @@ -604,6 +639,11 @@ Position Position::downstream() const if (!renderer || renderer->style()->visibility() != VISIBLE) continue; + if (rule == CanCrossEditingBoundary && boundaryCrossed) { + lastVisible = currentPos; + break; + } + // track last visible streamer position if (isStreamer(currentPos)) lastVisible = currentPos; @@ -704,10 +744,14 @@ bool Position::isCandidate() const if (isTableElement(node()) || editingIgnoresContent(node())) return (atFirstEditingPositionForNode() || atLastEditingPositionForNode()) && !nodeIsUserSelectNone(node()->parent()); - if (!node()->hasTagName(htmlTag) && renderer->isBlockFlow() && !hasRenderedNonAnonymousDescendantsWithHeight(renderer) && - (toRenderBox(renderer)->height() || node()->hasTagName(bodyTag))) - return atFirstEditingPositionForNode() && !nodeIsUserSelectNone(node()); - + if (!m_anchorNode->hasTagName(htmlTag) && renderer->isBlockFlow()) { + if (toRenderBlock(renderer)->height() || m_anchorNode->hasTagName(bodyTag)) { + if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer)) + return atFirstEditingPositionForNode() && !Position::nodeIsUserSelectNone(node()); + return m_anchorNode->isContentEditable() && !Position::nodeIsUserSelectNone(node()) && atEditingBoundary(); + } + } + return false; } @@ -949,7 +993,22 @@ void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDi { caretOffset = m_offset; RenderObject* renderer = node()->renderer(); + if (!renderer->isText()) { + if (renderer->isBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) { + bool lastPosition = caretOffset == lastOffsetInNode(node()); + Node* startNode = lastPosition ? node()->childNode(caretOffset - 1) : node()->childNode(caretOffset); + while (startNode && (!startNode->renderer() || (startNode->isTextNode() && toRenderText(startNode->renderer())->isAllCollapsibleWhitespace()))) + startNode = (lastPosition)? startNode->previousSibling(): startNode->nextSibling(); + if (startNode) { + Position pos(startNode, 0); + pos = pos.downstream(CanCrossEditingBoundary); + pos.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineBox, caretOffset); + if (lastPosition && inlineBox) + caretOffset = inlineBox->caretMaxOffset(); + return; + } + } inlineBox = renderer->isBox() ? toRenderBox(renderer)->inlineBoxWrapper() : 0; if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset())) return; diff --git a/WebCore/dom/Position.h b/WebCore/dom/Position.h index c08872d..1e0304e 100644 --- a/WebCore/dom/Position.h +++ b/WebCore/dom/Position.h @@ -56,6 +56,11 @@ public: PositionIsBeforeAnchor }; + enum EditingBoundaryCrossingRule { + CanCrossEditingBoundary, + CannotCrossEditingBoundary + }; + Position() : m_offset(0) , m_anchorType(PositionIsOffsetInAnchor) @@ -130,6 +135,9 @@ public: bool atFirstEditingPositionForNode() const; bool atLastEditingPositionForNode() const; + // Retuns true if the visually equivalent positions around have different editability + bool atEditingBoundary() const; + bool atStartOfTree() const; bool atEndOfTree() const; @@ -139,8 +147,8 @@ public: Position trailingWhitespacePosition(EAffinity, bool considerNonCollapsibleWhitespace = false) const; // These return useful visually equivalent positions. - Position upstream() const; - Position downstream() const; + Position upstream(EditingBoundaryCrossingRule = CannotCrossEditingBoundary) const; + Position downstream(EditingBoundaryCrossingRule = CannotCrossEditingBoundary) const; bool isCandidate() const; bool inRenderedText() const; diff --git a/WebCore/dom/PositionIterator.cpp b/WebCore/dom/PositionIterator.cpp index 8d881ba..f5b65f5 100644 --- a/WebCore/dom/PositionIterator.cpp +++ b/WebCore/dom/PositionIterator.cpp @@ -156,10 +156,14 @@ bool PositionIterator::isCandidate() const if (isTableElement(m_anchorNode) || editingIgnoresContent(m_anchorNode)) return (atStartOfNode() || atEndOfNode()) && !Position::nodeIsUserSelectNone(m_anchorNode->parent()); - if (!m_anchorNode->hasTagName(htmlTag) && renderer->isBlockFlow() && !Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer) && - (toRenderBlock(renderer)->height() || m_anchorNode->hasTagName(bodyTag))) - return atStartOfNode() && !Position::nodeIsUserSelectNone(m_anchorNode); - + if (!m_anchorNode->hasTagName(htmlTag) && renderer->isBlockFlow()) { + if (toRenderBlock(renderer)->height() || m_anchorNode->hasTagName(bodyTag)) { + if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer)) + return atStartOfNode() && !Position::nodeIsUserSelectNone(m_anchorNode); + return m_anchorNode->isContentEditable() && !Position::nodeIsUserSelectNone(m_anchorNode) && Position(*this).atEditingBoundary(); + } + } + return false; } diff --git a/WebCore/dom/ProcessingInstruction.cpp b/WebCore/dom/ProcessingInstruction.cpp index 8a94864..8adf9aa 100644 --- a/WebCore/dom/ProcessingInstruction.cpp +++ b/WebCore/dom/ProcessingInstruction.cpp @@ -42,6 +42,7 @@ inline ProcessingInstruction::ProcessingInstruction(Document* document, const St , m_cachedSheet(0) , m_loading(false) , m_alternate(false) + , m_createdByParser(false) #if ENABLE(XSLT) , m_isXSL(false) #endif diff --git a/WebCore/dom/QualifiedName.cpp b/WebCore/dom/QualifiedName.cpp index 2c5f39a..795bdb6 100644 --- a/WebCore/dom/QualifiedName.cpp +++ b/WebCore/dom/QualifiedName.cpp @@ -51,7 +51,7 @@ struct QNameComponentsTranslator { static QNameSet* gNameCache; -QualifiedName::QualifiedName(const AtomicString& p, const AtomicString& l, const AtomicString& n) +void QualifiedName::init(const AtomicString& p, const AtomicString& l, const AtomicString& n) { if (!gNameCache) gNameCache = new QNameSet; @@ -62,6 +62,16 @@ QualifiedName::QualifiedName(const AtomicString& p, const AtomicString& l, const m_impl->ref(); } +QualifiedName::QualifiedName(const AtomicString& p, const AtomicString& l, const AtomicString& n) +{ + init(p, l, n); +} + +QualifiedName::QualifiedName(const AtomicString& p, const char* l, const AtomicString& n) +{ + init(p, AtomicString(l), n); +} + void QualifiedName::deref() { #ifdef QNAME_DEFAULT_CONSTRUCTOR diff --git a/WebCore/dom/QualifiedName.h b/WebCore/dom/QualifiedName.h index 3b9f5c4..a7e1fcb 100644 --- a/WebCore/dom/QualifiedName.h +++ b/WebCore/dom/QualifiedName.h @@ -32,7 +32,7 @@ struct QualifiedNameComponents { StringImpl* m_namespace; }; -class QualifiedName { +class QualifiedName : public FastAllocBase { public: class QualifiedNameImpl : public RefCounted<QualifiedNameImpl> { public: @@ -57,6 +57,7 @@ public: }; QualifiedName(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI); + QualifiedName(const AtomicString& prefix, const char* localName, const AtomicString& namespaceURI); ~QualifiedName() { deref(); } #ifdef QNAME_DEFAULT_CONSTRUCTOR QualifiedName() : m_impl(0) { } @@ -88,6 +89,7 @@ public: static void init(); private: + void init(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI); void ref() const { m_impl->ref(); } void deref(); diff --git a/WebCore/dom/Range.cpp b/WebCore/dom/Range.cpp index 122130d..84a46c2 100644 --- a/WebCore/dom/Range.cpp +++ b/WebCore/dom/Range.cpp @@ -1595,12 +1595,32 @@ IntRect Range::boundingBox() void Range::textRects(Vector<IntRect>& rects, bool useSelectionHeight) { - if (!m_start.container() || !m_end.container()) + Node* startContainer = m_start.container(); + Node* endContainer = m_end.container(); + + if (!startContainer || !endContainer) return; + Node* stopNode = pastLastNode(); + for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) { + RenderObject* r = node->renderer(); + if (!r || !r->isText()) + continue; + RenderText* renderText = toRenderText(r); + int startOffset = node == startContainer ? m_start.offset() : 0; + int endOffset = node == endContainer ? m_end.offset() : numeric_limits<int>::max(); + renderText->absoluteRectsForRange(rects, startOffset, endOffset, useSelectionHeight); + } +} + +void Range::textQuads(Vector<FloatQuad>& quads, bool useSelectionHeight) +{ Node* startContainer = m_start.container(); Node* endContainer = m_end.container(); + if (!startContainer || !endContainer) + return; + Node* stopNode = pastLastNode(); for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) { RenderObject* r = node->renderer(); @@ -1608,8 +1628,8 @@ void Range::textRects(Vector<IntRect>& rects, bool useSelectionHeight) continue; RenderText* renderText = toRenderText(r); int startOffset = node == startContainer ? m_start.offset() : 0; - int endOffset = node == endContainer ? m_end.offset() : INT_MAX; - renderText->absoluteRectsForRange(rects, startOffset, endOffset, useSelectionHeight); + int endOffset = node == endContainer ? m_end.offset() : numeric_limits<int>::max(); + renderText->absoluteQuadsForRange(quads, startOffset, endOffset, useSelectionHeight); } } diff --git a/WebCore/dom/Range.h b/WebCore/dom/Range.h index e2e282b..583f9f0 100644 --- a/WebCore/dom/Range.h +++ b/WebCore/dom/Range.h @@ -105,7 +105,10 @@ public: Node* shadowTreeRootNode() const; IntRect boundingBox(); + // Not transform-friendly void textRects(Vector<IntRect>&, bool useSelectionHeight = false); + // Transform-friendly + void textQuads(Vector<FloatQuad>&, bool useSelectionHeight = false); void nodeChildrenChanged(ContainerNode*); void nodeWillBeRemoved(Node*); diff --git a/WebCore/dom/RangeException.h b/WebCore/dom/RangeException.h index 2eee3b0..c9f4f5c 100644 --- a/WebCore/dom/RangeException.h +++ b/WebCore/dom/RangeException.h @@ -1,6 +1,4 @@ /* - * This file is part of the DOM implementation for KDE. - * * (C) 1999 Lars Knoll (knoll@kde.org) * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) diff --git a/WebCore/dom/ScriptElement.cpp b/WebCore/dom/ScriptElement.cpp index 827aff3..83ed2bb 100644 --- a/WebCore/dom/ScriptElement.cpp +++ b/WebCore/dom/ScriptElement.cpp @@ -229,12 +229,14 @@ bool ScriptElementData::shouldExecuteAsJavaScript() const We want to accept all the values that either of these browsers accept, but not other values. */ String type = m_scriptElement->typeAttributeValue(); - if (!type.isEmpty()) - return MIMETypeRegistry::isSupportedJavaScriptMIMEType(type.stripWhiteSpace().lower()); - - String language = m_scriptElement->languageAttributeValue(); - if (!language.isEmpty()) - return isSupportedJavaScriptLanguage(language); + if (!type.isEmpty()) { + if (!MIMETypeRegistry::isSupportedJavaScriptMIMEType(type.stripWhiteSpace().lower())) + return false; + } else { + String language = m_scriptElement->languageAttributeValue(); + if (!language.isEmpty() && !isSupportedJavaScriptLanguage(language)) + return false; + } // No type or language is specified, so we assume the script to be JavaScript. // We don't yet support setting event listeners via the 'for' attribute for scripts. diff --git a/WebCore/dom/ScriptExecutionContext.cpp b/WebCore/dom/ScriptExecutionContext.cpp index f7046e3..bc71084 100644 --- a/WebCore/dom/ScriptExecutionContext.cpp +++ b/WebCore/dom/ScriptExecutionContext.cpp @@ -44,9 +44,9 @@ namespace WebCore { class ProcessMessagesSoonTask : public ScriptExecutionContext::Task { public: - static PassRefPtr<ProcessMessagesSoonTask> create() + static PassOwnPtr<ProcessMessagesSoonTask> create() { - return adoptRef(new ProcessMessagesSoonTask); + return new ProcessMessagesSoonTask; } virtual void performTask(ScriptExecutionContext* context) diff --git a/WebCore/dom/ScriptExecutionContext.h b/WebCore/dom/ScriptExecutionContext.h index 398afec..cf332c3 100644 --- a/WebCore/dom/ScriptExecutionContext.h +++ b/WebCore/dom/ScriptExecutionContext.h @@ -31,6 +31,7 @@ #include "KURL.h" #include <wtf/HashMap.h> #include <wtf/HashSet.h> +#include <wtf/PassOwnPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/Threading.h> @@ -92,13 +93,13 @@ namespace WebCore { void ref() { refScriptExecutionContext(); } void deref() { derefScriptExecutionContext(); } - class Task : public ThreadSafeShared<Task> { + class Task : public Noncopyable { public: virtual ~Task(); virtual void performTask(ScriptExecutionContext*) = 0; }; - virtual void postTask(PassRefPtr<Task>) = 0; // Executes the task on context's thread asynchronously. + virtual void postTask(PassOwnPtr<Task>) = 0; // Executes the task on context's thread asynchronously. void addTimeout(int timeoutId, DOMTimer*); void removeTimeout(int timeoutId); diff --git a/WebCore/dom/ClassNames.cpp b/WebCore/dom/SpaceSplitString.cpp index 1c5ff47..b062dbf 100644 --- a/WebCore/dom/ClassNames.cpp +++ b/WebCore/dom/SpaceSplitString.cpp @@ -19,7 +19,7 @@ */ #include "config.h" -#include "ClassNames.h" +#include "SpaceSplitString.h" #include <wtf/ASCIICType.h> @@ -41,7 +41,7 @@ static bool hasNonASCIIOrUpper(const String& string) return hasUpper || (ored & ~0x7F); } -void ClassNamesData::createVector() +void SpaceSplitStringData::createVector() { ASSERT(!m_createdVector); ASSERT(m_vector.isEmpty()); @@ -70,7 +70,7 @@ void ClassNamesData::createVector() m_createdVector = true; } -bool ClassNamesData::containsAll(ClassNamesData& other) +bool SpaceSplitStringData::containsAll(SpaceSplitStringData& other) { ensureVector(); other.ensureVector(); diff --git a/WebCore/dom/ClassNames.h b/WebCore/dom/SpaceSplitString.h index a836606..2ef3fc4 100644 --- a/WebCore/dom/ClassNames.h +++ b/WebCore/dom/SpaceSplitString.h @@ -18,8 +18,8 @@ * */ -#ifndef ClassNames_h -#define ClassNames_h +#ifndef SpaceSplitString_h +#define SpaceSplitString_h #include "AtomicString.h" #include <wtf/OwnPtr.h> @@ -27,9 +27,9 @@ namespace WebCore { - class ClassNamesData : public Noncopyable { + class SpaceSplitStringData : public Noncopyable { public: - ClassNamesData(const String& string, bool shouldFoldCase) + SpaceSplitStringData(const String& string, bool shouldFoldCase) : m_string(string), m_shouldFoldCase(shouldFoldCase), m_createdVector(false) { } @@ -45,7 +45,7 @@ namespace WebCore { return false; } - bool containsAll(ClassNamesData&); + bool containsAll(SpaceSplitStringData&); size_t size() { ensureVector(); return m_vector.size(); } const AtomicString& operator[](size_t i) { ensureVector(); ASSERT(i < size()); return m_vector[i]; } @@ -54,29 +54,29 @@ namespace WebCore { void ensureVector() { if (!m_createdVector) createVector(); } void createVector(); - typedef Vector<AtomicString, 8> ClassNameVector; + typedef Vector<AtomicString, 8> StringVector; String m_string; - ClassNameVector m_vector; + StringVector m_vector; bool m_shouldFoldCase; bool m_createdVector; }; - class ClassNames { + class SpaceSplitString { public: - ClassNames() { } - ClassNames(const String& string, bool shouldFoldCase) : m_data(new ClassNamesData(string, shouldFoldCase)) { } + SpaceSplitString() { } + SpaceSplitString(const String& string, bool shouldFoldCase) : m_data(new SpaceSplitStringData(string, shouldFoldCase)) { } - void set(const String& string, bool shouldFoldCase) { m_data.set(new ClassNamesData(string, shouldFoldCase)); } + void set(const String& string, bool shouldFoldCase) { m_data.set(new SpaceSplitStringData(string, shouldFoldCase)); } void clear() { m_data.clear(); } bool contains(const AtomicString& string) const { return m_data && m_data->contains(string); } - bool containsAll(const ClassNames& names) const { return !names.m_data || (m_data && m_data->containsAll(*names.m_data)); } + bool containsAll(const SpaceSplitString& names) const { return !names.m_data || (m_data && m_data->containsAll(*names.m_data)); } size_t size() const { return m_data ? m_data->size() : 0; } const AtomicString& operator[](size_t i) const { ASSERT(i < size()); return (*m_data)[i]; } private: - OwnPtr<ClassNamesData> m_data; + OwnPtr<SpaceSplitStringData> m_data; }; inline bool isClassWhitespace(UChar c) @@ -86,4 +86,4 @@ namespace WebCore { } // namespace WebCore -#endif // ClassNames_h +#endif // SpaceSplitString_h diff --git a/WebCore/dom/StyleElement.h b/WebCore/dom/StyleElement.h index 7f83909..9d3ac84 100644 --- a/WebCore/dom/StyleElement.h +++ b/WebCore/dom/StyleElement.h @@ -1,6 +1,4 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 2006, 2007 Rob Buis * * This library is free software; you can redistribute it and/or diff --git a/WebCore/dom/StyledElement.h b/WebCore/dom/StyledElement.h index 85fa7a7..52bffd3 100644 --- a/WebCore/dom/StyledElement.h +++ b/WebCore/dom/StyledElement.h @@ -66,7 +66,7 @@ public: CSSStyleDeclaration* style(); void invalidateStyleAttribute(); - const ClassNames& classNames() const { ASSERT(hasClass()); ASSERT(mappedAttributes()); return mappedAttributes()->classNames(); } + const SpaceSplitString& classNames() const { ASSERT(hasClass()); ASSERT(mappedAttributes()); return mappedAttributes()->classNames(); } virtual bool mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const; diff --git a/WebCore/dom/Tokenizer.h b/WebCore/dom/Tokenizer.h index ea303f9..9a9b7b3 100644 --- a/WebCore/dom/Tokenizer.h +++ b/WebCore/dom/Tokenizer.h @@ -1,6 +1,4 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 2000 Peter Kelly (pmk@post.com) * Copyright (C) 2005, 2006 Apple Computer, Inc. * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) @@ -30,7 +28,7 @@ namespace WebCore { class SegmentedString; class XSSAuditor; - class Tokenizer { + class Tokenizer : public Noncopyable { public: virtual ~Tokenizer() { } diff --git a/WebCore/dom/TreeWalker.h b/WebCore/dom/TreeWalker.h index 4cc8e9a..88e59da 100644 --- a/WebCore/dom/TreeWalker.h +++ b/WebCore/dom/TreeWalker.h @@ -52,14 +52,15 @@ namespace WebCore { Node* previousNode(ScriptState*); Node* nextNode(ScriptState*); - // For non-JS bindings. Silently ignores the JavaScript exception if any. - Node* parentNode() { return parentNode(scriptStateFromNode(m_current.get())); } - Node* firstChild() { return firstChild(scriptStateFromNode(m_current.get())); } - Node* lastChild() { return lastChild(scriptStateFromNode(m_current.get())); } - Node* previousSibling() { return previousSibling(scriptStateFromNode(m_current.get())); } - Node* nextSibling() { return nextSibling(scriptStateFromNode(m_current.get())); } - Node* previousNode() { return previousNode(scriptStateFromNode(m_current.get())); } - Node* nextNode() { return nextNode(scriptStateFromNode(m_current.get())); } + // Do not call these functions. They are just scaffolding to support the Objective-C bindings. + // They operate in the main thread normal world, and they swallow JS exceptions. + Node* parentNode() { return parentNode(scriptStateFromNode(mainThreadNormalWorld(), m_current.get())); } + Node* firstChild() { return firstChild(scriptStateFromNode(mainThreadNormalWorld(), m_current.get())); } + Node* lastChild() { return lastChild(scriptStateFromNode(mainThreadNormalWorld(), m_current.get())); } + Node* previousSibling() { return previousSibling(scriptStateFromNode(mainThreadNormalWorld(), m_current.get())); } + Node* nextSibling() { return nextSibling(scriptStateFromNode(mainThreadNormalWorld(), m_current.get())); } + Node* previousNode() { return previousNode(scriptStateFromNode(mainThreadNormalWorld(), m_current.get())); } + Node* nextNode() { return nextNode(scriptStateFromNode(mainThreadNormalWorld(), m_current.get())); } private: TreeWalker(PassRefPtr<Node>, unsigned whatToShow, PassRefPtr<NodeFilter>, bool expandEntityReferences); diff --git a/WebCore/dom/XMLTokenizer.cpp b/WebCore/dom/XMLTokenizer.cpp index 30d39e0..56f8ff4 100644 --- a/WebCore/dom/XMLTokenizer.cpp +++ b/WebCore/dom/XMLTokenizer.cpp @@ -91,7 +91,8 @@ void XMLTokenizer::pushCurrentNode(Node* n) void XMLTokenizer::popCurrentNode() { - ASSERT(m_currentNode); + if (!m_currentNode) + return; ASSERT(m_currentNodeStack.size()); if (m_currentNode != m_doc) diff --git a/WebCore/dom/XMLTokenizer.h b/WebCore/dom/XMLTokenizer.h index 095e8db..2f9c113 100644 --- a/WebCore/dom/XMLTokenizer.h +++ b/WebCore/dom/XMLTokenizer.h @@ -161,6 +161,23 @@ namespace WebCore { class PendingCallbacks; class ScriptElement; +#if !USE(QXMLSTREAM) + class XMLParserContext : public RefCounted<XMLParserContext> { + public: + static PassRefPtr<XMLParserContext> createMemoryParser(xmlSAXHandlerPtr, void*, const char*); + static PassRefPtr<XMLParserContext> createStringParser(xmlSAXHandlerPtr, void*); + ~XMLParserContext(); + xmlParserCtxtPtr context() const { return m_context; } + + private: + XMLParserContext(xmlParserCtxtPtr context) + : m_context(context) + { + } + xmlParserCtxtPtr m_context; + }; +#endif + class XMLTokenizer : public Tokenizer, public CachedResourceClient { public: XMLTokenizer(Document*, FrameView* = 0); @@ -255,7 +272,8 @@ public: QXmlStreamReader m_stream; bool m_wroteText; #else - xmlParserCtxtPtr m_context; + xmlParserCtxtPtr context() const { return m_context ? m_context->context() : 0; }; + RefPtr<XMLParserContext> m_context; OwnPtr<PendingCallbacks> m_pendingCallbacks; Vector<xmlChar> m_bufferedText; #endif diff --git a/WebCore/dom/XMLTokenizerLibxml2.cpp b/WebCore/dom/XMLTokenizerLibxml2.cpp index 9aa0961..42c8b9b 100644 --- a/WebCore/dom/XMLTokenizerLibxml2.cpp +++ b/WebCore/dom/XMLTokenizerLibxml2.cpp @@ -465,7 +465,7 @@ static void errorFunc(void*, const char*, ...) static bool didInit = false; -static xmlParserCtxtPtr createStringParser(xmlSAXHandlerPtr handlers, void* userData) +PassRefPtr<XMLParserContext> XMLParserContext::createStringParser(xmlSAXHandlerPtr handlers, void* userData) { if (!didInit) { xmlInitParser(); @@ -482,12 +482,12 @@ static xmlParserCtxtPtr createStringParser(xmlSAXHandlerPtr handlers, void* user const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM); xmlSwitchEncoding(parser, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE); - return parser; + return adoptRef(new XMLParserContext(parser)); } // Chunk should be encoded in UTF-8 -static xmlParserCtxtPtr createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const char* chunk) +PassRefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const char* chunk) { if (!didInit) { xmlInitParser(); @@ -518,8 +518,8 @@ static xmlParserCtxtPtr createMemoryParser(xmlSAXHandlerPtr handlers, void* user parser->str_xmlns = xmlDictLookup(parser->dict, BAD_CAST "xmlns", 5); parser->str_xml_ns = xmlDictLookup(parser->dict, XML_XML_NAMESPACE, 36); parser->_private = userData; - - return parser; + + return adoptRef(new XMLParserContext(parser)); } // -------------------------------- @@ -609,6 +609,13 @@ XMLTokenizer::XMLTokenizer(DocumentFragment* fragment, Element* parentElement) m_defaultNamespaceURI = parentElement->namespaceURI(); } +XMLParserContext::~XMLParserContext() +{ + if (m_context->myDoc) + xmlFreeDoc(m_context->myDoc); + xmlFreeParserCtxt(m_context); +} + XMLTokenizer::~XMLTokenizer() { clearCurrentNodeStack(); @@ -616,15 +623,16 @@ XMLTokenizer::~XMLTokenizer() m_doc->deref(); if (m_pendingScript) m_pendingScript->removeClient(this); - if (m_context) - xmlFreeParserCtxt(m_context); } void XMLTokenizer::doWrite(const String& parseString) { if (!m_context) initializeParserContext(); - + + // Protect the libxml context from deletion during a callback + RefPtr<XMLParserContext> context = m_context; + // libXML throws an error if you try to switch the encoding for an empty string. if (parseString.length()) { // Hack around libxml2's lack of encoding overide support by manually @@ -633,15 +641,15 @@ void XMLTokenizer::doWrite(const String& parseString) // and switch encodings, causing the parse to fail. const UChar BOM = 0xFEFF; const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM); - xmlSwitchEncoding(m_context, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE); + xmlSwitchEncoding(context->context(), BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE); XMLTokenizerScope scope(m_doc->docLoader()); - xmlParseChunk(m_context, reinterpret_cast<const char*>(parseString.characters()), sizeof(UChar) * parseString.length(), 0); + xmlParseChunk(context->context(), reinterpret_cast<const char*>(parseString.characters()), sizeof(UChar) * parseString.length(), 0); } if (m_doc->decoder() && m_doc->decoder()->sawError()) { // If the decoder saw an error, report it as fatal (stops parsing) - handleError(fatal, "Encoding error", lineNumber(), columnNumber()); + handleError(fatal, "Encoding error", context->context()->input->line, context->context()->input->col); } return; @@ -1277,9 +1285,9 @@ void XMLTokenizer::initializeParserContext(const char* chunk) XMLTokenizerScope scope(m_doc->docLoader()); if (m_parsingFragment) - m_context = createMemoryParser(&sax, this, chunk); + m_context = XMLParserContext::createMemoryParser(&sax, this, chunk); else - m_context = createStringParser(&sax, this); + m_context = XMLParserContext::createStringParser(&sax, this); } void XMLTokenizer::doEnd() @@ -1300,12 +1308,9 @@ void XMLTokenizer::doEnd() // Tell libxml we're done. { XMLTokenizerScope scope(m_doc->docLoader()); - xmlParseChunk(m_context, 0, 0, 1); + xmlParseChunk(context(), 0, 0, 1); } - if (m_context->myDoc) - xmlFreeDoc(m_context->myDoc); - xmlFreeParserCtxt(m_context); m_context = 0; } } @@ -1334,18 +1339,19 @@ void* xmlDocPtrForString(DocLoader* docLoader, const String& source, const Strin int XMLTokenizer::lineNumber() const { - return m_context ? m_context->input->line : 1; + return context() ? context()->input->line : 1; } int XMLTokenizer::columnNumber() const { - return m_context ? m_context->input->col : 1; + return context() ? context()->input->col : 1; } void XMLTokenizer::stopParsing() { Tokenizer::stopParsing(); - xmlStopParser(m_context); + if (context()) + xmlStopParser(context()); } void XMLTokenizer::resumeParsing() @@ -1384,17 +1390,17 @@ bool parseXMLDocumentFragment(const String& chunk, DocumentFragment* fragment, E CString chunkAsUtf8 = chunk.utf8(); tokenizer.initializeParserContext(chunkAsUtf8.data()); - xmlParseContent(tokenizer.m_context); + xmlParseContent(tokenizer.context()); tokenizer.endDocument(); // Check if all the chunk has been processed. - long bytesProcessed = xmlByteConsumed(tokenizer.m_context); + long bytesProcessed = xmlByteConsumed(tokenizer.context()); if (bytesProcessed == -1 || ((unsigned long)bytesProcessed) != chunkAsUtf8.length()) return false; // No error if the chunk is well formed or it is not but we have no error. - return tokenizer.m_context->wellFormed || xmlCtxtGetLastError(tokenizer.m_context) == 0; + return tokenizer.context()->wellFormed || xmlCtxtGetLastError(tokenizer.context()) == 0; } // -------------------------------- @@ -1437,12 +1443,9 @@ HashMap<String, String> parseAttributes(const String& string, bool& attrsOK) memset(&sax, 0, sizeof(sax)); sax.startElementNs = attributesStartElementNsHandler; sax.initialized = XML_SAX2_MAGIC; - xmlParserCtxtPtr parser = createStringParser(&sax, &state); + RefPtr<XMLParserContext> parser = XMLParserContext::createStringParser(&sax, &state); String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />"; - xmlParseChunk(parser, reinterpret_cast<const char*>(parseString.characters()), parseString.length() * sizeof(UChar), 1); - if (parser->myDoc) - xmlFreeDoc(parser->myDoc); - xmlFreeParserCtxt(parser); + xmlParseChunk(parser->context(), reinterpret_cast<const char*>(parseString.characters()), parseString.length() * sizeof(UChar), 1); attrsOK = state.gotAttributes; return state.attributes; } diff --git a/WebCore/dom/XMLTokenizerQt.cpp b/WebCore/dom/XMLTokenizerQt.cpp index c6e73ba..4e61715 100644 --- a/WebCore/dom/XMLTokenizerQt.cpp +++ b/WebCore/dom/XMLTokenizerQt.cpp @@ -66,7 +66,6 @@ using namespace std; namespace WebCore { -#if QT_VERSION >= 0x040400 class EntityResolver : public QXmlStreamEntityResolver { virtual QString resolveUndeclaredEntity(const QString &name); }; @@ -76,7 +75,6 @@ QString EntityResolver::resolveUndeclaredEntity(const QString &name) UChar c = decodeNamedEntity(name.toUtf8().constData()); return QString(c); } -#endif // -------------------------------- @@ -103,9 +101,7 @@ XMLTokenizer::XMLTokenizer(Document* _doc, FrameView* _view) , m_scriptStartLine(0) , m_parsingFragment(false) { -#if QT_VERSION >= 0x040400 m_stream.setEntityResolver(new EntityResolver); -#endif } XMLTokenizer::XMLTokenizer(DocumentFragment* fragment, Element* parentElement) @@ -149,19 +145,6 @@ XMLTokenizer::XMLTokenizer(DocumentFragment* fragment, Element* parentElement) if (elemStack.isEmpty()) return; -#if QT_VERSION < 0x040400 - for (Element* element = elemStack.last(); !elemStack.isEmpty(); elemStack.removeLast()) { - if (NamedNodeMap* attrs = element->attributes()) { - for (unsigned i = 0; i < attrs->length(); i++) { - Attribute* attr = attrs->attributeItem(i); - if (attr->localName() == "xmlns") - m_defaultNamespaceURI = attr->value(); - else if (attr->prefix() == "xmlns") - m_prefixToNamespaceMap.set(attr->localName(), attr->value()); - } - } - } -#else QXmlStreamNamespaceDeclarations namespaces; for (Element* element = elemStack.last(); !elemStack.isEmpty(); elemStack.removeLast()) { if (NamedNodeMap* attrs = element->attributes()) { @@ -176,7 +159,6 @@ XMLTokenizer::XMLTokenizer(DocumentFragment* fragment, Element* parentElement) } m_stream.addExtraNamespaceDeclarations(namespaces); m_stream.setEntityResolver(new EntityResolver); -#endif // If the parent element is not in document tree, there may be no xmlns attribute; just default to the parent's namespace. if (m_defaultNamespaceURI.isNull() && !parentElement->inDocument()) @@ -190,9 +172,7 @@ XMLTokenizer::~XMLTokenizer() m_doc->deref(); if (m_pendingScript) m_pendingScript->removeClient(this); -#if QT_VERSION >= 0x040400 delete m_stream.entityResolver(); -#endif } void XMLTokenizer::doWrite(const String& parseString) @@ -207,27 +187,6 @@ void XMLTokenizer::doWrite(const String& parseString) QString data(parseString); if (!data.isEmpty()) { -#if QT_VERSION < 0x040400 - if (!m_sawFirstElement) { - int idx = data.indexOf(QLatin1String("<?xml")); - if (idx != -1) { - int start = idx + 5; - int end = data.indexOf(QLatin1String("?>"), start); - QString content = data.mid(start, end-start); - bool ok = true; - HashMap<String, String> attrs = parseAttributes(content, ok); - String version = attrs.get("version"); - String encoding = attrs.get("encoding"); - ExceptionCode ec = 0; - if (!m_parsingFragment) { - if (!version.isEmpty()) - m_doc->setXMLVersion(version, ec); - if (!encoding.isEmpty()) - m_doc->setXMLEncoding(encoding); - } - } - } -#endif m_stream.addData(data); parse(); } @@ -256,7 +215,7 @@ void XMLTokenizer::doEnd() #endif if (m_stream.error() == QXmlStreamReader::PrematureEndOfDocumentError - || (m_wroteText && !m_sawFirstElement && !m_sawXSLTransform)) + || (m_wroteText && !m_sawFirstElement && !m_sawXSLTransform && !m_sawError)) handleError(fatal, qPrintable(m_stream.errorString()), lineNumber(), columnNumber()); } @@ -485,14 +444,12 @@ void XMLTokenizer::startDocument() if (!m_parsingFragment) { m_doc->setXMLStandalone(m_stream.isStandaloneDocument(), ec); -#if QT_VERSION >= 0x040400 QStringRef version = m_stream.documentVersion(); if (!version.isEmpty()) m_doc->setXMLVersion(version, ec); QStringRef encoding = m_stream.documentEncoding(); if (!encoding.isEmpty()) m_doc->setXMLEncoding(encoding); -#endif } } @@ -702,83 +659,11 @@ bool XMLTokenizer::hasError() const return m_stream.hasError(); } -#if QT_VERSION < 0x040400 -static QString parseId(const QString &dtd, int *pos, bool *ok) -{ - *ok = true; - int start = *pos + 1; - int end = start; - if (dtd.at(*pos) == QLatin1Char('\'')) - while (start < dtd.length() && dtd.at(end) != QLatin1Char('\'')) - ++end; - else if (dtd.at(*pos) == QLatin1Char('\"')) - while (start < dtd.length() && dtd.at(end) != QLatin1Char('\"')) - ++end; - else { - *ok = false; - return QString(); - } - *pos = end + 1; - return dtd.mid(start, end - start); -} -#endif - void XMLTokenizer::parseDtd() { -#if QT_VERSION >= 0x040400 QStringRef name = m_stream.dtdName(); QStringRef publicId = m_stream.dtdPublicId(); QStringRef systemId = m_stream.dtdSystemId(); -#else - QString dtd = m_stream.text().toString(); - - int start = dtd.indexOf("<!DOCTYPE ") + 10; - while (start < dtd.length() && dtd.at(start).isSpace()) - ++start; - int end = start; - while (start < dtd.length() && !dtd.at(end).isSpace()) - ++end; - QString name = dtd.mid(start, end - start); - - start = end; - while (start < dtd.length() && dtd.at(start).isSpace()) - ++start; - end = start; - while (start < dtd.length() && !dtd.at(end).isSpace()) - ++end; - QString id = dtd.mid(start, end - start); - start = end; - while (start < dtd.length() && dtd.at(start).isSpace()) - ++start; - QString publicId; - QString systemId; - if (id == QLatin1String("PUBLIC")) { - bool ok; - publicId = parseId(dtd, &start, &ok); - if (!ok) { - handleError(fatal, "Invalid DOCTYPE", lineNumber(), columnNumber()); - return; - } - while (start < dtd.length() && dtd.at(start).isSpace()) - ++start; - systemId = parseId(dtd, &start, &ok); - if (!ok) { - handleError(fatal, "Invalid DOCTYPE", lineNumber(), columnNumber()); - return; - } - } else if (id == QLatin1String("SYSTEM")) { - bool ok; - systemId = parseId(dtd, &start, &ok); - if (!ok) { - handleError(fatal, "Invalid DOCTYPE", lineNumber(), columnNumber()); - return; - } - } else if (id == QLatin1String("[") || id == QLatin1String(">")) { - } else { - handleError(fatal, "Invalid DOCTYPE", lineNumber(), columnNumber()); - return; - } -#endif //qDebug() << dtd << name << publicId << systemId; if ((publicId == QLatin1String("-//W3C//DTD XHTML 1.0 Transitional//EN")) diff --git a/WebCore/dom/default/PlatformMessagePortChannel.cpp b/WebCore/dom/default/PlatformMessagePortChannel.cpp index d668703..9e0e7dc 100644 --- a/WebCore/dom/default/PlatformMessagePortChannel.cpp +++ b/WebCore/dom/default/PlatformMessagePortChannel.cpp @@ -193,7 +193,8 @@ void PlatformMessagePortChannel::postMessageToRemote(PassOwnPtr<MessagePortChann bool PlatformMessagePortChannel::tryGetMessageFromRemote(OwnPtr<MessagePortChannel::EventData>& result) { MutexLocker lock(m_mutex); - return m_incomingQueue->tryGetMessage(result); + result = m_incomingQueue->tryGetMessage(); + return result; } bool PlatformMessagePortChannel::isConnectedTo(MessagePort* port) diff --git a/WebCore/dom/default/PlatformMessagePortChannel.h b/WebCore/dom/default/PlatformMessagePortChannel.h index 0ce2d13..2aad952 100644 --- a/WebCore/dom/default/PlatformMessagePortChannel.h +++ b/WebCore/dom/default/PlatformMessagePortChannel.h @@ -63,18 +63,14 @@ namespace WebCore { public: static PassRefPtr<MessagePortQueue> create() { return adoptRef(new MessagePortQueue()); } - bool tryGetMessage(OwnPtr<MessagePortChannel::EventData>& message) + PassOwnPtr<MessagePortChannel::EventData> tryGetMessage() { - MessagePortChannel::EventData* holder = 0; - bool messageAvailable = m_queue.tryGetMessage(holder); - if (messageAvailable) - message.set(holder); - return messageAvailable; + return m_queue.tryGetMessage(); } bool appendAndCheckEmpty(PassOwnPtr<MessagePortChannel::EventData> message) { - return m_queue.appendAndCheckEmpty(message.release()); + return m_queue.appendAndCheckEmpty(message); } bool isEmpty() @@ -82,19 +78,10 @@ namespace WebCore { 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; + MessageQueue<MessagePortChannel::EventData> m_queue; }; ~PlatformMessagePortChannel(); |