diff options
Diffstat (limited to 'WebCore/dom')
87 files changed, 2660 insertions, 2343 deletions
diff --git a/WebCore/dom/ActiveDOMObject.h b/WebCore/dom/ActiveDOMObject.h index e58d3f9..73b52d5 100644 --- a/WebCore/dom/ActiveDOMObject.h +++ b/WebCore/dom/ActiveDOMObject.h @@ -53,9 +53,6 @@ namespace WebCore { virtual void resume(); virtual void stop(); - protected: - virtual ~ActiveDOMObject(); - template<class T> void setPendingActivity(T* thisObject) { ASSERT(thisObject == this); @@ -70,6 +67,9 @@ namespace WebCore { thisObject->deref(); } + protected: + virtual ~ActiveDOMObject(); + private: ScriptExecutionContext* m_scriptExecutionContext; unsigned m_pendingActivityCount; diff --git a/WebCore/dom/Attr.cpp b/WebCore/dom/Attr.cpp index 435c1af..aa5916b 100644 --- a/WebCore/dom/Attr.cpp +++ b/WebCore/dom/Attr.cpp @@ -3,7 +3,7 @@ * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Peter Kelly (pmk@post.com) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -30,10 +30,10 @@ namespace WebCore { -Attr::Attr(Element* element, Document* docPtr, PassRefPtr<Attribute> a) - : ContainerNode(docPtr) +inline Attr::Attr(Element* element, Document* document, PassRefPtr<Attribute> attribute) + : ContainerNode(document) , m_element(element) - , m_attribute(a) + , m_attribute(attribute) , m_ignoreChildrenChanged(0) , m_specified(true) { @@ -41,6 +41,13 @@ Attr::Attr(Element* element, Document* docPtr, PassRefPtr<Attribute> a) m_attribute->m_impl = this; } +PassRefPtr<Attr> Attr::create(Element* element, Document* document, PassRefPtr<Attribute> attribute) +{ + RefPtr<Attr> attr = adoptRef(new Attr(element, document, attribute)); + attr->createTextChild(); + return attr.release(); +} + Attr::~Attr() { ASSERT(m_attribute->attr() == this); @@ -86,14 +93,14 @@ const AtomicString& Attr::prefix() const return m_attribute->prefix(); } -void Attr::setPrefix(const AtomicString &_prefix, ExceptionCode& ec) +void Attr::setPrefix(const AtomicString& prefix, ExceptionCode& ec) { ec = 0; - checkSetPrefix(_prefix, ec); + checkSetPrefix(prefix, ec); if (ec) return; - m_attribute->setPrefix(_prefix); + m_attribute->setPrefix(prefix); } String Attr::nodeValue() const @@ -101,11 +108,11 @@ String Attr::nodeValue() const return value(); } -void Attr::setValue(const String& v, ExceptionCode&) +void Attr::setValue(const AtomicString& value, ExceptionCode&) { m_ignoreChildrenChanged++; removeChildren(); - m_attribute->setValue(v.impl()); + m_attribute->setValue(value); createTextChild(); m_ignoreChildrenChanged--; @@ -120,7 +127,7 @@ void Attr::setNodeValue(const String& v, ExceptionCode& ec) PassRefPtr<Node> Attr::cloneNode(bool /*deep*/) { - RefPtr<Attr> clone = new Attr(0, document(), m_attribute->clone()); + RefPtr<Attr> clone = adoptRef(new Attr(0, document(), m_attribute->clone())); cloneChildNodes(clone.get()); return clone.release(); } diff --git a/WebCore/dom/Attr.h b/WebCore/dom/Attr.h index ed4dc07..e927a6e 100644 --- a/WebCore/dom/Attr.h +++ b/WebCore/dom/Attr.h @@ -3,7 +3,7 @@ * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Peter Kelly (pmk@post.com) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -39,48 +39,47 @@ namespace WebCore { class Attr : public ContainerNode { friend class NamedNodeMap; public: - Attr(Element*, Document*, PassRefPtr<Attribute>); - ~Attr(); + static PassRefPtr<Attr> create(Element*, Document*, PassRefPtr<Attribute>); + virtual ~Attr(); - // Call this after calling the constructor so the - // Attr node isn't floating when we append the text node. - void createTextChild(); - - // DOM methods & attributes for Attr String name() const { return qualifiedName().toString(); } bool specified() const { return m_specified; } Element* ownerElement() const { return m_element; } - String value() const { return m_attribute->value(); } - void setValue(const String&, ExceptionCode&); + const AtomicString& value() const { return m_attribute->value(); } + void setValue(const AtomicString&, ExceptionCode&); + + Attribute* attr() const { return m_attribute.get(); } + const QualifiedName& qualifiedName() const { return m_attribute->name(); } + + // An extension to get presentational information for attributes. + CSSStyleDeclaration* style() { return m_attribute->style(); } + + void setSpecified(bool specified) { m_specified = specified; } + +private: + Attr(Element*, Document*, PassRefPtr<Attribute>); + + void createTextChild(); - // DOM methods overridden from parent classes virtual String nodeName() const; virtual NodeType nodeType() const; + const AtomicString& localName() const; const AtomicString& namespaceURI() const; const AtomicString& prefix() const; + virtual void setPrefix(const AtomicString&, ExceptionCode&); virtual String nodeValue() const; virtual void setNodeValue(const String&, ExceptionCode&); virtual PassRefPtr<Node> cloneNode(bool deep); - // Other methods (not part of DOM) virtual bool isAttributeNode() const { return true; } virtual bool childTypeAllowed(NodeType); virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); - Attribute* attr() const { return m_attribute.get(); } - const QualifiedName& qualifiedName() const { return m_attribute->name(); } - - // An extension to get presentational information for attributes. - CSSStyleDeclaration* style() { return m_attribute->style(); } - - void setSpecified(bool specified) { m_specified = specified; } - -private: virtual const AtomicString& virtualPrefix() const { return prefix(); } virtual const AtomicString& virtualLocalName() const { return localName(); } virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); } diff --git a/WebCore/dom/Attr.idl b/WebCore/dom/Attr.idl index 29f4be1..c01f34a 100644 --- a/WebCore/dom/Attr.idl +++ b/WebCore/dom/Attr.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> * * This library is free software; you can redistribute it and/or @@ -21,6 +21,7 @@ module core { interface [ + CustomMarkFunction, GenerateConstructor, GenerateNativeConverter, InterfaceUUID=EEE8E22B-22C3-4e50-95F4-5E0B8AAD8231, diff --git a/WebCore/dom/Attribute.cpp b/WebCore/dom/Attribute.cpp index 048ac6a..0ab0bb6 100644 --- a/WebCore/dom/Attribute.cpp +++ b/WebCore/dom/Attribute.cpp @@ -37,10 +37,8 @@ PassRefPtr<Attribute> Attribute::clone() const PassRefPtr<Attr> Attribute::createAttrIfNeeded(Element* e) { RefPtr<Attr> r = m_impl; - if (!r) { - r = new Attr(e, e->document(), this); - r->createTextChild(); - } + if (!r) + r = Attr::create(e, e->document(), this); return r.release(); } diff --git a/WebCore/dom/BeforeLoadEvent.h b/WebCore/dom/BeforeLoadEvent.h new file mode 100644 index 0000000..8c86773 --- /dev/null +++ b/WebCore/dom/BeforeLoadEvent.h @@ -0,0 +1,65 @@ +/* + * 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 BeforeLoadEvent_h +#define BeforeLoadEvent_h + +#include "Event.h" +#include "EventNames.h" + +namespace WebCore { + +class BeforeLoadEvent : public Event { +public: + static PassRefPtr<BeforeLoadEvent> create(const String& url) + { + return adoptRef(new BeforeLoadEvent(url)); + } + + void initBeforeLoadEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& url) + { + if (dispatched()) + return; + + initEvent(type, canBubble, cancelable); + + m_url = url; + } + + const String& url() const { return m_url; } + +private: + BeforeLoadEvent(const String& url) + : Event(eventNames().beforeloadEvent, false, true) + , m_url(url) + {} + + String m_url; +}; + +} // namespace WebCore + +#endif // BeforeLoadEvent_h diff --git a/WebCore/dom/BeforeLoadEvent.idl b/WebCore/dom/BeforeLoadEvent.idl new file mode 100644 index 0000000..d06a39d --- /dev/null +++ b/WebCore/dom/BeforeLoadEvent.idl @@ -0,0 +1,39 @@ +/* + * 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 + ] BeforeLoadEvent : Event { + void initBeforeLoadEvent(in DOMString type, + in boolean canBubble, + in boolean cancelable, + in DOMString url); + readonly attribute DOMString url; + }; + +} diff --git a/WebCore/dom/CDATASection.cpp b/WebCore/dom/CDATASection.cpp index 72faa70..d73054e 100644 --- a/WebCore/dom/CDATASection.cpp +++ b/WebCore/dom/CDATASection.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2003, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -26,13 +26,14 @@ namespace WebCore { -CDATASection::CDATASection(Document* document, const String& text) - : Text(document, text) +inline CDATASection::CDATASection(Document* document, const String& data) + : Text(document, data) { } -CDATASection::~CDATASection() +PassRefPtr<CDATASection> CDATASection::create(Document* document, const String& data) { + return adoptRef(new CDATASection(document, data)); } String CDATASection::nodeName() const @@ -47,19 +48,17 @@ Node::NodeType CDATASection::nodeType() const PassRefPtr<Node> CDATASection::cloneNode(bool /*deep*/) { - return new CDATASection(document(), m_data); + return create(document(), data()); } -// DOM Section 1.1.1 bool CDATASection::childTypeAllowed(NodeType) { return false; } -PassRefPtr<Text> CDATASection::createNew(PassRefPtr<StringImpl> string) +PassRefPtr<Text> CDATASection::virtualCreate(const String& data) { - return new CDATASection(document(), string); + return create(document(), data); } - } // namespace WebCore diff --git a/WebCore/dom/CDATASection.h b/WebCore/dom/CDATASection.h index 8b7df9d..5cf07e1 100644 --- a/WebCore/dom/CDATASection.h +++ b/WebCore/dom/CDATASection.h @@ -1,9 +1,7 @@ /* - * 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) - * Copyright (C) 2003 Apple Computer, Inc. + * Copyright (C) 2003, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -31,16 +29,16 @@ namespace WebCore { class CDATASection : public Text { public: + static PassRefPtr<CDATASection> create(Document*, const String&); + +private: CDATASection(Document*, const String&); - virtual ~CDATASection(); virtual String nodeName() const; virtual NodeType nodeType() const; virtual PassRefPtr<Node> cloneNode(bool deep); virtual bool childTypeAllowed(NodeType); - -protected: - virtual PassRefPtr<Text> createNew(PassRefPtr<StringImpl>); + virtual PassRefPtr<Text> virtualCreate(const String&); }; } // namespace WebCore diff --git a/WebCore/dom/CharacterData.cpp b/WebCore/dom/CharacterData.cpp index 9a72de9..3c3dc37 100644 --- a/WebCore/dom/CharacterData.cpp +++ b/WebCore/dom/CharacterData.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -30,20 +30,11 @@ namespace WebCore { -CharacterData::CharacterData(Document *doc, bool isText) - : Node(doc, false, false, isText) - , m_data(StringImpl::empty()) -{ -} - -CharacterData::CharacterData(Document* document, const String& text, bool isText) - : Node(document, false, false, isText) -{ - m_data = text.impl() ? text.impl() : StringImpl::empty(); -} - -CharacterData::~CharacterData() +CharacterData::CharacterData(Document* document, const String& text, ConstructionType type) + : Node(document, type) + , m_data(text.impl() ? text.impl() : StringImpl::empty()) { + ASSERT(type == CreateOther || type == CreateText); } void CharacterData::setData(const String& data, ExceptionCode&) @@ -196,10 +187,8 @@ void CharacterData::dispatchModifiedEvent(StringImpl* prevValue) { if (parentNode()) parentNode()->childrenChanged(); - if (document()->hasListenerType(Document::DOMCHARACTERDATAMODIFIED_LISTENER)) { - ExceptionCode ec; - dispatchMutationEvent(eventNames().DOMCharacterDataModifiedEvent, true, 0, prevValue, m_data, ec); - } + if (document()->hasListenerType(Document::DOMCHARACTERDATAMODIFIED_LISTENER)) + dispatchEvent(MutationEvent::create(eventNames().DOMCharacterDataModifiedEvent, true, 0, prevValue, m_data)); dispatchSubtreeModifiedEvent(); } diff --git a/WebCore/dom/CharacterData.h b/WebCore/dom/CharacterData.h index d9e55c0..6c31933 100644 --- a/WebCore/dom/CharacterData.h +++ b/WebCore/dom/CharacterData.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -29,12 +29,6 @@ namespace WebCore { class CharacterData : public Node { public: - CharacterData(Document*, const String& text, bool isText = false); - CharacterData(Document*, bool isText = false); - virtual ~CharacterData(); - - // DOM methods & attributes for CharacterData - String data() const { return m_data; } void setData(const String&, ExceptionCode&); unsigned length() const { return m_data->length(); } @@ -42,31 +36,30 @@ public: void appendData(const String&, ExceptionCode&); void insertData(unsigned offset, const String&, ExceptionCode&); void deleteData(unsigned offset, unsigned count, ExceptionCode&); - void replaceData(unsigned offset, unsigned count, const String &arg, ExceptionCode&); + void replaceData(unsigned offset, unsigned count, const String&, ExceptionCode&); bool containsOnlyWhitespace() const; - // DOM methods overridden from parent classes - - virtual String nodeValue() const; - virtual void setNodeValue(const String&, ExceptionCode&); - - // Other methods (not part of DOM) + StringImpl* dataImpl() { return m_data.get(); } - virtual bool isCharacterDataNode() const { return true; } - virtual int maxCharacterOffset() const; - StringImpl* string() { return m_data.get(); } +protected: + CharacterData(Document*, const String&, ConstructionType); - virtual bool offsetInCharacters() const; virtual bool rendererIsNeeded(RenderStyle*); -protected: - RefPtr<StringImpl> m_data; - + void setDataImpl(PassRefPtr<StringImpl> impl) { m_data = impl; } void dispatchModifiedEvent(StringImpl* oldValue); private: + virtual String nodeValue() const; + virtual void setNodeValue(const String&, ExceptionCode&); + virtual bool isCharacterDataNode() const { return true; } + virtual int maxCharacterOffset() const; + virtual bool offsetInCharacters() const; + void checkCharDataOperation(unsigned offset, ExceptionCode&); + + RefPtr<StringImpl> m_data; }; } // namespace WebCore diff --git a/WebCore/dom/Clipboard.h b/WebCore/dom/Clipboard.h index 0fea604..f6c09b2 100644 --- a/WebCore/dom/Clipboard.h +++ b/WebCore/dom/Clipboard.h @@ -64,7 +64,9 @@ namespace WebCore { virtual void setDragImageElement(Node*, const IntPoint&) = 0; virtual DragImageRef createDragImage(IntPoint& dragLocation) const = 0; +#if ENABLE(DRAG_SUPPORT) virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*) = 0; +#endif virtual void writeURL(const KURL&, const String&, Frame*) = 0; virtual void writeRange(Range*, Frame*) = 0; diff --git a/WebCore/dom/Comment.cpp b/WebCore/dom/Comment.cpp index a36a491..3dcde38 100644 --- a/WebCore/dom/Comment.cpp +++ b/WebCore/dom/Comment.cpp @@ -1,9 +1,7 @@ -/** - * 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) - * Copyright (C) 2003 Apple Computer, Inc. + * Copyright (C) 2003, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -24,22 +22,16 @@ #include "config.h" #include "Comment.h" -#include "Document.h" - namespace WebCore { -Comment::Comment(Document* doc, const String& text) - : CharacterData(doc, text) -{ -} - -Comment::Comment(Document* doc) - : CharacterData(doc) +inline Comment::Comment(Document* document, const String& text) + : CharacterData(document, text, CreateOther) { } -Comment::~Comment() +PassRefPtr<Comment> Comment::create(Document* document, const String& text) { + return adoptRef(new Comment(document, text)); } String Comment::nodeName() const @@ -54,10 +46,9 @@ Node::NodeType Comment::nodeType() const PassRefPtr<Node> Comment::cloneNode(bool /*deep*/) { - return document()->createComment(m_data); + return create(document(), data()); } -// DOM Section 1.1.1 bool Comment::childTypeAllowed(NodeType) { return false; diff --git a/WebCore/dom/Comment.h b/WebCore/dom/Comment.h index d00ba62..680ffae 100644 --- a/WebCore/dom/Comment.h +++ b/WebCore/dom/Comment.h @@ -1,9 +1,7 @@ /* - * 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) - * Copyright (C) 2003 Apple Computer, Inc. + * Copyright (C) 2003, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -31,16 +29,14 @@ namespace WebCore { class Comment : public CharacterData { public: - Comment(Document*, const String &_text); - Comment(Document*); - virtual ~Comment(); + static PassRefPtr<Comment> create(Document*, const String&); + +private: + Comment(Document*, const String&); - // DOM methods overridden from parent classes virtual String nodeName() const; virtual NodeType nodeType() const; virtual PassRefPtr<Node> cloneNode(bool deep); - - // Other methods (not part of DOM) virtual bool isCommentNode() const { return true; } virtual bool childTypeAllowed(NodeType); }; diff --git a/WebCore/dom/ContainerNode.cpp b/WebCore/dom/ContainerNode.cpp index 2d79156..99b2c4f 100644 --- a/WebCore/dom/ContainerNode.cpp +++ b/WebCore/dom/ContainerNode.cpp @@ -23,6 +23,7 @@ #include "config.h" #include "ContainerNode.h" +#include "BeforeLoadEvent.h" #include "Cache.h" #include "ContainerNodeAlgorithms.h" #include "DeleteButtonController.h" @@ -41,8 +42,8 @@ namespace WebCore { -static void dispatchChildInsertionEvents(Node*, ExceptionCode&); -static void dispatchChildRemovalEvents(Node*, ExceptionCode&); +static void dispatchChildInsertionEvents(Node*); +static void dispatchChildRemovalEvents(Node*); typedef Vector<std::pair<NodeCallback, RefPtr<Node> > > NodeCallbackQueue; static NodeCallbackQueue* s_postAttachCallbackQueue; @@ -144,7 +145,7 @@ bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce // Dispatch the mutation events. childrenChanged(false, refChildPreviousSibling.get(), next.get(), 1); - dispatchChildInsertionEvents(child.get(), ec); + dispatchChildInsertionEvents(child.get()); // Add child to the rendering tree. if (attached() && !child->attached() && child->parent() == this) { @@ -255,7 +256,7 @@ bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce allowEventDispatch(); // Dispatch the mutation events - dispatchChildInsertionEvents(child.get(), ec); + dispatchChildInsertionEvents(child.get()); // Add child to the rendering tree if (attached() && !child->attached() && child->parent() == this) { @@ -287,7 +288,7 @@ static ExceptionCode willRemoveChild(Node *child) ExceptionCode ec = 0; // fire removed from document mutation events. - dispatchChildRemovalEvents(child, ec); + dispatchChildRemovalEvents(child); if (ec) return ec; @@ -480,7 +481,7 @@ bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bo // Dispatch the mutation events childrenChanged(false, prev.get(), 0, 1); - dispatchChildInsertionEvents(child.get(), ec); + dispatchChildInsertionEvents(child.get()); // Add child to the rendering tree if (attached() && !child->attached() && child->parent() == this) { @@ -690,7 +691,7 @@ bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const point = o->container()->localToAbsolute(); if (o->isText() && toRenderText(o)->firstTextBox()) { point.move(toRenderText(o)->linesBoundingBox().x(), - toRenderText(o)->firstTextBox()->root()->topOverflow()); + toRenderText(o)->firstTextBox()->root()->lineTop()); } else if (o->isBox()) { RenderBox* box = toRenderBox(o); point.move(box->x(), box->y()); @@ -864,63 +865,57 @@ Node *ContainerNode::childNode(unsigned index) const return n; } -static void dispatchChildInsertionEvents(Node* child, ExceptionCode& ec) +static void dispatchChildInsertionEvents(Node* child) { ASSERT(!eventDispatchForbidden()); RefPtr<Node> c = child; - DocPtr<Document> doc = child->document(); + RefPtr<Document> document = child->document(); if (c->parentNode() && c->parentNode()->inDocument()) c->insertedIntoDocument(); else c->insertedIntoTree(true); - doc->incDOMTreeVersion(); + document->incDOMTreeVersion(); - if (c->parentNode() && doc->hasListenerType(Document::DOMNODEINSERTED_LISTENER)) { - ec = 0; - c->dispatchMutationEvent(eventNames().DOMNodeInsertedEvent, true, c->parentNode(), String(), String(), ec); - if (ec) - return; - } + if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER)) + c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode())); // dispatch the DOMNodeInsertedIntoDocument event to all descendants - if (c->inDocument() && doc->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) - for (; c; c = c->traverseNextNode(child)) { - ec = 0; - c->dispatchMutationEvent(eventNames().DOMNodeInsertedIntoDocumentEvent, false, 0, String(), String(), ec); - if (ec) - return; - } + if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) { + for (; c; c = c->traverseNextNode(child)) + c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false)); + } } -static void dispatchChildRemovalEvents(Node* child, ExceptionCode& ec) +static void dispatchChildRemovalEvents(Node* child) { RefPtr<Node> c = child; - DocPtr<Document> doc = child->document(); + RefPtr<Document> document = child->document(); // update auxiliary doc info (e.g. iterators) to note that node is being removed - doc->nodeWillBeRemoved(child); + document->nodeWillBeRemoved(child); - doc->incDOMTreeVersion(); + document->incDOMTreeVersion(); // dispatch pre-removal mutation events - if (c->parentNode() && doc->hasListenerType(Document::DOMNODEREMOVED_LISTENER)) { - ec = 0; - c->dispatchMutationEvent(eventNames().DOMNodeRemovedEvent, true, c->parentNode(), String(), String(), ec); - if (ec) - return; - } + if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER)) + c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode())); // dispatch the DOMNodeRemovedFromDocument event to all descendants - if (c->inDocument() && doc->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) - for (; c; c = c->traverseNextNode(child)) { - ec = 0; - c->dispatchMutationEvent(eventNames().DOMNodeRemovedFromDocumentEvent, false, 0, String(), String(), ec); - if (ec) - return; - } + if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) { + for (; c; c = c->traverseNextNode(child)) + c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false)); + } } +bool ContainerNode::dispatchBeforeLoadEvent(const String& sourceURL) +{ + RefPtr<ContainerNode> protector(this); + RefPtr<BeforeLoadEvent> beforeLoadEvent = BeforeLoadEvent::create(sourceURL); + dispatchEvent(beforeLoadEvent.get()); + return inDocument() && !beforeLoadEvent->defaultPrevented(); } + +} // namespace WebCore diff --git a/WebCore/dom/ContainerNode.h b/WebCore/dom/ContainerNode.h index 3ad932c..9789f1f 100644 --- a/WebCore/dom/ContainerNode.h +++ b/WebCore/dom/ContainerNode.h @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -38,7 +38,6 @@ namespace Private { class ContainerNode : public Node { public: - ContainerNode(Document*, bool isElement = false); virtual ~ContainerNode(); Node* firstChild() const { return m_firstChild; } @@ -72,8 +71,12 @@ public: void removeAllChildren(); void cloneChildNodes(ContainerNode* clone); + + bool dispatchBeforeLoadEvent(const String& sourceURL); protected: + ContainerNode(Document*, ConstructionType = CreateContainer); + static void queuePostAttachCallback(NodeCallback, Node*); void suspendPostAttachCallbacks(); void resumePostAttachCallbacks(); @@ -97,8 +100,8 @@ private: Node* m_lastChild; }; -inline ContainerNode::ContainerNode(Document* document, bool isElement) - : Node(document, isElement, true) +inline ContainerNode::ContainerNode(Document* document, ConstructionType type) + : Node(document, type) , m_firstChild(0) , m_lastChild(0) { diff --git a/WebCore/dom/DOMImplementation.cpp b/WebCore/dom/DOMImplementation.cpp index 065f708..59b9703 100644 --- a/WebCore/dom/DOMImplementation.cpp +++ b/WebCore/dom/DOMImplementation.cpp @@ -223,12 +223,6 @@ DOMImplementation* DOMImplementation::getInterface(const String& /*feature*/) PassRefPtr<Document> DOMImplementation::createDocument(const String& namespaceURI, const String& qualifiedName, DocumentType* doctype, ExceptionCode& ec) { - // WRONG_DOCUMENT_ERR: Raised if doctype has already been used with a different document or was - // created from a different implementation. - bool shouldThrowWrongDocErr = false; - if (doctype && doctype->document()) - shouldThrowWrongDocErr = true; - RefPtr<Document> doc; #if ENABLE(SVG) if (namespaceURI == SVGNames::svgNamespaceURI) @@ -245,24 +239,27 @@ PassRefPtr<Document> DOMImplementation::createDocument(const String& namespaceUR else doc = Document::create(0); - // now get the interesting parts of the doctype - if (doctype) - doc->addChild(doctype); - + RefPtr<Node> documentElement; if (!qualifiedName.isEmpty()) { - RefPtr<Node> documentElement = doc->createElementNS(namespaceURI, qualifiedName, ec); + documentElement = doc->createElementNS(namespaceURI, qualifiedName, ec); if (ec) return 0; - doc->addChild(documentElement.release()); } + // WRONG_DOCUMENT_ERR: Raised if doctype has already been used with a different document or was + // created from a different implementation. // Hixie's interpretation of the DOM Core spec suggests we should prefer - // other exceptions to WRONG_DOCUMENT_ERR (based on order mentioned in spec) - if (shouldThrowWrongDocErr) { + // other exceptions to WRONG_DOCUMENT_ERR (based on order mentioned in spec). + if (doctype && doctype->document()) { ec = WRONG_DOCUMENT_ERR; return 0; } + if (doctype) + doc->addChild(doctype); + if (documentElement) + doc->addChild(documentElement.release()); + return doc.release(); } diff --git a/WebCore/dom/DocPtr.h b/WebCore/dom/DocPtr.h deleted file mode 100644 index 8b50e8d..0000000 --- a/WebCore/dom/DocPtr.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * This file is part of the DOM implementation for KDE. - * Copyright (C) 2005, 2006 Apple Computer, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef DocPtr_h -#define DocPtr_h - -namespace WebCore { - -template <class T> class DocPtr { -public: - DocPtr() : m_ptr(0) {} - DocPtr(T *ptr) : m_ptr(ptr) { if (ptr) ptr->selfOnlyRef(); } - DocPtr(const DocPtr &o) : m_ptr(o.m_ptr) { if (T *ptr = m_ptr) ptr->selfOnlyRef(); } - ~DocPtr() { if (T *ptr = m_ptr) ptr->selfOnlyDeref(); } - - template <class U> DocPtr(const DocPtr<U> &o) : m_ptr(o.get()) { if (T *ptr = m_ptr) ptr->selfOnlyRef(); } - - void resetSkippingRef(T *o) { m_ptr = o; } - - T *get() const { return m_ptr; } - - T &operator*() const { return *m_ptr; } - T *operator->() const { return m_ptr; } - - bool operator!() const { return !m_ptr; } - - // this type conversion operator allows implicit conversion to - // bool but not to other integer types - - typedef T * (DocPtr::*UnspecifiedBoolType)() const; - operator UnspecifiedBoolType() const - { - return m_ptr ? &DocPtr::get : 0; - } - - DocPtr &operator=(const DocPtr &); - DocPtr &operator=(T *); - - private: - T *m_ptr; -}; - -template <class T> DocPtr<T> &DocPtr<T>::operator=(const DocPtr<T> &o) -{ - T *optr = o.m_ptr; - if (optr) - optr->selfOnlyRef(); - if (T *ptr = m_ptr) - ptr->selfOnlyDeref(); - m_ptr = optr; - return *this; -} - -template <class T> inline DocPtr<T> &DocPtr<T>::operator=(T *optr) -{ - if (optr) - optr->selfOnlyRef(); - if (T *ptr = m_ptr) - ptr->selfOnlyDeref(); - m_ptr = optr; - return *this; -} - -template <class T> inline bool operator==(const DocPtr<T> &a, const DocPtr<T> &b) -{ - return a.get() == b.get(); -} - -template <class T> inline bool operator==(const DocPtr<T> &a, const T *b) -{ - return a.get() == b; -} - -template <class T> inline bool operator==(const T *a, const DocPtr<T> &b) -{ - return a == b.get(); -} - -template <class T> inline bool operator!=(const DocPtr<T> &a, const DocPtr<T> &b) -{ - return a.get() != b.get(); -} - -template <class T> inline bool operator!=(const DocPtr<T> &a, const T *b) -{ - return a.get() != b; -} - -template <class T> inline bool operator!=(const T *a, const DocPtr<T> &b) -{ - return a != b.get(); -} - -} // namespace WebCore - -#endif // DocPtr_h diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp index e4c5741..efa2f7a 100644 --- a/WebCore/dom/Document.cpp +++ b/WebCore/dom/Document.cpp @@ -22,6 +22,7 @@ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ + #include "config.h" #include "Document.h" @@ -79,7 +80,7 @@ #include "HitTestResult.h" #include "ImageLoader.h" #include "InspectorController.h" -#include "ScriptEventListener.h" +#include "InspectorTimelineAgent.h" #include "KeyboardEvent.h" #include "Logging.h" #include "MappedAttribute.h" @@ -93,6 +94,8 @@ #include "NodeWithIndex.h" #include "OverflowEvent.h" #include "Page.h" +#include "PageGroup.h" +#include "PageTransitionEvent.h" #include "PlatformKeyboardEvent.h" #include "ProcessingInstruction.h" #include "ProgressEvent.h" @@ -103,6 +106,7 @@ #include "RenderWidget.h" #include "ScriptController.h" #include "ScriptElement.h" +#include "ScriptEventListener.h" #include "SecurityOrigin.h" #include "SegmentedString.h" #include "SelectionController.h" @@ -112,14 +116,17 @@ #include "TextIterator.h" #include "TextResourceDecoder.h" #include "Timer.h" +#include "TransformSource.h" #include "TreeWalker.h" #include "UIEvent.h" +#include "UserContentURLPattern.h" #include "WebKitAnimationEvent.h" #include "WebKitTransitionEvent.h" #include "WheelEvent.h" #include "XMLHttpRequest.h" #include "XMLNames.h" #include "XMLTokenizer.h" +#include "htmlediting.h" #include <wtf/CurrentTime.h> #include <wtf/HashFunctions.h> #include <wtf/MainThread.h> @@ -131,6 +138,10 @@ #include "DatabaseThread.h" #endif +#if ENABLE(SHARED_WORKERS) +#include "SharedWorkerRepository.h" +#endif + #if ENABLE(DOM_STORAGE) #include "StorageEvent.h" #endif @@ -153,6 +164,7 @@ #if ENABLE(SVG) #include "SVGDocumentExtensions.h" #include "SVGElementFactory.h" +#include "SVGNames.h" #include "SVGZoomEvent.h" #include "SVGStyleElement.h" #endif @@ -184,6 +196,12 @@ #include "WMLNames.h" #endif +#if ENABLE(MATHML) +#include "MathMLElement.h" +#include "MathMLElementFactory.h" +#include "MathMLNames.h" +#endif + #if ENABLE(XHTMLMP) #include "HTMLNoScriptElement.h" #endif @@ -325,9 +343,6 @@ Document::Document(Frame* frame, bool isXHTML) , m_titleSetExplicitly(false) , m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired) , m_executeScriptSoonTimer(this, &Document::executeScriptSoonTimerFired) -#if ENABLE(XSLT) - , m_transformSource(0) -#endif , m_xmlVersion("1.0") , m_xmlStandalone(false) #if ENABLE(XBL) @@ -361,7 +376,9 @@ Document::Document(Frame* frame, bool isXHTML) , m_containsWMLContent(false) #endif { - m_document.resetSkippingRef(this); + m_document = this; + + m_pageGroupUserSheetCacheValid = false; m_printing = false; @@ -431,8 +448,7 @@ void Document::removedLastRef() // want the document to be destructed until after // removeAllChildren returns, so we guard ourselves with an // extra self-only ref. - - DocPtr<Document> guard(this); + selfOnlyRef(); // We must make sure not to be retaining any of our children through // these extra pointers or we will create a reference cycle. @@ -456,6 +472,8 @@ void Document::removedLastRef() #ifndef NDEBUG m_inRemovedLastRefFunction = false; #endif + + selfOnlyDeref(); } else { #ifndef NDEBUG m_deletionHasBegun = true; @@ -482,7 +500,7 @@ Document::~Document() #endif delete m_tokenizer; - m_document.resetSkippingRef(0); + m_document = 0; delete m_styleSelector; delete m_docLoader; @@ -491,10 +509,6 @@ Document::~Document() m_renderArena = 0; } -#if ENABLE(XSLT) - xmlFreeDoc((xmlDocPtr)m_transformSource); -#endif - #if ENABLE(XBL) delete m_bindingManager; #endif @@ -518,8 +532,6 @@ Document::~Document() if (m_styleSheets) m_styleSheets->documentDestroyed(); - - m_document = 0; } void Document::resetLinkColor() @@ -599,17 +611,17 @@ PassRefPtr<Element> Document::createElement(const AtomicString& name, ExceptionC PassRefPtr<DocumentFragment> Document::createDocumentFragment() { - return new DocumentFragment(document()); + return DocumentFragment::create(document()); } PassRefPtr<Text> Document::createTextNode(const String& data) { - return new Text(this, data); + return Text::create(this, data); } PassRefPtr<Comment> Document::createComment(const String& data) { - return new Comment(this, data); + return Comment::create(this, data); } PassRefPtr<CDATASection> Document::createCDATASection(const String& data, ExceptionCode& ec) @@ -618,7 +630,7 @@ PassRefPtr<CDATASection> Document::createCDATASection(const String& data, Except ec = NOT_SUPPORTED_ERR; return 0; } - return new CDATASection(this, data); + return CDATASection::create(this, data); } PassRefPtr<ProcessingInstruction> Document::createProcessingInstruction(const String& target, const String& data, ExceptionCode& ec) @@ -631,7 +643,7 @@ PassRefPtr<ProcessingInstruction> Document::createProcessingInstruction(const St ec = NOT_SUPPORTED_ERR; return 0; } - return new ProcessingInstruction(this, target, data); + return ProcessingInstruction::create(this, target, data); } PassRefPtr<EntityReference> Document::createEntityReference(const String& name, ExceptionCode& ec) @@ -644,12 +656,12 @@ PassRefPtr<EntityReference> Document::createEntityReference(const String& name, ec = NOT_SUPPORTED_ERR; return 0; } - return new EntityReference(this, name); + return EntityReference::create(this, name); } PassRefPtr<EditingText> Document::createEditingTextNode(const String& text) { - return new EditingText(this, text); + return EditingText::create(this, text); } PassRefPtr<CSSStyleDeclaration> Document::createCSSStyleDeclaration() @@ -714,11 +726,8 @@ PassRefPtr<Node> Document::importNode(Node* importedNode, bool deep, ExceptionCo return newElement.release(); } - case ATTRIBUTE_NODE: { - RefPtr<Attr> newAttr = new Attr(0, this, static_cast<Attr*>(importedNode)->attr()->clone()); - newAttr->createTextChild(); - return newAttr.release(); - } + case ATTRIBUTE_NODE: + return Attr::create(0, this, static_cast<Attr*>(importedNode)->attr()->clone()); case DOCUMENT_FRAGMENT_NODE: { DocumentFragment* oldFragment = static_cast<DocumentFragment*>(importedNode); RefPtr<DocumentFragment> newFragment = createDocumentFragment(); @@ -828,9 +837,13 @@ PassRefPtr<Element> Document::createElement(const QualifiedName& qName, bool cre else if (isWMLDocument()) e = WMLElementFactory::createWMLElement(QualifiedName(nullAtom, qName.localName(), WMLNames::wmlNamespaceURI), this, createdByParser); #endif +#if ENABLE(MATHML) + else if (qName.namespaceURI() == MathMLNames::mathmlNamespaceURI) + e = MathMLElementFactory::createMathMLElement(qName, this, createdByParser); +#endif if (!e) - e = new Element(qName, document()); + e = Element::create(qName, document()); // <image> uses imgTag so we need a special rule. #if ENABLE(WML) @@ -952,16 +965,25 @@ KURL Document::baseURI() const Element* Document::elementFromPoint(int x, int y) const { + // FIXME: Share code between this and caretRangeFromPoint. if (!renderer()) return 0; + Frame* frame = this->frame(); + if (!frame) + return 0; + FrameView* frameView = frame->view(); + if (!frameView) + return 0; - HitTestRequest request(HitTestRequest::ReadOnly | - HitTestRequest::Active); + float zoomFactor = frame->pageZoomFactor(); + IntPoint point = roundedIntPoint(FloatPoint(x * zoomFactor, y * zoomFactor)) + view()->scrollOffset(); - float zoomFactor = frame() ? frame()->pageZoomFactor() : 1.0f; + if (!frameView->visibleContentRect().contains(point)) + return 0; - HitTestResult result(roundedIntPoint(FloatPoint(x * zoomFactor, y * zoomFactor))); - renderView()->layer()->hitTest(request, result); + HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); + HitTestResult result(point); + renderView()->layer()->hitTest(request, result); Node* n = result.innerNode(); while (n && !n->isElementNode()) @@ -971,6 +993,50 @@ Element* Document::elementFromPoint(int x, int y) const return static_cast<Element*>(n); } +PassRefPtr<Range> Document::caretRangeFromPoint(int x, int y) +{ + // FIXME: Share code between this and elementFromPoint. + if (!renderer()) + return 0; + Frame* frame = this->frame(); + if (!frame) + return 0; + FrameView* frameView = frame->view(); + if (!frameView) + return 0; + + float zoomFactor = frame->pageZoomFactor(); + IntPoint point = roundedIntPoint(FloatPoint(x * zoomFactor, y * zoomFactor)) + view()->scrollOffset(); + + if (!frameView->visibleContentRect().contains(point)) + return 0; + + HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); + HitTestResult result(point); + renderView()->layer()->hitTest(request, result); + + Node* node = result.innerNode(); + if (!node) + return 0; + + Node* shadowAncestorNode = node->shadowAncestorNode(); + if (shadowAncestorNode != node) { + unsigned offset = shadowAncestorNode->nodeIndex(); + Node* container = shadowAncestorNode->parentNode(); + return Range::create(this, container, offset, container, offset); + } + + RenderObject* renderer = node->renderer(); + if (!renderer) + return 0; + VisiblePosition visiblePosition = renderer->positionForPoint(result.localPoint()); + if (visiblePosition.isNull()) + return 0; + + Position rangeCompliantPosition = rangeCompliantEquivalent(visiblePosition); + return Range::create(this, rangeCompliantPosition, rangeCompliantPosition); +} + void Document::addElementById(const AtomicString& elementId, Element* element) { typedef HashMap<AtomicStringImpl*, Element*>::iterator iterator; @@ -1186,6 +1252,12 @@ void Document::recalcStyle(StyleChange change) if (m_inStyleRecalc) return; // Guard against re-entrancy. -dwh +#if ENABLE(INSPECTOR) + InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent(); + if (timelineAgent) + timelineAgent->willRecalculateStyle(); +#endif + m_inStyleRecalc = true; suspendPostAttachCallbacks(); if (view()) @@ -1266,6 +1338,11 @@ bail_out: m_closeAfterStyleRecalc = false; implicitClose(); } + +#if ENABLE(INSPECTOR) + if (timelineAgent) + timelineAgent->didRecalculateStyle(); +#endif } void Document::updateStyleIfNeeded() @@ -1363,7 +1440,8 @@ void Document::attach() bool matchAuthorAndUserStyles = true; if (Settings* docSettings = settings()) matchAuthorAndUserStyles = docSettings->authorAndUserStylesEnabled(); - m_styleSelector = new CSSStyleSelector(this, userStyleSheet(), m_styleSheets.get(), m_mappedElementSheet.get(), !inCompatMode(), matchAuthorAndUserStyles); + m_styleSelector = new CSSStyleSelector(this, m_styleSheets.get(), m_mappedElementSheet.get(), pageUserSheet(), pageGroupUserSheets(), + !inCompatMode(), matchAuthorAndUserStyles); } recalcStyle(Force); @@ -1389,7 +1467,11 @@ void Document::detach() // Send out documentWillBecomeInactive() notifications to registered elements, // in order to stop media elements documentWillBecomeInactive(); - + +#if ENABLE(SHARED_WORKERS) + SharedWorkerRepository::documentDetached(this); +#endif + if (m_frame) { FrameView* view = m_frame->view(); if (view) @@ -1436,31 +1518,14 @@ void Document::detach() void Document::removeAllEventListeners() { + EventTarget::removeAllEventListeners(); + if (DOMWindow* domWindow = this->domWindow()) domWindow->removeAllEventListeners(); - removeAllDisconnectedNodeEventListeners(); - for (Node* node = this; node; node = node->traverseNextNode()) + for (Node* node = firstChild(); node; node = node->traverseNextNode()) node->removeAllEventListeners(); } -void Document::registerDisconnectedNodeWithEventListeners(Node* node) -{ - m_disconnectedNodesWithEventListeners.add(node); -} - -void Document::unregisterDisconnectedNodeWithEventListeners(Node* node) -{ - m_disconnectedNodesWithEventListeners.remove(node); -} - -void Document::removeAllDisconnectedNodeEventListeners() -{ - HashSet<Node*>::iterator end = m_disconnectedNodesWithEventListeners.end(); - for (HashSet<Node*>::iterator i = m_disconnectedNodesWithEventListeners.begin(); i != end; ++i) - (*i)->removeAllEventListeners(); - m_disconnectedNodesWithEventListeners.clear(); -} - RenderView* Document::renderView() const { return toRenderView(renderer()); @@ -1660,7 +1725,7 @@ void Document::implicitClose() return; } - bool wasLocationChangePending = frame() && frame()->loader()->isScheduledLocationChangePending(); + bool wasLocationChangePending = frame() && frame()->redirectScheduler()->locationChangePending(); bool doload = !parsing() && m_tokenizer && !m_processingLoadEvent && !wasLocationChangePending; if (!doload) @@ -1708,7 +1773,8 @@ void Document::implicitClose() f->animation()->resumeAnimations(this); ImageLoader::dispatchPendingLoadEvents(); - dispatchLoadEvent(); + dispatchWindowLoadEvent(); + dispatchWindowEvent(PageTransitionEvent::create(eventNames().pageshowEvent, false), this); if (f) f->loader()->handledOnloadEvents(); #ifdef INSTRUMENT_LAYOUT_SCHEDULING @@ -1726,7 +1792,7 @@ void Document::implicitClose() // fires. This will improve onload scores, and other browsers do it. // If they wanna cheat, we can too. -dwh - if (frame()->loader()->isScheduledLocationChangePending() && elapsedTime() < cLayoutScheduleThreshold) { + if (frame()->redirectScheduler()->locationChangePending() && elapsedTime() < cLayoutScheduleThreshold) { // Just bail out. Before or during the onload we were shifted to another page. // The old i-Bench suite does this. When this happens don't bother painting or laying out. view()->unscheduleRelayout(); @@ -1755,7 +1821,7 @@ void Document::implicitClose() // exists in the cache (we ignore the return value because we don't need it here). This is // only safe to call when a layout is not in progress, so it can not be used in postNotification. axObjectCache()->getOrCreate(renderObject); - axObjectCache()->postNotification(renderObject, "AXLoadComplete", true); + axObjectCache()->postNotification(renderObject, AXObjectCache::AXLoadComplete, true); } #endif @@ -1917,34 +1983,72 @@ String Document::userAgent(const KURL& url) const return frame() ? frame()->loader()->userAgent(url) : String(); } -void Document::setCSSStyleSheet(const String& url, const String& charset, const CachedCSSStyleSheet* sheet) +CSSStyleSheet* Document::pageUserSheet() { - m_sheet = CSSStyleSheet::create(this, url, charset); - m_sheet->parseString(sheet->sheetText()); + if (m_pageUserSheet) + return m_pageUserSheet.get(); + + Page* owningPage = page(); + if (!owningPage) + return 0; + + String userSheetText = owningPage->userStyleSheet(); + if (userSheetText.isEmpty()) + return 0; + + // Parse the sheet and cache it. + m_pageUserSheet = CSSStyleSheet::create(this, settings()->userStyleSheetLocation()); + m_pageUserSheet->setIsUserStyleSheet(true); + m_pageUserSheet->parseString(userSheetText, !inCompatMode()); + return m_pageUserSheet.get(); +} +void Document::clearPageUserSheet() +{ + m_pageUserSheet = 0; updateStyleSelector(); } -#if FRAME_LOADS_USER_STYLESHEET -void Document::setUserStyleSheet(const String& sheet) +const Vector<RefPtr<CSSStyleSheet> >* Document::pageGroupUserSheets() const { - if (m_usersheet != sheet) { - m_usersheet = sheet; - updateStyleSelector(); + if (m_pageGroupUserSheetCacheValid) + return m_pageGroupUserSheets.get(); + + m_pageGroupUserSheetCacheValid = true; + + Page* owningPage = page(); + if (!owningPage) + return 0; + + const PageGroup& pageGroup = owningPage->group(); + const UserStyleSheetMap* sheetsMap = pageGroup.userStyleSheets(); + if (!sheetsMap) + return 0; + + UserStyleSheetMap::const_iterator end = sheetsMap->end(); + for (UserStyleSheetMap::const_iterator it = sheetsMap->begin(); it != end; ++it) { + const UserStyleSheetVector* sheets = it->second; + for (unsigned i = 0; i < sheets->size(); ++i) { + const UserStyleSheet* sheet = sheets->at(i).get(); + if (!UserContentURLPattern::matchesPatterns(url(), sheet->whitelist(), sheet->blacklist())) + continue; + RefPtr<CSSStyleSheet> parsedSheet = CSSStyleSheet::create(const_cast<Document*>(this), sheet->url()); + parsedSheet->setIsUserStyleSheet(true); + parsedSheet->parseString(sheet->source(), !inCompatMode()); + if (!m_pageGroupUserSheets) + m_pageGroupUserSheets.set(new Vector<RefPtr<CSSStyleSheet> >); + m_pageGroupUserSheets->append(parsedSheet.release()); + } } + + return m_pageGroupUserSheets.get(); } -#endif -String Document::userStyleSheet() const +void Document::clearPageGroupUserSheets() { -#if FRAME_LOADS_USER_STYLESHEET - return m_usersheet; -#else - Page* page = this->page(); - if (!page) - return String(); - return page->userStyleSheet(); -#endif + m_pageGroupUserSheets.clear(); + m_pageGroupUserSheetCacheValid = false; + updateStyleSelector(); } CSSStyleSheet* Document::elementSheet() @@ -2175,7 +2279,7 @@ void Document::processHttpEquiv(const String& equiv, const String& content) url = frame->loader()->url().string(); else url = completeURL(url).string(); - frame->loader()->scheduleHTTPRedirection(delay, url); + frame->redirectScheduler()->scheduleRedirect(delay, url); } } else if (equalIgnoringCase(equiv, "set-cookie")) { // FIXME: make setCookie work on XML documents too; e.g. in case of <html:meta .....> @@ -2189,7 +2293,7 @@ void Document::processHttpEquiv(const String& equiv, const String& content) FrameLoader* frameLoader = frame->loader(); if (frameLoader->shouldInterruptLoadForXFrameOptions(content, url())) { frameLoader->stopAllLoaders(); - frameLoader->scheduleHTTPRedirection(0, blankURL()); + frame->redirectScheduler()->scheduleLocationChange(blankURL(), String()); } } } @@ -2566,7 +2670,8 @@ void Document::recalcStyleSelector() // Create a new style selector delete m_styleSelector; - m_styleSelector = new CSSStyleSelector(this, userStyleSheet(), m_styleSheets.get(), m_mappedElementSheet.get(), !inCompatMode(), matchAuthorAndUserStyles); + m_styleSelector = new CSSStyleSelector(this, m_styleSheets.get(), m_mappedElementSheet.get(), + pageUserSheet(), pageGroupUserSheets(), !inCompatMode(), matchAuthorAndUserStyles); m_didCalculateStyleSelector = true; } @@ -2661,7 +2766,7 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) // 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(eventNames().changeEvent, true, false); + oldFocusedNode->dispatchEvent(Event::create(eventNames().changeEvent, true, false)); r = oldFocusedNode->renderer(); if (r && r->isTextControl()) toRenderTextControl(r)->setEdited(false); @@ -2681,10 +2786,10 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) focusChangeBlocked = true; newFocusedNode = 0; } - if ((oldFocusedNode.get() == this) && oldFocusedNode->hasOneRef()) + if (oldFocusedNode == this && oldFocusedNode->hasOneRef()) return true; - if (oldFocusedNode.get() == oldFocusedNode->rootEditableElement()) + if (oldFocusedNode == oldFocusedNode->rootEditableElement()) frame()->editor()->didEndEditing(); } @@ -2713,7 +2818,7 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) } m_focusedNode->setFocus(); - if (m_focusedNode.get() == m_focusedNode->rootEditableElement()) + if (m_focusedNode == m_focusedNode->rootEditableElement()) frame()->editor()->didBeginEditing(); // eww, I suck. set the qt focus correctly @@ -2735,20 +2840,17 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) } } -#if PLATFORM(MAC) && !PLATFORM(CHROMIUM) - if (!focusChangeBlocked && m_focusedNode && AXObjectCache::accessibilityEnabled()) - axObjectCache()->handleFocusedUIElementChanged(); -#elif PLATFORM(GTK) +#if ((PLATFORM(MAC) || PLATFORM(WIN)) && !PLATFORM(CHROMIUM)) || PLATFORM(GTK) if (!focusChangeBlocked && m_focusedNode && AXObjectCache::accessibilityEnabled()) { RenderObject* oldFocusedRenderer = 0; RenderObject* newFocusedRenderer = 0; if (oldFocusedNode) - oldFocusedRenderer = oldFocusedNode.get()->renderer(); + oldFocusedRenderer = oldFocusedNode->renderer(); if (newFocusedNode) - newFocusedRenderer = newFocusedNode.get()->renderer(); + newFocusedRenderer = newFocusedNode->renderer(); - axObjectCache()->handleFocusedUIElementChangedWithRenderers(oldFocusedRenderer, newFocusedRenderer); + axObjectCache()->handleFocusedUIElementChanged(oldFocusedRenderer, newFocusedRenderer); } #endif @@ -2891,26 +2993,16 @@ EventListener* Document::getWindowAttributeEventListener(const AtomicString& eve return domWindow->getAttributeEventListener(eventType); } -void Document::dispatchWindowEvent(PassRefPtr<Event> event) -{ - ASSERT(!eventDispatchForbidden()); - DOMWindow* domWindow = this->domWindow(); - if (!domWindow) - return; - ExceptionCode ec; - domWindow->dispatchEvent(event, ec); -} - -void Document::dispatchWindowEvent(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg) +void Document::dispatchWindowEvent(PassRefPtr<Event> event, PassRefPtr<EventTarget> target) { ASSERT(!eventDispatchForbidden()); DOMWindow* domWindow = this->domWindow(); if (!domWindow) return; - domWindow->dispatchEvent(eventType, canBubbleArg, cancelableArg); + domWindow->dispatchEvent(event, target); } -void Document::dispatchLoadEvent() +void Document::dispatchWindowLoadEvent() { ASSERT(!eventDispatchForbidden()); DOMWindow* domWindow = this->domWindow(); @@ -2933,6 +3025,8 @@ PassRefPtr<Event> Document::createEvent(const String& eventType, ExceptionCode& return MutationEvent::create(); if (eventType == "OverflowEvent") return OverflowEvent::create(); + if (eventType == "PageTransitionEvent") + return PageTransitionEvent::create(); if (eventType == "ProgressEvent") return ProgressEvent::create(); #if ENABLE(DOM_STORAGE) @@ -3039,7 +3133,7 @@ String Document::domain() const return securityOrigin()->domain(); } -void Document::setDomain(const String& newDomain) +void Document::setDomain(const String& newDomain, ExceptionCode& ec) { // Both NS and IE specify that changing the domain is only allowed when // the new domain is a suffix of the old domain. @@ -3062,19 +3156,25 @@ void Document::setDomain(const String& newDomain) int oldLength = domain().length(); int newLength = newDomain.length(); // e.g. newDomain = webkit.org (10) and domain() = www.webkit.org (14) - if (newLength >= oldLength) + if (newLength >= oldLength) { + ec = SECURITY_ERR; return; + } String test = domain(); // Check that it's a subdomain, not e.g. "ebkit.org" - if (test[oldLength - newLength - 1] != '.') + if (test[oldLength - newLength - 1] != '.') { + ec = SECURITY_ERR; return; + } // Now test is "webkit.org" from domain() // and we check that it's the same thing as newDomain test.remove(0, oldLength - newLength); - if (test != newDomain) + if (test != newDomain) { + ec = SECURITY_ERR; return; + } securityOrigin()->setDomainFromDOM(newDomain); if (m_frame) @@ -3870,13 +3970,11 @@ void Document::applyXSLTransform(ProcessingInstruction* pi) processor->createDocumentFromSource(newSource, resultEncoding, resultMIMEType, this, frame()); } -void Document::setTransformSource(void* doc) +void Document::setTransformSource(PassOwnPtr<TransformSource> source) { - if (doc == m_transformSource) + if (m_transformSource == source) return; - - xmlFreeDoc((xmlDocPtr)m_transformSource); - m_transformSource = doc; + m_transformSource = source; } #endif @@ -3946,7 +4044,7 @@ PassRefPtr<Attr> Document::createAttributeNS(const String& namespaceURI, const S // FIXME: Assume this is a mapped attribute, since createAttribute isn't namespace-aware. There's no harm to XML // documents if we're wrong. - return new Attr(0, this, MappedAttribute::create(qName, StringImpl::empty())); + return Attr::create(0, this, MappedAttribute::create(qName, StringImpl::empty())); } #if ENABLE(SVG) @@ -4040,12 +4138,18 @@ CollectionCache* Document::nameCollectionInfo(CollectionType type, const AtomicS void Document::finishedParsing() { setParsing(false); + dispatchEvent(Event::create(eventNames().DOMContentLoadedEvent, true, false)); + if (Frame* f = frame()) { + f->loader()->finishedParsing(); - ExceptionCode ec = 0; - dispatchEvent(Event::create(eventNames().DOMContentLoadedEvent, true, false), ec); +#if ENABLE(INSPECTOR) + if (!page()) + return; - if (Frame* f = frame()) - f->loader()->finishedParsing(); + if (InspectorController* controller = page()->inspectorController()) + controller->mainResourceFiredDOMContentEvent(f->loader()->documentLoader(), url()); +#endif + } } Vector<String> Document::formElementsState() const @@ -4247,7 +4351,7 @@ void Document::initSecurityContext() if (!m_frame) { // No source for a security context. // This can occur via document.implementation.createDocument(). - m_cookieURL = KURL(""); + m_cookieURL = KURL(ParsedURLString, ""); ScriptExecutionContext::setSecurityOrigin(SecurityOrigin::createEmpty()); return; } @@ -4258,7 +4362,7 @@ void Document::initSecurityContext() m_cookieURL = url; ScriptExecutionContext::setSecurityOrigin(SecurityOrigin::create(url)); - if (FrameLoader::allowSubstituteDataAccessToLocal()) { + 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 // and https://bugs.webkit.org/show_bug.cgi?id=19760 for further @@ -4448,7 +4552,7 @@ void Document::detachRange(Range* range) m_ranges.remove(range); } -CanvasRenderingContext2D* Document::getCSSCanvasContext(const String& type, const String& name, int width, int height) +CanvasRenderingContext* Document::getCSSCanvasContext(const String& type, const String& name, int width, int height) { HTMLCanvasElement* result = getCSSCanvasElement(name); if (!result) @@ -4531,10 +4635,12 @@ void Document::reportException(const String& errorMessage, int lineNumber, const void Document::addMessage(MessageDestination destination, MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL) { switch (destination) { +#if ENABLE(INSPECTOR) case InspectorControllerDestination: if (page()) page()->inspectorController()->addMessageToConsole(source, type, level, message, lineNumber, sourceURL); return; +#endif case ConsoleDestination: if (DOMWindow* window = domWindow()) window->console()->addMessage(source, type, level, message, lineNumber, sourceURL); @@ -4545,8 +4651,10 @@ void Document::addMessage(MessageDestination destination, MessageSource source, void Document::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString) { +#if ENABLE(INSPECTOR) if (page()) page()->inspectorController()->resourceRetrievedByXMLHttpRequest(identifier, sourceString); +#endif Frame* frame = this->frame(); if (frame) { FrameLoader* frameLoader = frame->loader(); @@ -4556,8 +4664,13 @@ void Document::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const void Document::scriptImported(unsigned long identifier, const String& sourceString) { +#if ENABLE(INSPECTOR) if (page()) page()->inspectorController()->scriptImported(identifier, sourceString); +#else + UNUSED_PARAM(identifier); + UNUSED_PARAM(sourceString); +#endif } class ScriptExecutionContextTaskTimer : public TimerBase { diff --git a/WebCore/dom/Document.h b/WebCore/dom/Document.h index fc4dc7e..fc2eea0 100644 --- a/WebCore/dom/Document.h +++ b/WebCore/dom/Document.h @@ -33,18 +33,12 @@ #include "CollectionType.h" #include "Color.h" #include "DocumentMarker.h" +#include "Page.h" #include "ScriptExecutionContext.h" #include "Timer.h" #include <wtf/HashCountedSet.h> - -// FIXME: We should move Mac off of the old Frame-based user stylesheet loading -// code and onto the new code in Page. We can't do that until the code in Page -// supports non-file: URLs, however. -#if PLATFORM(MAC) || PLATFORM(QT) -#define FRAME_LOADS_USER_STYLESHEET 1 -#else -#define FRAME_LOADS_USER_STYLESHEET 0 -#endif +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> namespace WebCore { @@ -53,7 +47,7 @@ namespace WebCore { class CDATASection; class CachedCSSStyleSheet; class CachedScript; - class CanvasRenderingContext2D; + class CanvasRenderingContext; class CharacterData; class CSSStyleDeclaration; class CSSStyleSelector; @@ -83,12 +77,12 @@ namespace WebCore { class HTMLHeadElement; class HTMLInputElement; class HTMLMapElement; + class InspectorTimelineAgent; class IntPoint; class JSNode; class MouseEventWithHitTestResults; class NodeFilter; class NodeIterator; - class Page; class PlatformMouseEvent; class ProcessingInstruction; class Range; @@ -111,6 +105,10 @@ namespace WebCore { class SVGDocumentExtensions; #endif +#if ENABLE(XSLT) + class TransformSource; +#endif + #if ENABLE(XBL) class XBLBindingManager; #endif @@ -172,19 +170,16 @@ class Document : public ContainerNode, public ScriptExecutionContext { public: static PassRefPtr<Document> create(Frame* frame) { - return new Document(frame, false); + return adoptRef(new Document(frame, false)); } static PassRefPtr<Document> createXHTML(Frame* frame) { - return new Document(frame, true); + return adoptRef(new Document(frame, true)); } virtual ~Document(); - virtual bool isDocument() const { return true; } - using ContainerNode::ref; using ContainerNode::deref; - virtual void removedLastRef(); // Nodes belonging to this document hold "self-only" references - // these are enough to keep the document from being destroyed, but @@ -211,10 +206,52 @@ public: // DOM methods & attributes for Document + DEFINE_ATTRIBUTE_EVENT_LISTENER(abort); + DEFINE_ATTRIBUTE_EVENT_LISTENER(change); + DEFINE_ATTRIBUTE_EVENT_LISTENER(click); + DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu); + DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick); + DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter); + DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover); + DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave); + DEFINE_ATTRIBUTE_EVENT_LISTENER(drop); + DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart); + DEFINE_ATTRIBUTE_EVENT_LISTENER(drag); + DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend); + DEFINE_ATTRIBUTE_EVENT_LISTENER(input); + DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid); + DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown); + DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress); + DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup); + DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown); + DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove); + DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout); + DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover); + DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup); + DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel); + DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll); + DEFINE_ATTRIBUTE_EVENT_LISTENER(select); + DEFINE_ATTRIBUTE_EVENT_LISTENER(submit); + + DEFINE_ATTRIBUTE_EVENT_LISTENER(blur); + DEFINE_ATTRIBUTE_EVENT_LISTENER(error); + DEFINE_ATTRIBUTE_EVENT_LISTENER(focus); + DEFINE_ATTRIBUTE_EVENT_LISTENER(load); + + // WebKit extensions + DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut); + DEFINE_ATTRIBUTE_EVENT_LISTENER(cut); + DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy); + DEFINE_ATTRIBUTE_EVENT_LISTENER(copy); + DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste); + DEFINE_ATTRIBUTE_EVENT_LISTENER(paste); + DEFINE_ATTRIBUTE_EVENT_LISTENER(reset); + DEFINE_ATTRIBUTE_EVENT_LISTENER(search); + DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart); + DocumentType* doctype() const { return m_docType.get(); } DOMImplementation* implementation() const; - virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); Element* documentElement() const { @@ -240,6 +277,8 @@ public: bool containsMultipleElementsWithId(const AtomicString& elementId) { return m_duplicateIds.contains(elementId.impl()); } Element* elementFromPoint(int x, int y) const; + PassRefPtr<Range> caretRangeFromPoint(int x, int y); + String readyState() const; String defaultCharset() const; @@ -299,11 +338,6 @@ public: CollectionCache* nameCollectionInfo(CollectionType, const AtomicString& name); - // DOM methods overridden from parent classes - - virtual String nodeName() const; - virtual NodeType nodeType() const; - // Other methods (not part of DOM) virtual bool isHTMLDocument() const { return false; } virtual bool isImageDocument() const { return false; } @@ -392,6 +426,9 @@ public: Frame* frame() const { return m_frame; } // can be NULL Page* page() const; // can be NULL Settings* settings() const; // can be NULL +#if ENABLE(INSPECTOR) + InspectorTimelineAgent* inspectorTimelineAgent() const; // can be NULL +#endif PassRefPtr<Range> createRange(); @@ -455,17 +492,15 @@ public: virtual String userAgent(const KURL&) const; - // from cachedObjectClient - virtual void setCSSStyleSheet(const String& url, const String& charset, const CachedCSSStyleSheet*); - -#if FRAME_LOADS_USER_STYLESHEET - void setUserStyleSheet(const String& sheet); -#endif + CSSStyleSheet* pageUserSheet(); + void clearPageUserSheet(); - String userStyleSheet() const; + const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets() const; + void clearPageGroupUserSheets(); CSSStyleSheet* elementSheet(); CSSStyleSheet* mappedElementSheet(); + virtual Tokenizer* createTokenizer(); Tokenizer* tokenizer() { return m_tokenizer; } @@ -474,10 +509,6 @@ public: enum ParseMode { Compat, AlmostStrict, Strict }; -private: - virtual void determineParseMode() {} - -public: void setParseMode(ParseMode m) { m_parseMode = m; } ParseMode parseMode() const { return m_parseMode; } @@ -506,11 +537,6 @@ public: MouseEventWithHitTestResults prepareMouseEvent(const HitTestRequest&, const IntPoint&, const PlatformMouseEvent&); - virtual bool childTypeAllowed(NodeType); - virtual PassRefPtr<Node> cloneNode(bool deep); - - virtual bool canReplaceChild(Node* newChild, Node* oldChild); - StyleSheetList* styleSheets(); /* Newly proposed CSS3 mechanism for selecting alternate @@ -570,9 +596,8 @@ public: // Helper functions for forwarding DOMWindow event related tasks to the DOMWindow if it exists. void setWindowAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener>); EventListener* getWindowAttributeEventListener(const AtomicString& eventType); - void dispatchWindowEvent(PassRefPtr<Event>); - void dispatchWindowEvent(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg); - void dispatchLoadEvent(); + void dispatchWindowEvent(PassRefPtr<Event>, PassRefPtr<EventTarget> = 0); + void dispatchWindowLoadEvent(); PassRefPtr<Event> createEvent(const String& eventType, ExceptionCode&); @@ -661,7 +686,7 @@ public: String referrer() const; String domain() const; - void setDomain(const String& newDomain); + void setDomain(const String& newDomain, ExceptionCode&); String lastModified() const; @@ -735,10 +760,11 @@ public: #if ENABLE(XSLT) void applyXSLTransform(ProcessingInstruction* pi); - void setTransformSource(void* doc); - const void* transformSource() { return m_transformSource; } PassRefPtr<Document> transformSourceDocument() { return m_transformSourceDocument; } void setTransformSourceDocument(Document* doc) { m_transformSourceDocument = doc; } + + void setTransformSource(PassOwnPtr<TransformSource>); + TransformSource* transformSource() const { return m_transformSource.get(); } #endif #if ENABLE(XBL) @@ -751,8 +777,6 @@ public: void setDocType(PassRefPtr<DocumentType>); - virtual void finishedParsing(); - #if ENABLE(XPATH) // XPathEvaluator methods PassRefPtr<XPathExpression> createExpression(const String& expression, @@ -785,7 +809,7 @@ public: void updateFocusAppearanceSoon(); void cancelFocusAppearanceUpdate(); - + #ifdef ANDROID_MOBILE void setExtraLayoutDelay(int delay) { mExtraLayoutDelay = delay; } int extraLayoutDelay() { return mExtraLayoutDelay; } @@ -795,11 +819,10 @@ public: DOMSelection* getSelection() const; // Extension for manipulating canvas drawing contexts for use in CSS - CanvasRenderingContext2D* getCSSCanvasContext(const String& type, const String& name, int width, int height); + CanvasRenderingContext* getCSSCanvasContext(const String& type, const String& name, int width, int height); HTMLCanvasElement* getCSSCanvasElement(const String& name); bool isDNSPrefetchEnabled() const { return m_isDNSPrefetchEnabled; } - void initDNSPrefetch(); void parseDNSPrefetchControlHeader(const String&); virtual void reportException(const String& errorMessage, int lineNumber, const String& sourceURL); @@ -808,10 +831,92 @@ public: virtual void scriptImported(unsigned long, const String&); virtual void postTask(PassRefPtr<Task>); // Executes the task on context's thread asynchronously. + typedef HashMap<WebCore::Node*, JSNode*> JSWrapperCache; + JSWrapperCache& wrapperCache() { return m_wrapperCache; } + + virtual void finishedParsing(); + + bool inPageCache() const { return m_inPageCache; } + void setInPageCache(bool flag); + + // Elements can register themselves for the "documentWillBecomeInactive()" and + // "documentDidBecomeActive()" callbacks + void registerForDocumentActivationCallbacks(Element*); + void unregisterForDocumentActivationCallbacks(Element*); + void documentWillBecomeInactive(); + void documentDidBecomeActive(); + + void registerForMediaVolumeCallbacks(Element*); + void unregisterForMediaVolumeCallbacks(Element*); + void mediaVolumeDidChange(); + + void setShouldCreateRenderers(bool); + bool shouldCreateRenderers(); + + void setDecoder(PassRefPtr<TextResourceDecoder>); + TextResourceDecoder* decoder() const { return m_decoder.get(); } + + String displayStringModifiedByEncoding(const String&) const; + PassRefPtr<StringImpl> displayStringModifiedByEncoding(PassRefPtr<StringImpl>) const; + void displayBufferModifiedByEncoding(UChar* buffer, unsigned len) const; + + // Quirk for the benefit of Apple's Dictionary application. + void setFrameElementsShouldIgnoreScrolling(bool ignore) { m_frameElementsShouldIgnoreScrolling = ignore; } + bool frameElementsShouldIgnoreScrolling() const { return m_frameElementsShouldIgnoreScrolling; } + +#if ENABLE(DASHBOARD_SUPPORT) + void setDashboardRegionsDirty(bool f) { m_dashboardRegionsDirty = f; } + bool dashboardRegionsDirty() const { return m_dashboardRegionsDirty; } + bool hasDashboardRegions () const { return m_hasDashboardRegions; } + void setHasDashboardRegions(bool f) { m_hasDashboardRegions = f; } + const Vector<DashboardRegionValue>& dashboardRegions() const; + void setDashboardRegions(const Vector<DashboardRegionValue>&); +#endif + + virtual void removeAllEventListeners(); + + CheckedRadioButtons& checkedRadioButtons() { return m_checkedRadioButtons; } + +#if ENABLE(SVG) + const SVGDocumentExtensions* svgExtensions(); + SVGDocumentExtensions* accessSVGExtensions(); +#endif + + void initSecurityContext(); + + // Explicitly override the security origin for this document. + // Note: It is dangerous to change the security origin of a document + // that already contains content. + void setSecurityOrigin(SecurityOrigin*); + + bool processingLoadEvent() const { return m_processingLoadEvent; } + +#if ENABLE(DATABASE) + void addOpenDatabase(Database*); + void removeOpenDatabase(Database*); + DatabaseThread* databaseThread(); // Creates the thread as needed, but not if it has been already terminated. + void setHasOpenDatabases() { m_hasOpenDatabases = true; } + bool hasOpenDatabases() { return m_hasOpenDatabases; } + void stopDatabases(); +#endif + + void setUsingGeolocation(bool f) { m_usingGeolocation = f; } + bool usingGeolocation() const { return m_usingGeolocation; }; + +#if ENABLE(WML) + void setContainsWMLContent(bool value) { m_containsWMLContent = value; } + bool containsWMLContent() const { return m_containsWMLContent; } + + void resetWMLPageState(); + void initializeWMLPageState(); +#endif + protected: Document(Frame*, bool isXHTML); - void setStyleSelector(CSSStyleSelector* styleSelector) { m_styleSelector = styleSelector; } + void setStyleSelector(CSSStyleSelector* styleSelector) { m_styleSelector = styleSelector; } + + void clearXMLVersion() { m_xmlVersion = String(); } #if ENABLE(TOUCH_EVENTS) // Android public: @@ -826,16 +931,36 @@ private: #endif // ENABLE(TOUCH_EVENTS) private: + virtual bool isDocument() const { return true; } + virtual void removedLastRef(); + virtual void determineParseMode() { } + + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + + virtual String nodeName() const; + virtual NodeType nodeType() const; + virtual bool childTypeAllowed(NodeType); + virtual PassRefPtr<Node> cloneNode(bool deep); + virtual bool canReplaceChild(Node* newChild, Node* oldChild); + virtual void refScriptExecutionContext() { ref(); } virtual void derefScriptExecutionContext() { deref(); } virtual const KURL& virtualURL() const; // Same as url(), but needed for ScriptExecutionContext to implement it without a performance loss for direct calls. virtual KURL virtualCompleteURL(const String&) const; // Same as completeURL() for the same reason as above. + void initDNSPrefetch(); + String encoding() const; void executeScriptSoonTimerFired(Timer<Document>*); + void updateTitle(); + void updateFocusAppearanceTimerFired(Timer<Document>*); + void updateBaseURL(); + + void cacheDocumentElement() const; + CSSStyleSelector* m_styleSelector; bool m_didCalculateStyleSelector; @@ -863,11 +988,6 @@ private: RefPtr<DocumentType> m_docType; mutable RefPtr<DOMImplementation> m_implementation; - RefPtr<StyleSheet> m_sheet; -#if FRAME_LOADS_USER_STYLESHEET - String m_usersheet; -#endif - // Track the number of currently loading top-level stylesheets. Sheets // loaded using the @import directive are not included in this count. // We use this count of pending sheets to detect when we can begin attaching @@ -887,6 +1007,9 @@ private: RefPtr<CSSStyleSheet> m_elemSheet; RefPtr<CSSStyleSheet> m_mappedElementSheet; + RefPtr<CSSStyleSheet> m_pageUserSheet; + mutable OwnPtr<Vector<RefPtr<CSSStyleSheet> > > m_pageGroupUserSheets; + mutable bool m_pageGroupUserSheetCacheValid; bool m_printing; @@ -963,7 +1086,7 @@ private: Timer<Document> m_executeScriptSoonTimer; #if ENABLE(XSLT) - void* m_transformSource; + OwnPtr<TransformSource> m_transformSource; RefPtr<Document> m_transformSourceDocument; #endif @@ -974,8 +1097,6 @@ private: typedef HashMap<AtomicStringImpl*, HTMLMapElement*> ImageMapsByName; ImageMapsByName m_imageMapsByName; - HashSet<Node*> m_disconnectedNodesWithEventListeners; - int m_docID; // A unique document identifier used for things like document-specific mapped attributes. String m_xmlEncoding; @@ -988,96 +1109,6 @@ private: bool m_shouldProcessNoScriptElement; #endif -public: - bool inPageCache() const { return m_inPageCache; } - void setInPageCache(bool flag); - - // Elements can register themselves for the "documentWillBecomeInactive()" and - // "documentDidBecomeActive()" callbacks - void registerForDocumentActivationCallbacks(Element*); - void unregisterForDocumentActivationCallbacks(Element*); - void documentWillBecomeInactive(); - void documentDidBecomeActive(); - - void registerForMediaVolumeCallbacks(Element*); - void unregisterForMediaVolumeCallbacks(Element*); - void mediaVolumeDidChange(); - - void setShouldCreateRenderers(bool); - bool shouldCreateRenderers(); - - void setDecoder(PassRefPtr<TextResourceDecoder>); - TextResourceDecoder* decoder() const { return m_decoder.get(); } - - String displayStringModifiedByEncoding(const String&) const; - PassRefPtr<StringImpl> displayStringModifiedByEncoding(PassRefPtr<StringImpl>) const; - void displayBufferModifiedByEncoding(UChar* buffer, unsigned len) const; - - // Quirk for the benefit of Apple's Dictionary application. - void setFrameElementsShouldIgnoreScrolling(bool ignore) { m_frameElementsShouldIgnoreScrolling = ignore; } - bool frameElementsShouldIgnoreScrolling() const { return m_frameElementsShouldIgnoreScrolling; } - -#if ENABLE(DASHBOARD_SUPPORT) - void setDashboardRegionsDirty(bool f) { m_dashboardRegionsDirty = f; } - bool dashboardRegionsDirty() const { return m_dashboardRegionsDirty; } - bool hasDashboardRegions () const { return m_hasDashboardRegions; } - void setHasDashboardRegions(bool f) { m_hasDashboardRegions = f; } - const Vector<DashboardRegionValue>& dashboardRegions() const; - void setDashboardRegions(const Vector<DashboardRegionValue>&); -#endif - - void removeAllEventListeners(); - - void registerDisconnectedNodeWithEventListeners(Node*); - void unregisterDisconnectedNodeWithEventListeners(Node*); - - CheckedRadioButtons& checkedRadioButtons() { return m_checkedRadioButtons; } - -#if ENABLE(SVG) - const SVGDocumentExtensions* svgExtensions(); - SVGDocumentExtensions* accessSVGExtensions(); -#endif - - void initSecurityContext(); - - // Explicitly override the security origin for this document. - // Note: It is dangerous to change the security origin of a document - // that already contains content. - void setSecurityOrigin(SecurityOrigin*); - - bool processingLoadEvent() const { return m_processingLoadEvent; } - -#if ENABLE(DATABASE) - void addOpenDatabase(Database*); - void removeOpenDatabase(Database*); - DatabaseThread* databaseThread(); // Creates the thread as needed, but not if it has been already terminated. - void setHasOpenDatabases() { m_hasOpenDatabases = true; } - bool hasOpenDatabases() { return m_hasOpenDatabases; } - void stopDatabases(); -#endif - - void setUsingGeolocation(bool f) { m_usingGeolocation = f; } - bool usingGeolocation() const { return m_usingGeolocation; }; - -#if ENABLE(WML) - void setContainsWMLContent(bool value) { m_containsWMLContent = value; } - bool containsWMLContent() const { return m_containsWMLContent; } - - void resetWMLPageState(); - void initializeWMLPageState(); -#endif - -protected: - void clearXMLVersion() { m_xmlVersion = String(); } - -private: - void updateTitle(); - void removeAllDisconnectedNodeEventListeners(); - void updateFocusAppearanceTimerFired(Timer<Document>*); - void updateBaseURL(); - - void cacheDocumentElement() const; - RenderObject* m_savedRenderer; int m_secureForms; @@ -1131,10 +1162,6 @@ private: unsigned m_numNodeListCaches; -public: - typedef HashMap<WebCore::Node*, JSNode*> JSWrapperCache; - JSWrapperCache& wrapperCache() { return m_wrapperCache; } -private: JSWrapperCache m_wrapperCache; #if ENABLE(DATABASE) @@ -1163,9 +1190,15 @@ inline bool Document::hasElementWithId(AtomicStringImpl* id) const inline bool Node::isDocumentNode() const { - return this == m_document.get(); + 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 cd3ec77..e7a43c7 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] DOMString tagName) + [ReturnsNew] Element createElement(in [ConvertNullToNullString, HintAtomic] 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 [V8Custom=HintAtomic] DOMString elementId); + Element getElementById(in [HintAtomic] DOMString elementId); // DOM Level 3 Core @@ -155,7 +155,8 @@ module core { attribute [ConvertNullToNullString] DOMString title; readonly attribute DOMString referrer; #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT - attribute [ConvertNullToNullString] DOMString domain; + attribute [ConvertNullToNullString] DOMString domain + setter raises (DOMException); #else readonly attribute DOMString domain; #endif @@ -191,6 +192,9 @@ module core { readonly attribute [ConvertNullStringTo=Undefined] DOMString readyState; Element elementFromPoint(in long x, in long y); +#if !defined(LANGUAGE_COM) || !LANGUAGE_COM + Range caretRangeFromPoint(in long x, in long y); +#endif // Mozilla extensions #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT @@ -264,6 +268,7 @@ module core { attribute [DontEnum] EventListener onerror; attribute [DontEnum] EventListener onfocus; attribute [DontEnum] EventListener oninput; + attribute [DontEnum] EventListener oninvalid; attribute [DontEnum] EventListener onkeydown; attribute [DontEnum] EventListener onkeypress; attribute [DontEnum] EventListener onkeyup; @@ -291,7 +296,6 @@ module core { // attribute [DontEnum] EventListener onended; // attribute [DontEnum] EventListener onformchange; // attribute [DontEnum] EventListener onforminput; - // attribute [DontEnum] EventListener oninvalid; // attribute [DontEnum] EventListener onloadeddata; // attribute [DontEnum] EventListener onloadedmetadata; // attribute [DontEnum] EventListener onloadstart; diff --git a/WebCore/dom/DocumentFragment.cpp b/WebCore/dom/DocumentFragment.cpp index 7a6174f..3663e99 100644 --- a/WebCore/dom/DocumentFragment.cpp +++ b/WebCore/dom/DocumentFragment.cpp @@ -1,10 +1,8 @@ -/** - * 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) - * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,13 +21,18 @@ */ #include "config.h" - #include "DocumentFragment.h" namespace WebCore { -DocumentFragment::DocumentFragment(Document *doc) : ContainerNode(doc) +inline DocumentFragment::DocumentFragment(Document* document) + : ContainerNode(document) +{ +} + +PassRefPtr<DocumentFragment> DocumentFragment::create(Document* document) { + return adoptRef(new DocumentFragment(document)); } String DocumentFragment::nodeName() const @@ -42,7 +45,6 @@ Node::NodeType DocumentFragment::nodeType() const return DOCUMENT_FRAGMENT_NODE; } -// DOM Section 1.1.1 bool DocumentFragment::childTypeAllowed(NodeType type) { switch (type) { @@ -60,7 +62,7 @@ bool DocumentFragment::childTypeAllowed(NodeType type) PassRefPtr<Node> DocumentFragment::cloneNode(bool deep) { - RefPtr<DocumentFragment> clone = new DocumentFragment(document()); + RefPtr<DocumentFragment> clone = create(document()); if (deep) cloneChildNodes(clone.get()); return clone.release(); diff --git a/WebCore/dom/DocumentFragment.h b/WebCore/dom/DocumentFragment.h index 46d8ecd..e624ee4 100644 --- a/WebCore/dom/DocumentFragment.h +++ b/WebCore/dom/DocumentFragment.h @@ -1,10 +1,8 @@ /* - * 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) - * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -32,6 +30,9 @@ namespace WebCore { class DocumentFragment : public ContainerNode { public: + static PassRefPtr<DocumentFragment> create(Document*); + +private: DocumentFragment(Document*); virtual String nodeName() const; diff --git a/WebCore/dom/DocumentType.cpp b/WebCore/dom/DocumentType.cpp index 885a65b..b8185e7 100644 --- a/WebCore/dom/DocumentType.cpp +++ b/WebCore/dom/DocumentType.cpp @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -29,11 +29,11 @@ namespace WebCore { -DocumentType::DocumentType(Document* document, const String& n, const String& p, const String& s) - : Node(document) - , m_name(n) - , m_publicId(p) - , m_systemId(s) +DocumentType::DocumentType(Document* document, const String& name, const String& publicId, const String& systemId) + : Node(document, CreateOther) + , m_name(name) + , m_publicId(publicId) + , m_systemId(systemId) { } @@ -54,7 +54,7 @@ Node::NodeType DocumentType::nodeType() const PassRefPtr<Node> DocumentType::cloneNode(bool /*deep*/) { - return new DocumentType(document(), m_name, m_publicId, m_systemId); + return create(document(), m_name, m_publicId, m_systemId); } void DocumentType::insertedIntoDocument() diff --git a/WebCore/dom/DocumentType.h b/WebCore/dom/DocumentType.h index 9fd3c6e..4f89d01 100644 --- a/WebCore/dom/DocumentType.h +++ b/WebCore/dom/DocumentType.h @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -34,7 +34,7 @@ class DocumentType : public Node { public: static PassRefPtr<DocumentType> create(Document* document, const String& name, const String& publicId, const String& systemId) { - return new DocumentType(document, name, publicId, systemId); + return adoptRef(new DocumentType(document, name, publicId, systemId)); } NamedNodeMap* entities() const { return m_entities.get(); } diff --git a/WebCore/dom/EditingText.cpp b/WebCore/dom/EditingText.cpp index 40cf97d..b36931a 100644 --- a/WebCore/dom/EditingText.cpp +++ b/WebCore/dom/EditingText.cpp @@ -1,9 +1,5 @@ -/** - * 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) - * Copyright (C) 2003 Apple Computer, Inc. +/* + * Copyright (C) 2003, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -24,24 +20,19 @@ #include "config.h" #include "EditingText.h" -// FIXME: does this really require a class? Perhaps any Text node -// inside an editable element should have the "always create a renderer" -// behavior. +// FIXME: Does this really require a class? Perhaps instead any text node +// inside an editable element could have the "always create a renderer" behavior. namespace WebCore { -EditingText::EditingText(Document *impl, const String &text) - : Text(impl, text) -{ -} - -EditingText::EditingText(Document *impl) - : Text(impl) +inline EditingText::EditingText(Document* document, const String& data) + : Text(document, data) { } -EditingText::~EditingText() +PassRefPtr<EditingText> EditingText::create(Document* document, const String& data) { + return adoptRef(new EditingText(document, data)); } bool EditingText::rendererIsNeeded(RenderStyle*) diff --git a/WebCore/dom/EditingText.h b/WebCore/dom/EditingText.h index e114786..08223c2 100644 --- a/WebCore/dom/EditingText.h +++ b/WebCore/dom/EditingText.h @@ -1,9 +1,5 @@ /* - * 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) - * Copyright (C) 2003 Apple Computer, Inc. + * Copyright (C) 2003, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -31,11 +27,12 @@ namespace WebCore { class EditingText : public Text { public: - EditingText(Document *impl, const String &text); - EditingText(Document *impl); - virtual ~EditingText(); + static PassRefPtr<EditingText> create(Document*, const String&); +private: virtual bool rendererIsNeeded(RenderStyle *); + + EditingText(Document*, const String&); }; } // namespace WebCore diff --git a/WebCore/dom/Element.cpp b/WebCore/dom/Element.cpp index 1956be4..50ff033 100644 --- a/WebCore/dom/Element.cpp +++ b/WebCore/dom/Element.cpp @@ -28,6 +28,8 @@ #include "AXObjectCache.h" #include "Attr.h" +#include "CSSParser.h" +#include "CSSSelectorList.h" #include "CSSStyleSelector.h" #include "CString.h" #include "ClientRect.h" @@ -57,12 +59,17 @@ namespace WebCore { using namespace HTMLNames; using namespace XMLNames; -Element::Element(const QualifiedName& tagName, Document* doc) - : ContainerNode(doc, true) +Element::Element(const QualifiedName& tagName, Document* document, ConstructionType type) + : ContainerNode(document, type) , m_tagName(tagName) { } +PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new Element(tagName, document, CreateElement)); +} + Element::~Element() { if (namedAttrMap) @@ -275,42 +282,6 @@ static int adjustForLocalZoom(int value, RenderObject* renderer) return static_cast<int>(value / zoomFactor); } -static int adjustForAbsoluteZoom(int value, RenderObject* renderer) -{ - float zoomFactor = renderer->style()->effectiveZoom(); - if (zoomFactor == 1) - return value; - // Needed because computeLengthInt truncates (rather than rounds) when scaling up. - if (zoomFactor > 1) - value++; - return static_cast<int>(value / zoomFactor); -} - -static FloatPoint adjustFloatPointForAbsoluteZoom(const FloatPoint& point, RenderObject* renderer) -{ - // The result here is in floats, so we don't need the truncation hack from the integer version above. - float zoomFactor = renderer->style()->effectiveZoom(); - if (zoomFactor == 1) - return point; - return FloatPoint(point.x() / zoomFactor, point.y() / zoomFactor); -} - -static void adjustFloatQuadForAbsoluteZoom(FloatQuad& quad, RenderObject* renderer) -{ - quad.setP1(adjustFloatPointForAbsoluteZoom(quad.p1(), renderer)); - quad.setP2(adjustFloatPointForAbsoluteZoom(quad.p2(), renderer)); - quad.setP3(adjustFloatPointForAbsoluteZoom(quad.p3(), renderer)); - quad.setP4(adjustFloatPointForAbsoluteZoom(quad.p4(), renderer)); -} - -static void adjustIntRectForAbsoluteZoom(IntRect& rect, RenderObject* renderer) -{ - rect.setX(adjustForAbsoluteZoom(rect.x(), renderer)); - rect.setY(adjustForAbsoluteZoom(rect.y(), renderer)); - rect.setWidth(adjustForAbsoluteZoom(rect.width(), renderer)); - rect.setHeight(adjustForAbsoluteZoom(rect.height(), renderer)); -} - int Element::offsetLeft() { document()->updateLayoutIgnorePendingStylesheets(); @@ -597,16 +568,20 @@ void Element::attributeChanged(Attribute* attr, bool) void Element::updateAfterAttributeChanged(Attribute* attr) { - if (!document()->axObjectCache()->accessibilityEnabled()) + AXObjectCache* axObjectCache = document()->axObjectCache(); + if (!axObjectCache->accessibilityEnabled()) return; const QualifiedName& attrName = attr->name(); if (attrName == aria_activedescendantAttr) { // any change to aria-activedescendant attribute triggers accessibility focus change, but document focus remains intact - document()->axObjectCache()->handleActiveDescendantChanged(renderer()); + axObjectCache->handleActiveDescendantChanged(renderer()); } else if (attrName == roleAttr) { // the role attribute can change at any time, and the AccessibilityObject must pick up these changes - document()->axObjectCache()->handleAriaRoleChanged(renderer()); + axObjectCache->handleAriaRoleChanged(renderer()); + } else if (attrName == aria_valuenowAttr) { + // If the valuenow attribute changes, AX clients need to be notified. + axObjectCache->postNotification(renderer(), AXObjectCache::AXValueChanged, true); } } @@ -677,7 +652,7 @@ void Element::setPrefix(const AtomicString &_prefix, ExceptionCode& ec) KURL Element::baseURI() const { - KURL base(getAttribute(baseAttr)); + KURL base(KURL(), getAttribute(baseAttr)); if (!base.protocol().isEmpty()) return base; @@ -804,7 +779,8 @@ bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderS void Element::recalcStyle(StyleChange change) { - RenderStyle* currentStyle = renderStyle(); + // Ref currentStyle in case it would otherwise be deleted when setRenderStyle() is called. + RefPtr<RenderStyle> currentStyle(renderStyle()); bool hasParentStyle = parentNode() ? parentNode()->renderStyle() : false; bool hasPositionalRules = needsStyleRecalc() && currentStyle && currentStyle->childrenAffectedByPositionalRules(); bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules(); @@ -820,7 +796,7 @@ void Element::recalcStyle(StyleChange change) } if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) { RefPtr<RenderStyle> newStyle = document()->styleSelector()->styleForElement(this); - StyleChange ch = diff(currentStyle, newStyle.get()); + StyleChange ch = diff(currentStyle.get(), newStyle.get()); if (ch == Detach || !currentStyle) { if (attached()) detach(); @@ -852,9 +828,9 @@ void Element::recalcStyle(StyleChange change) newStyle->setChildrenAffectedByDirectAdjacentRules(); } - if (ch != NoChange || pseudoStyleCacheIsInvalid(currentStyle, newStyle.get())) { + if (ch != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get())) { setRenderStyle(newStyle); - } else if (needsStyleRecalc() && (styleChangeType() != AnimationStyleChange) && (document()->usesSiblingRules() || document()->usesDescendantRules())) { + } else if (needsStyleRecalc() && (styleChangeType() != SyntheticStyleChange) && (document()->usesSiblingRules() || document()->usesDescendantRules())) { // Although no change occurred, we use the new style so that the cousin style sharing code won't get // fooled into believing this style is the same. This is only necessary if the document actually uses // sibling/descendant rules, since otherwise it isn't possible for ancestor styles to affect sharing of @@ -863,7 +839,7 @@ void Element::recalcStyle(StyleChange change) renderer()->setStyleInternal(newStyle.get()); else setRenderStyle(newStyle); - } else if (styleChangeType() == AnimationStyleChange) + } else if (styleChangeType() == SyntheticStyleChange) setRenderStyle(newStyle); if (change != Force) { @@ -1215,14 +1191,24 @@ void Element::focus(bool restorePreviousSelection) if (doc->focusedNode() == this) return; - doc->updateLayoutIgnorePendingStylesheets(); - if (!supportsFocus()) return; - + + // If the stylesheets have already been loaded we can reliably check isFocusable. + // If not, we continue and set the focused node on the focus controller below so + // that it can be updated soon after attach. + if (doc->haveStylesheetsLoaded()) { + doc->updateLayoutIgnorePendingStylesheets(); + if (!isFocusable()) + return; + } + if (Page* page = doc->page()) page->focusController()->setFocusedNode(this, doc->frame()); + // Setting the focused node above might have invalidated the layout due to scripts. + doc->updateLayoutIgnorePendingStylesheets(); + if (!isFocusable()) { ensureRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(true); return; @@ -1386,6 +1372,39 @@ unsigned Element::childElementCount() const return count; } +bool Element::webkitMatchesSelector(const String& selector, ExceptionCode& ec) +{ + if (selector.isEmpty()) { + ec = SYNTAX_ERR; + return false; + } + + bool strictParsing = !document()->inCompatMode(); + CSSParser p(strictParsing); + + CSSSelectorList selectorList; + p.parseSelector(selector, document(), selectorList); + + if (!selectorList.first()) { + ec = SYNTAX_ERR; + return false; + } + + // Throw a NAMESPACE_ERR if the selector includes any namespace prefixes. + if (selectorList.selectorsNeedNamespaceResolution()) { + ec = NAMESPACE_ERR; + return false; + } + + CSSStyleSelector::SelectorChecker selectorChecker(document(), strictParsing); + for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) { + if (selectorChecker.checkSelector(selector, this)) + return true; + } + + return false; +} + KURL Element::getURLAttribute(const QualifiedName& name) const { #ifndef NDEBUG diff --git a/WebCore/dom/Element.h b/WebCore/dom/Element.h index 223c26a..d27976a 100644 --- a/WebCore/dom/Element.h +++ b/WebCore/dom/Element.h @@ -3,7 +3,7 @@ * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Peter Kelly (pmk@post.com) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -41,8 +41,53 @@ class IntSize; class Element : public ContainerNode { public: - Element(const QualifiedName&, Document*); - ~Element(); + static PassRefPtr<Element> create(const QualifiedName&, Document*); + virtual ~Element(); + + DEFINE_ATTRIBUTE_EVENT_LISTENER(abort); + DEFINE_ATTRIBUTE_EVENT_LISTENER(change); + DEFINE_ATTRIBUTE_EVENT_LISTENER(click); + DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu); + DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick); + DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter); + DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover); + DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave); + DEFINE_ATTRIBUTE_EVENT_LISTENER(drop); + DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart); + DEFINE_ATTRIBUTE_EVENT_LISTENER(drag); + DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend); + DEFINE_ATTRIBUTE_EVENT_LISTENER(input); + DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid); + DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown); + DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress); + DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup); + DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown); + DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove); + DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout); + DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover); + DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup); + DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel); + DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll); + DEFINE_ATTRIBUTE_EVENT_LISTENER(select); + DEFINE_ATTRIBUTE_EVENT_LISTENER(submit); + + // These 4 attribute event handler attributes are overrided by HTMLBodyElement + // and HTMLFrameSetElement to forward to the DOMWindow. + DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur); + DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error); + DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus); + DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load); + + // WebKit extensions + DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut); + DEFINE_ATTRIBUTE_EVENT_LISTENER(cut); + DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy); + DEFINE_ATTRIBUTE_EVENT_LISTENER(copy); + DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste); + DEFINE_ATTRIBUTE_EVENT_LISTENER(paste); + DEFINE_ATTRIBUTE_EVENT_LISTENER(reset); + DEFINE_ATTRIBUTE_EVENT_LISTENER(search); + DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart); const AtomicString& getIDAttribute() const; bool hasAttribute(const QualifiedName&) const; @@ -64,7 +109,6 @@ public: void scrollIntoView(bool alignToTop = true); void scrollIntoViewIfNeeded(bool centerIfNeeded = true); - void scrollByUnits(int units, ScrollGranularity); void scrollByLines(int lines); void scrollByPages(int pages); @@ -108,17 +152,11 @@ public: const AtomicString& localName() const { return m_tagName.localName(); } const AtomicString& prefix() const { return m_tagName.prefix(); } - virtual void setPrefix(const AtomicString&, ExceptionCode&); const AtomicString& namespaceURI() const { return m_tagName.namespaceURI(); } virtual KURL baseURI() const; - // DOM methods overridden from parent classes - virtual NodeType nodeType() const; virtual String nodeName() const; - virtual void insertedIntoDocument(); - virtual void removedFromDocument(); - virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); PassRefPtr<Element> cloneElementWithChildren(); PassRefPtr<Element> cloneElementWithoutChildren(); @@ -136,13 +174,9 @@ public: // This method is called whenever an attribute is added, changed or removed. virtual void attributeChanged(Attribute*, bool preserveDecls = false); - // The implementation of Element::attributeChanged() calls the following two functions. - // They are separated to allow a different flow of control in StyledElement::attributeChanged(). - void recalcStyleIfNeededAfterAttributeChanged(Attribute*); - void updateAfterAttributeChanged(Attribute*); - // not part of the DOM void setAttributeMap(PassRefPtr<NamedNodeMap>); + NamedNodeMap* attributeMap() const { return namedAttrMap.get(); } virtual void copyNonAttributeProperties(const Element* /*source*/) { } @@ -153,10 +187,6 @@ public: virtual RenderStyle* computedStyle(); - virtual bool childTypeAllowed(NodeType); - - virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value); - void dispatchAttrRemovalEvent(Attribute*); void dispatchAttrAdditionEvent(Attribute*); @@ -166,16 +196,11 @@ public: KURL getURLAttribute(const QualifiedName&) const; virtual const QualifiedName& imageSourceAttributeName() const; virtual String target() const { return String(); } + virtual void focus(bool restorePreviousSelection = true); virtual void updateFocusAppearance(bool restorePreviousSelection); void blur(); -#ifndef NDEBUG - virtual void formatForDebugger(char* buffer, unsigned length) const; -#endif - - bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle); - String innerText() const; String outerText() const; @@ -206,13 +231,17 @@ public: Element* nextElementSibling() const; unsigned childElementCount() const; - // FormControlElement API + bool webkitMatchesSelector(const String& selectors, ExceptionCode&); + virtual bool isFormControlElement() const { return false; } virtual bool isEnabledFormControl() const { return true; } virtual bool isReadOnlyFormControl() const { return false; } virtual bool isTextFormControl() const { return false; } virtual bool isOptionalFormControl() const { return false; } virtual bool isRequiredFormControl() const { return false; } + virtual bool isDefaultButtonForForm() const { return false; } + virtual bool willValidate() const { return false; } + virtual bool isValidFormControlElement() { return false; } virtual bool formControlValueMatchesRenderer() const { return false; } virtual void setFormControlValueMatchesRenderer(bool) { } @@ -225,13 +254,39 @@ public: virtual void dispatchFormControlChangeEvent() { } +protected: + Element(const QualifiedName&, Document*, ConstructionType); + + virtual void insertedIntoDocument(); + virtual void removedFromDocument(); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + + // The implementation of Element::attributeChanged() calls the following two functions. + // They are separated to allow a different flow of control in StyledElement::attributeChanged(). + void recalcStyleIfNeededAfterAttributeChanged(Attribute*); + void updateAfterAttributeChanged(Attribute*); + private: + void scrollByUnits(int units, ScrollGranularity); + + virtual void setPrefix(const AtomicString&, ExceptionCode&); + virtual NodeType nodeType() const; + virtual bool childTypeAllowed(NodeType); + + virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value); + +#ifndef NDEBUG + virtual void formatForDebugger(char* buffer, unsigned length) const; +#endif + + bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle); + virtual void createAttributeMap() const; - virtual void updateStyleAttribute() const {} + virtual void updateStyleAttribute() const { } #if ENABLE(SVG) - virtual void updateAnimatedSVGAttribute(const String&) const {} + virtual void updateAnimatedSVGAttribute(const String&) const { } #endif void updateFocusAppearanceSoonAfterAttach(); @@ -248,10 +303,10 @@ private: QualifiedName m_tagName; virtual NodeRareData* createRareData(); -protected: ElementRareData* rareData() const; ElementRareData* ensureRareData(); +protected: mutable RefPtr<NamedNodeMap> namedAttrMap; }; diff --git a/WebCore/dom/Element.idl b/WebCore/dom/Element.idl index e8988e1..c24ef65 100644 --- a/WebCore/dom/Element.idl +++ b/WebCore/dom/Element.idl @@ -21,6 +21,7 @@ module core { interface [ + CustomMarkFunction, GenerateConstructor, GenerateNativeConverter, InlineGetOwnPropertySlot, @@ -110,6 +111,10 @@ module core { raises(DOMException); #if !defined(LANGUAGE_COM) || !LANGUAGE_COM + // WebKit extension, pending specification. + boolean webkitMatchesSelector(in DOMString selectors) + raises(DOMException); + // ElementTraversal API readonly attribute Element firstElementChild; readonly attribute Element lastElementChild; @@ -148,6 +153,7 @@ module core { attribute [DontEnum] EventListener onerror; attribute [DontEnum] EventListener onfocus; attribute [DontEnum] EventListener oninput; + attribute [DontEnum] EventListener oninvalid; attribute [DontEnum] EventListener onkeydown; attribute [DontEnum] EventListener onkeypress; attribute [DontEnum] EventListener onkeyup; @@ -175,7 +181,6 @@ module core { // attribute [DontEnum] EventListener onended; // attribute [DontEnum] EventListener onformchange; // attribute [DontEnum] EventListener onforminput; - // attribute [DontEnum] EventListener oninvalid; // attribute [DontEnum] EventListener onloadeddata; // attribute [DontEnum] EventListener onloadedmetadata; // attribute [DontEnum] EventListener onloadstart; diff --git a/WebCore/dom/EntityReference.cpp b/WebCore/dom/EntityReference.cpp index 012605c..c4c292a 100644 --- a/WebCore/dom/EntityReference.cpp +++ b/WebCore/dom/EntityReference.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2000 Peter Kelly (pmk@post.com) - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,12 +23,17 @@ namespace WebCore { -EntityReference::EntityReference(Document* document, const String& entityName) +inline EntityReference::EntityReference(Document* document, const String& entityName) : ContainerNode(document) , m_entityName(entityName) { } +PassRefPtr<EntityReference> EntityReference::create(Document* document, const String& entityName) +{ + return adoptRef(new EntityReference(document, entityName)); +} + String EntityReference::nodeName() const { return m_entityName; @@ -41,7 +46,7 @@ Node::NodeType EntityReference::nodeType() const PassRefPtr<Node> EntityReference::cloneNode(bool) { - return new EntityReference(document(), m_entityName); + return create(document(), m_entityName); } } // namespace diff --git a/WebCore/dom/EntityReference.h b/WebCore/dom/EntityReference.h index 4767a5e..7a6f6c3 100644 --- a/WebCore/dom/EntityReference.h +++ b/WebCore/dom/EntityReference.h @@ -28,13 +28,15 @@ namespace WebCore { class EntityReference : public ContainerNode { public: + static PassRefPtr<EntityReference> create(Document*, const String& entityName); + +private: EntityReference(Document*, const String& entityName); virtual String nodeName() const; virtual NodeType nodeType() const; virtual PassRefPtr<Node> cloneNode(bool deep); -private: String m_entityName; }; diff --git a/WebCore/dom/Event.cpp b/WebCore/dom/Event.cpp index 4ad090b..cae4122 100644 --- a/WebCore/dom/Event.cpp +++ b/WebCore/dom/Event.cpp @@ -124,6 +124,11 @@ bool Event::isOverflowEvent() const return false; } +bool Event::isPageTransitionEvent() const +{ + return false; +} + bool Event::isProgressEvent() const { return false; @@ -171,7 +176,7 @@ bool Event::isErrorEvent() const return false; } #endif - + bool Event::storesResultAsString() const { return false; diff --git a/WebCore/dom/Event.h b/WebCore/dom/Event.h index b6a9c8f..30e5d27 100644 --- a/WebCore/dom/Event.h +++ b/WebCore/dom/Event.h @@ -109,6 +109,7 @@ namespace WebCore { virtual bool isWheelEvent() const; virtual bool isBeforeTextInsertedEvent() const; virtual bool isOverflowEvent() const; + virtual bool isPageTransitionEvent() const; virtual bool isProgressEvent() const; virtual bool isXMLHttpRequestProgressEvent() const; virtual bool isWebKitAnimationEvent() const; @@ -125,7 +126,7 @@ namespace WebCore { #if ENABLE(WORKERS) virtual bool isErrorEvent() const; #endif - + bool propagationStopped() const { return m_propagationStopped; } bool defaultPrevented() const { return m_defaultPrevented; } diff --git a/WebCore/dom/EventListener.h b/WebCore/dom/EventListener.h index 7c4812f..da9d179 100644 --- a/WebCore/dom/EventListener.h +++ b/WebCore/dom/EventListener.h @@ -31,31 +31,46 @@ namespace JSC { namespace WebCore { + class ScriptExecutionContext; class Event; class EventListener : public RefCounted<EventListener> { public: + enum Type { JSEventListenerType, + ImageEventListenerType, + InspectorDOMAgentType, + InspectorDOMStorageResourceType, + ObjCEventListenerType, + ConditionEventListenerType, + GeolocationEventListenerType }; + virtual ~EventListener() { } - virtual void handleEvent(Event*, bool isWindowEvent = false) = 0; + virtual bool operator==(const EventListener&) = 0; + virtual void handleEvent(ScriptExecutionContext*, Event*) = 0; // Return true to indicate that the error is handled. - virtual bool reportError(const String& /*message*/, const String& /*url*/, int /*lineNumber*/) { return false; } + virtual bool reportError(ScriptExecutionContext*, const String& /*message*/, const String& /*url*/, int /*lineNumber*/) { return false; } virtual bool wasCreatedFromMarkup() const { return false; } #if USE(JSC) - virtual JSC::JSObject* jsFunction() const { return 0; } + virtual JSC::JSObject* jsFunction(ScriptExecutionContext*) const { return 0; } virtual void markJSFunction(JSC::MarkStack&) { } #endif bool isAttribute() const { return virtualisAttribute(); } + Type type() const { return m_type; } + + protected: + EventListener(Type type) + : m_type(type) + { + } private: virtual bool virtualisAttribute() const { return false; } + + Type m_type; }; -#if USE(JSC) - inline void markIfNotNull(JSC::MarkStack& markStack, EventListener* listener) { if (listener) listener->markJSFunction(markStack); } -#endif - } #endif diff --git a/WebCore/dom/EventListener.idl b/WebCore/dom/EventListener.idl index 9dc2e0a..1edf52f 100644 --- a/WebCore/dom/EventListener.idl +++ b/WebCore/dom/EventListener.idl @@ -24,8 +24,8 @@ module events { interface [ NoStaticTables, ObjCProtocol, + PureInterface, InterfaceUUID=B04F2AE3-71E2-4ebe-ABFE-EF4938354082, - ImplementationUUID=DDFDD342-A78B-4f19-8F32-A5DF51B56E08 ] EventListener { void handleEvent(in Event evt); }; diff --git a/WebCore/dom/EventNames.h b/WebCore/dom/EventNames.h index d28b154..31c29fb 100644 --- a/WebCore/dom/EventNames.h +++ b/WebCore/dom/EventNames.h @@ -32,6 +32,7 @@ namespace WebCore { macro(abort) \ macro(beforecopy) \ macro(beforecut) \ + macro(beforeload) \ macro(beforepaste) \ macro(beforeunload) \ macro(blur) \ @@ -45,6 +46,7 @@ namespace WebCore { macro(copy) \ macro(cut) \ macro(dblclick) \ + macro(display) \ macro(downloading) \ macro(drag) \ macro(dragend) \ @@ -57,10 +59,12 @@ namespace WebCore { macro(focus) \ macro(hashchange) \ macro(input) \ + macro(invalid) \ macro(keydown) \ macro(keypress) \ macro(keyup) \ macro(load) \ + macro(loadend) \ macro(loadstart) \ macro(message) \ macro(mousedown) \ @@ -73,7 +77,10 @@ namespace WebCore { macro(obsolete) \ macro(offline) \ macro(online) \ + macro(open) \ macro(overflowchanged) \ + macro(pagehide) \ + macro(pageshow) \ macro(paste) \ macro(readystatechange) \ macro(reset) \ @@ -137,6 +144,8 @@ namespace WebCore { \ macro(webkitTransitionEnd) \ \ + macro(orientationchange) \ + \ // end of DOM_EVENT_NAMES_FOR_EACH class EventNames { diff --git a/WebCore/dom/EventTarget.cpp b/WebCore/dom/EventTarget.cpp index 7ba0584..ceb5221 100644 --- a/WebCore/dom/EventTarget.cpp +++ b/WebCore/dom/EventTarget.cpp @@ -34,16 +34,49 @@ #include "config.h" #include "EventTarget.h" +#include "Event.h" +#include "EventException.h" +#include <wtf/StdLibExtras.h> + +using namespace WTF; + namespace WebCore { #ifndef NDEBUG static int gEventDispatchForbidden = 0; -#endif + +void forbidEventDispatch() +{ + if (!isMainThread()) + return; + ++gEventDispatchForbidden; +} + +void allowEventDispatch() +{ + if (!isMainThread()) + return; + if (gEventDispatchForbidden > 0) + --gEventDispatchForbidden; +} + +bool eventDispatchForbidden() +{ + if (!isMainThread()) + return false; + return gEventDispatchForbidden > 0; +} +#endif // NDEBUG EventTarget::~EventTarget() { } +EventSource* EventTarget::toEventSource() +{ + return 0; +} + Node* EventTarget::toNode() { return 0; @@ -78,6 +111,13 @@ SVGElementInstance* EventTarget::toSVGElementInstance() } #endif +#if ENABLE(WEB_SOCKETS) +WebSocket* EventTarget::toWebSocket() +{ + return 0; +} +#endif + MessagePort* EventTarget::toMessagePort() { return 0; @@ -106,22 +146,160 @@ SharedWorkerContext* EventTarget::toSharedWorkerContext() } #endif -#ifndef NDEBUG -void forbidEventDispatch() +#if ENABLE(NOTIFICATIONS) +Notification* EventTarget::toNotification() { - ++gEventDispatchForbidden; + return 0; } +#endif -void allowEventDispatch() +bool EventTarget::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) { - if (gEventDispatchForbidden > 0) - --gEventDispatchForbidden; + EventTargetData* d = ensureEventTargetData(); + + pair<EventListenerMap::iterator, bool> result = d->eventListenerMap.add(eventType, EventListenerVector()); + EventListenerVector& entry = result.first->second; + + RegisteredEventListener registeredListener(listener, useCapture); + if (!result.second) { // pre-existing entry + if (entry.find(registeredListener) != notFound) // duplicate listener + return false; + } + + entry.append(registeredListener); + return true; } -bool eventDispatchForbidden() +bool EventTarget::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) { - return gEventDispatchForbidden > 0; + EventTargetData* d = eventTargetData(); + if (!d) + return false; + + EventListenerMap::iterator result = d->eventListenerMap.find(eventType); + if (result == d->eventListenerMap.end()) + return false; + EventListenerVector& entry = result->second; + + RegisteredEventListener registeredListener(listener, useCapture); + size_t index = entry.find(registeredListener); + if (index == notFound) + return false; + + entry.remove(index); + if (!entry.size()) + d->eventListenerMap.remove(result); + + // Notify firing events planning to invoke the listener at 'index' that + // they have one less listener to invoke. + for (size_t i = 0; i < d->firingEventEndIterators.size(); ++i) { + if (eventType == *d->firingEventEndIterators[i].eventType && index < *d->firingEventEndIterators[i].value) + --*d->firingEventEndIterators[i].value; + } + + return true; +} + +bool EventTarget::setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener) +{ + clearAttributeEventListener(eventType); + if (!listener) + return false; + return addEventListener(eventType, listener, false); +} + +EventListener* EventTarget::getAttributeEventListener(const AtomicString& eventType) +{ + const EventListenerVector& entry = getEventListeners(eventType); + for (size_t i = 0; i < entry.size(); ++i) { + if (entry[i].listener->isAttribute()) + return entry[i].listener.get(); + } + return 0; +} + +bool EventTarget::clearAttributeEventListener(const AtomicString& eventType) +{ + EventListener* listener = getAttributeEventListener(eventType); + if (!listener) + return false; + return removeEventListener(eventType, listener, false); +} + +bool EventTarget::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec) +{ + if (!event || event->type().isEmpty()) { + ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; + return false; + } + return dispatchEvent(event); +} + +bool EventTarget::dispatchEvent(PassRefPtr<Event> event) +{ + event->setTarget(this); + event->setCurrentTarget(this); + event->setEventPhase(Event::AT_TARGET); + return fireEventListeners(event.get()); +} + +bool EventTarget::fireEventListeners(Event* event) +{ + ASSERT(!eventDispatchForbidden()); + ASSERT(event && !event->type().isEmpty()); + + EventTargetData* d = eventTargetData(); + if (!d) + return true; + + EventListenerMap::iterator result = d->eventListenerMap.find(event->type()); + if (result == d->eventListenerMap.end()) + return false; + EventListenerVector& entry = result->second; + + RefPtr<EventTarget> protect = this; + + size_t end = entry.size(); + d->firingEventEndIterators.append(FiringEventEndIterator(&event->type(), &end)); + for (size_t i = 0; i < end; ++i) { + RegisteredEventListener& registeredListener = entry[i]; + if (event->eventPhase() == Event::CAPTURING_PHASE && !registeredListener.useCapture) + continue; + if (event->eventPhase() == Event::BUBBLING_PHASE && registeredListener.useCapture) + continue; + // To match Mozilla, the AT_TARGET phase fires both capturing and bubbling + // event listeners, even though that violates some versions of the DOM spec. + registeredListener.listener->handleEvent(scriptExecutionContext(), event); + } + d->firingEventEndIterators.removeLast(); + + return !event->defaultPrevented(); +} + +const EventListenerVector& EventTarget::getEventListeners(const AtomicString& eventType) +{ + DEFINE_STATIC_LOCAL(EventListenerVector, emptyVector, ()); + + EventTargetData* d = eventTargetData(); + if (!d) + return emptyVector; + EventListenerMap::iterator it = d->eventListenerMap.find(eventType); + if (it == d->eventListenerMap.end()) + return emptyVector; + return it->second; +} + +void EventTarget::removeAllEventListeners() +{ + EventTargetData* d = eventTargetData(); + if (!d) + return; + d->eventListenerMap.clear(); + + // Notify firing events planning to invoke the listener at 'index' that + // they have one less listener to invoke. + for (size_t i = 0; i < d->firingEventEndIterators.size(); ++i) + *d->firingEventEndIterators[i].value = 0; } -#endif // NDEBUG -} // end namespace +} // namespace WebCore diff --git a/WebCore/dom/EventTarget.h b/WebCore/dom/EventTarget.h index 2ededda..2d612e1 100644 --- a/WebCore/dom/EventTarget.h +++ b/WebCore/dom/EventTarget.h @@ -32,6 +32,9 @@ #ifndef EventTarget_h #define EventTarget_h +#include "AtomicStringHash.h" +#include "EventNames.h" +#include "RegisteredEventListener.h" #include <wtf/Forward.h> namespace WebCore { @@ -43,20 +46,47 @@ namespace WebCore { class DOMWindow; class Event; class EventListener; + class EventSource; class MessagePort; class Node; + class Notification; class SVGElementInstance; class ScriptExecutionContext; class SharedWorker; class SharedWorkerContext; + class WebSocket; class Worker; class XMLHttpRequest; class XMLHttpRequestUpload; typedef int ExceptionCode; + struct FiringEventEndIterator { + FiringEventEndIterator(const AtomicString* eventType, size_t* value) + : eventType(eventType) + , value(value) + { + } + + const AtomicString* eventType; + size_t* value; + }; + typedef Vector<FiringEventEndIterator, 1> FiringEventEndIteratorVector; + + typedef Vector<RegisteredEventListener, 1> EventListenerVector; + typedef HashMap<AtomicString, EventListenerVector> EventListenerMap; + + struct EventTargetData { + EventListenerMap eventListenerMap; + FiringEventEndIteratorVector firingEventEndIterators; + }; + class EventTarget { public: + void ref() { refEventTarget(); } + void deref() { derefEventTarget(); } + + virtual EventSource* toEventSource(); virtual MessagePort* toMessagePort(); virtual Node* toNode(); virtual DOMWindow* toDOMWindow(); @@ -72,44 +102,132 @@ namespace WebCore { virtual Worker* toWorker(); virtual DedicatedWorkerContext* toDedicatedWorkerContext(); #endif - #if ENABLE(SHARED_WORKERS) virtual SharedWorker* toSharedWorker(); virtual SharedWorkerContext* toSharedWorkerContext(); #endif +#if ENABLE(WEB_SOCKETS) + virtual WebSocket* toWebSocket(); +#endif + +#if ENABLE(NOTIFICATIONS) + virtual Notification* toNotification(); +#endif virtual ScriptExecutionContext* scriptExecutionContext() const = 0; - virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture) = 0; - virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture) = 0; - virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&) = 0; + virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture); + virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture); + virtual void removeAllEventListeners(); + virtual bool dispatchEvent(PassRefPtr<Event>); + bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&); // DOM API - void ref() { refEventTarget(); } - void deref() { derefEventTarget(); } + // Used for legacy "onEvent" attribute APIs. + bool setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener>); + bool clearAttributeEventListener(const AtomicString& eventType); + EventListener* getAttributeEventListener(const AtomicString& eventType); - // Handlers to do/undo actions on the target node before an event is dispatched to it and after the event - // has been dispatched. The data pointer is handed back by the preDispatch and passed to postDispatch. - virtual void* preDispatchEventHandler(Event*) { return 0; } - virtual void postDispatchEventHandler(Event*, void* /*dataFromPreDispatch*/) { } + bool hasEventListeners(); + bool hasEventListeners(const AtomicString& eventType); + const EventListenerVector& getEventListeners(const AtomicString& eventType); + + bool fireEventListeners(Event*); + bool isFiringEventListeners(); + +#if USE(JSC) + void markEventListeners(JSC::MarkStack&); + void invalidateEventListeners(); +#endif protected: virtual ~EventTarget(); + + virtual EventTargetData* eventTargetData() = 0; + virtual EventTargetData* ensureEventTargetData() = 0; private: virtual void refEventTarget() = 0; virtual void derefEventTarget() = 0; }; - void forbidEventDispatch(); - void allowEventDispatch(); + #define DEFINE_ATTRIBUTE_EVENT_LISTENER(attribute) \ + EventListener* on##attribute() { return getAttributeEventListener(eventNames().attribute##Event); } \ + void setOn##attribute(PassRefPtr<EventListener> listener) { setAttributeEventListener(eventNames().attribute##Event, listener); } \ + + #define DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(attribute) \ + virtual EventListener* on##attribute() { return getAttributeEventListener(eventNames().attribute##Event); } \ + virtual void setOn##attribute(PassRefPtr<EventListener> listener) { setAttributeEventListener(eventNames().attribute##Event, listener); } \ + + #define DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(attribute) \ + EventListener* on##attribute() { return document()->getWindowAttributeEventListener(eventNames().attribute##Event); } \ + void setOn##attribute(PassRefPtr<EventListener> listener) { document()->setWindowAttributeEventListener(eventNames().attribute##Event, listener); } \ + + #define DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(attribute, eventName) \ + EventListener* on##attribute() { return getAttributeEventListener(eventNames().eventName##Event); } \ + void setOn##attribute(PassRefPtr<EventListener> listener) { setAttributeEventListener(eventNames().eventName##Event, listener); } \ + + #define DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(recipient, attribute) \ + EventListener* on##attribute() { return recipient ? recipient->getAttributeEventListener(eventNames().attribute##Event) : 0; } \ + void setOn##attribute(PassRefPtr<EventListener> listener) { if (recipient) recipient->setAttributeEventListener(eventNames().attribute##Event, listener); } \ #ifndef NDEBUG + void forbidEventDispatch(); + void allowEventDispatch(); bool eventDispatchForbidden(); #else inline void forbidEventDispatch() { } inline void allowEventDispatch() { } #endif -} - +#if USE(JSC) + inline void EventTarget::markEventListeners(JSC::MarkStack& markStack) + { + EventTargetData* d = eventTargetData(); + if (!d) + return; + + EventListenerMap::iterator end = d->eventListenerMap.end(); + for (EventListenerMap::iterator it = d->eventListenerMap.begin(); it != end; ++it) { + EventListenerVector& entry = it->second; + for (size_t i = 0; i < entry.size(); ++i) + entry[i].listener->markJSFunction(markStack); + } + } + + inline void EventTarget::invalidateEventListeners() + { + EventTargetData* d = eventTargetData(); + if (!d) + return; + + d->eventListenerMap.clear(); + } #endif + + inline bool EventTarget::isFiringEventListeners() + { + EventTargetData* d = eventTargetData(); + if (!d) + return false; + return d->firingEventEndIterators.size() != 0; + } + + inline bool EventTarget::hasEventListeners() + { + EventTargetData* d = eventTargetData(); + if (!d) + return false; + return !d->eventListenerMap.isEmpty(); + } + + inline bool EventTarget::hasEventListeners(const AtomicString& eventType) + { + EventTargetData* d = eventTargetData(); + if (!d) + return false; + return d->eventListenerMap.contains(eventType); + } + +} // namespace WebCore + +#endif // EventTarget_h diff --git a/WebCore/dom/InputElement.cpp b/WebCore/dom/InputElement.cpp index 0e2456d..c29cb1c 100644 --- a/WebCore/dom/InputElement.cpp +++ b/WebCore/dom/InputElement.cpp @@ -34,7 +34,6 @@ #include "RenderTextControlSingleLine.h" #include "SelectionController.h" #include "TextIterator.h" -#include "TextBreakIterator.h" #if ENABLE(WML) #include "WMLInputElement.h" @@ -46,25 +45,23 @@ namespace WebCore { using namespace HTMLNames; // FIXME: According to HTML4, the length attribute's value can be arbitrarily -// large. However, due to http://bugs.webkit.org/show_bugs.cgi?id=14536 things +// large. However, due to https://bugs.webkit.org/show_bug.cgi?id=14536 things // get rather sluggish when a text field has a larger number of characters than // this, even when just clicking in the text field. const int InputElement::s_maximumLength = 524288; const int InputElement::s_defaultSize = 20; -void InputElement::dispatchFocusEvent(InputElementData& data, InputElement* inputElement, Element* element) +void InputElement::dispatchFocusEvent(InputElement* inputElement, Element* element) { if (!inputElement->isTextField()) return; - updatePlaceholderVisibility(data, inputElement, element); - Document* document = element->document(); if (inputElement->isPasswordField() && document->frame()) document->setUseSecureKeyboardEntryWhenActive(true); } -void InputElement::dispatchBlurEvent(InputElementData& data, InputElement* inputElement, Element* element) +void InputElement::dispatchBlurEvent(InputElement* inputElement, Element* element) { if (!inputElement->isTextField()) return; @@ -74,28 +71,12 @@ void InputElement::dispatchBlurEvent(InputElementData& data, InputElement* input if (!frame) return; - updatePlaceholderVisibility(data, inputElement, element); - if (inputElement->isPasswordField()) document->setUseSecureKeyboardEntryWhenActive(false); frame->textFieldDidEndEditing(element); } -void InputElement::updatePlaceholderVisibility(InputElementData& data, InputElement* inputElement, Element* element, bool placeholderValueChanged) -{ - ASSERT(inputElement->isTextField()); - Document* document = element->document(); - - bool oldPlaceholderShouldBeVisible = data.placeholderShouldBeVisible(); - data.setPlaceholderShouldBeVisible(inputElement->value().isEmpty() - && document->focusedNode() != element - && !inputElement->placeholder().isEmpty()); - - if ((oldPlaceholderShouldBeVisible != data.placeholderShouldBeVisible() || placeholderValueChanged) && element->renderer()) - toRenderTextControlSingleLine(element->renderer())->updatePlaceholderVisibility(); -} - void InputElement::updateFocusAppearance(InputElementData& data, InputElement* inputElement, Element* element, bool restorePreviousSelection) { ASSERT(inputElement->isTextField()); @@ -137,11 +118,8 @@ void InputElement::aboutToUnload(InputElement* inputElement, Element* element) void InputElement::setValueFromRenderer(InputElementData& data, InputElement* inputElement, Element* element, const String& value) { - // Renderer and our event handler are responsible for constraining values. - ASSERT(value == inputElement->constrainValue(value) || inputElement->constrainValue(value).isEmpty()); - - if (inputElement->isTextField()) - updatePlaceholderVisibility(data, inputElement, element); + // Renderer and our event handler are responsible for sanitizing values. + ASSERT_UNUSED(inputElement, value == inputElement->sanitizeValue(value) || inputElement->sanitizeValue(value).isEmpty()); // Workaround for bug where trailing \n is included in the result of textContent. // The assert macro above may also be simplified to: value == constrainValue(value) @@ -153,84 +131,58 @@ void InputElement::setValueFromRenderer(InputElementData& data, InputElement* in element->setFormControlValueMatchesRenderer(true); - // Fire the "input" DOM event - element->dispatchEvent(eventNames().inputEvent, true, false); + element->dispatchEvent(Event::create(eventNames().inputEvent, true, false)); notifyFormStateChanged(element); } -static int numCharactersInGraphemeClusters(StringImpl* s, int numGraphemeClusters) +String InputElement::sanitizeValue(const InputElement* inputElement, const String& proposedValue) { - if (!s) - return 0; - - TextBreakIterator* it = characterBreakIterator(s->characters(), s->length()); - if (!it) - return 0; - - for (int i = 0; i < numGraphemeClusters; ++i) { - if (textBreakNext(it) == TextBreakDone) - return s->length(); - } - - return textBreakCurrent(it); + return InputElement::sanitizeUserInputValue(inputElement, proposedValue, s_maximumLength); } -String InputElement::constrainValue(const InputElement* inputElement, const String& proposedValue, int maxLength) +String InputElement::sanitizeUserInputValue(const InputElement* inputElement, const String& proposedValue, int maxLength) { - String string = proposedValue; if (!inputElement->isTextField()) - return string; + return proposedValue; + String string = proposedValue; string.replace("\r\n", " "); string.replace('\r', ' '); string.replace('\n', ' '); - - StringImpl* s = string.impl(); - int newLength = numCharactersInGraphemeClusters(s, maxLength); - for (int i = 0; i < newLength; ++i) { - const UChar& current = (*s)[i]; + + unsigned newLength = string.numCharactersInGraphemeClusters(maxLength); + for (unsigned i = 0; i < newLength; ++i) { + const UChar current = string[i]; if (current < ' ' && current != '\t') { newLength = i; break; } } - - if (newLength < static_cast<int>(string.length())) - return string.left(newLength); - - return string; -} - -static int numGraphemeClusters(StringImpl* s) -{ - if (!s) - return 0; - - TextBreakIterator* it = characterBreakIterator(s->characters(), s->length()); - if (!it) - return 0; - - int num = 0; - while (textBreakNext(it) != TextBreakDone) - ++num; - - return num; + return string.left(newLength); } -void InputElement::handleBeforeTextInsertedEvent(InputElementData& data, InputElement* inputElement, Document* document, Event* event) +void InputElement::handleBeforeTextInsertedEvent(InputElementData& data, InputElement* inputElement, Element* element, Event* event) { ASSERT(event->isBeforeTextInsertedEvent()); - // Make sure that the text to be inserted will not violate the maxLength. - int oldLength = numGraphemeClusters(inputElement->value().impl()); - ASSERT(oldLength <= data.maxLength()); - int selectionLength = numGraphemeClusters(plainText(document->frame()->selection()->selection().toNormalizedRange().get()).impl()); + + // We use RenderTextControlSingleLine::text() instead of InputElement::value() + // because they can be mismatched by sanitizeValue() in + // RenderTextControlSingleLine::subtreeHasChanged() in some cases. + unsigned oldLength = toRenderTextControlSingleLine(element->renderer())->text().numGraphemeClusters(); + + // selection() may be a pre-edit text. + unsigned selectionLength = plainText(element->document()->frame()->selection()->selection().toNormalizedRange().get()).numGraphemeClusters(); ASSERT(oldLength >= selectionLength); - int maxNewLength = data.maxLength() - (oldLength - selectionLength); + + // Selected characters will be removed by the next text event. + unsigned baseLength = oldLength - selectionLength; + unsigned maxLength = static_cast<unsigned>(data.maxLength()); // maxLength() can never be negative. + unsigned appendableLength = maxLength > baseLength ? maxLength - baseLength : 0; // Truncate the inserted text to avoid violating the maxLength and other constraints. BeforeTextInsertedEvent* textEvent = static_cast<BeforeTextInsertedEvent*>(event); - textEvent->setText(constrainValue(inputElement, textEvent->text(), maxNewLength)); + textEvent->setText(sanitizeUserInputValue(inputElement, textEvent->text(), appendableLength)); } void InputElement::parseSizeAttribute(InputElementData& data, Element* element, MappedAttribute* attribute) @@ -259,7 +211,7 @@ void InputElement::parseMaxLengthAttribute(InputElementData& data, InputElement* void InputElement::updateValueIfNeeded(InputElementData& data, InputElement* inputElement) { String oldValue = data.value(); - String newValue = inputElement->constrainValue(oldValue); + String newValue = sanitizeValue(inputElement, oldValue); if (newValue != oldValue) inputElement->setValue(newValue); } @@ -277,8 +229,7 @@ void InputElement::notifyFormStateChanged(Element* element) // InputElementData InputElementData::InputElementData() - : m_placeholderShouldBeVisible(false) - , m_size(InputElement::s_defaultSize) + : m_size(InputElement::s_defaultSize) , m_maxLength(InputElement::s_maximumLength) , m_cachedSelectionStart(-1) , m_cachedSelectionEnd(-1) diff --git a/WebCore/dom/InputElement.h b/WebCore/dom/InputElement.h index 7ad3cbd..e0e7110 100644 --- a/WebCore/dom/InputElement.h +++ b/WebCore/dom/InputElement.h @@ -44,17 +44,13 @@ public: virtual bool isSearchField() const = 0; virtual bool isTextField() const = 0; - virtual bool placeholderShouldBeVisible() const = 0; virtual bool searchEventsShouldBeDispatched() const = 0; virtual int size() const = 0; virtual String value() const = 0; virtual void setValue(const String&) = 0; - virtual String placeholder() const = 0; - virtual void setPlaceholder(const String&) = 0; - - virtual String constrainValue(const String&) const = 0; + virtual String sanitizeValue(const String&) const = 0; virtual void setValueFromRenderer(const String&) = 0; virtual void cacheSelection(int start, int end) = 0; @@ -64,15 +60,19 @@ public: static const int s_defaultSize; protected: - static void dispatchFocusEvent(InputElementData&, InputElement*, Element*); - static void dispatchBlurEvent(InputElementData&, InputElement*, Element*); - static void updatePlaceholderVisibility(InputElementData&, InputElement*, Element*, bool placeholderValueChanged = false); + static void dispatchFocusEvent(InputElement*, Element*); + static void dispatchBlurEvent(InputElement*, Element*); static void updateFocusAppearance(InputElementData&, InputElement*, Element*, bool restorePreviousSelection); static void updateSelectionRange(InputElement*, Element*, int start, int end); static void aboutToUnload(InputElement*, Element*); static void setValueFromRenderer(InputElementData&, InputElement*, Element*, const String&); - static String constrainValue(const InputElement*, const String& proposedValue, int maxLength); - static void handleBeforeTextInsertedEvent(InputElementData&, InputElement*, Document*, Event*); + // Replaces CRs and LFs, shrinks the value for s_maximumLength. + // This should be applied to values from the HTML value attribute and the DOM value property. + static String sanitizeValue(const InputElement*, const String&); + // Replaces CRs and LFs, shrinks the value for the specified maximum length. + // This should be applied to values specified by users. + static String sanitizeUserInputValue(const InputElement*, const String&, int); + static void handleBeforeTextInsertedEvent(InputElementData&, InputElement*, Element*, Event*); static void parseSizeAttribute(InputElementData&, Element*, MappedAttribute*); static void parseMaxLengthAttribute(InputElementData&, InputElement*, Element*, MappedAttribute*); static void updateValueIfNeeded(InputElementData&, InputElement*); @@ -85,9 +85,6 @@ class InputElementData { public: InputElementData(); - bool placeholderShouldBeVisible() const { return m_placeholderShouldBeVisible; } - void setPlaceholderShouldBeVisible(bool visible) { m_placeholderShouldBeVisible = visible; } - const AtomicString& name() const; void setName(const AtomicString& value) { m_name = value; } @@ -107,7 +104,6 @@ public: void setCachedSelectionEnd(int value) { m_cachedSelectionEnd = value; } private: - bool m_placeholderShouldBeVisible; AtomicString m_name; String m_value; int m_size; diff --git a/WebCore/dom/MessageEvent.cpp b/WebCore/dom/MessageEvent.cpp index a0af32d..3c84642 100644 --- a/WebCore/dom/MessageEvent.cpp +++ b/WebCore/dom/MessageEvent.cpp @@ -34,16 +34,17 @@ namespace WebCore { MessageEvent::MessageEvent() + : m_data(SerializedScriptValue::create()) { } -MessageEvent::MessageEvent(const String& data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassRefPtr<MessagePort> messagePort) - : Event(eventNames().messageEvent, false, true) +MessageEvent::MessageEvent(PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortArray> ports) + : Event(eventNames().messageEvent, false, false) , m_data(data) , m_origin(origin) , m_lastEventId(lastEventId) , m_source(source) - , m_messagePort(messagePort) + , m_ports(ports) { } @@ -51,7 +52,7 @@ MessageEvent::~MessageEvent() { } -void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& data, const String& origin, const String& lastEventId, DOMWindow* source, MessagePort* messagePort) +void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, PassOwnPtr<MessagePortArray> ports) { if (dispatched()) return; @@ -62,7 +63,26 @@ void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bo m_origin = origin; m_lastEventId = lastEventId; m_source = source; - m_messagePort = messagePort; + m_ports = ports; +} + +// FIXME: remove this when we update the ObjC bindings (bug #28774). +MessagePort* MessageEvent::messagePort() +{ + if (!m_ports) + return 0; + ASSERT(m_ports->size() == 1); + return (*m_ports)[0].get(); +} + +void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, MessagePort* port) +{ + MessagePortArray* ports = 0; + if (port) { + ports = new MessagePortArray(); + ports->append(port); + } + initMessageEvent(type, canBubble, cancelable, data, origin, lastEventId, source, ports); } bool MessageEvent::isMessageEvent() const diff --git a/WebCore/dom/MessageEvent.h b/WebCore/dom/MessageEvent.h index 87a6745..b7f9b02 100644 --- a/WebCore/dom/MessageEvent.h +++ b/WebCore/dom/MessageEvent.h @@ -28,8 +28,10 @@ #ifndef MessageEvent_h #define MessageEvent_h +#include "DOMWindow.h" #include "Event.h" #include "MessagePort.h" +#include "SerializedScriptValue.h" namespace WebCore { @@ -41,31 +43,36 @@ namespace WebCore { { return adoptRef(new MessageEvent); } - static PassRefPtr<MessageEvent> create(const String& data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassRefPtr<MessagePort> messagePort) + static PassRefPtr<MessageEvent> create(PassOwnPtr<MessagePortArray> ports, PassRefPtr<SerializedScriptValue> data = 0, const String& origin = "", const String& lastEventId = "", PassRefPtr<DOMWindow> source = 0) { - return adoptRef(new MessageEvent(data, origin, lastEventId, source, messagePort)); + return adoptRef(new MessageEvent(data, origin, lastEventId, source, ports)); } virtual ~MessageEvent(); - void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& data, const String& origin, const String& lastEventId, DOMWindow* source, MessagePort*); - - const String& data() const { return m_data; } + void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, PassOwnPtr<MessagePortArray>); + + SerializedScriptValue* data() const { return m_data.get(); } const String& origin() const { return m_origin; } const String& lastEventId() const { return m_lastEventId; } DOMWindow* source() const { return m_source.get(); } - MessagePort* messagePort() const { return m_messagePort.get(); } - + MessagePortArray* ports() const { return m_ports.get(); } + + // FIXME: remove this when we update the ObjC bindings (bug #28774). + MessagePort* messagePort(); + // FIXME: remove this when we update the ObjC bindings (bug #28774). + void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, MessagePort*); + virtual bool isMessageEvent() const; - private: + private: MessageEvent(); - MessageEvent(const String& data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassRefPtr<MessagePort> messagePort); + MessageEvent(PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortArray>); - String m_data; + RefPtr<SerializedScriptValue> m_data; String m_origin; String m_lastEventId; RefPtr<DOMWindow> m_source; - RefPtr<MessagePort> m_messagePort; + OwnPtr<MessagePortArray> m_ports; }; } // namespace WebCore diff --git a/WebCore/dom/MessageEvent.idl b/WebCore/dom/MessageEvent.idl index 8e8f271..7e497fc 100644 --- a/WebCore/dom/MessageEvent.idl +++ b/WebCore/dom/MessageEvent.idl @@ -30,14 +30,21 @@ module events { GenerateConstructor, NoStaticTables ] MessageEvent : Event { + readonly attribute SerializedScriptValue data; - readonly attribute DOMString data; readonly attribute DOMString origin; readonly attribute DOMString lastEventId; readonly attribute DOMWindow source; +#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT + readonly attribute [CustomGetter] Array ports; + + [Custom] void initMessageEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in SerializedScriptValue dataArg, in DOMString originArg, in DOMString lastEventIdArg, in DOMWindow sourceArg, in Array messagePorts); +#else + // There's no good way to expose an array via the ObjC bindings, so for now just expose a single port. readonly attribute MessagePort messagePort; - - void initMessageEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString dataArg, in DOMString originArg, in DOMString lastEventIdArg, in DOMWindow sourceArg, in MessagePort messagePort); + + void initMessageEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in SerializedScriptValue dataArg, in DOMString originArg, in DOMString lastEventIdArg, in DOMWindow sourceArg, in MessagePort messagePort); +#endif }; diff --git a/WebCore/dom/MessagePort.cpp b/WebCore/dom/MessagePort.cpp index 9f3e4d2..9f6e649 100644 --- a/WebCore/dom/MessagePort.cpp +++ b/WebCore/dom/MessagePort.cpp @@ -55,28 +55,41 @@ MessagePort::~MessagePort() m_scriptExecutionContext->destroyedMessagePort(this); } -void MessagePort::postMessage(const String& message, ExceptionCode& ec) +// FIXME: remove this when we update the ObjC bindings (bug #28774). +void MessagePort::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, ExceptionCode& ec) { - postMessage(message, 0, ec); + MessagePortArray ports; + if (port) + ports.append(port); + postMessage(message, &ports, ec); } -void MessagePort::postMessage(const String& message, MessagePort* dataPort, ExceptionCode& ec) +void MessagePort::postMessage(PassRefPtr<SerializedScriptValue> message, ExceptionCode& ec) +{ + postMessage(message, static_cast<MessagePortArray*>(0), ec); +} + +void MessagePort::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionCode& ec) { if (!m_entangledChannel) return; ASSERT(m_scriptExecutionContext); - OwnPtr<MessagePortChannel> channel; - if (dataPort) { - if (dataPort == this || m_entangledChannel->isConnectedTo(dataPort)) { - ec = INVALID_STATE_ERR; - return; + OwnPtr<MessagePortChannelArray> channels; + // Make sure we aren't connected to any of the passed-in ports. + if (ports) { + for (unsigned int i = 0; i < ports->size(); ++i) { + MessagePort* dataPort = (*ports)[i].get(); + if (dataPort == this || m_entangledChannel->isConnectedTo(dataPort)) { + ec = INVALID_STATE_ERR; + return; + } } - channel = dataPort->disentangle(ec); + channels = MessagePort::disentanglePorts(ports, ec); if (ec) return; } - m_entangledChannel->postMessageToRemote(MessagePortChannel::EventData::create(message, channel.release())); + m_entangledChannel->postMessageToRemote(MessagePortChannel::EventData::create(message, channels.release())); } PassOwnPtr<MessagePortChannel> MessagePort::disentangle(ExceptionCode& ec) @@ -155,20 +168,8 @@ void MessagePort::dispatchMessages() OwnPtr<MessagePortChannel::EventData> eventData; while (m_entangledChannel && m_entangledChannel->tryGetMessageFromRemote(eventData)) { - RefPtr<MessagePort> port; - OwnPtr<MessagePortChannel> channel = eventData->channel(); - if (channel) { - // The remote side sent over a MessagePortChannel, so create a MessagePort to wrap it. - port = MessagePort::create(*m_scriptExecutionContext); - port->entangle(channel.release()); - } - RefPtr<Event> evt = MessageEvent::create(eventData->message(), "", "", 0, port.release()); - - if (m_onMessageListener) { - evt->setTarget(this); - evt->setCurrentTarget(this); - m_onMessageListener->handleEvent(evt.get(), false); - } + OwnPtr<MessagePortArray> ports = MessagePort::entanglePorts(*m_scriptExecutionContext, eventData->channels()); + RefPtr<Event> evt = MessageEvent::create(ports.release(), eventData->message()); ExceptionCode ec = 0; dispatchEvent(evt.release(), ec); @@ -176,73 +177,68 @@ void MessagePort::dispatchMessages() } } -void MessagePort::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool) +bool MessagePort::hasPendingActivity() { - EventListenersMap::iterator iter = m_eventListeners.find(eventType); - if (iter == m_eventListeners.end()) { - ListenerVector listeners; - listeners.append(eventListener); - m_eventListeners.add(eventType, listeners); - } else { - ListenerVector& listeners = iter->second; - for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) { - if (*listenerIter == eventListener) - return; - } - - listeners.append(eventListener); - m_eventListeners.add(eventType, listeners); - } + // The spec says that entangled message ports should always be treated as if they have a strong reference. + // We'll also stipulate that the queue needs to be open (if the app drops its reference to the port before start()-ing it, then it's not really entangled as it's unreachable). + return m_started && m_entangledChannel && m_entangledChannel->hasPendingActivity(); } -void MessagePort::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool) +MessagePort* MessagePort::locallyEntangledPort() { - EventListenersMap::iterator iter = m_eventListeners.find(eventType); - if (iter == m_eventListeners.end()) - return; - - ListenerVector& listeners = iter->second; - for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) { - if (*listenerIter == eventListener) { - listeners.remove(listenerIter - listeners.begin()); - return; - } - } + return m_entangledChannel ? m_entangledChannel->locallyEntangledPort(m_scriptExecutionContext) : 0; } -bool MessagePort::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec) +PassOwnPtr<MessagePortChannelArray> MessagePort::disentanglePorts(const MessagePortArray* ports, ExceptionCode& ec) { - if (!event || event->type().isEmpty()) { - ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; - return true; + if (!ports || !ports->size()) + return 0; + + // HashSet used to efficiently check for duplicates in the passed-in array. + HashSet<MessagePort*> portSet; + + // 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)) { + ec = INVALID_STATE_ERR; + return 0; + } + portSet.add(port); } - - ListenerVector listenersCopy = m_eventListeners.get(event->type()); - for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) { - event->setTarget(this); - event->setCurrentTarget(this); - listenerIter->get()->handleEvent(event.get(), false); + + // Passed-in ports passed validity checks, so we can disentangle them. + MessagePortChannelArray* portArray = new MessagePortChannelArray(ports->size()); + for (unsigned int i = 0 ; i < ports->size() ; ++i) { + OwnPtr<MessagePortChannel> channel = (*ports)[i]->disentangle(ec); + ASSERT(!ec); // Can't generate exception here if passed above checks. + (*portArray)[i] = channel.release(); } - - return !event->defaultPrevented(); + return portArray; } -void MessagePort::setOnmessage(PassRefPtr<EventListener> eventListener) +PassOwnPtr<MessagePortArray> MessagePort::entanglePorts(ScriptExecutionContext& context, PassOwnPtr<MessagePortChannelArray> channels) { - m_onMessageListener = eventListener; - start(); + if (!channels || !channels->size()) + return 0; + + MessagePortArray* portArray = new MessagePortArray(channels->size()); + for (unsigned int i = 0; i < channels->size(); ++i) { + RefPtr<MessagePort> port = MessagePort::create(context); + port->entangle((*channels)[i].release()); + (*portArray)[i] = port.release(); + } + return portArray; } -bool MessagePort::hasPendingActivity() +EventTargetData* MessagePort::eventTargetData() { - // The spec says that entangled message ports should always be treated as if they have a strong reference. - // We'll also stipulate that the queue needs to be open (if the app drops its reference to the port before start()-ing it, then it's not really entangled as it's unreachable). - return m_started && m_entangledChannel && m_entangledChannel->hasPendingActivity(); + return &m_eventTargetData; } -MessagePort* MessagePort::locallyEntangledPort() +EventTargetData* MessagePort::ensureEventTargetData() { - return m_entangledChannel ? m_entangledChannel->locallyEntangledPort(m_scriptExecutionContext) : 0; + return &m_eventTargetData; } } // namespace WebCore diff --git a/WebCore/dom/MessagePort.h b/WebCore/dom/MessagePort.h index f416b9b..0ab0f50 100644 --- a/WebCore/dom/MessagePort.h +++ b/WebCore/dom/MessagePort.h @@ -29,9 +29,9 @@ #include "AtomicStringHash.h" #include "EventListener.h" +#include "EventNames.h" #include "EventTarget.h" #include "MessagePortChannel.h" - #include <wtf/HashMap.h> #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> @@ -44,22 +44,38 @@ namespace WebCore { class AtomicStringImpl; class Event; class Frame; + class MessagePort; class ScriptExecutionContext; class String; + // The overwhelmingly common case is sending a single port, so handle that efficiently with an inline buffer of size 1. + typedef Vector<RefPtr<MessagePort>, 1> MessagePortArray; + class MessagePort : public RefCounted<MessagePort>, public EventTarget { public: static PassRefPtr<MessagePort> create(ScriptExecutionContext& scriptExecutionContext) { return adoptRef(new MessagePort(scriptExecutionContext)); } ~MessagePort(); - void postMessage(const String& message, ExceptionCode&); - void postMessage(const String& message, MessagePort*, ExceptionCode&); + void postMessage(PassRefPtr<SerializedScriptValue> message, ExceptionCode&); + void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, ExceptionCode&); + // FIXME: remove this when we update the ObjC bindings (bug #28774). + void postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort*, ExceptionCode&); + void start(); void close(); void entangle(PassOwnPtr<MessagePortChannel>); PassOwnPtr<MessagePortChannel> disentangle(ExceptionCode&); + // Disentangle an array of ports, returning the entangled channels. + // Per section 8.3.3 of the HTML5 spec, generates an INVALID_STATE_ERR exception if any of the passed ports are null or not entangled. + // Returns 0 if there is an exception, or if the passed-in array is 0/empty. + static PassOwnPtr<MessagePortChannelArray> disentanglePorts(const MessagePortArray*, ExceptionCode&); + + // Entangles an array of channels, returning an array of MessagePorts in matching order. + // Returns 0 if the passed array is 0/empty. + static PassOwnPtr<MessagePortArray> entanglePorts(ScriptExecutionContext&, PassOwnPtr<MessagePortChannelArray>); + void messageAvailable(); bool started() const { return m_started; } @@ -71,21 +87,17 @@ namespace WebCore { void dispatchMessages(); - virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture); - virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture); - virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&); - - typedef Vector<RefPtr<EventListener> > ListenerVector; - typedef HashMap<AtomicString, ListenerVector> EventListenersMap; - EventListenersMap& eventListeners() { return m_eventListeners; } - using RefCounted<MessagePort>::ref; using RefCounted<MessagePort>::deref; bool hasPendingActivity(); - void setOnmessage(PassRefPtr<EventListener>); - EventListener* onmessage() const { return m_onMessageListener.get(); } + void setOnmessage(PassRefPtr<EventListener> listener) + { + setAttributeEventListener(eventNames().messageEvent, listener); + start(); + } + EventListener* onmessage() { return getAttributeEventListener(eventNames().messageEvent); } // Returns null if there is no entangled port, or if the entangled port is run by a different thread. // Returns null otherwise. @@ -98,16 +110,15 @@ namespace WebCore { virtual void refEventTarget() { ref(); } virtual void derefEventTarget() { deref(); } + virtual EventTargetData* eventTargetData(); + virtual EventTargetData* ensureEventTargetData(); OwnPtr<MessagePortChannel> m_entangledChannel; bool m_started; ScriptExecutionContext* m_scriptExecutionContext; - - RefPtr<EventListener> m_onMessageListener; - - EventListenersMap m_eventListeners; + EventTargetData m_eventTargetData; }; } // namespace WebCore diff --git a/WebCore/dom/MessagePort.idl b/WebCore/dom/MessagePort.idl index e5f9ad1..a9149ec 100644 --- a/WebCore/dom/MessagePort.idl +++ b/WebCore/dom/MessagePort.idl @@ -28,13 +28,14 @@ module events { interface [ CustomMarkFunction, + EventTarget, GenerateConstructor, NoStaticTables ] MessagePort { // We need to have something as an ObjC binding, because MessagePort is used in MessageEvent, which already has one, // but we don't want to actually expose the API while it is in flux. #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT - void postMessage(in DOMString message, in [Optional] MessagePort messagePort) + [Custom] void postMessage(in DOMString message, in [Optional] Array messagePorts) raises(DOMException); void start(); void close(); diff --git a/WebCore/dom/MessagePortChannel.cpp b/WebCore/dom/MessagePortChannel.cpp index 05134c0..e1a3ac6 100644 --- a/WebCore/dom/MessagePortChannel.cpp +++ b/WebCore/dom/MessagePortChannel.cpp @@ -33,14 +33,14 @@ namespace WebCore { -PassOwnPtr<MessagePortChannel::EventData> MessagePortChannel::EventData::create(const String& message, PassOwnPtr<MessagePortChannel> channel) +PassOwnPtr<MessagePortChannel::EventData> MessagePortChannel::EventData::create(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels) { - return new EventData(message, channel); + return new EventData(message, channels); } -MessagePortChannel::EventData::EventData(const String& message, PassOwnPtr<MessagePortChannel> channel) - : m_message(message.copy()) - , m_channel(channel) +MessagePortChannel::EventData::EventData(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels) + : m_message(message->release()) + , m_channels(channels) { } diff --git a/WebCore/dom/MessagePortChannel.h b/WebCore/dom/MessagePortChannel.h index 93b224b..2321b1f 100644 --- a/WebCore/dom/MessagePortChannel.h +++ b/WebCore/dom/MessagePortChannel.h @@ -33,6 +33,8 @@ #include "PlatformString.h" +#include "SerializedScriptValue.h" + #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> #include <wtf/PassRefPtr.h> @@ -42,10 +44,15 @@ namespace WebCore { class MessagePort; + class MessagePortChannel; class PlatformMessagePortChannel; class ScriptExecutionContext; + class SerializedScriptValue; class String; + // The overwhelmingly common case is sending a single port, so handle that efficiently with an inline buffer of size 1. + typedef Vector<OwnPtr<MessagePortChannel>, 1> MessagePortChannelArray; + // MessagePortChannel is a platform-independent interface to the remote side of a message channel. // It acts as a wrapper around the platform-dependent PlatformMessagePortChannel implementation which ensures that the platform-dependent close() method is invoked before destruction. class MessagePortChannel : public Noncopyable { @@ -73,15 +80,15 @@ namespace WebCore { class EventData { public: - static PassOwnPtr<EventData> create(const String&, PassOwnPtr<MessagePortChannel>); + static PassOwnPtr<EventData> create(PassRefPtr<SerializedScriptValue>, PassOwnPtr<MessagePortChannelArray>); - const String& message() { return m_message; } - PassOwnPtr<MessagePortChannel> channel() { return m_channel.release(); } + SerializedScriptValue* message() { return m_message.get(); } + PassOwnPtr<MessagePortChannelArray> channels() { return m_channels.release(); } private: - EventData(const String& message, PassOwnPtr<MessagePortChannel>); - String m_message; - OwnPtr<MessagePortChannel> m_channel; + EventData(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray>); + RefPtr<SerializedScriptValue> m_message; + OwnPtr<MessagePortChannelArray> m_channels; }; // Sends a message and optional cloned port to the remote port. diff --git a/WebCore/dom/MutationEvent.h b/WebCore/dom/MutationEvent.h index c5f2d1d..29b978c 100644 --- a/WebCore/dom/MutationEvent.h +++ b/WebCore/dom/MutationEvent.h @@ -41,10 +41,11 @@ namespace WebCore { { return adoptRef(new MutationEvent); } - static PassRefPtr<MutationEvent> create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<Node> relatedNode, - const String& prevValue, const String& newValue, const String& attrName, unsigned short attrChange) + + static PassRefPtr<MutationEvent> create(const AtomicString& type, bool canBubble, PassRefPtr<Node> relatedNode = 0, + const String& prevValue = String(), const String& newValue = String(), const String& attrName = String(), unsigned short attrChange = 0) { - return adoptRef(new MutationEvent(type, canBubble, cancelable, relatedNode, prevValue, newValue, attrName, attrChange)); + return adoptRef(new MutationEvent(type, canBubble, false, relatedNode, prevValue, newValue, attrName, attrChange)); } void initMutationEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<Node> relatedNode, diff --git a/WebCore/dom/NamedAttrMap.cpp b/WebCore/dom/NamedAttrMap.cpp index fe631c8..d4ec598 100644 --- a/WebCore/dom/NamedAttrMap.cpp +++ b/WebCore/dom/NamedAttrMap.cpp @@ -178,10 +178,8 @@ Attribute* NamedNodeMap::getAttributeItem(const String& name, bool shouldIgnoreA { unsigned len = length(); 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 (!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(); } @@ -206,10 +204,12 @@ void NamedNodeMap::clearAttributes() void NamedNodeMap::detachFromElement() { - // we allow a NamedNodeMap w/o an element in case someone still has a reference - // to if after the element gets deleted - but the map is now invalid + // This can't happen if the holder of the map is JavaScript, because we mark the + // element if the map is alive. So it has no impact on web page behavior. Because + // of that, we can simply clear all the attributes to avoid accessing stale + // pointers to do things like create Attr objects. m_element = 0; - detachAttributesFromElement(); + clearAttributes(); } void NamedNodeMap::setAttributes(const NamedNodeMap& other) @@ -251,7 +251,7 @@ void NamedNodeMap::addAttribute(PassRefPtr<Attribute> prpAttribute) attr->m_element = m_element; // Notify the element that the attribute has been added, and dispatch appropriate mutation events - // Note that element may be null here if we are called from insertAttr() during parsing + // Note that element may be null here if we are called from insertAttribute() during parsing if (m_element) { m_element->attributeChanged(attribute.get()); // Because of our updateStyleAttribute() style modification events are never sent at the right time, so don't bother sending them. @@ -265,12 +265,13 @@ void NamedNodeMap::addAttribute(PassRefPtr<Attribute> prpAttribute) void NamedNodeMap::removeAttribute(const QualifiedName& name) { unsigned len = length(); - unsigned index = len + 1; - for (unsigned i = 0; i < len; ++i) + unsigned index = len; + for (unsigned i = 0; i < len; ++i) { if (m_attributes[i]->name().matches(name)) { index = i; break; } + } if (index >= len) return; diff --git a/WebCore/dom/NamedAttrMap.h b/WebCore/dom/NamedAttrMap.h index 4fb96de..759900b 100644 --- a/WebCore/dom/NamedAttrMap.h +++ b/WebCore/dom/NamedAttrMap.h @@ -94,11 +94,11 @@ public: void addAttribute(PassRefPtr<Attribute>); void removeAttribute(const QualifiedName&); + Element* element() const { return m_element; } + protected: virtual void clearAttributes(); - Element* element() const { return m_element; } - private: void detachAttributesFromElement(); void detachFromElement(); diff --git a/WebCore/dom/NamedNodeMap.idl b/WebCore/dom/NamedNodeMap.idl index 3310ded..8166853 100644 --- a/WebCore/dom/NamedNodeMap.idl +++ b/WebCore/dom/NamedNodeMap.idl @@ -1,6 +1,6 @@ /* * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -21,6 +21,7 @@ module core { interface [ + CustomMarkFunction, GenerateConstructor, HasIndexGetter, HasNameGetter, diff --git a/WebCore/dom/Node.cpp b/WebCore/dom/Node.cpp index 18655c6..4b91a40 100644 --- a/WebCore/dom/Node.cpp +++ b/WebCore/dom/Node.cpp @@ -55,6 +55,7 @@ #include "Frame.h" #include "FrameView.h" #include "HTMLNames.h" +#include "InspectorTimelineAgent.h" #include "KeyboardEvent.h" #include "Logging.h" #include "MouseEvent.h" @@ -337,8 +338,69 @@ Node::StyleChange Node::diff(const RenderStyle* s1, const RenderStyle* s2) return ch; } -Node::Node(Document* doc, bool isElement, bool isContainer, bool isText) - : m_document(doc) +inline bool Node::initialRefCount(ConstructionType type) +{ + switch (type) { + case CreateContainer: + case CreateElement: + case CreateOther: + case CreateText: + return 1; + case CreateElementZeroRefCount: + return 0; + } + ASSERT_NOT_REACHED(); + return 1; +} + +inline bool Node::isContainer(ConstructionType type) +{ + switch (type) { + case CreateContainer: + case CreateElement: + case CreateElementZeroRefCount: + return true; + case CreateOther: + case CreateText: + return false; + } + ASSERT_NOT_REACHED(); + return false; +} + +inline bool Node::isElement(ConstructionType type) +{ + switch (type) { + case CreateContainer: + case CreateOther: + case CreateText: + return false; + case CreateElement: + case CreateElementZeroRefCount: + return true; + } + ASSERT_NOT_REACHED(); + return false; +} + +inline bool Node::isText(ConstructionType type) +{ + switch (type) { + case CreateContainer: + case CreateElement: + case CreateElementZeroRefCount: + case CreateOther: + return false; + case CreateText: + return true; + } + ASSERT_NOT_REACHED(); + return false; +} + +Node::Node(Document* document, ConstructionType type) + : TreeShared<Node>(initialRefCount(type)) + , m_document(document) , m_previous(0) , m_next(0) , m_renderer(0) @@ -355,25 +417,27 @@ Node::Node(Document* doc, bool isElement, bool isContainer, bool isText) , m_inDetach(false) , m_inSubtreeMark(false) , m_hasRareData(false) - , m_isElement(isElement) - , m_isContainer(isContainer) - , m_isText(isText) + , m_isElement(isElement(type)) + , m_isContainer(isContainer(type)) + , m_isText(isText(type)) , m_parsingChildrenFinished(true) -#if ENABLE(SVG) - , m_areSVGAttributesValid(true) -#endif , m_isStyleAttributeValid(true) , m_synchronizingStyleAttribute(false) #if ENABLE(SVG) + , m_areSVGAttributesValid(true) , m_synchronizingSVGAttributes(false) #endif { + if (m_document) + m_document->selfOnlyRef(); + #ifndef NDEBUG if (shouldIgnoreLeaks) ignoreSet.add(this); else nodeCounter.increment(); #endif + #if DUMP_NODE_STATISTICS liveNodeSet.add(this); #endif @@ -393,9 +457,6 @@ Node::~Node() liveNodeSet.remove(this); #endif - if (!eventListeners().isEmpty() && !inDocument()) - document()->unregisterDisconnectedNodeWithEventListeners(this); - if (!hasRareData()) ASSERT(!NodeRareData::rareDataMap().contains(this)); else { @@ -416,6 +477,9 @@ Node::~Node() m_previous->setNextSibling(0); if (m_next) m_next->setPreviousSibling(0); + + if (m_document) + m_document->selfOnlyDeref(); } #ifdef NDEBUG @@ -450,14 +514,19 @@ void Node::setDocument(Document* document) if (inDocument() || m_document == document) return; + document->selfOnlyRef(); + setWillMoveToNewOwnerDocumentWasCalled(false); willMoveToNewOwnerDocument(); ASSERT(willMoveToNewOwnerDocumentWasCalled); #if USE(JSC) - updateDOMNodeDocument(this, m_document.get(), document); + updateDOMNodeDocument(this, m_document, document); #endif + if (m_document) + m_document->selfOnlyDeref(); + m_document = document; setDidMoveToNewOwnerDocumentWasCalled(false); @@ -519,7 +588,8 @@ PassRefPtr<NodeList> Node::childNodes() NodeRareData* data = ensureRareData(); if (!data->nodeLists()) { data->setNodeLists(NodeListsNodeData::create()); - document()->addNodeListCache(); + if (document()) + document()->addNodeListCache(); } return ChildNodeList::create(this, data->nodeLists()->m_childNodeListCaches.get()); @@ -699,7 +769,7 @@ void Node::setNeedsStyleRecalc(StyleChangeType changeType) if ((changeType != NoStyleChange) && !attached()) // changed compared to what? return; - if (!(changeType == InlineStyleChange && (m_styleChange == FullStyleChange || m_styleChange == AnimationStyleChange))) + if (!(changeType == InlineStyleChange && (m_styleChange == FullStyleChange || m_styleChange == SyntheticStyleChange))) m_styleChange = changeType; if (m_styleChange != NoStyleChange) { @@ -762,10 +832,30 @@ bool Node::rareDataFocused() const ASSERT(hasRareData()); return rareData()->isFocused(); } + +bool Node::supportsFocus() const +{ + return hasRareData() && rareData()->tabIndexSetExplicitly(); +} bool Node::isFocusable() const { - return hasRareData() && rareData()->tabIndexSetExplicitly(); + if (!inDocument() || !supportsFocus()) + return false; + + if (renderer()) + ASSERT(!renderer()->needsLayout()); + else + // If the node is in a display:none tree it might say it needs style recalc but + // the whole document is atually up to date. + ASSERT(!document()->childNeedsStyleRecalc()); + + // FIXME: Even if we are not visible, we might have a child that is visible. + // Hyatt wants to fix that some day with a "has visible content" flag or the like. + if (!renderer() || renderer()->style()->visibility() != VISIBLE) + return false; + + return true; } bool Node::isKeyboardFocusable(KeyboardEvent*) const @@ -793,7 +883,7 @@ void Node::registerDynamicNodeList(DynamicNodeList* list) if (!data->nodeLists()) { data->setNodeLists(NodeListsNodeData::create()); document()->addNodeListCache(); - } else if (!m_document->hasNodeListCaches()) { + } else if (!m_document || !m_document->hasNodeListCaches()) { // We haven't been receiving notifications while there were no registered lists, so the cache is invalid now. data->nodeLists()->invalidateCaches(); } @@ -811,7 +901,8 @@ void Node::unregisterDynamicNodeList(DynamicNodeList* list) data->nodeLists()->m_listsWithCaches.remove(list); if (data->nodeLists()->isEmpty()) { data->clearNodeLists(); - document()->removeNodeListCache(); + if (document()) + document()->removeNodeListCache(); } } } @@ -1540,52 +1631,6 @@ PassRefPtr<NodeList> Node::getElementsByClassName(const String& classNames) return ClassNodeList::create(this, classNames, result.first->second.get()); } -template <typename Functor> -static bool forEachTagSelector(Functor& functor, CSSSelector* selector) -{ - ASSERT(selector); - - do { - if (functor(selector)) - return true; - if (CSSSelector* simpleSelector = selector->simpleSelector()) { - if (forEachTagSelector(functor, simpleSelector)) - return true; - } - } while ((selector = selector->tagHistory())); - - return false; -} - -template <typename Functor> -static bool forEachSelector(Functor& functor, const CSSSelectorList& selectorList) -{ - for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) { - if (forEachTagSelector(functor, selector)) - return true; - } - - return false; -} - -class SelectorNeedsNamespaceResolutionFunctor { -public: - bool operator()(CSSSelector* selector) - { - if (selector->hasTag() && selector->m_tag.prefix() != nullAtom && selector->m_tag.prefix() != starAtom) - return true; - if (selector->hasAttribute() && selector->attribute().prefix() != nullAtom && selector->attribute().prefix() != starAtom) - return true; - return false; - } -}; - -static bool selectorNeedsNamespaceResolution(const CSSSelectorList& selectorList) -{ - SelectorNeedsNamespaceResolutionFunctor functor; - return forEachSelector(functor, selectorList); -} - PassRefPtr<Element> Node::querySelector(const String& selectors, ExceptionCode& ec) { if (selectors.isEmpty()) { @@ -1604,7 +1649,7 @@ PassRefPtr<Element> Node::querySelector(const String& selectors, ExceptionCode& } // throw a NAMESPACE_ERR if the selector includes any namespace prefixes. - if (selectorNeedsNamespaceResolution(querySelectorList)) { + if (querySelectorList.selectorsNeedNamespaceResolution()) { ec = NAMESPACE_ERR; return 0; } @@ -1652,7 +1697,7 @@ PassRefPtr<NodeList> Node::querySelectorAll(const String& selectors, ExceptionCo } // Throw a NAMESPACE_ERR if the selector includes any namespace prefixes. - if (selectorNeedsNamespaceResolution(querySelectorList)) { + if (querySelectorList.selectorsNeedNamespaceResolution()) { ec = NAMESPACE_ERR; return 0; } @@ -1900,11 +1945,11 @@ void Node::appendTextContent(bool convertBRsToNewlines, StringBuilder& content) case TEXT_NODE: case CDATA_SECTION_NODE: case COMMENT_NODE: - content.append(static_cast<const CharacterData*>(this)->CharacterData::nodeValue()); + content.append(static_cast<const CharacterData*>(this)->data()); break; case PROCESSING_INSTRUCTION_NODE: - content.append(static_cast<const ProcessingInstruction*>(this)->ProcessingInstruction::nodeValue()); + content.append(static_cast<const ProcessingInstruction*>(this)->data()); break; case ELEMENT_NODE: @@ -2288,16 +2333,28 @@ ContainerNode* Node::eventParentNode() #ifdef ANDROID_INSTRUMENT static size_t nodeSize = 0; -void* Node::operator new(size_t s) throw() +void* Node::operator new(size_t size) +{ + nodeSize += size; + return ::operator new(size); +} + +void* Node::operator new[](size_t size) { - nodeSize += s; - return ::operator new(s); + nodeSize += size; + return ::operator new[](size); } -void Node::operator delete(void* ptr, size_t s) +void Node::operator delete(void* p, size_t size) { - nodeSize -= s; - ::operator delete(ptr); + nodeSize -= size; + ::operator delete(p); +} + +void Node::operator delete[](void* p, size_t size) +{ + nodeSize -= size; + ::operator delete[](p); } size_t Node::reportDOMNodesSize() @@ -2313,46 +2370,24 @@ ScriptExecutionContext* Node::scriptExecutionContext() const return document(); } -const RegisteredEventListenerVector& Node::eventListeners() const -{ - if (hasRareData()) { - if (RegisteredEventListenerVector* listeners = rareData()->listeners()) - return *listeners; - } - static const RegisteredEventListenerVector* emptyListenersVector = new RegisteredEventListenerVector; - return *emptyListenersVector; -} - void Node::insertedIntoDocument() { - if (!eventListeners().isEmpty()) - document()->unregisterDisconnectedNodeWithEventListeners(this); - setInDocument(true); } void Node::removedFromDocument() { - if (!eventListeners().isEmpty()) - document()->registerDisconnectedNodeWithEventListeners(this); - setInDocument(false); } void Node::willMoveToNewOwnerDocument() { - if (!eventListeners().isEmpty()) - document()->unregisterDisconnectedNodeWithEventListeners(this); - ASSERT(!willMoveToNewOwnerDocumentWasCalled); setWillMoveToNewOwnerDocumentWasCalled(true); } void Node::didMoveToNewOwnerDocument() { - if (!eventListeners().isEmpty()) - document()->registerDisconnectedNodeWithEventListeners(this); - ASSERT(!didMoveToNewOwnerDocumentWasCalled); setDidMoveToNewOwnerDocumentWasCalled(true); } @@ -2382,99 +2417,63 @@ static inline void updateSVGElementInstancesAfterEventListenerChange(Node* refer #endif } -void Node::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) +bool Node::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) { - Document* document = this->document(); - if (!document->attached()) - return; - - document->addListenerTypeIfNeeded(eventType); - - RegisteredEventListenerVector& listeners = ensureRareData()->ensureListeners(); - - // Remove existing identical listener set with identical arguments. - // The DOM2 spec says that "duplicate instances are discarded" in this case. - removeEventListener(eventType, listener.get(), useCapture); - - // adding the first one - if (listeners.isEmpty() && !inDocument()) - document->registerDisconnectedNodeWithEventListeners(this); + if (!EventTarget::addEventListener(eventType, listener, useCapture)) + return false; - listeners.append(RegisteredEventListener::create(eventType, listener, useCapture)); + if (Document* document = this->document()) + document->addListenerTypeIfNeeded(eventType); updateSVGElementInstancesAfterEventListenerChange(this); #if ENABLE(TOUCH_EVENTS) // Android - if (eventType == eventNames().touchstartEvent || - eventType == eventNames().touchendEvent || - eventType == eventNames().touchmoveEvent || - eventType == eventNames().touchcancelEvent) - document->addTouchEventListener(this); + if (this->document() && + (eventType == eventNames().touchstartEvent || + eventType == eventNames().touchendEvent || + eventType == eventNames().touchmoveEvent || + eventType == eventNames().touchcancelEvent)) + this->document()->addTouchEventListener(this); #endif + return true; } -void Node::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) +bool Node::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) { - if (!hasRareData()) - return; - - RegisteredEventListenerVector* listeners = rareData()->listeners(); - if (!listeners) - return; - - size_t size = listeners->size(); - for (size_t i = 0; i < size; ++i) { - RegisteredEventListener& r = *listeners->at(i); - if (r.eventType() == eventType && r.listener() == listener && r.useCapture() == useCapture) { - r.setRemoved(true); - listeners->remove(i); + if (!EventTarget::removeEventListener(eventType, listener, useCapture)) + return false; - // removed last - if (listeners->isEmpty() && !inDocument()) - document()->unregisterDisconnectedNodeWithEventListeners(this); + updateSVGElementInstancesAfterEventListenerChange(this); - updateSVGElementInstancesAfterEventListenerChange(this); #if ENABLE(TOUCH_EVENTS) // Android - if (eventType == eventNames().touchstartEvent || - eventType == eventNames().touchendEvent || - eventType == eventNames().touchmoveEvent || - eventType == eventNames().touchcancelEvent) - document()->removeTouchEventListener(this); + if (this->document() && + (eventType == eventNames().touchstartEvent || + eventType == eventNames().touchendEvent || + eventType == eventNames().touchmoveEvent || + eventType == eventNames().touchcancelEvent)) + this->document()->removeTouchEventListener(this); #endif - return; - } - } + return true; } -void Node::removeAllEventListenersSlowCase() +EventTargetData* Node::eventTargetData() { - ASSERT(hasRareData()); - - RegisteredEventListenerVector* listeners = rareData()->listeners(); - if (!listeners) - return; - -#if ENABLE(TOUCH_EVENTS) // Android - document()->removeTouchEventListener(this); -#endif + return hasRareData() ? rareData()->eventTargetData() : 0; +} - size_t size = listeners->size(); - for (size_t i = 0; i < size; ++i) - listeners->at(i)->setRemoved(true); - listeners->clear(); +EventTargetData* Node::ensureEventTargetData() +{ + return ensureRareData()->ensureEventTargetData(); } -void Node::handleLocalEvents(Event* event, bool useCapture) +void Node::handleLocalEvents(Event* event) { + if (!hasRareData() || !rareData()->eventTargetData()) + return; + if (disabled() && event->isMouseEvent()) return; - RegisteredEventListenerVector listenersCopy = eventListeners(); - size_t size = listenersCopy.size(); - for (size_t i = 0; i < size; ++i) { - const RegisteredEventListener& r = *listenersCopy[i]; - if (r.eventType() == event->type() && r.useCapture() == useCapture && !r.removed()) - r.listener()->handleEvent(event, false); - } + fireEventListeners(event); } #if ENABLE(SVG) @@ -2515,19 +2514,29 @@ static inline EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNo return referenceNode; } -bool Node::dispatchEvent(PassRefPtr<Event> e, ExceptionCode& ec) +void Node::eventAncestors(Vector<RefPtr<ContainerNode> > &ancestors) { - RefPtr<Event> evt(e); - ASSERT(!eventDispatchForbidden()); - if (!evt || evt->type().isEmpty()) { - ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; - return false; + if (inDocument()) { + for (ContainerNode* ancestor = eventParentNode(); ancestor; ancestor = ancestor->eventParentNode()) { +#if ENABLE(SVG) + // Skip <use> shadow tree elements. + if (ancestor->isSVGElement() && ancestor->isShadowNode()) + continue; +#endif + ancestors.append(ancestor); + } } +} + +bool Node::dispatchEvent(PassRefPtr<Event> prpEvent) +{ + RefPtr<EventTarget> protect = this; + RefPtr<Event> event = prpEvent; - evt->setTarget(eventTargetRespectingSVGTargetRules(this)); + event->setTarget(eventTargetRespectingSVGTargetRules(this)); RefPtr<FrameView> view = document()->view(); - return dispatchGenericEvent(evt.release()); + return dispatchGenericEvent(event.release()); } bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) @@ -2538,21 +2547,18 @@ 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. RefPtr<Node> thisNode(this); Vector<RefPtr<ContainerNode> > ancestors; - if (inDocument()) { - for (ContainerNode* ancestor = eventParentNode(); ancestor; ancestor = ancestor->eventParentNode()) { -#if ENABLE(SVG) - // Skip <use> shadow tree elements. - if (ancestor->isSVGElement() && ancestor->isShadowNode()) - continue; -#endif - ancestors.append(ancestor); - } - } + eventAncestors(ancestors); // Set up a pointer to indicate whether / where to dispatch window events. // We don't dispatch load events to the window. That quirk was originally @@ -2574,27 +2580,22 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) if (targetForWindowEvents) { event->setCurrentTarget(targetForWindowEvents); - targetForWindowEvents->handleEvent(event.get(), true); + targetForWindowEvents->fireEventListeners(event.get()); if (event->propagationStopped()) goto doneDispatching; } for (size_t i = ancestors.size(); i; --i) { ContainerNode* ancestor = ancestors[i - 1].get(); event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor)); - ancestor->handleLocalEvents(event.get(), true); + ancestor->handleLocalEvents(event.get()); if (event->propagationStopped()) goto doneDispatching; } event->setEventPhase(Event::AT_TARGET); - // We do want capturing event listeners to be invoked here, even though - // that violates some versions of the DOM specification; Mozilla does it. event->setCurrentTarget(eventTargetRespectingSVGTargetRules(this)); - handleLocalEvents(event.get(), true); - if (event->propagationStopped()) - goto doneDispatching; - handleLocalEvents(event.get(), false); + handleLocalEvents(event.get()); if (event->propagationStopped()) goto doneDispatching; @@ -2606,13 +2607,13 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) for (size_t i = 0; i < size; ++i) { ContainerNode* ancestor = ancestors[i].get(); event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor)); - ancestor->handleLocalEvents(event.get(), false); + ancestor->handleLocalEvents(event.get()); if (event->propagationStopped() || event->cancelBubble()) goto doneDispatching; } if (targetForWindowEvents) { event->setCurrentTarget(targetForWindowEvents); - targetForWindowEvents->handleEvent(event.get(), false); + targetForWindowEvents->fireEventListeners(event.get()); if (event->propagationStopped() || event->cancelBubble()) goto doneDispatching; } @@ -2649,6 +2650,11 @@ doneDispatching: } doneWithDefault: +#if ENABLE(INSPECTOR) + if (timelineAgent) + timelineAgent->didDispatchDOMEvent(); +#endif + Document::updateStyleForAllDocuments(); return !event->defaultPrevented(); @@ -2665,8 +2671,7 @@ void Node::dispatchSubtreeModifiedEvent() if (!document()->hasListenerType(Document::DOMSUBTREEMODIFIED_LISTENER)) return; - ExceptionCode ec = 0; - dispatchMutationEvent(eventNames().DOMSubtreeModifiedEvent, true, 0, String(), String(), ec); + dispatchEvent(MutationEvent::create(eventNames().DOMSubtreeModifiedEvent, true)); } void Node::dispatchUIEvent(const AtomicString& eventType, int detail, PassRefPtr<Event> underlyingEvent) @@ -2676,18 +2681,15 @@ void Node::dispatchUIEvent(const AtomicString& eventType, int detail, PassRefPtr bool cancelable = eventType == eventNames().DOMActivateEvent; - ExceptionCode ec = 0; - RefPtr<UIEvent> evt = UIEvent::create(eventType, true, cancelable, document()->defaultView(), detail); - evt->setUnderlyingEvent(underlyingEvent); - dispatchEvent(evt.release(), ec); + RefPtr<UIEvent> event = UIEvent::create(eventType, true, cancelable, document()->defaultView(), detail); + event->setUnderlyingEvent(underlyingEvent); + dispatchEvent(event.release()); } bool Node::dispatchKeyEvent(const PlatformKeyboardEvent& key) { - ASSERT(!eventDispatchForbidden()); - ExceptionCode ec = 0; RefPtr<KeyboardEvent> keyboardEvent = KeyboardEvent::create(key, document()->defaultView()); - bool r = dispatchEvent(keyboardEvent, ec); + bool r = dispatchEvent(keyboardEvent); // we want to return false if default is prevented (already taken care of) // or if the element is default-handled by the DOM. Otherwise we let it just @@ -2781,8 +2783,6 @@ bool Node::dispatchMouseEvent(const AtomicString& eventType, int button, int det bool cancelable = eventType != eventNames().mousemoveEvent; - ExceptionCode ec = 0; - bool swallowEvent = false; // Attempting to dispatch with a non-EventTarget relatedTarget causes the relatedTarget to be silently ignored. @@ -2807,7 +2807,7 @@ bool Node::dispatchMouseEvent(const AtomicString& eventType, int button, int det mouseEvent->setUnderlyingEvent(underlyingEvent.get()); mouseEvent->setAbsoluteLocation(IntPoint(pageX, pageY)); - dispatchEvent(mouseEvent, ec); + dispatchEvent(mouseEvent); bool defaultHandled = mouseEvent->defaultHandled(); bool defaultPrevented = mouseEvent->defaultPrevented(); if (defaultHandled || defaultPrevented) @@ -2825,7 +2825,7 @@ bool Node::dispatchMouseEvent(const AtomicString& eventType, int button, int det doubleClickEvent->setUnderlyingEvent(underlyingEvent.get()); if (defaultHandled) doubleClickEvent->setDefaultHandled(); - dispatchEvent(doubleClickEvent, ec); + dispatchEvent(doubleClickEvent); if (doubleClickEvent->defaultHandled() || doubleClickEvent->defaultPrevented()) swallowEvent = true; } @@ -2862,102 +2862,18 @@ void Node::dispatchWheelEvent(PlatformWheelEvent& e) we->setAbsoluteLocation(IntPoint(pos.x(), pos.y())); - ExceptionCode ec = 0; - if (!dispatchEvent(we.release(), ec)) + if (!dispatchEvent(we.release())) e.accept(); } -void Node::dispatchWebKitAnimationEvent(const AtomicString& eventType, const String& animationName, double elapsedTime) -{ - ASSERT(!eventDispatchForbidden()); - - ExceptionCode ec = 0; - dispatchEvent(WebKitAnimationEvent::create(eventType, animationName, elapsedTime), ec); -} - -void Node::dispatchWebKitTransitionEvent(const AtomicString& eventType, const String& propertyName, double elapsedTime) -{ - ASSERT(!eventDispatchForbidden()); - - ExceptionCode ec = 0; - dispatchEvent(WebKitTransitionEvent::create(eventType, propertyName, elapsedTime), ec); -} - -void Node::dispatchMutationEvent(const AtomicString& eventType, bool canBubble, PassRefPtr<Node> relatedNode, const String& prevValue, const String& newValue, ExceptionCode& ec) -{ - ASSERT(!eventDispatchForbidden()); - - dispatchEvent(MutationEvent::create(eventType, canBubble, false, relatedNode, prevValue, newValue, String(), 0), ec); -} - void Node::dispatchFocusEvent() { - dispatchEvent(eventNames().focusEvent, false, false); + dispatchEvent(Event::create(eventNames().focusEvent, false, false)); } void Node::dispatchBlurEvent() { - dispatchEvent(eventNames().blurEvent, false, false); -} - -bool Node::dispatchEvent(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg) -{ - ASSERT(!eventDispatchForbidden()); - ExceptionCode ec = 0; - return dispatchEvent(Event::create(eventType, canBubbleArg, cancelableArg), ec); -} - -void Node::dispatchProgressEvent(const AtomicString &eventType, bool lengthComputableArg, unsigned loadedArg, unsigned totalArg) -{ - ASSERT(!eventDispatchForbidden()); - ExceptionCode ec = 0; - dispatchEvent(ProgressEvent::create(eventType, lengthComputableArg, loadedArg, totalArg), ec); -} - -void Node::clearAttributeEventListener(const AtomicString& eventType) -{ - if (!hasRareData()) - return; - - RegisteredEventListenerVector* listeners = rareData()->listeners(); - if (!listeners) - return; - - size_t size = listeners->size(); - for (size_t i = 0; i < size; ++i) { - RegisteredEventListener& r = *listeners->at(i); - if (r.eventType() != eventType || !r.listener()->isAttribute()) - continue; - - r.setRemoved(true); - listeners->remove(i); - - // removed last - if (listeners->isEmpty() && !inDocument()) - document()->unregisterDisconnectedNodeWithEventListeners(this); - - updateSVGElementInstancesAfterEventListenerChange(this); - return; - } -} - -void Node::setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener) -{ - clearAttributeEventListener(eventType); - if (listener) - addEventListener(eventType, listener, false); -} - -EventListener* Node::getAttributeEventListener(const AtomicString& eventType) const -{ - const RegisteredEventListenerVector& listeners = eventListeners(); - size_t size = listeners.size(); - for (size_t i = 0; i < size; ++i) { - const RegisteredEventListener& r = *listeners[i]; - if (r.eventType() == eventType && r.listener()->isAttribute()) - return r.listener(); - } - return 0; + dispatchEvent(Event::create(eventNames().blurEvent, false, false)); } bool Node::disabled() const @@ -2977,10 +2893,12 @@ void Node::defaultEventHandler(Event* event) } else if (eventType == eventNames().clickEvent) { int detail = event->isUIEvent() ? static_cast<UIEvent*>(event)->detail() : 0; dispatchUIEvent(eventNames().DOMActivateEvent, detail, event); +#if ENABLE(CONTEXT_MENUS) } else if (eventType == eventNames().contextmenuEvent) { if (Frame* frame = document()->frame()) if (Page* page = frame->page()) page->contextMenuController()->handleContextMenuEvent(event); +#endif } else if (eventType == eventNames().textInputEvent) { if (event->isTextEvent()) if (Frame* frame = document()->frame()) @@ -2988,438 +2906,6 @@ void Node::defaultEventHandler(Event* event) } } -EventListener* Node::onabort() const -{ - return getAttributeEventListener(eventNames().abortEvent); -} - -void Node::setOnabort(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().abortEvent, eventListener); -} - -EventListener* Node::onblur() const -{ - return getAttributeEventListener(eventNames().blurEvent); -} - -void Node::setOnblur(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().blurEvent, eventListener); -} - -EventListener* Node::onchange() const -{ - return getAttributeEventListener(eventNames().changeEvent); -} - -void Node::setOnchange(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().changeEvent, eventListener); -} - -EventListener* Node::onclick() const -{ - return getAttributeEventListener(eventNames().clickEvent); -} - -void Node::setOnclick(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().clickEvent, eventListener); -} - -EventListener* Node::oncontextmenu() const -{ - return getAttributeEventListener(eventNames().contextmenuEvent); -} - -void Node::setOncontextmenu(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().contextmenuEvent, eventListener); -} - -EventListener* Node::ondblclick() const -{ - return getAttributeEventListener(eventNames().dblclickEvent); -} - -void Node::setOndblclick(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().dblclickEvent, eventListener); -} - -EventListener* Node::onerror() const -{ - return getAttributeEventListener(eventNames().errorEvent); -} - -void Node::setOnerror(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().errorEvent, eventListener); -} - -EventListener* Node::onfocus() const -{ - return getAttributeEventListener(eventNames().focusEvent); -} - -void Node::setOnfocus(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().focusEvent, eventListener); -} - -EventListener* Node::oninput() const -{ - return getAttributeEventListener(eventNames().inputEvent); -} - -void Node::setOninput(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().inputEvent, eventListener); -} - -EventListener* Node::onkeydown() const -{ - return getAttributeEventListener(eventNames().keydownEvent); -} - -void Node::setOnkeydown(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().keydownEvent, eventListener); -} - -EventListener* Node::onkeypress() const -{ - return getAttributeEventListener(eventNames().keypressEvent); -} - -void Node::setOnkeypress(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().keypressEvent, eventListener); -} - -EventListener* Node::onkeyup() const -{ - return getAttributeEventListener(eventNames().keyupEvent); -} - -void Node::setOnkeyup(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().keyupEvent, eventListener); -} - -EventListener* Node::onload() const -{ - return getAttributeEventListener(eventNames().loadEvent); -} - -void Node::setOnload(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().loadEvent, eventListener); -} - -EventListener* Node::onmousedown() const -{ - return getAttributeEventListener(eventNames().mousedownEvent); -} - -void Node::setOnmousedown(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().mousedownEvent, eventListener); -} - -EventListener* Node::onmousemove() const -{ - return getAttributeEventListener(eventNames().mousemoveEvent); -} - -void Node::setOnmousemove(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().mousemoveEvent, eventListener); -} - -EventListener* Node::onmouseout() const -{ - return getAttributeEventListener(eventNames().mouseoutEvent); -} - -void Node::setOnmouseout(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().mouseoutEvent, eventListener); -} - -EventListener* Node::onmouseover() const -{ - return getAttributeEventListener(eventNames().mouseoverEvent); -} - -void Node::setOnmouseover(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().mouseoverEvent, eventListener); -} - -EventListener* Node::onmouseup() const -{ - return getAttributeEventListener(eventNames().mouseupEvent); -} - -void Node::setOnmouseup(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().mouseupEvent, eventListener); -} - -EventListener* Node::onmousewheel() const -{ - return getAttributeEventListener(eventNames().mousewheelEvent); -} - -void Node::setOnmousewheel(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().mousewheelEvent, eventListener); -} - -EventListener* Node::ondragenter() const -{ - return getAttributeEventListener(eventNames().dragenterEvent); -} - -void Node::setOndragenter(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().dragenterEvent, eventListener); -} - -EventListener* Node::ondragover() const -{ - return getAttributeEventListener(eventNames().dragoverEvent); -} - -void Node::setOndragover(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().dragoverEvent, eventListener); -} - -EventListener* Node::ondragleave() const -{ - return getAttributeEventListener(eventNames().dragleaveEvent); -} - -void Node::setOndragleave(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().dragleaveEvent, eventListener); -} - -EventListener* Node::ondrop() const -{ - return getAttributeEventListener(eventNames().dropEvent); -} - -void Node::setOndrop(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().dropEvent, eventListener); -} - -EventListener* Node::ondragstart() const -{ - return getAttributeEventListener(eventNames().dragstartEvent); -} - -void Node::setOndragstart(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().dragstartEvent, eventListener); -} - -EventListener* Node::ondrag() const -{ - return getAttributeEventListener(eventNames().dragEvent); -} - -void Node::setOndrag(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().dragEvent, eventListener); -} - -EventListener* Node::ondragend() const -{ - return getAttributeEventListener(eventNames().dragendEvent); -} - -void Node::setOndragend(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().dragendEvent, eventListener); -} - -EventListener* Node::onscroll() const -{ - return getAttributeEventListener(eventNames().scrollEvent); -} - -void Node::setOnscroll(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().scrollEvent, eventListener); -} - -EventListener* Node::onselect() const -{ - return getAttributeEventListener(eventNames().selectEvent); -} - -void Node::setOnselect(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().selectEvent, eventListener); -} - -EventListener* Node::onsubmit() const -{ - return getAttributeEventListener(eventNames().submitEvent); -} - -void Node::setOnsubmit(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().submitEvent, eventListener); -} - -EventListener* Node::onbeforecut() const -{ - return getAttributeEventListener(eventNames().beforecutEvent); -} - -void Node::setOnbeforecut(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().beforecutEvent, eventListener); -} - -EventListener* Node::oncut() const -{ - return getAttributeEventListener(eventNames().cutEvent); -} - -void Node::setOncut(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().cutEvent, eventListener); -} - -EventListener* Node::onbeforecopy() const -{ - return getAttributeEventListener(eventNames().beforecopyEvent); -} - -void Node::setOnbeforecopy(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().beforecopyEvent, eventListener); -} - -EventListener* Node::oncopy() const -{ - return getAttributeEventListener(eventNames().copyEvent); -} - -void Node::setOncopy(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().copyEvent, eventListener); -} - -EventListener* Node::onbeforepaste() const -{ - return getAttributeEventListener(eventNames().beforepasteEvent); -} - -void Node::setOnbeforepaste(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().beforepasteEvent, eventListener); -} - -EventListener* Node::onpaste() const -{ - return getAttributeEventListener(eventNames().pasteEvent); -} - -void Node::setOnpaste(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().pasteEvent, eventListener); -} - -EventListener* Node::onreset() const -{ - return getAttributeEventListener(eventNames().resetEvent); -} - -void Node::setOnreset(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().resetEvent, eventListener); -} - -EventListener* Node::onsearch() const -{ - return getAttributeEventListener(eventNames().searchEvent); -} - -void Node::setOnsearch(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().searchEvent, eventListener); -} - -EventListener* Node::onselectstart() const -{ - return getAttributeEventListener(eventNames().selectstartEvent); -} - -void Node::setOnselectstart(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().selectstartEvent, eventListener); -} - -EventListener* Node::onunload() const -{ - return getAttributeEventListener(eventNames().unloadEvent); -} - -void Node::setOnunload(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().unloadEvent, eventListener); -} - -#if ENABLE(TOUCH_EVENTS) // Android -EventListener* Node::ontouchstart() const -{ - return getAttributeEventListener(eventNames().touchstartEvent); -} - -void Node::setOntouchstart(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().touchstartEvent, eventListener); -} - -EventListener* Node::ontouchend() const -{ - return getAttributeEventListener(eventNames().touchendEvent); -} - -void Node::setOntouchend(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().touchendEvent, eventListener); -} - -EventListener* Node::ontouchmove() const -{ - return getAttributeEventListener(eventNames().touchmoveEvent); -} - -void Node::setOntouchmove(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().touchmoveEvent, eventListener); -} - -EventListener* Node::ontouchcancel() const -{ - return getAttributeEventListener(eventNames().touchcancelEvent); -} - -void Node::setOntouchcancel(PassRefPtr<EventListener> eventListener) -{ - setAttributeEventListener(eventNames().touchcancelEvent, eventListener); -} -#endif // ENABLE(TOUCH_EVENT) - } // namespace WebCore #ifndef NDEBUG diff --git a/WebCore/dom/Node.h b/WebCore/dom/Node.h index f10e830..082ab16 100644 --- a/WebCore/dom/Node.h +++ b/WebCore/dom/Node.h @@ -25,7 +25,6 @@ #ifndef Node_h #define Node_h -#include "DocPtr.h" #include "EventTarget.h" #include "KURLHash.h" #include "PlatformString.h" @@ -68,7 +67,10 @@ class StringBuilder; typedef int ExceptionCode; -enum StyleChangeType { NoStyleChange, InlineStyleChange, FullStyleChange, AnimationStyleChange }; +// SyntheticStyleChange means that we need to go through the entire style change logic even though +// no style property has actually changed. It is used to restructure the tree when, for instance, +// RenderLayers are created or destroyed due to animation changes. +enum StyleChangeType { NoStyleChange, InlineStyleChange, FullStyleChange, SyntheticStyleChange }; const unsigned short DOCUMENT_POSITION_EQUIVALENT = 0x00; const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01; @@ -108,7 +110,6 @@ public: enum StyleChange { NoChange, NoInherit, Inherit, Detach, Force }; static StyleChange diff(const RenderStyle*, const RenderStyle*); - Node(Document*, bool isElement = false, bool isContainer = false, bool isText = false); virtual ~Node(); // DOM methods & attributes for Node @@ -182,6 +183,14 @@ public: static bool isWMLElement() { return false; } #endif +#if ENABLE(MATHML) + virtual bool isMathMLElement() const { return false; } +#else + static bool isMathMLElement() { return false; } +#endif + + + virtual bool isMediaControlElement() const { return false; } virtual bool isStyledElement() const { return false; } virtual bool isFrameOwnerElement() const { return false; } virtual bool isAttributeNode() const { return false; } @@ -197,6 +206,9 @@ public: // The node's parent for the purpose of event capture and bubbling. virtual ContainerNode* eventParentNode(); + // Node ancestors when concerned about event flow + void eventAncestors(Vector<RefPtr<ContainerNode> > &ancestors); + bool isBlockFlow() const; bool isBlockFlowOrBlockTable() const; @@ -289,10 +301,10 @@ public: virtual short tabIndex() const; - /** - * Whether this node can receive the keyboard focus. - */ - virtual bool supportsFocus() const { return isFocusable(); } + // Whether this kind of node can receive focus by default. Most nodes are + // not focusable but some elements, such as form controls and links are. + virtual bool supportsFocus() const; + // Whether the node can actually be focused. virtual bool isFocusable() const; virtual bool isKeyboardFocusable(KeyboardEvent*) const; virtual bool isMouseFocusable() const; @@ -316,7 +328,7 @@ public: { ASSERT(this); ASSERT(m_document || (nodeType() == DOCUMENT_TYPE_NODE && !inDocument())); - return m_document.get(); + return m_document; } void setDocument(Document*); @@ -501,44 +513,33 @@ public: #ifdef ANDROID_INSTRUMENT // Overridden to prevent the normal new from being called. - void* operator new(size_t) throw(); + void* operator new(size_t size); + void* operator new[](size_t size); // Overridden to prevent the normal delete from being called. - void operator delete(void*, size_t); + void operator delete(void* p, size_t size); + void operator delete[](void* p, size_t size); static size_t reportDOMNodesSize(); #endif -protected: - virtual void willMoveToNewOwnerDocument(); - virtual void didMoveToNewOwnerDocument(); - - virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const { } - void setTabIndexExplicitly(short); - - bool hasRareData() const { return m_hasRareData; } - - NodeRareData* rareData() const; - NodeRareData* ensureRareData(); - -public: virtual Node* toNode() { return this; } virtual ScriptExecutionContext* scriptExecutionContext() const; - // Used for standard DOM addEventListener / removeEventListener APIs. - virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture); - virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture); + virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture); + virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture); - // Used for legacy "onEvent" property APIs. - void setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener>); - void clearAttributeEventListener(const AtomicString& eventType); - EventListener* getAttributeEventListener(const AtomicString& eventType) const; + // Handlers to do/undo actions on the target node before an event is dispatched to it and after the event + // has been dispatched. The data pointer is handed back by the preDispatch and passed to postDispatch. + virtual void* preDispatchEventHandler(Event*) { return 0; } + virtual void postDispatchEventHandler(Event*, void* /*dataFromPreDispatch*/) { } - virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&); - bool dispatchEvent(const AtomicString& eventType, bool canBubble, bool cancelable); + using EventTarget::dispatchEvent; + virtual bool dispatchEvent(PassRefPtr<Event>); - void removeAllEventListeners() { if (hasRareData()) removeAllEventListenersSlowCase(); } + bool dispatchGenericEvent(PassRefPtr<Event>); + virtual void handleLocalEvents(Event*); void dispatchSubtreeModifiedEvent(); void dispatchUIEvent(const AtomicString& eventType, int detail, PassRefPtr<Event> underlyingEvent); @@ -552,14 +553,6 @@ public: bool isSimulated, Node* relatedTarget, PassRefPtr<Event> underlyingEvent); void dispatchSimulatedMouseEvent(const AtomicString& eventType, PassRefPtr<Event> underlyingEvent); void dispatchSimulatedClick(PassRefPtr<Event> underlyingEvent, bool sendMouseEvents = false, bool showPressedLook = true); - void dispatchProgressEvent(const AtomicString& eventType, bool lengthComputableArg, unsigned loadedArg, unsigned totalArg); - void dispatchWebKitAnimationEvent(const AtomicString& eventType, const String& animationName, double elapsedTime); - void dispatchWebKitTransitionEvent(const AtomicString& eventType, const String& propertyName, double elapsedTime); - void dispatchMutationEvent(const AtomicString& type, bool canBubble, PassRefPtr<Node> relatedNode, const String& prevValue, const String& newValue, ExceptionCode&); - - bool dispatchGenericEvent(PassRefPtr<Event>); - - virtual void handleLocalEvents(Event*, bool useCapture); virtual void dispatchFocusEvent(); virtual void dispatchBlurEvent(); @@ -575,112 +568,47 @@ public: */ virtual bool disabled() const; - const RegisteredEventListenerVector& eventListeners() const; - - // These 4 attribute event handler attributes are overrided by HTMLBodyElement - // and HTMLFrameSetElement to forward to the DOMWindow. - virtual EventListener* onblur() const; - virtual void setOnblur(PassRefPtr<EventListener>); - virtual EventListener* onerror() const; - virtual void setOnerror(PassRefPtr<EventListener>); - virtual EventListener* onfocus() const; - virtual void setOnfocus(PassRefPtr<EventListener>); - virtual EventListener* onload() const; - virtual void setOnload(PassRefPtr<EventListener>); - - EventListener* onabort() const; - void setOnabort(PassRefPtr<EventListener>); - EventListener* onchange() const; - void setOnchange(PassRefPtr<EventListener>); - EventListener* onclick() const; - void setOnclick(PassRefPtr<EventListener>); - EventListener* oncontextmenu() const; - void setOncontextmenu(PassRefPtr<EventListener>); - EventListener* ondblclick() const; - void setOndblclick(PassRefPtr<EventListener>); - EventListener* oninput() const; - void setOninput(PassRefPtr<EventListener>); - EventListener* onkeydown() const; - void setOnkeydown(PassRefPtr<EventListener>); - EventListener* onkeypress() const; - void setOnkeypress(PassRefPtr<EventListener>); - EventListener* onkeyup() const; - void setOnkeyup(PassRefPtr<EventListener>); - EventListener* onmousedown() const; - void setOnmousedown(PassRefPtr<EventListener>); - EventListener* onmousemove() const; - void setOnmousemove(PassRefPtr<EventListener>); - EventListener* onmouseout() const; - void setOnmouseout(PassRefPtr<EventListener>); - EventListener* onmouseover() const; - void setOnmouseover(PassRefPtr<EventListener>); - EventListener* onmouseup() const; - void setOnmouseup(PassRefPtr<EventListener>); - EventListener* onmousewheel() const; - void setOnmousewheel(PassRefPtr<EventListener>); - EventListener* ondragenter() const; - void setOndragenter(PassRefPtr<EventListener>); - EventListener* ondragover() const; - void setOndragover(PassRefPtr<EventListener>); - EventListener* ondragleave() const; - void setOndragleave(PassRefPtr<EventListener>); - EventListener* ondrop() const; - void setOndrop(PassRefPtr<EventListener>); - EventListener* ondragstart() const; - void setOndragstart(PassRefPtr<EventListener>); - EventListener* ondrag() const; - void setOndrag(PassRefPtr<EventListener>); - EventListener* ondragend() const; - void setOndragend(PassRefPtr<EventListener>); - EventListener* onscroll() const; - void setOnscroll(PassRefPtr<EventListener>); - EventListener* onselect() const; - void setOnselect(PassRefPtr<EventListener>); - EventListener* onsubmit() const; - void setOnsubmit(PassRefPtr<EventListener>); - - // WebKit extensions - EventListener* onbeforecut() const; - void setOnbeforecut(PassRefPtr<EventListener>); - EventListener* oncut() const; - void setOncut(PassRefPtr<EventListener>); - EventListener* onbeforecopy() const; - void setOnbeforecopy(PassRefPtr<EventListener>); - EventListener* oncopy() const; - void setOncopy(PassRefPtr<EventListener>); - EventListener* onbeforepaste() const; - void setOnbeforepaste(PassRefPtr<EventListener>); - EventListener* onpaste() const; - void setOnpaste(PassRefPtr<EventListener>); - EventListener* onreset() const; - void setOnreset(PassRefPtr<EventListener>); - EventListener* onsearch() const; - void setOnsearch(PassRefPtr<EventListener>); - EventListener* onselectstart() const; - void setOnselectstart(PassRefPtr<EventListener>); - EventListener* onunload() const; - void setOnunload(PassRefPtr<EventListener>); #if ENABLE(TOUCH_EVENTS) // Android - EventListener* ontouchstart() const; - void setOntouchstart(PassRefPtr<EventListener>); - EventListener* ontouchend() const; - void setOntouchend(PassRefPtr<EventListener>); - EventListener* ontouchmove() const; - void setOntouchmove(PassRefPtr<EventListener>); - EventListener* ontouchcancel() const; - void setOntouchcancel(PassRefPtr<EventListener>); + DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart); + DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend); + DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove); + DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel); #endif using TreeShared<Node>::ref; using TreeShared<Node>::deref; - + + virtual EventTargetData* eventTargetData(); + virtual EventTargetData* ensureEventTargetData(); + +protected: + // CreateElementZeroRefCount is deprecated and can be removed once we convert all element + // classes to start with a reference count of 1. + enum ConstructionType { CreateContainer, CreateElement, CreateOther, CreateText, CreateElementZeroRefCount }; + Node(Document*, ConstructionType); + + virtual void willMoveToNewOwnerDocument(); + virtual void didMoveToNewOwnerDocument(); + + virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const { } + void setTabIndexExplicitly(short); + + bool hasRareData() const { return m_hasRareData; } + + NodeRareData* rareData() const; + NodeRareData* ensureRareData(); + private: + static bool initialRefCount(ConstructionType); + static bool isContainer(ConstructionType); + static bool isElement(ConstructionType); + static bool isText(ConstructionType); + virtual void refEventTarget() { ref(); } virtual void derefEventTarget() { deref(); } void removeAllEventListenersSlowCase(); -private: virtual NodeRareData* createRareData(); Node* containerChildNode(unsigned index) const; unsigned containerChildNodeCount() const; @@ -698,7 +626,7 @@ private: void appendTextContent(bool convertBRsToNewlines, StringBuilder&) const; - DocPtr<Document> m_document; + Document* m_document; Node* m_previous; Node* m_next; RenderObject* m_renderer; @@ -721,22 +649,16 @@ private: const bool m_isText : 1; protected: - // These bits are used by the Element derived class, pulled up here so they can + // These bits are used by derived classes, pulled up here so they can // be stored in the same memory word as the Node bits above. - bool m_parsingChildrenFinished : 1; -#if ENABLE(SVG) - mutable bool m_areSVGAttributesValid : 1; -#endif - // These bits are used by the StyledElement derived class, and live here for the - // same reason as above. - mutable bool m_isStyleAttributeValid : 1; - mutable bool m_synchronizingStyleAttribute : 1; + bool m_parsingChildrenFinished : 1; // Element + mutable bool m_isStyleAttributeValid : 1; // StyledElement + mutable bool m_synchronizingStyleAttribute : 1; // StyledElement #if ENABLE(SVG) - // This bit is used by the SVGElement derived class, and lives here for the same - // reason as above. - mutable bool m_synchronizingSVGAttributes : 1; + mutable bool m_areSVGAttributesValid : 1; // Element + mutable bool m_synchronizingSVGAttributes : 1; // SVGElement #endif // 11 bits remaining diff --git a/WebCore/dom/Node.idl b/WebCore/dom/Node.idl index 1e31aea..45ea132 100644 --- a/WebCore/dom/Node.idl +++ b/WebCore/dom/Node.idl @@ -24,6 +24,7 @@ module core { CustomMarkFunction, CustomPushEventHandlerScope, CustomToJS, + EventTarget, GenerateConstructor, GenerateNativeConverter, InlineGetOwnPropertySlot, diff --git a/WebCore/dom/NodeRareData.h b/WebCore/dom/NodeRareData.h index 7740344..8b9e1bf 100644 --- a/WebCore/dom/NodeRareData.h +++ b/WebCore/dom/NodeRareData.h @@ -93,12 +93,12 @@ public: void setTabIndexExplicitly(short index) { m_tabIndex = index; m_tabIndexWasSetExplicitly = true; } bool tabIndexSetExplicitly() const { return m_tabIndexWasSetExplicitly; } - RegisteredEventListenerVector* listeners() { return m_eventListeners.get(); } - RegisteredEventListenerVector& ensureListeners() + EventTargetData* eventTargetData() { return m_eventTargetData.get(); } + EventTargetData* ensureEventTargetData() { - if (!m_eventListeners) - m_eventListeners.set(new RegisteredEventListenerVector); - return *m_eventListeners; + if (!m_eventTargetData) + m_eventTargetData.set(new EventTargetData); + return m_eventTargetData.get(); } bool isFocused() const { return m_isFocused; } @@ -111,7 +111,7 @@ protected: private: OwnPtr<NodeListsNodeData> m_nodeLists; - OwnPtr<RegisteredEventListenerVector > m_eventListeners; + OwnPtr<EventTargetData> m_eventTargetData; short m_tabIndex; bool m_tabIndexWasSetExplicitly : 1; bool m_isFocused : 1; diff --git a/WebCore/dom/Notation.cpp b/WebCore/dom/Notation.cpp index 7081d98..cade384 100644 --- a/WebCore/dom/Notation.cpp +++ b/WebCore/dom/Notation.cpp @@ -1,8 +1,6 @@ -/** - * This file is part of the DOM implementation for KDE. - * +/* * Copyright (C) 2000 Peter Kelly (pmk@post.com) - * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2006, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -19,17 +17,14 @@ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ + #include "config.h" #include "Notation.h" namespace WebCore { -Notation::Notation(Document* doc) : ContainerNode(doc) -{ -} - -Notation::Notation(Document* doc, const String& name, const String& publicId, const String& systemId) - : ContainerNode(doc) +Notation::Notation(Document* document, const String& name, const String& publicId, const String& systemId) + : ContainerNode(document) , m_name(name) , m_publicId(publicId) , m_systemId(systemId) @@ -52,7 +47,6 @@ PassRefPtr<Node> Notation::cloneNode(bool /*deep*/) return 0; } -// DOM Section 1.1.1 bool Notation::childTypeAllowed(NodeType) { return false; diff --git a/WebCore/dom/Notation.h b/WebCore/dom/Notation.h index 2bd5363..547c9e7 100644 --- a/WebCore/dom/Notation.h +++ b/WebCore/dom/Notation.h @@ -1,8 +1,6 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 2000 Peter Kelly (pmk@post.com) - * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2006, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -24,26 +22,25 @@ #ifndef Notation_h #define Notation_h -#include "CachedResourceClient.h" #include "ContainerNode.h" namespace WebCore { +// FIXME: This class is never instantiated. Maybe it should be removed. + class Notation : public ContainerNode { public: - Notation(Document*); - Notation(Document*, const String& name, const String& publicId, const String& systemId); + const String& publicId() const { return m_publicId; } + const String& systemId() const { return m_systemId; } - // DOM methods & attributes for Notation - String publicId() const { return m_publicId; } - String systemId() const { return m_systemId; } +private: + Notation(Document*, const String& name, const String& publicId, const String& systemId); virtual String nodeName() const; virtual NodeType nodeType() const; virtual PassRefPtr<Node> cloneNode(bool deep); virtual bool childTypeAllowed(NodeType); -private: String m_name; String m_publicId; String m_systemId; diff --git a/WebCore/dom/PageTransitionEvent.cpp b/WebCore/dom/PageTransitionEvent.cpp new file mode 100644 index 0000000..f9c487d --- /dev/null +++ b/WebCore/dom/PageTransitionEvent.cpp @@ -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 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 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 "PageTransitionEvent.h" + +#include "EventNames.h" + +namespace WebCore { + +PageTransitionEvent::PageTransitionEvent() + : m_persisted(false) +{ +} + +PageTransitionEvent::PageTransitionEvent(const AtomicString& type, bool persisted) + : Event(type, true, true) + , m_persisted(persisted) +{ +} + +PageTransitionEvent::~PageTransitionEvent() +{ +} + +void PageTransitionEvent::initPageTransitionEvent(const AtomicString& type, + bool canBubbleArg, + bool cancelableArg, + bool persisted) +{ + if (dispatched()) + return; + + initEvent(type, canBubbleArg, cancelableArg); + + m_persisted = persisted; +} + +} // namespace WebCore diff --git a/WebCore/dom/PageTransitionEvent.h b/WebCore/dom/PageTransitionEvent.h new file mode 100644 index 0000000..33c5a0c --- /dev/null +++ b/WebCore/dom/PageTransitionEvent.h @@ -0,0 +1,64 @@ +/* + * 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 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 PageTransitionEvent_h +#define PageTransitionEvent_h + +#include "Event.h" + +namespace WebCore { + + class PageTransitionEvent : public Event { + public: + static PassRefPtr<PageTransitionEvent> create() + { + return adoptRef(new PageTransitionEvent); + } + static PassRefPtr<PageTransitionEvent> create(const AtomicString& type, bool persisted) + { + return adoptRef(new PageTransitionEvent(type, persisted)); + } + + virtual ~PageTransitionEvent(); + + void initPageTransitionEvent(const AtomicString& type, + bool canBubbleArg, + bool cancelableArg, + bool persisted); + + virtual bool isPageTransitionEvent() const { return true; } + + bool persisted() const { return m_persisted; } + + private: + PageTransitionEvent(); + PageTransitionEvent(const AtomicString& type, bool persisted); + + bool m_persisted; + }; + +} // namespace WebCore + +#endif // PageTransitionEvent_h diff --git a/WebCore/dom/PageTransitionEvent.idl b/WebCore/dom/PageTransitionEvent.idl new file mode 100644 index 0000000..a09f94b --- /dev/null +++ b/WebCore/dom/PageTransitionEvent.idl @@ -0,0 +1,37 @@ +/* + * 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 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 + ] PageTransitionEvent : Event { + + readonly attribute boolean persisted; + + void initPageTransitionEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in boolean persisted); + }; + +} diff --git a/WebCore/dom/Position.cpp b/WebCore/dom/Position.cpp index 3b4c3e8..060b28c 100644 --- a/WebCore/dom/Position.cpp +++ b/WebCore/dom/Position.cpp @@ -138,10 +138,7 @@ int Position::computeOffsetInContainerNode() const switch (anchorType()) { case PositionIsOffsetInAnchor: - { - int maximumValidOffset = m_anchorNode->offsetInCharacters() ? m_anchorNode->maxCharacterOffset() : m_anchorNode->childNodeCount(); - return std::min(maximumValidOffset, m_offset); - } + return std::min(lastOffsetInNode(m_anchorNode.get()), m_offset); case PositionIsBeforeAnchor: return m_anchorNode->nodeIndex(); case PositionIsAfterAnchor: @@ -1115,28 +1112,7 @@ void Position::showTreeForThis() const #endif -Position startPosition(const Range* r) -{ - return r ? r->startPosition() : Position(); -} - -Position endPosition(const Range* r) -{ - return r ? r->endPosition() : Position(); -} -// NOTE: first/lastDeepEditingPositionForNode can return "editing positions" (like [img, 0]) -// for elements which editing "ignores". the rest of the editing code will treat [img, 0] -// as "the last position before the img" -Position firstDeepEditingPositionForNode(Node* node) -{ - return Position(node, 0); -} - -Position lastDeepEditingPositionForNode(Node* node) -{ - return Position(node, lastOffsetForEditing(node)); -} } // namespace WebCore diff --git a/WebCore/dom/Position.h b/WebCore/dom/Position.h index b434ec9..c08872d 100644 --- a/WebCore/dom/Position.h +++ b/WebCore/dom/Position.h @@ -28,6 +28,7 @@ #include "TextAffinity.h" #include "TextDirection.h" +#include "Node.h" // for position creation functions #include <wtf/Assertions.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> @@ -188,14 +189,53 @@ inline bool operator!=(const Position& a, const Position& b) return !(a == b); } -Position startPosition(const Range*); -Position endPosition(const Range*); +// We define position creation functions to make callsites more readable. +// These are inline to prevent ref-churn when returning a Position object. +// If we ever add a PassPosition we can make these non-inline. -// NOTE: first/lastDeepEditingPositionForNode can return "editing positions" (like [img, 0]) -// for elements which editing "ignores". the rest of the editing code will treat [img, 0] -// as "the last position before the img" -Position firstDeepEditingPositionForNode(Node*); -Position lastDeepEditingPositionForNode(Node*); +inline Position positionInParentBeforeNode(const Node* node) +{ + // FIXME: This should ASSERT(node->parentNode()) + // At least one caller currently hits this ASSERT though, which indicates + // that the caller is trying to make a position relative to a disconnected node (which is likely an error) + // Specifically, editing/deleting/delete-ligature-001.html crashes with ASSERT(node->parentNode()) + return Position(node->parentNode(), node->nodeIndex(), Position::PositionIsOffsetInAnchor); +} + +inline Position positionInParentAfterNode(const Node* node) +{ + ASSERT(node->parentNode()); + return Position(node->parentNode(), node->nodeIndex() + 1, Position::PositionIsOffsetInAnchor); +} + +// positionBeforeNode and positionAfterNode return neighbor-anchored positions, construction is O(1) +inline Position positionBeforeNode(Node* anchorNode) +{ + ASSERT(anchorNode); + return Position(anchorNode, Position::PositionIsBeforeAnchor); +} + +inline Position positionAfterNode(Node* anchorNode) +{ + ASSERT(anchorNode); + return Position(anchorNode, Position::PositionIsAfterAnchor); +} + +inline int lastOffsetInNode(Node* node) +{ + return node->offsetInCharacters() ? node->maxCharacterOffset() : node->childNodeCount(); +} + +// firstPositionInNode and lastPositionInNode return parent-anchored positions, lastPositionInNode construction is O(n) due to childNodeCount() +inline Position firstPositionInNode(Node* anchorNode) +{ + return Position(anchorNode, 0, Position::PositionIsOffsetInAnchor); +} + +inline Position lastPositionInNode(Node* anchorNode) +{ + return Position(anchorNode, lastOffsetInNode(anchorNode), Position::PositionIsOffsetInAnchor); +} } // namespace WebCore diff --git a/WebCore/dom/PositionCreationFunctions.h b/WebCore/dom/PositionCreationFunctions.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/WebCore/dom/PositionCreationFunctions.h diff --git a/WebCore/dom/PositionIterator.cpp b/WebCore/dom/PositionIterator.cpp index a029b5e..8d881ba 100644 --- a/WebCore/dom/PositionIterator.cpp +++ b/WebCore/dom/PositionIterator.cpp @@ -38,7 +38,7 @@ PositionIterator::operator Position() const { if (m_nodeAfterPositionInAnchor) { ASSERT(m_nodeAfterPositionInAnchor->parentNode() == m_anchorNode); - return positionBeforeNode(m_nodeAfterPositionInAnchor); + return positionInParentBeforeNode(m_nodeAfterPositionInAnchor); } if (m_anchorNode->hasChildNodes()) return lastDeepEditingPositionForNode(m_anchorNode); diff --git a/WebCore/dom/ProcessingInstruction.cpp b/WebCore/dom/ProcessingInstruction.cpp index 806bf92..8a94864 100644 --- a/WebCore/dom/ProcessingInstruction.cpp +++ b/WebCore/dom/ProcessingInstruction.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2000 Peter Kelly (pmk@post.com) - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -35,8 +35,10 @@ namespace WebCore { -ProcessingInstruction::ProcessingInstruction(Document* doc) - : ContainerNode(doc) +inline ProcessingInstruction::ProcessingInstruction(Document* document, const String& target, const String& data) + : ContainerNode(document) + , m_target(target) + , m_data(data) , m_cachedSheet(0) , m_loading(false) , m_alternate(false) @@ -46,17 +48,9 @@ ProcessingInstruction::ProcessingInstruction(Document* doc) { } -ProcessingInstruction::ProcessingInstruction(Document* doc, const String& target, const String& data) - : ContainerNode(doc) - , m_target(target) - , m_data(data) - , m_cachedSheet(0) - , m_loading(false) - , m_alternate(false) -#if ENABLE(XSLT) - , m_isXSL(false) -#endif +PassRefPtr<ProcessingInstruction> ProcessingInstruction::create(Document* document, const String& target, const String& data) { + return adoptRef(new ProcessingInstruction(document, target, data)); } ProcessingInstruction::~ProcessingInstruction() @@ -70,6 +64,7 @@ void ProcessingInstruction::setData(const String& data, ExceptionCode&) int oldLength = m_data.length(); m_data = data; document()->textRemoved(this, 0, oldLength); + checkStyleSheet(); } String ProcessingInstruction::nodeName() const @@ -95,8 +90,9 @@ void ProcessingInstruction::setNodeValue(const String& nodeValue, ExceptionCode& PassRefPtr<Node> ProcessingInstruction::cloneNode(bool /*deep*/) { - // ### copy m_localHref - return new ProcessingInstruction(document(), m_target, m_data); + // FIXME: Is it a problem that this does not copy m_localHref? + // What about other data members? + return create(document(), m_target, m_data); } // DOM Section 1.1.1 @@ -147,13 +143,21 @@ void ProcessingInstruction::checkStyleSheet() } #endif } else { + if (m_cachedSheet) { + m_cachedSheet->removeClient(this); + m_cachedSheet = 0; + } + + String url = document()->completeURL(href).string(); + if (!dispatchBeforeLoadEvent(url)) + return; + m_loading = true; document()->addPendingSheet(); - if (m_cachedSheet) - m_cachedSheet->removeClient(this); + #if ENABLE(XSLT) if (m_isXSL) - m_cachedSheet = document()->docLoader()->requestXSLStyleSheet(document()->completeURL(href).string()); + m_cachedSheet = document()->docLoader()->requestXSLStyleSheet(url); else #endif { @@ -161,10 +165,15 @@ void ProcessingInstruction::checkStyleSheet() if (charset.isEmpty()) charset = document()->frame()->loader()->encoding(); - m_cachedSheet = document()->docLoader()->requestCSSStyleSheet(document()->completeURL(href).string(), charset); + m_cachedSheet = document()->docLoader()->requestCSSStyleSheet(url, charset); } if (m_cachedSheet) m_cachedSheet->addClient(this); + else { + // The request may have been denied if (for example) the stylesheet is local and the document is remote. + m_loading = false; + document()->removePendingSheet(); + } } } } @@ -271,4 +280,26 @@ void ProcessingInstruction::finishParsingChildren() ContainerNode::finishParsingChildren(); } +#ifdef ANDROID_INSTRUMENT +void* ProcessingInstruction::operator new(size_t size) +{ + return Node::operator new(size); +} + +void* ProcessingInstruction::operator new[](size_t size) +{ + return Node::operator new[](size); +} + +void ProcessingInstruction::operator delete(void* p, size_t size) +{ + Node::operator delete(p, size); +} + +void ProcessingInstruction::operator delete[](void* p, size_t size) +{ + Node::operator delete[](p, size); +} +#endif + } // namespace diff --git a/WebCore/dom/ProcessingInstruction.h b/WebCore/dom/ProcessingInstruction.h index d133019..61af9cf 100644 --- a/WebCore/dom/ProcessingInstruction.h +++ b/WebCore/dom/ProcessingInstruction.h @@ -1,8 +1,6 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 2000 Peter Kelly (pmk@post.com) - * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2006 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -35,15 +33,36 @@ class CSSStyleSheet; class ProcessingInstruction : public ContainerNode, private CachedResourceClient { public: - ProcessingInstruction(Document*); - ProcessingInstruction(Document*, const String& target, const String& data); + static PassRefPtr<ProcessingInstruction> create(Document*, const String& target, const String& data); virtual ~ProcessingInstruction(); - // DOM methods & attributes for Notation - String target() const { return m_target; } - String data() const { return m_data; } + const String& target() const { return m_target; } + const String& data() const { return m_data; } void setData(const String&, ExceptionCode&); + void setCreatedByParser(bool createdByParser) { m_createdByParser = createdByParser; } + + virtual void finishParsingChildren(); + + const String& localHref() const { return m_localHref; } + StyleSheet* sheet() const { return m_sheet.get(); } + void setCSSStyleSheet(PassRefPtr<CSSStyleSheet>); + +#if ENABLE(XSLT) + bool isXSL() const { return m_isXSL; } +#endif + +private: + ProcessingInstruction(Document*, const String& target, const String& data); + +#ifdef ANDROID_INSTRUMENT + // Overridden to resolve the ambiguous + void* operator new(size_t size); + void* operator new[](size_t size); + void operator delete(void* p, size_t size); + void operator delete[](void* p, size_t size); +#endif + virtual String nodeName() const; virtual NodeType nodeType() const; virtual String nodeValue() const; @@ -55,28 +74,18 @@ public: virtual void insertedIntoDocument(); virtual void removedFromDocument(); - void setCreatedByParser(bool createdByParser) { m_createdByParser = createdByParser; } - virtual void finishParsingChildren(); - // Other methods (not part of DOM) - String localHref() const { return m_localHref; } - StyleSheet* sheet() const { return m_sheet.get(); } void checkStyleSheet(); virtual void setCSSStyleSheet(const String& url, const String& charset, const CachedCSSStyleSheet*); #if ENABLE(XSLT) virtual void setXSLStyleSheet(const String& url, const String& sheet); #endif - void setCSSStyleSheet(PassRefPtr<CSSStyleSheet>); + bool isLoading() const; virtual bool sheetLoaded(); -#if ENABLE(XSLT) - bool isXSL() const { return m_isXSL; } -#endif - virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; -private: void parseStyleSheet(const String& sheet); String m_target; diff --git a/WebCore/dom/Range.cpp b/WebCore/dom/Range.cpp index edee305..122130d 100644 --- a/WebCore/dom/Range.cpp +++ b/WebCore/dom/Range.cpp @@ -3,7 +3,7 @@ * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) * (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -26,13 +26,17 @@ #include "RangeException.h" #include "CString.h" +#include "ClientRect.h" +#include "ClientRectList.h" #include "DocumentFragment.h" +#include "FrameView.h" #include "HTMLElement.h" #include "NodeWithIndex.h" #include "ProcessingInstruction.h" #include "Text.h" #include "TextIterator.h" #include "VisiblePosition.h" +#include "htmlediting.h" #include "markup.h" #include "visible_units.h" #include <stdio.h> @@ -586,7 +590,7 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception RefPtr<DocumentFragment> fragment; if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) - fragment = new DocumentFragment(m_ownerDocument.get()); + fragment = DocumentFragment::create(m_ownerDocument.get()); ec = 0; if (collapsed(ec)) @@ -1798,4 +1802,111 @@ void Range::textNodeSplit(Text* oldNode) boundaryTextNodesSplit(m_end, oldNode); } +void Range::expand(const String& unit, ExceptionCode& ec) +{ + VisiblePosition start(startPosition()); + VisiblePosition end(endPosition()); + if (unit == "word") { + start = startOfWord(start); + end = endOfWord(end); + } else if (unit == "sentence") { + start = startOfSentence(start); + end = endOfSentence(end); + } else if (unit == "block") { + start = startOfParagraph(start); + end = endOfParagraph(end); + } else if (unit == "document") { + start = startOfDocument(start); + end = endOfDocument(end); + } else + return; + setStart(start.deepEquivalent().containerNode(), start.deepEquivalent().computeOffsetInContainerNode(), ec); + setEnd(end.deepEquivalent().containerNode(), end.deepEquivalent().computeOffsetInContainerNode(), ec); +} + +PassRefPtr<ClientRectList> Range::getClientRects() const +{ + if (!m_start.container()) + return 0; + + m_ownerDocument->updateLayoutIgnorePendingStylesheets(); + + Vector<FloatQuad> quads; + getBorderAndTextQuads(quads); + + return ClientRectList::create(quads); +} + +PassRefPtr<ClientRect> Range::getBoundingClientRect() const +{ + if (!m_start.container()) + return 0; + + m_ownerDocument->updateLayoutIgnorePendingStylesheets(); + + Vector<FloatQuad> quads; + getBorderAndTextQuads(quads); + + if (quads.isEmpty()) + return ClientRect::create(); + + IntRect result; + for (size_t i = 0; i < quads.size(); ++i) + result.unite(quads[i].enclosingBoundingBox()); + + return ClientRect::create(result); } + +static void adjustFloatQuadsForScrollAndAbsoluteZoom(Vector<FloatQuad>& quads, Document* document, RenderObject* renderer) +{ + FrameView* view = document->view(); + if (!view) + return; + + IntRect visibleContentRect = view->visibleContentRect(); + for (size_t i = 0; i < quads.size(); ++i) { + quads[i].move(-visibleContentRect.x(), -visibleContentRect.y()); + adjustFloatQuadForAbsoluteZoom(quads[i], renderer); + } +} + +void Range::getBorderAndTextQuads(Vector<FloatQuad>& quads) const +{ + Node* startContainer = m_start.container(); + Node* endContainer = m_end.container(); + Node* stopNode = pastLastNode(); + + HashSet<Node*> nodeSet; + for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) { + if (node->isElementNode()) + nodeSet.add(node); + } + + for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) { + if (node->isElementNode()) { + if (!nodeSet.contains(node->parentNode())) { + if (RenderBoxModelObject* renderBoxModelObject = static_cast<Element*>(node)->renderBoxModelObject()) { + Vector<FloatQuad> elementQuads; + renderBoxModelObject->absoluteQuads(elementQuads); + adjustFloatQuadsForScrollAndAbsoluteZoom(elementQuads, m_ownerDocument.get(), renderBoxModelObject); + + quads.append(elementQuads); + } + } + } else if (node->isTextNode()) { + if (RenderObject* renderer = static_cast<Text*>(node)->renderer()) { + RenderText* renderText = toRenderText(renderer); + int startOffset = (node == startContainer) ? m_start.offset() : 0; + int endOffset = (node == endContainer) ? m_end.offset() : INT_MAX; + + Vector<FloatQuad> textQuads; + renderText->absoluteQuadsForRange(textQuads, startOffset, endOffset); + adjustFloatQuadsForScrollAndAbsoluteZoom(textQuads, m_ownerDocument.get(), renderText); + + quads.append(textQuads); + } + } + } +} + +} // namespace WebCore diff --git a/WebCore/dom/Range.h b/WebCore/dom/Range.h index 1487a7c..e2e282b 100644 --- a/WebCore/dom/Range.h +++ b/WebCore/dom/Range.h @@ -3,7 +3,7 @@ * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) * (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -25,12 +25,15 @@ #ifndef Range_h #define Range_h +#include "FloatQuad.h" #include "RangeBoundaryPoint.h" +#include <wtf/Forward.h> #include <wtf/RefCounted.h> -#include <wtf/Vector.h> namespace WebCore { +class ClientRect; +class ClientRectList; class DocumentFragment; class NodeWithIndex; class Text; @@ -112,6 +115,14 @@ public: void textNodesMerged(NodeWithIndex& oldNode, unsigned offset); void textNodeSplit(Text* oldNode); + // Expand range to a unit (word or sentence or block or document) boundary. + // Please refer to https://bugs.webkit.org/show_bug.cgi?id=27632 comment #5 + // for details. + void expand(const String&, ExceptionCode&); + + PassRefPtr<ClientRectList> getClientRects() const; + PassRefPtr<ClientRect> getBoundingClientRect() const; + #ifndef NDEBUG void formatForDebugger(char* buffer, unsigned length) const; #endif @@ -130,6 +141,8 @@ private: enum ActionType { DELETE_CONTENTS, EXTRACT_CONTENTS, CLONE_CONTENTS }; PassRefPtr<DocumentFragment> processContents(ActionType, ExceptionCode&); + void getBorderAndTextQuads(Vector<FloatQuad>&) const; + RefPtr<Document> m_ownerDocument; RangeBoundaryPoint m_start; RangeBoundaryPoint m_end; diff --git a/WebCore/dom/Range.idl b/WebCore/dom/Range.idl index 0750c32..9024e09 100644 --- a/WebCore/dom/Range.idl +++ b/WebCore/dom/Range.idl @@ -85,6 +85,13 @@ module ranges { void detach() raises(DOMException); +#if defined(LANGUAGE_JAVASCRIPT) || LANGUAGE_JAVASCRIPT + // CSSOM View Module API extensions + + ClientRectList getClientRects(); + ClientRect getBoundingClientRect(); +#endif + // extensions DocumentFragment createContextualFragment(in DOMString html) @@ -112,6 +119,9 @@ module ranges { in long offset) raises(RangeException, DOMException); + void expand(in DOMString unit) + raises(RangeException, DOMException); + #if !defined(LANGUAGE_JAVASCRIPT) || !LANGUAGE_JAVASCRIPT readonly attribute DOMString text; #endif diff --git a/WebCore/dom/RegisteredEventListener.cpp b/WebCore/dom/RegisteredEventListener.cpp index f257e56..e8bc594 100644 --- a/WebCore/dom/RegisteredEventListener.cpp +++ b/WebCore/dom/RegisteredEventListener.cpp @@ -27,12 +27,4 @@ namespace WebCore { -RegisteredEventListener::RegisteredEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) - : m_eventType(eventType) - , m_listener(listener) - , m_useCapture(useCapture) - , m_removed(false) -{ -} - } // namespace WebCore diff --git a/WebCore/dom/RegisteredEventListener.h b/WebCore/dom/RegisteredEventListener.h index 034f6c3..c34a341 100644 --- a/WebCore/dom/RegisteredEventListener.h +++ b/WebCore/dom/RegisteredEventListener.h @@ -29,47 +29,22 @@ namespace WebCore { - class RegisteredEventListener : public RefCounted<RegisteredEventListener> { + class RegisteredEventListener { public: - static PassRefPtr<RegisteredEventListener> create(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) + RegisteredEventListener(PassRefPtr<EventListener> listener, bool useCapture) + : listener(listener) + , useCapture(useCapture) { - return adoptRef(new RegisteredEventListener(eventType, listener, useCapture)); } - const AtomicString& eventType() const { return m_eventType; } - EventListener* listener() const { return m_listener.get(); } - bool useCapture() const { return m_useCapture; } - - bool removed() const { return m_removed; } - void setRemoved(bool removed) { m_removed = removed; } - - private: - RegisteredEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture); - - AtomicString m_eventType; - RefPtr<EventListener> m_listener; - bool m_useCapture; - bool m_removed; + RefPtr<EventListener> listener; + bool useCapture; }; - - typedef Vector<RefPtr<RegisteredEventListener> > RegisteredEventListenerVector; - -#if USE(JSC) - inline void markEventListeners(JSC::MarkStack& markStack, const RegisteredEventListenerVector& listeners) - { - for (size_t i = 0; i < listeners.size(); ++i) - listeners[i]->listener()->markJSFunction(markStack); - } - - inline void invalidateEventListeners(const RegisteredEventListenerVector& listeners) + + inline bool operator==(const RegisteredEventListener& a, const RegisteredEventListener& b) { - // For efficiency's sake, we just set the "removed" bit, instead of - // actually removing the event listener. The node that owns these - // listeners is about to be deleted, anyway. - for (size_t i = 0; i < listeners.size(); ++i) - listeners[i]->setRemoved(true); + return *a.listener == *b.listener && a.useCapture == b.useCapture; } -#endif } // namespace WebCore diff --git a/WebCore/dom/ScriptElement.cpp b/WebCore/dom/ScriptElement.cpp index fe38b46..827aff3 100644 --- a/WebCore/dom/ScriptElement.cpp +++ b/WebCore/dom/ScriptElement.cpp @@ -151,6 +151,9 @@ void ScriptElementData::requestScript(const String& sourceUrl) if (!document->frame()) return; + if (!m_element->dispatchBeforeLoadEvent(sourceUrl)) + return; + ASSERT(!m_cachedScript); m_cachedScript = document->docLoader()->requestScript(sourceUrl, scriptCharset()); m_requested = true; diff --git a/WebCore/dom/ScriptExecutionContext.h b/WebCore/dom/ScriptExecutionContext.h index 3f8febc..bb78b6f 100644 --- a/WebCore/dom/ScriptExecutionContext.h +++ b/WebCore/dom/ScriptExecutionContext.h @@ -44,7 +44,9 @@ namespace WebCore { class String; enum MessageDestination { +#if ENABLE(INSPECTOR) InspectorControllerDestination, +#endif ConsoleDestination, }; diff --git a/WebCore/dom/SelectElement.cpp b/WebCore/dom/SelectElement.cpp index 1eb001e..49713ba 100644 --- a/WebCore/dom/SelectElement.cpp +++ b/WebCore/dom/SelectElement.cpp @@ -48,11 +48,11 @@ #endif // Configure platform-specific behavior when focused pop-up receives arrow/space/return keystroke. -// (PLATFORM(MAC) is always false in Chromium, hence the extra test.) +// (PLATFORM(MAC) and PLATFORM(GTK) are always false in Chromium, hence the extra tests.) #if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) #define ARROW_KEYS_POP_MENU 1 #define SPACE_OR_RETURN_POP_MENU 0 -#elif PLATFORM(GTK) +#elif PLATFORM(GTK) || (PLATFORM(CHROMIUM) && PLATFORM(LINUX)) #define ARROW_KEYS_POP_MENU 0 #define SPACE_OR_RETURN_POP_MENU 1 #else @@ -644,14 +644,16 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) { element->focus(); - if (RenderMenuList* menuList = toRenderMenuList(element->renderer())) { - if (menuList->popupIsVisible()) - menuList->hidePopup(); - else { - // Save the selection so it can be compared to the new selection when we call onChange during setSelectedIndex, - // which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu. - saveLastSelection(data, element); - menuList->showPopup(); + if (element->renderer() && element->renderer()->isMenuList()) { + if (RenderMenuList* menuList = toRenderMenuList(element->renderer())) { + if (menuList->popupIsVisible()) + menuList->hidePopup(); + else { + // Save the selection so it can be compared to the new selection when we call onChange during setSelectedIndex, + // which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu. + saveLastSelection(data, element); + menuList->showPopup(); + } } } event->setDefaultHandled(); @@ -676,7 +678,7 @@ void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element* data.setActiveSelectionState(true); bool multiSelectKeyPressed = false; -#if PLATFORM(MAC) +#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) multiSelectKeyPressed = mouseEvent->metaKey(); #else multiSelectKeyPressed = mouseEvent->ctrlKey(); diff --git a/WebCore/dom/StyledElement.cpp b/WebCore/dom/StyledElement.cpp index 456cc52..5212380 100644 --- a/WebCore/dom/StyledElement.cpp +++ b/WebCore/dom/StyledElement.cpp @@ -101,11 +101,6 @@ void StyledElement::removeMappedAttributeDecl(MappedAttributeEntry entryType, co mappedAttributeDecls->remove(MappedAttributeKey(entryType, attrName.localName().impl(), attrValue.impl())); } -void StyledElement::invalidateStyleAttribute() -{ - m_isStyleAttributeValid = false; -} - void StyledElement::updateStyleAttribute() const { ASSERT(!m_isStyleAttributeValid); @@ -116,8 +111,8 @@ void StyledElement::updateStyleAttribute() const m_synchronizingStyleAttribute = false; } -StyledElement::StyledElement(const QualifiedName& name, Document *doc) - : Element(name, doc) +StyledElement::StyledElement(const QualifiedName& name, Document* document, ConstructionType type) + : Element(name, document, type) { } @@ -280,14 +275,6 @@ CSSStyleDeclaration* StyledElement::style() return getInlineStyleDecl(); } -static inline int toHex(UChar c) -{ - return ((c >= '0' && c <= '9') ? (c - '0') - : ((c >= 'a' && c <= 'f') ? (c - 'a' + 10) - : ((c >= 'A' && c <= 'F') ? (c - 'A' + 10) - : -1))); -} - void StyledElement::addCSSProperty(MappedAttribute* attr, int id, const String &value) { if (!attr->decl()) createMappedDecl(attr); @@ -300,12 +287,6 @@ void StyledElement::addCSSProperty(MappedAttribute* attr, int id, int value) attr->decl()->setProperty(id, value, false); } -void StyledElement::addCSSStringProperty(MappedAttribute* attr, int id, const String &value, CSSPrimitiveValue::UnitTypes type) -{ - if (!attr->decl()) createMappedDecl(attr); - attr->decl()->setStringProperty(id, value, type, false); -} - void StyledElement::addCSSImageProperty(MappedAttribute* attr, int id, const String& url) { if (!attr->decl()) createMappedDecl(attr); @@ -393,10 +374,9 @@ void StyledElement::addCSSColor(MappedAttribute* attr, int id, const String& c) // search forward for digits in the string int numDigits = 0; while (pos < (int)color.length() && numDigits < basicLength) { - int hex = toHex(color[pos]); - colors[component] = (colors[component] << 4); - if (hex > 0) { - colors[component] += hex; + colors[component] <<= 4; + if (isASCIIHexDigit(color[pos])) { + colors[component] += toASCIIHexValue(color[pos]); maxDigit = min(maxDigit, numDigits); } numDigits++; @@ -410,10 +390,9 @@ void StyledElement::addCSSColor(MappedAttribute* attr, int id, const String& c) // normalize to 00-ff. The highest filled digit counts, minimum is 2 digits maxDigit -= 2; - colors[0] >>= 4*maxDigit; - colors[1] >>= 4*maxDigit; - colors[2] >>= 4*maxDigit; - // ASSERT(colors[0] < 0x100 && colors[1] < 0x100 && colors[2] < 0x100); + colors[0] >>= 4 * maxDigit; + colors[1] >>= 4 * maxDigit; + colors[2] >>= 4 * maxDigit; color = String::format("#%02x%02x%02x", colors[0], colors[1], colors[2]); if (attr->decl()->setProperty(id, color, false)) diff --git a/WebCore/dom/StyledElement.h b/WebCore/dom/StyledElement.h index 158992e..85fa7a7 100644 --- a/WebCore/dom/StyledElement.h +++ b/WebCore/dom/StyledElement.h @@ -3,7 +3,7 @@ * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Peter Kelly (pmk@post.com) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -38,54 +38,49 @@ class MappedAttribute; class StyledElement : public Element { public: - StyledElement(const QualifiedName&, Document*); virtual ~StyledElement(); - virtual bool isStyledElement() const { return true; } - NamedMappedAttrMap* mappedAttributes() { return static_cast<NamedMappedAttrMap*>(namedAttrMap.get()); } const NamedMappedAttrMap* mappedAttributes() const { return static_cast<NamedMappedAttrMap*>(namedAttrMap.get()); } + bool hasMappedAttributes() const { return namedAttrMap && mappedAttributes()->hasMappedAttributes(); } bool isMappedAttribute(const QualifiedName& name) const { MappedAttributeEntry res = eNone; mapToEntry(name, res); return res != eNone; } - void addCSSLength(MappedAttribute* attr, int id, const String &value); - void addCSSProperty(MappedAttribute* attr, int id, const String &value); - void addCSSProperty(MappedAttribute* attr, int id, int value); - void addCSSStringProperty(MappedAttribute* attr, int id, const String &value, CSSPrimitiveValue::UnitTypes = CSSPrimitiveValue::CSS_STRING); + void addCSSLength(MappedAttribute*, int id, const String& value); + void addCSSProperty(MappedAttribute*, int id, const String& value); + void addCSSProperty(MappedAttribute*, int id, int value); void addCSSImageProperty(MappedAttribute*, int propertyID, const String& url); - void addCSSColor(MappedAttribute* attr, int id, const String &c); - void createMappedDecl(MappedAttribute* attr); - - static CSSMappedAttributeDeclaration* getMappedAttributeDecl(MappedAttributeEntry type, const QualifiedName& name, const AtomicString& value); + void addCSSColor(MappedAttribute*, int id, const String& color); + + static CSSMappedAttributeDeclaration* getMappedAttributeDecl(MappedAttributeEntry, const QualifiedName& name, const AtomicString& value); static void setMappedAttributeDecl(MappedAttributeEntry, const QualifiedName& name, const AtomicString& value, CSSMappedAttributeDeclaration*); - static void removeMappedAttributeDecl(MappedAttributeEntry type, const QualifiedName& name, const AtomicString& value); + static void removeMappedAttributeDecl(MappedAttributeEntry, const QualifiedName& name, const AtomicString& value); static CSSMappedAttributeDeclaration* getMappedAttributeDecl(MappedAttributeEntry, Attribute*); static void setMappedAttributeDecl(MappedAttributeEntry, Attribute*, CSSMappedAttributeDeclaration*); - + CSSMutableStyleDeclaration* inlineStyleDecl() const { return m_inlineStyleDecl.get(); } virtual bool canHaveAdditionalAttributeStyleDecls() const { return false; } virtual void additionalAttributeStyleDecls(Vector<CSSMutableStyleDeclaration*>&) {}; CSSMutableStyleDeclaration* getInlineStyleDecl(); CSSStyleDeclaration* style(); - void createInlineStyleDecl(); - void destroyInlineStyleDecl(); void invalidateStyleAttribute(); - virtual void updateStyleAttribute() const; - + const ClassNames& classNames() const { ASSERT(hasClass()); ASSERT(mappedAttributes()); return mappedAttributes()->classNames(); } - virtual void attributeChanged(Attribute*, bool preserveDecls = false); - virtual void parseMappedAttribute(MappedAttribute*); virtual bool mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const; - virtual void createAttributeMap() const; + virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value); +protected: + StyledElement(const QualifiedName&, Document*, ConstructionType); + + virtual void attributeChanged(Attribute*, bool preserveDecls = false); + virtual void parseMappedAttribute(MappedAttribute*); virtual void copyNonAttributeProperties(const Element*); virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; -protected: // classAttributeChanged() exists to share code between // parseMappedAttribute (called via setAttribute()) and // svgAttributeChanged (called when element.className.baseValue is set) @@ -93,9 +88,25 @@ protected: virtual void didMoveToNewOwnerDocument(); +private: + virtual bool isStyledElement() const { return true; } + + void createMappedDecl(MappedAttribute*); + + void createInlineStyleDecl(); + void destroyInlineStyleDecl(); + virtual void updateStyleAttribute() const; + + virtual void createAttributeMap() const; + RefPtr<CSSMutableStyleDeclaration> m_inlineStyleDecl; }; +inline void StyledElement::invalidateStyleAttribute() +{ + m_isStyleAttributeValid = false; +} + } //namespace #endif diff --git a/WebCore/dom/Text.cpp b/WebCore/dom/Text.cpp index bbd926b..1ce074a 100644 --- a/WebCore/dom/Text.cpp +++ b/WebCore/dom/Text.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -37,22 +37,18 @@ #include "WMLVariables.h" #endif -namespace WebCore { - -// DOM Section 1.1.1 +using namespace std; -Text::Text(Document* document, const String& text) - : CharacterData(document, text, true) -{ -} +namespace WebCore { -Text::Text(Document* document) - : CharacterData(document, true) +Text::Text(Document* document, const String& data) + : CharacterData(document, data, CreateText) { } -Text::~Text() +PassRefPtr<Text> Text::create(Document* document, const String& data) { + return adoptRef(new Text(document, data)); } PassRefPtr<Text> Text::splitText(unsigned offset, ExceptionCode& ec) @@ -61,14 +57,14 @@ PassRefPtr<Text> Text::splitText(unsigned offset, ExceptionCode& ec) // INDEX_SIZE_ERR: Raised if the specified offset is negative or greater than // the number of 16-bit units in data. - if (offset > m_data->length()) { + if (offset > length()) { ec = INDEX_SIZE_ERR; return 0; } - RefPtr<StringImpl> oldStr = m_data; - RefPtr<Text> newText = createNew(oldStr->substring(offset)); - m_data = oldStr->substring(0, offset); + RefPtr<StringImpl> oldStr = dataImpl(); + RefPtr<Text> newText = virtualCreate(oldStr->substring(offset)); + setDataImpl(oldStr->substring(0, offset)); dispatchModifiedEvent(oldStr.get()); @@ -81,7 +77,7 @@ PassRefPtr<Text> Text::splitText(unsigned offset, ExceptionCode& ec) document()->textNodeSplit(this); if (renderer()) - toRenderText(renderer())->setText(m_data); + toRenderText(renderer())->setText(dataImpl()); return newText.release(); } @@ -199,7 +195,7 @@ Node::NodeType Text::nodeType() const PassRefPtr<Node> Text::cloneNode(bool /*deep*/) { - return document()->createTextNode(m_data); + return create(document(), data()); } bool Text::rendererIsNeeded(RenderStyle *style) @@ -244,7 +240,7 @@ bool Text::rendererIsNeeded(RenderStyle *style) return true; } -RenderObject *Text::createRenderer(RenderArena* arena, RenderStyle*) +RenderObject* Text::createRenderer(RenderArena* arena, RenderStyle*) { #if ENABLE(SVG) if (parentNode()->isSVGElement() @@ -252,17 +248,17 @@ RenderObject *Text::createRenderer(RenderArena* arena, RenderStyle*) && !parentNode()->hasTagName(SVGNames::foreignObjectTag) #endif ) - return new (arena) RenderSVGInlineText(this, m_data); + return new (arena) RenderSVGInlineText(this, dataImpl()); #endif - return new (arena) RenderText(this, m_data); + return new (arena) RenderText(this, dataImpl()); } void Text::attach() { #if ENABLE(WML) if (document()->isWMLDocument() && !containsOnlyWhitespace()) { - String text = m_data; + String text = data(); ASSERT(!text.isEmpty()); text = substituteVariableReferences(text, document()); @@ -286,7 +282,7 @@ void Text::recalcStyle(StyleChange change) if (needsStyleRecalc()) { if (renderer()) { if (renderer()->isText()) - toRenderText(renderer())->setText(m_data); + toRenderText(renderer())->setText(dataImpl()); } else { if (attached()) detach(); @@ -296,40 +292,47 @@ void Text::recalcStyle(StyleChange change) setNeedsStyleRecalc(NoStyleChange); } -// DOM Section 1.1.1 bool Text::childTypeAllowed(NodeType) { return false; } -PassRefPtr<Text> Text::createNew(PassRefPtr<StringImpl> string) +PassRefPtr<Text> Text::virtualCreate(const String& data) { - return new Text(document(), string); + return create(document(), data); } -PassRefPtr<Text> Text::createWithLengthLimit(Document* doc, const String& text, unsigned& charsLeft, unsigned maxChars) +PassRefPtr<Text> Text::createWithLengthLimit(Document* document, const String& data, unsigned& charsLeft, unsigned maxChars) { - if (charsLeft == text.length() && charsLeft <= maxChars) { + unsigned dataLength = data.length(); + + if (charsLeft == dataLength && charsLeft <= maxChars) { charsLeft = 0; - return new Text(doc, text); + return create(document, data); } + + unsigned start = dataLength - charsLeft; + unsigned end = start + min(charsLeft, maxChars); - unsigned start = text.length() - charsLeft; - unsigned end = start + std::min(charsLeft, maxChars); + // Check we are not on an unbreakable boundary. + // Some text break iterator implementations work best if the passed buffer is as small as possible, + // see <https://bugs.webkit.org/show_bug.cgi?id=29092>. + // We need at least two characters look-ahead to account for UTF-16 surrogates. + if (end < dataLength) { + TextBreakIterator* it = characterBreakIterator(data.characters() + start, (end + 2 > dataLength) ? dataLength - start : end - start + 2); + if (!isTextBreak(it, end - start)) + end = textBreakPreceding(it, end - start) + start; + } - // check we are not on an unbreakable boundary - TextBreakIterator* it = characterBreakIterator(text.characters(), text.length()); - if (end < text.length() && !isTextBreak(it, end)) - end = textBreakPreceding(it, end); - - // maxChars of unbreakable characters could lead to infinite loop + // If we have maxChars of unbreakable characters the above could lead to + // an infinite loop. + // FIXME: It would be better to just have the old value of end before calling + // textBreakPreceding rather than this, because this exceeds the length limit. if (end <= start) - end = text.length(); + end = dataLength; - String nodeText = text.substring(start, end - start); - charsLeft = text.length() - end; - - return new Text(doc, nodeText); + charsLeft = dataLength - end; + return create(document, data.substring(start, end - start)); } #ifndef NDEBUG @@ -343,7 +346,7 @@ void Text::formatForDebugger(char *buffer, unsigned length) const result += s; } - s = nodeValue(); + s = data(); if (s.length() > 0) { if (result.length() > 0) result += "; "; diff --git a/WebCore/dom/Text.h b/WebCore/dom/Text.h index e5a6e69..4722736 100644 --- a/WebCore/dom/Text.h +++ b/WebCore/dom/Text.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -27,44 +27,39 @@ namespace WebCore { -const unsigned cTextNodeLengthLimit = 1 << 16; - class Text : public CharacterData { public: - Text(Document *impl, const String &_text); - Text(Document *impl); - virtual ~Text(); + static const unsigned defaultLengthLimit = 1 << 16; - // DOM methods & attributes for CharacterData + static PassRefPtr<Text> create(Document*, const String&); + static PassRefPtr<Text> createWithLengthLimit(Document*, const String&, unsigned& charsLeft, unsigned lengthLimit = defaultLengthLimit); PassRefPtr<Text> splitText(unsigned offset, ExceptionCode&); // DOM Level 3: http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-1312295772 + String wholeText() const; PassRefPtr<Text> replaceWholeText(const String&, ExceptionCode&); - // DOM methods overridden from parent classes + virtual void attach(); + +protected: + Text(Document*, const String&); +private: virtual String nodeName() const; virtual NodeType nodeType() const; virtual PassRefPtr<Node> cloneNode(bool deep); - - // Other methods (not part of DOM) - - virtual void attach(); virtual bool rendererIsNeeded(RenderStyle*); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); virtual void recalcStyle(StyleChange = NoChange); virtual bool childTypeAllowed(NodeType); - static PassRefPtr<Text> createWithLengthLimit(Document*, const String&, unsigned& charsLeft, unsigned maxChars = cTextNodeLengthLimit); + virtual PassRefPtr<Text> virtualCreate(const String&); #ifndef NDEBUG virtual void formatForDebugger(char* buffer, unsigned length) const; #endif - -protected: - virtual PassRefPtr<Text> createNew(PassRefPtr<StringImpl>); }; } // namespace WebCore diff --git a/WebCore/dom/TransformSource.h b/WebCore/dom/TransformSource.h new file mode 100644 index 0000000..f97afcf --- /dev/null +++ b/WebCore/dom/TransformSource.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2009 Jakub Wieczorek <faw217@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef TransformSource_h +#define TransformSource_h + +#if ENABLE(XSLT) + +#include "PlatformString.h" +#include <wtf/Noncopyable.h> + +namespace WebCore { + +#if USE(QXMLQUERY) + typedef String PlatformTransformSource; +#else + typedef void* PlatformTransformSource; +#endif + + class TransformSource : public Noncopyable { + public: + TransformSource(const PlatformTransformSource& source); + ~TransformSource(); + + PlatformTransformSource platformSource() const { return m_source; } + + private: + PlatformTransformSource m_source; + }; + +} // namespace WebCore + +#endif + +#endif // TransformSource_h diff --git a/WebCore/dom/TransformSourceLibxslt.cpp b/WebCore/dom/TransformSourceLibxslt.cpp new file mode 100644 index 0000000..33a85e8 --- /dev/null +++ b/WebCore/dom/TransformSourceLibxslt.cpp @@ -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 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 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 "TransformSource.h" + +#include <libxml/tree.h> + +namespace WebCore { + +TransformSource::TransformSource(const PlatformTransformSource& source) + : m_source(source) +{ +} + +TransformSource::~TransformSource() +{ + xmlFreeDoc((xmlDocPtr)m_source); +} + +} diff --git a/WebCore/dom/TransformSourceQt.cpp b/WebCore/dom/TransformSourceQt.cpp new file mode 100644 index 0000000..074f2cb --- /dev/null +++ b/WebCore/dom/TransformSourceQt.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009 Jakub Wieczorek <faw217@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "TransformSource.h" + +namespace WebCore { + +TransformSource::TransformSource(const PlatformTransformSource& source) + : m_source(source) +{ +} + +TransformSource::~TransformSource() +{ +} + +} diff --git a/WebCore/dom/XMLTokenizer.cpp b/WebCore/dom/XMLTokenizer.cpp index 1747c3c..4d06343 100644 --- a/WebCore/dom/XMLTokenizer.cpp +++ b/WebCore/dom/XMLTokenizer.cpp @@ -136,7 +136,7 @@ bool XMLTokenizer::enterText() #if !USE(QXMLSTREAM) ASSERT(m_bufferedText.size() == 0); #endif - RefPtr<Node> newNode = new Text(m_doc, ""); + RefPtr<Node> newNode = Text::create(m_doc, ""); if (!m_currentNode->addChild(newNode.get())) return false; setCurrentNode(newNode.get()); diff --git a/WebCore/dom/XMLTokenizerLibxml2.cpp b/WebCore/dom/XMLTokenizerLibxml2.cpp index 4387a66..e4a98d5 100644 --- a/WebCore/dom/XMLTokenizerLibxml2.cpp +++ b/WebCore/dom/XMLTokenizerLibxml2.cpp @@ -50,6 +50,7 @@ #include "ScriptSourceCode.h" #include "ScriptValue.h" #include "TextResourceDecoder.h" +#include "TransformSource.h" #include "XMLTokenizerScope.h" #include <libxml/parser.h> #include <libxml/parserInternals.h> @@ -850,7 +851,8 @@ void XMLTokenizer::endElementNs() if (!scriptHref.isEmpty()) { // we have a src attribute String scriptCharset = scriptElement->scriptCharset(); - if ((m_pendingScript = m_doc->docLoader()->requestScript(scriptHref, scriptCharset))) { + if (element->dispatchBeforeLoadEvent(scriptHref) && + (m_pendingScript = m_doc->docLoader()->requestScript(scriptHref, scriptCharset))) { m_scriptElement = element; m_pendingScript->addClient(this); @@ -951,7 +953,7 @@ void XMLTokenizer::cdataBlock(const xmlChar* s, int len) exitText(); - RefPtr<Node> newNode = new CDATASection(m_doc, toString(s, len)); + RefPtr<Node> newNode = CDATASection::create(m_doc, toString(s, len)); if (!m_currentNode->addChild(newNode.get())) return; if (m_view && !newNode->attached()) @@ -970,7 +972,7 @@ void XMLTokenizer::comment(const xmlChar* s) exitText(); - RefPtr<Node> newNode = new Comment(m_doc, toString(s)); + RefPtr<Node> newNode = Comment::create(m_doc, toString(s)); m_currentNode->addChild(newNode.get()); if (m_view && !newNode->attached()) newNode->attach(); @@ -1280,7 +1282,8 @@ void XMLTokenizer::doEnd() { #if ENABLE(XSLT) if (m_sawXSLTransform) { - m_doc->setTransformSource(xmlDocPtrForString(m_doc->docLoader(), m_originalSourceForTransform, m_doc->url().string())); + void* doc = xmlDocPtrForString(m_doc->docLoader(), m_originalSourceForTransform, m_doc->url().string()); + m_doc->setTransformSource(new TransformSource(doc)); m_doc->setParsing(false); // Make the doc think it's done, so it will apply xsl sheets. m_doc->updateStyleSelector(); diff --git a/WebCore/dom/XMLTokenizerQt.cpp b/WebCore/dom/XMLTokenizerQt.cpp index 16c637f..04405d6 100644 --- a/WebCore/dom/XMLTokenizerQt.cpp +++ b/WebCore/dom/XMLTokenizerQt.cpp @@ -50,6 +50,7 @@ #include "ScriptSourceCode.h" #include "ScriptValue.h" #include "TextResourceDecoder.h" +#include "TransformSource.h" #include <QDebug> #include <wtf/Platform.h> #include <wtf/StringExtras.h> @@ -237,7 +238,7 @@ void XMLTokenizer::doWrite(const String& parseString) return; } -void XMLTokenizer::initializeParserContext(const char* chunk) +void XMLTokenizer::initializeParserContext(const char*) { m_parserStopped = false; m_sawError = false; @@ -248,45 +249,19 @@ void XMLTokenizer::initializeParserContext(const char* chunk) void XMLTokenizer::doEnd() { #if ENABLE(XSLT) - #warning Look at XMLTokenizerLibXml.cpp -#endif - - if (m_stream.error() == QXmlStreamReader::PrematureEndOfDocumentError || (m_wroteText && !m_sawFirstElement)) { - handleError(fatal, qPrintable(m_stream.errorString()), lineNumber(), - columnNumber()); + if (m_sawXSLTransform) { + m_doc->setTransformSource(new TransformSource(m_originalSourceForTransform)); + m_doc->setParsing(false); // Make the doc think it's done, so it will apply xsl sheets. + m_doc->updateStyleSelector(); + m_doc->setParsing(true); + m_parserStopped = true; } -} - -#if ENABLE(XSLT) -void* xmlDocPtrForString(DocLoader* docLoader, const String& source, const String& url) -{ - if (source.isEmpty()) - return 0; - - // Parse in a single chunk into an xmlDocPtr - // FIXME: Hook up error handlers so that a failure to parse the main document results in - // good error messages. - const UChar BOM = 0xFEFF; - const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM); - - xmlGenericErrorFunc oldErrorFunc = xmlGenericError; - void* oldErrorContext = xmlGenericErrorContext; - - setLoaderForLibXMLCallbacks(docLoader); - xmlSetGenericErrorFunc(0, errorFunc); - - xmlDocPtr sourceDoc = xmlReadMemory(reinterpret_cast<const char*>(source.characters()), - source.length() * sizeof(UChar), - url.latin1().data(), - BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE", - XSLT_PARSE_OPTIONS); - - setLoaderForLibXMLCallbacks(0); - xmlSetGenericErrorFunc(oldErrorContext, oldErrorFunc); +#endif - return sourceDoc; + if (m_stream.error() == QXmlStreamReader::PrematureEndOfDocumentError + || (m_wroteText && !m_sawFirstElement && !m_sawXSLTransform)) + handleError(fatal, qPrintable(m_stream.errorString()), lineNumber(), columnNumber()); } -#endif int XMLTokenizer::lineNumber() const { @@ -683,7 +658,7 @@ void XMLTokenizer::parseProcessingInstruction() #if ENABLE(XSLT) m_sawXSLTransform = !m_sawFirstElement && pi->isXSL(); - if (m_sawXSLTransform && !m_doc->transformSourceDocument())) + if (m_sawXSLTransform && !m_doc->transformSourceDocument()) stopParsing(); #endif } @@ -692,7 +667,7 @@ void XMLTokenizer::parseCdata() { exitText(); - RefPtr<Node> newNode = new CDATASection(m_doc, m_stream.text()); + RefPtr<Node> newNode = CDATASection::create(m_doc, m_stream.text()); if (!m_currentNode->addChild(newNode.get())) return; if (m_view && !newNode->attached()) @@ -703,7 +678,7 @@ void XMLTokenizer::parseComment() { exitText(); - RefPtr<Node> newNode = new Comment(m_doc, m_stream.text()); + RefPtr<Node> newNode = Comment::create(m_doc, m_stream.text()); m_currentNode->addChild(newNode.get()); if (m_view && !newNode->attached()) newNode->attach(); diff --git a/WebCore/dom/make_names.pl b/WebCore/dom/make_names.pl index e6d59a0..6b5ddb4 100755 --- a/WebCore/dom/make_names.pl +++ b/WebCore/dom/make_names.pl @@ -48,28 +48,30 @@ my %parameters = (); my $extraDefines = 0; my $preprocessor = "/usr/bin/gcc -E -P -x c++"; -GetOptions('tags=s' => \$tagsFile, +GetOptions( + 'tags=s' => \$tagsFile, 'attrs=s' => \$attrsFile, 'factory' => \$printFactory, 'outputDir=s' => \$outputDir, 'extraDefines=s' => \$extraDefines, 'preprocessor=s' => \$preprocessor, - 'wrapperFactory' => \$printWrapperFactory); + 'wrapperFactory' => \$printWrapperFactory +); die "You must specify at least one of --tags <file> or --attrs <file>" unless (length($tagsFile) || length($attrsFile)); readNames($tagsFile, "tags") if length($tagsFile); readNames($attrsFile, "attrs") if length($attrsFile); -die "You must specify a namespace (e.g. SVG) for <namespace>Names.h" unless $parameters{'namespace'}; -die "You must specify a namespaceURI (e.g. http://www.w3.org/2000/svg)" unless $parameters{'namespaceURI'}; +die "You must specify a namespace (e.g. SVG) for <namespace>Names.h" unless $parameters{namespace}; +die "You must specify a namespaceURI (e.g. http://www.w3.org/2000/svg)" unless $parameters{namespaceURI}; -$parameters{'namespacePrefix'} = $parameters{'namespace'} unless $parameters{'namespacePrefix'}; +$parameters{namespacePrefix} = $parameters{namespace} unless $parameters{namespacePrefix}; mkpath($outputDir); -my $namesBasePath = "$outputDir/$parameters{'namespace'}Names"; -my $factoryBasePath = "$outputDir/$parameters{'namespace'}ElementFactory"; -my $wrapperFactoryBasePath = "$outputDir/JS$parameters{'namespace'}ElementWrapperFactory"; +my $namesBasePath = "$outputDir/$parameters{namespace}Names"; +my $factoryBasePath = "$outputDir/$parameters{namespace}ElementFactory"; +my $wrapperFactoryBasePath = "$outputDir/JS$parameters{namespace}ElementWrapperFactory"; printNamesHeaderFile("$namesBasePath.h"); printNamesCppFile("$namesBasePath.cpp"); @@ -86,39 +88,44 @@ if ($printWrapperFactory) { ### Hash initialization -sub initializeTagPropertyHash +sub defaultTagPropertyHash { - return ('constructorNeedsCreatedByParser' => 0, - 'constructorNeedsFormElement' => 0, - 'exportString' => 0, - 'interfaceName' => defaultInterfaceName($_[0]), - # By default, the JSInterfaceName is the same as the interfaceName. - 'JSInterfaceName' => defaultInterfaceName($_[0]), - 'mapToTagName' => '', - 'wrapperOnlyIfMediaIsAvailable' => 0, - 'conditional' => 0); + return ( + 'constructorNeedsCreatedByParser' => 0, + 'constructorNeedsFormElement' => 0, + 'createWithNew' => 0, + 'exportString' => 0, + 'interfaceName' => defaultInterfaceName($_[0]), + # By default, the JSInterfaceName is the same as the interfaceName. + 'JSInterfaceName' => defaultInterfaceName($_[0]), + 'mapToTagName' => '', + 'wrapperOnlyIfMediaIsAvailable' => 0, + 'conditional' => 0 + ); } -sub initializeAttrPropertyHash +sub defaultAttrPropertyHash { return ('exportString' => 0); } -sub initializeParametersHash +sub defaultParametersHash { - return ('namespace' => '', - 'namespacePrefix' => '', - 'namespaceURI' => '', - 'guardFactoryWith' => '', - 'tagsNullNamespace' => 0, - 'attrsNullNamespace' => 0, - 'exportStrings' => 0); + return ( + 'namespace' => '', + 'namespacePrefix' => '', + 'namespaceURI' => '', + 'guardFactoryWith' => '', + 'tagsNullNamespace' => 0, + 'attrsNullNamespace' => 0, + 'exportStrings' => 0 + ); } sub defaultInterfaceName { - die "No namespace found" if !$parameters{'namespace'}; - return $parameters{'namespace'} . upperCaseName($_[0]) . "Element" + die "No namespace found" if !$parameters{namespace}; + return $parameters{namespace} . upperCaseName($_[0]) . "Element" } ### Parsing handlers @@ -129,16 +136,16 @@ sub tagsHandler $tag =~ s/-/_/g; - # Initialize default properties' values. - $tags{$tag} = { initializeTagPropertyHash($tag) } if !defined($tags{$tag}); + # Initialize default property values. + $tags{$tag} = { defaultTagPropertyHash($tag) } if !defined($tags{$tag}); if ($property) { die "Unknown property $property for tag $tag\n" if !defined($tags{$tag}{$property}); - # The code rely on JSInterfaceName deriving from interfaceName to check for custom JSInterfaceName. - # So just override JSInterfaceName if it was not already set. - if ($property eq "interfaceName" && $tags{$tag}{'JSInterfaceName'} eq $tags{$tag}{'interfaceName'}) { - $tags{$tag}{'JSInterfaceName'} = $value; - } + + # The code relies on JSInterfaceName deriving from interfaceName to check for custom JSInterfaceName. + # So override JSInterfaceName if it was not already set. + $tags{$tag}{JSInterfaceName} = $value if $property eq "interfaceName" && $tags{$tag}{JSInterfaceName} eq $tags{$tag}{interfaceName}; + $tags{$tag}{$property} = $value; } } @@ -150,7 +157,7 @@ sub attrsHandler $attr =~ s/-/_/g; # Initialize default properties' values. - $attrs{$attr} = { initializeAttrPropertyHash($attr) } if !defined($attrs{$attr}); + $attrs{$attr} = { defaultAttrPropertyHash($attr) } if !defined($attrs{$attr}); if ($property) { die "Unknown property $property for attribute $attr\n" if !defined($attrs{$attr}{$property}); @@ -163,7 +170,7 @@ sub parametersHandler my ($parameter, $value) = @_; # Initialize default properties' values. - %parameters = initializeParametersHash() if !(keys %parameters); + %parameters = defaultParametersHash() if !(keys %parameters); die "Unknown parameter $parameter for tags/attrs\n" if !defined($parameters{$parameter}); $parameters{$parameter} = $value; @@ -214,7 +221,7 @@ sub printMacros for my $name (sort keys %$namesRef) { print F "$macro $name","$suffix;\n"; - if ($parameters{'exportStrings'} or $names{$name}{"exportString"}) { + if ($parameters{exportStrings} or $names{$name}{exportString}) { print F "extern char $name", "${suffix}String[];\n"; } } @@ -223,7 +230,7 @@ sub printMacros sub usesDefaultWrapper { my $tagName = shift; - return $tagName eq $parameters{'namespace'} . "Element"; + return $tagName eq $parameters{namespace} . "Element"; } # Build a direct mapping from the tags to the Element to create, excluding @@ -232,16 +239,16 @@ sub buildConstructorMap { my %tagConstructorMap = (); for my $tagName (keys %tags) { - my $interfaceName = $tags{$tagName}{'interfaceName'}; + my $interfaceName = $tags{$tagName}{interfaceName}; next if (usesDefaultWrapper($interfaceName)); - if ($tags{$tagName}{'mapToTagName'}) { - die "Cannot handle multiple mapToTagName for $tagName\n" if $tags{$tags{$tagName}{'mapToTagName'}}{'mapToTagName'}; - $interfaceName = $tags{ $tags{$tagName}{'mapToTagName'} }{'interfaceName'}; + if ($tags{$tagName}{mapToTagName}) { + die "Cannot handle multiple mapToTagName for $tagName\n" if $tags{$tags{$tagName}{mapToTagName}}{mapToTagName}; + $interfaceName = $tags{ $tags{$tagName}{mapToTagName} }{interfaceName}; } # Chop the string to keep the interesting part. - $interfaceName =~ s/$parameters{'namespace'}(.*)Element/$1/; + $interfaceName =~ s/$parameters{namespace}(.*)Element/$1/; $tagConstructorMap{$tagName} = lc($interfaceName); } @@ -254,17 +261,13 @@ sub printConstructorSignature { my ($F, $tagName, $constructorName, $constructorTagName) = @_; - print F "static PassRefPtr<$parameters{'namespace'}Element> ${constructorName}Constructor(const QualifiedName& $constructorTagName, Document* doc"; - if ($parameters{'namespace'} eq "HTML") { + print F "static PassRefPtr<$parameters{namespace}Element> ${constructorName}Constructor(const QualifiedName& $constructorTagName, Document* document"; + if ($parameters{namespace} eq "HTML") { print F ", HTMLFormElement*"; - if ($tags{$tagName}{'constructorNeedsFormElement'}) { - print F " formElement"; - } + print F " formElement" if $tags{$tagName}{constructorNeedsFormElement}; } print F ", bool"; - if ($tags{$tagName}{'constructorNeedsCreatedByParser'}) { - print F " createdByParser"; - } + print F " createdByParser" if $tags{$tagName}{constructorNeedsCreatedByParser}; print F ")\n{\n"; } @@ -276,22 +279,26 @@ sub printConstructorInterior my ($F, $tagName, $interfaceName, $constructorTagName) = @_; # Handle media elements. - if ($tags{$tagName}{'wrapperOnlyIfMediaIsAvailable'}) { + if ($tags{$tagName}{wrapperOnlyIfMediaIsAvailable}) { print F <<END if (!MediaPlayer::isAvailable()) - return new HTMLElement($constructorTagName, doc); + return HTMLElement::create($constructorTagName, document); END ; } - # Now call the constructor with the right parameters. - print F " return new ${interfaceName}($constructorTagName, doc"; - if ($tags{$tagName}{'constructorNeedsFormElement'}) { - print F ", formElement"; - } - if ($tags{$tagName}{'constructorNeedsCreatedByParser'}) { - print F ", createdByParser"; + my $newPrefix = ""; + my $createSuffix = "::create"; + + if ($tags{$tagName}{createWithNew}) { + $newPrefix = "new "; + $createSuffix = ""; } + + # Call the constructor with the right parameters. + print F " return $newPrefix$interfaceName${createSuffix}($constructorTagName, document"; + print F ", formElement" if $tags{$tagName}{constructorNeedsFormElement}; + print F ", createdByParser" if $tags{$tagName}{constructorNeedsCreatedByParser}; print F ");\n}\n\n"; } @@ -300,20 +307,20 @@ sub printConstructors my ($F, $tagConstructorMapRef) = @_; my %tagConstructorMap = %$tagConstructorMapRef; - print F "#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'}; + print F "#if $parameters{guardFactoryWith}\n" if $parameters{guardFactoryWith}; # This is to avoid generating the same constructor several times. my %uniqueTags = (); for my $tagName (sort keys %tagConstructorMap) { - my $interfaceName = $tags{$tagName}{'interfaceName'}; + my $interfaceName = $tags{$tagName}{interfaceName}; # Ignore the mapped tag # FIXME: It could be moved inside this loop but was split for readibility. - next if (defined($uniqueTags{$interfaceName}) || $tags{$tagName}{'mapToTagName'}); + next if (defined($uniqueTags{$interfaceName}) || $tags{$tagName}{mapToTagName}); $uniqueTags{$interfaceName} = '1'; - my $conditional = $tags{$tagName}{"conditional"}; + my $conditional = $tags{$tagName}{conditional}; if ($conditional) { my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; print F "#if ${conditionalString}\n\n"; @@ -323,20 +330,20 @@ sub printConstructors printConstructorInterior($F, $tagName, $interfaceName, "tagName"); if ($conditional) { - print F "#endif\n\n"; + print F "#endif\n"; } } # Mapped tag name uses a special wrapper to keep their prefix and namespaceURI while using the mapped localname. for my $tagName (sort keys %tagConstructorMap) { - if ($tags{$tagName}{'mapToTagName'}) { - my $mappedName = $tags{$tagName}{'mapToTagName'}; + if ($tags{$tagName}{mapToTagName}) { + my $mappedName = $tags{$tagName}{mapToTagName}; printConstructorSignature($F, $mappedName, $mappedName . "To" . $tagName, "tagName"); - printConstructorInterior($F, $mappedName, $tags{$mappedName}{'interfaceName'}, "QualifiedName(tagName.prefix(), ${mappedName}Tag.localName(), tagName.namespaceURI())"); + printConstructorInterior($F, $mappedName, $tags{$mappedName}{interfaceName}, "QualifiedName(tagName.prefix(), ${mappedName}Tag.localName(), tagName.namespaceURI())"); } } - print F "#endif\n" if $parameters{'guardFactoryWith'}; + print F "#endif\n" if $parameters{guardFactoryWith}; } sub printFunctionInits @@ -346,14 +353,14 @@ sub printFunctionInits for my $tagName (sort keys %tagConstructorMap) { - my $conditional = $tags{$tagName}{"conditional"}; + my $conditional = $tags{$tagName}{conditional}; if ($conditional) { my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; print F "#if ${conditionalString}\n"; } - if ($tags{$tagName}{'mapToTagName'}) { - print F " addTag(${tagName}Tag, $tags{$tagName}{'mapToTagName'}To${tagName}Constructor);\n"; + if ($tags{$tagName}{mapToTagName}) { + print F " addTag(${tagName}Tag, $tags{$tagName}{mapToTagName}To${tagName}Constructor);\n"; } else { print F " addTag(${tagName}Tag, $tagConstructorMap{$tagName}Constructor);\n"; } @@ -368,9 +375,7 @@ sub svgCapitalizationHacks { my $name = shift; - if ($name =~ /^fe(.+)$/) { - $name = "FE" . ucfirst $1; - } + $name = "FE" . ucfirst $1 if $name =~ /^fe(.+)$/; return $name; } @@ -379,7 +384,7 @@ sub upperCaseName { my $name = shift; - $name = svgCapitalizationHacks($name) if ($parameters{'namespace'} eq "SVG"); + $name = svgCapitalizationHacks($name) if ($parameters{namespace} eq "SVG"); while ($name =~ /^(.*?)_(.*)/) { $name = $1 . ucfirst $2; @@ -392,10 +397,11 @@ sub printLicenseHeader { my $F = shift; print F "/* - * THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT. + * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT. * + * This file was generated by the dom/make_names.pl script. * - * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2005, 2006, 2007, 2008, 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 @@ -416,10 +422,9 @@ sub printLicenseHeader * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - "; } @@ -428,16 +433,16 @@ sub printNamesHeaderFile my ($headerPath) = shift; my $F; open F, ">$headerPath"; - + printLicenseHeader($F); - print F "#ifndef DOM_$parameters{'namespace'}NAMES_H\n"; - print F "#define DOM_$parameters{'namespace'}NAMES_H\n\n"; + print F "#ifndef DOM_$parameters{namespace}NAMES_H\n"; + print F "#define DOM_$parameters{namespace}NAMES_H\n\n"; print F "#include \"QualifiedName.h\"\n\n"; - - print F "namespace WebCore {\n\n namespace $parameters{'namespace'}Names {\n\n"; - - my $lowerNamespace = lc($parameters{'namespacePrefix'}); - print F "#ifndef DOM_$parameters{'namespace'}NAMES_HIDE_GLOBALS\n"; + + print F "namespace WebCore {\n\n namespace $parameters{namespace}Names {\n\n"; + + my $lowerNamespace = lc($parameters{namespacePrefix}); + print F "#ifndef DOM_$parameters{namespace}NAMES_HIDE_GLOBALS\n"; print F "// Namespace\n"; print F "extern const WebCore::AtomicString ${lowerNamespace}NamespaceURI;\n\n"; @@ -451,19 +456,19 @@ sub printNamesHeaderFile printMacros($F, "extern const WebCore::QualifiedName", "Attr", \%attrs); } print F "#endif\n\n"; - + if (keys %tags) { - print F "WebCore::QualifiedName** get$parameters{'namespace'}Tags(size_t* size);\n"; + print F "WebCore::QualifiedName** get$parameters{namespace}Tags(size_t* size);\n"; } if (keys %attrs) { - print F "WebCore::QualifiedName** get$parameters{'namespace'}Attrs(size_t* size);\n"; + print F "WebCore::QualifiedName** get$parameters{namespace}Attrs(size_t* size);\n"; } - + print F "\nvoid init();\n\n"; print F "} }\n\n"; print F "#endif\n\n"; - + close F; } @@ -475,25 +480,25 @@ sub printNamesCppFile printLicenseHeader($F); - my $lowerNamespace = lc($parameters{'namespacePrefix'}); + my $lowerNamespace = lc($parameters{namespacePrefix}); print F "#include \"config.h\"\n"; print F "#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC\n"; -print F "#define DOM_$parameters{'namespace'}NAMES_HIDE_GLOBALS 1\n"; +print F "#define DOM_$parameters{namespace}NAMES_HIDE_GLOBALS 1\n"; print F "#else\n"; print F "#define QNAME_DEFAULT_CONSTRUCTOR 1\n"; print F "#endif\n\n"; -print F "#include \"$parameters{'namespace'}Names.h\"\n\n"; +print F "#include \"$parameters{namespace}Names.h\"\n\n"; print F "#include \"StaticConstructors.h\"\n"; -print F "namespace WebCore {\n\n namespace $parameters{'namespace'}Names { +print F "namespace WebCore {\n\n namespace $parameters{namespace}Names { using namespace WebCore; -DEFINE_GLOBAL(AtomicString, ${lowerNamespace}NamespaceURI, \"$parameters{'namespaceURI'}\") +DEFINE_GLOBAL(AtomicString, ${lowerNamespace}NamespaceURI, \"$parameters{namespaceURI}\") "; if (keys %tags) { @@ -502,14 +507,14 @@ DEFINE_GLOBAL(AtomicString, ${lowerNamespace}NamespaceURI, \"$parameters{'namesp print F "DEFINE_GLOBAL(QualifiedName, ", $name, "Tag, nullAtom, \"$name\", ${lowerNamespace}NamespaceURI);\n"; } - print F "\n\nWebCore::QualifiedName** get$parameters{'namespace'}Tags(size_t* size)\n"; - print F "{\n static WebCore::QualifiedName* $parameters{'namespace'}Tags[] = {\n"; + print F "\n\nWebCore::QualifiedName** get$parameters{namespace}Tags(size_t* size)\n"; + print F "{\n static WebCore::QualifiedName* $parameters{namespace}Tags[] = {\n"; for my $name (sort keys %tags) { print F " (WebCore::QualifiedName*)&${name}Tag,\n"; } print F " };\n"; print F " *size = ", scalar(keys %tags), ";\n"; - print F " return $parameters{'namespace'}Tags;\n"; + print F " return $parameters{namespace}Tags;\n"; print F "}\n"; } @@ -518,14 +523,14 @@ DEFINE_GLOBAL(AtomicString, ${lowerNamespace}NamespaceURI, \"$parameters{'namesp for my $name (sort keys %attrs) { print F "DEFINE_GLOBAL(QualifiedName, ", $name, "Attr, nullAtom, \"$name\", ${lowerNamespace}NamespaceURI);\n"; } - print F "\n\nWebCore::QualifiedName** get$parameters{'namespace'}Attrs(size_t* size)\n"; - print F "{\n static WebCore::QualifiedName* $parameters{'namespace'}Attr[] = {\n"; + print F "\n\nWebCore::QualifiedName** get$parameters{namespace}Attrs(size_t* size)\n"; + print F "{\n static WebCore::QualifiedName* $parameters{namespace}Attr[] = {\n"; for my $name (sort keys %attrs) { print F " (WebCore::QualifiedName*)&${name}Attr,\n"; } print F " };\n"; print F " *size = ", scalar(keys %attrs), ";\n"; - print F " return $parameters{'namespace'}Attr;\n"; + print F " return $parameters{namespace}Attr;\n"; print F "}\n"; } @@ -549,16 +554,16 @@ print F "\nvoid init() AtomicString::init(); "; - print(F " AtomicString ${lowerNamespace}NS(\"$parameters{'namespaceURI'}\");\n\n"); + print(F " AtomicString ${lowerNamespace}NS(\"$parameters{namespaceURI}\");\n\n"); print(F " // Namespace\n"); print(F " new ((void*)&${lowerNamespace}NamespaceURI) AtomicString(${lowerNamespace}NS);\n\n"); if (keys %tags) { - my $tagsNamespace = $parameters{'tagsNullNamespace'} ? "nullAtom" : "${lowerNamespace}NS"; + my $tagsNamespace = $parameters{tagsNullNamespace} ? "nullAtom" : "${lowerNamespace}NS"; printDefinitions($F, \%tags, "tags", $tagsNamespace); } if (keys %attrs) { - my $attrsNamespace = $parameters{'attrsNullNamespace'} ? "nullAtom" : "${lowerNamespace}NS"; + my $attrsNamespace = $parameters{attrsNullNamespace} ? "nullAtom" : "${lowerNamespace}NS"; printDefinitions($F, \%attrs, "attributes", $attrsNamespace); } @@ -572,7 +577,7 @@ sub printJSElementIncludes my %tagsSeen; for my $tagName (sort keys %tags) { - my $JSInterfaceName = $tags{$tagName}{"JSInterfaceName"}; + my $JSInterfaceName = $tags{$tagName}{JSInterfaceName}; next if defined($tagsSeen{$JSInterfaceName}) || usesDefaultJSWrapper($tagName); $tagsSeen{$JSInterfaceName} = 1; @@ -586,7 +591,7 @@ sub printElementIncludes my %tagsSeen; for my $tagName (sort keys %tags) { - my $interfaceName = $tags{$tagName}{"interfaceName"}; + my $interfaceName = $tags{$tagName}{interfaceName}; next if defined($tagsSeen{$interfaceName}); $tagsSeen{$interfaceName} = 1; @@ -604,7 +609,7 @@ sub printDefinitionStrings my %names = %$namesRef; for my $name (sort keys %$namesRef) { - next if (!$parameters{'exportStrings'} and !$names{$name}{"exportString"}); + next if (!$parameters{exportStrings} and !$names{$name}{exportString}); my $realName = $name; $realName =~ s/_/-/g; @@ -625,7 +630,7 @@ sub printDefinitions my %names = %$namesRef; for my $name (sort keys %$namesRef) { - next if ($parameters{'exportStrings'} or $names{$name}{"exportString"}); + next if ($parameters{exportStrings} or $names{$name}{exportString}); my $realName = $name; $realName =~ s/_/-/g; @@ -651,39 +656,31 @@ printLicenseHeader($F); print F <<END #include "config.h" -#include "$parameters{'namespace'}ElementFactory.h" - -#include "$parameters{'namespace'}Names.h" -#if ENABLE(DASHBOARD_SUPPORT) -#include "Document.h" -#include "Settings.h" -#endif +#include "$parameters{namespace}ElementFactory.h" +#include "$parameters{namespace}Names.h" END ; -if ($parameters{'namespace'} eq "HTML") { - print F "#include \"HTMLFormElement.h\"\n"; -} - printElementIncludes($F); print F <<END #include <wtf/HashMap.h> +#if ENABLE(DASHBOARD_SUPPORT) +#include "Document.h" +#include "Settings.h" +#endif + namespace WebCore { -using namespace $parameters{'namespace'}Names; +using namespace $parameters{namespace}Names; END ; -print F "typedef PassRefPtr<$parameters{'namespace'}Element> (*ConstructorFunction)(const QualifiedName&, Document*"; - -if ($parameters{'namespace'} eq "HTML") { - print F ", HTMLFormElement*"; -} - +print F "typedef PassRefPtr<$parameters{namespace}Element> (*ConstructorFunction)(const QualifiedName&, Document*"; +print F ", HTMLFormElement*" if $parameters{namespace} eq "HTML"; print F ", bool createdByParser);\n"; print F <<END typedef HashMap<AtomicStringImpl*, ConstructorFunction> FunctionMap; @@ -697,7 +694,7 @@ my %tagConstructorMap = buildConstructorMap(); printConstructors($F, \%tagConstructorMap); -print F "#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'}; +print F "#if $parameters{guardFactoryWith}\n" if $parameters{guardFactoryWith}; print F <<END static void addTag(const QualifiedName& tag, ConstructorFunction func) @@ -705,10 +702,10 @@ static void addTag(const QualifiedName& tag, ConstructorFunction func) gFunctionMap->set(tag.localName().impl(), func); } -static inline void createFunctionMapIfNecessary() +static void createFunctionMap() { - if (gFunctionMap) - return; + ASSERT(!gFunctionMap); + // Create the table. gFunctionMap = new FunctionMap; @@ -719,30 +716,25 @@ END printFunctionInits($F, \%tagConstructorMap); print F "}\n"; -print F "#endif\n" if $parameters{'guardFactoryWith'}; - -print F "\nPassRefPtr<$parameters{'namespace'}Element> $parameters{'namespace'}ElementFactory::create$parameters{'namespace'}Element(const QualifiedName& qName, Document* doc"; - -if ($parameters{"namespace"} eq "HTML") { - print F ", HTMLFormElement* formElement"; -} +print F "#endif\n" if $parameters{guardFactoryWith}; +print F "\nPassRefPtr<$parameters{namespace}Element> $parameters{namespace}ElementFactory::create$parameters{namespace}Element(const QualifiedName& qName, Document* document"; +print F ", HTMLFormElement* formElement" if $parameters{namespace} eq "HTML"; print F ", bool createdByParser)\n{\n"; -print F "#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'}; +print F "#if $parameters{guardFactoryWith}\n" if $parameters{guardFactoryWith}; print F <<END - // Don't make elements without a document - if (!doc) + if (!document) return 0; END ; -if ($parameters{'namespace'} ne "HTML") { +if ($parameters{namespace} ne "HTML") { print F <<END #if ENABLE(DASHBOARD_SUPPORT) - Settings* settings = doc->settings(); + Settings* settings = document->settings(); if (settings && settings->usesDashboardBackwardCompatibilityMode()) return 0; #endif @@ -752,21 +744,21 @@ END } print F <<END - createFunctionMapIfNecessary(); - ConstructorFunction func = gFunctionMap->get(qName.localName().impl()); - if (func) + if (!gFunctionMap) + createFunctionMap(); + if (ConstructorFunction function = gFunctionMap->get(qName.localName().impl())) END ; -if ($parameters{"namespace"} eq "HTML") { - print F " return func(qName, doc, formElement, createdByParser);\n"; +if ($parameters{namespace} eq "HTML") { + print F " return function(qName, document, formElement, createdByParser);\n"; } else { - print F " return func(qName, doc, createdByParser);\n"; + print F " return function(qName, document, createdByParser);\n"; } -print F " return new $parameters{'namespace'}Element(qName, doc);\n"; +print F " return $parameters{namespace}Element::create(qName, document);\n"; -if ($parameters{'guardFactoryWith'}) { +if ($parameters{guardFactoryWith}) { print F <<END #else @@ -797,8 +789,8 @@ sub printFactoryHeaderFile printLicenseHeader($F); print F<<END -#ifndef $parameters{'namespace'}ElementFactory_h -#define $parameters{'namespace'}ElementFactory_h +#ifndef $parameters{namespace}ElementFactory_h +#define $parameters{namespace}ElementFactory_h #include <wtf/PassRefPtr.h> @@ -811,35 +803,29 @@ namespace WebCore { namespace WebCore { - class $parameters{'namespace'}Element; + class $parameters{namespace}Element; END ; -if ($parameters{'namespace'} eq "HTML") { - print F " class HTMLFormElement;\n"; -} +print F " class HTMLFormElement;\n" if $parameters{namespace} eq "HTML"; print F<<END // The idea behind this class is that there will eventually be a mapping from namespace URIs to ElementFactories that can dispense // elements. In a compound document world, the generic createElement function (will end up being virtual) will be called. - class $parameters{'namespace'}ElementFactory { + class $parameters{namespace}ElementFactory { public: PassRefPtr<Element> createElement(const WebCore::QualifiedName&, WebCore::Document*, bool createdByParser = true); END ; -print F " static PassRefPtr<$parameters{'namespace'}Element> create$parameters{'namespace'}Element(const WebCore::QualifiedName&, WebCore::Document*"; - -if ($parameters{'namespace'} eq "HTML") { - print F ", HTMLFormElement* = 0"; -} - +print F " static PassRefPtr<$parameters{namespace}Element> create$parameters{namespace}Element(const WebCore::QualifiedName&, WebCore::Document*"; +print F ", HTMLFormElement* = 0" if $parameters{namespace} eq "HTML"; print F ", bool /*createdByParser*/ = true);\n"; printf F<<END }; } -#endif // $parameters{'namespace'}ElementFactory_h +#endif // $parameters{namespace}ElementFactory_h END ; @@ -854,7 +840,7 @@ sub usesDefaultJSWrapper my $name = shift; # A tag reuses the default wrapper if its JSInterfaceName matches the default namespace Element. - return $tags{$name}{'JSInterfaceName'} eq $parameters{"namespace"} . "Element" || $tags{$name}{'JSInterfaceName'} eq "HTMLNoScriptElement"; + return $tags{$name}{JSInterfaceName} eq $parameters{namespace} . "Element" || $tags{$name}{JSInterfaceName} eq "HTMLNoScriptElement"; } sub printWrapperFunctions @@ -864,11 +850,11 @@ sub printWrapperFunctions my %tagsSeen; for my $tagName (sort keys %tags) { # Avoid defining the same wrapper method twice. - my $JSInterfaceName = $tags{$tagName}{"JSInterfaceName"}; + my $JSInterfaceName = $tags{$tagName}{JSInterfaceName}; next if defined($tagsSeen{$JSInterfaceName}) || usesDefaultJSWrapper($tagName); $tagsSeen{$JSInterfaceName} = 1; - my $conditional = $tags{$tagName}{"conditional"}; + my $conditional = $tags{$tagName}{conditional}; if ($conditional) { my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; print F "#if ${conditionalString}\n\n"; @@ -876,12 +862,12 @@ sub printWrapperFunctions # Hack for the media tags # FIXME: This should have been done via a CustomWrapper attribute and a separate *Custom file. - if ($tags{$tagName}{"wrapperOnlyIfMediaIsAvailable"}) { + if ($tags{$tagName}{wrapperOnlyIfMediaIsAvailable}) { print F <<END -static JSNode* create${JSInterfaceName}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{'namespace'}Element> element) +static JSNode* create${JSInterfaceName}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element) { if (!MediaPlayer::isAvailable()) - return CREATE_DOM_NODE_WRAPPER(exec, globalObject, $parameters{'namespace'}Element, element.get()); + return CREATE_DOM_NODE_WRAPPER(exec, globalObject, $parameters{namespace}Element, element.get()); return CREATE_DOM_NODE_WRAPPER(exec, globalObject, ${JSInterfaceName}, element.get()); } @@ -889,7 +875,7 @@ END ; } else { print F <<END -static JSNode* create${JSInterfaceName}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{'namespace'}Element> element) +static JSNode* create${JSInterfaceName}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element) { return CREATE_DOM_NODE_WRAPPER(exec, globalObject, ${JSInterfaceName}, element.get()); } @@ -897,6 +883,7 @@ static JSNode* create${JSInterfaceName}Wrapper(ExecState* exec, JSDOMGlobalObjec END ; } + if ($conditional) { print F "#endif\n\n"; } @@ -913,13 +900,13 @@ sub printWrapperFactoryCppFile print F "#include \"config.h\"\n\n"; - print F "#if $parameters{'guardFactoryWith'}\n\n" if $parameters{'guardFactoryWith'}; + print F "#if $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith}; - print F "#include \"JS$parameters{'namespace'}ElementWrapperFactory.h\"\n"; + print F "#include \"JS$parameters{namespace}ElementWrapperFactory.h\"\n"; printJSElementIncludes($F); - print F "\n#include \"$parameters{'namespace'}Names.h\"\n\n"; + print F "\n#include \"$parameters{namespace}Names.h\"\n\n"; printElementIncludes($F); @@ -930,9 +917,9 @@ using namespace JSC; namespace WebCore { -using namespace $parameters{'namespace'}Names; +using namespace $parameters{namespace}Names; -typedef JSNode* (*Create$parameters{'namespace'}ElementWrapperFunction)(ExecState*, JSDOMGlobalObject*, PassRefPtr<$parameters{'namespace'}Element>); +typedef JSNode* (*Create$parameters{namespace}ElementWrapperFunction)(ExecState*, JSDOMGlobalObject*, PassRefPtr<$parameters{namespace}Element>); END ; @@ -940,9 +927,9 @@ END printWrapperFunctions($F); print F <<END -JSNode* createJS$parameters{'namespace'}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{'namespace'}Element> element) +JSNode* createJS$parameters{namespace}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element) { - typedef HashMap<WebCore::AtomicStringImpl*, Create$parameters{'namespace'}ElementWrapperFunction> FunctionMap; + typedef HashMap<WebCore::AtomicStringImpl*, Create$parameters{namespace}ElementWrapperFunction> FunctionMap; DEFINE_STATIC_LOCAL(FunctionMap, map, ()); if (map.isEmpty()) { END @@ -952,13 +939,13 @@ END # Do not add the name to the map if it does not have a JS wrapper constructor or uses the default wrapper. next if usesDefaultJSWrapper($tag, \%tags); - my $conditional = $tags{$tag}{"conditional"}; + my $conditional = $tags{$tag}{conditional}; if ($conditional) { my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; print F "#if ${conditionalString}\n"; } - my $ucTag = $tags{$tag}{"JSInterfaceName"}; + my $ucTag = $tags{$tag}{JSInterfaceName}; print F " map.set(${tag}Tag.localName().impl(), create${ucTag}Wrapper);\n"; if ($conditional) { @@ -968,10 +955,10 @@ END print F <<END } - Create$parameters{'namespace'}ElementWrapperFunction createWrapperFunction = map.get(element->localName().impl()); + Create$parameters{namespace}ElementWrapperFunction createWrapperFunction = map.get(element->localName().impl()); if (createWrapperFunction) return createWrapperFunction(exec, globalObject, element); - return CREATE_DOM_NODE_WRAPPER(exec, globalObject, $parameters{'namespace'}Element, element.get()); + return CREATE_DOM_NODE_WRAPPER(exec, globalObject, $parameters{namespace}Element, element.get()); } } @@ -979,7 +966,7 @@ END END ; - print F "#endif\n" if $parameters{'guardFactoryWith'}; + print F "#endif\n" if $parameters{guardFactoryWith}; close F; } @@ -992,10 +979,10 @@ sub printWrapperFactoryHeaderFile printLicenseHeader($F); - print F "#ifndef JS$parameters{'namespace'}ElementWrapperFactory_h\n"; - print F "#define JS$parameters{'namespace'}ElementWrapperFactory_h\n\n"; + print F "#ifndef JS$parameters{namespace}ElementWrapperFactory_h\n"; + print F "#define JS$parameters{namespace}ElementWrapperFactory_h\n\n"; - print F "#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'}; + print F "#if $parameters{guardFactoryWith}\n" if $parameters{guardFactoryWith}; print F <<END #include <wtf/Forward.h> @@ -1008,18 +995,18 @@ namespace WebCore { class JSNode; class JSDOMGlobalObject; - class $parameters{'namespace'}Element; + class $parameters{namespace}Element; - JSNode* createJS$parameters{'namespace'}Wrapper(JSC::ExecState*, JSDOMGlobalObject*, PassRefPtr<$parameters{'namespace'}Element>); + JSNode* createJS$parameters{namespace}Wrapper(JSC::ExecState*, JSDOMGlobalObject*, PassRefPtr<$parameters{namespace}Element>); } END ; - print F "#endif // $parameters{'guardFactoryWith'}\n\n" if $parameters{'guardFactoryWith'}; + print F "#endif // $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith}; - print F "#endif // JS$parameters{'namespace'}ElementWrapperFactory_h\n"; + print F "#endif // JS$parameters{namespace}ElementWrapperFactory_h\n"; close F; } |