summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/dom
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-25 19:08:45 +0100
committerSteve Block <steveblock@google.com>2011-06-08 13:51:31 +0100
commit2bde8e466a4451c7319e3a072d118917957d6554 (patch)
tree28f4a1b869a513e565c7760d0e6a06e7cf1fe95a /Source/WebCore/dom
parent6939c99b71d9372d14a0c74a772108052e8c48c8 (diff)
downloadexternal_webkit-2bde8e466a4451c7319e3a072d118917957d6554.zip
external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.tar.gz
external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.tar.bz2
Merge WebKit at r82507: Initial merge by git
Change-Id: I60ce9d780725b58b45e54165733a8ffee23b683e
Diffstat (limited to 'Source/WebCore/dom')
-rw-r--r--Source/WebCore/dom/CheckedRadioButtons.cpp2
-rw-r--r--Source/WebCore/dom/Clipboard.h7
-rw-r--r--Source/WebCore/dom/Clipboard.idl2
-rw-r--r--Source/WebCore/dom/ContainerNode.cpp2
-rw-r--r--Source/WebCore/dom/DOMAllInOne.cpp3
-rw-r--r--Source/WebCore/dom/DOMImplementation.cpp3
-rw-r--r--Source/WebCore/dom/DataTransferItem.cpp43
-rw-r--r--Source/WebCore/dom/DataTransferItem.h60
-rw-r--r--Source/WebCore/dom/DataTransferItem.idl42
-rw-r--r--Source/WebCore/dom/DataTransferItems.h62
-rw-r--r--Source/WebCore/dom/DataTransferItems.idl45
-rw-r--r--Source/WebCore/dom/DatasetDOMStringMap.cpp27
-rw-r--r--Source/WebCore/dom/Document.cpp207
-rw-r--r--Source/WebCore/dom/Document.h43
-rw-r--r--Source/WebCore/dom/Element.cpp44
-rw-r--r--Source/WebCore/dom/Element.h3
-rw-r--r--Source/WebCore/dom/Element.idl2
-rw-r--r--Source/WebCore/dom/Event.cpp9
-rw-r--r--Source/WebCore/dom/Event.h3
-rw-r--r--Source/WebCore/dom/EventDispatcher.cpp396
-rw-r--r--Source/WebCore/dom/EventDispatcher.h78
-rw-r--r--Source/WebCore/dom/ExceptionCode.h6
-rw-r--r--Source/WebCore/dom/InputElement.cpp22
-rw-r--r--Source/WebCore/dom/InputElement.h2
-rw-r--r--Source/WebCore/dom/KeyboardEvent.cpp7
-rw-r--r--Source/WebCore/dom/KeyboardEvent.h3
-rw-r--r--Source/WebCore/dom/MouseEvent.cpp34
-rw-r--r--Source/WebCore/dom/MouseEvent.h19
-rw-r--r--Source/WebCore/dom/MouseRelatedEvent.cpp62
-rw-r--r--Source/WebCore/dom/MouseRelatedEvent.h10
-rw-r--r--Source/WebCore/dom/NamedNodeMap.cpp6
-rw-r--r--Source/WebCore/dom/Node.cpp482
-rw-r--r--Source/WebCore/dom/Node.h28
-rw-r--r--Source/WebCore/dom/Position.cpp63
-rw-r--r--Source/WebCore/dom/Position.h3
-rw-r--r--Source/WebCore/dom/PositionIterator.cpp7
-rw-r--r--Source/WebCore/dom/QualifiedName.h2
-rw-r--r--Source/WebCore/dom/Range.cpp14
-rw-r--r--Source/WebCore/dom/ScriptElement.cpp29
-rw-r--r--Source/WebCore/dom/ScriptElement.h4
-rw-r--r--Source/WebCore/dom/ScriptExecutionContext.cpp2
-rw-r--r--Source/WebCore/dom/ScriptRunner.cpp (renamed from Source/WebCore/dom/AsyncScriptRunner.cpp)53
-rw-r--r--Source/WebCore/dom/ScriptRunner.h (renamed from Source/WebCore/dom/AsyncScriptRunner.h)27
-rw-r--r--Source/WebCore/dom/StringCallback.cpp71
-rw-r--r--Source/WebCore/dom/StringCallback.h52
-rw-r--r--Source/WebCore/dom/StringCallback.idl37
-rw-r--r--Source/WebCore/dom/StyleElement.cpp7
-rw-r--r--Source/WebCore/dom/StyledElement.cpp2
-rw-r--r--Source/WebCore/dom/UIEvent.cpp4
-rw-r--r--Source/WebCore/dom/UIEvent.h4
-rw-r--r--Source/WebCore/dom/ViewportArguments.cpp18
-rw-r--r--Source/WebCore/dom/ViewportArguments.h7
-rw-r--r--Source/WebCore/dom/default/PlatformMessagePortChannel.h4
53 files changed, 1468 insertions, 706 deletions
diff --git a/Source/WebCore/dom/CheckedRadioButtons.cpp b/Source/WebCore/dom/CheckedRadioButtons.cpp
index 3cf8848..20662a2 100644
--- a/Source/WebCore/dom/CheckedRadioButtons.cpp
+++ b/Source/WebCore/dom/CheckedRadioButtons.cpp
@@ -77,7 +77,7 @@ void CheckedRadioButtons::removeButton(HTMLFormControlElement* element)
if (it == m_nameToCheckedRadioButtonMap->end() || it->second != element)
return;
- InputElement* inputElement = toInputElement(element);
+ InputElement* inputElement = element->toInputElement();
ASSERT_UNUSED(inputElement, inputElement);
ASSERT(inputElement->isChecked());
ASSERT(element->isRadioButton());
diff --git a/Source/WebCore/dom/Clipboard.h b/Source/WebCore/dom/Clipboard.h
index b8eadfb..40141af 100644
--- a/Source/WebCore/dom/Clipboard.h
+++ b/Source/WebCore/dom/Clipboard.h
@@ -33,6 +33,7 @@
namespace WebCore {
+ class DataTransferItems;
class DragData;
class FileList;
class Frame;
@@ -84,6 +85,7 @@ namespace WebCore {
virtual bool hasData() = 0;
void setAccessPolicy(ClipboardAccessPolicy);
+ ClipboardAccessPolicy policy() const { return m_policy; }
DragOperation sourceOperation() const;
DragOperation destinationOperation() const;
@@ -91,11 +93,14 @@ namespace WebCore {
void setDestinationOperation(DragOperation);
void setDragHasStarted() { m_dragStarted = true; }
+
+#if ENABLE(DATA_TRANSFER_ITEMS)
+ virtual PassRefPtr<DataTransferItems> items() = 0;
+#endif
protected:
Clipboard(ClipboardAccessPolicy, ClipboardType);
- ClipboardAccessPolicy policy() const { return m_policy; }
bool dragStarted() const { return m_dragStarted; }
private:
diff --git a/Source/WebCore/dom/Clipboard.idl b/Source/WebCore/dom/Clipboard.idl
index 1024a36..d5bb331 100644
--- a/Source/WebCore/dom/Clipboard.idl
+++ b/Source/WebCore/dom/Clipboard.idl
@@ -42,6 +42,8 @@ module core {
[RequiresAllArguments] boolean setData(in DOMString type, in DOMString data);
[Custom] void setDragImage(in HTMLImageElement image, in long x, in long y)
raises(DOMException);
+
+ readonly attribute [Conditional=DATA_TRANSFER_ITEMS, EnabledAtRuntime=DataTransferItems] DataTransferItems items;
};
}
diff --git a/Source/WebCore/dom/ContainerNode.cpp b/Source/WebCore/dom/ContainerNode.cpp
index 7424875..4014cca 100644
--- a/Source/WebCore/dom/ContainerNode.cpp
+++ b/Source/WebCore/dom/ContainerNode.cpp
@@ -735,7 +735,7 @@ void ContainerNode::insertedIntoDocument()
{
Node::insertedIntoDocument();
insertedIntoTree(false);
- for (Node* child = m_firstChild; child; child = child->nextSibling())
+ for (Node* child = m_firstChild; child && inDocument(); child = child->nextSibling())
child->insertedIntoDocument();
}
diff --git a/Source/WebCore/dom/DOMAllInOne.cpp b/Source/WebCore/dom/DOMAllInOne.cpp
index c88aecf..cc4888f 100644
--- a/Source/WebCore/dom/DOMAllInOne.cpp
+++ b/Source/WebCore/dom/DOMAllInOne.cpp
@@ -26,7 +26,6 @@
// This all-in-one cpp file cuts down on template bloat to allow us to build our Windows release build.
#include "ActiveDOMObject.cpp"
-#include "AsyncScriptRunner.cpp"
#include "Attr.cpp"
#include "Attribute.cpp"
#include "BeforeProcessEvent.cpp"
@@ -70,6 +69,7 @@
#include "ErrorEvent.cpp"
#include "Event.cpp"
#include "EventContext.cpp"
+#include "EventDispatcher.cpp"
#include "EventNames.cpp"
#include "EventQueue.cpp"
#include "EventTarget.cpp"
@@ -104,6 +104,7 @@
#include "ScopedEventQueue.cpp"
#include "ScriptElement.cpp"
#include "ScriptExecutionContext.cpp"
+#include "ScriptRunner.cpp"
#include "ScriptableDocumentParser.cpp"
#include "SelectElement.cpp"
#include "SelectorNodeList.cpp"
diff --git a/Source/WebCore/dom/DOMImplementation.cpp b/Source/WebCore/dom/DOMImplementation.cpp
index 3ba1137..782f203 100644
--- a/Source/WebCore/dom/DOMImplementation.cpp
+++ b/Source/WebCore/dom/DOMImplementation.cpp
@@ -262,7 +262,8 @@ PassRefPtr<Document> DOMImplementation::createDocument(const String& namespaceUR
// 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).
+ // other exceptions to WRONG_DOCUMENT_ERR (based on order mentioned in spec),
+ // but this matches the new DOM Core spec (http://www.w3.org/TR/domcore/).
if (doctype && doctype->document()) {
ec = WRONG_DOCUMENT_ERR;
return 0;
diff --git a/Source/WebCore/dom/DataTransferItem.cpp b/Source/WebCore/dom/DataTransferItem.cpp
new file mode 100644
index 0000000..8eec869
--- /dev/null
+++ b/Source/WebCore/dom/DataTransferItem.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DataTransferItem.h"
+
+#if ENABLE(DATA_TRANSFER_ITEMS)
+
+namespace WebCore {
+
+const char DataTransferItem::kindString[] = "string";
+const char DataTransferItem::kindFile[] = "file";
+
+} // namespace WebCore
+
+#endif // ENABLE(DATA_TRANSFER_ITEMS)
diff --git a/Source/WebCore/dom/DataTransferItem.h b/Source/WebCore/dom/DataTransferItem.h
new file mode 100644
index 0000000..7b5886a
--- /dev/null
+++ b/Source/WebCore/dom/DataTransferItem.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DataTransferItem_h
+#define DataTransferItem_h
+
+#if ENABLE(DATA_TRANSFER_ITEMS)
+
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class StringCallback;
+
+class DataTransferItem : public RefCounted<DataTransferItem> {
+public:
+ ~DataTransferItem() {}
+
+ static const char kindString[];
+ static const char kindFile[];
+
+ virtual String kind() const = 0;
+ virtual String type() const = 0;
+
+ virtual void getAsString(PassRefPtr<StringCallback>) = 0;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(DATA_TRANSFER_ITEMS)
+
+#endif // DataTransferItem_h
diff --git a/Source/WebCore/dom/DataTransferItem.idl b/Source/WebCore/dom/DataTransferItem.idl
new file mode 100644
index 0000000..a2c9942
--- /dev/null
+++ b/Source/WebCore/dom/DataTransferItem.idl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module core {
+
+ interface [
+ Conditional=DATA_TRANSFER_ITEMS
+ ] DataTransferItem {
+ readonly attribute DOMString kind;
+ readonly attribute DOMString type;
+
+ void getAsString(in [Callback] StringCallback callback);
+ };
+
+}
diff --git a/Source/WebCore/dom/DataTransferItems.h b/Source/WebCore/dom/DataTransferItems.h
new file mode 100644
index 0000000..0873384
--- /dev/null
+++ b/Source/WebCore/dom/DataTransferItems.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DataTransferItems_h
+#define DataTransferItems_h
+
+#if ENABLE(DATA_TRANSFER_ITEMS)
+
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class DataTransferItem;
+
+typedef int ExceptionCode;
+
+class DataTransferItems : public RefCounted<DataTransferItems> {
+public:
+ ~DataTransferItems() {}
+
+ virtual unsigned long length() const = 0;
+ virtual PassRefPtr<DataTransferItem> item(unsigned long index) const = 0;
+ virtual void deleteItem(unsigned long index, ExceptionCode&) = 0;
+ virtual void clear() = 0;
+
+ virtual void add(const String& data, const String& type, ExceptionCode&) = 0;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(DATA_TRANSFER_ITEMS)
+
+#endif // DataTransferItems_h
+
diff --git a/Source/WebCore/dom/DataTransferItems.idl b/Source/WebCore/dom/DataTransferItems.idl
new file mode 100644
index 0000000..1cb36b8
--- /dev/null
+++ b/Source/WebCore/dom/DataTransferItems.idl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module core {
+
+ interface [
+ Conditional=DATA_TRANSFER_ITEMS,
+ HasIndexGetter,
+ CustomDeleteProperty,
+ ] DataTransferItems {
+ readonly attribute long length;
+ DataTransferItem item(in unsigned long index) getter;
+
+ void clear();
+ void add(in DOMString data, in DOMString type) raises(DOMException);
+ };
+
+}
diff --git a/Source/WebCore/dom/DatasetDOMStringMap.cpp b/Source/WebCore/dom/DatasetDOMStringMap.cpp
index 6359d55..a143743 100644
--- a/Source/WebCore/dom/DatasetDOMStringMap.cpp
+++ b/Source/WebCore/dom/DatasetDOMStringMap.cpp
@@ -72,13 +72,30 @@ static String convertAttributeNameToPropertyName(const String& name)
static bool propertyNameMatchesAttributeName(const String& propertyName, const String& attributeName)
{
- // FIXME: This should be able to match without creating a new string.
-
- if (!isValidAttributeName(attributeName))
+ if (!attributeName.startsWith("data-"))
return false;
- String convertedName = convertAttributeNameToPropertyName(attributeName);
- return (convertedName == propertyName);
+ const UChar* property = propertyName.characters();
+ const UChar* attribute = attributeName.characters();
+ unsigned propertyLength = propertyName.length();
+ unsigned attributeLength = attributeName.length();
+
+ unsigned a = 5;
+ unsigned p = 0;
+ bool wordBoundary = false;
+ while (a < attributeLength && p < propertyLength) {
+ if (attribute[a] == '-' && a + 1 < attributeLength && attribute[a + 1] != '-')
+ wordBoundary = true;
+ else {
+ if ((wordBoundary ? toASCIIUpper(attribute[a]) : attribute[a]) != property[p])
+ return false;
+ p++;
+ wordBoundary = false;
+ }
+ a++;
+ }
+
+ return (a == attributeLength && p == propertyLength);
}
static bool isValidPropertyName(const String& name)
diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp
index a2a8040..233b798 100644
--- a/Source/WebCore/dom/Document.cpp
+++ b/Source/WebCore/dom/Document.cpp
@@ -7,7 +7,6 @@
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
* Copyright (C) 2008, 2009 Google Inc. All rights reserved.
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
- * Copyright (C) Research In Motion, Limited 2010-2011.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -30,7 +29,6 @@
#include "AXObjectCache.h"
#include "AnimationController.h"
-#include "AsyncScriptRunner.h"
#include "Attr.h"
#include "Attribute.h"
#include "CDATASection.h"
@@ -44,6 +42,7 @@
#include "ChromeClient.h"
#include "Comment.h"
#include "Console.h"
+#include "ContentSecurityPolicy.h"
#include "CookieJar.h"
#include "CustomEvent.h"
#include "DateComponents.h"
@@ -120,6 +119,7 @@
#include "RegisteredEventListener.h"
#include "RenderArena.h"
#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
#include "RenderTextControl.h"
#include "RenderView.h"
#include "RenderWidget.h"
@@ -128,6 +128,7 @@
#include "ScriptController.h"
#include "ScriptElement.h"
#include "ScriptEventListener.h"
+#include "ScriptRunner.h"
#include "SecurityOrigin.h"
#include "SegmentedString.h"
#include "SelectionController.h"
@@ -333,7 +334,7 @@ static Widget* widgetForNode(Node* focusedNode)
static bool acceptsEditingFocus(Node* node)
{
ASSERT(node);
- ASSERT(node->isContentEditable());
+ ASSERT(node->rendererIsEditable());
Node* root = node->rootEditableElement();
Frame* frame = node->document()->frame();
@@ -358,7 +359,7 @@ static bool disableRangeMutation(Page* page)
static HashSet<Document*>* documentsThatNeedStyleRecalc = 0;
-class DocumentWeakReference : public ThreadSafeShared<DocumentWeakReference> {
+class DocumentWeakReference : public ThreadSafeRefCounted<DocumentWeakReference> {
public:
static PassRefPtr<DocumentWeakReference> create(Document* document)
{
@@ -387,14 +388,20 @@ private:
Document* m_document;
};
+uint64_t Document::s_globalTreeVersion = 0;
+
Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
: ContainerNode(0)
, m_compatibilityMode(NoQuirksMode)
, m_compatibilityModeLocked(false)
+<<<<<<< HEAD
, m_domTreeVersion(0)
#ifdef ANDROID_STYLE_VERSION
, m_styleVersion(0)
#endif
+=======
+ , m_domTreeVersion(++s_globalTreeVersion)
+>>>>>>> webkit.org at r82507
, m_styleSheets(StyleSheetList::create(this))
, m_readyState(Complete)
, m_styleRecalcTimer(this, &Document::styleRecalcTimerFired)
@@ -410,7 +417,7 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
, m_startTime(currentTime())
, m_overMinimumLayoutThreshold(false)
, m_extraLayoutDelay(0)
- , m_asyncScriptRunner(AsyncScriptRunner::create(this))
+ , m_scriptRunner(ScriptRunner::create(this))
, m_xmlVersion("1.0")
, m_xmlStandalone(false)
, m_savedRenderer(0)
@@ -454,7 +461,6 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
, m_writingModeSetOnDocumentElement(false)
, m_writeRecursionIsTooDeep(false)
, m_writeRecursionDepth(0)
- , m_pendingTasksTimer(this, &Document::pendingTasksTimerFired)
{
m_document = this;
@@ -563,6 +569,11 @@ void Document::removedLastRef()
m_cssCanvasElements.clear();
+#if ENABLE(REQUEST_ANIMATION_FRAME)
+ // FIXME: consider using ActiveDOMObject.
+ m_scriptedAnimationController = 0;
+#endif
+
#ifndef NDEBUG
m_inRemovedLastRefFunction = false;
#endif
@@ -584,7 +595,7 @@ Document::~Document()
ASSERT(m_ranges.isEmpty());
ASSERT(!m_styleRecalcTimer.isActive());
- m_asyncScriptRunner.clear();
+ m_scriptRunner.clear();
removeAllEventListeners();
@@ -1345,43 +1356,51 @@ static inline String canonicalizedTitle(Document* document, const String& title)
return String::adopt(buffer);
}
-void Document::updateTitle()
+void Document::updateTitle(const String& title)
{
+ if (m_rawTitle == title)
+ return;
+
+ m_rawTitle = title;
m_title = canonicalizedTitle(this, m_rawTitle);
if (Frame* f = frame())
f->loader()->setTitle(m_title);
}
-void Document::setTitle(const String& title, Element* titleElement)
+void Document::setTitle(const String& title)
{
- if (!titleElement) {
- // Title set by JavaScript -- overrides any title elements.
- m_titleSetExplicitly = true;
- if (!isHTMLDocument())
- m_titleElement = 0;
- else if (!m_titleElement) {
- if (HTMLElement* headElement = head()) {
- m_titleElement = createElement(titleTag, false);
- ExceptionCode ec = 0;
- headElement->appendChild(m_titleElement, ec);
- ASSERT(!ec);
- }
+ // Title set by JavaScript -- overrides any title elements.
+ m_titleSetExplicitly = true;
+ if (!isHTMLDocument())
+ m_titleElement = 0;
+ else if (!m_titleElement) {
+ if (HTMLElement* headElement = head()) {
+ m_titleElement = createElement(titleTag, false);
+ ExceptionCode ec = 0;
+ headElement->appendChild(m_titleElement, ec);
+ ASSERT(!ec);
}
- } else if (titleElement != m_titleElement) {
+ }
+
+ updateTitle(title);
+
+ if (m_titleElement) {
+ ASSERT(m_titleElement->hasTagName(titleTag));
+ if (m_titleElement->hasTagName(titleTag))
+ static_cast<HTMLTitleElement*>(m_titleElement.get())->setText(m_title);
+ }
+}
+
+void Document::setTitleElement(const String& title, Element* titleElement)
+{
+ if (titleElement != m_titleElement) {
if (m_titleElement || m_titleSetExplicitly)
// Only allow the first title element to change the title -- others have no effect.
return;
m_titleElement = titleElement;
}
- if (m_rawTitle == title)
- return;
-
- m_rawTitle = title;
- updateTitle();
-
- if (m_titleSetExplicitly && m_titleElement && m_titleElement->hasTagName(titleTag) && !titleElement)
- static_cast<HTMLTitleElement*>(m_titleElement.get())->setText(m_title);
+ updateTitle(title);
}
void Document::removeTitle(Element* titleElement)
@@ -1397,15 +1416,13 @@ void Document::removeTitle(Element* titleElement)
for (Node* e = headElement->firstChild(); e; e = e->nextSibling())
if (e->hasTagName(titleTag)) {
HTMLTitleElement* titleElement = static_cast<HTMLTitleElement*>(e);
- setTitle(titleElement->text(), titleElement);
+ setTitleElement(titleElement->text(), titleElement);
break;
}
}
- if (!m_titleElement && !m_rawTitle.isEmpty()) {
- m_rawTitle = "";
- updateTitle();
- }
+ if (!m_titleElement)
+ updateTitle("");
}
String Document::nodeName() const
@@ -1793,7 +1810,12 @@ void Document::detach()
clearAXObjectCache();
stopActiveDOMObjects();
-
+
+#if ENABLE(REQUEST_ANIMATION_FRAME)
+ // FIXME: consider using ActiveDOMObject.
+ m_scriptedAnimationController = 0;
+#endif
+
RenderObject* render = renderer();
// Send out documentWillBecomeInactive() notifications to registered elements,
@@ -3994,7 +4016,7 @@ void Document::setInPageCache(bool flag)
ASSERT(!m_savedRenderer);
m_savedRenderer = renderer();
if (FrameView* v = view())
- v->resetScrollbars();
+ v->resetScrollbarsAndClearContentsSize();
m_styleRecalcTimer.stop();
} else {
ASSERT(!renderer() || renderer() == m_savedRenderer);
@@ -4486,7 +4508,7 @@ void FormElementKey::deref() const
unsigned FormElementKeyHash::hash(const FormElementKey& key)
{
- return WTF::StringHasher::createBlobHash<sizeof(FormElementKey)>(&key);
+ return StringHasher::hashMemory<sizeof(FormElementKey)>(&key);
}
void Document::setIconURL(const String& iconURL, const String& type)
@@ -4551,7 +4573,7 @@ void Document::initSecurityContext()
// loading URL with a fresh content security policy.
m_cookieURL = m_url;
ScriptExecutionContext::setSecurityOrigin(SecurityOrigin::create(m_url, m_frame->loader()->sandboxFlags()));
- m_contentSecurityPolicy = ContentSecurityPolicy::create();
+ m_contentSecurityPolicy = ContentSecurityPolicy::create(securityOrigin());
if (SecurityOrigin::allowSubstituteDataAccessToLocal()) {
// If this document was loaded with substituteData, then the document can
@@ -4780,59 +4802,22 @@ public:
OwnPtr<ScriptExecutionContext::Task> task;
};
-void Document::didReceiveTask(void* untypedContext)
+static void performTask(void* ctx)
{
ASSERT(isMainThread());
- OwnPtr<PerformTaskContext> context = adoptPtr(static_cast<PerformTaskContext*>(untypedContext));
+ PerformTaskContext* context = reinterpret_cast<PerformTaskContext*>(ctx);
ASSERT(context);
- Document* document = context->documentReference->document();
- if (!document)
- return;
-
- Page* page = document->page();
- if ((page && page->defersLoading()) || !document->m_pendingTasks.isEmpty()) {
- document->m_pendingTasks.append(context->task.release());
- return;
- }
+ if (Document* document = context->documentReference->document())
+ context->task->performTask(document);
- context->task->performTask(document);
+ delete context;
}
void Document::postTask(PassOwnPtr<Task> task)
{
- callOnMainThread(didReceiveTask, new PerformTaskContext(m_weakReference, task));
-}
-
-void Document::pendingTasksTimerFired(Timer<Document>*)
-{
- while (!m_pendingTasks.isEmpty()) {
- OwnPtr<Task> task = m_pendingTasks[0].release();
- m_pendingTasks.remove(0);
- task->performTask(this);
- }
-}
-
-void Document::suspendScheduledTasks()
-{
- suspendScriptedAnimationControllerCallbacks();
- suspendActiveDOMObjects(ActiveDOMObject::WillShowDialog);
- asyncScriptRunner()->suspend();
- m_pendingTasksTimer.stop();
- if (m_parser)
- m_parser->suspendScheduledTasks();
-}
-
-void Document::resumeScheduledTasks()
-{
- if (m_parser)
- m_parser->resumeScheduledTasks();
- if (!m_pendingTasks.isEmpty())
- m_pendingTasksTimer.startOneShot(0);
- asyncScriptRunner()->resume();
- resumeActiveDOMObjects();
- resumeScriptedAnimationControllerCallbacks();
+ callOnMainThread(performTask, new PerformTaskContext(m_weakReference, task));
}
void Document::suspendScriptedAnimationControllerCallbacks()
@@ -4947,6 +4932,20 @@ bool Document::isXHTMLMPDocument() const
#endif
#if ENABLE(FULLSCREEN_API)
+bool Document::fullScreenIsAllowedForElement(Element* element) const
+{
+ ASSERT(element);
+ while (HTMLFrameOwnerElement* ownerElement = element->document()->ownerElement()) {
+ if (!ownerElement->hasTagName(frameTag) && !ownerElement->hasTagName(iframeTag))
+ continue;
+
+ if (!static_cast<HTMLFrameElementBase*>(ownerElement)->allowFullScreen())
+ return false;
+ element = ownerElement;
+ }
+ return true;
+}
+
void Document::webkitRequestFullScreenForElement(Element* element, unsigned short flags)
{
if (!page() || !page()->settings()->fullScreenEnabled())
@@ -4955,7 +4954,13 @@ void Document::webkitRequestFullScreenForElement(Element* element, unsigned shor
if (!element)
element = documentElement();
- if (!page()->chrome()->client()->supportsFullScreenForElement(element))
+ if (!fullScreenIsAllowedForElement(element))
+ return;
+
+ if (!ScriptController::processingUserGesture())
+ return;
+
+ if (!page()->chrome()->client()->supportsFullScreenForElement(element, flags & Element::ALLOW_KEYBOARD_INPUT))
return;
m_areKeysEnabledInFullScreen = flags & Element::ALLOW_KEYBOARD_INPUT;
@@ -4983,23 +4988,40 @@ void Document::webkitWillEnterFullScreenForElement(Element* element)
recalcStyle(Force);
- if (m_fullScreenRenderer)
+ if (m_fullScreenRenderer) {
m_fullScreenRenderer->setAnimating(true);
+#if USE(ACCELERATED_COMPOSITING)
+ view()->updateCompositingLayers();
+ ASSERT(m_fullScreenRenderer->layer()->backing());
+ page()->chrome()->client()->setRootFullScreenLayer(m_fullScreenRenderer->layer()->backing()->graphicsLayer());
+#endif
+ }
}
void Document::webkitDidEnterFullScreenForElement(Element*)
{
- if (m_fullScreenRenderer)
+ if (m_fullScreenRenderer) {
m_fullScreenRenderer->setAnimating(false);
+#if USE(ACCELERATED_COMPOSITING)
+ view()->updateCompositingLayers();
+ ASSERT(!m_fullScreenRenderer->layer()->backing());
+ page()->chrome()->client()->setRootFullScreenLayer(0);
+#endif
+ }
m_fullScreenChangeDelayTimer.startOneShot(0);
}
void Document::webkitWillExitFullScreenForElement(Element*)
{
- if (m_fullScreenRenderer)
+ if (m_fullScreenRenderer) {
m_fullScreenRenderer->setAnimating(true);
-
- recalcStyle(Force);
+ m_fullScreenRenderer->setAnimating(true);
+#if USE(ACCELERATED_COMPOSITING)
+ view()->updateCompositingLayers();
+ ASSERT(m_fullScreenRenderer->layer()->backing());
+ page()->chrome()->client()->setRootFullScreenLayer(m_fullScreenRenderer->layer()->backing()->graphicsLayer());
+#endif
+ }
}
void Document::webkitDidExitFullScreenForElement(Element*)
@@ -5014,6 +5036,9 @@ void Document::webkitDidExitFullScreenForElement(Element*)
m_fullScreenElement->detach();
setFullScreenRenderer(0);
+#if USE(ACCELERATED_COMPOSITING)
+ page()->chrome()->client()->setRootFullScreenLayer(0);
+#endif
recalcStyle(Force);
m_fullScreenChangeDelayTimer.startOneShot(0);
@@ -5021,6 +5046,11 @@ void Document::webkitDidExitFullScreenForElement(Element*)
void Document::setFullScreenRenderer(RenderFullScreen* renderer)
{
+ if (renderer == m_fullScreenRenderer)
+ return;
+
+ if (m_fullScreenRenderer)
+ m_fullScreenRenderer->destroy();
m_fullScreenRenderer = renderer;
// This notification can come in after the page has been destroyed.
@@ -5041,6 +5071,7 @@ void Document::setFullScreenRendererSize(const IntSize& size)
newStyle->setTop(Length(0, WebCore::Fixed));
newStyle->setLeft(Length(0, WebCore::Fixed));
m_fullScreenRenderer->setStyle(newStyle);
+ updateLayout();
}
}
diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h
index ae9b24e..c9a1b55 100644
--- a/Source/WebCore/dom/Document.h
+++ b/Source/WebCore/dom/Document.h
@@ -32,7 +32,6 @@
#include "CollectionType.h"
#include "Color.h"
#include "ContainerNode.h"
-#include "ContentSecurityPolicy.h"
#include "DOMTimeStamp.h"
#include "DocumentOrderedMap.h"
#include "DocumentTiming.h"
@@ -51,20 +50,20 @@
namespace WebCore {
-class AsyncScriptRunner;
-class Attr;
class AXObjectCache;
+class Attr;
class CDATASection;
+class CSSPrimitiveValueCache;
+class CSSStyleDeclaration;
+class CSSStyleSelector;
+class CSSStyleSheet;
class CachedCSSStyleSheet;
class CachedResourceLoader;
class CachedScript;
class CanvasRenderingContext;
class CharacterData;
-class CSSPrimitiveValueCache;
-class CSSStyleDeclaration;
-class CSSStyleSelector;
-class CSSStyleSheet;
class Comment;
+class ContentSecurityPolicy;
class DOMImplementation;
class DOMSelection;
class DOMWindow;
@@ -115,6 +114,7 @@ class RenderView;
class RenderFullScreen;
class ScriptableDocumentParser;
class ScriptElementData;
+class ScriptRunner;
class SecurityOrigin;
class SerializedScriptValue;
class SegmentedString;
@@ -820,7 +820,8 @@ public:
HTMLFrameOwnerElement* ownerElement() const;
String title() const { return m_title; }
- void setTitle(const String&, Element* titleElement = 0);
+ void setTitle(const String&);
+ void setTitleElement(const String& title, Element* titleElement);
void removeTitle(Element* titleElement);
String cookie(ExceptionCode&) const;
@@ -908,7 +909,7 @@ public:
int docID() const { return m_docID; }
- AsyncScriptRunner* asyncScriptRunner() { return m_asyncScriptRunner.get(); }
+ ScriptRunner* scriptRunner() { return m_scriptRunner.get(); }
#if ENABLE(XSLT)
void applyXSLTransform(ProcessingInstruction* pi);
@@ -919,8 +920,8 @@ public:
TransformSource* transformSource() const { return m_transformSource.get(); }
#endif
- void incDOMTreeVersion() { ++m_domTreeVersion; }
- unsigned domTreeVersion() const { return m_domTreeVersion; }
+ void incDOMTreeVersion() { m_domTreeVersion = ++s_globalTreeVersion; }
+ uint64_t domTreeVersion() const { return m_domTreeVersion; }
#ifdef ANDROID_STYLE_VERSION
void incStyleVersion() { ++m_styleVersion; }
@@ -1106,6 +1107,7 @@ public:
void setFullScreenRendererBackgroundColor(Color);
void fullScreenChangeDelayTimerFired(Timer<Document>*);
+ bool fullScreenIsAllowedForElement(Element*) const;
#endif
// Used to allow element that loads data without going through a FrameLoader to delay the 'load' event.
@@ -1135,9 +1137,6 @@ public:
ContentSecurityPolicy* contentSecurityPolicy() { return m_contentSecurityPolicy.get(); }
- void suspendScheduledTasks();
- void resumeScheduledTasks();
-
protected:
Document(Frame*, const KURL&, bool isXHTML, bool isHTML);
@@ -1173,7 +1172,7 @@ private:
String encoding() const;
- void updateTitle();
+ void updateTitle(const String& title);
void updateFocusAppearanceTimerFired(Timer<Document>*);
void updateBaseURL();
@@ -1185,10 +1184,6 @@ private:
void loadEventDelayTimerFired(Timer<Document>*);
- void pendingTasksTimerFired(Timer<Document>*);
-
- static void didReceiveTask(void*);
-
OwnPtr<CSSStyleSelector> m_styleSelector;
bool m_didCalculateStyleSelector;
bool m_hasDirtyStyleSelector;
@@ -1258,10 +1253,15 @@ private:
RefPtr<Node> m_activeNode;
mutable RefPtr<Element> m_documentElement;
+<<<<<<< HEAD
unsigned m_domTreeVersion;
#ifdef ANDROID_STYLE_VERSION
unsigned m_styleVersion;
#endif
+=======
+ uint64_t m_domTreeVersion;
+ static uint64_t s_globalTreeVersion;
+>>>>>>> webkit.org at r82507
HashSet<NodeIterator*> m_nodeIterators;
HashSet<Range*> m_ranges;
@@ -1341,7 +1341,7 @@ private:
// points during the lifetime of the Document.
int m_extraLayoutDelay;
- OwnPtr<AsyncScriptRunner> m_asyncScriptRunner;
+ OwnPtr<ScriptRunner> m_scriptRunner;
#if ENABLE(XSLT)
OwnPtr<TransformSource> m_transformSource;
@@ -1460,9 +1460,6 @@ private:
#endif
RefPtr<ContentSecurityPolicy> m_contentSecurityPolicy;
-
- Timer<Document> m_pendingTasksTimer;
- Vector<OwnPtr<Task> > m_pendingTasks;
};
inline bool Document::hasElementWithId(AtomicStringImpl* id) const
diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp
index 41c0fb1..81668cf 100644
--- a/Source/WebCore/dom/Element.cpp
+++ b/Source/WebCore/dom/Element.cpp
@@ -55,7 +55,9 @@
#include "RenderWidget.h"
#include "Settings.h"
#include "TextIterator.h"
+#include "WebKitAnimationList.h"
#include "XMLNames.h"
+#include "htmlediting.h"
#include <wtf/text/CString.h>
#if ENABLE(SVG)
@@ -1199,6 +1201,15 @@ bool Element::childTypeAllowed(NodeType type)
return false;
}
+static void checkForEmptyStyleChange(Element* element, RenderStyle* style)
+{
+ if (!style)
+ return;
+
+ if (style->affectedByEmpty() && (!style->emptyState() || element->hasChildNodes()))
+ element->setNeedsStyleRecalc();
+}
+
static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback,
Node* beforeChange, Node* afterChange, int childCountDelta)
{
@@ -1275,17 +1286,18 @@ static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool fin
e->setNeedsStyleRecalc();
// :empty selector.
- if (style->affectedByEmpty() && (!style->emptyState() || e->hasChildNodes()))
- e->setNeedsStyleRecalc();
+ checkForEmptyStyleChange(e, style);
}
void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
{
ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
- if (!changedByParser)
+ if (changedByParser)
+ checkForEmptyStyleChange(this, renderStyle());
+ else
checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);
}
-
+
void Element::beginParsingChildren()
{
clearIsParsingChildrenFinished();
@@ -1413,10 +1425,8 @@ PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
ec = NOT_FOUND_ERR;
return 0;
}
- if (document() != attr->document()) {
- ec = WRONG_DOCUMENT_ERR;
- return 0;
- }
+
+ ASSERT(document() == attr->document());
NamedNodeMap* attrs = attributes(true);
if (!attrs)
@@ -1508,6 +1518,9 @@ CSSStyleDeclaration *Element::style()
void Element::focus(bool restorePreviousSelection)
{
+ if (!inDocument())
+ return;
+
Document* doc = document();
if (doc->focusedNode() == this)
return;
@@ -1558,7 +1571,7 @@ void Element::updateFocusAppearance(bool /*restorePreviousSelection*/)
return;
// FIXME: We should restore the previous selection if there is one.
- VisibleSelection newSelection = VisibleSelection(firstPositionInNode(this), DOWNSTREAM);
+ VisibleSelection newSelection = VisibleSelection(firstPositionInOrBeforeNode(this), DOWNSTREAM);
if (frame->selection()->shouldChangeSelection(newSelection)) {
frame->selection()->setSelection(newSelection);
@@ -1891,4 +1904,17 @@ bool Element::isSpellCheckingEnabled() const
return true;
}
+PassRefPtr<WebKitAnimationList> Element::webkitGetAnimations() const
+{
+ if (!renderer())
+ return 0;
+
+ AnimationController* animController = renderer()->animation();
+
+ if (!animController)
+ return 0;
+
+ return animController->animationsForRenderer(renderer());
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/dom/Element.h b/Source/WebCore/dom/Element.h
index 5c54ce4..ba0870c 100644
--- a/Source/WebCore/dom/Element.h
+++ b/Source/WebCore/dom/Element.h
@@ -39,6 +39,7 @@ class DOMStringMap;
class DOMTokenList;
class ElementRareData;
class IntSize;
+class WebKitAnimationList;
enum SpellcheckAttributeState {
SpellcheckAttributeTrue,
@@ -344,6 +345,8 @@ public:
virtual bool isSpellCheckingEnabled() const;
+ PassRefPtr<WebKitAnimationList> webkitGetAnimations() const;
+
protected:
Element(const QualifiedName& tagName, Document* document, ConstructionType type)
: ContainerNode(document, type)
diff --git a/Source/WebCore/dom/Element.idl b/Source/WebCore/dom/Element.idl
index 652a75b..fc28642 100644
--- a/Source/WebCore/dom/Element.idl
+++ b/Source/WebCore/dom/Element.idl
@@ -96,6 +96,8 @@ module core {
void scrollByLines(in long lines);
void scrollByPages(in long pages);
+ WebKitAnimationList webkitGetAnimations();
+
// HTML 5
NodeList getElementsByClassName(in DOMString name);
diff --git a/Source/WebCore/dom/Event.cpp b/Source/WebCore/dom/Event.cpp
index 795dace..a1352dc 100644
--- a/Source/WebCore/dom/Event.cpp
+++ b/Source/WebCore/dom/Event.cpp
@@ -22,6 +22,7 @@
#include "config.h"
#include "Event.h"
+#include "EventDispatcher.h"
#include "EventTarget.h"
#include "UserGestureIndicator.h"
@@ -270,8 +271,16 @@ void Event::storeResult(const String&)
{
}
+bool Event::dispatch(EventDispatcher* dispatcher)
+{
+ return dispatcher->dispatchEvent(this);
+}
+
void Event::setTarget(PassRefPtr<EventTarget> target)
{
+ if (m_target == target)
+ return;
+
m_target = target;
if (m_target)
receivedTarget();
diff --git a/Source/WebCore/dom/Event.h b/Source/WebCore/dom/Event.h
index ba9576b..d4d7e06 100644
--- a/Source/WebCore/dom/Event.h
+++ b/Source/WebCore/dom/Event.h
@@ -32,6 +32,7 @@
namespace WebCore {
class EventTarget;
+ class EventDispatcher;
class Event : public RefCounted<Event> {
public:
@@ -165,6 +166,8 @@ namespace WebCore {
virtual Clipboard* clipboard() const { return 0; }
+ virtual bool dispatch(EventDispatcher*);
+
protected:
Event();
Event(const AtomicString& type, bool canBubble, bool cancelable);
diff --git a/Source/WebCore/dom/EventDispatcher.cpp b/Source/WebCore/dom/EventDispatcher.cpp
new file mode 100644
index 0000000..c8b330d
--- /dev/null
+++ b/Source/WebCore/dom/EventDispatcher.cpp
@@ -0,0 +1,396 @@
+/*
+ * 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, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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 "EventDispatcher.h"
+
+#include "Event.h"
+#include "EventContext.h"
+#include "EventTarget.h"
+#include "FrameView.h"
+#include "InspectorInstrumentation.h"
+#include "MouseEvent.h"
+#include "Node.h"
+#include "PlatformWheelEvent.h"
+#include "ScopedEventQueue.h"
+
+#if ENABLE(SVG)
+#include "SVGElementInstance.h"
+#include "SVGNames.h"
+#include "SVGUseElement.h"
+#endif
+
+#include "UIEvent.h"
+#include "UIEventWithKeyState.h"
+#include "WheelEvent.h"
+#include "WindowEventContext.h"
+
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+static HashSet<Node*>* gNodesDispatchingSimulatedClicks = 0;
+
+bool EventDispatcher::dispatchEvent(Node* node, PassRefPtr<Event> prpEvent)
+{
+ RefPtr<Event> event = prpEvent;
+
+ EventDispatcher dispatcher(node);
+ return event->dispatch(&dispatcher);
+}
+
+static EventTarget* findElementInstance(Node* referenceNode)
+{
+#if ENABLE(SVG)
+ // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
+ // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
+ for (Node* n = referenceNode; n; n = n->parentNode()) {
+ if (!n->isShadowRoot() || !n->isSVGElement())
+ continue;
+
+ Element* shadowTreeParentElement = n->shadowHost();
+ ASSERT(shadowTreeParentElement->hasTagName(SVGNames::useTag));
+
+ if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode))
+ return instance;
+ }
+#else
+ // SVG elements with SVG disabled should not be possible.
+ ASSERT_NOT_REACHED();
+#endif
+
+ return referenceNode;
+}
+
+inline static EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode)
+{
+ ASSERT(referenceNode);
+
+ return referenceNode->isSVGElement() ? findElementInstance(referenceNode) : referenceNode;
+}
+
+void EventDispatcher::dispatchScopedEvent(Node* node, PassRefPtr<Event> event)
+{
+ // We need to set the target here because it can go away by the time we actually fire the event.
+ event->setTarget(eventTargetRespectingSVGTargetRules(node));
+
+ ScopedEventQueue::instance()->enqueueEvent(event);
+}
+
+void EventDispatcher::dispatchSimulatedClick(Node* node, PassRefPtr<Event> underlyingEvent, bool sendMouseEvents, bool showPressedLook)
+{
+ EventDispatcher dispatcher(node);
+
+ if (!gNodesDispatchingSimulatedClicks)
+ gNodesDispatchingSimulatedClicks = new HashSet<Node*>;
+ else if (gNodesDispatchingSimulatedClicks->contains(node))
+ return;
+
+ gNodesDispatchingSimulatedClicks->add(node);
+
+ // send mousedown and mouseup before the click, if requested
+ if (sendMouseEvents)
+ dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().mousedownEvent, node->document()->defaultView(), underlyingEvent));
+ node->setActive(true, showPressedLook);
+ if (sendMouseEvents)
+ dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().mouseupEvent, node->document()->defaultView(), underlyingEvent));
+ node->setActive(false);
+
+ // always send click
+ dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().clickEvent, node->document()->defaultView(), underlyingEvent));
+
+ gNodesDispatchingSimulatedClicks->remove(node);
+}
+
+inline static WheelEvent::Granularity granularity(const PlatformWheelEvent& event)
+{
+ return event.granularity() == ScrollByPageWheelEvent ? WheelEvent::Page : WheelEvent::Pixel;
+}
+
+void EventDispatcher::dispatchWheelEvent(Node* node, PlatformWheelEvent& event)
+{
+ ASSERT(!eventDispatchForbidden());
+ if (!(event.deltaX() || event.deltaY()))
+ return;
+
+ EventDispatcher dispatcher(node);
+
+ if (!dispatcher.m_view)
+ return;
+
+ IntPoint position = dispatcher.m_view->windowToContents(event.pos());
+
+ int adjustedPageX = position.x();
+ int adjustedPageY = position.y();
+ if (Frame* frame = node->document()->frame()) {
+ float pageZoom = frame->pageZoomFactor();
+ if (pageZoom != 1.0f) {
+ adjustedPageX = lroundf(position.x() / pageZoom);
+ adjustedPageY = lroundf(position.y() / pageZoom);
+ }
+ }
+
+ RefPtr<WheelEvent> wheelEvent = WheelEvent::create(event.wheelTicksX(), event.wheelTicksY(), event.deltaX(), event.deltaY(), granularity(event),
+ node->document()->defaultView(), event.globalX(), event.globalY(), adjustedPageX, adjustedPageY,
+ event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey());
+
+ wheelEvent->setAbsoluteLocation(position);
+
+ if (!dispatcher.dispatchEvent(wheelEvent) || wheelEvent->defaultHandled())
+ event.accept();
+
+}
+
+// FIXME: Once https://bugs.webkit.org/show_bug.cgi?id=52963 lands, this should
+// be greatly improved. See https://bugs.webkit.org/show_bug.cgi?id=54025.
+static Node* pullOutOfShadow(Node* node)
+{
+ Node* outermostShadowBoundary = node;
+ for (Node* n = node; n; n = n->parentOrHostNode()) {
+ if (n->isShadowRoot())
+ outermostShadowBoundary = n->parentOrHostNode();
+ }
+ return outermostShadowBoundary;
+}
+
+EventDispatcher::EventDispatcher(Node* node)
+ : m_node(node)
+{
+ ASSERT(node);
+ m_view = node->document()->view();
+}
+
+void EventDispatcher::getEventAncestors(EventTarget* originalTarget, EventDispatchBehavior behavior)
+{
+ if (!m_node->inDocument())
+ return;
+
+ if (ancestorsInitialized())
+ return;
+
+ EventTarget* target = originalTarget;
+ Node* ancestor = m_node.get();
+ bool shouldSkipNextAncestor = false;
+ while (true) {
+ if (ancestor->isShadowRoot()) {
+ if (behavior == StayInsideShadowDOM)
+ return;
+ ancestor = ancestor->shadowHost();
+ if (!shouldSkipNextAncestor)
+ target = ancestor;
+ } else
+ ancestor = ancestor->parentNodeGuaranteedHostFree();
+
+ if (!ancestor)
+ return;
+
+#if ENABLE(SVG)
+ // Skip SVGShadowTreeRootElement.
+ shouldSkipNextAncestor = ancestor->isSVGElement() && ancestor->isShadowRoot();
+ if (shouldSkipNextAncestor)
+ continue;
+#endif
+ // FIXME: Unroll the extra loop inside eventTargetRespectingSVGTargetRules into this loop.
+ m_ancestors.append(EventContext(ancestor, eventTargetRespectingSVGTargetRules(ancestor), target));
+ }
+}
+
+bool EventDispatcher::dispatchEvent(PassRefPtr<Event> event)
+{
+ event->setTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
+
+ ASSERT(!eventDispatchForbidden());
+ ASSERT(event->target());
+ ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.
+
+ RefPtr<EventTarget> originalTarget = event->target();
+ getEventAncestors(originalTarget.get(), determineDispatchBehavior(event.get()));
+
+ WindowEventContext windowContext(event.get(), m_node.get(), topEventContext());
+
+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *event, windowContext.window(), m_node.get(), m_ancestors);
+
+ // Give the target node a chance to do some work before DOM event handlers get a crack.
+ void* data = m_node->preDispatchEventHandler(event.get());
+ if (event->propagationStopped())
+ goto doneDispatching;
+
+ // Trigger capturing event handlers, starting at the top and working our way down.
+ event->setEventPhase(Event::CAPTURING_PHASE);
+
+ if (windowContext.handleLocalEvents(event.get()) && event->propagationStopped())
+ goto doneDispatching;
+
+ for (size_t i = m_ancestors.size(); i; --i) {
+ m_ancestors[i - 1].handleLocalEvents(event.get());
+ if (event->propagationStopped())
+ goto doneDispatching;
+ }
+
+ event->setEventPhase(Event::AT_TARGET);
+ event->setTarget(originalTarget.get());
+ event->setCurrentTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
+ m_node->handleLocalEvents(event.get());
+ if (event->propagationStopped())
+ goto doneDispatching;
+
+ if (event->bubbles() && !event->cancelBubble()) {
+ // Trigger bubbling event handlers, starting at the bottom and working our way up.
+ event->setEventPhase(Event::BUBBLING_PHASE);
+
+ size_t size = m_ancestors.size();
+ for (size_t i = 0; i < size; ++i) {
+ m_ancestors[i].handleLocalEvents(event.get());
+ if (event->propagationStopped() || event->cancelBubble())
+ goto doneDispatching;
+ }
+ windowContext.handleLocalEvents(event.get());
+ }
+
+doneDispatching:
+ event->setTarget(originalTarget.get());
+ event->setCurrentTarget(0);
+ event->setEventPhase(0);
+
+ // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
+ m_node->postDispatchEventHandler(event.get(), data);
+
+ // Call default event handlers. While the DOM does have a concept of preventing
+ // default handling, the detail of which handlers are called is an internal
+ // implementation detail and not part of the DOM.
+ if (!event->defaultPrevented() && !event->defaultHandled()) {
+ // Non-bubbling events call only one default event handler, the one for the target.
+ m_node->defaultEventHandler(event.get());
+ ASSERT(!event->defaultPrevented());
+ if (event->defaultHandled())
+ goto doneWithDefault;
+ // For bubbling events, call default event handlers on the same targets in the
+ // same order as the bubbling phase.
+ if (event->bubbles()) {
+ size_t size = m_ancestors.size();
+ for (size_t i = 0; i < size; ++i) {
+ m_ancestors[i].node()->defaultEventHandler(event.get());
+ ASSERT(!event->defaultPrevented());
+ if (event->defaultHandled())
+ goto doneWithDefault;
+ }
+ }
+ }
+
+doneWithDefault:
+
+ // Ensure that after event dispatch, the event's target object is the
+ // outermost shadow DOM boundary.
+ event->setTarget(windowContext.target());
+ event->setCurrentTarget(0);
+ InspectorInstrumentation::didDispatchEvent(cookie);
+
+ return !event->defaultPrevented();
+}
+bool EventDispatcher::dispatchMouseEvent(Node* node, const PlatformMouseEvent& event, const AtomicString& eventType,
+ int detail, Node* relatedTargetArg)
+{
+ ASSERT(!eventDispatchForbidden());
+ ASSERT(event.eventType() == MouseEventMoved || event.button() != NoButton);
+
+ if (node->disabled()) // Don't even send DOM events for disabled controls..
+ return true;
+
+ if (eventType.isEmpty())
+ return false; // Shouldn't happen.
+
+ EventDispatcher dispatcher(node);
+
+ // Attempting to dispatch with a non-EventTarget relatedTarget causes the relatedTarget to be silently ignored.
+ RefPtr<Node> relatedTarget = pullOutOfShadow(relatedTargetArg);
+
+ IntPoint contentsPosition;
+ if (FrameView* view = node->document()->view())
+ contentsPosition = view->windowToContents(event.pos());
+
+ IntPoint adjustedPagePosition = contentsPosition;
+ if (Frame* frame = node->document()->frame()) {
+ float pageZoom = frame->pageZoomFactor();
+ if (pageZoom != 1.0f) {
+ // Adjust our pageX and pageY to account for the page zoom.
+ adjustedPagePosition.setX(lroundf(contentsPosition.x() / pageZoom));
+ adjustedPagePosition.setY(lroundf(contentsPosition.y() / pageZoom));
+ }
+ }
+
+ RefPtr<MouseEvent> mouseEvent = MouseEvent::create(eventType, node->document()->defaultView(), event, adjustedPagePosition, detail, relatedTarget);
+ mouseEvent->setAbsoluteLocation(contentsPosition);
+
+ bool swallowEvent = false;
+
+ dispatcher.dispatchEvent(mouseEvent);
+ bool defaultHandled = mouseEvent->defaultHandled();
+ bool defaultPrevented = mouseEvent->defaultPrevented();
+ if (defaultHandled || defaultPrevented)
+ swallowEvent = true;
+
+ // Special case: If it's a double click event, we also send the dblclick event. This is not part
+ // of the DOM specs, but is used for compatibility with the ondblclick="" attribute. This is treated
+ // as a separate event in other DOM-compliant browsers like Firefox, and so we do the same.
+ if (eventType == eventNames().clickEvent && detail == 2) {
+ RefPtr<Event> doubleClickEvent = MouseEvent::create(eventNames().dblclickEvent, node->document()->defaultView(), event, adjustedPagePosition, detail, relatedTarget);
+ if (defaultHandled)
+ doubleClickEvent->setDefaultHandled();
+ dispatcher.dispatchEvent(doubleClickEvent);
+ if (doubleClickEvent->defaultHandled() || doubleClickEvent->defaultPrevented())
+ swallowEvent = true;
+ }
+
+ return swallowEvent;
+}
+
+const EventContext* EventDispatcher::topEventContext()
+{
+ return m_ancestors.isEmpty() ? 0 : &m_ancestors.last();
+}
+
+bool EventDispatcher::ancestorsInitialized() const
+{
+ return m_ancestors.size();
+}
+
+EventDispatchBehavior EventDispatcher::determineDispatchBehavior(Event* event)
+{
+ // Per XBL 2.0 spec, mutation events should never cross shadow DOM boundary:
+ // http://dev.w3.org/2006/xbl2/#event-flow-and-targeting-across-shadow-s
+ if (event->isMutationEvent())
+ return StayInsideShadowDOM;
+
+ // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
+ // Changing this breaks existing sites.
+ // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
+ if (event->type() == eventNames().selectstartEvent)
+ return StayInsideShadowDOM;
+
+ return RetargetEvent;
+}
+
+}
+
diff --git a/Source/WebCore/dom/EventDispatcher.h b/Source/WebCore/dom/EventDispatcher.h
new file mode 100644
index 0000000..d43127f
--- /dev/null
+++ b/Source/WebCore/dom/EventDispatcher.h
@@ -0,0 +1,78 @@
+/*
+ * 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, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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 EventDispatcher_h
+#define EventDispatcher_h
+
+#include <wtf/Forward.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Event;
+class EventContext;
+class EventTarget;
+class FrameView;
+class Node;
+class PlatformKeyboardEvent;
+class PlatformMouseEvent;
+class PlatformWheelEvent;
+
+enum EventDispatchBehavior {
+ RetargetEvent,
+ StayInsideShadowDOM
+};
+
+class EventDispatcher {
+public:
+ static bool dispatchEvent(Node*, PassRefPtr<Event>);
+ static void dispatchScopedEvent(Node*, PassRefPtr<Event>);
+
+ static bool dispatchMouseEvent(Node*, const PlatformMouseEvent&, const AtomicString& eventType, int clickCount = 0, Node* relatedTarget = 0);
+ static void dispatchSimulatedClick(Node*, PassRefPtr<Event> underlyingEvent, bool sendMouseEvents, bool showPressedLook);
+ static void dispatchWheelEvent(Node*, PlatformWheelEvent&);
+
+ bool dispatchEvent(PassRefPtr<Event>);
+private:
+ EventDispatcher(Node*);
+
+ EventDispatchBehavior determineDispatchBehavior(Event*);
+ void getEventAncestors(EventTarget* originalTarget, EventDispatchBehavior);
+ const EventContext* topEventContext();
+ bool ancestorsInitialized() const;
+
+ bool dispatchMouseEvent(const AtomicString& eventType, int button, int detail,
+ int pageX, int pageY, int screenX, int screenY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
+ bool isSimulated, Node* relatedTargetArg, PassRefPtr<Event> underlyingEvent);
+
+ Vector<EventContext> m_ancestors;
+ RefPtr<Node> m_node;
+ RefPtr<EventTarget> m_originalTarget;
+ RefPtr<FrameView> m_view;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/dom/ExceptionCode.h b/Source/WebCore/dom/ExceptionCode.h
index dd976c7..881c3a3 100644
--- a/Source/WebCore/dom/ExceptionCode.h
+++ b/Source/WebCore/dom/ExceptionCode.h
@@ -57,13 +57,13 @@ namespace WebCore {
NETWORK_ERR = 19,
ABORT_ERR = 20,
URL_MISMATCH_ERR = 21,
- QUOTA_EXCEEDED_ERR = 22,
+ QUOTA_EXCEEDED_ERR = 22
// Introduced in File API:
// http://www.w3.org/TR/file-upload/#dfn-fileerror
#if ENABLE(BLOB) || ENABLE(FILE_SYSTEM)
- NOT_READABLE_ERR = 24,
- ENCODING_ERR = 26,
+ , NOT_READABLE_ERR = 24
+ , ENCODING_ERR = 26
#endif
};
diff --git a/Source/WebCore/dom/InputElement.cpp b/Source/WebCore/dom/InputElement.cpp
index b60fd44..b467df3 100644
--- a/Source/WebCore/dom/InputElement.cpp
+++ b/Source/WebCore/dom/InputElement.cpp
@@ -38,22 +38,13 @@
#include "Event.h"
#include "EventNames.h"
#include "Frame.h"
-#include "HTMLInputElement.h"
-#include "HTMLNames.h"
#include "Page.h"
#include "RenderTextControlSingleLine.h"
#include "SelectionController.h"
#include "TextIterator.h"
-#if ENABLE(WML)
-#include "WMLInputElement.h"
-#include "WMLNames.h"
-#endif
-
namespace WebCore {
-using namespace HTMLNames;
-
// FIXME: According to HTML4, the length attribute's value can be arbitrarily
// 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
@@ -287,19 +278,6 @@ const AtomicString& InputElementData::name() const
return m_name.isNull() ? emptyAtom : m_name;
}
-InputElement* toInputElement(Element* element)
-{
- if (element->isHTMLElement() && (element->hasTagName(inputTag) || element->hasTagName(isindexTag)))
- return static_cast<HTMLInputElement*>(element);
-
-#if ENABLE(WML)
- if (element->isWMLElement() && element->hasTagName(WMLNames::inputTag))
- return static_cast<WMLInputElement*>(element);
-#endif
-
- return 0;
-}
-
#if ENABLE(WCSS)
static inline const AtomicString& formatCodes()
{
diff --git a/Source/WebCore/dom/InputElement.h b/Source/WebCore/dom/InputElement.h
index 838adf5..26bf58d 100644
--- a/Source/WebCore/dom/InputElement.h
+++ b/Source/WebCore/dom/InputElement.h
@@ -160,8 +160,6 @@ private:
#endif
};
-InputElement* toInputElement(Element*);
-
}
#endif
diff --git a/Source/WebCore/dom/KeyboardEvent.cpp b/Source/WebCore/dom/KeyboardEvent.cpp
index 7b0f3af..109135d 100644
--- a/Source/WebCore/dom/KeyboardEvent.cpp
+++ b/Source/WebCore/dom/KeyboardEvent.cpp
@@ -25,6 +25,7 @@
#include "Document.h"
#include "DOMWindow.h"
+#include "EventDispatcher.h"
#include "EventNames.h"
#include "EventHandler.h"
#include "Frame.h"
@@ -160,4 +161,10 @@ KeyboardEvent* findKeyboardEvent(Event* event)
return 0;
}
+bool KeyboardEvent::dispatch(EventDispatcher* dispatcher)
+{
+ // Make sure not to return true if we already took default action while handling the event.
+ return dispatcher->dispatchEvent(this) && !defaultHandled();
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/dom/KeyboardEvent.h b/Source/WebCore/dom/KeyboardEvent.h
index eeaef80..ebdb9c8 100644
--- a/Source/WebCore/dom/KeyboardEvent.h
+++ b/Source/WebCore/dom/KeyboardEvent.h
@@ -29,6 +29,8 @@
namespace WebCore {
+ class EventDispatcher;
+ class Node;
class PlatformKeyboardEvent;
#if PLATFORM(MAC)
@@ -99,6 +101,7 @@ namespace WebCore {
KeyboardEvent(const AtomicString& type, bool canBubble, bool cancelable, AbstractView*,
const String& keyIdentifier, unsigned keyLocation,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool altGraphKey);
+ virtual bool dispatch(EventDispatcher*);
OwnPtr<PlatformKeyboardEvent> m_keyEvent;
String m_keyIdentifier;
diff --git a/Source/WebCore/dom/MouseEvent.cpp b/Source/WebCore/dom/MouseEvent.cpp
index bdd39d3..0acbd74 100644
--- a/Source/WebCore/dom/MouseEvent.cpp
+++ b/Source/WebCore/dom/MouseEvent.cpp
@@ -23,10 +23,23 @@
#include "config.h"
#include "MouseEvent.h"
+#include "Frame.h"
+#include "FrameView.h"
#include "EventNames.h"
+#include "PlatformMouseEvent.h"
namespace WebCore {
+PassRefPtr<MouseEvent> MouseEvent::create(const AtomicString& eventType, PassRefPtr<AbstractView> view, const PlatformMouseEvent& event, const IntPoint& position, int detail, PassRefPtr<Node> relatedTarget)
+{
+ bool isCancelable = eventType != eventNames().mousemoveEvent;
+
+ return MouseEvent::create(eventType, true, isCancelable, view,
+ detail, event.globalX(), event.globalY(), position.x(), position.y(),
+ event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), event.button(),
+ relatedTarget, 0, false);
+}
+
MouseEvent::MouseEvent()
: m_button(0)
, m_buttonDown(false)
@@ -115,4 +128,25 @@ Node* MouseEvent::fromElement() const
return target() ? target()->toNode() : 0;
}
+PassRefPtr<SimulatedMouseEvent> SimulatedMouseEvent::create(const AtomicString& eventType, PassRefPtr<AbstractView> view, PassRefPtr<Event> underlyingEvent)
+{
+ return adoptRef(new SimulatedMouseEvent(eventType, view, underlyingEvent));
+}
+
+SimulatedMouseEvent::~SimulatedMouseEvent()
+{
+}
+
+SimulatedMouseEvent::SimulatedMouseEvent(const AtomicString& eventType, PassRefPtr<AbstractView> view, PassRefPtr<Event> underlyingEvent)
+ : MouseEvent(eventType, true, true, view, 0, 0, 0, 0, 0, false, false, false, false, 0, 0, 0, true)
+{
+ if (UIEventWithKeyState* keyStateEvent = findEventWithKeyState(underlyingEvent.get())) {
+ m_ctrlKey = keyStateEvent->ctrlKey();
+ m_altKey = keyStateEvent->altKey();
+ m_shiftKey = keyStateEvent->shiftKey();
+ m_metaKey = keyStateEvent->metaKey();
+ }
+ setUnderlyingEvent(underlyingEvent);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/dom/MouseEvent.h b/Source/WebCore/dom/MouseEvent.h
index 7454b04..06e6218 100644
--- a/Source/WebCore/dom/MouseEvent.h
+++ b/Source/WebCore/dom/MouseEvent.h
@@ -29,6 +29,8 @@
namespace WebCore {
+class PlatformMouseEvent;
+
// Introduced in DOM Level 2
class MouseEvent : public MouseRelatedEvent {
public:
@@ -44,6 +46,8 @@ namespace WebCore {
return adoptRef(new MouseEvent(type, canBubble, cancelable, view, detail, screenX, screenY, pageX, pageY,
ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget, clipboard, isSimulated));
}
+ static PassRefPtr<MouseEvent> create(const AtomicString& eventType, PassRefPtr<AbstractView>, const PlatformMouseEvent&, const IntPoint&, int detail, PassRefPtr<Node> relatedTarget);
+
virtual ~MouseEvent();
void initMouseEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>,
@@ -68,19 +72,30 @@ namespace WebCore {
virtual bool isDragEvent() const;
virtual int which() const;
- private:
- MouseEvent();
+ protected:
MouseEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>,
int detail, int screenX, int screenY, int pageX, int pageY,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, unsigned short button,
PassRefPtr<EventTarget> relatedTarget, PassRefPtr<Clipboard> clipboard, bool isSimulated);
+ private:
+ MouseEvent();
+
unsigned short m_button;
bool m_buttonDown;
RefPtr<EventTarget> m_relatedTarget;
RefPtr<Clipboard> m_clipboard;
};
+class SimulatedMouseEvent : public MouseEvent {
+public:
+ static PassRefPtr<SimulatedMouseEvent> create(const AtomicString& eventType, PassRefPtr<AbstractView>, PassRefPtr<Event> underlyingEvent);
+ virtual ~SimulatedMouseEvent();
+
+private:
+ SimulatedMouseEvent(const AtomicString& eventType, PassRefPtr<AbstractView>, PassRefPtr<Event> underlyingEvent);
+};
+
} // namespace WebCore
#endif // MouseEvent_h
diff --git a/Source/WebCore/dom/MouseRelatedEvent.cpp b/Source/WebCore/dom/MouseRelatedEvent.cpp
index 072656e..f752670 100644
--- a/Source/WebCore/dom/MouseRelatedEvent.cpp
+++ b/Source/WebCore/dom/MouseRelatedEvent.cpp
@@ -44,6 +44,7 @@ MouseRelatedEvent::MouseRelatedEvent()
, m_offsetX(0)
, m_offsetY(0)
, m_isSimulated(false)
+ , m_hasCachedRelativePosition(false)
{
}
@@ -91,21 +92,20 @@ MouseRelatedEvent::MouseRelatedEvent(const AtomicString& eventType, bool canBubb
void MouseRelatedEvent::initCoordinates()
{
// Set up initial values for coordinates.
- // Correct values can't be computed until we have at target, so receivedTarget
- // does the "real" computation.
+ // Correct values are computed lazily, see computeRelativePosition.
m_layerX = m_pageX;
m_layerY = m_pageY;
m_offsetX = m_pageX;
m_offsetY = m_pageY;
computePageLocation();
+ m_hasCachedRelativePosition = false;
}
void MouseRelatedEvent::initCoordinates(int clientX, int clientY)
{
// Set up initial values for coordinates.
- // Correct values can't be computed until we have at target, so receivedTarget
- // does the "real" computation.
+ // Correct values are computed lazily, see computeRelativePosition.
m_clientX = clientX;
m_clientY = clientY;
m_pageX = clientX + contentsX(view());
@@ -116,9 +116,10 @@ void MouseRelatedEvent::initCoordinates(int clientX, int clientY)
m_offsetY = m_pageY;
computePageLocation();
+ m_hasCachedRelativePosition = false;
}
-static float pageZoomFactor(UIEvent* event)
+static float pageZoomFactor(const UIEvent* event)
{
DOMWindow* window = event->view();
if (!window)
@@ -137,9 +138,13 @@ void MouseRelatedEvent::computePageLocation()
void MouseRelatedEvent::receivedTarget()
{
- ASSERT(target());
- Node* targ = target()->toNode();
- if (!targ)
+ m_hasCachedRelativePosition = false;
+}
+
+void MouseRelatedEvent::computeRelativePosition()
+{
+ Node* targetNode = target() ? target()->toNode() : 0;
+ if (!targetNode)
return;
// Compute coordinates that are based on the target.
@@ -149,11 +154,11 @@ void MouseRelatedEvent::receivedTarget()
m_offsetY = m_pageY;
// Must have an updated render tree for this math to work correctly.
- targ->document()->updateStyleIfNeeded();
+ targetNode->document()->updateStyleIfNeeded();
// Adjust offsetX/Y to be relative to the target's position.
if (!isSimulated()) {
- if (RenderObject* r = targ->renderer()) {
+ if (RenderObject* r = targetNode->renderer()) {
FloatPoint localPos = r->absoluteToLocal(absoluteLocation(), false, true);
float zoomFactor = pageZoomFactor(this);
m_offsetX = lroundf(localPos.x() / zoomFactor);
@@ -166,17 +171,48 @@ void MouseRelatedEvent::receivedTarget()
// Our RenderLayer is a more modern concept, and layerX/Y is some
// other notion about groups of elements (left over from the Netscape 4 days?);
// we should test and fix this.
- Node* n = targ;
+ Node* n = targetNode;
while (n && !n->renderer())
n = n->parentNode();
- if (n) {
- RenderLayer* layer = n->renderer()->enclosingLayer();
+
+ RenderLayer* layer;
+ if (n && (layer = n->renderer()->enclosingLayer())) {
layer->updateLayerPosition();
for (; layer; layer = layer->parent()) {
m_layerX -= layer->x();
m_layerY -= layer->y();
}
}
+
+ m_hasCachedRelativePosition = true;
+}
+
+int MouseRelatedEvent::layerX()
+{
+ if (!m_hasCachedRelativePosition)
+ computeRelativePosition();
+ return m_layerX;
+}
+
+int MouseRelatedEvent::layerY()
+{
+ if (!m_hasCachedRelativePosition)
+ computeRelativePosition();
+ return m_layerY;
+}
+
+int MouseRelatedEvent::offsetX()
+{
+ if (!m_hasCachedRelativePosition)
+ computeRelativePosition();
+ return m_offsetX;
+}
+
+int MouseRelatedEvent::offsetY()
+{
+ if (!m_hasCachedRelativePosition)
+ computeRelativePosition();
+ return m_offsetY;
}
int MouseRelatedEvent::pageX() const
diff --git a/Source/WebCore/dom/MouseRelatedEvent.h b/Source/WebCore/dom/MouseRelatedEvent.h
index fc494d1..b03b28a 100644
--- a/Source/WebCore/dom/MouseRelatedEvent.h
+++ b/Source/WebCore/dom/MouseRelatedEvent.h
@@ -38,10 +38,10 @@ namespace WebCore {
int screenY() const { return m_screenY; }
int clientX() const { return m_clientX; }
int clientY() const { return m_clientY; }
- int layerX() const { return m_layerX; }
- int layerY() const { return m_layerY; }
- int offsetX() const { return m_offsetX; }
- int offsetY() const { return m_offsetY; }
+ int layerX();
+ int layerY();
+ int offsetX();
+ int offsetY();
bool isSimulated() const { return m_isSimulated; }
virtual int pageX() const;
virtual int pageY() const;
@@ -64,6 +64,7 @@ namespace WebCore {
virtual void receivedTarget();
void computePageLocation();
+ void computeRelativePosition();
// Expose these so MouseEvent::initMouseEvent can set them.
int m_screenX;
@@ -80,6 +81,7 @@ namespace WebCore {
int m_offsetY;
IntPoint m_absoluteLocation;
bool m_isSimulated;
+ bool m_hasCachedRelativePosition;
};
} // namespace WebCore
diff --git a/Source/WebCore/dom/NamedNodeMap.cpp b/Source/WebCore/dom/NamedNodeMap.cpp
index 2861226..6fa30bf 100644
--- a/Source/WebCore/dom/NamedNodeMap.cpp
+++ b/Source/WebCore/dom/NamedNodeMap.cpp
@@ -100,12 +100,6 @@ PassRefPtr<Node> NamedNodeMap::setNamedItem(Node* arg, ExceptionCode& ec)
return 0;
}
- // WRONG_DOCUMENT_ERR: Raised if arg was created from a different document than the one that created this map.
- if (arg->document() != m_element->document()) {
- ec = WRONG_DOCUMENT_ERR;
- return 0;
- }
-
// Not mentioned in spec: throw a HIERARCHY_REQUEST_ERROR if the user passes in a non-attribute node
if (!arg->isAttributeNode()) {
ec = HIERARCHY_REQUEST_ERR;
diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp
index c125d16..4def034 100644
--- a/Source/WebCore/dom/Node.cpp
+++ b/Source/WebCore/dom/Node.cpp
@@ -51,6 +51,7 @@
#include "Element.h"
#include "Event.h"
#include "EventContext.h"
+#include "EventDispatcher.h"
#include "EventException.h"
#include "EventHandler.h"
#include "EventListener.h"
@@ -106,10 +107,13 @@
#if ENABLE(SVG)
#include "SVGElementInstance.h"
-#include "SVGNames.h"
#include "SVGUseElement.h"
#endif
+#if ENABLE(WML)
+#include "WMLNames.h"
+#endif
+
#if ENABLE(XHTMLMP)
#include "HTMLNoScriptElement.h"
#endif
@@ -126,8 +130,6 @@ namespace WebCore {
using namespace HTMLNames;
-static HashSet<Node*>* gNodesDispatchingSimulatedClicks = 0;
-
bool Node::isSupported(const String& feature, const String& version)
{
return DOMImplementation::hasFeature(feature, version);
@@ -347,6 +349,12 @@ Node::StyleChange Node::diff(const RenderStyle* s1, const RenderStyle* s2)
}
}
+ // When text-combine property has been changed, we need to prepare a separate renderer object.
+ // When text-combine is on, we use RenderCombineText, otherwise RenderText.
+ // https://bugs.webkit.org/show_bug.cgi?id=55069
+ if ((s1 && s2) && (s1->hasTextCombine() != s2->hasTextCombine()))
+ ch = Detach;
+
return ch;
}
@@ -506,6 +514,18 @@ void Node::setShadowHost(Element* host)
setParent(host);
}
+InputElement* Node::toInputElement()
+{
+ // If one of the below ASSERTs trigger, you are calling this function
+ // directly or indirectly from a constructor or destructor of this object.
+ // Don't do this!
+ ASSERT(!(isHTMLElement() && hasTagName(inputTag)));
+#if ENABLE(WML)
+ ASSERT(!(isWMLElement() && hasTagName(WMLNames::inputTag)));
+#endif
+ return 0;
+}
+
short Node::tabIndex() const
{
return hasRareData() ? rareData()->tabIndex() : 0;
@@ -694,19 +714,36 @@ void Node::deprecatedParserAddChild(PassRefPtr<Node>)
{
}
-bool Node::isContentEditable() const
+bool Node::rendererIsEditable(EditableLevel editableLevel) const
{
- return parentOrHostNode() && parentOrHostNode()->isContentEditable();
-}
+ if (document()->inDesignMode() || (document()->frame() && document()->frame()->page() && document()->frame()->page()->isEditable()))
+ return true;
-bool Node::isContentRichlyEditable() const
-{
- return parentOrHostNode() && parentOrHostNode()->isContentRichlyEditable();
+ // Ideally we'd call ASSERT(!needsStyleRecalc()) here, but
+ // ContainerNode::setFocus() calls setNeedsStyleRecalc(), so the assertion
+ // would fire in the middle of Document::setFocusedNode().
+
+ for (const Node* node = this; node; node = node->parentNode()) {
+ if ((node->isHTMLElement() || node->isDocumentNode()) && node->renderer()) {
+ switch (node->renderer()->style()->userModify()) {
+ case READ_ONLY:
+ return false;
+ case READ_WRITE:
+ return true;
+ case READ_WRITE_PLAINTEXT_ONLY:
+ return editableLevel != RichlyEditable;
+ }
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+ }
+
+ return false;
}
bool Node::shouldUseInputMethod() const
{
- return isContentEditable();
+ return rendererIsEditable();
}
RenderBox* Node::renderBox() const
@@ -764,10 +801,16 @@ bool Node::hasNonEmptyBoundingBox() const
void Node::setDocumentRecursively(Document* document)
{
- // FIXME: To match Gecko, we should do this for nodes that are already in the document as well.
- if (this->document() == document || this->inDocument())
+ if (this->document() == document)
return;
+ // If an element is moved from a document and then eventually back again the collection cache for
+ // that element may contain stale data as changes made to it will have updated the DOMTreeVersion
+ // of the document it was moved to. By increasing the DOMTreeVersion of the donating document here
+ // we ensure that the collection cache will be invalidated as needed when the element is moved back.
+ if (this->document())
+ this->document()->incDOMTreeVersion();
+
for (Node* node = this; node; node = node->traverseNextNode(this)) {
node->setDocument(document);
if (!node->isElementNode())
@@ -1147,37 +1190,25 @@ bool Node::canReplaceChild(Node* newChild, Node*)
static void checkAcceptChild(Node* newParent, Node* newChild, ExceptionCode& ec)
{
- // Perform error checking as required by spec for adding a new child. Used by replaceChild().
-
// Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
if (!newChild) {
ec = NOT_FOUND_ERR;
return;
}
- // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
if (newParent->isReadOnlyNode()) {
ec = NO_MODIFICATION_ALLOWED_ERR;
return;
}
-
- // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
- // created this node.
- // We assume that if newChild is a DocumentFragment, all children are created from the same document
- // as the fragment itself (otherwise they could not have been added as children)
- if (newChild->document() != newParent->document() && newChild->inDocument()) {
- // but if the child is not in a document yet then loosen the
- // restriction, so that e.g. creating an element with the Option()
- // constructor and then adding it to a different document works,
- // as it does in Mozilla and Mac IE.
- ec = WRONG_DOCUMENT_ERR;
+
+ if (newChild->inDocument() && newChild->nodeType() == Node::DOCUMENT_TYPE_NODE) {
+ ec = HIERARCHY_REQUEST_ERR;
return;
}
-
+
// HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
// newChild node, or if the node to append is one of this node's ancestors.
- // check for ancestor/same node
if (newChild == newParent || newParent->isDescendantOf(newChild)) {
ec = HIERARCHY_REQUEST_ERR;
return;
@@ -1186,6 +1217,11 @@ static void checkAcceptChild(Node* newParent, Node* newChild, ExceptionCode& ec)
void Node::checkReplaceChild(Node* newChild, Node* oldChild, ExceptionCode& ec)
{
+ if (!oldChild) {
+ ec = NOT_FOUND_ERR;
+ return;
+ }
+
checkAcceptChild(this, newChild, ec);
if (ec)
return;
@@ -1481,7 +1517,7 @@ int Node::maxCharacterOffset() const
// is obviously misplaced.
bool Node::canStartSelection() const
{
- if (isContentEditable())
+ if (rendererIsEditable())
return true;
if (renderer()) {
@@ -1559,7 +1595,7 @@ Element *Node::enclosingBlockFlowElement() const
Element* Node::rootEditableElement() const
{
Element* result = 0;
- for (Node* n = const_cast<Node*>(this); n && n->isContentEditable(); n = n->parentNode()) {
+ for (Node* n = const_cast<Node*>(this); n && n->rendererIsEditable(); n = n->parentNode()) {
if (n->isElementNode())
result = static_cast<Element*>(n);
if (n->hasTagName(bodyTag))
@@ -2638,200 +2674,14 @@ void Node::handleLocalEvents(Event* event)
fireEventListeners(event);
}
-static inline EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode)
-{
- ASSERT(referenceNode);
-
-#if ENABLE(SVG)
- if (!referenceNode->isSVGElement())
- return referenceNode;
-
- // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
- // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
- for (Node* n = referenceNode; n; n = n->parentNode()) {
- if (!n->isShadowRoot() || !n->isSVGElement())
- continue;
-
- Element* shadowTreeParentElement = n->shadowHost();
- ASSERT(shadowTreeParentElement->hasTagName(SVGNames::useTag));
-
- if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode))
- return instance;
- }
-#endif
-
- return referenceNode;
-}
-
-void Node::getEventAncestors(Vector<EventContext>& ancestors, EventTarget* originalTarget, EventDispatchBehavior behavior)
-{
- if (!inDocument())
- return;
-
- EventTarget* target = originalTarget;
- Node* ancestor = this;
- bool shouldSkipNextAncestor = false;
- while (true) {
- if (ancestor->isShadowRoot()) {
- if (behavior == StayInsideShadowDOM)
- return;
- ancestor = ancestor->shadowHost();
- if (!shouldSkipNextAncestor)
- target = ancestor;
- } else
- ancestor = ancestor->parentNodeGuaranteedHostFree();
-
- if (!ancestor)
- return;
-
-#if ENABLE(SVG)
- // Skip SVGShadowTreeRootElement.
- shouldSkipNextAncestor = ancestor->isSVGElement() && ancestor->isShadowRoot();
- if (shouldSkipNextAncestor)
- continue;
-#endif
- // FIXME: Unroll the extra loop inside eventTargetRespectingSVGTargetRules into this loop.
- ancestors.append(EventContext(ancestor, eventTargetRespectingSVGTargetRules(ancestor), target));
-
- }
-}
-
-bool Node::dispatchEvent(PassRefPtr<Event> prpEvent)
-{
- RefPtr<EventTarget> protect = this;
- RefPtr<Event> event = prpEvent;
-
- event->setTarget(eventTargetRespectingSVGTargetRules(this));
-
- RefPtr<FrameView> view = document()->view();
- return dispatchGenericEvent(event.release());
-}
-
void Node::dispatchScopedEvent(PassRefPtr<Event> event)
{
- // We need to set the target here because it can go away by the time we actually fire the event.
- event->setTarget(eventTargetRespectingSVGTargetRules(this));
-
- ScopedEventQueue::instance()->enqueueEvent(event);
-}
-
-static const EventContext* topEventContext(const Vector<EventContext>& ancestors)
-{
- return ancestors.isEmpty() ? 0 : &ancestors.last();
+ EventDispatcher::dispatchScopedEvent(this, event);
}
-static EventDispatchBehavior determineDispatchBehavior(Event* event)
+bool Node::dispatchEvent(PassRefPtr<Event> event)
{
- // Per XBL 2.0 spec, mutation events should never cross shadow DOM boundary:
- // http://dev.w3.org/2006/xbl2/#event-flow-and-targeting-across-shadow-s
- if (event->isMutationEvent())
- return StayInsideShadowDOM;
-
- // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
- // Changing this breaks existing sites.
- // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
- if (event->type() == eventNames().selectstartEvent)
- return StayInsideShadowDOM;
-
- return RetargetEvent;
-}
-
-bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent)
-{
- RefPtr<Event> event(prpEvent);
-
- ASSERT(!eventDispatchForbidden());
- ASSERT(event->target());
- ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.
-
- // 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);
- RefPtr<EventTarget> originalTarget = event->target();
- Vector<EventContext> ancestors;
- getEventAncestors(ancestors, originalTarget.get(), determineDispatchBehavior(event.get()));
-
- WindowEventContext windowContext(event.get(), this, topEventContext(ancestors));
-
- InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(document(), *event, windowContext.window(), this, ancestors);
-
- // Give the target node a chance to do some work before DOM event handlers get a crack.
- void* data = preDispatchEventHandler(event.get());
- if (event->propagationStopped())
- goto doneDispatching;
-
- // Trigger capturing event handlers, starting at the top and working our way down.
- event->setEventPhase(Event::CAPTURING_PHASE);
-
- if (windowContext.handleLocalEvents(event.get()) && event->propagationStopped())
- goto doneDispatching;
-
- for (size_t i = ancestors.size(); i; --i) {
- ancestors[i - 1].handleLocalEvents(event.get());
- if (event->propagationStopped())
- goto doneDispatching;
- }
-
- event->setEventPhase(Event::AT_TARGET);
- event->setTarget(originalTarget.get());
- event->setCurrentTarget(eventTargetRespectingSVGTargetRules(this));
- handleLocalEvents(event.get());
- if (event->propagationStopped())
- goto doneDispatching;
-
- if (event->bubbles() && !event->cancelBubble()) {
- // Trigger bubbling event handlers, starting at the bottom and working our way up.
- event->setEventPhase(Event::BUBBLING_PHASE);
-
- size_t size = ancestors.size();
- for (size_t i = 0; i < size; ++i) {
- ancestors[i].handleLocalEvents(event.get());
- if (event->propagationStopped() || event->cancelBubble())
- goto doneDispatching;
- }
- windowContext.handleLocalEvents(event.get());
- }
-
-doneDispatching:
- event->setTarget(originalTarget.get());
- event->setCurrentTarget(0);
- event->setEventPhase(0);
-
- // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
- postDispatchEventHandler(event.get(), data);
-
- // Call default event handlers. While the DOM does have a concept of preventing
- // default handling, the detail of which handlers are called is an internal
- // implementation detail and not part of the DOM.
- if (!event->defaultPrevented() && !event->defaultHandled()) {
- // Non-bubbling events call only one default event handler, the one for the target.
- defaultEventHandler(event.get());
- ASSERT(!event->defaultPrevented());
- if (event->defaultHandled())
- goto doneWithDefault;
- // For bubbling events, call default event handlers on the same targets in the
- // same order as the bubbling phase.
- if (event->bubbles()) {
- size_t size = ancestors.size();
- for (size_t i = 0; i < size; ++i) {
- ancestors[i].node()->defaultEventHandler(event.get());
- ASSERT(!event->defaultPrevented());
- if (event->defaultHandled())
- goto doneWithDefault;
- }
- }
- }
-
-doneWithDefault:
-
- // Ensure that after event dispatch, the event's target object is the
- // outermost shadow DOM boundary.
- event->setTarget(windowContext.target());
- event->setCurrentTarget(0);
- InspectorInstrumentation::didDispatchEvent(cookie);
-
- return !event->defaultPrevented();
+ return EventDispatcher::dispatchEvent(this, event);
}
void Node::dispatchSubtreeModifiedEvent()
@@ -2861,209 +2711,25 @@ void Node::dispatchUIEvent(const AtomicString& eventType, int detail, PassRefPtr
dispatchScopedEvent(event.release());
}
-bool Node::dispatchKeyEvent(const PlatformKeyboardEvent& key)
+bool Node::dispatchKeyEvent(const PlatformKeyboardEvent& event)
{
- RefPtr<KeyboardEvent> keyboardEvent = KeyboardEvent::create(key, document()->defaultView());
- 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
- // let it get handled by AppKit
- if (keyboardEvent->defaultHandled())
- r = false;
-
- return r;
+ return EventDispatcher::dispatchEvent(this, KeyboardEvent::create(event, document()->defaultView()));
}
bool Node::dispatchMouseEvent(const PlatformMouseEvent& event, const AtomicString& eventType,
int detail, Node* relatedTarget)
{
- ASSERT(!eventDispatchForbidden());
-
- IntPoint contentsPos;
- if (FrameView* view = document()->view())
- contentsPos = view->windowToContents(event.pos());
-
- short button = event.button();
-
- ASSERT(event.eventType() == MouseEventMoved || button != NoButton);
-
- return dispatchMouseEvent(eventType, button, detail,
- contentsPos.x(), contentsPos.y(), event.globalX(), event.globalY(),
- event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
- false, relatedTarget, 0);
-}
-
-void Node::dispatchSimulatedMouseEvent(const AtomicString& eventType,
- PassRefPtr<Event> underlyingEvent)
-{
- ASSERT(!eventDispatchForbidden());
-
- bool ctrlKey = false;
- bool altKey = false;
- bool shiftKey = false;
- bool metaKey = false;
- if (UIEventWithKeyState* keyStateEvent = findEventWithKeyState(underlyingEvent.get())) {
- ctrlKey = keyStateEvent->ctrlKey();
- altKey = keyStateEvent->altKey();
- shiftKey = keyStateEvent->shiftKey();
- metaKey = keyStateEvent->metaKey();
- }
-
- // Like Gecko, we just pass 0 for everything when we make a fake mouse event.
- // Internet Explorer instead gives the current mouse position and state.
- dispatchMouseEvent(eventType, 0, 0, 0, 0, 0, 0,
- ctrlKey, altKey, shiftKey, metaKey, true, 0, underlyingEvent);
+ return EventDispatcher::dispatchMouseEvent(this, event, eventType, detail, relatedTarget);
}
void Node::dispatchSimulatedClick(PassRefPtr<Event> event, bool sendMouseEvents, bool showPressedLook)
{
- if (!gNodesDispatchingSimulatedClicks)
- gNodesDispatchingSimulatedClicks = new HashSet<Node*>;
- else if (gNodesDispatchingSimulatedClicks->contains(this))
- return;
-
- gNodesDispatchingSimulatedClicks->add(this);
-
- // send mousedown and mouseup before the click, if requested
- if (sendMouseEvents)
- dispatchSimulatedMouseEvent(eventNames().mousedownEvent, event.get());
- setActive(true, showPressedLook);
- if (sendMouseEvents)
- dispatchSimulatedMouseEvent(eventNames().mouseupEvent, event.get());
- setActive(false);
-
- // always send click
- dispatchSimulatedMouseEvent(eventNames().clickEvent, event);
-
- gNodesDispatchingSimulatedClicks->remove(this);
-}
-
-// FIXME: Once https://bugs.webkit.org/show_bug.cgi?id=52963 lands, this should
-// be greatly improved. See https://bugs.webkit.org/show_bug.cgi?id=54025.
-static Node* pullOutOfShadow(Node* node)
-{
- Node* outermostShadowBoundary = node;
- for (Node* n = node; n; n = n->parentOrHostNode()) {
- if (n->isShadowRoot())
- outermostShadowBoundary = n->parentOrHostNode();
- }
- return outermostShadowBoundary;
-}
-
-bool Node::dispatchMouseEvent(const AtomicString& eventType, int button, int detail,
- int pageX, int pageY, int screenX, int screenY,
- bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
- bool isSimulated, Node* relatedTargetArg, PassRefPtr<Event> underlyingEvent)
-{
- ASSERT(!eventDispatchForbidden());
- if (disabled()) // Don't even send DOM events for disabled controls..
- return true;
-
- if (eventType.isEmpty())
- return false; // Shouldn't happen.
-
- // Dispatching the first event can easily result in this node being destroyed.
- // Since we dispatch up to three events here, we need to make sure we're referenced
- // so the pointer will be good for the two subsequent ones.
- RefPtr<Node> protect(this);
-
- bool cancelable = eventType != eventNames().mousemoveEvent;
-
- bool swallowEvent = false;
-
- // Attempting to dispatch with a non-EventTarget relatedTarget causes the relatedTarget to be silently ignored.
- RefPtr<Node> relatedTarget = pullOutOfShadow(relatedTargetArg);
-
- int adjustedPageX = pageX;
- int adjustedPageY = pageY;
- if (Frame* frame = document()->frame()) {
- float pageZoom = frame->pageZoomFactor();
- if (pageZoom != 1.0f) {
- // Adjust our pageX and pageY to account for the page zoom.
- adjustedPageX = lroundf(pageX / pageZoom);
- adjustedPageY = lroundf(pageY / pageZoom);
- }
- }
-
- RefPtr<MouseEvent> mouseEvent = MouseEvent::create(eventType,
- true, cancelable, document()->defaultView(),
- detail, screenX, screenY, adjustedPageX, adjustedPageY,
- ctrlKey, altKey, shiftKey, metaKey, button,
- relatedTarget, 0, isSimulated);
- mouseEvent->setUnderlyingEvent(underlyingEvent.get());
- mouseEvent->setAbsoluteLocation(IntPoint(pageX, pageY));
-
- dispatchEvent(mouseEvent);
- bool defaultHandled = mouseEvent->defaultHandled();
- bool defaultPrevented = mouseEvent->defaultPrevented();
- if (defaultHandled || defaultPrevented)
- swallowEvent = true;
-
- // Special case: If it's a double click event, we also send the dblclick event. This is not part
- // of the DOM specs, but is used for compatibility with the ondblclick="" attribute. This is treated
- // as a separate event in other DOM-compliant browsers like Firefox, and so we do the same.
- if (eventType == eventNames().clickEvent && detail == 2) {
- RefPtr<Event> doubleClickEvent = MouseEvent::create(eventNames().dblclickEvent,
- true, cancelable, document()->defaultView(),
- detail, screenX, screenY, adjustedPageX, adjustedPageY,
- ctrlKey, altKey, shiftKey, metaKey, button,
- relatedTarget, 0, isSimulated);
- doubleClickEvent->setUnderlyingEvent(underlyingEvent.get());
- if (defaultHandled)
- doubleClickEvent->setDefaultHandled();
- dispatchEvent(doubleClickEvent);
- if (doubleClickEvent->defaultHandled() || doubleClickEvent->defaultPrevented())
- swallowEvent = true;
- }
-
- return swallowEvent;
+ EventDispatcher::dispatchSimulatedClick(this, event, sendMouseEvents, showPressedLook);
}
void Node::dispatchWheelEvent(PlatformWheelEvent& e)
{
- ASSERT(!eventDispatchForbidden());
- if (e.deltaX() == 0 && e.deltaY() == 0)
- return;
-
- FrameView* view = document()->view();
- if (!view)
- return;
-
- IntPoint pos = view->windowToContents(e.pos());
-
- int adjustedPageX = pos.x();
- int adjustedPageY = pos.y();
- if (Frame* frame = document()->frame()) {
- float pageZoom = frame->pageZoomFactor();
- if (pageZoom != 1.0f) {
- // Adjust our pageX and pageY to account for the page zoom.
- adjustedPageX = lroundf(pos.x() / pageZoom);
- adjustedPageY = lroundf(pos.y() / pageZoom);
- }
- }
-
- WheelEvent::Granularity granularity;
- switch (e.granularity()) {
- case ScrollByPageWheelEvent:
- granularity = WheelEvent::Page;
- break;
- case ScrollByPixelWheelEvent:
- default:
- granularity = WheelEvent::Pixel;
- break;
- }
-
- RefPtr<WheelEvent> we = WheelEvent::create(e.wheelTicksX(), e.wheelTicksY(), e.deltaX(), e.deltaY(), granularity,
- document()->defaultView(), e.globalX(), e.globalY(), adjustedPageX, adjustedPageY,
- e.ctrlKey(), e.altKey(), e.shiftKey(), e.metaKey());
-
- we->setAbsoluteLocation(IntPoint(pos.x(), pos.y()));
-
- if (!dispatchEvent(we) || we->defaultHandled())
- e.accept();
-
- we.release();
+ EventDispatcher::dispatchWheelEvent(this, e);
}
void Node::dispatchFocusEvent()
diff --git a/Source/WebCore/dom/Node.h b/Source/WebCore/dom/Node.h
index 7ef7e80..31f6ae8 100644
--- a/Source/WebCore/dom/Node.h
+++ b/Source/WebCore/dom/Node.h
@@ -53,6 +53,7 @@ class EventContext;
class EventListener;
class FloatPoint;
class Frame;
+class InputElement;
class IntRect;
class KeyboardEvent;
class NSResolver;
@@ -86,11 +87,6 @@ enum StyleChangeType {
SyntheticStyleChange = 3 << nodeStyleChangeShift
};
-enum EventDispatchBehavior {
- RetargetEvent,
- StayInsideShadowDOM
-};
-
class Node : public EventTarget, public TreeShared<ContainerNode>, public ScriptWrappable {
friend class Document;
public:
@@ -224,9 +220,6 @@ public:
// Returns the enclosing event parent node (or self) that, when clicked, would trigger a navigation.
Node* enclosingLinkEventParentOrSelf();
- // Node ancestors when concerned about event flow.
- void getEventAncestors(Vector<EventContext>& ancestors, EventTarget*, EventDispatchBehavior = RetargetEvent);
-
bool isBlockFlow() const;
bool isBlockFlowOrBlockTable() const;
@@ -326,8 +319,12 @@ public:
virtual bool isKeyboardFocusable(KeyboardEvent*) const;
virtual bool isMouseFocusable() const;
- virtual bool isContentEditable() const;
- virtual bool isContentRichlyEditable() const;
+#if PLATFORM(MAC)
+ // Objective-C extensions
+ bool isContentEditable() const { return rendererIsEditable(Editable); }
+#endif
+ bool rendererIsEditable() const { return rendererIsEditable(Editable); }
+ bool rendererIsRichlyEditable() const { return rendererIsEditable(RichlyEditable); }
virtual bool shouldUseInputMethod() const;
virtual IntRect getRect() const;
IntRect renderRect(bool* isReplaced);
@@ -529,6 +526,8 @@ public:
virtual Node* toNode() { return this; }
+ virtual InputElement* toInputElement();
+
virtual ScriptExecutionContext* scriptExecutionContext() const;
virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
@@ -543,7 +542,6 @@ public:
bool dispatchEvent(PassRefPtr<Event>);
void dispatchScopedEvent(PassRefPtr<Event>);
- bool dispatchGenericEvent(PassRefPtr<Event>);
virtual void handleLocalEvents(Event*);
void dispatchSubtreeModifiedEvent();
@@ -551,11 +549,6 @@ public:
bool dispatchKeyEvent(const PlatformKeyboardEvent&);
void dispatchWheelEvent(PlatformWheelEvent&);
bool dispatchMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType, int clickCount = 0, Node* relatedTarget = 0);
- bool dispatchMouseEvent(const AtomicString& eventType, int button, int clickCount,
- int pageX, int pageY, int screenX, int screenY,
- bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
- bool isSimulated, Node* relatedTarget, PassRefPtr<Event> underlyingEvent);
- void dispatchSimulatedMouseEvent(const AtomicString& eventType, PassRefPtr<Event> underlyingEvent);
void dispatchSimulatedClick(PassRefPtr<Event> underlyingEvent, bool sendMouseEvents = false, bool showPressedLook = true);
virtual void dispatchFocusEvent();
@@ -668,6 +661,9 @@ private:
void markCachedNodeListsSlow(JSC::MarkStack&, JSC::JSGlobalData&);
#endif
+ enum EditableLevel { Editable, RichlyEditable };
+ bool rendererIsEditable(EditableLevel) const;
+
void setStyleChange(StyleChangeType);
// Used to share code between lazyAttach and setNeedsStyleRecalc.
diff --git a/Source/WebCore/dom/Position.cpp b/Source/WebCore/dom/Position.cpp
index 473610a..1b58a42 100644
--- a/Source/WebCore/dom/Position.cpp
+++ b/Source/WebCore/dom/Position.cpp
@@ -46,7 +46,7 @@ using namespace HTMLNames;
static Node* nextRenderedEditable(Node* node)
{
while ((node = node->nextLeafNode())) {
- if (!node->isContentEditable())
+ if (!node->rendererIsEditable())
continue;
RenderObject* renderer = node->renderer();
if (!renderer)
@@ -60,7 +60,7 @@ static Node* nextRenderedEditable(Node* node)
static Node* previousRenderedEditable(Node* node)
{
while ((node = node->previousLeafNode())) {
- if (!node->isContentEditable())
+ if (!node->rendererIsEditable())
continue;
RenderObject* renderer = node->renderer();
if (!renderer)
@@ -94,11 +94,13 @@ Position::Position(PassRefPtr<Node> anchorNode, int offset, AnchorType anchorTyp
, m_anchorType(anchorType)
, m_isLegacyEditingPosition(false)
{
+ ASSERT(!m_anchorNode || !editingIgnoresContent(m_anchorNode.get()));
ASSERT(anchorType == PositionIsOffsetInAnchor);
}
void Position::moveToPosition(PassRefPtr<Node> node, int offset)
{
+ ASSERT(!editingIgnoresContent(node.get()));
ASSERT(anchorType() == PositionIsOffsetInAnchor || m_isLegacyEditingPosition);
m_anchorNode = node;
m_offset = offset;
@@ -161,12 +163,12 @@ Position Position::parentAnchoredEquivalent() const
return Position();
// FIXME: This should only be necessary for legacy positions, but is also needed for positions before and after Tables
- if (m_offset <= 0) {
+ if (m_offset <= 0 && m_anchorType != PositionIsAfterAnchor) {
if (m_anchorNode->parentNode() && (editingIgnoresContent(m_anchorNode.get()) || isTableElement(m_anchorNode.get())))
return positionInParentBeforeNode(m_anchorNode.get());
- return Position(m_anchorNode, 0, PositionIsOffsetInAnchor);
+ return firstPositionInOrBeforeNode(m_anchorNode.get());
}
- if (!m_anchorNode->offsetInCharacters() && static_cast<unsigned>(m_offset) == m_anchorNode->childNodeCount()
+ if (!m_anchorNode->offsetInCharacters() && (m_anchorType == PositionIsAfterAnchor || static_cast<unsigned>(m_offset) == m_anchorNode->childNodeCount())
&& (editingIgnoresContent(m_anchorNode.get()) || isTableElement(m_anchorNode.get()))) {
return positionInParentAfterNode(m_anchorNode.get());
}
@@ -240,15 +242,15 @@ Position Position::previous(PositionMoveType moveType) const
Node* n = deprecatedNode();
if (!n)
return *this;
-
- int o = m_offset;
+
+ int o = deprecatedEditingOffset();
// FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.
ASSERT(o >= 0);
if (o > 0) {
Node* child = n->childNode(o - 1);
if (child)
- return lastDeepEditingPositionForNode(child);
+ return lastPositionInOrAfterNode(child);
// There are two reasons child might be 0:
// 1) The node is node like a text node that is not an element, and therefore has no children.
@@ -279,15 +281,15 @@ Position Position::next(PositionMoveType moveType) const
Node* n = deprecatedNode();
if (!n)
return *this;
-
- int o = m_offset;
+
+ int o = deprecatedEditingOffset();
// FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.
ASSERT(o >= 0);
Node* child = n->childNode(o);
if (child || (!n->hasChildNodes() && o < lastOffsetForEditing(n))) {
if (child)
- return firstDeepEditingPositionForNode(child);
+ return firstPositionInOrBeforeNode(child);
// There are two reasons child might be 0:
// 1) The node is node like a text node that is not an element, and therefore has no children.
@@ -323,14 +325,14 @@ bool Position::atFirstEditingPositionForNode() const
{
if (isNull())
return true;
- return m_offset <= 0;
+ return m_anchorType == PositionIsBeforeAnchor || m_offset <= 0;
}
bool Position::atLastEditingPositionForNode() const
{
if (isNull())
return true;
- return m_offset >= lastOffsetForEditing(deprecatedNode());
+ return m_anchorType == PositionIsAfterAnchor || m_offset >= lastOffsetForEditing(deprecatedNode());
}
// A position is considered at editing boundary if one of the following is true:
@@ -343,15 +345,15 @@ bool Position::atLastEditingPositionForNode() const
bool Position::atEditingBoundary() const
{
Position nextPosition = downstream(CanCrossEditingBoundary);
- if (atFirstEditingPositionForNode() && nextPosition.isNotNull() && !nextPosition.deprecatedNode()->isContentEditable())
+ if (atFirstEditingPositionForNode() && nextPosition.isNotNull() && !nextPosition.deprecatedNode()->rendererIsEditable())
return true;
Position prevPosition = upstream(CanCrossEditingBoundary);
- if (atLastEditingPositionForNode() && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->isContentEditable())
+ if (atLastEditingPositionForNode() && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->rendererIsEditable())
return true;
- return nextPosition.isNotNull() && !nextPosition.deprecatedNode()->isContentEditable()
- && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->isContentEditable();
+ return nextPosition.isNotNull() && !nextPosition.deprecatedNode()->rendererIsEditable()
+ && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->rendererIsEditable();
}
Node* Position::parentEditingBoundary() const
@@ -364,7 +366,7 @@ Node* Position::parentEditingBoundary() const
return 0;
Node* boundary = m_anchorNode.get();
- while (boundary != documentElement && boundary->parentNode() && m_anchorNode->isContentEditable() == boundary->parentNode()->isContentEditable())
+ while (boundary != documentElement && boundary->parentNode() && m_anchorNode->rendererIsEditable() == boundary->parentNode()->rendererIsEditable())
boundary = boundary->parentNode();
return boundary;
@@ -523,17 +525,17 @@ Position Position::upstream(EditingBoundaryCrossingRule rule) const
// FIXME: PositionIterator should respect Before and After positions.
PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? Position(m_anchorNode, caretMaxOffset(m_anchorNode.get())) : *this;
PositionIterator currentPos = lastVisible;
- bool startEditable = startNode->isContentEditable();
+ bool startEditable = startNode->rendererIsEditable();
Node* lastNode = startNode;
bool boundaryCrossed = false;
for (; !currentPos.atStart(); currentPos.decrement()) {
Node* currentNode = currentPos.node();
// Don't check for an editability change if we haven't moved to a different node,
- // to avoid the expense of computing isContentEditable().
+ // to avoid the expense of computing rendererIsEditable().
if (currentNode != lastNode) {
// Don't change editability.
- bool currentEditable = currentNode->isContentEditable();
+ bool currentEditable = currentNode->rendererIsEditable();
if (startEditable != currentEditable) {
if (rule == CannotCrossEditingBoundary)
break;
@@ -569,7 +571,7 @@ Position Position::upstream(EditingBoundaryCrossingRule rule) const
// Return position after tables and nodes which have content that can be ignored.
if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) {
if (currentPos.atEndOfNode())
- return lastDeepEditingPositionForNode(currentNode);
+ return positionAfterNode(currentNode);
continue;
}
@@ -645,17 +647,17 @@ Position Position::downstream(EditingBoundaryCrossingRule rule) const
// FIXME: PositionIterator should respect Before and After positions.
PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? Position(m_anchorNode, caretMaxOffset(m_anchorNode.get())) : *this;
PositionIterator currentPos = lastVisible;
- bool startEditable = startNode->isContentEditable();
+ bool startEditable = startNode->rendererIsEditable();
Node* lastNode = startNode;
bool boundaryCrossed = false;
for (; !currentPos.atEnd(); currentPos.increment()) {
Node* currentNode = currentPos.node();
// Don't check for an editability change if we haven't moved to a different node,
- // to avoid the expense of computing isContentEditable().
+ // to avoid the expense of computing rendererIsEditable().
if (currentNode != lastNode) {
// Don't change editability.
- bool currentEditable = currentNode->isContentEditable();
+ bool currentEditable = currentNode->rendererIsEditable();
if (startEditable != currentEditable) {
if (rule == CannotCrossEditingBoundary)
break;
@@ -781,7 +783,8 @@ bool Position::isCandidate() const
return false;
if (renderer->isBR())
- return !m_offset && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
+ // FIXME: The condition should be m_anchorType == PositionIsBeforeAnchor, but for now we still need to support legacy positions.
+ return !m_offset && m_anchorType != PositionIsAfterAnchor && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
if (renderer->isText())
return !nodeIsUserSelectNone(deprecatedNode()) && inRenderedText();
@@ -796,10 +799,10 @@ bool Position::isCandidate() const
if (toRenderBlock(renderer)->height() || m_anchorNode->hasTagName(bodyTag)) {
if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer))
return atFirstEditingPositionForNode() && !Position::nodeIsUserSelectNone(deprecatedNode());
- return m_anchorNode->isContentEditable() && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
+ return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
}
} else
- return m_anchorNode->isContentEditable() && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
+ return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
return false;
}
@@ -982,7 +985,7 @@ Position Position::trailingWhitespacePosition(EAffinity, bool considerNonCollaps
VisiblePosition v(*this);
UChar c = v.characterAfter();
// The space must not be in another paragraph and it must be editable.
- if (!isEndOfParagraph(v) && v.next(true).isNotNull())
+ if (!isEndOfParagraph(v) && v.next(CannotCrossEditingBoundary).isNotNull())
if (considerNonCollapsibleWhitespace ? (isSpaceOrNewline(c) || c == noBreakSpace) : isCollapsibleWhitespace(c))
return *this;
@@ -1053,7 +1056,7 @@ static Position upstreamIgnoringEditingBoundaries(Position position)
void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const
{
- caretOffset = m_offset;
+ caretOffset = deprecatedEditingOffset();
RenderObject* renderer = deprecatedNode()->renderer();
if (!renderer->isText()) {
diff --git a/Source/WebCore/dom/Position.h b/Source/WebCore/dom/Position.h
index 4e1eff4..a72664e 100644
--- a/Source/WebCore/dom/Position.h
+++ b/Source/WebCore/dom/Position.h
@@ -133,6 +133,7 @@ public:
// These can be either inside or just before/after the node, depending on
// if the node is ignored by editing or not.
+ // FIXME: These should go away. They only make sense for legacy positions.
bool atFirstEditingPositionForNode() const;
bool atLastEditingPositionForNode() const;
@@ -196,7 +197,7 @@ inline bool operator==(const Position& a, const Position& b)
{
// FIXME: In <div><img></div> [div, 0] != [img, 0] even though most of the
// editing code will treat them as identical.
- return a.anchorNode() == b.anchorNode() && a.deprecatedEditingOffset() == b.deprecatedEditingOffset();
+ return a.anchorNode() == b.anchorNode() && a.deprecatedEditingOffset() == b.deprecatedEditingOffset() && a.anchorType() == b.anchorType();
}
inline bool operator!=(const Position& a, const Position& b)
diff --git a/Source/WebCore/dom/PositionIterator.cpp b/Source/WebCore/dom/PositionIterator.cpp
index 5de9d9d..6821308 100644
--- a/Source/WebCore/dom/PositionIterator.cpp
+++ b/Source/WebCore/dom/PositionIterator.cpp
@@ -38,10 +38,13 @@ PositionIterator::operator Position() const
{
if (m_nodeAfterPositionInAnchor) {
ASSERT(m_nodeAfterPositionInAnchor->parentNode() == m_anchorNode);
+ // FIXME: This check is inadaquete because any ancestor could be ignored by editing
+ if (editingIgnoresContent(m_nodeAfterPositionInAnchor->parentNode()))
+ return positionBeforeNode(m_anchorNode);
return positionInParentBeforeNode(m_nodeAfterPositionInAnchor);
}
if (m_anchorNode->hasChildNodes())
- return lastDeepEditingPositionForNode(m_anchorNode);
+ return lastPositionInOrAfterNode(m_anchorNode);
return Position(m_anchorNode, m_offsetInAnchor);
}
@@ -166,7 +169,7 @@ bool PositionIterator::isCandidate() const
if (toRenderBlock(renderer)->height() || m_anchorNode->hasTagName(bodyTag)) {
if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer))
return atStartOfNode() && !Position::nodeIsUserSelectNone(m_anchorNode);
- return m_anchorNode->isContentEditable() && !Position::nodeIsUserSelectNone(m_anchorNode) && Position(*this).atEditingBoundary();
+ return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSelectNone(m_anchorNode) && Position(*this).atEditingBoundary();
}
}
diff --git a/Source/WebCore/dom/QualifiedName.h b/Source/WebCore/dom/QualifiedName.h
index cb95f20..192e7bc 100644
--- a/Source/WebCore/dom/QualifiedName.h
+++ b/Source/WebCore/dom/QualifiedName.h
@@ -113,7 +113,7 @@ inline bool operator!=(const QualifiedName& q, const AtomicString& a) { return a
inline unsigned hashComponents(const QualifiedNameComponents& buf)
{
- return WTF::StringHasher::createBlobHash<sizeof(QualifiedNameComponents)>(&buf);
+ return StringHasher::hashMemory<sizeof(QualifiedNameComponents)>(&buf);
}
struct QualifiedNameHash {
diff --git a/Source/WebCore/dom/Range.cpp b/Source/WebCore/dom/Range.cpp
index a0370fa..423d43f 100644
--- a/Source/WebCore/dom/Range.cpp
+++ b/Source/WebCore/dom/Range.cpp
@@ -932,13 +932,6 @@ void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionCode& ec)
return;
}
- // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were
- // not created from the same document.
- if (newNode->document() != m_start.container()->document()) {
- ec = WRONG_DOCUMENT_ERR;
- return;
- }
-
// HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that
// does not allow children of the type of newNode or if newNode is an ancestor of the container.
@@ -1423,13 +1416,6 @@ void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionCode& ec)
return;
}
- // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were
- // not created from the same document.
- if (newParent->document() != m_start.container()->document()) {
- ec = WRONG_DOCUMENT_ERR;
- return;
- }
-
// Raise a HIERARCHY_REQUEST_ERR if m_start.container() doesn't accept children like newParent.
Node* parentOfNewParent = m_start.container();
diff --git a/Source/WebCore/dom/ScriptElement.cpp b/Source/WebCore/dom/ScriptElement.cpp
index 3bba9a0..9a07bb8 100644
--- a/Source/WebCore/dom/ScriptElement.cpp
+++ b/Source/WebCore/dom/ScriptElement.cpp
@@ -24,9 +24,9 @@
#include "config.h"
#include "ScriptElement.h"
-#include "AsyncScriptRunner.h"
#include "CachedScript.h"
#include "CachedResourceLoader.h"
+#include "ContentSecurityPolicy.h"
#include "Document.h"
#include "DocumentParser.h"
#include "Frame.h"
@@ -37,6 +37,7 @@
#include "MIMETypeRegistry.h"
#include "Page.h"
#include "ScriptController.h"
+#include "ScriptRunner.h"
#include "ScriptSourceCode.h"
#include "ScriptValue.h"
#include "Settings.h"
@@ -61,6 +62,8 @@ ScriptElement::ScriptElement(Element* element, bool parserInserted, bool already
, m_willBeParserExecuted(false)
, m_readyToBeParserExecuted(false)
, m_willExecuteWhenDocumentFinishedParsing(false)
+ , m_forceAsync(!parserInserted)
+ , m_willExecuteInOrder(false)
{
ASSERT(m_element);
}
@@ -96,6 +99,11 @@ void ScriptElement::handleSourceAttribute(const String& sourceUrl)
prepareScript(); // FIXME: Provide a real starting line number here.
}
+void ScriptElement::handleAsyncAttribute()
+{
+ m_forceAsync = false;
+}
+
// Helper function
static bool isLegacySupportedJavaScriptLanguage(const String& language)
{
@@ -159,7 +167,8 @@ bool ScriptElement::prepareScript(const TextPosition1& scriptStartPosition, Lega
} else
wasParserInserted = false;
- // FIXME: HTML5 spec says we should set forceAsync.
+ if (wasParserInserted && !asyncAttributeValue())
+ m_forceAsync = true;
// FIXME: HTML5 spec says we should check that all children are either comments or empty text nodes.
if (!hasSourceAttribute() && !m_element->firstChild())
@@ -171,8 +180,10 @@ bool ScriptElement::prepareScript(const TextPosition1& scriptStartPosition, Lega
if (!isScriptTypeSupported(supportLegacyTypes))
return false;
- if (wasParserInserted)
+ if (wasParserInserted) {
m_parserInserted = true;
+ m_forceAsync = false;
+ }
m_alreadyStarted = true;
@@ -207,6 +218,10 @@ bool ScriptElement::prepareScript(const TextPosition1& scriptStartPosition, Lega
else if (!hasSourceAttribute() && m_parserInserted && !m_element->document()->haveStylesheetsLoaded()) {
m_willBeParserExecuted = true;
m_readyToBeParserExecuted = true;
+ } else if (hasSourceAttribute() && !asyncAttributeValue() && !m_forceAsync) {
+ m_willExecuteInOrder = true;
+ m_element->document()->scriptRunner()->queueScriptForExecution(this, m_cachedScript, ScriptRunner::IN_ORDER_EXECUTION);
+ m_cachedScript->addClient(this);
} else if (hasSourceAttribute())
m_cachedScript->addClient(this);
else
@@ -217,9 +232,6 @@ bool ScriptElement::prepareScript(const TextPosition1& scriptStartPosition, Lega
bool ScriptElement::requestScript(const String& sourceUrl)
{
- if (!m_element->document()->contentSecurityPolicy()->canLoadExternalScriptFromSrc(sourceUrl))
- return false;
-
RefPtr<Document> originalDocument = m_element->document();
if (!m_element->dispatchBeforeLoadEvent(sourceUrl))
return false;
@@ -286,7 +298,10 @@ void ScriptElement::notifyFinished(CachedResource* o)
{
ASSERT(!m_willBeParserExecuted);
ASSERT_UNUSED(o, o == m_cachedScript);
- m_element->document()->asyncScriptRunner()->executeScriptSoon(this, m_cachedScript);
+ if (m_willExecuteInOrder)
+ m_element->document()->scriptRunner()->notifyInOrderScriptReady();
+ else
+ m_element->document()->scriptRunner()->queueScriptForExecution(this, m_cachedScript, ScriptRunner::ASYNC_EXECUTION);
m_cachedScript = 0;
}
diff --git a/Source/WebCore/dom/ScriptElement.h b/Source/WebCore/dom/ScriptElement.h
index 79dff33..9ce66e5 100644
--- a/Source/WebCore/dom/ScriptElement.h
+++ b/Source/WebCore/dom/ScriptElement.h
@@ -63,12 +63,14 @@ protected:
void setHaveFiredLoadEvent(bool haveFiredLoad) { m_haveFiredLoad = haveFiredLoad; }
bool isParserInserted() const { return m_parserInserted; }
bool alreadyStarted() const { return m_alreadyStarted; }
+ bool forceAsync() const { return m_forceAsync; }
// Helper functions used by our parent classes.
void insertedIntoDocument();
void removedFromDocument();
void childrenChanged();
void handleSourceAttribute(const String& sourceUrl);
+ void handleAsyncAttribute();
private:
bool ignoresLoadRequest() const;
@@ -98,6 +100,8 @@ private:
bool m_willBeParserExecuted : 1; // Same as "The parser will handle executing the script."
bool m_readyToBeParserExecuted : 1;
bool m_willExecuteWhenDocumentFinishedParsing : 1;
+ bool m_forceAsync : 1;
+ bool m_willExecuteInOrder : 1;
String m_characterEncoding;
String m_fallbackCharacterEncoding;
};
diff --git a/Source/WebCore/dom/ScriptExecutionContext.cpp b/Source/WebCore/dom/ScriptExecutionContext.cpp
index 6685416..b9a1e92 100644
--- a/Source/WebCore/dom/ScriptExecutionContext.cpp
+++ b/Source/WebCore/dom/ScriptExecutionContext.cpp
@@ -382,6 +382,8 @@ KURL ScriptExecutionContext::createPublicBlobURL(Blob* blob)
if (!blob)
return KURL();
KURL publicURL = BlobURL::createPublicURL(securityOrigin());
+ if (publicURL.isEmpty())
+ return KURL();
ThreadableBlobRegistry::registerBlobURL(publicURL, blob->url());
m_publicBlobURLs.add(publicURL.string());
return publicURL;
diff --git a/Source/WebCore/dom/AsyncScriptRunner.cpp b/Source/WebCore/dom/ScriptRunner.cpp
index 28b1b31..10198bf 100644
--- a/Source/WebCore/dom/AsyncScriptRunner.cpp
+++ b/Source/WebCore/dom/ScriptRunner.cpp
@@ -24,7 +24,7 @@
*/
#include "config.h"
-#include "AsyncScriptRunner.h"
+#include "ScriptRunner.h"
#include "CachedScript.h"
#include "Document.h"
@@ -34,52 +34,79 @@
namespace WebCore {
-AsyncScriptRunner::AsyncScriptRunner(Document* document)
+ScriptRunner::ScriptRunner(Document* document)
: m_document(document)
- , m_timer(this, &AsyncScriptRunner::timerFired)
+ , m_timer(this, &ScriptRunner::timerFired)
{
ASSERT(document);
}
-AsyncScriptRunner::~AsyncScriptRunner()
+ScriptRunner::~ScriptRunner()
{
for (size_t i = 0; i < m_scriptsToExecuteSoon.size(); ++i)
m_document->decrementLoadEventDelayCount();
+ for (size_t i = 0; i < m_scriptsToExecuteInOrder.size(); ++i)
+ m_document->decrementLoadEventDelayCount();
}
-void AsyncScriptRunner::executeScriptSoon(ScriptElement* scriptElement, CachedResourceHandle<CachedScript> cachedScript)
+void ScriptRunner::queueScriptForExecution(ScriptElement* scriptElement, CachedResourceHandle<CachedScript> cachedScript, ExecutionType executionType)
{
- ASSERT_ARG(scriptElement, scriptElement);
+ ASSERT(scriptElement);
Element* element = scriptElement->element();
ASSERT(element);
ASSERT(element->inDocument());
m_document->incrementLoadEventDelayCount();
- m_scriptsToExecuteSoon.append(PendingScript(element, cachedScript.get()));
- if (!m_timer.isActive())
- m_timer.startOneShot(0);
+
+ switch (executionType) {
+ case ASYNC_EXECUTION:
+ m_scriptsToExecuteSoon.append(PendingScript(element, cachedScript.get()));
+ if (!m_timer.isActive())
+ m_timer.startOneShot(0);
+ break;
+
+ case IN_ORDER_EXECUTION:
+ m_scriptsToExecuteInOrder.append(PendingScript(element, cachedScript.get()));
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ }
}
-void AsyncScriptRunner::suspend()
+void ScriptRunner::suspend()
{
m_timer.stop();
}
-void AsyncScriptRunner::resume()
+void ScriptRunner::resume()
{
if (hasPendingScripts())
m_timer.startOneShot(0);
}
-void AsyncScriptRunner::timerFired(Timer<AsyncScriptRunner>* timer)
+void ScriptRunner::notifyInOrderScriptReady()
+{
+ ASSERT(!m_scriptsToExecuteInOrder.isEmpty());
+ m_timer.startOneShot(0);
+}
+
+void ScriptRunner::timerFired(Timer<ScriptRunner>* timer)
{
ASSERT_UNUSED(timer, timer == &m_timer);
RefPtr<Document> protect(m_document);
-
+
Vector<PendingScript> scripts;
scripts.swap(m_scriptsToExecuteSoon);
+
+ size_t numInOrderScriptsToExecute = 0;
+ for (; numInOrderScriptsToExecute < m_scriptsToExecuteInOrder.size() && m_scriptsToExecuteInOrder[numInOrderScriptsToExecute].cachedScript()->isLoaded(); ++numInOrderScriptsToExecute)
+ scripts.append(m_scriptsToExecuteInOrder[numInOrderScriptsToExecute]);
+ if (numInOrderScriptsToExecute)
+ m_scriptsToExecuteInOrder.remove(0, numInOrderScriptsToExecute);
+
size_t size = scripts.size();
for (size_t i = 0; i < size; ++i) {
CachedScript* cachedScript = scripts[i].cachedScript();
diff --git a/Source/WebCore/dom/AsyncScriptRunner.h b/Source/WebCore/dom/ScriptRunner.h
index 6a75323..d6d7411 100644
--- a/Source/WebCore/dom/AsyncScriptRunner.h
+++ b/Source/WebCore/dom/ScriptRunner.h
@@ -23,8 +23,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef AsyncScriptRunner_h
-#define AsyncScriptRunner_h
+#ifndef ScriptRunner_h
+#define ScriptRunner_h
#include "CachedResourceHandle.h"
#include "Timer.h"
@@ -38,26 +38,29 @@ class CachedScript;
class Document;
class PendingScript;
class ScriptElement;
-
-class AsyncScriptRunner {
- WTF_MAKE_NONCOPYABLE(AsyncScriptRunner); WTF_MAKE_FAST_ALLOCATED;
+
+class ScriptRunner {
+ WTF_MAKE_NONCOPYABLE(ScriptRunner); WTF_MAKE_FAST_ALLOCATED;
public:
- static PassOwnPtr<AsyncScriptRunner> create(Document* document) { return new AsyncScriptRunner(document); }
- ~AsyncScriptRunner();
+ static PassOwnPtr<ScriptRunner> create(Document* document) { return new ScriptRunner(document); }
+ ~ScriptRunner();
- void executeScriptSoon(ScriptElement*, CachedResourceHandle<CachedScript>);
- bool hasPendingScripts() const { return !m_scriptsToExecuteSoon.isEmpty(); }
+ enum ExecutionType { ASYNC_EXECUTION, IN_ORDER_EXECUTION };
+ void queueScriptForExecution(ScriptElement*, CachedResourceHandle<CachedScript>, ExecutionType);
+ bool hasPendingScripts() const { return !m_scriptsToExecuteSoon.isEmpty() || !m_scriptsToExecuteInOrder.isEmpty(); }
void suspend();
void resume();
+ void notifyInOrderScriptReady();
private:
- AsyncScriptRunner(Document*);
+ ScriptRunner(Document*);
- void timerFired(Timer<AsyncScriptRunner>*);
+ void timerFired(Timer<ScriptRunner>*);
Document* m_document;
+ Vector<PendingScript> m_scriptsToExecuteInOrder;
Vector<PendingScript> m_scriptsToExecuteSoon; // http://www.whatwg.org/specs/web-apps/current-work/#set-of-scripts-that-will-execute-as-soon-as-possible
- Timer<AsyncScriptRunner> m_timer;
+ Timer<ScriptRunner> m_timer;
};
}
diff --git a/Source/WebCore/dom/StringCallback.cpp b/Source/WebCore/dom/StringCallback.cpp
new file mode 100644
index 0000000..c6285b1
--- /dev/null
+++ b/Source/WebCore/dom/StringCallback.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StringCallback.h"
+
+#include "ScriptExecutionContext.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+namespace {
+
+class DispatchCallbackTask : public ScriptExecutionContext::Task {
+public:
+ static PassOwnPtr<DispatchCallbackTask> create(PassRefPtr<StringCallback> callback, const String& data)
+ {
+ return adoptPtr(new DispatchCallbackTask(callback, data));
+ }
+
+ virtual void performTask(ScriptExecutionContext*)
+ {
+ m_callback->handleEvent(m_data);
+ }
+
+private:
+ DispatchCallbackTask(PassRefPtr<StringCallback> callback, const String& data)
+ : m_callback(callback)
+ , m_data(data)
+ {
+ }
+
+ RefPtr<StringCallback> m_callback;
+ const String m_data;
+};
+
+} // namespace
+
+void StringCallback::scheduleCallback(ScriptExecutionContext* context, const String& data)
+{
+ context->postTask(DispatchCallbackTask::create(this, data));
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/dom/StringCallback.h b/Source/WebCore/dom/StringCallback.h
new file mode 100644
index 0000000..92e83e2
--- /dev/null
+++ b/Source/WebCore/dom/StringCallback.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StringCallback_h
+#define StringCallback_h
+
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class ScriptExecutionContext;
+
+class StringCallback : public RefCounted<StringCallback> {
+public:
+ virtual ~StringCallback() { }
+ virtual bool handleEvent(const String& data) = 0;
+
+ // Helper to post callback task.
+ void scheduleCallback(ScriptExecutionContext*, const String& data);
+};
+
+} // namespace WebCore
+
+#endif // StringCallback_h
diff --git a/Source/WebCore/dom/StringCallback.idl b/Source/WebCore/dom/StringCallback.idl
new file mode 100644
index 0000000..1e18d83
--- /dev/null
+++ b/Source/WebCore/dom/StringCallback.idl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module core {
+ interface [
+ Callback
+ ] StringCallback {
+ boolean handleEvent(in DOMString data);
+ };
+}
diff --git a/Source/WebCore/dom/StyleElement.cpp b/Source/WebCore/dom/StyleElement.cpp
index f984fda..e9d035d 100644
--- a/Source/WebCore/dom/StyleElement.cpp
+++ b/Source/WebCore/dom/StyleElement.cpp
@@ -103,8 +103,15 @@ void StyleElement::process(Element* e)
for (Node* c = e->firstChild(); c; c = c->nextSibling()) {
if (isValidStyleChild(c)) {
unsigned length = c->nodeValue().length();
+<<<<<<< HEAD
if (length > std::numeric_limits<unsigned>::max() - resultLength)
CRASH();
+=======
+ if (length > std::numeric_limits<unsigned>::max() - resultLength) {
+ createSheet(e, m_startLineNumber, "");
+ return;
+ }
+>>>>>>> webkit.org at r82507
resultLength += length;
}
}
diff --git a/Source/WebCore/dom/StyledElement.cpp b/Source/WebCore/dom/StyledElement.cpp
index d6a532f..3c55591 100644
--- a/Source/WebCore/dom/StyledElement.cpp
+++ b/Source/WebCore/dom/StyledElement.cpp
@@ -412,7 +412,7 @@ unsigned MappedAttributeHash::hash(const MappedAttributeKey& key)
COMPILE_ASSERT(sizeof(key.name) == 4 || sizeof(key.name) == 8, key_name_size);
COMPILE_ASSERT(sizeof(key.value) == 4 || sizeof(key.value) == 8, key_value_size);
- WTF::StringHasher hasher;
+ StringHasher hasher;
const UChar* data;
data = reinterpret_cast<const UChar*>(&key.name);
diff --git a/Source/WebCore/dom/UIEvent.cpp b/Source/WebCore/dom/UIEvent.cpp
index 401015b..dfdd34d 100644
--- a/Source/WebCore/dom/UIEvent.cpp
+++ b/Source/WebCore/dom/UIEvent.cpp
@@ -69,12 +69,12 @@ int UIEvent::charCode() const
return 0;
}
-int UIEvent::layerX() const
+int UIEvent::layerX()
{
return 0;
}
-int UIEvent::layerY() const
+int UIEvent::layerY()
{
return 0;
}
diff --git a/Source/WebCore/dom/UIEvent.h b/Source/WebCore/dom/UIEvent.h
index 8e330a5..a2f4e65 100644
--- a/Source/WebCore/dom/UIEvent.h
+++ b/Source/WebCore/dom/UIEvent.h
@@ -53,8 +53,8 @@ namespace WebCore {
virtual int keyCode() const;
virtual int charCode() const;
- virtual int layerX() const;
- virtual int layerY() const;
+ virtual int layerX();
+ virtual int layerY();
virtual int pageX() const;
virtual int pageY() const;
diff --git a/Source/WebCore/dom/ViewportArguments.cpp b/Source/WebCore/dom/ViewportArguments.cpp
index e75a3eb..49c94d7 100644
--- a/Source/WebCore/dom/ViewportArguments.cpp
+++ b/Source/WebCore/dom/ViewportArguments.cpp
@@ -257,32 +257,32 @@ static float findScaleValue(const String& keyString, const String& valueString,
return value;
}
-static bool findUserScalableValue(const String& keyString, const String& valueString, Document* document)
+static float findUserScalableValue(const String& keyString, const String& valueString, Document* document)
{
// yes and no are used as keywords.
// Numbers >= 1, numbers <= -1, device-width and device-height are mapped to yes.
// Numbers in the range <-1, 1>, and unknown values, are mapped to no.
if (equalIgnoringCase(valueString, "yes"))
- return true;
+ return 1;
if (equalIgnoringCase(valueString, "no"))
- return false;
+ return 0;
if (equalIgnoringCase(valueString, "desktop-width"))
- return true;
+ return 1;
if (equalIgnoringCase(valueString, "device-width"))
- return true;
+ return 1;
if (equalIgnoringCase(valueString, "device-height"))
- return true;
+ return 1;
bool ok;
float value = numericPrefix(keyString, valueString, document, &ok);
if (!ok)
- return false;
+ return 0;
if (fabs(value) < 1)
- return false;
+ return 0;
- return true;
+ return 1;
}
static float findTargetDensityDPIValue(const String& keyString, const String& valueString, Document* document)
diff --git a/Source/WebCore/dom/ViewportArguments.h b/Source/WebCore/dom/ViewportArguments.h
index 2e0fd19..66bb281 100644
--- a/Source/WebCore/dom/ViewportArguments.h
+++ b/Source/WebCore/dom/ViewportArguments.h
@@ -51,7 +51,7 @@ struct ViewportAttributes {
float minimumScale;
float maximumScale;
- bool userScalable;
+ float userScalable;
};
struct ViewportArguments {
@@ -74,7 +74,7 @@ struct ViewportArguments {
, width(ValueAuto)
, height(ValueAuto)
, targetDensityDpi(ValueAuto)
- , userScalable(true)
+ , userScalable(ValueAuto)
{
}
@@ -84,8 +84,7 @@ struct ViewportArguments {
float width;
float height;
float targetDensityDpi;
-
- bool userScalable;
+ float userScalable;
bool operator==(const ViewportArguments& other) const
{
diff --git a/Source/WebCore/dom/default/PlatformMessagePortChannel.h b/Source/WebCore/dom/default/PlatformMessagePortChannel.h
index 2aad952..651810b 100644
--- a/Source/WebCore/dom/default/PlatformMessagePortChannel.h
+++ b/Source/WebCore/dom/default/PlatformMessagePortChannel.h
@@ -44,7 +44,7 @@ namespace WebCore {
// PlatformMessagePortChannel is a platform-dependent interface to the remote side of a message channel.
// This default implementation supports multiple threads running within a single process. Implementations for multi-process platforms should define these public APIs in their own platform-specific PlatformMessagePortChannel file.
// The goal of this implementation is to eliminate contention except when cloning or closing the port, so each side of the channel has its own separate mutex.
- class PlatformMessagePortChannel : public ThreadSafeShared<PlatformMessagePortChannel> {
+ class PlatformMessagePortChannel : public ThreadSafeRefCounted<PlatformMessagePortChannel> {
public:
static void createChannel(PassRefPtr<MessagePort>, PassRefPtr<MessagePort>);
@@ -59,7 +59,7 @@ namespace WebCore {
MessagePort* locallyEntangledPort(const ScriptExecutionContext*);
// Wrapper for MessageQueue that allows us to do thread safe sharing by two proxies.
- class MessagePortQueue : public ThreadSafeShared<MessagePortQueue> {
+ class MessagePortQueue : public ThreadSafeRefCounted<MessagePortQueue> {
public:
static PassRefPtr<MessagePortQueue> create() { return adoptRef(new MessagePortQueue()); }