summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/dom
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-06-02 12:07:03 +0100
committerBen Murdoch <benm@google.com>2011-06-10 10:47:21 +0100
commit2daae5fd11344eaa88a0d92b0f6d65f8d2255c00 (patch)
treee4964fbd1cb70599f7718ff03e50ea1dab33890b /Source/WebCore/dom
parent87bdf0060a247bfbe668342b87e0874182e0ffa9 (diff)
downloadexternal_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.zip
external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.gz
external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.bz2
Merge WebKit at r84325: Initial merge by git.
Change-Id: Ic1a909300ecc0a13ddc6b4e784371d2ac6e3d59b
Diffstat (limited to 'Source/WebCore/dom')
-rw-r--r--Source/WebCore/dom/Attr.cpp2
-rw-r--r--Source/WebCore/dom/Attr.h2
-rw-r--r--Source/WebCore/dom/CDATASection.cpp2
-rw-r--r--Source/WebCore/dom/CDATASection.h2
-rw-r--r--Source/WebCore/dom/Comment.cpp2
-rw-r--r--Source/WebCore/dom/Comment.h2
-rw-r--r--Source/WebCore/dom/ContainerNode.cpp54
-rw-r--r--Source/WebCore/dom/DOMAllInOne.cpp2
-rw-r--r--Source/WebCore/dom/DataTransferItem.h2
-rw-r--r--Source/WebCore/dom/DataTransferItem.idl1
-rw-r--r--Source/WebCore/dom/Document.cpp349
-rw-r--r--Source/WebCore/dom/Document.h125
-rw-r--r--Source/WebCore/dom/Document.idl4
-rw-r--r--Source/WebCore/dom/DocumentFragment.cpp4
-rw-r--r--Source/WebCore/dom/DocumentFragment.h7
-rw-r--r--Source/WebCore/dom/DocumentMarker.h39
-rw-r--r--Source/WebCore/dom/DocumentMarkerController.cpp88
-rw-r--r--Source/WebCore/dom/DocumentMarkerController.h21
-rw-r--r--Source/WebCore/dom/DocumentOrderedMap.cpp17
-rw-r--r--Source/WebCore/dom/DocumentOrderedMap.h10
-rw-r--r--Source/WebCore/dom/DynamicNodeList.cpp5
-rw-r--r--Source/WebCore/dom/DynamicNodeList.h2
-rw-r--r--Source/WebCore/dom/Element.cpp73
-rw-r--r--Source/WebCore/dom/Element.h17
-rw-r--r--Source/WebCore/dom/Element.idl2
-rw-r--r--Source/WebCore/dom/ElementRareData.h4
-rw-r--r--Source/WebCore/dom/Event.cpp26
-rw-r--r--Source/WebCore/dom/Event.h33
-rw-r--r--Source/WebCore/dom/EventDispatcher.cpp203
-rw-r--r--Source/WebCore/dom/EventDispatcher.h22
-rw-r--r--Source/WebCore/dom/EventNames.h2
-rw-r--r--Source/WebCore/dom/EventQueue.cpp28
-rw-r--r--Source/WebCore/dom/EventQueue.h3
-rw-r--r--Source/WebCore/dom/EventTarget.cpp5
-rw-r--r--Source/WebCore/dom/EventTarget.h2
-rw-r--r--Source/WebCore/dom/InputElement.cpp2
-rw-r--r--Source/WebCore/dom/KeyboardEvent.cpp9
-rw-r--r--Source/WebCore/dom/KeyboardEvent.h18
-rw-r--r--Source/WebCore/dom/MessagePort.cpp8
-rw-r--r--Source/WebCore/dom/MouseEvent.cpp52
-rw-r--r--Source/WebCore/dom/MouseEvent.h14
-rw-r--r--Source/WebCore/dom/MouseRelatedEvent.cpp39
-rw-r--r--Source/WebCore/dom/NamedNodeMap.idl1
-rw-r--r--Source/WebCore/dom/Node.cpp180
-rw-r--r--Source/WebCore/dom/Node.h67
-rw-r--r--Source/WebCore/dom/NodeFilter.h9
-rw-r--r--Source/WebCore/dom/NodeList.h3
-rw-r--r--Source/WebCore/dom/NodeList.idl1
-rw-r--r--Source/WebCore/dom/NodeRareData.h11
-rw-r--r--Source/WebCore/dom/NodeRenderStyle.h6
-rw-r--r--Source/WebCore/dom/Notation.cpp2
-rw-r--r--Source/WebCore/dom/Notation.h2
-rw-r--r--Source/WebCore/dom/ProcessingInstruction.cpp2
-rw-r--r--Source/WebCore/dom/ProcessingInstruction.h2
-rw-r--r--Source/WebCore/dom/QualifiedName.h4
-rw-r--r--Source/WebCore/dom/Range.cpp56
-rw-r--r--Source/WebCore/dom/Range.h6
-rw-r--r--Source/WebCore/dom/ScriptElement.cpp3
-rw-r--r--Source/WebCore/dom/ScriptExecutionContext.h2
-rw-r--r--Source/WebCore/dom/SelectElement.cpp167
-rw-r--r--Source/WebCore/dom/SelectElement.h2
-rw-r--r--Source/WebCore/dom/ShadowRoot.cpp52
-rw-r--r--Source/WebCore/dom/ShadowRoot.h55
-rw-r--r--Source/WebCore/dom/StyledElement.cpp15
-rw-r--r--Source/WebCore/dom/Text.cpp2
-rw-r--r--Source/WebCore/dom/Text.h2
-rw-r--r--Source/WebCore/dom/TreeScope.cpp170
-rw-r--r--Source/WebCore/dom/TreeScope.h102
-rw-r--r--Source/WebCore/dom/WheelEvent.cpp31
-rw-r--r--Source/WebCore/dom/WheelEvent.h9
-rw-r--r--Source/WebCore/dom/XMLDocumentParserLibxml2.cpp16
-rwxr-xr-xSource/WebCore/dom/make_names.pl59
72 files changed, 1524 insertions, 819 deletions
diff --git a/Source/WebCore/dom/Attr.cpp b/Source/WebCore/dom/Attr.cpp
index 6500a97..e3ae348 100644
--- a/Source/WebCore/dom/Attr.cpp
+++ b/Source/WebCore/dom/Attr.cpp
@@ -152,7 +152,7 @@ PassRefPtr<Node> Attr::cloneNode(bool /*deep*/)
}
// DOM Section 1.1.1
-bool Attr::childTypeAllowed(NodeType type)
+bool Attr::childTypeAllowed(NodeType type) const
{
switch (type) {
case TEXT_NODE:
diff --git a/Source/WebCore/dom/Attr.h b/Source/WebCore/dom/Attr.h
index e76d2fa..217a0c3 100644
--- a/Source/WebCore/dom/Attr.h
+++ b/Source/WebCore/dom/Attr.h
@@ -79,7 +79,7 @@ private:
virtual PassRefPtr<Node> cloneNode(bool deep);
virtual bool isAttributeNode() const { return true; }
- virtual bool childTypeAllowed(NodeType);
+ virtual bool childTypeAllowed(NodeType) const;
virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
diff --git a/Source/WebCore/dom/CDATASection.cpp b/Source/WebCore/dom/CDATASection.cpp
index d73054e..33a3acc 100644
--- a/Source/WebCore/dom/CDATASection.cpp
+++ b/Source/WebCore/dom/CDATASection.cpp
@@ -51,7 +51,7 @@ PassRefPtr<Node> CDATASection::cloneNode(bool /*deep*/)
return create(document(), data());
}
-bool CDATASection::childTypeAllowed(NodeType)
+bool CDATASection::childTypeAllowed(NodeType) const
{
return false;
}
diff --git a/Source/WebCore/dom/CDATASection.h b/Source/WebCore/dom/CDATASection.h
index 5cf07e1..d7aca9d 100644
--- a/Source/WebCore/dom/CDATASection.h
+++ b/Source/WebCore/dom/CDATASection.h
@@ -37,7 +37,7 @@ private:
virtual String nodeName() const;
virtual NodeType nodeType() const;
virtual PassRefPtr<Node> cloneNode(bool deep);
- virtual bool childTypeAllowed(NodeType);
+ virtual bool childTypeAllowed(NodeType) const;
virtual PassRefPtr<Text> virtualCreate(const String&);
};
diff --git a/Source/WebCore/dom/Comment.cpp b/Source/WebCore/dom/Comment.cpp
index 00f1724..92cffed 100644
--- a/Source/WebCore/dom/Comment.cpp
+++ b/Source/WebCore/dom/Comment.cpp
@@ -51,7 +51,7 @@ PassRefPtr<Node> Comment::cloneNode(bool /*deep*/)
return create(document(), data());
}
-bool Comment::childTypeAllowed(NodeType)
+bool Comment::childTypeAllowed(NodeType) const
{
return false;
}
diff --git a/Source/WebCore/dom/Comment.h b/Source/WebCore/dom/Comment.h
index a0210c4..9db1f31 100644
--- a/Source/WebCore/dom/Comment.h
+++ b/Source/WebCore/dom/Comment.h
@@ -37,7 +37,7 @@ private:
virtual String nodeName() const;
virtual NodeType nodeType() const;
virtual PassRefPtr<Node> cloneNode(bool deep);
- virtual bool childTypeAllowed(NodeType);
+ virtual bool childTypeAllowed(NodeType) const;
};
} // namespace WebCore
diff --git a/Source/WebCore/dom/ContainerNode.cpp b/Source/WebCore/dom/ContainerNode.cpp
index 4014cca..276df56 100644
--- a/Source/WebCore/dom/ContainerNode.cpp
+++ b/Source/WebCore/dom/ContainerNode.cpp
@@ -56,15 +56,19 @@ static NodeCallbackQueue* s_postAttachCallbackQueue;
static size_t s_attachDepth;
static bool s_shouldReEnableMemoryCacheCallsAfterAttach;
+static inline void collectNodes(Node* node, NodeVector& nodes)
+{
+ for (Node* child = node->firstChild(); child; child = child->nextSibling())
+ nodes.append(child);
+}
+
static void collectTargetNodes(Node* node, NodeVector& nodes)
{
if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) {
nodes.append(node);
return;
}
-
- for (Node* child = node->firstChild(); child; child = child->nextSibling())
- nodes.append(child);
+ collectNodes(node, nodes);
}
void ContainerNode::removeAllChildren()
@@ -75,8 +79,7 @@ void ContainerNode::removeAllChildren()
void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent)
{
NodeVector children;
- for (Node* child = oldParent->firstChild(); child; child = child->nextSibling())
- children.append(child);
+ collectNodes(oldParent, children);
oldParent->removeAllChildren();
for (unsigned i = 0; i < children.size(); ++i) {
@@ -101,7 +104,7 @@ bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce
{
// Check that this node is not "floating".
// If it is, it can be deleted as a side effect of sending mutation events.
- ASSERT(refCount() || parentNode());
+ ASSERT(refCount() || parentOrHostNode());
ec = 0;
@@ -158,7 +161,8 @@ bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce
InspectorInstrumentation::willInsertDOMNode(document(), child, this);
#endif
- child->setDocumentRecursively(document());
+ child->setTreeScopeRecursively(treeScope());
+
insertBeforeCommon(next.get(), child);
// Send notification about the children change.
@@ -241,7 +245,7 @@ bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce
{
// Check that this node is not "floating".
// If it is, it can be deleted as a side effect of sending mutation events.
- ASSERT(refCount() || parentNode());
+ ASSERT(refCount() || parentOrHostNode());
ec = 0;
@@ -307,7 +311,7 @@ bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce
InspectorInstrumentation::willInsertDOMNode(document(), child.get(), this);
#endif
- child->setDocumentRecursively(document());
+ child->setTreeScopeRecursively(treeScope());
// Add child after "prev".
forbidEventDispatch();
@@ -384,8 +388,7 @@ static void willRemoveChildren(ContainerNode* container)
container->document()->incDOMTreeVersion();
NodeVector children;
- for (Node* n = container->firstChild(); n; n = n->nextSibling())
- children.append(n);
+ collectNodes(container, children);
for (NodeVector::const_iterator it = children.begin(); it != children.end(); it++) {
Node* child = it->get();
@@ -399,7 +402,7 @@ bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec)
{
// Check that this node is not "floating".
// If it is, it can be deleted as a side effect of sending mutation events.
- ASSERT(refCount() || parentNode());
+ ASSERT(refCount() || parentOrHostNode());
ec = 0;
@@ -559,7 +562,7 @@ bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bo
{
// Check that this node is not "floating".
// If it is, it can be deleted as a side effect of sending mutation events.
- ASSERT(refCount() || parentNode());
+ ASSERT(refCount() || parentOrHostNode());
ec = 0;
@@ -597,7 +600,7 @@ bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bo
InspectorInstrumentation::willInsertDOMNode(document(), child, this);
#endif
- child->setDocumentRecursively(document());
+ child->setTreeScopeRecursively(treeScope());
// Append child to the end of the list
forbidEventDispatch();
@@ -735,8 +738,16 @@ void ContainerNode::insertedIntoDocument()
{
Node::insertedIntoDocument();
insertedIntoTree(false);
- for (Node* child = m_firstChild; child && inDocument(); child = child->nextSibling())
+
+ // Determine set of children before operating on any of them.
+ NodeVector children;
+ collectNodes(this, children);
+
+ NodeVector::iterator it;
+ for (it = children.begin(); it != children.end() && inDocument(); ++it) {
+ Node* child = it->get();
child->insertedIntoDocument();
+ }
}
void ContainerNode::removedFromDocument()
@@ -778,9 +789,16 @@ void ContainerNode::childrenChanged(bool changedByParser, Node* beforeChange, No
void ContainerNode::cloneChildNodes(ContainerNode *clone)
{
// disable the delete button so it's elements are not serialized into the markup
- bool isEditorEnabled = document()->frame() && document()->frame()->editor()->canEdit();
- if (isEditorEnabled)
- document()->frame()->editor()->deleteButtonController()->disable();
+ bool isEditorEnabled = false;
+ if (document()->frame() && document()->frame()->editor()->canEdit()) {
+ SelectionController* selection = document()->frame()->selection();
+ Element* root = selection ? selection->rootEditableElement() : 0;
+ isEditorEnabled = root && isDescendantOf(root);
+
+ if (isEditorEnabled)
+ document()->frame()->editor()->deleteButtonController()->disable();
+ }
+
ExceptionCode ec = 0;
for (Node* n = firstChild(); n && !ec; n = n->nextSibling())
clone->appendChild(n->cloneNode(true), ec);
diff --git a/Source/WebCore/dom/DOMAllInOne.cpp b/Source/WebCore/dom/DOMAllInOne.cpp
index cc4888f..4a51d90 100644
--- a/Source/WebCore/dom/DOMAllInOne.cpp
+++ b/Source/WebCore/dom/DOMAllInOne.cpp
@@ -108,6 +108,7 @@
#include "ScriptableDocumentParser.cpp"
#include "SelectElement.cpp"
#include "SelectorNodeList.cpp"
+#include "ShadowRoot.cpp"
#include "SpaceSplitString.cpp"
#include "StaticHashSetNodeList.cpp"
#include "StaticNodeList.cpp"
@@ -121,6 +122,7 @@
#include "TouchList.cpp"
#include "TransformSourceLibxslt.cpp"
#include "Traversal.cpp"
+#include "TreeScope.cpp"
#include "TreeWalker.cpp"
#include "UIEvent.cpp"
#include "UIEventWithKeyState.cpp"
diff --git a/Source/WebCore/dom/DataTransferItem.h b/Source/WebCore/dom/DataTransferItem.h
index 7b5886a..d648c56 100644
--- a/Source/WebCore/dom/DataTransferItem.h
+++ b/Source/WebCore/dom/DataTransferItem.h
@@ -38,6 +38,7 @@
namespace WebCore {
+class Blob;
class StringCallback;
class DataTransferItem : public RefCounted<DataTransferItem> {
@@ -51,6 +52,7 @@ public:
virtual String type() const = 0;
virtual void getAsString(PassRefPtr<StringCallback>) = 0;
+ virtual PassRefPtr<Blob> getAsFile() = 0;
};
} // namespace WebCore
diff --git a/Source/WebCore/dom/DataTransferItem.idl b/Source/WebCore/dom/DataTransferItem.idl
index a2c9942..accaf50 100644
--- a/Source/WebCore/dom/DataTransferItem.idl
+++ b/Source/WebCore/dom/DataTransferItem.idl
@@ -37,6 +37,7 @@ module core {
readonly attribute DOMString type;
void getAsString(in [Callback] StringCallback callback);
+ Blob getAsFile();
};
}
diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp
index a0ddede..b85bdfb 100644
--- a/Source/WebCore/dom/Document.cpp
+++ b/Source/WebCore/dom/Document.cpp
@@ -123,7 +123,7 @@
#include "RenderTextControl.h"
#include "RenderView.h"
#include "RenderWidget.h"
-#include "ScopedEventQueue.h"
+#include "ScopedEventQueue.h"
#include "ScriptCallStack.h"
#include "ScriptController.h"
#include "ScriptElement.h"
@@ -391,7 +391,8 @@ private:
uint64_t Document::s_globalTreeVersion = 0;
Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
- : ContainerNode(0)
+ : TreeScope(this)
+ , m_guardRefCount(0)
, m_compatibilityMode(NoQuirksMode)
, m_compatibilityModeLocked(false)
, m_domTreeVersion(++s_globalTreeVersion)
@@ -406,8 +407,6 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
, m_containsValidityStyleRules(false)
, m_updateFocusAppearanceRestoresSelection(false)
, m_ignoreDestructiveWriteCount(0)
- , m_title("")
- , m_rawTitle("")
, m_titleSetExplicitly(false)
, m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired)
, m_startTime(currentTime())
@@ -418,7 +417,6 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
, m_xmlStandalone(false)
, m_savedRenderer(0)
, m_designMode(inherit)
- , m_selfOnlyRefCount(0)
#if ENABLE(SVG)
, m_svgExtensions(0)
#endif
@@ -426,7 +424,6 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
, m_hasDashboardRegions(false)
, m_dashboardRegionsDirty(false)
#endif
- , m_accessKeyMapValid(false)
, m_createRenderers(true)
, m_inPageCache(false)
, m_useSecureKeyboardEntryWhenActive(false)
@@ -434,10 +431,6 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
, m_isHTML(isHTML)
, m_usesViewSourceStyles(false)
, m_sawElementsInKnownNamespaces(false)
- , m_numNodeListCaches(0)
-#if USE(JSC)
- , m_normalWorldWrapperCache(0)
-#endif
, m_usingGeolocation(false)
, m_eventQueue(EventQueue::create(this))
#if ENABLE(WML)
@@ -446,7 +439,6 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
, m_weakReference(DocumentWeakReference::create(this))
, m_idAttributeName(idAttr)
#if ENABLE(FULLSCREEN_API)
- , m_isFullScreen(0)
, m_areKeysEnabledInFullScreen(0)
, m_fullScreenRenderer(0)
, m_fullScreenChangeDelayTimer(this, &Document::fullScreenChangeDelayTimerFired)
@@ -506,7 +498,7 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
m_usesLinkRules = false;
m_gotoAnchorNeededAfterStylesheetsLoad = false;
-
+
m_didCalculateStyleSelector = false;
m_hasDirtyStyleSelector = false;
m_pendingStylesheets = 0;
@@ -532,57 +524,6 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
#endif
}
-void Document::removedLastRef()
-{
- ASSERT(!m_deletionHasBegun);
- if (m_selfOnlyRefCount) {
- // If removing a child removes the last self-only ref, we don't
- // want the document to be destructed until after
- // removeAllChildren returns, so we guard ourselves with an
- // extra self-only ref.
- selfOnlyRef();
-
- // We must make sure not to be retaining any of our children through
- // these extra pointers or we will create a reference cycle.
- m_docType = 0;
- m_focusedNode = 0;
- m_hoverNode = 0;
- m_activeNode = 0;
- m_titleElement = 0;
- m_documentElement = 0;
-#if ENABLE(FULLSCREEN_API)
- m_fullScreenElement = 0;
-#endif
-
- // removeAllChildren() doesn't always unregister IDs, do it upfront to avoid having stale references in the map.
- m_elementsById.clear();
-
- removeAllChildren();
-
- m_markers->detach();
-
- detachParser();
-
- m_cssCanvasElements.clear();
-
-#if ENABLE(REQUEST_ANIMATION_FRAME)
- // FIXME: consider using ActiveDOMObject.
- m_scriptedAnimationController = 0;
-#endif
-
-#ifndef NDEBUG
- m_inRemovedLastRefFunction = false;
-#endif
-
- selfOnlyDeref();
- } else {
-#ifndef NDEBUG
- m_deletionHasBegun = true;
-#endif
- delete this;
- }
-}
-
Document::~Document()
{
ASSERT(!renderer());
@@ -590,15 +531,12 @@ Document::~Document()
ASSERT(!m_savedRenderer);
ASSERT(m_ranges.isEmpty());
ASSERT(!m_styleRecalcTimer.isActive());
+ ASSERT(!m_parentTreeScope);
m_scriptRunner.clear();
removeAllEventListeners();
-#if USE(JSC)
- destroyAllWrapperCaches();
-#endif
-
// Currently we believe that Document can never outlive the parser.
// Although the Document may be replaced synchronously, DocumentParsers
// generally keep at least one reference to an Element which would in turn
@@ -642,41 +580,74 @@ Document::~Document()
m_implementation->ownerDocumentDestroyed();
}
-MediaQueryMatcher* Document::mediaQueryMatcher()
+void Document::removedLastRef()
{
- if (!m_mediaQueryMatcher)
- m_mediaQueryMatcher = MediaQueryMatcher::create(this);
- return m_mediaQueryMatcher.get();
-}
+ ASSERT(!m_deletionHasBegun);
+ if (m_guardRefCount) {
+ // If removing a child removes the last self-only ref, we don't
+ // want the scope to be destructed until after
+ // removeAllChildren returns, so we guard ourselves with an
+ // extra self-only ref.
+ guardRef();
-#if USE(JSC)
-Document::JSWrapperCache* Document::createWrapperCache(DOMWrapperWorld* world)
-{
- JSWrapperCache* wrapperCache = new JSWrapperCache;
- m_wrapperCacheMap.set(world, wrapperCache);
- if (world->isNormal()) {
- ASSERT(!m_normalWorldWrapperCache);
- m_normalWorldWrapperCache = wrapperCache;
+ // We must make sure not to be retaining any of our children through
+ // these extra pointers or we will create a reference cycle.
+ m_docType = 0;
+ m_focusedNode = 0;
+ m_hoverNode = 0;
+ m_activeNode = 0;
+ m_titleElement = 0;
+ m_documentElement = 0;
+#if ENABLE(FULLSCREEN_API)
+ m_fullScreenElement = 0;
+#endif
+ m_styleSelector.clear();
+ m_styleSheets.clear();
+ m_elemSheet.clear();
+ m_mappedElementSheet.clear();
+ m_pageUserSheet.clear();
+ m_pageGroupUserSheets.clear();
+
+ // removeAllChildren() doesn't always unregister IDs,
+ // so tear down scope information upfront to avoid having stale references in the map.
+ destroyTreeScopeData();
+ removeAllChildren();
+
+ m_markers->detach();
+
+ detachParser();
+
+ m_cssCanvasElements.clear();
+
+#if ENABLE(REQUEST_ANIMATION_FRAME)
+ // FIXME: consider using ActiveDOMObject.
+ m_scriptedAnimationController = 0;
+#endif
+
+#ifndef NDEBUG
+ m_inRemovedLastRefFunction = false;
+#endif
+
+ guardDeref();
+ } else {
+#ifndef NDEBUG
+ m_deletionHasBegun = true;
+#endif
+ delete this;
}
- world->didCreateWrapperCache(this);
- return wrapperCache;
}
-void Document::destroyWrapperCache(DOMWrapperWorld* world)
+Element* Document::getElementById(const AtomicString& id) const
{
- Document::JSWrapperCache* wrappers = wrapperCacheMap().take(world);
- ASSERT(wrappers);
- delete wrappers;
- world->didDestroyWrapperCache(this);
+ return TreeScope::getElementById(id);
}
-void Document::destroyAllWrapperCaches()
+MediaQueryMatcher* Document::mediaQueryMatcher()
{
- JSWrapperCacheMap& wrapperCacheMap = this->wrapperCacheMap();
- while (!wrapperCacheMap.isEmpty())
- destroyWrapperCache(wrapperCacheMap.begin()->first);
+ if (!m_mediaQueryMatcher)
+ m_mediaQueryMatcher = MediaQueryMatcher::create(this);
+ return m_mediaQueryMatcher.get();
}
-#endif
void Document::setCompatibilityMode(CompatibilityMode mode)
{
@@ -718,6 +689,7 @@ void Document::setDocType(PassRefPtr<DocumentType> docType)
ASSERT(!m_docType || !docType);
m_docType = docType;
if (m_docType)
+<<<<<<< HEAD
m_docType->setDocument(this);
#ifdef ANDROID_META_SUPPORT
if (m_docType && !ownerElement()
@@ -729,6 +701,9 @@ void Document::setDocType(PassRefPtr<DocumentType> docType)
PlatformBridge::updateViewport(frameView);
}
#endif
+=======
+ m_docType->setTreeScope(this);
+>>>>>>> WebKit.org at r84325
}
DOMImplementation* Document::implementation()
@@ -740,7 +715,7 @@ DOMImplementation* Document::implementation()
void Document::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
{
- ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
+ TreeScope::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
// Invalidate the document element we have cached in case it was replaced.
m_documentElement = 0;
@@ -958,7 +933,7 @@ PassRefPtr<Node> Document::adoptNode(PassRefPtr<Node> source, ExceptionCode& ec)
source->parentNode()->removeChild(source.get(), ec);
}
- source->setDocumentRecursively(this);
+ source->setTreeScopeRecursively(this);
return source;
}
@@ -1033,13 +1008,6 @@ PassRefPtr<Element> Document::createElementNS(const String& namespaceURI, const
return createElement(qName, false);
}
-Element* Document::getElementById(const AtomicString& elementId) const
-{
- if (elementId.isEmpty())
- return 0;
- return m_elementsById.getElementById(elementId.impl(), this);
-}
-
String Document::readyState() const
{
DEFINE_STATIC_LOCAL(const String, loading, ("loading"));
@@ -1266,42 +1234,15 @@ PassRefPtr<Range> Document::caretRangeFromPoint(int x, int y)
return Range::create(this, rangeCompliantPosition, rangeCompliantPosition);
}
-void Document::addElementById(const AtomicString& elementId, Element* element)
-{
- m_elementsById.add(elementId.impl(), element);
-}
-
-void Document::removeElementById(const AtomicString& elementId, Element* element)
-{
- m_elementsById.remove(elementId.impl(), element);
-}
-
-Element* Document::getElementByAccessKey(const String& key) const
-{
- if (key.isEmpty())
- return 0;
- if (!m_accessKeyMapValid) {
- for (Node* n = firstChild(); n; n = n->traverseNextNode()) {
- if (!n->isElementNode())
- continue;
- Element* element = static_cast<Element*>(n);
- const AtomicString& accessKey = element->getAttribute(accesskeyAttr);
- if (!accessKey.isEmpty())
- m_elementsByAccessKey.set(accessKey.impl(), element);
- }
- m_accessKeyMapValid = true;
- }
- return m_elementsByAccessKey.get(key.impl());
-}
-
/*
* Performs three operations:
* 1. Convert control characters to spaces
* 2. Trim leading and trailing spaces
* 3. Collapse internal whitespace.
*/
-static inline String canonicalizedTitle(Document* document, const String& title)
+static inline StringWithDirection canonicalizedTitle(Document* document, const StringWithDirection& titleWithDirection)
{
+ const String& title = titleWithDirection.string();
const UChar* characters = title.characters();
unsigned length = title.length();
unsigned i;
@@ -1317,7 +1258,7 @@ static inline String canonicalizedTitle(Document* document, const String& title)
}
if (i == length)
- return "";
+ return StringWithDirection();
// Replace control characters with spaces, and backslashes with currency symbols, and collapse whitespace.
bool previousCharWasWS = false;
@@ -1342,17 +1283,17 @@ static inline String canonicalizedTitle(Document* document, const String& title)
}
if (!builderIndex && buffer[builderIndex] == ' ')
- return "";
+ return StringWithDirection();
buffer.shrink(builderIndex + 1);
// Replace the backslashes with currency symbols if the encoding requires it.
document->displayBufferModifiedByEncoding(buffer.characters(), buffer.length());
- return String::adopt(buffer);
+ return StringWithDirection(String::adopt(buffer), titleWithDirection.direction());
}
-void Document::updateTitle(const String& title)
+void Document::updateTitle(const StringWithDirection& title)
{
if (m_rawTitle == title)
return;
@@ -1378,16 +1319,17 @@ void Document::setTitle(const String& title)
}
}
- updateTitle(title);
+ // The DOM API has no method of specifying direction, so assume LTR.
+ updateTitle(StringWithDirection(title, LTR));
if (m_titleElement) {
ASSERT(m_titleElement->hasTagName(titleTag));
if (m_titleElement->hasTagName(titleTag))
- static_cast<HTMLTitleElement*>(m_titleElement.get())->setText(m_title);
+ static_cast<HTMLTitleElement*>(m_titleElement.get())->setText(title);
}
}
-void Document::setTitleElement(const String& title, Element* titleElement)
+void Document::setTitleElement(const StringWithDirection& title, Element* titleElement)
{
if (titleElement != m_titleElement) {
if (m_titleElement || m_titleSetExplicitly)
@@ -1412,13 +1354,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);
- setTitleElement(titleElement->text(), titleElement);
+ setTitleElement(titleElement->textWithDirection(), titleElement);
break;
}
}
if (!m_titleElement)
- updateTitle("");
+ updateTitle(StringWithDirection());
}
String Document::nodeName() const
@@ -1489,10 +1431,7 @@ void Document::scheduleStyleRecalc()
documentsThatNeedStyleRecalc->add(this);
// FIXME: Why on earth is this here? This is clearly misplaced.
- if (m_accessKeyMapValid) {
- m_accessKeyMapValid = false;
- m_elementsByAccessKey.clear();
- }
+ invalidateAccessKeyMap();
m_styleRecalcTimer.startOneShot(0);
}
@@ -1542,17 +1481,24 @@ void Document::recalcStyle(StyleChange change)
m_inStyleRecalc = true;
suspendPostAttachCallbacks();
RenderWidget::suspendWidgetHierarchyUpdates();
- if (view())
- view()->pauseScheduledEvents();
+<<<<<<< HEAD
#ifdef ANDROID_INSTRUMENT
android::TimeCounter::start(android::TimeCounter::CalculateStyleTimeCounter);
#endif
+=======
+ RefPtr<FrameView> frameView = view();
+ if (frameView) {
+ frameView->pauseScheduledEvents();
+ frameView->beginDeferredRepaints();
+ }
+
+>>>>>>> WebKit.org at r84325
ASSERT(!renderer() || renderArena());
if (!renderer() || !renderArena())
goto bail_out;
-
+
if (m_pendingStyleRecalcShouldForce)
change = Force;
@@ -1596,8 +1542,10 @@ bail_out:
m_usesLinkRules = m_styleSelector->usesLinkRules();
}
- if (view())
- view()->resumeScheduledEvents();
+ if (frameView) {
+ frameView->resumeScheduledEvents();
+ frameView->endDeferredRepaints();
+ }
RenderWidget::resumeWidgetHierarchyUpdates();
resumePostAttachCallbacks();
m_inStyleRecalc = false;
@@ -1794,7 +1742,7 @@ void Document::attach()
RenderObject* render = renderer();
setRenderer(0);
- ContainerNode::attach();
+ TreeScope::attach();
setRenderer(render);
}
@@ -1806,6 +1754,7 @@ void Document::detach()
clearAXObjectCache();
stopActiveDOMObjects();
+ m_eventQueue->cancelQueuedEvents();
#if ENABLE(REQUEST_ANIMATION_FRAME)
// FIXME: consider using ActiveDOMObject.
@@ -1840,7 +1789,7 @@ void Document::detach()
m_focusedNode = 0;
m_activeNode = 0;
- ContainerNode::detach();
+ TreeScope::detach();
unscheduleStyleRecalc();
@@ -2725,7 +2674,8 @@ void Document::processHttpEquiv(const String& equiv, const String& content)
frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
}
}
- }
+ } else if (equalIgnoringCase(equiv, "x-webkit-csp"))
+ contentSecurityPolicy()->didReceiveHeader(content);
}
// Though isspace() considers \t and \v to be whitespace, Win IE doesn't.
@@ -2821,7 +2771,7 @@ MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& r
}
// DOM Section 1.1.1
-bool Document::childTypeAllowed(NodeType type)
+bool Document::childTypeAllowed(NodeType type) const
{
switch (type) {
case ATTRIBUTE_NODE:
@@ -3957,33 +3907,6 @@ bool Document::parseQualifiedName(const String& qualifiedName, String& prefix, S
return true;
}
-void Document::addImageMap(HTMLMapElement* imageMap)
-{
- AtomicStringImpl* name = imageMap->getName().impl();
- if (!name)
- return;
- m_imageMapsByName.add(name, imageMap);
-}
-
-void Document::removeImageMap(HTMLMapElement* imageMap)
-{
- AtomicStringImpl* name = imageMap->getName().impl();
- if (!name)
- return;
- m_imageMapsByName.remove(name, imageMap);
-}
-
-HTMLMapElement* Document::getImageMap(const String& url) const
-{
- if (url.isNull())
- return 0;
- size_t hashPos = url.find('#');
- String name = (hashPos == notFound ? url : url.substring(hashPos + 1)).impl();
- if (isHTMLDocument())
- return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByLowercasedMapName(AtomicString(name.lower()).impl(), this));
- return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByMapName(AtomicString(name).impl(), this));
-}
-
void Document::setDecoder(PassRefPtr<TextResourceDecoder> decoder)
{
m_decoder = decoder;
@@ -4832,29 +4755,6 @@ void Document::resumeScriptedAnimationControllerCallbacks()
#endif
}
-Element* Document::findAnchor(const String& name)
-{
- if (name.isEmpty())
- return 0;
- if (Element* element = getElementById(name))
- return element;
- for (Node* node = this; node; node = node->traverseNextNode()) {
- if (node->hasTagName(aTag)) {
- HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(node);
- if (inQuirksMode()) {
- // Quirks mode, case insensitive comparison of names.
- if (equalIgnoringCase(anchor->name(), name))
- return anchor;
- } else {
- // Strict mode, names need to match exactly.
- if (anchor->name() == name)
- return anchor;
- }
- }
- }
- return 0;
-}
-
String Document::displayStringModifiedByEncoding(const String& str) const
{
if (m_decoder)
@@ -4977,7 +4877,6 @@ void Document::webkitWillEnterFullScreenForElement(Element* element)
ASSERT(page() && page()->settings()->fullScreenEnabled());
m_fullScreenElement = element;
- m_isFullScreen = true;
if (m_fullScreenElement != documentElement())
m_fullScreenElement->detach();
@@ -4988,8 +4887,8 @@ void Document::webkitWillEnterFullScreenForElement(Element* element)
m_fullScreenRenderer->setAnimating(true);
#if USE(ACCELERATED_COMPOSITING)
view()->updateCompositingLayers();
- ASSERT(m_fullScreenRenderer->layer()->backing());
- page()->chrome()->client()->setRootFullScreenLayer(m_fullScreenRenderer->layer()->backing()->graphicsLayer());
+ if (m_fullScreenRenderer->layer()->isComposited())
+ page()->chrome()->client()->setRootFullScreenLayer(m_fullScreenRenderer->layer()->backing()->graphicsLayer());
#endif
}
}
@@ -5000,7 +4899,6 @@ void Document::webkitDidEnterFullScreenForElement(Element*)
m_fullScreenRenderer->setAnimating(false);
#if USE(ACCELERATED_COMPOSITING)
view()->updateCompositingLayers();
- ASSERT(!m_fullScreenRenderer->layer()->backing());
page()->chrome()->client()->setRootFullScreenLayer(0);
#endif
}
@@ -5011,18 +4909,16 @@ void Document::webkitWillExitFullScreenForElement(Element*)
{
if (m_fullScreenRenderer) {
m_fullScreenRenderer->setAnimating(true);
- m_fullScreenRenderer->setAnimating(true);
#if USE(ACCELERATED_COMPOSITING)
view()->updateCompositingLayers();
- ASSERT(m_fullScreenRenderer->layer()->backing());
- page()->chrome()->client()->setRootFullScreenLayer(m_fullScreenRenderer->layer()->backing()->graphicsLayer());
+ if (m_fullScreenRenderer->layer()->isComposited())
+ page()->chrome()->client()->setRootFullScreenLayer(m_fullScreenRenderer->layer()->backing()->graphicsLayer());
#endif
}
}
void Document::webkitDidExitFullScreenForElement(Element*)
{
- m_isFullScreen = false;
m_areKeysEnabledInFullScreen = false;
if (m_fullScreenRenderer)
@@ -5030,7 +4926,8 @@ void Document::webkitDidExitFullScreenForElement(Element*)
if (m_fullScreenElement != documentElement())
m_fullScreenElement->detach();
-
+
+ m_fullScreenElement = 0;
setFullScreenRenderer(0);
#if USE(ACCELERATED_COMPOSITING)
page()->chrome()->client()->setRootFullScreenLayer(0);
@@ -5149,34 +5046,4 @@ PassRefPtr<TouchList> Document::createTouchList(ExceptionCode&) const
}
#endif
-static bool hasHeadSibling(const Document* document)
-{
- Node* de = document->documentElement();
- if (!de)
- return false;
-
- for (Node* i = de->firstChild(); i; i = i->nextSibling()) {
- // A child of the document element which is rather than <head> is
- // typically visible and FOUC safe. So we return true here.
- if (!i->hasTagName(headTag))
- return true;
- }
-
- return false;
-}
-
-bool Document::mayCauseFlashOfUnstyledContent() const
-{
- // Some kind of FOUC is caused by a repaint request before page's <body> arrival
- // because page authors often give background styles to <body>, not to <html>.
- // (And these styles are unavailable before <style> or <link> is given.)
- // This functions is used for checking such possibility of FOUCs.
- // Note that the implementation considers only empty or <head> only contents as a FOUC cause
- // rather than missing <body>, because non-HTML document like SVG and arbitrary XML from foreign namespace
- // should be painted even if there is no <body>.
- if (didLayoutWithPendingStylesheets())
- return true;
- return !hasHeadSibling(this);
-}
-
} // namespace WebCore
diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h
index 11c595a..5ab6d77 100644
--- a/Source/WebCore/dom/Document.h
+++ b/Source/WebCore/dom/Document.h
@@ -31,23 +31,19 @@
#include "CollectionCache.h"
#include "CollectionType.h"
#include "Color.h"
-#include "ContainerNode.h"
#include "DOMTimeStamp.h"
-#include "DocumentOrderedMap.h"
#include "DocumentTiming.h"
#include "QualifiedName.h"
#include "ScriptExecutionContext.h"
+#include "StringWithDirection.h"
#include "Timer.h"
+#include "TreeScope.h"
#include "ViewportArguments.h"
#include <wtf/FixedArray.h>
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/PassRefPtr.h>
-#if USE(JSC)
-#include <runtime/WeakGCMap.h>
-#endif
-
namespace WebCore {
class AXObjectCache;
@@ -205,7 +201,7 @@ enum PageshowEventPersistence {
enum StyleSelectorUpdateFlag { RecalcStyleImmediately, DeferRecalcStyle };
-class Document : public ContainerNode, public ScriptExecutionContext {
+class Document : public TreeScope, public ScriptExecutionContext {
public:
static PassRefPtr<Document> create(Frame* frame, const KURL& url)
{
@@ -219,25 +215,25 @@ public:
MediaQueryMatcher* mediaQueryMatcher();
- using ContainerNode::ref;
- using ContainerNode::deref;
+ using TreeScope::ref;
+ using TreeScope::deref;
- // Nodes belonging to this document hold "self-only" references -
+ // Nodes belonging to this document hold guard references -
// these are enough to keep the document from being destroyed, but
// not enough to keep it from removing its children. This allows a
// node that outlives its document to still have a valid document
- // pointer without introducing reference cycles
-
- void selfOnlyRef()
+ // pointer without introducing reference cycles.
+ void guardRef()
{
ASSERT(!m_deletionHasBegun);
- ++m_selfOnlyRefCount;
+ ++m_guardRefCount;
}
- void selfOnlyDeref()
+
+ void guardDeref()
{
ASSERT(!m_deletionHasBegun);
- --m_selfOnlyRefCount;
- if (!m_selfOnlyRefCount && !refCount()) {
+ --m_guardRefCount;
+ if (!m_guardRefCount && !refCount()) {
#ifndef NDEBUG
m_deletionHasBegun = true;
#endif
@@ -245,6 +241,10 @@ public:
}
}
+ virtual void removedLastRef();
+
+ Element* getElementById(const AtomicString& id) const;
+
// DOM methods & attributes for Document
DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
@@ -259,8 +259,6 @@ public:
DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(formchange);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(forminput);
DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
@@ -328,9 +326,6 @@ public:
PassRefPtr<Node> importNode(Node* importedNode, bool deep, ExceptionCode&);
virtual PassRefPtr<Element> createElementNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode&);
PassRefPtr<Element> createElement(const QualifiedName&, bool createdByParser);
- Element* getElementById(const AtomicString&) const;
- bool hasElementWithId(AtomicStringImpl* id) const;
- bool containsMultipleElementsWithId(const AtomicString& id) const;
/**
* Retrieve all nodes that intersect a rect in the window's document, until it is fully enclosed by
@@ -394,13 +389,6 @@ public:
PassRefPtr<HTMLAllCollection> all();
- // Find first anchor with the given name.
- // First searches for an element with the given ID, but if that fails, then looks
- // for an anchor with the given name. ID matching is always case sensitive, but
- // Anchor name matching is case sensitive in strict mode and not case sensitive in
- // quirks mode for historical compatibility reasons.
- Element* findAnchor(const String& name);
-
CollectionCache* collectionInfo(CollectionType type)
{
ASSERT(type >= FirstUnnamedDocumentCachedType);
@@ -451,8 +439,6 @@ public:
return m_styleSelector.get();
}
- Element* getElementByAccessKey(const String& key) const;
-
/**
* Updates the pending sheet count and then calls updateStyleSelector.
*/
@@ -819,9 +805,11 @@ public:
// Returns 0 if this is the top level document.
HTMLFrameOwnerElement* ownerElement() const;
- String title() const { return m_title; }
+ // Used by DOM bindings; no direction known.
+ String title() const { return m_title.string(); }
void setTitle(const String&);
- void setTitleElement(const String& title, Element* titleElement);
+
+ void setTitleElement(const StringWithDirection&, Element* titleElement);
void removeTitle(Element* titleElement);
String cookie(ExceptionCode&) const;
@@ -872,13 +860,6 @@ public:
// Checks to make sure prefix and namespace do not conflict (per DOM Core 3)
static bool hasPrefixNamespaceMismatch(const QualifiedName&);
- void addElementById(const AtomicString& elementId, Element *element);
- void removeElementById(const AtomicString& elementId, Element *element);
-
- void addImageMap(HTMLMapElement*);
- void removeImageMap(HTMLMapElement*);
- HTMLMapElement* getImageMap(const String& url) const;
-
HTMLElement* body() const;
void setBody(PassRefPtr<HTMLElement>, ExceptionCode&);
@@ -956,10 +937,6 @@ public:
void setUseSecureKeyboardEntryWhenActive(bool);
bool useSecureKeyboardEntryWhenActive() const;
- void addNodeListCache() { ++m_numNodeListCaches; }
- void removeNodeListCache() { ASSERT(m_numNodeListCaches > 0); --m_numNodeListCaches; }
- bool hasNodeListCaches() const { return m_numNodeListCaches; }
-
void updateFocusAppearanceSoon(bool restorePreviousSelection);
void cancelFocusAppearanceUpdate();
@@ -979,16 +956,6 @@ public:
virtual void suspendScriptedAnimationControllerCallbacks();
virtual void resumeScriptedAnimationControllerCallbacks();
-#if USE(JSC)
- typedef JSC::WeakGCMap<WebCore::Node*, JSNode> JSWrapperCache;
- typedef HashMap<DOMWrapperWorld*, JSWrapperCache*> JSWrapperCacheMap;
- JSWrapperCacheMap& wrapperCacheMap() { return m_wrapperCacheMap; }
- JSWrapperCache* getWrapperCache(DOMWrapperWorld* world);
- JSWrapperCache* createWrapperCache(DOMWrapperWorld*);
- void destroyWrapperCache(DOMWrapperWorld*);
- void destroyAllWrapperCaches();
-#endif
-
virtual void finishedParsing();
bool inPageCache() const { return m_inPageCache; }
@@ -1059,7 +1026,7 @@ public:
#endif
virtual bool isContextThread() const;
- virtual bool isJSExecutionTerminated() const { return false; }
+ virtual bool isJSExecutionForbidden() const { return false; }
void setUsingGeolocation(bool f) { m_usingGeolocation = f; }
bool usingGeolocation() const { return m_usingGeolocation; };
@@ -1089,8 +1056,8 @@ public:
const QualifiedName& idAttributeName() const { return m_idAttributeName; }
#if ENABLE(FULLSCREEN_API)
- bool webkitIsFullScreen() const { return m_isFullScreen; }
- bool webkitFullScreenKeyboardInputAllowed() const { return m_isFullScreen && m_areKeysEnabledInFullScreen; }
+ bool webkitIsFullScreen() const { return m_fullScreenElement.get(); }
+ bool webkitFullScreenKeyboardInputAllowed() const { return m_fullScreenElement.get() && m_areKeysEnabledInFullScreen; }
Element* webkitCurrentFullScreenElement() const { return m_fullScreenElement.get(); }
void webkitRequestFullScreenForElement(Element*, unsigned short flags);
void webkitCancelFullScreen();
@@ -1128,8 +1095,6 @@ public:
void serviceScriptedAnimations(DOMTimeStamp);
#endif
- bool mayCauseFlashOfUnstyledContent() const;
-
virtual EventTarget* errorEventTarget();
virtual void logExceptionToConsole(const String& errorMessage, int lineNumber, const String& sourceURL, PassRefPtr<ScriptCallStack>);
@@ -1152,13 +1117,12 @@ private:
void processArguments(const String& features, void* data, ArgumentsCallback);
virtual bool isDocument() const { return true; }
- virtual void removedLastRef();
virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
virtual String nodeName() const;
virtual NodeType nodeType() const;
- virtual bool childTypeAllowed(NodeType);
+ virtual bool childTypeAllowed(NodeType) const;
virtual PassRefPtr<Node> cloneNode(bool deep);
virtual bool canReplaceChild(Node* newChild, Node* oldChild);
@@ -1172,7 +1136,7 @@ private:
String encoding() const;
- void updateTitle(const String& title);
+ void updateTitle(const StringWithDirection&);
void updateFocusAppearanceTimerFired(Timer<Document>*);
void updateBaseURL();
@@ -1184,6 +1148,8 @@ private:
void loadEventDelayTimerFired(Timer<Document>*);
+ int m_guardRefCount;
+
OwnPtr<CSSStyleSelector> m_styleSelector;
bool m_didCalculateStyleSelector;
bool m_hasDirtyStyleSelector;
@@ -1312,8 +1278,8 @@ private:
// http://www.whatwg.org/specs/web-apps/current-work/#ignore-destructive-writes-counter
unsigned m_ignoreDestructiveWriteCount;
- String m_title;
- String m_rawTitle;
+ StringWithDirection m_title;
+ StringWithDirection m_rawTitle;
bool m_titleSetExplicitly;
RefPtr<Element> m_titleElement;
@@ -1344,8 +1310,6 @@ private:
RefPtr<Document> m_transformSourceDocument;
#endif
- DocumentOrderedMap m_imageMapsByName;
-
int m_docID; // A unique document identifier used for things like document-specific mapped attributes.
String m_xmlEncoding;
@@ -1362,14 +1326,8 @@ private:
RefPtr<TextResourceDecoder> m_decoder;
- DocumentOrderedMap m_elementsById;
-
- mutable HashMap<StringImpl*, Element*, CaseFoldingHash> m_elementsByAccessKey;
-
InheritedBool m_designMode;
- int m_selfOnlyRefCount;
-
CheckedRadioButtons m_checkedRadioButtons;
typedef HashMap<AtomicStringImpl*, CollectionCache*> NamedCollectionMap;
@@ -1392,7 +1350,6 @@ private:
HashMap<String, RefPtr<HTMLCanvasElement> > m_cssCanvasElements;
- mutable bool m_accessKeyMapValid;
bool m_createRenderers;
bool m_inPageCache;
String m_iconURL;
@@ -1409,13 +1366,6 @@ private:
bool m_usesViewSourceStyles;
bool m_sawElementsInKnownNamespaces;
- unsigned m_numNodeListCaches;
-
-#if USE(JSC)
- JSWrapperCacheMap m_wrapperCacheMap;
- JSWrapperCache* m_normalWorldWrapperCache;
-#endif
-
bool m_usingGeolocation;
RefPtr<EventQueue> m_eventQueue;
@@ -1431,7 +1381,6 @@ private:
QualifiedName m_idAttributeName;
#if ENABLE(FULLSCREEN_API)
- bool m_isFullScreen;
bool m_areKeysEnabledInFullScreen;
RefPtr<Element> m_fullScreenElement;
RenderFullScreen* m_fullScreenRenderer;
@@ -1458,23 +1407,13 @@ private:
RefPtr<ContentSecurityPolicy> m_contentSecurityPolicy;
};
-inline bool Document::hasElementWithId(AtomicStringImpl* id) const
-{
- ASSERT(id);
- return m_elementsById.contains(id);
-}
+// Put these methods here, because they require the Document definition, but we really want to inline them.
-inline bool Document::containsMultipleElementsWithId(const AtomicString& id) const
-{
- return m_elementsById.containsMultiple(id.impl());
-}
-
inline bool Node::isDocumentNode() const
{
return this == m_document;
}
-// here because it uses a Document method but we really want to inline it
inline Node::Node(Document* document, ConstructionType type)
: m_document(document)
, m_previous(0)
@@ -1483,7 +1422,7 @@ inline Node::Node(Document* document, ConstructionType type)
, m_nodeFlags(type)
{
if (m_document)
- m_document->selfOnlyRef();
+ m_document->guardRef();
#if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS)
trackForDebugging();
#endif
diff --git a/Source/WebCore/dom/Document.idl b/Source/WebCore/dom/Document.idl
index 11d6678..cf820ba 100644
--- a/Source/WebCore/dom/Document.idl
+++ b/Source/WebCore/dom/Document.idl
@@ -29,7 +29,7 @@ module core {
// DOM Level 1 Core
readonly attribute DocumentType doctype;
- readonly attribute [V8Custom] DOMImplementation implementation;
+ readonly attribute DOMImplementation implementation;
readonly attribute Element documentElement;
[ReturnsNew] Element createElement(in [ConvertNullToNullString] DOMString tagName)
@@ -266,8 +266,6 @@ module core {
attribute [DontEnum] EventListener ondrop;
attribute [DontEnum] EventListener onerror;
attribute [DontEnum] EventListener onfocus;
- attribute [DontEnum] EventListener onformchange;
- attribute [DontEnum] EventListener onforminput;
attribute [DontEnum] EventListener oninput;
attribute [DontEnum] EventListener oninvalid;
attribute [DontEnum] EventListener onkeydown;
diff --git a/Source/WebCore/dom/DocumentFragment.cpp b/Source/WebCore/dom/DocumentFragment.cpp
index c9c3020..3882c4d 100644
--- a/Source/WebCore/dom/DocumentFragment.cpp
+++ b/Source/WebCore/dom/DocumentFragment.cpp
@@ -31,7 +31,7 @@
namespace WebCore {
-inline DocumentFragment::DocumentFragment(Document* document)
+DocumentFragment::DocumentFragment(Document* document)
: ContainerNode(document)
{
ASSERT(document);
@@ -52,7 +52,7 @@ Node::NodeType DocumentFragment::nodeType() const
return DOCUMENT_FRAGMENT_NODE;
}
-bool DocumentFragment::childTypeAllowed(NodeType type)
+bool DocumentFragment::childTypeAllowed(NodeType type) const
{
switch (type) {
case ELEMENT_NODE:
diff --git a/Source/WebCore/dom/DocumentFragment.h b/Source/WebCore/dom/DocumentFragment.h
index d588b4e..b035a64 100644
--- a/Source/WebCore/dom/DocumentFragment.h
+++ b/Source/WebCore/dom/DocumentFragment.h
@@ -36,13 +36,14 @@ public:
void parseHTML(const String&, Element* contextElement, FragmentScriptingPermission = FragmentScriptingAllowed);
bool parseXML(const String&, Element* contextElement, FragmentScriptingPermission = FragmentScriptingAllowed);
-private:
+protected:
DocumentFragment(Document*);
-
virtual String nodeName() const;
+
+private:
virtual NodeType nodeType() const;
virtual PassRefPtr<Node> cloneNode(bool deep);
- virtual bool childTypeAllowed(NodeType);
+ virtual bool childTypeAllowed(NodeType) const;
};
} //namespace
diff --git a/Source/WebCore/dom/DocumentMarker.h b/Source/WebCore/dom/DocumentMarker.h
index 81112bf..1711a96 100644
--- a/Source/WebCore/dom/DocumentMarker.h
+++ b/Source/WebCore/dom/DocumentMarker.h
@@ -37,9 +37,9 @@ struct DocumentMarker {
Spelling = 1 << 0,
Grammar = 1 << 1,
TextMatch = 1 << 2,
- // Text has been modified by spell correction. On some platforms, this prevents the text
- // to be autocorrected again. On post Snow Leopard Mac OS X, if a Replacement marker contains
- // non-empty description, a reversion UI will be shown.
+ // Text has been modified by spell correction, reversion of spell correction or other type of substitution.
+ // On some platforms, this prevents the text from being autocorrected again. On post Snow Leopard Mac OS X,
+ // if a Replacement marker contains non-empty description, a reversion UI will be shown.
Replacement = 1 << 3,
// Renderer needs to add underline indicating that the text has been modified by spell
// correction. Text with Replacement marker doesn't necessarily has CorrectionIndicator
@@ -49,12 +49,37 @@ struct DocumentMarker {
CorrectionIndicator = 1 << 4,
// Correction suggestion has been offered, but got rejected by user.
RejectedCorrection = 1 << 5,
- // On some platforms, this prevents the text to be spellchecked again.
- SpellCheckingExemption = 1 << 6,
- AllMarkers = Spelling | Grammar | TextMatch | Replacement | CorrectionIndicator | RejectedCorrection | SpellCheckingExemption
+ // Text has been modified by autocorrection. The description of this marker is the original text before autocorrection.
+ Autocorrected = 1 << 6,
+ // On some platforms, this prevents the text from being spellchecked again.
+ SpellCheckingExemption = 1 << 7,
};
+
+ class MarkerTypes {
+ public:
+ // The constructor is intentionally implicit to allow conversion from the bit-wise sum of above types
+ MarkerTypes(unsigned mask) : m_mask(mask) { }
+
+ bool contains(MarkerType type) const { return m_mask & type; }
+ bool intersects(const MarkerTypes& types) const { return (m_mask & types.m_mask); }
+ bool operator==(const MarkerTypes& other) const { return m_mask == other.m_mask; }
+
+ void add(const MarkerTypes& types) { m_mask |= types.m_mask; }
+ void remove(const MarkerTypes& types) { m_mask &= ~types.m_mask; }
+
+ private:
+ unsigned m_mask;
+ };
+
+ class AllMarkers : public MarkerTypes {
+ public:
+ AllMarkers()
+ : MarkerTypes(Spelling | Grammar | TextMatch | Replacement | CorrectionIndicator | RejectedCorrection | Autocorrected | SpellCheckingExemption)
+ {
+ }
+ };
+
MarkerType type;
- typedef unsigned MarkerTypes;
unsigned startOffset;
unsigned endOffset;
String description;
diff --git a/Source/WebCore/dom/DocumentMarkerController.cpp b/Source/WebCore/dom/DocumentMarkerController.cpp
index f646f3c..d97f2af 100644
--- a/Source/WebCore/dom/DocumentMarkerController.cpp
+++ b/Source/WebCore/dom/DocumentMarkerController.cpp
@@ -40,7 +40,7 @@ static IntRect placeholderRectForMarker()
inline bool DocumentMarkerController::possiblyHasMarkers(DocumentMarker::MarkerTypes types)
{
- return m_possiblyExistingMarkerTypes & types;
+ return m_possiblyExistingMarkerTypes.intersects(types);
}
DocumentMarkerController::DocumentMarkerController()
@@ -91,7 +91,7 @@ void DocumentMarkerController::addMarker(Node* node, DocumentMarker newMarker)
if (newMarker.endOffset == newMarker.startOffset)
return;
- m_possiblyExistingMarkerTypes |= newMarker.type;
+ m_possiblyExistingMarkerTypes.add(newMarker.type);
MarkerMapVectorPair* vectorPair = m_markers.get(node);
@@ -152,12 +152,12 @@ void DocumentMarkerController::addMarker(Node* node, DocumentMarker newMarker)
// copies markers from srcNode to dstNode, applying the specified shift delta to the copies. The shift is
// useful if, e.g., the caller has created the dstNode from a non-prefix substring of the srcNode.
-void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta, DocumentMarker::MarkerType markerType)
+void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta)
{
if (length <= 0)
return;
- if (!possiblyHasMarkers(markerType))
+ if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
return;
ASSERT(!m_markers.isEmpty());
@@ -178,7 +178,7 @@ void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset,
break;
// skip marker that is before the specified range or is the wrong type
- if (marker.endOffset < startOffset || (marker.type != markerType && markerType != DocumentMarker::AllMarkers))
+ if (marker.endOffset < startOffset)
continue;
// pin the marker to the specified range and apply the shift delta
@@ -224,7 +224,7 @@ void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, i
break;
// skip marker that is wrong type or before target
- if (marker.endOffset <= startOffset || !(marker.type & markerTypes)) {
+ if (marker.endOffset <= startOffset || !markerTypes.contains(marker.type)) {
i++;
continue;
}
@@ -292,7 +292,7 @@ DocumentMarker* DocumentMarkerController::markerContainingPoint(const IntPoint&
DocumentMarker& marker = markers[markerIndex];
// skip marker that is wrong type
- if (marker.type != markerType && markerType != DocumentMarker::AllMarkers)
+ if (marker.type != markerType)
continue;
IntRect& r = rects[markerIndex];
@@ -317,6 +317,35 @@ Vector<DocumentMarker> DocumentMarkerController::markersForNode(Node* node)
return Vector<DocumentMarker>();
}
+Vector<DocumentMarker> DocumentMarkerController::markersInRange(Range* range, DocumentMarker::MarkerType markerType)
+{
+ if (!possiblyHasMarkers(markerType))
+ return Vector<DocumentMarker>();
+
+ Vector<DocumentMarker> foundMarkers;
+
+ Node* startContainer = range->startContainer();
+ ASSERT(startContainer);
+ Node* endContainer = range->endContainer();
+ ASSERT(endContainer);
+
+ Node* pastLastNode = range->pastLastNode();
+ for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) {
+ Vector<DocumentMarker> markers = markersForNode(node);
+ Vector<DocumentMarker>::const_iterator end = markers.end();
+ for (Vector<DocumentMarker>::const_iterator it = markers.begin(); it != end; ++it) {
+ if (markerType != it->type)
+ continue;
+ if (node == startContainer && it->endOffset <= static_cast<unsigned>(range->startOffset()))
+ continue;
+ if (node == endContainer && it->startOffset >= static_cast<unsigned>(range->endOffset()))
+ continue;
+ foundMarkers.append(*it);
+ }
+ }
+ return foundMarkers;
+}
+
Vector<IntRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker::MarkerType markerType)
{
Vector<IntRect> result;
@@ -338,7 +367,7 @@ Vector<IntRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker
DocumentMarker marker = markers[markerIndex];
// skip marker that is wrong type
- if (marker.type != markerType && markerType != DocumentMarker::AllMarkers)
+ if (marker.type != markerType)
continue;
IntRect r = rects[markerIndex];
@@ -379,13 +408,13 @@ void DocumentMarkerController::removeMarkers(DocumentMarker::MarkerTypes markerT
removeMarkersFromMarkerMapVectorPair(node, vectorPair, markerTypes);
}
- m_possiblyExistingMarkerTypes &= ~markerTypes;
+ m_possiblyExistingMarkerTypes.remove(markerTypes);
}
// This function may release node and vectorPair.
void DocumentMarkerController::removeMarkersFromMarkerMapVectorPair(Node* node, MarkerMapVectorPair* vectorPair, DocumentMarker::MarkerTypes markerTypes)
{
- if (!~(markerTypes & DocumentMarker::AllMarkers)) {
+ if (markerTypes == DocumentMarker::AllMarkers()) {
delete vectorPair;
m_markers.remove(node);
if (RenderObject* renderer = node->renderer())
@@ -399,7 +428,7 @@ void DocumentMarkerController::removeMarkersFromMarkerMapVectorPair(Node* node,
DocumentMarker marker = markers[i];
// skip nodes that are not of the specified type
- if (!(marker.type & markerTypes)) {
+ if (!markerTypes.contains(marker.type)) {
++i;
continue;
}
@@ -430,9 +459,9 @@ void DocumentMarkerController::removeMarkersFromMarkerMapVectorPair(Node* node,
m_possiblyExistingMarkerTypes = 0;
}
-void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerType markerType)
+void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes markerTypes)
{
- if (!possiblyHasMarkers(markerType))
+ if (!possiblyHasMarkers(markerTypes))
return;
ASSERT(!m_markers.isEmpty());
@@ -449,7 +478,7 @@ void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerType markerT
DocumentMarker marker = markers[i];
// skip nodes that are not of the specified type
- if (marker.type == markerType || markerType == DocumentMarker::AllMarkers) {
+ if (markerTypes.contains(marker.type)) {
nodeNeedsRepaint = true;
break;
}
@@ -503,9 +532,9 @@ void DocumentMarkerController::invalidateRenderedRectsForMarkersInRect(const Int
}
}
-void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, int delta, DocumentMarker::MarkerType markerType)
+void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, int delta)
{
- if (!possiblyHasMarkers(markerType))
+ if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
return;
ASSERT(!m_markers.isEmpty());
@@ -520,7 +549,7 @@ void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, in
bool docDirty = false;
for (size_t i = 0; i != markers.size(); ++i) {
DocumentMarker& marker = markers[i];
- if (marker.startOffset >= startOffset && (markerType == DocumentMarker::AllMarkers || marker.type == markerType)) {
+ if (marker.startOffset >= startOffset) {
ASSERT((int)marker.startOffset + delta >= 0);
marker.startOffset += delta;
marker.endOffset += delta;
@@ -538,7 +567,7 @@ void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, in
void DocumentMarkerController::setMarkersActive(Range* range, bool active)
{
- if (!possiblyHasMarkers(DocumentMarker::AllMarkers))
+ if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
return;
ASSERT(!m_markers.isEmpty());
@@ -600,22 +629,13 @@ bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTy
Vector<DocumentMarker> markers = markersForNode(node);
Vector<DocumentMarker>::const_iterator end = markers.end();
for (Vector<DocumentMarker>::const_iterator it = markers.begin(); it != end; ++it) {
- if (!(markerTypes & it->type))
+ if (!markerTypes.contains(it->type))
continue;
- if (node == startContainer && node == endContainer) {
- // The range spans only one node.
- if (it->endOffset > static_cast<unsigned>(range->startOffset()) && it->startOffset < static_cast<unsigned>(range->endOffset()))
- return true;
- } else {
- if (node == startContainer) {
- if (it->endOffset > static_cast<unsigned>(range->startOffset()))
- return true;
- } else if (node == endContainer) {
- if (it->startOffset < static_cast<unsigned>(range->endOffset()))
- return true;
- } else
- return true;
- }
+ if (node == startContainer && it->endOffset <= static_cast<unsigned>(range->startOffset()))
+ continue;
+ if (node == endContainer && it->startOffset >= static_cast<unsigned>(range->endOffset()))
+ continue;
+ return true;
}
}
return false;
@@ -647,7 +667,7 @@ void DocumentMarkerController::clearDescriptionOnMarkersIntersectingRange(Range*
break;
// skip marker that is wrong type or before target
- if (marker.endOffset <= startOffset || !(marker.type & markerTypes)) {
+ if (marker.endOffset <= startOffset || !markerTypes.contains(marker.type)) {
i++;
continue;
}
diff --git a/Source/WebCore/dom/DocumentMarkerController.h b/Source/WebCore/dom/DocumentMarkerController.h
index 6fa060a..0f34c9f 100644
--- a/Source/WebCore/dom/DocumentMarkerController.h
+++ b/Source/WebCore/dom/DocumentMarkerController.h
@@ -47,28 +47,29 @@ public:
void detach();
void addMarker(Range*, DocumentMarker::MarkerType, String description = String());
void addMarker(Node*, DocumentMarker);
- void copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta, DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
- bool hasMarkers(Range*, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers);
+ void copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta);
+ bool hasMarkers(Range*, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers());
// When a marker partially overlaps with range, if removePartiallyOverlappingMarkers is true, we completely
// remove the marker. If the argument is false, we will adjust the span of the marker so that it retains
// the portion that is outside of the range.
enum RemovePartiallyOverlappingMarkerOrNot { DoNotRemovePartiallyOverlappingMarker, RemovePartiallyOverlappingMarker };
- void removeMarkers(Range*, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers, RemovePartiallyOverlappingMarkerOrNot = DoNotRemovePartiallyOverlappingMarker);
- void removeMarkers(Node*, unsigned startOffset, int length, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers, RemovePartiallyOverlappingMarkerOrNot = DoNotRemovePartiallyOverlappingMarker);
+ void removeMarkers(Range*, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers(), RemovePartiallyOverlappingMarkerOrNot = DoNotRemovePartiallyOverlappingMarker);
+ void removeMarkers(Node*, unsigned startOffset, int length, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers(), RemovePartiallyOverlappingMarkerOrNot = DoNotRemovePartiallyOverlappingMarker);
- void removeMarkers(DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers);
- void removeMarkers(Node*, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers);
- void repaintMarkers(DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
+ void removeMarkers(DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers());
+ void removeMarkers(Node*, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers());
+ void repaintMarkers(DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers());
void setRenderedRectForMarker(Node*, const DocumentMarker&, const IntRect&);
void invalidateRenderedRectsForMarkersInRect(const IntRect&);
- void shiftMarkers(Node*, unsigned startOffset, int delta, DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
+ void shiftMarkers(Node*, unsigned startOffset, int delta);
void setMarkersActive(Range*, bool);
void setMarkersActive(Node*, unsigned startOffset, unsigned endOffset, bool);
- DocumentMarker* markerContainingPoint(const IntPoint&, DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
+ DocumentMarker* markerContainingPoint(const IntPoint&, DocumentMarker::MarkerType);
Vector<DocumentMarker> markersForNode(Node*);
- Vector<IntRect> renderedRectsForMarkers(DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
+ Vector<DocumentMarker> markersInRange(Range*, DocumentMarker::MarkerType);
+ Vector<IntRect> renderedRectsForMarkers(DocumentMarker::MarkerType);
void clearDescriptionOnMarkersIntersectingRange(Range*, DocumentMarker::MarkerTypes);
#ifndef NDEBUG
diff --git a/Source/WebCore/dom/DocumentOrderedMap.cpp b/Source/WebCore/dom/DocumentOrderedMap.cpp
index 787fcf4..47268c4 100644
--- a/Source/WebCore/dom/DocumentOrderedMap.cpp
+++ b/Source/WebCore/dom/DocumentOrderedMap.cpp
@@ -34,6 +34,7 @@
#include "Element.h"
#include "HTMLMapElement.h"
#include "HTMLNames.h"
+#include "TreeScope.h"
namespace WebCore {
@@ -104,7 +105,7 @@ void DocumentOrderedMap::remove(AtomicStringImpl* key, Element* element)
}
template<bool keyMatches(AtomicStringImpl*, Element*)>
-inline Element* DocumentOrderedMap::get(AtomicStringImpl* key, const Document* document) const
+inline Element* DocumentOrderedMap::get(AtomicStringImpl* key, const TreeScope* scope) const
{
ASSERT(key);
@@ -116,7 +117,7 @@ inline Element* DocumentOrderedMap::get(AtomicStringImpl* key, const Document* d
if (m_duplicateCounts.contains(key)) {
// We know there's at least one node that matches; iterate to find the first one.
- for (Node* node = document->firstChild(); node; node = node->traverseNextNode()) {
+ for (Node* node = scope->firstChild(); node; node = node->traverseNextNode()) {
if (!node->isElementNode())
continue;
element = static_cast<Element*>(node);
@@ -132,19 +133,19 @@ inline Element* DocumentOrderedMap::get(AtomicStringImpl* key, const Document* d
return 0;
}
-Element* DocumentOrderedMap::getElementById(AtomicStringImpl* key, const Document* document) const
+Element* DocumentOrderedMap::getElementById(AtomicStringImpl* key, const TreeScope* scope) const
{
- return get<keyMatchesId>(key, document);
+ return get<keyMatchesId>(key, scope);
}
-Element* DocumentOrderedMap::getElementByMapName(AtomicStringImpl* key, const Document* document) const
+Element* DocumentOrderedMap::getElementByMapName(AtomicStringImpl* key, const TreeScope* scope) const
{
- return get<keyMatchesMapName>(key, document);
+ return get<keyMatchesMapName>(key, scope);
}
-Element* DocumentOrderedMap::getElementByLowercasedMapName(AtomicStringImpl* key, const Document* document) const
+Element* DocumentOrderedMap::getElementByLowercasedMapName(AtomicStringImpl* key, const TreeScope* scope) const
{
- return get<keyMatchesLowercasedMapName>(key, document);
+ return get<keyMatchesLowercasedMapName>(key, scope);
}
} // namespace WebCore
diff --git a/Source/WebCore/dom/DocumentOrderedMap.h b/Source/WebCore/dom/DocumentOrderedMap.h
index 58767c6..7d12686 100644
--- a/Source/WebCore/dom/DocumentOrderedMap.h
+++ b/Source/WebCore/dom/DocumentOrderedMap.h
@@ -37,8 +37,8 @@
namespace WebCore {
-class Document;
class Element;
+class TreeScope;
class DocumentOrderedMap {
public:
@@ -49,14 +49,14 @@ public:
bool contains(AtomicStringImpl*) const;
bool containsMultiple(AtomicStringImpl*) const;
// concrete instantiations of the get<>() method template
- Element* getElementById(AtomicStringImpl*, const Document*) const;
- Element* getElementByMapName(AtomicStringImpl*, const Document*) const;
- Element* getElementByLowercasedMapName(AtomicStringImpl*, const Document*) const;
+ Element* getElementById(AtomicStringImpl*, const TreeScope*) const;
+ Element* getElementByMapName(AtomicStringImpl*, const TreeScope*) const;
+ Element* getElementByLowercasedMapName(AtomicStringImpl*, const TreeScope*) const;
void checkConsistency() const;
private:
- template<bool keyMatches(AtomicStringImpl*, Element*)> Element* get(AtomicStringImpl*, const Document*) const;
+ template<bool keyMatches(AtomicStringImpl*, Element*)> Element* get(AtomicStringImpl*, const TreeScope*) const;
typedef HashMap<AtomicStringImpl*, Element*> Map;
diff --git a/Source/WebCore/dom/DynamicNodeList.cpp b/Source/WebCore/dom/DynamicNodeList.cpp
index 3538b60..23664e8 100644
--- a/Source/WebCore/dom/DynamicNodeList.cpp
+++ b/Source/WebCore/dom/DynamicNodeList.cpp
@@ -145,6 +145,11 @@ Node* DynamicNodeList::itemWithName(const AtomicString& elementId) const
return 0;
}
+bool DynamicNodeList::isDynamicNodeList() const
+{
+ return true;
+}
+
void DynamicNodeList::invalidateCache()
{
// This should only be called for node lists that own their own caches.
diff --git a/Source/WebCore/dom/DynamicNodeList.h b/Source/WebCore/dom/DynamicNodeList.h
index db133b7..9c8f3cc 100644
--- a/Source/WebCore/dom/DynamicNodeList.h
+++ b/Source/WebCore/dom/DynamicNodeList.h
@@ -60,6 +60,7 @@ namespace WebCore {
// Other methods (not part of DOM)
void invalidateCache();
+ Node* rootNode() const { return m_rootNode.get(); }
protected:
DynamicNodeList(PassRefPtr<Node> rootNode);
@@ -72,6 +73,7 @@ namespace WebCore {
bool m_ownsCaches;
private:
+ virtual bool isDynamicNodeList() const;
Node* itemForwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const;
Node* itemBackwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const;
};
diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp
index 81668cf..50431aa 100644
--- a/Source/WebCore/dom/Element.cpp
+++ b/Source/WebCore/dom/Element.cpp
@@ -54,6 +54,7 @@
#include "RenderView.h"
#include "RenderWidget.h"
#include "Settings.h"
+#include "ShadowRoot.h"
#include "TextIterator.h"
#include "WebKitAnimationList.h"
#include "XMLNames.h"
@@ -543,11 +544,19 @@ PassRefPtr<ClientRectList> Element::getClientRects() const
Vector<FloatQuad> quads;
renderBoxModelObject->absoluteQuads(quads);
+ float pageScale = 1;
+ if (Page* page = document()->page()) {
+ if (Frame* frame = page->mainFrame())
+ pageScale = frame->pageScaleFactor();
+ }
+
if (FrameView* view = document()->view()) {
IntRect visibleContentRect = view->visibleContentRect();
for (size_t i = 0; i < quads.size(); ++i) {
quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
adjustFloatQuadForAbsoluteZoom(quads[i], renderBoxModelObject);
+ if (pageScale != 1)
+ adjustFloatQuadForPageScale(quads[i], pageScale);
}
}
@@ -587,6 +596,11 @@ PassRefPtr<ClientRect> Element::getBoundingClientRect() const
}
adjustFloatRectForAbsoluteZoom(result, renderer());
+ if (Page* page = document()->page()) {
+ if (Frame* frame = page->mainFrame())
+ adjustFloatRectForPageScale(result, frame->pageScaleFactor());
+ }
+
return ClientRect::create(result);
}
@@ -643,22 +657,20 @@ void Element::setAttribute(const AtomicString& name, const AtomicString& value,
#endif
const AtomicString& localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
-
+ QualifiedName attributeName(nullAtom, localName, nullAtom);
+
// Allocate attribute map if necessary.
Attribute* old = attributes(false)->getAttributeItem(localName, false);
document()->incDOMTreeVersion();
- // FIXME: This check is probably not correct for the case where the document has an id attribute
- // with a non-null namespace, because it will return true if the local name happens to match
- // but the namespace does not.
- if (localName == document()->idAttributeName().localName())
+ if (isIdAttributeName(old ? old->name() : attributeName))
updateId(old ? old->value() : nullAtom, value);
if (old && value.isNull())
m_attributeMap->removeAttribute(old->name());
else if (!old && !value.isNull())
- m_attributeMap->addAttribute(createAttribute(QualifiedName(nullAtom, localName, nullAtom), value));
+ m_attributeMap->addAttribute(createAttribute(attributeName, value));
else if (old && !value.isNull()) {
if (Attr* attrNode = old->attr())
attrNode->setValue(value);
@@ -713,6 +725,8 @@ PassRefPtr<Attribute> Element::createAttribute(const QualifiedName& name, const
void Element::attributeChanged(Attribute* attr, bool)
{
+ if (isIdAttributeName(attr->name()))
+ idAttributeChanged(attr);
recalcStyleIfNeededAfterAttributeChanged(attr);
updateAfterAttributeChanged(attr);
}
@@ -751,6 +765,20 @@ void Element::recalcStyleIfNeededAfterAttributeChanged(Attribute* attr)
setNeedsStyleRecalc();
}
+void Element::idAttributeChanged(Attribute* attr)
+{
+ setHasID(!attr->isNull());
+ if (attributeMap()) {
+ if (attr->isNull())
+ attributeMap()->setIdForStyleResolution(nullAtom);
+ else if (document()->inQuirksMode())
+ attributeMap()->setIdForStyleResolution(attr->value().lower());
+ else
+ attributeMap()->setIdForStyleResolution(attr->value());
+ }
+ setNeedsStyleRecalc();
+}
+
// Returns true is the given attribute is an event handler.
// We consider an event handler any attribute that begins with "on".
// It is a simple solution that has the advantage of not requiring any
@@ -957,13 +985,16 @@ void Element::attach()
createRendererIfNeeded();
StyleSelectorParentPusher parentPusher(this);
- if (firstChild())
- parentPusher.push();
- ContainerNode::attach();
+
if (Node* shadow = shadowRoot()) {
parentPusher.push();
shadow->attach();
}
+
+ if (firstChild())
+ parentPusher.push();
+ ContainerNode::attach();
+
if (hasRareData()) {
ElementRareData* data = rareData();
if (data->needsFocusAppearanceUpdateSoonAfterAttach()) {
@@ -1047,7 +1078,7 @@ void Element::recalcStyle(StyleChange change)
{
// Ref currentStyle in case it would otherwise be deleted when setRenderStyle() is called.
RefPtr<RenderStyle> currentStyle(renderStyle());
- bool hasParentStyle = parentOrHostNode() ? parentOrHostNode()->renderStyle() : false;
+ bool hasParentStyle = parentNodeForRenderingAndStyle() ? parentNodeForRenderingAndStyle()->renderStyle() : false;
bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules();
if ((change > NoChange || needsStyleRecalc())) {
@@ -1134,7 +1165,7 @@ void Element::recalcStyle(StyleChange change)
}
// FIXME: This does not care about sibling combinators. Will be necessary in XBL2 world.
if (Node* shadow = shadowRoot()) {
- if (change >= Inherit || shadow->isTextNode() || shadow->childNeedsStyleRecalc() || shadow->needsStyleRecalc()) {
+ if (change >= Inherit || shadow->childNeedsStyleRecalc() || shadow->needsStyleRecalc()) {
parentPusher.push();
shadow->recalcStyle(change);
}
@@ -1144,28 +1175,24 @@ void Element::recalcStyle(StyleChange change)
clearChildNeedsStyleRecalc();
}
-Node* Element::shadowRoot()
+ContainerNode* Element::shadowRoot() const
{
return hasRareData() ? rareData()->m_shadowRoot : 0;
}
-void Element::setShadowRoot(PassRefPtr<Node> node)
+ContainerNode* Element::ensureShadowRoot()
{
- // FIXME: Because today this is never called from script directly, we don't have to worry
- // about compromising DOM tree integrity (eg. node being a parent of this). However,
- // once we implement XBL2, we will have to add integrity checks here.
- removeShadowRoot();
-
- RefPtr<Node> newRoot = node;
- if (!newRoot)
- return;
+ if (ContainerNode* existingRoot = shadowRoot())
+ return existingRoot;
+ RefPtr<ShadowRoot> newRoot = ShadowRoot::create(document());
ensureRareData()->m_shadowRoot = newRoot.get();
newRoot->setShadowHost(this);
if (inDocument())
newRoot->insertedIntoDocument();
- if (attached() && !newRoot->attached())
+ if (attached())
newRoot->lazyAttach();
+ return newRoot.get();
}
void Element::removeShadowRoot()
@@ -1185,7 +1212,7 @@ void Element::removeShadowRoot()
}
}
-bool Element::childTypeAllowed(NodeType type)
+bool Element::childTypeAllowed(NodeType type) const
{
switch (type) {
case ELEMENT_NODE:
diff --git a/Source/WebCore/dom/Element.h b/Source/WebCore/dom/Element.h
index ba0870c..d269dbe 100644
--- a/Source/WebCore/dom/Element.h
+++ b/Source/WebCore/dom/Element.h
@@ -64,8 +64,6 @@ public:
DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(formchange);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(forminput);
DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
@@ -231,8 +229,10 @@ public:
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
virtual void recalcStyle(StyleChange = NoChange);
- Node* shadowRoot();
- void setShadowRoot(PassRefPtr<Node>);
+ ContainerNode* shadowRoot() const;
+ ContainerNode* ensureShadowRoot();
+ void removeShadowRoot();
+
virtual const AtomicString& shadowPseudoId() const;
RenderStyle* computedStyle(PseudoId = NOPSEUDO);
@@ -303,6 +303,10 @@ public:
static bool isMathMLElement() { return false; }
#endif
+#if ENABLE(INPUT_SPEECH)
+ virtual bool isInputFieldSpeechButtonElement() const { return false; }
+#endif
+
virtual bool isFormControlElement() const { return false; }
virtual bool isEnabledFormControl() const { return true; }
virtual bool isReadOnlyFormControl() const { return false; }
@@ -364,13 +368,15 @@ protected:
// They are separated to allow a different flow of control in StyledElement::attributeChanged().
void recalcStyleIfNeededAfterAttributeChanged(Attribute*);
void updateAfterAttributeChanged(Attribute*);
+
+ void idAttributeChanged(Attribute*);
private:
void scrollByUnits(int units, ScrollGranularity);
virtual void setPrefix(const AtomicString&, ExceptionCode&);
virtual NodeType nodeType() const;
- virtual bool childTypeAllowed(NodeType);
+ virtual bool childTypeAllowed(NodeType) const;
virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value);
@@ -407,7 +413,6 @@ private:
ElementRareData* ensureRareData();
SpellcheckAttributeState spellcheckAttributeState() const;
- void removeShadowRoot();
private:
mutable RefPtr<NamedNodeMap> m_attributeMap;
diff --git a/Source/WebCore/dom/Element.idl b/Source/WebCore/dom/Element.idl
index fc28642..0e91811 100644
--- a/Source/WebCore/dom/Element.idl
+++ b/Source/WebCore/dom/Element.idl
@@ -155,8 +155,6 @@ module core {
attribute [DontEnum] EventListener ondrop;
attribute [DontEnum] EventListener onerror;
attribute [DontEnum] EventListener onfocus;
- attribute [DontEnum] EventListener onformchange;
- attribute [DontEnum] EventListener onforminput;
attribute [DontEnum] EventListener oninput;
attribute [DontEnum] EventListener oninvalid;
attribute [DontEnum] EventListener onkeydown;
diff --git a/Source/WebCore/dom/ElementRareData.h b/Source/WebCore/dom/ElementRareData.h
index 818a2c2..14ceef2 100644
--- a/Source/WebCore/dom/ElementRareData.h
+++ b/Source/WebCore/dom/ElementRareData.h
@@ -30,6 +30,8 @@
namespace WebCore {
+class ShadowRoot;
+
class ElementRareData : public NodeRareData {
public:
ElementRareData();
@@ -42,7 +44,7 @@ public:
IntSize m_minimumSizeForResizing;
RefPtr<RenderStyle> m_computedStyle;
- Node* m_shadowRoot;
+ ShadowRoot* m_shadowRoot;
OwnPtr<DatasetDOMStringMap> m_datasetDOMStringMap;
OwnPtr<ClassList> m_classList;
diff --git a/Source/WebCore/dom/Event.cpp b/Source/WebCore/dom/Event.cpp
index a1352dc..9cb2778 100644
--- a/Source/WebCore/dom/Event.cpp
+++ b/Source/WebCore/dom/Event.cpp
@@ -229,6 +229,11 @@ bool Event::isAudioProcessingEvent() const
{
return false;
}
+
+bool Event::isOfflineAudioCompletionEvent() const
+{
+ return false;
+}
#endif
#if ENABLE(INPUT_SPEECH)
@@ -259,7 +264,7 @@ bool Event::fromUserGesture()
// other accepted events
|| type == eventNames().selectEvent || type == eventNames().changeEvent
|| type == eventNames().focusEvent || type == eventNames().blurEvent
- || type == eventNames().submitEvent || type == eventNames().formchangeEvent;
+ || type == eventNames().submitEvent;
}
bool Event::storesResultAsString() const
@@ -271,11 +276,6 @@ void Event::storeResult(const String&)
{
}
-bool Event::dispatch(EventDispatcher* dispatcher)
-{
- return dispatcher->dispatchEvent(this);
-}
-
void Event::setTarget(PassRefPtr<EventTarget> target)
{
if (m_target == target)
@@ -299,4 +299,18 @@ void Event::setUnderlyingEvent(PassRefPtr<Event> ue)
m_underlyingEvent = ue;
}
+EventDispatchMediator::EventDispatchMediator(PassRefPtr<Event> event)
+ : m_event(event)
+{
+}
+
+EventDispatchMediator::~EventDispatchMediator()
+{
+}
+
+bool EventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
+{
+ return dispatcher->dispatchEvent(m_event.get());
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/dom/Event.h b/Source/WebCore/dom/Event.h
index d4d7e06..f6e5586 100644
--- a/Source/WebCore/dom/Event.h
+++ b/Source/WebCore/dom/Event.h
@@ -131,6 +131,7 @@ namespace WebCore {
#endif
#if ENABLE(WEB_AUDIO)
virtual bool isAudioProcessingEvent() const;
+ virtual bool isOfflineAudioCompletionEvent() const;
#endif
virtual bool isErrorEvent() const;
#if ENABLE(TOUCH_EVENTS)
@@ -166,7 +167,6 @@ namespace WebCore {
virtual Clipboard* clipboard() const { return 0; }
- virtual bool dispatch(EventDispatcher*);
protected:
Event();
@@ -194,6 +194,37 @@ namespace WebCore {
RefPtr<Event> m_underlyingEvent;
};
+class EventDispatchMediator {
+public:
+ explicit EventDispatchMediator(PassRefPtr<Event>);
+ virtual ~EventDispatchMediator();
+
+ virtual bool dispatchEvent(EventDispatcher*) const;
+
+protected:
+ EventDispatchMediator();
+
+ Event* event() const;
+ void setEvent(PassRefPtr<Event>);
+
+private:
+ RefPtr<Event> m_event;
+};
+
+inline EventDispatchMediator::EventDispatchMediator()
+{
+}
+
+inline Event* EventDispatchMediator::event() const
+{
+ return m_event.get();
+}
+
+inline void EventDispatchMediator::setEvent(PassRefPtr<Event> event)
+{
+ m_event = event;
+}
+
} // namespace WebCore
#endif // Event_h
diff --git a/Source/WebCore/dom/EventDispatcher.cpp b/Source/WebCore/dom/EventDispatcher.cpp
index c8b330d..ca2ed30 100644
--- a/Source/WebCore/dom/EventDispatcher.cpp
+++ b/Source/WebCore/dom/EventDispatcher.cpp
@@ -33,7 +33,6 @@
#include "InspectorInstrumentation.h"
#include "MouseEvent.h"
#include "Node.h"
-#include "PlatformWheelEvent.h"
#include "ScopedEventQueue.h"
#if ENABLE(SVG)
@@ -44,7 +43,6 @@
#include "UIEvent.h"
#include "UIEventWithKeyState.h"
-#include "WheelEvent.h"
#include "WindowEventContext.h"
#include <wtf/RefPtr.h>
@@ -53,12 +51,12 @@ namespace WebCore {
static HashSet<Node*>* gNodesDispatchingSimulatedClicks = 0;
-bool EventDispatcher::dispatchEvent(Node* node, PassRefPtr<Event> prpEvent)
+bool EventDispatcher::dispatchEvent(Node* node, const EventDispatchMediator& mediator)
{
- RefPtr<Event> event = prpEvent;
+ ASSERT(!eventDispatchForbidden());
EventDispatcher dispatcher(node);
- return event->dispatch(&dispatcher);
+ return mediator.dispatchEvent(&dispatcher);
}
static EventTarget* findElementInstance(Node* referenceNode)
@@ -67,10 +65,10 @@ static EventTarget* findElementInstance(Node* 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())
+ if (!n->isSVGShadowRoot() || !n->isSVGElement())
continue;
- Element* shadowTreeParentElement = n->shadowHost();
+ Element* shadowTreeParentElement = n->svgShadowHost();
ASSERT(shadowTreeParentElement->hasTagName(SVGNames::useTag));
if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode))
@@ -124,80 +122,138 @@ void EventDispatcher::dispatchSimulatedClick(Node* node, PassRefPtr<Event> under
gNodesDispatchingSimulatedClicks->remove(node);
}
-inline static WheelEvent::Granularity granularity(const PlatformWheelEvent& event)
+static inline bool isShadowRootOrSVGShadowRoot(const Node* node)
{
- return event.granularity() == ScrollByPageWheelEvent ? WheelEvent::Page : WheelEvent::Pixel;
+ return node->isShadowRoot() || node->isSVGShadowRoot();
}
-void EventDispatcher::dispatchWheelEvent(Node* node, PlatformWheelEvent& event)
+PassRefPtr<EventTarget> EventDispatcher::adjustToShadowBoundaries(PassRefPtr<Node> relatedTarget, const Vector<Node*> relatedTargetAncestors)
{
- ASSERT(!eventDispatchForbidden());
- if (!(event.deltaX() || event.deltaY()))
- return;
+ Vector<EventContext>::const_iterator lowestCommonBoundary = m_ancestors.end();
+ // Assume divergent boundary is the relatedTarget itself (in other words, related target ancestor chain does not cross any shadow DOM boundaries).
+ Vector<Node*>::const_iterator firstDivergentBoundary = relatedTargetAncestors.begin();
+
+ Vector<EventContext>::const_iterator targetAncestor = m_ancestors.end();
+ // Walk down from the top, looking for lowest common ancestor, also monitoring shadow DOM boundaries.
+ bool diverged = false;
+ for (Vector<Node*>::const_iterator i = relatedTargetAncestors.end() - 1; i >= relatedTargetAncestors.begin(); --i) {
+ if (diverged) {
+ if (isShadowRootOrSVGShadowRoot(*i)) {
+ firstDivergentBoundary = i + 1;
+ break;
+ }
+ continue;
+ }
- EventDispatcher dispatcher(node);
+ if (targetAncestor == m_ancestors.begin()) {
+ diverged = true;
+ continue;
+ }
- if (!dispatcher.m_view)
- return;
+ targetAncestor--;
- IntPoint position = dispatcher.m_view->windowToContents(event.pos());
+ if (isShadowRootOrSVGShadowRoot(*i))
+ lowestCommonBoundary = targetAncestor;
- 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);
- }
+ if ((*i) != (*targetAncestor).node())
+ diverged = true;
}
- 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 (!diverged) {
+ // The relatedTarget is a parent or shadowHost of the target.
+ if (isShadowRootOrSVGShadowRoot(m_node.get()))
+ lowestCommonBoundary = m_ancestors.begin();
+ } else if ((*firstDivergentBoundary) == m_node.get()) {
+ // Since ancestors does not contain target itself, we must account
+ // for the possibility that target is a shadowHost of relatedTarget
+ // and thus serves as the lowestCommonBoundary.
+ // Luckily, in this case the firstDivergentBoundary is target.
+ lowestCommonBoundary = m_ancestors.begin();
+ }
- if (!dispatcher.dispatchEvent(wheelEvent) || wheelEvent->defaultHandled())
- event.accept();
+ // Trim ancestors to lowestCommonBoundary to keep events inside of the common shadow DOM subtree.
+ if (lowestCommonBoundary != m_ancestors.end())
+ m_ancestors.shrink(lowestCommonBoundary - m_ancestors.begin());
+ // Set event's related target to the first encountered shadow DOM boundary in the divergent subtree.
+ return firstDivergentBoundary != relatedTargetAncestors.begin() ? *firstDivergentBoundary : relatedTarget;
+}
+inline static bool ancestorsCrossShadowBoundaries(const Vector<EventContext>& ancestors)
+{
+ return ancestors.isEmpty() || ancestors.first().node() == ancestors.last().node();
}
// 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)
+PassRefPtr<EventTarget> EventDispatcher::adjustRelatedTarget(Event* event, PassRefPtr<EventTarget> prpRelatedTarget)
{
- Node* outermostShadowBoundary = node;
- for (Node* n = node; n; n = n->parentOrHostNode()) {
- if (n->isShadowRoot())
+ if (!prpRelatedTarget)
+ return 0;
+
+ RefPtr<Node> relatedTarget = prpRelatedTarget->toNode();
+ if (!relatedTarget)
+ return 0;
+
+ Node* target = m_node.get();
+ if (!target)
+ return prpRelatedTarget;
+
+ ensureEventAncestors(event);
+
+ // Calculate early if the common boundary is even possible by looking at
+ // ancestors size and if the retargeting has occured (indicating the presence of shadow DOM boundaries).
+ // If there are no boundaries detected, the target and related target can't have a common boundary.
+ bool noCommonBoundary = ancestorsCrossShadowBoundaries(m_ancestors);
+
+ Vector<Node*> relatedTargetAncestors;
+ Node* outermostShadowBoundary = relatedTarget.get();
+ for (Node* n = outermostShadowBoundary; n; n = n->parentOrHostNode()) {
+ if (isShadowRootOrSVGShadowRoot(n))
outermostShadowBoundary = n->parentOrHostNode();
+ if (!noCommonBoundary)
+ relatedTargetAncestors.append(n);
}
- return outermostShadowBoundary;
+
+ // Short-circuit the fast case when we know there is no need to calculate a common boundary.
+ if (noCommonBoundary)
+ return outermostShadowBoundary;
+
+ return adjustToShadowBoundaries(relatedTarget.release(), relatedTargetAncestors);
}
EventDispatcher::EventDispatcher(Node* node)
: m_node(node)
+ , m_ancestorsInitialized(false)
{
ASSERT(node);
m_view = node->document()->view();
}
-void EventDispatcher::getEventAncestors(EventTarget* originalTarget, EventDispatchBehavior behavior)
+void EventDispatcher::ensureEventAncestors(Event* event)
{
+ EventDispatchBehavior behavior = determineDispatchBehavior(event);
+
if (!m_node->inDocument())
return;
- if (ancestorsInitialized())
+ if (m_ancestorsInitialized)
return;
- EventTarget* target = originalTarget;
+ m_ancestorsInitialized = true;
+
Node* ancestor = m_node.get();
+ EventTarget* target = eventTargetRespectingSVGTargetRules(ancestor);
bool shouldSkipNextAncestor = false;
while (true) {
- if (ancestor->isShadowRoot()) {
+ bool isSVGShadowRoot = ancestor->isSVGShadowRoot();
+ if (isSVGShadowRoot || ancestor->isShadowRoot()) {
if (behavior == StayInsideShadowDOM)
return;
+#if ENABLE(SVG)
+ ancestor = isSVGShadowRoot ? ancestor->svgShadowHost() : ancestor->shadowHost();
+#else
ancestor = ancestor->shadowHost();
+#endif
if (!shouldSkipNextAncestor)
target = ancestor;
} else
@@ -208,7 +264,7 @@ void EventDispatcher::getEventAncestors(EventTarget* originalTarget, EventDispat
#if ENABLE(SVG)
// Skip SVGShadowTreeRootElement.
- shouldSkipNextAncestor = ancestor->isSVGElement() && ancestor->isShadowRoot();
+ shouldSkipNextAncestor = ancestor->isSVGShadowRoot();
if (shouldSkipNextAncestor)
continue;
#endif
@@ -226,7 +282,7 @@ bool EventDispatcher::dispatchEvent(PassRefPtr<Event> event)
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()));
+ ensureEventAncestors(event.get());
WindowEventContext windowContext(event.get(), m_node.get(), topEventContext());
@@ -309,73 +365,12 @@ doneWithDefault:
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:
diff --git a/Source/WebCore/dom/EventDispatcher.h b/Source/WebCore/dom/EventDispatcher.h
index d43127f..88e9756 100644
--- a/Source/WebCore/dom/EventDispatcher.h
+++ b/Source/WebCore/dom/EventDispatcher.h
@@ -33,6 +33,7 @@ namespace WebCore {
class Event;
class EventContext;
+class EventDispatchMediator;
class EventTarget;
class FrameView;
class Node;
@@ -47,32 +48,35 @@ enum EventDispatchBehavior {
class EventDispatcher {
public:
- static bool dispatchEvent(Node*, PassRefPtr<Event>);
+ static bool dispatchEvent(Node*, const EventDispatchMediator&);
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>);
+ PassRefPtr<EventTarget> adjustRelatedTarget(Event*, PassRefPtr<EventTarget>);
+ Node* node() const;
+
private:
EventDispatcher(Node*);
+ PassRefPtr<EventTarget> adjustToShadowBoundaries(PassRefPtr<Node> relatedTarget, const Vector<Node*> relatedTargetAncestors);
EventDispatchBehavior determineDispatchBehavior(Event*);
- void getEventAncestors(EventTarget* originalTarget, EventDispatchBehavior);
+ void ensureEventAncestors(Event*);
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;
+ bool m_ancestorsInitialized;
};
+inline Node* EventDispatcher::node() const
+{
+ return m_node.get();
+}
+
}
#endif
diff --git a/Source/WebCore/dom/EventNames.h b/Source/WebCore/dom/EventNames.h
index 12afbc4..c445a7d 100644
--- a/Source/WebCore/dom/EventNames.h
+++ b/Source/WebCore/dom/EventNames.h
@@ -67,8 +67,6 @@ namespace WebCore {
macro(focus) \
macro(focusin) \
macro(focusout) \
- macro(formchange) \
- macro(forminput) \
macro(hashchange) \
macro(input) \
macro(invalid) \
diff --git a/Source/WebCore/dom/EventQueue.cpp b/Source/WebCore/dom/EventQueue.cpp
index 8e544c1..90f3e5d 100644
--- a/Source/WebCore/dom/EventQueue.cpp
+++ b/Source/WebCore/dom/EventQueue.cpp
@@ -28,12 +28,20 @@
#include "EventQueue.h"
#include "DOMWindow.h"
+#include "Document.h"
#include "Event.h"
#include "EventNames.h"
+#include "RuntimeApplicationChecks.h"
#include "ScriptExecutionContext.h"
#include "SuspendableTimer.h"
namespace WebCore {
+
+static inline bool shouldDispatchScrollEventSynchronously(Document* document)
+{
+ ASSERT_ARG(document, document);
+ return applicationIsSafari() && (document->url().protocolIs("feed") || document->url().protocolIs("feeds"));
+}
class EventQueueTimer : public SuspendableTimer {
WTF_MAKE_NONCOPYABLE(EventQueueTimer);
@@ -71,14 +79,20 @@ void EventQueue::enqueueEvent(PassRefPtr<Event> event)
m_pendingEventTimer->startOneShot(0);
}
-void EventQueue::enqueueScrollEvent(PassRefPtr<Node> target, ScrollEventTargetType targetType)
+void EventQueue::enqueueOrDispatchScrollEvent(PassRefPtr<Node> target, ScrollEventTargetType targetType)
{
- if (!m_nodesWithQueuedScrollEvents.add(target.get()).second)
- return;
-
// Per the W3C CSSOM View Module, scroll events fired at the document should bubble, others should not.
bool canBubble = targetType == ScrollEventDocumentTarget;
RefPtr<Event> scrollEvent = Event::create(eventNames().scrollEvent, canBubble, false /* non cancelleable */);
+
+ if (shouldDispatchScrollEventSynchronously(target->document())) {
+ target->dispatchEvent(scrollEvent.release());
+ return;
+ }
+
+ if (!m_nodesWithQueuedScrollEvents.add(target.get()).second)
+ return;
+
scrollEvent->setTarget(target);
enqueueEvent(scrollEvent.release());
}
@@ -92,6 +106,12 @@ bool EventQueue::cancelEvent(Event* event)
return found;
}
+void EventQueue::cancelQueuedEvents()
+{
+ m_pendingEventTimer->stop();
+ m_queuedEvents.clear();
+}
+
void EventQueue::pendingEventTimerFired()
{
ASSERT(!m_pendingEventTimer->isActive());
diff --git a/Source/WebCore/dom/EventQueue.h b/Source/WebCore/dom/EventQueue.h
index 94b6eaf..2cb38f4 100644
--- a/Source/WebCore/dom/EventQueue.h
+++ b/Source/WebCore/dom/EventQueue.h
@@ -51,8 +51,9 @@ public:
~EventQueue();
void enqueueEvent(PassRefPtr<Event>);
- void enqueueScrollEvent(PassRefPtr<Node>, ScrollEventTargetType);
+ void enqueueOrDispatchScrollEvent(PassRefPtr<Node>, ScrollEventTargetType);
bool cancelEvent(Event*);
+ void cancelQueuedEvents();
private:
explicit EventQueue(ScriptExecutionContext*);
diff --git a/Source/WebCore/dom/EventTarget.cpp b/Source/WebCore/dom/EventTarget.cpp
index 7bd5cd6..d84d66b 100644
--- a/Source/WebCore/dom/EventTarget.cpp
+++ b/Source/WebCore/dom/EventTarget.cpp
@@ -119,6 +119,11 @@ SVGElementInstance* EventTarget::toSVGElementInstance()
#endif
#if ENABLE(WEB_AUDIO)
+AudioContext* EventTarget::toAudioContext()
+{
+ return 0;
+}
+
JavaScriptAudioNode* EventTarget::toJavaScriptAudioNode()
{
return 0;
diff --git a/Source/WebCore/dom/EventTarget.h b/Source/WebCore/dom/EventTarget.h
index 31644b7..3544ce6 100644
--- a/Source/WebCore/dom/EventTarget.h
+++ b/Source/WebCore/dom/EventTarget.h
@@ -40,6 +40,7 @@
namespace WebCore {
+ class AudioContext;
class AbstractWorker;
class DedicatedWorkerContext;
class DOMApplicationCache;
@@ -122,6 +123,7 @@ namespace WebCore {
#endif
#if ENABLE(WEB_AUDIO)
+ virtual AudioContext* toAudioContext();
virtual JavaScriptAudioNode* toJavaScriptAudioNode();
#endif
diff --git a/Source/WebCore/dom/InputElement.cpp b/Source/WebCore/dom/InputElement.cpp
index b467df3..bbdf2f4 100644
--- a/Source/WebCore/dom/InputElement.cpp
+++ b/Source/WebCore/dom/InputElement.cpp
@@ -131,7 +131,7 @@ void InputElement::setValueFromRenderer(InputElementData& data, InputElement* in
// Input event is fired by the Node::defaultEventHandler for editable controls.
if (!inputElement->isTextField())
- element->dispatchInputEvents();
+ element->dispatchInputEvent();
notifyFormStateChanged(element);
}
diff --git a/Source/WebCore/dom/KeyboardEvent.cpp b/Source/WebCore/dom/KeyboardEvent.cpp
index 109135d..e244fd2 100644
--- a/Source/WebCore/dom/KeyboardEvent.cpp
+++ b/Source/WebCore/dom/KeyboardEvent.cpp
@@ -161,10 +161,15 @@ KeyboardEvent* findKeyboardEvent(Event* event)
return 0;
}
-bool KeyboardEvent::dispatch(EventDispatcher* dispatcher)
+KeyboardEventDispatchMediator::KeyboardEventDispatchMediator(PassRefPtr<KeyboardEvent> event)
+ : EventDispatchMediator(event)
+{
+}
+
+bool KeyboardEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
{
// Make sure not to return true if we already took default action while handling the event.
- return dispatcher->dispatchEvent(this) && !defaultHandled();
+ return EventDispatchMediator::dispatchEvent(dispatcher) && !event()->defaultHandled();
}
} // namespace WebCore
diff --git a/Source/WebCore/dom/KeyboardEvent.h b/Source/WebCore/dom/KeyboardEvent.h
index ebdb9c8..68910b5 100644
--- a/Source/WebCore/dom/KeyboardEvent.h
+++ b/Source/WebCore/dom/KeyboardEvent.h
@@ -36,10 +36,10 @@ namespace WebCore {
#if PLATFORM(MAC)
struct KeypressCommand {
KeypressCommand() { }
- KeypressCommand(const String& commandName) : commandName(commandName) { }
- KeypressCommand(const String& commandName, const String& text) : commandName(commandName), text(text) { }
+ KeypressCommand(const String& commandName) : commandName(commandName) { ASSERT(isASCIILower(commandName[0U])); }
+ KeypressCommand(const String& commandName, const String& text) : commandName(commandName), text(text) { ASSERT(commandName == "insertText:"); }
- String commandName;
+ String commandName; // Actually, a selector name - it may have a trailing colon, and a name that can be different from an editor command name.
String text;
};
#endif
@@ -101,20 +101,28 @@ 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;
unsigned m_keyLocation;
bool m_altGraphKey : 1;
-#if PLATFORM(MAC)
+#if PLATFORM(MAC)
+ // Commands that were sent by AppKit when interpreting the event. Doesn't include input method commands.
Vector<KeypressCommand> m_keypressCommands;
#endif
};
KeyboardEvent* findKeyboardEvent(Event*);
+class KeyboardEventDispatchMediator : public EventDispatchMediator {
+public:
+ explicit KeyboardEventDispatchMediator(PassRefPtr<KeyboardEvent>);
+
+private:
+ virtual bool dispatchEvent(EventDispatcher*) const;
+};
+
} // namespace WebCore
#endif // KeyboardEvent_h
diff --git a/Source/WebCore/dom/MessagePort.cpp b/Source/WebCore/dom/MessagePort.cpp
index 1b7aea7..5edc36c 100644
--- a/Source/WebCore/dom/MessagePort.cpp
+++ b/Source/WebCore/dom/MessagePort.cpp
@@ -34,6 +34,7 @@
#include "MessageEvent.h"
#include "SecurityOrigin.h"
#include "Timer.h"
+#include "WorkerContext.h"
#include <wtf/text/AtomicString.h>
namespace WebCore {
@@ -171,6 +172,13 @@ void MessagePort::dispatchMessages()
OwnPtr<MessagePortChannel::EventData> eventData;
while (m_entangledChannel && m_entangledChannel->tryGetMessageFromRemote(eventData)) {
+
+#if ENABLE(WORKERS)
+ // close() in Worker onmessage handler should prevent next message from dispatching.
+ if (m_scriptExecutionContext->isWorkerContext() && static_cast<WorkerContext*>(m_scriptExecutionContext)->isClosing())
+ return;
+#endif
+
OwnPtr<MessagePortArray> ports = MessagePort::entanglePorts(*m_scriptExecutionContext, eventData->channels());
RefPtr<Event> evt = MessageEvent::create(ports.release(), eventData->message());
diff --git a/Source/WebCore/dom/MouseEvent.cpp b/Source/WebCore/dom/MouseEvent.cpp
index 0acbd74..134e5f6 100644
--- a/Source/WebCore/dom/MouseEvent.cpp
+++ b/Source/WebCore/dom/MouseEvent.cpp
@@ -23,19 +23,22 @@
#include "config.h"
#include "MouseEvent.h"
+#include "EventDispatcher.h"
+#include "EventNames.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)
+PassRefPtr<MouseEvent> MouseEvent::create(const AtomicString& eventType, PassRefPtr<AbstractView> view, const PlatformMouseEvent& event, int detail, PassRefPtr<Node> relatedTarget)
{
+ ASSERT(event.eventType() == MouseEventMoved || event.button() != NoButton);
+
bool isCancelable = eventType != eventNames().mousemoveEvent;
return MouseEvent::create(eventType, true, isCancelable, view,
- detail, event.globalX(), event.globalY(), position.x(), position.y(),
+ detail, event.globalX(), event.globalY(), event.x(), event.y(),
event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), event.button(),
relatedTarget, 0, false);
}
@@ -149,4 +152,47 @@ SimulatedMouseEvent::SimulatedMouseEvent(const AtomicString& eventType, PassRefP
setUnderlyingEvent(underlyingEvent);
}
+MouseEventDispatchMediator::MouseEventDispatchMediator(PassRefPtr<MouseEvent> mouseEvent)
+ : EventDispatchMediator(mouseEvent)
+{
+}
+
+MouseEvent* MouseEventDispatchMediator::event() const
+{
+ return static_cast<MouseEvent*>(EventDispatchMediator::event());
+}
+
+bool MouseEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
+{
+ if (dispatcher->node()->disabled()) // Don't even send DOM events for disabled controls..
+ return true;
+
+ if (event()->type().isEmpty())
+ return false; // Shouldn't happen.
+
+ RefPtr<EventTarget> relatedTarget = dispatcher->adjustRelatedTarget(event(), event()->relatedTarget());
+ event()->setRelatedTarget(relatedTarget);
+
+ dispatcher->dispatchEvent(event());
+ bool swallowEvent = event()->defaultHandled() || event()->defaultPrevented();
+
+ // 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 (event()->type() == eventNames().clickEvent && event()->detail() == 2) {
+ RefPtr<MouseEvent> doubleClickEvent = MouseEvent::create();
+ doubleClickEvent->initMouseEvent(eventNames().dblclickEvent, event()->bubbles(), event()->cancelable(), event()->view(),
+ event()->detail(), event()->screenX(), event()->screenY(), event()->clientX(), event()->clientY(),
+ event()->ctrlKey(), event()->altKey(), event()->shiftKey(), event()->metaKey(),
+ event()->button(), relatedTarget);
+ if (event()->defaultHandled())
+ doubleClickEvent->setDefaultHandled();
+ dispatcher->dispatchEvent(doubleClickEvent);
+ if (doubleClickEvent->defaultHandled() || doubleClickEvent->defaultPrevented())
+ swallowEvent = true;
+ }
+
+ return swallowEvent;
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/dom/MouseEvent.h b/Source/WebCore/dom/MouseEvent.h
index 06e6218..bab2b42 100644
--- a/Source/WebCore/dom/MouseEvent.h
+++ b/Source/WebCore/dom/MouseEvent.h
@@ -29,6 +29,7 @@
namespace WebCore {
+class EventDispatcher;
class PlatformMouseEvent;
// Introduced in DOM Level 2
@@ -46,7 +47,7 @@ class PlatformMouseEvent;
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);
+ static PassRefPtr<MouseEvent> create(const AtomicString& eventType, PassRefPtr<AbstractView>, const PlatformMouseEvent&, int detail, PassRefPtr<Node> relatedTarget);
virtual ~MouseEvent();
@@ -60,6 +61,7 @@ class PlatformMouseEvent;
unsigned short button() const { return m_button; }
bool buttonDown() const { return m_buttonDown; }
EventTarget* relatedTarget() const { return m_relatedTarget.get(); }
+ void setRelatedTarget(PassRefPtr<EventTarget> relatedTarget) { m_relatedTarget = relatedTarget; }
Clipboard* clipboard() const { return m_clipboard.get(); }
@@ -96,6 +98,16 @@ private:
SimulatedMouseEvent(const AtomicString& eventType, PassRefPtr<AbstractView>, PassRefPtr<Event> underlyingEvent);
};
+class MouseEventDispatchMediator : public EventDispatchMediator {
+public:
+ explicit MouseEventDispatchMediator(PassRefPtr<MouseEvent>);
+
+private:
+ MouseEvent* event() const;
+
+ virtual bool dispatchEvent(EventDispatcher*) const;
+};
+
} // namespace WebCore
#endif // MouseEvent_h
diff --git a/Source/WebCore/dom/MouseRelatedEvent.cpp b/Source/WebCore/dom/MouseRelatedEvent.cpp
index f752670..01e2d19 100644
--- a/Source/WebCore/dom/MouseRelatedEvent.cpp
+++ b/Source/WebCore/dom/MouseRelatedEvent.cpp
@@ -74,18 +74,43 @@ static int contentsY(AbstractView* abstractView)
return frameView->scrollY() / frame->pageZoomFactor();
}
-MouseRelatedEvent::MouseRelatedEvent(const AtomicString& eventType, bool canBubble, bool cancelable, PassRefPtr<AbstractView> viewArg,
- int detail, int screenX, int screenY, int pageX, int pageY,
+MouseRelatedEvent::MouseRelatedEvent(const AtomicString& eventType, bool canBubble, bool cancelable, PassRefPtr<AbstractView> abstractView,
+ int detail, int screenX, int screenY, int windowX, int windowY,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool isSimulated)
- : UIEventWithKeyState(eventType, canBubble, cancelable, viewArg, detail, ctrlKey, altKey, shiftKey, metaKey)
+ : UIEventWithKeyState(eventType, canBubble, cancelable, abstractView, detail, ctrlKey, altKey, shiftKey, metaKey)
, m_screenX(screenX)
, m_screenY(screenY)
- , m_clientX(pageX - contentsX(view()))
- , m_clientY(pageY - contentsY(view()))
- , m_pageX(pageX)
- , m_pageY(pageY)
+ , m_clientX(0)
+ , m_clientY(0)
+ , m_pageX(0)
+ , m_pageY(0)
, m_isSimulated(isSimulated)
{
+ IntPoint adjustedPageLocation;
+ IntPoint scrollPosition;
+
+ Frame* frame = view() ? view()->frame() : 0;
+ if (frame && !isSimulated) {
+ if (FrameView* frameView = frame->view()) {
+ scrollPosition = frameView->scrollPosition();
+ adjustedPageLocation = frameView->windowToContents(IntPoint(windowX, windowY));
+ float pageZoom = frame->pageZoomFactor();
+ if (pageZoom != 1.0f) {
+ // Adjust our pageX and pageY to account for the page zoom.
+ adjustedPageLocation.setX(lroundf(adjustedPageLocation.x() / pageZoom));
+ adjustedPageLocation.setY(lroundf(adjustedPageLocation.y() / pageZoom));
+ scrollPosition.setX(scrollPosition.x() / pageZoom);
+ scrollPosition.setY(scrollPosition.y() / pageZoom);
+ }
+ }
+ }
+
+ IntPoint clientLocation(adjustedPageLocation - scrollPosition);
+ m_clientX = clientLocation.x();
+ m_clientY = clientLocation.y();
+ m_pageX = adjustedPageLocation.x();
+ m_pageY = adjustedPageLocation.y();
+
initCoordinates();
}
diff --git a/Source/WebCore/dom/NamedNodeMap.idl b/Source/WebCore/dom/NamedNodeMap.idl
index 4d36577..3350d2f 100644
--- a/Source/WebCore/dom/NamedNodeMap.idl
+++ b/Source/WebCore/dom/NamedNodeMap.idl
@@ -21,6 +21,7 @@
module core {
interface [
+ CustomToJS,
CustomMarkFunction,
HasIndexGetter,
HasNameGetter
diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp
index 4def034..1fd4b92 100644
--- a/Source/WebCore/dom/Node.cpp
+++ b/Source/WebCore/dom/Node.cpp
@@ -411,7 +411,7 @@ Node::~Node()
m_next->setPreviousSibling(0);
if (m_document)
- m_document->selfOnlyDeref();
+ m_document->guardDeref();
}
#ifdef NDEBUG
@@ -447,16 +447,12 @@ void Node::setDocument(Document* document)
if (inDocument() || m_document == document)
return;
- document->selfOnlyRef();
+ document->guardRef();
setWillMoveToNewOwnerDocumentWasCalled(false);
willMoveToNewOwnerDocument();
ASSERT(willMoveToNewOwnerDocumentWasCalled);
-#if USE(JSC)
- updateDOMNodeDocument(this, m_document, document);
-#endif
-
if (hasRareData() && rareData()->nodeLists()) {
if (m_document)
m_document->removeNodeListCache();
@@ -465,7 +461,7 @@ void Node::setDocument(Document* document)
if (m_document) {
m_document->moveNodeIteratorsToNewDocument(this, document);
- m_document->selfOnlyDeref();
+ m_document->guardDeref();
}
m_document = document;
@@ -475,6 +471,58 @@ void Node::setDocument(Document* document)
ASSERT(didMoveToNewOwnerDocumentWasCalled);
}
+TreeScope* Node::treeScope() const
+{
+ if (!hasRareData())
+ return document();
+ TreeScope* scope = rareData()->treeScope();
+ // FIXME: Until we land shadow scopes, there should be no non-document scopes.
+ ASSERT(!scope);
+ return scope ? scope : document();
+}
+
+void Node::setTreeScope(TreeScope* newTreeScope)
+{
+ ASSERT(!isDocumentNode());
+ ASSERT(newTreeScope);
+ ASSERT(!inDocument() || treeScope() == newTreeScope);
+
+ if (newTreeScope->isDocumentNode()) {
+ if (hasRareData())
+ rareData()->setTreeScope(0);
+ // Setting the new document scope will be handled implicitly
+ // by setDocument() below.
+ } else {
+ // FIXME: Until we land shadow scopes, this branch should be inert.
+ ASSERT_NOT_REACHED();
+ ensureRareData()->setTreeScope(newTreeScope);
+ }
+
+ setDocument(newTreeScope->document());
+}
+
+void Node::setTreeScopeRecursively(TreeScope* newTreeScope)
+{
+ ASSERT(!isDocumentNode());
+ ASSERT(newTreeScope);
+ if (treeScope() == newTreeScope)
+ return;
+
+ Document* currentDocument = document();
+ Document* newDocument = newTreeScope->document();
+ // 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 (currentDocument && currentDocument != newDocument)
+ currentDocument->incDOMTreeVersion();
+
+ for (Node* node = this; node; node = node->traverseNextNode(this)) {
+ node->setTreeScope(newTreeScope);
+ // FIXME: Once shadow scopes are landed, update parent scope, etc.
+ }
+}
+
NodeRareData* Node::rareData() const
{
ASSERT(hasRareData());
@@ -505,7 +553,7 @@ Element* Node::shadowHost() const
void Node::setShadowHost(Element* host)
{
- ASSERT(!parentNode());
+ ASSERT(!parentNode() && !isSVGShadowRoot());
if (host)
setFlag(IsShadowRootFlag);
else
@@ -714,6 +762,12 @@ void Node::deprecatedParserAddChild(PassRefPtr<Node>)
{
}
+bool Node::isContentEditable() const
+{
+ document()->updateLayoutIgnorePendingStylesheets();
+ return rendererIsEditable(Editable);
+}
+
bool Node::rendererIsEditable(EditableLevel editableLevel) const
{
if (document()->inDesignMode() || (document()->frame() && document()->frame()->page() && document()->frame()->page()->isEditable()))
@@ -743,7 +797,7 @@ bool Node::rendererIsEditable(EditableLevel editableLevel) const
bool Node::shouldUseInputMethod() const
{
- return rendererIsEditable();
+ return isContentEditable();
}
RenderBox* Node::renderBox() const
@@ -799,24 +853,21 @@ bool Node::hasNonEmptyBoundingBox() const
return false;
}
-void Node::setDocumentRecursively(Document* document)
+inline static ContainerNode* shadowRoot(Node* node)
{
- if (this->document() == document)
- return;
+ return node->isElementNode() ? toElement(node)->shadowRoot() : 0;
+}
- // 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();
+void Node::setDocumentRecursively(Document* newDocument)
+{
+ ASSERT(document() != newDocument);
for (Node* node = this; node; node = node->traverseNextNode(this)) {
- node->setDocument(document);
+ node->setDocument(newDocument);
if (!node->isElementNode())
continue;
- if (Node* shadow = toElement(node)->shadowRoot())
- shadow->setDocumentRecursively(document);
+ if (Node* shadow = shadowRoot(node))
+ shadow->setDocumentRecursively(newDocument);
}
}
@@ -1401,18 +1452,44 @@ Node *Node::nextLeafNode() const
return 0;
}
+ContainerNode* Node::parentNodeForRenderingAndStyle() const
+{
+ ContainerNode* parent = parentOrHostNode();
+ return parent && parent->isShadowBoundary() ? parent->shadowHost() : parent;
+}
+
+static bool shouldCreateRendererFor(Node* node, ContainerNode* parentForRenderingAndStyle)
+{
+ RenderObject* parentRenderer = parentForRenderingAndStyle->renderer();
+ if (!parentRenderer)
+ return false;
+
+ bool atShadowBoundary = node->parentOrHostNode()->isShadowBoundary();
+
+ // FIXME: Ignoring canHaveChildren() in a case of isShadowRoot() might be wrong.
+ // See https://bugs.webkit.org/show_bug.cgi?id=52423
+ if (!parentRenderer->canHaveChildren() && !(node->isShadowRoot() || atShadowBoundary))
+ return false;
+
+ if (shadowRoot(parentForRenderingAndStyle) && !atShadowBoundary
+ && !parentForRenderingAndStyle->canHaveLightChildRendererWithShadow())
+ return false;
+
+ if (!parentForRenderingAndStyle->childShouldCreateRenderer(node))
+ return false;
+
+ return true;
+}
+
RenderObject* Node::createRendererAndStyle()
{
ASSERT(!renderer());
ASSERT(document()->shouldCreateRenderers());
- ContainerNode* parent = parentOrHostNode();
+ ContainerNode* parent = parentNodeForRenderingAndStyle();
ASSERT(parent);
- RenderObject* parentRenderer = parent->renderer();
- // FIXME: Ignoring canHaveChildren() in a case of isShadowRoot() might be wrong.
- // See https://bugs.webkit.org/show_bug.cgi?id=52423
- if (!parentRenderer || (!parentRenderer->canHaveChildren() && !isShadowRoot()) || !parent->childShouldCreateRenderer(this))
+ if (!shouldCreateRendererFor(this, parent))
return 0;
RefPtr<RenderStyle> style = styleForRenderer();
@@ -1423,7 +1500,7 @@ RenderObject* Node::createRendererAndStyle()
if (!newRenderer)
return 0;
- if (!parentRenderer->isChildAllowed(newRenderer, style.get())) {
+ if (!parent->renderer()->isChildAllowed(newRenderer, style.get())) {
newRenderer->destroy();
return 0;
}
@@ -1464,7 +1541,7 @@ void Node::createRendererIfNeeded()
return;
// Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
- parentOrHostNode()->renderer()->addChild(newRenderer, nextRenderer());
+ parentNodeForRenderingAndStyle()->renderer()->addChild(newRenderer, nextRenderer());
}
PassRefPtr<RenderStyle> Node::styleForRenderer()
@@ -1530,6 +1607,13 @@ bool Node::canStartSelection() const
return parentOrHostNode() ? parentOrHostNode()->canStartSelection() : true;
}
+#if ENABLE(SVG)
+SVGUseElement* Node::svgShadowHost() const
+{
+ return isSVGShadowRoot() ? static_cast<SVGUseElement*>(parent()) : 0;
+}
+#endif
+
Node* Node::shadowAncestorNode()
{
#if ENABLE(SVG)
@@ -1551,7 +1635,7 @@ Node* Node::shadowTreeRootNode()
{
Node* root = this;
while (root) {
- if (root->isShadowRoot())
+ if (root->isShadowRoot() || root->isSVGShadowRoot())
return root;
root = root->parentNodeGuaranteedHostFree();
}
@@ -2641,28 +2725,6 @@ EventTargetData* Node::ensureEventTargetData()
return ensureRareData()->ensureEventTargetData();
}
-#if USE(JSC)
-
-template <class NodeListMap>
-void markNodeLists(const NodeListMap& map, JSC::MarkStack& markStack, JSC::JSGlobalData& globalData)
-{
- for (typename NodeListMap::const_iterator it = map.begin(); it != map.end(); ++it)
- markDOMObjectWrapper(markStack, globalData, it->second);
-}
-
-void Node::markCachedNodeListsSlow(JSC::MarkStack& markStack, JSC::JSGlobalData& globalData)
-{
- NodeListsNodeData* nodeLists = rareData()->nodeLists();
- if (!nodeLists)
- return;
-
- markNodeLists(nodeLists->m_classNodeListCache, markStack, globalData);
- markNodeLists(nodeLists->m_nameNodeListCache, markStack, globalData);
- markNodeLists(nodeLists->m_tagNodeListCache, markStack, globalData);
-}
-
-#endif
-
void Node::handleLocalEvents(Event* event)
{
if (!hasRareData() || !rareData()->eventTargetData())
@@ -2681,7 +2743,7 @@ void Node::dispatchScopedEvent(PassRefPtr<Event> event)
bool Node::dispatchEvent(PassRefPtr<Event> event)
{
- return EventDispatcher::dispatchEvent(this, event);
+ return EventDispatcher::dispatchEvent(this, EventDispatchMediator(event));
}
void Node::dispatchSubtreeModifiedEvent()
@@ -2713,13 +2775,13 @@ void Node::dispatchUIEvent(const AtomicString& eventType, int detail, PassRefPtr
bool Node::dispatchKeyEvent(const PlatformKeyboardEvent& event)
{
- return EventDispatcher::dispatchEvent(this, KeyboardEvent::create(event, document()->defaultView()));
+ return EventDispatcher::dispatchEvent(this, KeyboardEventDispatchMediator(KeyboardEvent::create(event, document()->defaultView())));
}
bool Node::dispatchMouseEvent(const PlatformMouseEvent& event, const AtomicString& eventType,
int detail, Node* relatedTarget)
{
- return EventDispatcher::dispatchMouseEvent(this, event, eventType, detail, relatedTarget);
+ return EventDispatcher::dispatchEvent(this, MouseEventDispatchMediator(MouseEvent::create(eventType, document()->defaultView(), event, detail, relatedTarget)));
}
void Node::dispatchSimulatedClick(PassRefPtr<Event> event, bool sendMouseEvents, bool showPressedLook)
@@ -2727,9 +2789,9 @@ void Node::dispatchSimulatedClick(PassRefPtr<Event> event, bool sendMouseEvents,
EventDispatcher::dispatchSimulatedClick(this, event, sendMouseEvents, showPressedLook);
}
-void Node::dispatchWheelEvent(PlatformWheelEvent& e)
+bool Node::dispatchWheelEvent(const PlatformWheelEvent& event)
{
- EventDispatcher::dispatchWheelEvent(this, e);
+ return EventDispatcher::dispatchEvent(this, WheelEventDispatchMediator(event, document()->defaultView()));
}
void Node::dispatchFocusEvent()
@@ -2742,12 +2804,12 @@ void Node::dispatchBlurEvent()
dispatchEvent(Event::create(eventNames().blurEvent, false, false));
}
-void Node::dispatchChangeEvents()
+void Node::dispatchChangeEvent()
{
dispatchEvent(Event::create(eventNames().changeEvent, true, false));
}
-void Node::dispatchInputEvents()
+void Node::dispatchInputEvent()
{
dispatchEvent(Event::create(eventNames().inputEvent, true, false));
}
@@ -2809,7 +2871,7 @@ void Node::defaultEventHandler(Event* event)
if (Frame* frame = document()->frame())
frame->eventHandler()->defaultWheelEventHandler(startNode, wheelEvent);
} else if (event->type() == eventNames().webkitEditableContentChangedEvent) {
- dispatchInputEvents();
+ dispatchInputEvent();
}
}
diff --git a/Source/WebCore/dom/Node.h b/Source/WebCore/dom/Node.h
index 31f6ae8..c7bf90d 100644
--- a/Source/WebCore/dom/Node.h
+++ b/Source/WebCore/dom/Node.h
@@ -71,7 +71,11 @@ class RenderBox;
class RenderBoxModelObject;
class RenderObject;
class RenderStyle;
+#if ENABLE(SVG)
+class SVGUseElement;
+#endif
class TagNodeList;
+class TreeScope;
typedef int ExceptionCode;
@@ -89,6 +93,8 @@ enum StyleChangeType {
class Node : public EventTarget, public TreeShared<ContainerNode>, public ScriptWrappable {
friend class Document;
+ friend class TreeScope;
+
public:
enum NodeType {
ELEMENT_NODE = 1,
@@ -188,6 +194,10 @@ public:
bool isHTMLElement() const { return getFlag(IsHTMLFlag); }
bool isSVGElement() const { return getFlag(IsSVGFlag); }
+ virtual bool isSVGShadowRoot() const { return false; }
+#if ENABLE(SVG)
+ SVGUseElement* svgShadowHost() const;
+#endif
#if ENABLE(WML)
virtual bool isWMLElement() const { return false; }
@@ -203,12 +213,16 @@ public:
virtual bool isCharacterDataNode() const { return false; }
bool isDocumentNode() const;
bool isShadowRoot() const { return getFlag(IsShadowRootFlag); }
+ // FIXME: Remove this when all shadow roots are ShadowRoots.
+ virtual bool isShadowBoundary() const { return false; }
+ virtual bool canHaveLightChildRendererWithShadow() const { return false; }
+
Node* shadowAncestorNode();
Node* shadowTreeRootNode();
bool isInShadowTree();
- // Node's parent or shadow tree host.
+ // Node's parent, shadow tree host, or SVG use.
ContainerNode* parentOrHostNode() const;
- // Use when it's guaranteed to that shadowHost is 0.
+ // Use when it's guaranteed to that shadowHost is 0 and svgShadowHost is 0.
ContainerNode* parentNodeGuaranteedHostFree() const;
Element* shadowHost() const;
@@ -319,10 +333,8 @@ public:
virtual bool isKeyboardFocusable(KeyboardEvent*) const;
virtual bool isMouseFocusable() const;
-#if PLATFORM(MAC)
- // Objective-C extensions
- bool isContentEditable() const { return rendererIsEditable(Editable); }
-#endif
+ bool isContentEditable() const;
+
bool rendererIsEditable() const { return rendererIsEditable(Editable); }
bool rendererIsRichlyEditable() const { return rendererIsEditable(RichlyEditable); }
virtual bool shouldUseInputMethod() const;
@@ -351,12 +363,14 @@ public:
return m_document;
}
- // Do not use this method to change the document of a node until after the node has been
- // removed from its previous document.
- void setDocument(Document*);
+ TreeScope* treeScope() const;
+
+ // Do not use this method to change the scope of a node until after the node has been
+ // removed from its previous scope. Do not use to change documents.
+ void setTreeScope(TreeScope*);
// Used by the basic DOM methods (e.g., appendChild()).
- void setDocumentRecursively(Document*);
+ void setTreeScopeRecursively(TreeScope*);
// Returns true if this node is associated with a document and is in its associated document's
// node tree, false otherwise.
@@ -367,7 +381,7 @@ public:
}
bool isReadOnlyNode() const { return nodeType() == ENTITY_REFERENCE_NODE; }
- virtual bool childTypeAllowed(NodeType) { return false; }
+ virtual bool childTypeAllowed(NodeType) const { return false; }
unsigned childNodeCount() const;
Node* childNode(unsigned index) const;
@@ -446,6 +460,7 @@ public:
virtual bool rendererIsNeeded(RenderStyle*);
virtual bool childShouldCreateRenderer(Node*) const { return true; }
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
+ ContainerNode* parentNodeForRenderingAndStyle() const;
// Wrapper for nodes that don't have a renderer, but still cache the style (like HTMLOptionElement).
RenderStyle* renderStyle() const;
@@ -547,14 +562,14 @@ public:
void dispatchSubtreeModifiedEvent();
void dispatchUIEvent(const AtomicString& eventType, int detail, PassRefPtr<Event> underlyingEvent);
bool dispatchKeyEvent(const PlatformKeyboardEvent&);
- void dispatchWheelEvent(PlatformWheelEvent&);
+ bool dispatchWheelEvent(const PlatformWheelEvent&);
bool dispatchMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType, int clickCount = 0, Node* relatedTarget = 0);
void dispatchSimulatedClick(PassRefPtr<Event> underlyingEvent, bool sendMouseEvents = false, bool showPressedLook = true);
virtual void dispatchFocusEvent();
virtual void dispatchBlurEvent();
- virtual void dispatchChangeEvents();
- virtual void dispatchInputEvents();
+ virtual void dispatchChangeEvent();
+ virtual void dispatchInputEvent();
// Perform the default action for an event.
virtual void defaultEventHandler(Event*);
@@ -569,17 +584,6 @@ public:
virtual EventTargetData* eventTargetData();
virtual EventTargetData* ensureEventTargetData();
-#if USE(JSC)
- void markCachedNodeLists(JSC::MarkStack& markStack, JSC::JSGlobalData& globalData)
- {
- // NodeLists may be present. If so, they need to be marked.
- if (!hasRareData())
- return;
-
- markCachedNodeListsSlow(markStack, globalData);
- }
-#endif
-
private:
enum NodeFlags {
IsTextFlag = 1,
@@ -644,6 +648,11 @@ protected:
};
Node(Document*, ConstructionType);
+ // Do not use this method to change the document of a node until after the node has been
+ // removed from its previous document.
+ void setDocument(Document*);
+ void setDocumentRecursively(Document*);
+
virtual void willMoveToNewOwnerDocument();
virtual void didMoveToNewOwnerDocument();
@@ -657,10 +666,6 @@ protected:
NodeRareData* ensureRareData();
private:
-#if USE(JSC)
- void markCachedNodeListsSlow(JSC::MarkStack&, JSC::JSGlobalData&);
-#endif
-
enum EditableLevel { Editable, RichlyEditable };
bool rendererIsEditable(EditableLevel) const;
@@ -734,7 +739,7 @@ inline void addSubresourceURL(ListHashSet<KURL>& urls, const KURL& url)
inline ContainerNode* Node::parentNode() const
{
- return getFlag(IsShadowRootFlag) ? 0 : parent();
+ return getFlag(IsShadowRootFlag) || isSVGShadowRoot() ? 0 : parent();
}
inline ContainerNode* Node::parentOrHostNode() const
@@ -744,7 +749,7 @@ inline ContainerNode* Node::parentOrHostNode() const
inline ContainerNode* Node::parentNodeGuaranteedHostFree() const
{
- ASSERT(!getFlag(IsShadowRootFlag));
+ ASSERT(!getFlag(IsShadowRootFlag) && !isSVGShadowRoot());
return parentOrHostNode();
}
diff --git a/Source/WebCore/dom/NodeFilter.h b/Source/WebCore/dom/NodeFilter.h
index 5ce2866..d6e47fb 100644
--- a/Source/WebCore/dom/NodeFilter.h
+++ b/Source/WebCore/dom/NodeFilter.h
@@ -70,15 +70,22 @@ namespace WebCore {
return adoptRef(new NodeFilter(condition));
}
+ static PassRefPtr<NodeFilter> create()
+ {
+ return adoptRef(new NodeFilter());
+ }
+
short acceptNode(ScriptState*, Node*) const;
- void markAggregate(JSC::MarkStack& markStack) { m_condition->markAggregate(markStack); };
// Do not call these functions. They are just scaffolding to support the Objective-C bindings.
// They operate in the main thread normal world, and they swallow JS exceptions.
short acceptNode(Node* node) const { return acceptNode(scriptStateFromNode(mainThreadNormalWorld(), node), node); }
+
+ void setCondition(PassRefPtr<NodeFilterCondition> condition) { ASSERT(!m_condition); m_condition = condition; }
private:
NodeFilter(PassRefPtr<NodeFilterCondition> condition) : m_condition(condition) { }
+ NodeFilter() {}
RefPtr<NodeFilterCondition> m_condition;
};
diff --git a/Source/WebCore/dom/NodeList.h b/Source/WebCore/dom/NodeList.h
index d4e18aa..7639d37 100644
--- a/Source/WebCore/dom/NodeList.h
+++ b/Source/WebCore/dom/NodeList.h
@@ -39,6 +39,9 @@ namespace WebCore {
virtual unsigned length() const = 0;
virtual Node* item(unsigned index) const = 0;
virtual Node* itemWithName(const AtomicString&) const = 0;
+
+ // Other methods (not part of DOM)
+ virtual bool isDynamicNodeList() const { return false; }
};
} // namespace WebCore
diff --git a/Source/WebCore/dom/NodeList.idl b/Source/WebCore/dom/NodeList.idl
index edb2dc7..b751f66 100644
--- a/Source/WebCore/dom/NodeList.idl
+++ b/Source/WebCore/dom/NodeList.idl
@@ -21,6 +21,7 @@
module core {
interface [
+ CustomToJS,
HasIndexGetter,
HasNameGetter,
CustomCall
diff --git a/Source/WebCore/dom/NodeRareData.h b/Source/WebCore/dom/NodeRareData.h
index badc4e1..ac05d3e 100644
--- a/Source/WebCore/dom/NodeRareData.h
+++ b/Source/WebCore/dom/NodeRareData.h
@@ -34,6 +34,8 @@
namespace WebCore {
+class TreeScope;
+
struct NodeListsNodeData {
WTF_MAKE_NONCOPYABLE(NodeListsNodeData); WTF_MAKE_FAST_ALLOCATED;
public:
@@ -73,7 +75,8 @@ class NodeRareData {
WTF_MAKE_NONCOPYABLE(NodeRareData); WTF_MAKE_FAST_ALLOCATED;
public:
NodeRareData()
- : m_tabIndex(0)
+ : m_treeScope(0)
+ , m_tabIndex(0)
, m_tabIndexWasSetExplicitly(false)
, m_isFocused(false)
, m_needsFocusAppearanceUpdateSoonAfterAttach(false)
@@ -96,11 +99,14 @@ public:
{
return rareDataMap().get(node);
}
+
+ TreeScope* treeScope() const { return m_treeScope; }
+ void setTreeScope(TreeScope* treeScope) { m_treeScope = treeScope; }
void clearNodeLists() { m_nodeLists.clear(); }
void setNodeLists(PassOwnPtr<NodeListsNodeData> lists) { m_nodeLists = lists; }
NodeListsNodeData* nodeLists() const { return m_nodeLists.get(); }
-
+
short tabIndex() const { return m_tabIndex; }
void setTabIndexExplicitly(short index) { m_tabIndex = index; m_tabIndexWasSetExplicitly = true; }
bool tabIndexSetExplicitly() const { return m_tabIndexWasSetExplicitly; }
@@ -123,6 +129,7 @@ protected:
void setNeedsFocusAppearanceUpdateSoonAfterAttach(bool needs) { m_needsFocusAppearanceUpdateSoonAfterAttach = needs; }
private:
+ TreeScope* m_treeScope;
OwnPtr<NodeListsNodeData> m_nodeLists;
OwnPtr<EventTargetData> m_eventTargetData;
short m_tabIndex;
diff --git a/Source/WebCore/dom/NodeRenderStyle.h b/Source/WebCore/dom/NodeRenderStyle.h
index 3a67e02..1a2d2c3 100644
--- a/Source/WebCore/dom/NodeRenderStyle.h
+++ b/Source/WebCore/dom/NodeRenderStyle.h
@@ -33,7 +33,11 @@ namespace WebCore {
inline RenderStyle* Node::renderStyle() const
{
- return m_renderer ? m_renderer->style() : nonRendererRenderStyle();
+ // Using a ternary here confuses the Solaris Studio 12/12.1/12.2 compilers:
+ // Bug is CR 6569194, "Problem with question operator binding in inline function"
+ if (m_renderer)
+ return m_renderer->style();
+ return nonRendererRenderStyle();
}
}
diff --git a/Source/WebCore/dom/Notation.cpp b/Source/WebCore/dom/Notation.cpp
index 4b3ab28..f62e630 100644
--- a/Source/WebCore/dom/Notation.cpp
+++ b/Source/WebCore/dom/Notation.cpp
@@ -49,7 +49,7 @@ PassRefPtr<Node> Notation::cloneNode(bool /*deep*/)
return 0;
}
-bool Notation::childTypeAllowed(NodeType)
+bool Notation::childTypeAllowed(NodeType) const
{
return false;
}
diff --git a/Source/WebCore/dom/Notation.h b/Source/WebCore/dom/Notation.h
index 547c9e7..b2155ba 100644
--- a/Source/WebCore/dom/Notation.h
+++ b/Source/WebCore/dom/Notation.h
@@ -39,7 +39,7 @@ private:
virtual String nodeName() const;
virtual NodeType nodeType() const;
virtual PassRefPtr<Node> cloneNode(bool deep);
- virtual bool childTypeAllowed(NodeType);
+ virtual bool childTypeAllowed(NodeType) const;
String m_name;
String m_publicId;
diff --git a/Source/WebCore/dom/ProcessingInstruction.cpp b/Source/WebCore/dom/ProcessingInstruction.cpp
index ae0e40d..7135644 100644
--- a/Source/WebCore/dom/ProcessingInstruction.cpp
+++ b/Source/WebCore/dom/ProcessingInstruction.cpp
@@ -101,7 +101,7 @@ PassRefPtr<Node> ProcessingInstruction::cloneNode(bool /*deep*/)
}
// DOM Section 1.1.1
-bool ProcessingInstruction::childTypeAllowed(NodeType)
+bool ProcessingInstruction::childTypeAllowed(NodeType) const
{
return false;
}
diff --git a/Source/WebCore/dom/ProcessingInstruction.h b/Source/WebCore/dom/ProcessingInstruction.h
index 8619070..fd98566 100644
--- a/Source/WebCore/dom/ProcessingInstruction.h
+++ b/Source/WebCore/dom/ProcessingInstruction.h
@@ -69,7 +69,7 @@ private:
virtual String nodeValue() const;
virtual void setNodeValue(const String&, ExceptionCode&);
virtual PassRefPtr<Node> cloneNode(bool deep);
- virtual bool childTypeAllowed(NodeType);
+ virtual bool childTypeAllowed(NodeType) const;
virtual bool offsetInCharacters() const;
virtual int maxCharacterOffset() const;
diff --git a/Source/WebCore/dom/QualifiedName.h b/Source/WebCore/dom/QualifiedName.h
index 192e7bc..01eaebb 100644
--- a/Source/WebCore/dom/QualifiedName.h
+++ b/Source/WebCore/dom/QualifiedName.h
@@ -141,11 +141,9 @@ namespace WTF {
typedef WebCore::QualifiedNameHash Hash;
};
- template<> struct HashTraits<WebCore::QualifiedName> : GenericHashTraits<WebCore::QualifiedName> {
+ template<> struct HashTraits<WebCore::QualifiedName> : SimpleClassHashTraits<WebCore::QualifiedName> {
static const bool emptyValueIsZero = false;
static WebCore::QualifiedName emptyValue() { return WebCore::QualifiedName(nullAtom, nullAtom, nullAtom); }
- static void constructDeletedValue(WebCore::QualifiedName& slot) { new (&slot) WebCore::QualifiedName(WTF::HashTableDeletedValue); }
- static bool isDeletedValue(const WebCore::QualifiedName& slot) { return slot.isHashTableDeletedValue(); }
};
}
diff --git a/Source/WebCore/dom/Range.cpp b/Source/WebCore/dom/Range.cpp
index 423d43f..469a94a 100644
--- a/Source/WebCore/dom/Range.cpp
+++ b/Source/WebCore/dom/Range.cpp
@@ -224,8 +224,10 @@ void Range::setStart(PassRefPtr<Node> refNode, int offset, ExceptionCode& ec)
if (startRootContainer != endRootContainer)
collapse(true, ec);
// check if new start after end
- else if (compareBoundaryPoints(m_start, m_end) > 0)
+ else if (compareBoundaryPoints(m_start, m_end, ec) > 0) {
+ ASSERT(!ec);
collapse(true, ec);
+ }
}
void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionCode& ec)
@@ -262,8 +264,10 @@ void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionCode& ec)
if (startRootContainer != endRootContainer)
collapse(false, ec);
// check if new end before start
- if (compareBoundaryPoints(m_start, m_end) > 0)
+ if (compareBoundaryPoints(m_start, m_end, ec) > 0) {
+ ASSERT(!ec);
collapse(false, ec);
+ }
}
void Range::collapse(bool toStart, ExceptionCode& ec)
@@ -306,8 +310,8 @@ bool Range::isPointInRange(Node* refNode, int offset, ExceptionCode& ec)
if (ec)
return false;
- return compareBoundaryPoints(refNode, offset, m_start.container(), m_start.offset()) >= 0
- && compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset()) <= 0;
+ return compareBoundaryPoints(refNode, offset, m_start.container(), m_start.offset(), ec) >= 0 && !ec
+ && compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset(), ec) <= 0 && !ec;
}
short Range::comparePoint(Node* refNode, int offset, ExceptionCode& ec) const
@@ -337,11 +341,14 @@ short Range::comparePoint(Node* refNode, int offset, ExceptionCode& ec) const
return 0;
// compare to start, and point comes before
- if (compareBoundaryPoints(refNode, offset, m_start.container(), m_start.offset()) < 0)
+ if (compareBoundaryPoints(refNode, offset, m_start.container(), m_start.offset(), ec) < 0)
return -1;
+ if (ec)
+ return 0;
+
// compare to end, and point comes after
- if (compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset()) > 0)
+ if (compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset(), ec) > 0 && !ec)
return 1;
// point is in the middle of this range, or on the boundary points
@@ -433,20 +440,20 @@ short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, Exc
switch (how) {
case START_TO_START:
- return compareBoundaryPoints(m_start, sourceRange->m_start);
+ return compareBoundaryPoints(m_start, sourceRange->m_start, ec);
case START_TO_END:
- return compareBoundaryPoints(m_end, sourceRange->m_start);
+ return compareBoundaryPoints(m_end, sourceRange->m_start, ec);
case END_TO_END:
- return compareBoundaryPoints(m_end, sourceRange->m_end);
+ return compareBoundaryPoints(m_end, sourceRange->m_end, ec);
case END_TO_START:
- return compareBoundaryPoints(m_start, sourceRange->m_end);
+ return compareBoundaryPoints(m_start, sourceRange->m_end, ec);
}
ec = SYNTAX_ERR;
return 0;
}
-short Range::compareBoundaryPoints(Node* containerA, int offsetA, Node* containerB, int offsetB)
+short Range::compareBoundaryPoints(Node* containerA, int offsetA, Node* containerB, int offsetB, ExceptionCode& ec)
{
ASSERT(containerA);
ASSERT(containerB);
@@ -507,8 +514,10 @@ short Range::compareBoundaryPoints(Node* containerA, int offsetA, Node* containe
// case 4: containers A & B are siblings, or children of siblings
// ### we need to do a traversal here instead
Node* commonAncestor = commonAncestorContainer(containerA, containerB);
- if (!commonAncestor)
+ if (!commonAncestor) {
+ ec = WRONG_DOCUMENT_ERR;
return 0;
+ }
Node* childA = containerA;
while (childA && childA->parentNode() != commonAncestor)
childA = childA->parentNode();
@@ -537,14 +546,15 @@ short Range::compareBoundaryPoints(Node* containerA, int offsetA, Node* containe
return 0;
}
-short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const RangeBoundaryPoint& boundaryB)
+short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const RangeBoundaryPoint& boundaryB, ExceptionCode& ec)
{
- return compareBoundaryPoints(boundaryA.container(), boundaryA.offset(), boundaryB.container(), boundaryB.offset());
+ return compareBoundaryPoints(boundaryA.container(), boundaryA.offset(), boundaryB.container(), boundaryB.offset(), ec);
}
bool Range::boundaryPointsValid() const
{
- return m_start.container() && compareBoundaryPoints(m_start, m_end) <= 0;
+ ExceptionCode ec = 0;
+ return m_start.container() && compareBoundaryPoints(m_start, m_end, ec) <= 0 && !ec;
}
void Range::deleteContents(ExceptionCode& ec)
@@ -1620,7 +1630,7 @@ void Range::textRects(Vector<IntRect>& rects, bool useSelectionHeight)
}
}
-void Range::textQuads(Vector<FloatQuad>& quads, bool useSelectionHeight)
+void Range::textQuads(Vector<FloatQuad>& quads, bool useSelectionHeight) const
{
Node* startContainer = m_start.container();
Node* endContainer = m_end.container();
@@ -1893,16 +1903,24 @@ PassRefPtr<ClientRect> Range::getBoundingClientRect() const
return rect.isEmpty() ? 0 : ClientRect::create(rect);
}
-static void adjustFloatQuadsForScrollAndAbsoluteZoom(Vector<FloatQuad>& quads, Document* document, RenderObject* renderer)
+static void adjustFloatQuadsForScrollAndAbsoluteZoomAndPageScale(Vector<FloatQuad>& quads, Document* document, RenderObject* renderer)
{
FrameView* view = document->view();
if (!view)
return;
+ float pageScale = 1;
+ if (Page* page = document->page()) {
+ if (Frame* frame = page->mainFrame())
+ pageScale = frame->pageScaleFactor();
+ }
+
IntRect visibleContentRect = view->visibleContentRect();
for (size_t i = 0; i < quads.size(); ++i) {
quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
adjustFloatQuadForAbsoluteZoom(quads[i], renderer);
+ if (pageScale != 1)
+ adjustFloatQuadForPageScale(quads[i], pageScale);
}
}
@@ -1924,7 +1942,7 @@ void Range::getBorderAndTextQuads(Vector<FloatQuad>& quads) const
if (RenderBoxModelObject* renderBoxModelObject = static_cast<Element*>(node)->renderBoxModelObject()) {
Vector<FloatQuad> elementQuads;
renderBoxModelObject->absoluteQuads(elementQuads);
- adjustFloatQuadsForScrollAndAbsoluteZoom(elementQuads, m_ownerDocument.get(), renderBoxModelObject);
+ adjustFloatQuadsForScrollAndAbsoluteZoomAndPageScale(elementQuads, m_ownerDocument.get(), renderBoxModelObject);
quads.append(elementQuads);
}
@@ -1937,7 +1955,7 @@ void Range::getBorderAndTextQuads(Vector<FloatQuad>& quads) const
Vector<FloatQuad> textQuads;
renderText->absoluteQuadsForRange(textQuads, startOffset, endOffset);
- adjustFloatQuadsForScrollAndAbsoluteZoom(textQuads, m_ownerDocument.get(), renderText);
+ adjustFloatQuadsForScrollAndAbsoluteZoomAndPageScale(textQuads, m_ownerDocument.get(), renderText);
quads.append(textQuads);
}
diff --git a/Source/WebCore/dom/Range.h b/Source/WebCore/dom/Range.h
index 5637b77..062ad67 100644
--- a/Source/WebCore/dom/Range.h
+++ b/Source/WebCore/dom/Range.h
@@ -69,8 +69,8 @@ public:
CompareResults compareNode(Node* refNode, ExceptionCode&) const;
enum CompareHow { START_TO_START, START_TO_END, END_TO_END, END_TO_START };
short compareBoundaryPoints(CompareHow, const Range* sourceRange, ExceptionCode&) const;
- static short compareBoundaryPoints(Node* containerA, int offsetA, Node* containerB, int offsetB);
- static short compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const RangeBoundaryPoint& boundaryB);
+ static short compareBoundaryPoints(Node* containerA, int offsetA, Node* containerB, int offsetB, ExceptionCode&);
+ static short compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const RangeBoundaryPoint& boundaryB, ExceptionCode&);
bool boundaryPointsValid() const;
bool intersectsNode(Node* refNode, ExceptionCode&);
void deleteContents(ExceptionCode&);
@@ -109,7 +109,7 @@ public:
// Not transform-friendly
void textRects(Vector<IntRect>&, bool useSelectionHeight = false);
// Transform-friendly
- void textQuads(Vector<FloatQuad>&, bool useSelectionHeight = false);
+ void textQuads(Vector<FloatQuad>&, bool useSelectionHeight = false) const;
void getBorderAndTextQuads(Vector<FloatQuad>&) const;
FloatRect boundingRect() const;
diff --git a/Source/WebCore/dom/ScriptElement.cpp b/Source/WebCore/dom/ScriptElement.cpp
index 9a07bb8..5dd6b7d 100644
--- a/Source/WebCore/dom/ScriptElement.cpp
+++ b/Source/WebCore/dom/ScriptElement.cpp
@@ -257,6 +257,9 @@ void ScriptElement::executeScript(const ScriptSourceCode& sourceCode)
if (sourceCode.isEmpty())
return;
+ if (!m_isExternalScript && !m_element->document()->contentSecurityPolicy()->allowInlineScript())
+ return;
+
RefPtr<Document> document = m_element->document();
ASSERT(document);
if (Frame* frame = document->frame()) {
diff --git a/Source/WebCore/dom/ScriptExecutionContext.h b/Source/WebCore/dom/ScriptExecutionContext.h
index 3b37f0c..8407699 100644
--- a/Source/WebCore/dom/ScriptExecutionContext.h
+++ b/Source/WebCore/dom/ScriptExecutionContext.h
@@ -82,7 +82,7 @@ namespace WebCore {
void stopDatabases(DatabaseTaskSynchronizer*);
#endif
virtual bool isContextThread() const = 0;
- virtual bool isJSExecutionTerminated() const = 0;
+ virtual bool isJSExecutionForbidden() const = 0;
const KURL& url() const { return virtualURL(); }
KURL completeURL(const String& url) const { return virtualCompleteURL(url); }
diff --git a/Source/WebCore/dom/SelectElement.cpp b/Source/WebCore/dom/SelectElement.cpp
index 15c69ad..545f271 100644
--- a/Source/WebCore/dom/SelectElement.cpp
+++ b/Source/WebCore/dom/SelectElement.cpp
@@ -70,6 +70,74 @@ namespace WebCore {
static const DOMTimeStamp typeAheadTimeout = 1000;
+enum SkipDirection {
+ SkipBackwards = -1,
+ SkipForwards = 1
+};
+
+// Returns the 1st valid item |skip| items from |listIndex| in direction |direction| if there is one.
+// Otherwise, it returns the valid item closest to that boundary which is past |listIndex| if there is one.
+// Otherwise, it returns |listIndex|.
+// Valid means that it is enabled and an option element.
+static int nextValidIndex(const Vector<Element*>& listItems, int listIndex, SkipDirection direction, int skip)
+{
+ ASSERT(direction == -1 || direction == 1);
+ int lastGoodIndex = listIndex;
+ int size = listItems.size();
+ for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex += direction) {
+ --skip;
+ if (!listItems[listIndex]->disabled() && isOptionElement(listItems[listIndex])) {
+ lastGoodIndex = listIndex;
+ if (skip <= 0)
+ break;
+ }
+ }
+ return lastGoodIndex;
+}
+
+static int nextSelectableListIndex(SelectElementData& data, Element* element, int startIndex)
+{
+ return nextValidIndex(data.listItems(element), startIndex, SkipForwards, 1);
+}
+
+static int previousSelectableListIndex(SelectElementData& data, Element* element, int startIndex)
+{
+ if (startIndex == -1)
+ startIndex = data.listItems(element).size();
+ return nextValidIndex(data.listItems(element), startIndex, SkipBackwards, 1);
+}
+
+static int firstSelectableListIndex(SelectElementData& data, Element* element)
+{
+ const Vector<Element*>& items = data.listItems(element);
+ int index = nextValidIndex(items, items.size(), SkipBackwards, INT_MAX);
+ if (static_cast<unsigned>(index) == items.size())
+ return -1;
+ return index;
+}
+
+static int lastSelectableListIndex(SelectElementData& data, Element* element)
+{
+ return nextValidIndex(data.listItems(element), -1, SkipForwards, INT_MAX);
+}
+
+// Returns the index of the next valid item one page away from |startIndex| in direction |direction|.
+static int nextSelectableListIndexPageAway(SelectElementData& data, Element* element, int startIndex, SkipDirection direction)
+{
+ const Vector<Element*>& items = data.listItems(element);
+ // Can't use data->size() because renderer forces a minimum size.
+ int pageSize = 0;
+ if (element->renderer()->isListBox())
+ pageSize = toRenderListBox(element->renderer())->size() - 1; // -1 so we still show context
+
+ // One page away, but not outside valid bounds.
+ // If there is a valid option item one page away, the index is chosen.
+ // If there is no exact one page away valid option, returns startIndex or the most far index.
+ int edgeIndex = (direction == SkipForwards) ? 0 : (items.size() - 1);
+ int skipAmount = pageSize + ((direction == SkipForwards) ? startIndex : (edgeIndex - startIndex));
+ return nextValidIndex(items, edgeIndex, direction, skipAmount);
+}
+
void SelectElement::selectAll(SelectElementData& data, Element* element)
{
ASSERT(!data.usesMenuList());
@@ -104,30 +172,6 @@ void SelectElement::saveLastSelection(SelectElementData& data, Element* element)
}
}
-int SelectElement::nextSelectableListIndex(SelectElementData& data, Element* element, int startIndex)
-{
- const Vector<Element*>& items = data.listItems(element);
- int index = startIndex + 1;
- while (index >= 0 && (unsigned) index < items.size() && (!isOptionElement(items[index]) || items[index]->disabled()))
- ++index;
- if ((unsigned) index == items.size())
- return startIndex;
- return index;
-}
-
-int SelectElement::previousSelectableListIndex(SelectElementData& data, Element* element, int startIndex)
-{
- const Vector<Element*>& items = data.listItems(element);
- if (startIndex == -1)
- startIndex = items.size();
- int index = startIndex - 1;
- while (index >= 0 && (unsigned) index < items.size() && (!isOptionElement(items[index]) || items[index]->disabled()))
- --index;
- if (index == -1)
- return startIndex;
- return index;
-}
-
void SelectElement::setActiveSelectionAnchorIndex(SelectElementData& data, Element* element, int index)
{
data.setActiveSelectionAnchorIndex(index);
@@ -515,27 +559,6 @@ void SelectElement::reset(SelectElementData& data, Element* element)
setOptionsChangedOnRenderer(data, element);
element->setNeedsStyleRecalc();
}
-
-enum SkipDirection {
- SkipBackwards = -1,
- SkipForwards = 1
-};
-
-// Returns the index of the next valid list item |skip| items past |listIndex| in direction |direction|.
-static int nextValidIndex(const Vector<Element*>& listItems, int listIndex, SkipDirection direction, int skip)
-{
- int lastGoodIndex = listIndex;
- int size = listItems.size();
- for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex += direction) {
- --skip;
- if (!listItems[listIndex]->disabled() && isOptionElement(listItems[listIndex])) {
- lastGoodIndex = listIndex;
- if (skip <= 0)
- break;
- }
- }
- return lastGoodIndex;
-}
void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element* element, Event* event, HTMLFormElement* htmlForm)
{
@@ -594,8 +617,8 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element
listIndex = nextValidIndex(listItems, listItems.size(), SkipBackwards, 1);
handled = true;
}
-
- if (handled && listIndex >= 0 && (unsigned)listIndex < listItems.size())
+
+ if (handled && listIndex >= 0 && static_cast<unsigned>(listIndex) < listItems.size())
setSelectedIndex(data, element, listToOptionIndex(data, element, listIndex));
if (handled)
@@ -760,19 +783,47 @@ void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element*
return;
const String& keyIdentifier = static_cast<KeyboardEvent*>(event)->keyIdentifier();
- int endIndex = 0;
+ bool handled = false;
+ int endIndex = 0;
if (data.activeSelectionEndIndex() < 0) {
// Initialize the end index
- if (keyIdentifier == "Down")
- endIndex = nextSelectableListIndex(data, element, lastSelectedListIndex(data, element));
- else if (keyIdentifier == "Up")
- endIndex = previousSelectableListIndex(data, element, optionToListIndex(data, element, selectedIndex(data, element)));
+ if (keyIdentifier == "Down" || keyIdentifier == "PageDown") {
+ int startIndex = lastSelectedListIndex(data, element);
+ handled = true;
+ if (keyIdentifier == "Down")
+ endIndex = nextSelectableListIndex(data, element, startIndex);
+ else
+ endIndex = nextSelectableListIndexPageAway(data, element, startIndex, SkipForwards);
+ } else if (keyIdentifier == "Up" || keyIdentifier == "PageUp") {
+ int startIndex = optionToListIndex(data, element, selectedIndex(data, element));
+ handled = true;
+ if (keyIdentifier == "Up")
+ endIndex = previousSelectableListIndex(data, element, startIndex);
+ else
+ endIndex = nextSelectableListIndexPageAway(data, element, startIndex, SkipBackwards);
+ }
} else {
// Set the end index based on the current end index
- if (keyIdentifier == "Down")
+ if (keyIdentifier == "Down") {
endIndex = nextSelectableListIndex(data, element, data.activeSelectionEndIndex());
- else if (keyIdentifier == "Up")
- endIndex = previousSelectableListIndex(data, element, data.activeSelectionEndIndex());
+ handled = true;
+ } else if (keyIdentifier == "Up") {
+ endIndex = previousSelectableListIndex(data, element, data.activeSelectionEndIndex());
+ handled = true;
+ } else if (keyIdentifier == "PageDown") {
+ endIndex = nextSelectableListIndexPageAway(data, element, data.activeSelectionEndIndex(), SkipForwards);
+ handled = true;
+ } else if (keyIdentifier == "PageUp") {
+ endIndex = nextSelectableListIndexPageAway(data, element, data.activeSelectionEndIndex(), SkipBackwards);
+ handled = true;
+ }
+ }
+ if (keyIdentifier == "Home") {
+ endIndex = firstSelectableListIndex(data, element);
+ handled = true;
+ } else if (keyIdentifier == "End") {
+ endIndex = lastSelectableListIndex(data, element);
+ handled = true;
}
if (isSpatialNavigationEnabled(element->document()->frame()))
@@ -780,13 +831,13 @@ void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element*
if (keyIdentifier == "Left" || keyIdentifier == "Right" || ((keyIdentifier == "Down" || keyIdentifier == "Up") && endIndex == data.activeSelectionEndIndex()))
return;
- if (keyIdentifier == "Down" || keyIdentifier == "Up") {
+ if (endIndex >= 0 && handled) {
// Save the selection so it can be compared to the new selection when dispatching change events immediately after making the new selection.
saveLastSelection(data, element);
- ASSERT_UNUSED(listItems, !listItems.size() || (endIndex >= 0 && (unsigned) endIndex < listItems.size()));
+ ASSERT_UNUSED(listItems, !listItems.size() || (endIndex >= 0 && static_cast<unsigned>(endIndex) < listItems.size()));
setActiveSelectionEndIndex(data, endIndex);
-
+
bool selectNewItem = !data.multiple() || static_cast<KeyboardEvent*>(event)->shiftKey() || !isSpatialNavigationEnabled(element->document()->frame());
if (selectNewItem)
data.setActiveSelectionState(true);
diff --git a/Source/WebCore/dom/SelectElement.h b/Source/WebCore/dom/SelectElement.h
index 222a1bb..dd073a2 100644
--- a/Source/WebCore/dom/SelectElement.h
+++ b/Source/WebCore/dom/SelectElement.h
@@ -72,8 +72,6 @@ protected:
static void selectAll(SelectElementData&, Element*);
static void saveLastSelection(SelectElementData&, Element*);
- static int nextSelectableListIndex(SelectElementData&, Element*, int startIndex);
- static int previousSelectableListIndex(SelectElementData&, Element*, int startIndex);
static void setActiveSelectionAnchorIndex(SelectElementData&, Element*, int index);
static void setActiveSelectionEndIndex(SelectElementData&, int index);
static void updateListBoxSelection(SelectElementData&, Element*, bool deselectOtherOptions);
diff --git a/Source/WebCore/dom/ShadowRoot.cpp b/Source/WebCore/dom/ShadowRoot.cpp
new file mode 100644
index 0000000..8fe56b5
--- /dev/null
+++ b/Source/WebCore/dom/ShadowRoot.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ * * 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 "ShadowRoot.h"
+
+namespace WebCore {
+
+ShadowRoot::ShadowRoot(Document* document)
+ : DocumentFragment(document)
+{
+ ASSERT(document);
+}
+
+String ShadowRoot::nodeName() const
+{
+ return "#shadow-root";
+}
+
+void ShadowRoot::recalcStyle(StyleChange change)
+{
+ for (Node* n = firstChild(); n; n = n->nextSibling())
+ n->recalcStyle(change);
+
+ clearNeedsStyleRecalc();
+ clearChildNeedsStyleRecalc();
+}
+
+}
diff --git a/Source/WebCore/dom/ShadowRoot.h b/Source/WebCore/dom/ShadowRoot.h
new file mode 100644
index 0000000..aeccd8a
--- /dev/null
+++ b/Source/WebCore/dom/ShadowRoot.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ * * 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 ShadowRoot_h
+#define ShadowRoot_h
+
+#include "DocumentFragment.h"
+
+namespace WebCore {
+
+class Document;
+
+class ShadowRoot : public DocumentFragment {
+public:
+ static PassRefPtr<ShadowRoot> create(Document*);
+
+ virtual bool isShadowBoundary() const { return true; }
+ virtual void recalcStyle(StyleChange = NoChange);
+
+private:
+ ShadowRoot(Document*);
+ virtual String nodeName() const;
+};
+
+inline PassRefPtr<ShadowRoot> ShadowRoot::create(Document* document)
+{
+ return adoptRef(new ShadowRoot(document));
+}
+
+} // namespace
+
+#endif
diff --git a/Source/WebCore/dom/StyledElement.cpp b/Source/WebCore/dom/StyledElement.cpp
index 3c55591..6781ed5 100644
--- a/Source/WebCore/dom/StyledElement.cpp
+++ b/Source/WebCore/dom/StyledElement.cpp
@@ -233,18 +233,9 @@ void StyledElement::classAttributeChanged(const AtomicString& newClassString)
void StyledElement::parseMappedAttribute(Attribute* attr)
{
- if (isIdAttributeName(attr->name())) {
- setHasID(!attr->isNull());
- if (attributeMap()) {
- if (attr->isNull())
- attributeMap()->setIdForStyleResolution(nullAtom);
- else if (document()->inQuirksMode())
- attributeMap()->setIdForStyleResolution(attr->value().lower());
- else
- attributeMap()->setIdForStyleResolution(attr->value());
- }
- setNeedsStyleRecalc();
- } else if (attr->name() == classAttr)
+ if (isIdAttributeName(attr->name()))
+ idAttributeChanged(attr);
+ else if (attr->name() == classAttr)
classAttributeChanged(attr->value());
else if (attr->name() == styleAttr) {
if (attr->isNull())
diff --git a/Source/WebCore/dom/Text.cpp b/Source/WebCore/dom/Text.cpp
index 5a28e37..906e421 100644
--- a/Source/WebCore/dom/Text.cpp
+++ b/Source/WebCore/dom/Text.cpp
@@ -292,7 +292,7 @@ void Text::recalcStyle(StyleChange change)
clearNeedsStyleRecalc();
}
-bool Text::childTypeAllowed(NodeType)
+bool Text::childTypeAllowed(NodeType) const
{
return false;
}
diff --git a/Source/WebCore/dom/Text.h b/Source/WebCore/dom/Text.h
index f693f3b..5995f1f 100644
--- a/Source/WebCore/dom/Text.h
+++ b/Source/WebCore/dom/Text.h
@@ -56,7 +56,7 @@ private:
virtual bool rendererIsNeeded(RenderStyle*);
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
virtual void recalcStyle(StyleChange = NoChange);
- virtual bool childTypeAllowed(NodeType);
+ virtual bool childTypeAllowed(NodeType) const;
virtual PassRefPtr<Text> virtualCreate(const String&);
diff --git a/Source/WebCore/dom/TreeScope.cpp b/Source/WebCore/dom/TreeScope.cpp
new file mode 100644
index 0000000..a995a2d
--- /dev/null
+++ b/Source/WebCore/dom/TreeScope.cpp
@@ -0,0 +1,170 @@
+/*
+ * 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TreeScope.h"
+
+#include "Element.h"
+#include "HTMLAnchorElement.h"
+#include "HTMLMapElement.h"
+#include "HTMLNames.h"
+#include "NodeRareData.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+TreeScope::TreeScope(Document* document, ConstructionType constructionType)
+ : ContainerNode(0, constructionType)
+ , m_parentTreeScope(0)
+ , m_accessKeyMapValid(false)
+ , m_numNodeListCaches(0)
+{
+ m_document = document;
+ if (document != this) {
+ // Assume document as parent scope
+ m_parentTreeScope = document;
+ // FIXME: This branch should be inert until shadow scopes are landed.
+ ASSERT_NOT_REACHED();
+ }
+}
+
+TreeScope::~TreeScope()
+{
+ if (hasRareData())
+ rareData()->setTreeScope(0);
+}
+
+void TreeScope::destroyTreeScopeData()
+{
+ m_elementsById.clear();
+ m_imageMapsByName.clear();
+ m_elementsByAccessKey.clear();
+}
+
+void TreeScope::setParentTreeScope(TreeScope* newParentScope)
+{
+ // A document node cannot be re-parented.
+ ASSERT(!isDocumentNode());
+ // Every scope other than document needs a parent scope.
+ ASSERT(m_parentTreeScope);
+ ASSERT(newParentScope);
+
+ m_parentTreeScope = newParentScope;
+}
+
+Element* TreeScope::getElementById(const AtomicString& elementId) const
+{
+ if (elementId.isEmpty())
+ return 0;
+ return m_elementsById.getElementById(elementId.impl(), this);
+}
+
+void TreeScope::addElementById(const AtomicString& elementId, Element* element)
+{
+ m_elementsById.add(elementId.impl(), element);
+}
+
+void TreeScope::removeElementById(const AtomicString& elementId, Element* element)
+{
+ m_elementsById.remove(elementId.impl(), element);
+}
+
+Element* TreeScope::getElementByAccessKey(const String& key) const
+{
+ if (key.isEmpty())
+ return 0;
+ if (!m_accessKeyMapValid) {
+ for (Node* n = firstChild(); n; n = n->traverseNextNode()) {
+ if (!n->isElementNode())
+ continue;
+ Element* element = static_cast<Element*>(n);
+ const AtomicString& accessKey = element->getAttribute(accesskeyAttr);
+ if (!accessKey.isEmpty())
+ m_elementsByAccessKey.set(accessKey.impl(), element);
+ }
+ m_accessKeyMapValid = true;
+ }
+ return m_elementsByAccessKey.get(key.impl());
+}
+
+void TreeScope::invalidateAccessKeyMap()
+{
+ m_accessKeyMapValid = false;
+ m_elementsByAccessKey.clear();
+}
+
+void TreeScope::addImageMap(HTMLMapElement* imageMap)
+{
+ AtomicStringImpl* name = imageMap->getName().impl();
+ if (!name)
+ return;
+ m_imageMapsByName.add(name, imageMap);
+}
+
+void TreeScope::removeImageMap(HTMLMapElement* imageMap)
+{
+ AtomicStringImpl* name = imageMap->getName().impl();
+ if (!name)
+ return;
+ m_imageMapsByName.remove(name, imageMap);
+}
+
+HTMLMapElement* TreeScope::getImageMap(const String& url) const
+{
+ if (url.isNull())
+ return 0;
+ size_t hashPos = url.find('#');
+ String name = (hashPos == notFound ? url : url.substring(hashPos + 1)).impl();
+ if (document()->isHTMLDocument())
+ return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByLowercasedMapName(AtomicString(name.lower()).impl(), this));
+ return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByMapName(AtomicString(name).impl(), this));
+}
+
+Element* TreeScope::findAnchor(const String& name)
+{
+ if (name.isEmpty())
+ return 0;
+ if (Element* element = getElementById(name))
+ return element;
+ for (Node* node = this; node; node = node->traverseNextNode()) {
+ if (node->hasTagName(aTag)) {
+ HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(node);
+ if (document()->inQuirksMode()) {
+ // Quirks mode, case insensitive comparison of names.
+ if (equalIgnoringCase(anchor->name(), name))
+ return anchor;
+ } else {
+ // Strict mode, names need to match exactly.
+ if (anchor->name() == name)
+ return anchor;
+ }
+ }
+ }
+ return 0;
+}
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/dom/TreeScope.h b/Source/WebCore/dom/TreeScope.h
new file mode 100644
index 0000000..6271541
--- /dev/null
+++ b/Source/WebCore/dom/TreeScope.h
@@ -0,0 +1,102 @@
+/*
+ * 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TreeScope_h
+#define TreeScope_h
+
+#include "ContainerNode.h"
+#include "DocumentOrderedMap.h"
+
+namespace WebCore {
+
+class Element;
+class HTMLMapElement;
+
+class TreeScope : public ContainerNode {
+ friend class Document;
+
+public:
+ TreeScope* parentTreeScope() const { return m_parentTreeScope; }
+
+ Element* getElementById(const AtomicString&) const;
+ bool hasElementWithId(AtomicStringImpl* id) const;
+ bool containsMultipleElementsWithId(const AtomicString& id) const;
+ void addElementById(const AtomicString& elementId, Element*);
+ void removeElementById(const AtomicString& elementId, Element*);
+
+ void addImageMap(HTMLMapElement*);
+ void removeImageMap(HTMLMapElement*);
+ HTMLMapElement* getImageMap(const String& url) const;
+
+ Element* getElementByAccessKey(const String& key) const;
+ void invalidateAccessKeyMap();
+
+ void addNodeListCache() { ++m_numNodeListCaches; }
+ void removeNodeListCache() { ASSERT(m_numNodeListCaches > 0); --m_numNodeListCaches; }
+ bool hasNodeListCaches() const { return m_numNodeListCaches; }
+
+ // Find first anchor with the given name.
+ // First searches for an element with the given ID, but if that fails, then looks
+ // for an anchor with the given name. ID matching is always case sensitive, but
+ // Anchor name matching is case sensitive in strict mode and not case sensitive in
+ // quirks mode for historical compatibility reasons.
+ Element* findAnchor(const String& name);
+
+protected:
+ TreeScope(Document*, ConstructionType = CreateContainer);
+
+ virtual ~TreeScope();
+
+ void destroyTreeScopeData();
+
+ void setParentTreeScope(TreeScope*);
+
+private:
+ TreeScope* m_parentTreeScope;
+
+ DocumentOrderedMap m_elementsById;
+ DocumentOrderedMap m_imageMapsByName;
+
+ mutable HashMap<StringImpl*, Element*, CaseFoldingHash> m_elementsByAccessKey;
+ mutable bool m_accessKeyMapValid;
+
+ unsigned m_numNodeListCaches;
+};
+
+inline bool TreeScope::hasElementWithId(AtomicStringImpl* id) const
+{
+ ASSERT(id);
+ return m_elementsById.contains(id);
+}
+
+inline bool TreeScope::containsMultipleElementsWithId(const AtomicString& id) const
+{
+ return m_elementsById.containsMultiple(id.impl());
+}
+
+} // namespace WebCore
+
+#endif // TreeScope_h
+
diff --git a/Source/WebCore/dom/WheelEvent.cpp b/Source/WebCore/dom/WheelEvent.cpp
index 0981a57..a673c93 100644
--- a/Source/WebCore/dom/WheelEvent.cpp
+++ b/Source/WebCore/dom/WheelEvent.cpp
@@ -23,7 +23,10 @@
#include "config.h"
#include "WheelEvent.h"
+#include "EventDispatcher.h"
#include "EventNames.h"
+#include "PlatformWheelEvent.h"
+
#include <wtf/MathExtras.h>
namespace WebCore {
@@ -92,4 +95,32 @@ bool WheelEvent::isWheelEvent() const
return true;
}
+inline static WheelEvent::Granularity granularity(const PlatformWheelEvent& event)
+{
+ return event.granularity() == ScrollByPageWheelEvent ? WheelEvent::Page : WheelEvent::Pixel;
+}
+
+WheelEventDispatchMediator::WheelEventDispatchMediator(const PlatformWheelEvent& event, PassRefPtr<AbstractView> view)
+{
+ if (!(event.deltaX() || event.deltaY()))
+ return;
+
+ setEvent(WheelEvent::create(event.wheelTicksX(), event.wheelTicksY(), event.deltaX(), event.deltaY(), granularity(event),
+ view, event.globalX(), event.globalY(), event.x(), event.y(), event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey()));
+
+}
+
+WheelEvent* WheelEventDispatchMediator::event() const
+{
+ return static_cast<WheelEvent*>(EventDispatchMediator::event());
+}
+
+bool WheelEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
+{
+ if (!event())
+ return true;
+
+ return EventDispatchMediator::dispatchEvent(dispatcher) && !event()->defaultHandled();
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/dom/WheelEvent.h b/Source/WebCore/dom/WheelEvent.h
index b085e86..5f0d569 100644
--- a/Source/WebCore/dom/WheelEvent.h
+++ b/Source/WebCore/dom/WheelEvent.h
@@ -82,6 +82,15 @@ namespace WebCore {
Granularity m_granularity;
};
+class WheelEventDispatchMediator : public EventDispatchMediator {
+public:
+ WheelEventDispatchMediator(const PlatformWheelEvent&, PassRefPtr<AbstractView>);
+
+private:
+ WheelEvent* event() const;
+ virtual bool dispatchEvent(EventDispatcher*) const;
+};
+
} // namespace WebCore
#endif // WheelEvent_h
diff --git a/Source/WebCore/dom/XMLDocumentParserLibxml2.cpp b/Source/WebCore/dom/XMLDocumentParserLibxml2.cpp
index 9214391..85cf285 100644
--- a/Source/WebCore/dom/XMLDocumentParserLibxml2.cpp
+++ b/Source/WebCore/dom/XMLDocumentParserLibxml2.cpp
@@ -1341,25 +1341,21 @@ void XMLDocumentParser::doEnd()
#if ENABLE(XSLT)
XMLTreeViewer xmlTreeViewer(document());
-
bool xmlViewerMode = !m_sawError && !m_sawCSS && !m_sawXSLTransform && xmlTreeViewer.hasNoStyleInformation();
+ if (xmlViewerMode)
+ xmlTreeViewer.transformDocumentToTreeView();
- if (xmlViewerMode || m_sawXSLTransform) {
+ if (m_sawXSLTransform) {
void* doc = xmlDocPtrForString(document()->cachedResourceLoader(), m_originalSourceForTransform, document()->url().string());
document()->setTransformSource(new TransformSource(doc));
- if (xmlViewerMode)
- xmlTreeViewer.transformDocumentToTreeView();
- else {
- document()->setParsing(false); // Make the document think it's done, so it will apply XSL stylesheets.
- document()->styleSelectorChanged(RecalcStyleImmediately);
- document()->setParsing(true);
- }
+ document()->setParsing(false); // Make the document think it's done, so it will apply XSL stylesheets.
+ document()->styleSelectorChanged(RecalcStyleImmediately);
+ document()->setParsing(true);
DocumentParser::stopParsing();
}
#endif
-
}
#if ENABLE(XSLT)
diff --git a/Source/WebCore/dom/make_names.pl b/Source/WebCore/dom/make_names.pl
index 836137e..674831c 100755
--- a/Source/WebCore/dom/make_names.pl
+++ b/Source/WebCore/dom/make_names.pl
@@ -3,6 +3,7 @@
# Copyright (C) 2005, 2006, 2007, 2009 Apple Inc. All rights reserved.
# Copyright (C) 2009, Julien Chaffraix <jchaffraix@webkit.org>
# Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+# Copyright (C) 2011 Ericsson AB. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -65,7 +66,7 @@ if ($ENV{CC}) {
} else {
$gccLocation = "/usr/bin/gcc";
}
-my $preprocessor = $gccLocation . " -E -P -x c++";
+my $preprocessor = $gccLocation . " -E -x c++";
GetOptions(
'tags=s' => \$tagsFile,
@@ -596,6 +597,10 @@ sub printJSElementIncludes
for my $tagName (sort keys %enabledTags) {
my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName};
next if defined($tagsSeen{$JSInterfaceName}) || usesDefaultJSWrapper($tagName);
+ if ($enabledTags{$tagName}{conditional}) {
+ # We skip feature-define-specific #includes here since we handle them separately.
+ next;
+ }
$tagsSeen{$JSInterfaceName} = 1;
print F "#include \"${wrapperFactoryType}${JSInterfaceName}.h\"\n";
@@ -610,12 +615,54 @@ sub printElementIncludes
for my $tagName (sort keys %enabledTags) {
my $interfaceName = $enabledTags{$tagName}{interfaceName};
next if defined($tagsSeen{$interfaceName});
+ if ($enabledTags{$tagName}{conditional}) {
+ # We skip feature-define-specific #includes here since we handle them separately.
+ next;
+ }
$tagsSeen{$interfaceName} = 1;
print F "#include \"${interfaceName}.h\"\n";
}
}
+sub printConditionalElementIncludes
+{
+ my ($F, $wrapperFactoryType) = @_;
+
+ my %conditionals;
+ my %unconditionalElementIncludes;
+ my %unconditionalJSElementIncludes;
+
+ for my $tagName (keys %enabledTags) {
+ my $conditional = $enabledTags{$tagName}{conditional};
+ my $interfaceName = $enabledTags{$tagName}{interfaceName};
+ my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName};
+
+ if ($conditional) {
+ $conditionals{$conditional}{interfaceNames}{$interfaceName} = 1;
+ $conditionals{$conditional}{JSInterfaceNames}{$JSInterfaceName} = 1;
+ } else {
+ $unconditionalElementIncludes{$interfaceName} = 1;
+ $unconditionalJSElementIncludes{$JSInterfaceName} = 1;
+ }
+ }
+
+ for my $conditional (sort keys %conditionals) {
+ print F "\n#if ENABLE($conditional)\n";
+ for my $interfaceName (sort keys %{$conditionals{$conditional}{interfaceNames}}) {
+ next if $unconditionalElementIncludes{$interfaceName};
+ print F "#include \"$interfaceName.h\"\n";
+ }
+ if ($wrapperFactoryType) {
+ for my $JSInterfaceName (sort keys %{$conditionals{$conditional}{JSInterfaceNames}}) {
+ next if $unconditionalJSElementIncludes{$JSInterfaceName};
+ print F "#include \"$wrapperFactoryType$JSInterfaceName.h\"\n";
+ }
+ }
+ print F "#endif\n";
+ }
+}
+
sub printDefinitions
{
my ($F, $namesRef, $type, $namespaceURI) = @_;
@@ -661,8 +708,11 @@ END
printElementIncludes($F);
+print F "\n#include <wtf/HashMap.h>\n";
+
+printConditionalElementIncludes($F);
+
print F <<END
-#include <wtf/HashMap.h>
#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(VIDEO)
#include "Document.h"
@@ -922,8 +972,11 @@ sub printWrapperFactoryCppFile
printElementIncludes($F);
+ print F "\n#include <wtf/StdLibExtras.h>\n";
+
+ printConditionalElementIncludes($F, $wrapperFactoryType);
+
print F <<END
-#include <wtf/StdLibExtras.h>
#if ENABLE(VIDEO)
#include "Document.h"