Merge from Chromium at DEPS revision r198571

This commit was generated by merge_to_master.py.

Change-Id: I3a7f89ea6b8c017335bd52739166aed708cad1e5
diff --git a/Source/core/dom/ActiveDOMObject.cpp b/Source/core/dom/ActiveDOMObject.cpp
new file mode 100644
index 0000000..b15d2da
--- /dev/null
+++ b/Source/core/dom/ActiveDOMObject.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "core/dom/ActiveDOMObject.h"
+
+#include "core/dom/ScriptExecutionContext.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/workers/WorkerContext.h"
+#include "core/workers/WorkerThread.h"
+
+namespace WebCore {
+
+ActiveDOMObject::ActiveDOMObject(ScriptExecutionContext* scriptExecutionContext)
+    : ContextDestructionObserver(scriptExecutionContext)
+    , m_pendingActivityCount(0)
+#if !ASSERT_DISABLED
+    , m_suspendIfNeededCalled(false)
+#endif
+{
+    if (!m_scriptExecutionContext)
+        return;
+
+    ASSERT(m_scriptExecutionContext->isContextThread());
+    m_scriptExecutionContext->didCreateActiveDOMObject(this);
+}
+
+ActiveDOMObject::~ActiveDOMObject()
+{
+    if (!m_scriptExecutionContext)
+        return;
+
+    ASSERT(m_suspendIfNeededCalled);
+
+    // ActiveDOMObject may be inherited by a sub-class whose life-cycle
+    // exceeds that of the associated ScriptExecutionContext. In those cases,
+    // m_scriptExecutionContext would/should have been nullified by
+    // ContextDestructionObserver::contextDestroyed() (which we implement /
+    // inherit). Hence, we should ensure that this is not 0 before use it
+    // here.
+    if (m_scriptExecutionContext) {
+        ASSERT(m_scriptExecutionContext->isContextThread());
+        m_scriptExecutionContext->willDestroyActiveDOMObject(this);
+    }
+}
+
+void ActiveDOMObject::suspendIfNeeded()
+{
+#if !ASSERT_DISABLED
+    ASSERT(!m_suspendIfNeededCalled);
+    m_suspendIfNeededCalled = true;
+#endif
+    if (!m_scriptExecutionContext)
+        return;
+
+    m_scriptExecutionContext->suspendActiveDOMObjectIfNeeded(this);
+}
+
+bool ActiveDOMObject::hasPendingActivity() const
+{
+    return m_pendingActivityCount;
+}
+
+bool ActiveDOMObject::canSuspend() const
+{
+    return false;
+}
+
+void ActiveDOMObject::suspend(ReasonForSuspension)
+{
+}
+
+void ActiveDOMObject::resume()
+{
+}
+
+void ActiveDOMObject::stop()
+{
+}
+
+void ActiveDOMObject::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+}
+
+
+} // namespace WebCore
diff --git a/Source/core/dom/ActiveDOMObject.h b/Source/core/dom/ActiveDOMObject.h
new file mode 100644
index 0000000..d37017e
--- /dev/null
+++ b/Source/core/dom/ActiveDOMObject.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef ActiveDOMObject_h
+#define ActiveDOMObject_h
+
+#include "core/dom/ContextDestructionObserver.h"
+#include <wtf/Assertions.h>
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class ActiveDOMObject : public ContextDestructionObserver {
+public:
+    ActiveDOMObject(ScriptExecutionContext*);
+
+    // suspendIfNeeded() should be called exactly once after object construction to synchronize
+    // the suspend state with that in ScriptExecutionContext.
+    void suspendIfNeeded();
+#if !ASSERT_DISABLED
+    bool suspendIfNeededCalled() const { return m_suspendIfNeededCalled; }
+#endif
+
+    virtual bool hasPendingActivity() const;
+
+    // canSuspend() is used by the caller if there is a choice between suspending and stopping.
+    // For example, a page won't be suspended and placed in the back/forward cache if it has
+    // the objects that can not be suspended.
+    // However, 'suspend' can be called even if canSuspend() would return 'false'. That
+    // happens in step-by-step JS debugging for example - in this case it would be incorrect
+    // to stop the object. Exact semantics of suspend is up to the object then.
+    enum ReasonForSuspension {
+        JavaScriptDebuggerPaused,
+        WillDeferLoading,
+        DocumentWillBecomeInactive
+    };
+    virtual bool canSuspend() const;
+    virtual void suspend(ReasonForSuspension);
+    virtual void resume();
+    virtual void stop();
+
+    template<class T> void setPendingActivity(T* thisObject)
+    {
+        ASSERT(thisObject == this);
+        thisObject->ref();
+        m_pendingActivityCount++;
+    }
+
+    template<class T> void unsetPendingActivity(T* thisObject)
+    {
+        ASSERT(m_pendingActivityCount > 0);
+        --m_pendingActivityCount;
+        thisObject->deref();
+    }
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+
+protected:
+    virtual ~ActiveDOMObject();
+
+private:
+    unsigned m_pendingActivityCount;
+#if !ASSERT_DISABLED
+    bool m_suspendIfNeededCalled;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // ActiveDOMObject_h
diff --git a/Source/core/dom/AnimationEvent.cpp b/Source/core/dom/AnimationEvent.cpp
new file mode 100644
index 0000000..b583c06
--- /dev/null
+++ b/Source/core/dom/AnimationEvent.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/AnimationEvent.h"
+
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+AnimationEventInit::AnimationEventInit()
+    : animationName()
+    , elapsedTime(0.0)
+{
+}
+
+AnimationEvent::AnimationEvent()
+    : m_elapsedTime(0.0)
+{
+    ScriptWrappable::init(this);
+}
+
+AnimationEvent::AnimationEvent(const AtomicString& type, const AnimationEventInit& initializer)
+    : Event(type, initializer)
+    , m_animationName(initializer.animationName)
+    , m_elapsedTime(initializer.elapsedTime)
+{
+    ScriptWrappable::init(this);
+}
+
+AnimationEvent::AnimationEvent(const AtomicString& type, const String& animationName, double elapsedTime)
+    : Event(type, true, true)
+    , m_animationName(animationName)
+    , m_elapsedTime(elapsedTime)
+{
+    ScriptWrappable::init(this);
+}
+
+AnimationEvent::~AnimationEvent()
+{
+}
+
+const String& AnimationEvent::animationName() const
+{
+    return m_animationName;
+}
+
+double AnimationEvent::elapsedTime() const
+{
+    return m_elapsedTime;
+}
+
+const AtomicString& AnimationEvent::interfaceName() const
+{
+    return eventNames().interfaceForAnimationEvent;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/AnimationEvent.h b/Source/core/dom/AnimationEvent.h
new file mode 100644
index 0000000..3eadf3d
--- /dev/null
+++ b/Source/core/dom/AnimationEvent.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AnimationEvent_h
+#define AnimationEvent_h
+
+#include "core/dom/Event.h"
+
+namespace WebCore {
+
+struct AnimationEventInit : public EventInit {
+    AnimationEventInit();
+
+    String animationName;
+    double elapsedTime;
+};
+
+class AnimationEvent : public Event {
+public:
+    static PassRefPtr<AnimationEvent> create()
+    {
+        return adoptRef(new AnimationEvent);
+    }
+    static PassRefPtr<AnimationEvent> create(const AtomicString& type, const String& animationName, double elapsedTime)
+    {
+        return adoptRef(new AnimationEvent(type, animationName, elapsedTime));
+    }
+    static PassRefPtr<AnimationEvent> create(const AtomicString& type, const AnimationEventInit& initializer)
+    {
+        return adoptRef(new AnimationEvent(type, initializer));
+    }
+
+    virtual ~AnimationEvent();
+
+    const String& animationName() const;
+    double elapsedTime() const;
+
+    virtual const AtomicString& interfaceName() const;
+
+private:
+    AnimationEvent();
+    AnimationEvent(const AtomicString& type, const String& animationName, double elapsedTime);
+    AnimationEvent(const AtomicString&, const AnimationEventInit&);
+
+    String m_animationName;
+    double m_elapsedTime;
+};
+
+} // namespace WebCore
+
+#endif // AnimationEvent_h
diff --git a/Source/core/dom/AnimationEvent.idl b/Source/core/dom/AnimationEvent.idl
new file mode 100644
index 0000000..46ff164
--- /dev/null
+++ b/Source/core/dom/AnimationEvent.idl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    ConstructorTemplate=Event,
+    InterfaceName=WebKitAnimationEvent
+] interface AnimationEvent : Event {
+    [InitializedByEventConstructor] readonly attribute DOMString animationName;
+    [InitializedByEventConstructor] readonly attribute double elapsedTime;
+};
+
diff --git a/Source/core/dom/Attr.cpp b/Source/core/dom/Attr.cpp
new file mode 100644
index 0000000..b71a1e2
--- /dev/null
+++ b/Source/core/dom/Attr.cpp
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Peter Kelly (pmk@post.com)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2012 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include "config.h"
+#include "core/dom/Attr.h"
+
+#include "HTMLNames.h"
+#include "XMLNSNames.h"
+#include "core/css/StylePropertySet.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/ScopedEventQueue.h"
+#include "core/dom/StyledElement.h"
+#include "core/dom/Text.h"
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+Attr::Attr(Element* element, const QualifiedName& name)
+    : ContainerNode(element->document())
+    , m_element(element)
+    , m_name(name)
+    , m_ignoreChildrenChanged(0)
+    , m_specified(true)
+{
+    ScriptWrappable::init(this);
+}
+
+Attr::Attr(Document* document, const QualifiedName& name, const AtomicString& standaloneValue)
+    : ContainerNode(document)
+    , m_element(0)
+    , m_name(name)
+    , m_standaloneValue(standaloneValue)
+    , m_ignoreChildrenChanged(0)
+    , m_specified(true)
+{
+    ScriptWrappable::init(this);
+}
+
+PassRefPtr<Attr> Attr::create(Element* element, const QualifiedName& name)
+{
+    RefPtr<Attr> attr = adoptRef(new Attr(element, name));
+    attr->createTextChild();
+    return attr.release();
+}
+
+PassRefPtr<Attr> Attr::create(Document* document, const QualifiedName& name, const AtomicString& value)
+{
+    RefPtr<Attr> attr = adoptRef(new Attr(document, name, value));
+    attr->createTextChild();
+    return attr.release();
+}
+
+Attr::~Attr()
+{
+}
+
+void Attr::createTextChild()
+{
+    ASSERT(refCount());
+    if (!value().isEmpty()) {
+        RefPtr<Text> textNode = document()->createTextNode(value().string());
+
+        // This does everything appendChild() would do in this situation (assuming m_ignoreChildrenChanged was set),
+        // but much more efficiently.
+        textNode->setParentOrShadowHostNode(this);
+        setFirstChild(textNode.get());
+        setLastChild(textNode.get());
+    }
+}
+
+void Attr::setPrefix(const AtomicString& prefix, ExceptionCode& ec)
+{
+    ec = 0;
+    checkSetPrefix(prefix, ec);
+    if (ec)
+        return;
+
+    if ((prefix == xmlnsAtom && namespaceURI() != XMLNSNames::xmlnsNamespaceURI)
+        || static_cast<Attr*>(this)->qualifiedName() == xmlnsAtom) {
+        ec = NAMESPACE_ERR;
+        return;
+    }
+
+    const AtomicString& newPrefix = prefix.isEmpty() ? nullAtom : prefix;
+
+    if (m_element)
+        elementAttribute().setPrefix(newPrefix);
+    m_name.setPrefix(newPrefix);
+}
+
+void Attr::setValue(const AtomicString& value)
+{
+    EventQueueScope scope;
+    m_ignoreChildrenChanged++;
+    removeChildren();
+    if (m_element)
+        elementAttribute().setValue(value);
+    else
+        m_standaloneValue = value;
+    createTextChild();
+    m_ignoreChildrenChanged--;
+
+    invalidateNodeListCachesInAncestors(&m_name, m_element);
+}
+
+void Attr::setValue(const AtomicString& value, ExceptionCode&)
+{
+    if (m_element)
+        m_element->willModifyAttribute(qualifiedName(), this->value(), value);
+
+    setValue(value);
+
+    if (m_element)
+        m_element->didModifyAttribute(qualifiedName(), value);
+}
+
+void Attr::setNodeValue(const String& v, ExceptionCode& ec)
+{
+    setValue(v, ec);
+}
+
+PassRefPtr<Node> Attr::cloneNode(bool /*deep*/)
+{
+    RefPtr<Attr> clone = adoptRef(new Attr(document(), qualifiedName(), value()));
+    cloneChildNodes(clone.get());
+    return clone.release();
+}
+
+// DOM Section 1.1.1
+bool Attr::childTypeAllowed(NodeType type) const
+{
+    switch (type) {
+        case TEXT_NODE:
+        case ENTITY_REFERENCE_NODE:
+            return true;
+        default:
+            return false;
+    }
+}
+
+void Attr::childrenChanged(bool, Node*, Node*, int)
+{
+    if (m_ignoreChildrenChanged > 0)
+        return;
+
+    invalidateNodeListCachesInAncestors(&qualifiedName(), m_element);
+
+    // FIXME: We should include entity references in the value
+
+    StringBuilder valueBuilder;
+    for (Node *n = firstChild(); n; n = n->nextSibling()) {
+        if (n->isTextNode())
+            valueBuilder.append(toText(n)->data());
+    }
+
+    AtomicString newValue = valueBuilder.toAtomicString();
+    if (m_element)
+        m_element->willModifyAttribute(qualifiedName(), value(), newValue);
+
+    if (m_element)
+        elementAttribute().setValue(newValue);
+    else
+        m_standaloneValue = newValue;
+
+    if (m_element)
+        m_element->attributeChanged(qualifiedName(), newValue);
+}
+
+bool Attr::isId() const
+{
+    return qualifiedName().matches(document()->idAttributeName());
+}
+
+CSSStyleDeclaration* Attr::style()
+{
+    // This function only exists to support the Obj-C bindings.
+    if (!m_element || !m_element->isStyledElement())
+        return 0;
+    m_style = StylePropertySet::create();
+    static_cast<StyledElement*>(m_element)->collectStyleForPresentationAttribute(qualifiedName(), value(), static_cast<MutableStylePropertySet*>(m_style.get()));
+    return m_style->ensureCSSStyleDeclaration();
+}
+
+const AtomicString& Attr::value() const
+{
+    if (m_element)
+        return m_element->getAttribute(qualifiedName());
+    return m_standaloneValue;
+}
+
+Attribute& Attr::elementAttribute()
+{
+    ASSERT(m_element);
+    ASSERT(m_element->elementData());
+    return *m_element->ensureUniqueElementData()->getAttributeItem(qualifiedName());
+}
+
+void Attr::detachFromElementWithValue(const AtomicString& value)
+{
+    ASSERT(m_element);
+    ASSERT(m_standaloneValue.isNull());
+    m_standaloneValue = value;
+    m_element = 0;
+}
+
+void Attr::attachToElement(Element* element)
+{
+    ASSERT(!m_element);
+    m_element = element;
+    m_standaloneValue = nullAtom;
+}
+
+}
diff --git a/Source/core/dom/Attr.h b/Source/core/dom/Attr.h
new file mode 100644
index 0000000..c525725
--- /dev/null
+++ b/Source/core/dom/Attr.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Peter Kelly (pmk@post.com)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Attr_h
+#define Attr_h
+
+#include "core/dom/ContainerNode.h"
+#include "core/dom/QualifiedName.h"
+
+namespace WebCore {
+
+class CSSStyleDeclaration;
+class StylePropertySet;
+
+// Attr can have Text and EntityReference children
+// therefore it has to be a fullblown Node. The plan
+// is to dynamically allocate a textchild and store the
+// resulting nodevalue in the attribute upon
+// destruction. however, this is not yet implemented.
+
+class Attr FINAL : public ContainerNode {
+public:
+    static PassRefPtr<Attr> create(Element*, const QualifiedName&);
+    static PassRefPtr<Attr> create(Document*, const QualifiedName&, const AtomicString& value);
+    virtual ~Attr();
+
+    String name() const { return qualifiedName().toString(); }
+    bool specified() const { return m_specified; }
+    Element* ownerElement() const { return m_element; }
+
+    const AtomicString& value() const;
+    void setValue(const AtomicString&, ExceptionCode&);
+    void setValue(const AtomicString&);
+
+    const QualifiedName& qualifiedName() const { return m_name; }
+
+    bool isId() const;
+
+    CSSStyleDeclaration* style();
+
+    void setSpecified(bool specified) { m_specified = specified; }
+
+    void attachToElement(Element*);
+    void detachFromElementWithValue(const AtomicString&);
+
+private:
+    Attr(Element*, const QualifiedName&);
+    Attr(Document*, const QualifiedName&, const AtomicString& value);
+
+    void createTextChild();
+
+    virtual String nodeName() const OVERRIDE { return name(); }
+    virtual NodeType nodeType() const OVERRIDE { return ATTRIBUTE_NODE; }
+
+    const AtomicString& localName() const { return m_name.localName(); }
+    const AtomicString& namespaceURI() const { return m_name.namespaceURI(); }
+    const AtomicString& prefix() const { return m_name.prefix(); }
+
+    virtual void setPrefix(const AtomicString&, ExceptionCode&);
+
+    virtual String nodeValue() const OVERRIDE { return value(); }
+    virtual void setNodeValue(const String&, ExceptionCode&);
+    virtual PassRefPtr<Node> cloneNode(bool deep);
+
+    virtual bool isAttributeNode() const { return true; }
+    virtual bool childTypeAllowed(NodeType) const;
+
+    virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
+
+    virtual const AtomicString& virtualPrefix() const { return prefix(); }
+    virtual const AtomicString& virtualLocalName() const { return localName(); }
+    virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); }
+
+    Attribute& elementAttribute();
+
+    // Attr wraps either an element/name, or a name/value pair (when it's a standalone Node.)
+    // Note that m_name is always set, but m_element/m_standaloneValue may be null.
+    Element* m_element;
+    QualifiedName m_name;
+    AtomicString m_standaloneValue;
+
+    RefPtr<StylePropertySet> m_style;
+    unsigned m_ignoreChildrenChanged : 31;
+    bool m_specified : 1;
+};
+
+} // namespace WebCore
+
+#endif // Attr_h
diff --git a/Source/core/dom/Attr.idl b/Source/core/dom/Attr.idl
new file mode 100644
index 0000000..de9d951
--- /dev/null
+++ b/Source/core/dom/Attr.idl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+interface Attr : Node {
+
+    // DOM Level 1
+
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString name;
+
+    readonly attribute boolean specified;
+
+             [TreatReturnedNullStringAs=Null, TreatNullAs=NullString, SetterRaisesException] attribute DOMString value;
+
+    // DOM Level 2
+
+    readonly attribute Element ownerElement;
+
+    // DOM Level 3
+
+    readonly attribute boolean isId;
+};
+
diff --git a/Source/core/dom/Attribute.h b/Source/core/dom/Attribute.h
new file mode 100644
index 0000000..3dece08
--- /dev/null
+++ b/Source/core/dom/Attribute.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Peter Kelly (pmk@post.com)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2012 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Attribute_h
+#define Attribute_h
+
+#include "core/dom/QualifiedName.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+
+namespace WebCore {
+
+// This has no counterpart in DOM.
+// It is an internal representation of the node value of an Attr.
+// The actual Attr with its value as a Text child is allocated only if needed.
+class Attribute {
+public:
+    Attribute(const QualifiedName& name, const AtomicString& value)
+        : m_name(name)
+        , m_value(value)
+    {
+    }
+
+    // NOTE: The references returned by these functions are only valid for as long
+    // as the Attribute stays in place. For example, calling a function that mutates
+    // an Element's internal attribute storage may invalidate them.
+    const AtomicString& value() const { return m_value; }
+    const AtomicString& prefix() const { return m_name.prefix(); }
+    const AtomicString& localName() const { return m_name.localName(); }
+    const AtomicString& namespaceURI() const { return m_name.namespaceURI(); }
+
+    const QualifiedName& name() const { return m_name; }
+
+    bool isEmpty() const { return m_value.isEmpty(); }
+    bool matches(const QualifiedName&) const;
+
+    void setValue(const AtomicString& value) { m_value = value; }
+    void setPrefix(const AtomicString& prefix) { m_name.setPrefix(prefix); }
+
+    // Note: This API is only for HTMLTreeBuilder.  It is not safe to change the
+    // name of an attribute once parseAttribute has been called as DOM
+    // elements may have placed the Attribute in a hash by name.
+    void parserSetName(const QualifiedName& name) { m_name = name; }
+
+    void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+    {
+        MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+        info.addMember(m_name, "name");
+        info.addMember(m_value, "value");
+    }
+
+#if COMPILER(MSVC)
+    // NOTE: This constructor is not actually implemented, it's just defined so MSVC
+    // will let us use a zero-length array of Attributes.
+    Attribute();
+#endif
+
+private:
+    QualifiedName m_name;
+    AtomicString m_value;
+};
+
+inline bool Attribute::matches(const QualifiedName& qualifiedName) const
+{
+    if (qualifiedName.localName() != localName())
+        return false;
+    return qualifiedName.prefix() == starAtom || qualifiedName.namespaceURI() == namespaceURI();
+}
+
+} // namespace WebCore
+
+#endif // Attribute_h
diff --git a/Source/core/dom/AutocompleteErrorEvent.h b/Source/core/dom/AutocompleteErrorEvent.h
new file mode 100644
index 0000000..1f35fe3
--- /dev/null
+++ b/Source/core/dom/AutocompleteErrorEvent.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2013 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. AND ITS 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 APPLE INC. OR ITS 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 AutocompleteErrorEvent_h
+#define AutocompleteErrorEvent_h
+
+#include "core/dom/Event.h"
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+struct AutocompleteErrorEventInit : public EventInit {
+    String reason;
+};
+
+class AutocompleteErrorEvent : public Event {
+public:
+    static PassRefPtr<AutocompleteErrorEvent> create()
+    {
+        return adoptRef(new AutocompleteErrorEvent);
+    }
+
+    static PassRefPtr<AutocompleteErrorEvent> create(const String& reason)
+    {
+        return adoptRef(new AutocompleteErrorEvent(reason));
+    }
+
+    static PassRefPtr<AutocompleteErrorEvent> create(const AtomicString& eventType, const AutocompleteErrorEventInit& initializer)
+    {
+        return adoptRef(new AutocompleteErrorEvent(eventType, initializer));
+    }
+
+    const String& reason() const { return m_reason; }
+
+    virtual const AtomicString& interfaceName() const { return eventNames().interfaceForAutocompleteErrorEvent; }
+
+private:
+    AutocompleteErrorEvent()
+    {
+        ScriptWrappable::init(this);
+    }
+
+    AutocompleteErrorEvent(const String& reason)
+        : Event(eventNames().autocompleteerrorEvent, false, false)
+        , m_reason(reason)
+    {
+        ScriptWrappable::init(this);
+    }
+
+    AutocompleteErrorEvent(const AtomicString& eventType, const AutocompleteErrorEventInit& initializer)
+        : Event(eventType, initializer)
+        , m_reason(initializer.reason)
+    {
+        ScriptWrappable::init(this);
+    }
+
+    String m_reason;
+};
+
+} // namespace WebCore
+
+#endif // AutocompleteErrorEvent_h
diff --git a/Source/core/dom/AutocompleteErrorEvent.idl b/Source/core/dom/AutocompleteErrorEvent.idl
new file mode 100644
index 0000000..807ef04
--- /dev/null
+++ b/Source/core/dom/AutocompleteErrorEvent.idl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013 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. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+[
+    ConstructorTemplate=Event
+] interface AutocompleteErrorEvent : Event {
+    [InitializedByEventConstructor] readonly attribute DOMString reason;
+};
+
diff --git a/Source/core/dom/BeforeLoadEvent.h b/Source/core/dom/BeforeLoadEvent.h
new file mode 100644
index 0000000..946693b
--- /dev/null
+++ b/Source/core/dom/BeforeLoadEvent.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef BeforeLoadEvent_h
+#define BeforeLoadEvent_h
+
+#include "core/dom/Event.h"
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+struct BeforeLoadEventInit : public EventInit {
+    BeforeLoadEventInit()
+    {
+    };
+
+    String url;
+};
+
+class BeforeLoadEvent : public Event {
+public:
+    static PassRefPtr<BeforeLoadEvent> create()
+    {
+        return adoptRef(new BeforeLoadEvent);
+    }
+
+    static PassRefPtr<BeforeLoadEvent> create(const String& url)
+    {
+        return adoptRef(new BeforeLoadEvent(url));
+    }
+
+    static PassRefPtr<BeforeLoadEvent> create(const AtomicString& type, const BeforeLoadEventInit& initializer)
+    {
+        return adoptRef(new BeforeLoadEvent(type, initializer));
+    }
+
+    const String& url() const { return m_url; }
+
+    virtual const AtomicString& interfaceName() const { return eventNames().interfaceForBeforeLoadEvent; }
+
+private:
+    BeforeLoadEvent()
+    {
+        ScriptWrappable::init(this);
+    }
+
+    explicit BeforeLoadEvent(const String& url)
+        : Event(eventNames().beforeloadEvent, false, true)
+        , m_url(url)
+    {
+        ScriptWrappable::init(this);
+    }
+
+    BeforeLoadEvent(const AtomicString& type, const BeforeLoadEventInit& initializer)
+        : Event(type, initializer)
+        , m_url(initializer.url)
+    {
+        ScriptWrappable::init(this);
+    }
+
+    String m_url;
+};
+
+} // namespace WebCore
+
+#endif // BeforeLoadEvent_h
diff --git a/Source/core/dom/BeforeLoadEvent.idl b/Source/core/dom/BeforeLoadEvent.idl
new file mode 100644
index 0000000..54b8501
--- /dev/null
+++ b/Source/core/dom/BeforeLoadEvent.idl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+[
+    ConstructorTemplate=Event
+] interface BeforeLoadEvent : Event {
+    [InitializedByEventConstructor] readonly attribute DOMString url;
+};
+
diff --git a/Source/core/dom/BeforeTextInsertedEvent.cpp b/Source/core/dom/BeforeTextInsertedEvent.cpp
new file mode 100644
index 0000000..213737c
--- /dev/null
+++ b/Source/core/dom/BeforeTextInsertedEvent.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "core/dom/BeforeTextInsertedEvent.h"
+
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+BeforeTextInsertedEvent::BeforeTextInsertedEvent(const String& text)
+    : Event(eventNames().webkitBeforeTextInsertedEvent, false, true), m_text(text)
+{
+}
+
+BeforeTextInsertedEvent::~BeforeTextInsertedEvent()
+{
+}
+
+const AtomicString& BeforeTextInsertedEvent::interfaceName() const
+{
+    // Notice that there is no BeforeTextInsertedEvent.idl.
+    return eventNames().interfaceForEvent;
+}
+
+}
diff --git a/Source/core/dom/BeforeTextInsertedEvent.h b/Source/core/dom/BeforeTextInsertedEvent.h
new file mode 100644
index 0000000..207daf6
--- /dev/null
+++ b/Source/core/dom/BeforeTextInsertedEvent.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+ 
+#ifndef BeforeTextInsertedEvent_h
+#define BeforeTextInsertedEvent_h
+
+#include "core/dom/Event.h"
+
+namespace WebCore {
+
+class BeforeTextInsertedEvent : public Event {
+public:
+    virtual ~BeforeTextInsertedEvent();
+
+    static PassRefPtr<BeforeTextInsertedEvent> create(const String& text)
+    {
+        return adoptRef(new BeforeTextInsertedEvent(text));
+    }
+
+    virtual const AtomicString& interfaceName() const;
+    virtual bool isBeforeTextInsertedEvent() const { return true; }
+
+    const String& text() const { return m_text; }
+    void setText(const String& s) { m_text = s; }
+
+private:
+    explicit BeforeTextInsertedEvent(const String&);
+
+    String m_text;
+};
+
+} // namespace
+
+#endif
diff --git a/Source/core/dom/BeforeUnloadEvent.cpp b/Source/core/dom/BeforeUnloadEvent.cpp
new file mode 100644
index 0000000..25f7b0e
--- /dev/null
+++ b/Source/core/dom/BeforeUnloadEvent.cpp
@@ -0,0 +1,49 @@
+/**
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2005, 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/BeforeUnloadEvent.h"
+
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+BeforeUnloadEvent::BeforeUnloadEvent()
+    : Event(eventNames().beforeunloadEvent, false, true)
+{
+}
+
+BeforeUnloadEvent::~BeforeUnloadEvent()
+{
+}
+
+bool BeforeUnloadEvent::storesResultAsString() const
+{
+    return true;
+}
+
+void BeforeUnloadEvent::storeResult(const String& s)
+{
+    m_result = s;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/BeforeUnloadEvent.h b/Source/core/dom/BeforeUnloadEvent.h
new file mode 100644
index 0000000..c3be346
--- /dev/null
+++ b/Source/core/dom/BeforeUnloadEvent.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BeforeUnloadEvent_h
+#define BeforeUnloadEvent_h
+
+#include "core/dom/Event.h"
+
+namespace WebCore {
+
+    class BeforeUnloadEvent : public Event {
+    public:
+        virtual ~BeforeUnloadEvent();
+
+        static PassRefPtr<BeforeUnloadEvent> create()
+        {
+            return adoptRef(new BeforeUnloadEvent);
+        }
+
+        virtual bool storesResultAsString() const;
+        virtual void storeResult(const String&);
+
+        String result() const { return m_result; }
+
+    private:
+        BeforeUnloadEvent();
+
+        String m_result;
+    };
+
+} // namespace WebCore
+
+#endif // BeforeUnloadEvent_h
diff --git a/Source/core/dom/CDATASection.cpp b/Source/core/dom/CDATASection.cpp
new file mode 100644
index 0000000..5e19e27
--- /dev/null
+++ b/Source/core/dom/CDATASection.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/CDATASection.h"
+
+#include "core/dom/Document.h"
+
+namespace WebCore {
+
+inline CDATASection::CDATASection(Document* document, const String& data)
+    : Text(document, data, CreateText)
+{
+    ScriptWrappable::init(this);
+}
+
+PassRefPtr<CDATASection> CDATASection::create(Document* document, const String& data)
+{
+    return adoptRef(new CDATASection(document, data));
+}
+
+String CDATASection::nodeName() const
+{
+    return "#cdata-section";
+}
+
+Node::NodeType CDATASection::nodeType() const
+{
+    return CDATA_SECTION_NODE;
+}
+
+bool CDATASection::childTypeAllowed(NodeType) const
+{
+    return false;
+}
+
+PassRefPtr<Text> CDATASection::cloneWithData(const String& data)
+{
+    return create(document(), data);
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/CDATASection.h b/Source/core/dom/CDATASection.h
new file mode 100644
index 0000000..3adcd28
--- /dev/null
+++ b/Source/core/dom/CDATASection.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CDATASection_h
+#define CDATASection_h
+
+#include "core/dom/Text.h"
+
+namespace WebCore {
+
+class CDATASection FINAL : public Text {
+public:
+    static PassRefPtr<CDATASection> create(Document*, const String&);
+
+private:
+    CDATASection(Document*, const String&);
+
+    virtual String nodeName() const;
+    virtual NodeType nodeType() const;
+    virtual bool childTypeAllowed(NodeType) const;
+    virtual PassRefPtr<Text> cloneWithData(const String&) OVERRIDE;
+};
+
+} // namespace WebCore
+
+#endif // CDATASection_h
diff --git a/Source/core/dom/CDATASection.idl b/Source/core/dom/CDATASection.idl
new file mode 100644
index 0000000..939fe27
--- /dev/null
+++ b/Source/core/dom/CDATASection.idl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+interface CDATASection : Text {
+};
+
diff --git a/Source/core/dom/CharacterData.cpp b/Source/core/dom/CharacterData.cpp
new file mode 100644
index 0000000..67a7e7e
--- /dev/null
+++ b/Source/core/dom/CharacterData.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/CharacterData.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/MutationEvent.h"
+#include "core/dom/MutationObserverInterestGroup.h"
+#include "core/dom/MutationRecord.h"
+#include "core/dom/NodeRenderingContext.h"
+#include "core/dom/Text.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/editing/FrameSelection.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/platform/text/TextBreakIterator.h"
+#include "core/rendering/RenderText.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+using namespace std;
+
+namespace WebCore {
+
+void CharacterData::setData(const String& data, ExceptionCode&)
+{
+    const String& nonNullData = !data.isNull() ? data : emptyString();
+    if (m_data == nonNullData)
+        return;
+
+    RefPtr<CharacterData> protect = this;
+
+    unsigned oldLength = length();
+
+    setDataAndUpdate(nonNullData, 0, oldLength, nonNullData.length());
+    document()->textRemoved(this, 0, oldLength);
+}
+
+String CharacterData::substringData(unsigned offset, unsigned count, ExceptionCode& ec)
+{
+    checkCharDataOperation(offset, ec);
+    if (ec)
+        return String();
+
+    return m_data.substring(offset, count);
+}
+
+unsigned CharacterData::parserAppendData(const String& string, unsigned offset, unsigned lengthLimit)
+{
+    unsigned oldLength = m_data.length();
+
+    ASSERT(lengthLimit >= oldLength);
+
+    unsigned characterLength = string.length() - offset;
+    unsigned characterLengthLimit = min(characterLength, lengthLimit - oldLength);
+
+    // Check that we are not on an unbreakable boundary.
+    // Some text break iterator implementations work best if the passed buffer is as small as possible,
+    // see <https://bugs.webkit.org/show_bug.cgi?id=29092>.
+    // We need at least two characters look-ahead to account for UTF-16 surrogates.
+    if (characterLengthLimit < characterLength) {
+        NonSharedCharacterBreakIterator it(string.characters() + offset, (characterLengthLimit + 2 > characterLength) ? characterLength : characterLengthLimit + 2);
+        if (!isTextBreak(it, characterLengthLimit))
+            characterLengthLimit = textBreakPreceding(it, characterLengthLimit);
+    }
+
+    if (!characterLengthLimit)
+        return 0;
+
+    if (string.is8Bit())
+        m_data.append(string.characters8() + offset, characterLengthLimit);
+    else
+        m_data.append(string.characters16() + offset, characterLengthLimit);
+
+    ASSERT(!renderer() || isTextNode());
+    if (isTextNode())
+        toText(this)->updateTextRenderer(oldLength, 0);
+
+    document()->incDOMTreeVersion();
+    // We don't call dispatchModifiedEvent here because we don't want the
+    // parser to dispatch DOM mutation events.
+    if (parentNode())
+        parentNode()->childrenChanged();
+
+    return characterLengthLimit;
+}
+
+void CharacterData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    Node::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_data, "data");
+}
+
+void CharacterData::appendData(const String& data, ExceptionCode&)
+{
+    String newStr = m_data;
+    newStr.append(data);
+
+    setDataAndUpdate(newStr, m_data.length(), 0, data.length());
+
+    // FIXME: Should we call textInserted here?
+}
+
+void CharacterData::insertData(unsigned offset, const String& data, ExceptionCode& ec)
+{
+    checkCharDataOperation(offset, ec);
+    if (ec)
+        return;
+
+    String newStr = m_data;
+    newStr.insert(data, offset);
+
+    setDataAndUpdate(newStr, offset, 0, data.length());
+
+    document()->textInserted(this, offset, data.length());
+}
+
+void CharacterData::deleteData(unsigned offset, unsigned count, ExceptionCode& ec)
+{
+    checkCharDataOperation(offset, ec);
+    if (ec)
+        return;
+
+    unsigned realCount;
+    if (offset + count > length())
+        realCount = length() - offset;
+    else
+        realCount = count;
+
+    String newStr = m_data;
+    newStr.remove(offset, realCount);
+
+    setDataAndUpdate(newStr, offset, count, 0);
+
+    document()->textRemoved(this, offset, realCount);
+}
+
+void CharacterData::replaceData(unsigned offset, unsigned count, const String& data, ExceptionCode& ec)
+{
+    checkCharDataOperation(offset, ec);
+    if (ec)
+        return;
+
+    unsigned realCount;
+    if (offset + count > length())
+        realCount = length() - offset;
+    else
+        realCount = count;
+
+    String newStr = m_data;
+    newStr.remove(offset, realCount);
+    newStr.insert(data, offset);
+
+    setDataAndUpdate(newStr, offset, count, data.length());
+
+    // update the markers for spell checking and grammar checking
+    document()->textRemoved(this, offset, realCount);
+    document()->textInserted(this, offset, data.length());
+}
+
+String CharacterData::nodeValue() const
+{
+    return m_data;
+}
+
+bool CharacterData::containsOnlyWhitespace() const
+{
+    return m_data.containsOnlyWhitespace();
+}
+
+void CharacterData::setNodeValue(const String& nodeValue, ExceptionCode& ec)
+{
+    setData(nodeValue, ec);
+}
+
+void CharacterData::setDataAndUpdate(const String& newData, unsigned offsetOfReplacedData, unsigned oldLength, unsigned newLength)
+{
+    String oldData = m_data;
+    m_data = newData;
+
+    ASSERT(!renderer() || isTextNode());
+    if (isTextNode())
+        toText(this)->updateTextRenderer(offsetOfReplacedData, oldLength);
+
+    if (document()->frame())
+        document()->frame()->selection()->textWasReplaced(this, offsetOfReplacedData, oldLength, newLength);
+
+    document()->incDOMTreeVersion();
+    dispatchModifiedEvent(oldData);
+}
+
+void CharacterData::dispatchModifiedEvent(const String& oldData)
+{
+    if (OwnPtr<MutationObserverInterestGroup> mutationRecipients = MutationObserverInterestGroup::createForCharacterDataMutation(this))
+        mutationRecipients->enqueueMutationRecord(MutationRecord::createCharacterData(this, oldData));
+    if (!isInShadowTree()) {
+        if (parentNode())
+            parentNode()->childrenChanged();
+        if (document()->hasListenerType(Document::DOMCHARACTERDATAMODIFIED_LISTENER))
+            dispatchScopedEvent(MutationEvent::create(eventNames().DOMCharacterDataModifiedEvent, true, 0, oldData, m_data));
+        dispatchSubtreeModifiedEvent();
+    }
+    InspectorInstrumentation::characterDataModified(document(), this);
+}
+
+void CharacterData::checkCharDataOperation(unsigned offset, ExceptionCode& ec)
+{
+    ec = 0;
+
+    // INDEX_SIZE_ERR: Raised if the specified offset is negative or greater than the number of 16-bit
+    // units in data.
+    if (offset > length()) {
+        ec = INDEX_SIZE_ERR;
+        return;
+    }
+}
+
+int CharacterData::maxCharacterOffset() const
+{
+    return static_cast<int>(length());
+}
+
+bool CharacterData::offsetInCharacters() const
+{
+    return true;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/CharacterData.h b/Source/core/dom/CharacterData.h
new file mode 100644
index 0000000..4550589
--- /dev/null
+++ b/Source/core/dom/CharacterData.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CharacterData_h
+#define CharacterData_h
+
+#include "core/dom/Node.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class CharacterData : public Node {
+public:
+    String data() const { return m_data; }
+    void setData(const String&, ExceptionCode&);
+    unsigned length() const { return m_data.length(); }
+    String substringData(unsigned offset, unsigned count, ExceptionCode&);
+    void appendData(const String&, ExceptionCode&);
+    void insertData(unsigned offset, const String&, ExceptionCode&);
+    void deleteData(unsigned offset, unsigned count, ExceptionCode&);
+    void replaceData(unsigned offset, unsigned count, const String&, ExceptionCode&);
+
+    bool containsOnlyWhitespace() const;
+
+    StringImpl* dataImpl() { return m_data.impl(); }
+
+    // Like appendData, but optimized for the parser (e.g., no mutation events).
+    // Returns how much could be added before length limit was met.
+    unsigned parserAppendData(const String& string, unsigned offset, unsigned lengthLimit);
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+
+protected:
+    CharacterData(Document* document, const String& text, ConstructionType type)
+        : Node(document, type)
+        , m_data(!text.isNull() ? text : emptyString())
+    {
+        ASSERT(type == CreateOther || type == CreateText || type == CreateEditingText);
+        ScriptWrappable::init(this);
+    }
+
+    void setDataWithoutUpdate(const String& data)
+    {
+        ASSERT(!data.isNull());
+        m_data = data;
+    }
+    void dispatchModifiedEvent(const String& oldValue);
+
+private:
+    virtual String nodeValue() const OVERRIDE FINAL;
+    virtual void setNodeValue(const String&, ExceptionCode&) OVERRIDE FINAL;
+    virtual bool isCharacterDataNode() const OVERRIDE FINAL { return true; }
+    virtual int maxCharacterOffset() const OVERRIDE FINAL;
+    virtual bool offsetInCharacters() const OVERRIDE FINAL;
+    void setDataAndUpdate(const String&, unsigned offsetOfReplacedData, unsigned oldLength, unsigned newLength);
+    void checkCharDataOperation(unsigned offset, ExceptionCode&);
+
+    String m_data;
+};
+
+} // namespace WebCore
+
+#endif // CharacterData_h
diff --git a/Source/core/dom/CharacterData.idl b/Source/core/dom/CharacterData.idl
new file mode 100644
index 0000000..4b45308
--- /dev/null
+++ b/Source/core/dom/CharacterData.idl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+interface CharacterData : Node {
+
+    [TreatNullAs=NullString, SetterRaisesException] attribute DOMString data;
+
+    readonly attribute unsigned long length;
+    
+    [TreatReturnedNullStringAs=Null, RaisesException] DOMString substringData([IsIndex,Default=Undefined] optional unsigned long offset, [IsIndex,Default=Undefined] optional unsigned long length);
+
+    [RaisesException] void appendData([Default=Undefined] optional DOMString data);
+
+     [RaisesException] void insertData([IsIndex,Default=Undefined] optional unsigned long offset, 
+                                   [Default=Undefined] optional DOMString data);
+
+     [RaisesException] void deleteData([IsIndex,Default=Undefined] optional unsigned long offset, 
+                                   [IsIndex,Default=Undefined] optional unsigned long length);
+
+     [RaisesException] void replaceData([IsIndex,Default=Undefined] optional unsigned long offset, 
+                                    [IsIndex,Default=Undefined] optional unsigned long length,
+                                    [Default=Undefined] optional DOMString data);
+
+    // DOM 4
+    [RaisesException] void remove();
+};
+
diff --git a/Source/core/dom/CheckedRadioButtons.cpp b/Source/core/dom/CheckedRadioButtons.cpp
new file mode 100644
index 0000000..c377b7a
--- /dev/null
+++ b/Source/core/dom/CheckedRadioButtons.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/CheckedRadioButtons.h"
+
+#include "core/html/HTMLInputElement.h"
+#include <wtf/HashSet.h>
+
+namespace WebCore {
+
+class RadioButtonGroup {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<RadioButtonGroup> create();
+    bool isEmpty() const { return m_members.isEmpty(); }
+    bool isRequired() const { return m_requiredCount; }
+    HTMLInputElement* checkedButton() const { return m_checkedButton; }
+    void add(HTMLInputElement*);
+    void updateCheckedState(HTMLInputElement*);
+    void requiredAttributeChanged(HTMLInputElement*);
+    void remove(HTMLInputElement*);
+    bool contains(HTMLInputElement*) const;
+
+private:
+    RadioButtonGroup();
+    void setNeedsValidityCheckForAllButtons();
+    bool isValid() const;
+    void setCheckedButton(HTMLInputElement*);
+
+    HashSet<HTMLInputElement*> m_members;
+    HTMLInputElement* m_checkedButton;
+    size_t m_requiredCount;
+};
+
+RadioButtonGroup::RadioButtonGroup()
+    : m_checkedButton(0)
+    , m_requiredCount(0)
+{
+}
+
+PassOwnPtr<RadioButtonGroup> RadioButtonGroup::create()
+{
+    return adoptPtr(new RadioButtonGroup);
+}
+
+inline bool RadioButtonGroup::isValid() const
+{
+    return !isRequired() || m_checkedButton;
+}
+
+void RadioButtonGroup::setCheckedButton(HTMLInputElement* button)
+{
+    HTMLInputElement* oldCheckedButton = m_checkedButton;
+    if (oldCheckedButton == button)
+        return;
+    m_checkedButton = button;
+    if (oldCheckedButton)
+        oldCheckedButton->setChecked(false);
+}
+
+void RadioButtonGroup::add(HTMLInputElement* button)
+{
+    ASSERT(button->isRadioButton());
+    if (!m_members.add(button).isNewEntry)
+        return;
+    bool groupWasValid = isValid();
+    if (button->isRequired())
+        ++m_requiredCount;
+    if (button->checked())
+        setCheckedButton(button);
+
+    bool groupIsValid = isValid();
+    if (groupWasValid != groupIsValid)
+        setNeedsValidityCheckForAllButtons();
+    else if (!groupIsValid) {
+        // A radio button not in a group is always valid. We need to make it
+        // invalid only if the group is invalid.
+        button->setNeedsValidityCheck();
+    }
+}
+
+void RadioButtonGroup::updateCheckedState(HTMLInputElement* button)
+{
+    ASSERT(button->isRadioButton());
+    ASSERT(m_members.contains(button));
+    bool wasValid = isValid();
+    if (button->checked())
+        setCheckedButton(button);
+    else {
+        if (m_checkedButton == button)
+            m_checkedButton = 0;
+    }
+    if (wasValid != isValid())
+        setNeedsValidityCheckForAllButtons();
+}
+
+void RadioButtonGroup::requiredAttributeChanged(HTMLInputElement* button)
+{
+    ASSERT(button->isRadioButton());
+    ASSERT(m_members.contains(button));
+    bool wasValid = isValid();
+    if (button->isRequired())
+        ++m_requiredCount;
+    else {
+        ASSERT(m_requiredCount);
+        --m_requiredCount;
+    }
+    if (wasValid != isValid())
+        setNeedsValidityCheckForAllButtons();
+}
+
+void RadioButtonGroup::remove(HTMLInputElement* button)
+{
+    ASSERT(button->isRadioButton());
+    HashSet<HTMLInputElement*>::iterator it = m_members.find(button);
+    if (it == m_members.end())
+        return;
+    bool wasValid = isValid();
+    m_members.remove(it);
+    if (button->isRequired()) {
+        ASSERT(m_requiredCount);
+        --m_requiredCount;
+    }
+    if (m_checkedButton == button)
+        m_checkedButton = 0;
+
+    if (m_members.isEmpty()) {
+        ASSERT(!m_requiredCount);
+        ASSERT(!m_checkedButton);
+    } else if (wasValid != isValid())
+        setNeedsValidityCheckForAllButtons();
+    if (!wasValid) {
+        // A radio button not in a group is always valid. We need to make it
+        // valid only if the group was invalid.
+        button->setNeedsValidityCheck();
+    }
+}
+
+void RadioButtonGroup::setNeedsValidityCheckForAllButtons()
+{
+    typedef HashSet<HTMLInputElement*>::const_iterator Iterator;
+    Iterator end = m_members.end();
+    for (Iterator it = m_members.begin(); it != end; ++it) {
+        HTMLInputElement* button = *it;
+        ASSERT(button->isRadioButton());
+        button->setNeedsValidityCheck();
+    }
+}
+
+bool RadioButtonGroup::contains(HTMLInputElement* button) const
+{
+    return m_members.contains(button);
+}
+
+// ----------------------------------------------------------------
+
+// Explicity define empty constructor and destructor in order to prevent the
+// compiler from generating them as inlines. So we don't need to to define
+// RadioButtonGroup in the header.
+CheckedRadioButtons::CheckedRadioButtons()
+{
+}
+
+CheckedRadioButtons::~CheckedRadioButtons()
+{
+}
+
+void CheckedRadioButtons::addButton(HTMLInputElement* element)
+{
+    ASSERT(element->isRadioButton());
+    if (element->name().isEmpty())
+        return;
+
+    if (!m_nameToGroupMap)
+        m_nameToGroupMap = adoptPtr(new NameToGroupMap);
+
+    OwnPtr<RadioButtonGroup>& group = m_nameToGroupMap->add(element->name().impl(), PassOwnPtr<RadioButtonGroup>()).iterator->value;
+    if (!group)
+        group = RadioButtonGroup::create();
+    group->add(element);
+}
+
+void CheckedRadioButtons::updateCheckedState(HTMLInputElement* element)
+{
+    ASSERT(element->isRadioButton());
+    if (element->name().isEmpty())
+        return;
+    ASSERT(m_nameToGroupMap);
+    if (!m_nameToGroupMap)
+        return;
+    RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
+    ASSERT(group);
+    group->updateCheckedState(element);
+}
+
+void CheckedRadioButtons::requiredAttributeChanged(HTMLInputElement* element)
+{
+    ASSERT(element->isRadioButton());
+    if (element->name().isEmpty())
+        return;
+    ASSERT(m_nameToGroupMap);
+    if (!m_nameToGroupMap)
+        return;
+    RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
+    ASSERT(group);
+    group->requiredAttributeChanged(element);
+}
+
+HTMLInputElement* CheckedRadioButtons::checkedButtonForGroup(const AtomicString& name) const
+{
+    if (!m_nameToGroupMap)
+        return 0;
+    m_nameToGroupMap->checkConsistency();
+    RadioButtonGroup* group = m_nameToGroupMap->get(name.impl());
+    return group ? group->checkedButton() : 0;
+}
+
+bool CheckedRadioButtons::isInRequiredGroup(HTMLInputElement* element) const
+{
+    ASSERT(element->isRadioButton());
+    if (element->name().isEmpty())
+        return false;
+    if (!m_nameToGroupMap)
+        return false;
+    RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
+    return group && group->isRequired() && group->contains(element);
+}
+
+void CheckedRadioButtons::removeButton(HTMLInputElement* element)
+{
+    ASSERT(element->isRadioButton());
+    if (element->name().isEmpty())
+        return;
+    if (!m_nameToGroupMap)
+        return;
+
+    m_nameToGroupMap->checkConsistency();
+    NameToGroupMap::iterator it = m_nameToGroupMap->find(element->name().impl());
+    if (it == m_nameToGroupMap->end())
+        return;
+    it->value->remove(element);
+    if (it->value->isEmpty()) {
+        // FIXME: We may skip deallocating the empty RadioButtonGroup for
+        // performance improvement. If we do so, we need to change the key type
+        // of m_nameToGroupMap from AtomicStringImpl* to RefPtr<AtomicStringImpl>.
+        m_nameToGroupMap->remove(it);
+        if (m_nameToGroupMap->isEmpty())
+            m_nameToGroupMap.clear();
+    }
+}
+
+} // namespace
diff --git a/Source/core/dom/CheckedRadioButtons.h b/Source/core/dom/CheckedRadioButtons.h
new file mode 100644
index 0000000..f050faa
--- /dev/null
+++ b/Source/core/dom/CheckedRadioButtons.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CheckedRadioButtons_h
+#define CheckedRadioButtons_h
+
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class HTMLInputElement;
+class RadioButtonGroup;
+
+// FIXME: Rename the class. The class was a simple map from a name to a checked
+// radio button. It manages RadioButtonGroup objects now.
+class CheckedRadioButtons {
+public:
+    CheckedRadioButtons();
+    ~CheckedRadioButtons();
+    void addButton(HTMLInputElement*);
+    void updateCheckedState(HTMLInputElement*);
+    void requiredAttributeChanged(HTMLInputElement*);
+    void removeButton(HTMLInputElement*);
+    HTMLInputElement* checkedButtonForGroup(const AtomicString& groupName) const;
+    bool isInRequiredGroup(HTMLInputElement*) const;
+
+private:
+    typedef HashMap<AtomicStringImpl*, OwnPtr<RadioButtonGroup> > NameToGroupMap;
+    OwnPtr<NameToGroupMap> m_nameToGroupMap;
+};
+
+} // namespace WebCore
+
+#endif // CheckedRadioButtons_h
diff --git a/Source/core/dom/ChildListMutationScope.cpp b/Source/core/dom/ChildListMutationScope.cpp
new file mode 100644
index 0000000..190069f
--- /dev/null
+++ b/Source/core/dom/ChildListMutationScope.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "core/dom/ChildListMutationScope.h"
+
+#include "core/dom/DocumentFragment.h"
+#include "core/dom/Element.h"
+#include "core/dom/MutationObserverInterestGroup.h"
+#include "core/dom/MutationRecord.h"
+#include "core/dom/Node.h"
+#include "core/dom/StaticNodeList.h"
+#include <wtf/HashMap.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+typedef HashMap<Node*, ChildListMutationAccumulator*> AccumulatorMap;
+static AccumulatorMap& accumulatorMap()
+{
+    DEFINE_STATIC_LOCAL(AccumulatorMap, map, ());
+    return map;
+}
+
+ChildListMutationAccumulator::ChildListMutationAccumulator(PassRefPtr<Node> target, PassOwnPtr<MutationObserverInterestGroup> observers)
+    : m_target(target)
+    , m_lastAdded(0)
+    , m_observers(observers)
+{
+}
+
+ChildListMutationAccumulator::~ChildListMutationAccumulator()
+{
+    if (!isEmpty())
+        enqueueMutationRecord();
+    accumulatorMap().remove(m_target.get());
+}
+
+PassRefPtr<ChildListMutationAccumulator> ChildListMutationAccumulator::getOrCreate(Node* target)
+{
+    AccumulatorMap::AddResult result = accumulatorMap().add(target, 0);
+    RefPtr<ChildListMutationAccumulator> accumulator;
+    if (!result.isNewEntry)
+        accumulator = result.iterator->value;
+    else {
+        accumulator = adoptRef(new ChildListMutationAccumulator(target, MutationObserverInterestGroup::createForChildListMutation(target)));
+        result.iterator->value = accumulator.get();
+    }
+    return accumulator.release();
+}
+
+inline bool ChildListMutationAccumulator::isAddedNodeInOrder(Node* child)
+{
+    return isEmpty() || (m_lastAdded == child->previousSibling() && m_nextSibling == child->nextSibling());
+}
+
+void ChildListMutationAccumulator::childAdded(PassRefPtr<Node> prpChild)
+{
+    ASSERT(hasObservers());
+
+    RefPtr<Node> child = prpChild;
+
+    if (!isAddedNodeInOrder(child.get()))
+        enqueueMutationRecord();
+
+    if (isEmpty()) {
+        m_previousSibling = child->previousSibling();
+        m_nextSibling = child->nextSibling();
+    }
+
+    m_lastAdded = child.get();
+    m_addedNodes.append(child.release());
+}
+
+inline bool ChildListMutationAccumulator::isRemovedNodeInOrder(Node* child)
+{
+    return isEmpty() || m_nextSibling == child;
+}
+
+void ChildListMutationAccumulator::willRemoveChild(PassRefPtr<Node> prpChild)
+{
+    ASSERT(hasObservers());
+
+    RefPtr<Node> child = prpChild;
+
+    if (!m_addedNodes.isEmpty() || !isRemovedNodeInOrder(child.get()))
+        enqueueMutationRecord();
+
+    if (isEmpty()) {
+        m_previousSibling = child->previousSibling();
+        m_nextSibling = child->nextSibling();
+        m_lastAdded = child->previousSibling();
+    } else
+        m_nextSibling = child->nextSibling();
+
+    m_removedNodes.append(child.release());
+}
+
+void ChildListMutationAccumulator::enqueueMutationRecord()
+{
+    ASSERT(hasObservers());
+    ASSERT(!isEmpty());
+
+    RefPtr<NodeList> addedNodes = StaticNodeList::adopt(m_addedNodes);
+    RefPtr<NodeList> removedNodes = StaticNodeList::adopt(m_removedNodes);
+    RefPtr<MutationRecord> record = MutationRecord::createChildList(m_target, addedNodes.release(), removedNodes.release(), m_previousSibling.release(), m_nextSibling.release());
+    m_observers->enqueueMutationRecord(record.release());
+    m_lastAdded = 0;
+    ASSERT(isEmpty());
+}
+
+bool ChildListMutationAccumulator::isEmpty()
+{
+    bool result = m_removedNodes.isEmpty() && m_addedNodes.isEmpty();
+#ifndef NDEBUG
+    if (result) {
+        ASSERT(!m_previousSibling);
+        ASSERT(!m_nextSibling);
+        ASSERT(!m_lastAdded);
+    }
+#endif
+    return result;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/ChildListMutationScope.h b/Source/core/dom/ChildListMutationScope.h
new file mode 100644
index 0000000..b5060e1
--- /dev/null
+++ b/Source/core/dom/ChildListMutationScope.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ChildListMutationScope_h
+#define ChildListMutationScope_h
+
+#include "core/dom/Document.h"
+#include "core/dom/MutationObserver.h"
+#include "core/dom/Node.h"
+#include <wtf/HashMap.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class MutationObserverInterestGroup;
+
+// ChildListMutationAccumulator is not meant to be used directly; ChildListMutationScope is the public interface.
+class ChildListMutationAccumulator : public RefCounted<ChildListMutationAccumulator> {
+public:
+    static PassRefPtr<ChildListMutationAccumulator> getOrCreate(Node*);
+    ~ChildListMutationAccumulator();
+
+    void childAdded(PassRefPtr<Node>);
+    void willRemoveChild(PassRefPtr<Node>);
+
+    bool hasObservers() const { return m_observers; }
+
+private:
+    ChildListMutationAccumulator(PassRefPtr<Node>, PassOwnPtr<MutationObserverInterestGroup>);
+
+    void enqueueMutationRecord();
+    bool isEmpty();
+    bool isAddedNodeInOrder(Node*);
+    bool isRemovedNodeInOrder(Node*);
+
+    RefPtr<Node> m_target;
+
+    Vector<RefPtr<Node> > m_removedNodes;
+    Vector<RefPtr<Node> > m_addedNodes;
+    RefPtr<Node> m_previousSibling;
+    RefPtr<Node> m_nextSibling;
+    Node* m_lastAdded;
+
+    OwnPtr<MutationObserverInterestGroup> m_observers;
+};
+
+class ChildListMutationScope {
+    WTF_MAKE_NONCOPYABLE(ChildListMutationScope);
+public:
+    explicit ChildListMutationScope(Node* target)
+    {
+        if (target->document()->hasMutationObserversOfType(MutationObserver::ChildList))
+            m_accumulator = ChildListMutationAccumulator::getOrCreate(target);
+    }
+
+    void childAdded(Node* child)
+    {
+        if (m_accumulator && m_accumulator->hasObservers())
+            m_accumulator->childAdded(child);
+    }
+
+    void willRemoveChild(Node* child)
+    {
+        if (m_accumulator && m_accumulator->hasObservers())
+            m_accumulator->willRemoveChild(child);
+    }
+
+private:
+    RefPtr<ChildListMutationAccumulator> m_accumulator;
+};
+
+} // namespace WebCore
+
+#endif // ChildListMutationScope_h
diff --git a/Source/core/dom/ChildNodeList.cpp b/Source/core/dom/ChildNodeList.cpp
new file mode 100644
index 0000000..4144c04
--- /dev/null
+++ b/Source/core/dom/ChildNodeList.cpp
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/ChildNodeList.h"
+
+#include "core/dom/Element.h"
+#include "core/dom/NodeRareData.h"
+
+namespace WebCore {
+
+ChildNodeList::ChildNodeList(PassRefPtr<Node> node)
+    : LiveNodeList(node, ChildNodeListType, DoNotInvalidateOnAttributeChanges)
+{
+}
+
+ChildNodeList::~ChildNodeList()
+{
+    ownerNode()->nodeLists()->removeChildNodeList(this);
+}
+
+bool ChildNodeList::nodeMatches(Element* testNode) const
+{
+    // This function will be called only by LiveNodeList::namedItem,
+    // for an element that was located with getElementById.
+    return testNode->parentNode() == rootNode();
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/ChildNodeList.h b/Source/core/dom/ChildNodeList.h
new file mode 100644
index 0000000..34b4040
--- /dev/null
+++ b/Source/core/dom/ChildNodeList.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2007 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ChildNodeList_h
+#define ChildNodeList_h
+
+#include "core/dom/LiveNodeList.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+    class ChildNodeList : public LiveNodeList {
+    public:
+        static PassRefPtr<ChildNodeList> create(PassRefPtr<Node> rootNode)
+        {
+            return adoptRef(new ChildNodeList(rootNode));
+        }
+
+        virtual ~ChildNodeList();
+
+    protected:
+        explicit ChildNodeList(PassRefPtr<Node> rootNode);
+
+        virtual bool nodeMatches(Element*) const;
+    };
+
+} // namespace WebCore
+
+#endif // ChildNodeList_h
diff --git a/Source/core/dom/ClassNodeList.cpp b/Source/core/dom/ClassNodeList.cpp
new file mode 100644
index 0000000..dc6f36d
--- /dev/null
+++ b/Source/core/dom/ClassNodeList.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 David Smith (catfish.man@gmail.com)
+ *
+ * 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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "core/dom/ClassNodeList.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/NodeRareData.h"
+#include "core/dom/StyledElement.h"
+
+namespace WebCore {
+
+ClassNodeList::ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames)
+    : LiveNodeList(rootNode, ClassNodeListType, InvalidateOnClassAttrChange)
+    , m_classNames(classNames, document()->inQuirksMode())
+    , m_originalClassNames(classNames)
+{
+}
+
+ClassNodeList::~ClassNodeList()
+{
+    ownerNode()->nodeLists()->removeCacheWithName(this, ClassNodeListType, m_originalClassNames);
+} 
+
+bool ClassNodeList::nodeMatches(Element* testNode) const
+{
+    return nodeMatchesInlined(testNode);
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/ClassNodeList.h b/Source/core/dom/ClassNodeList.h
new file mode 100644
index 0000000..0d90b3d
--- /dev/null
+++ b/Source/core/dom/ClassNodeList.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 David Smith (catfish.man@gmail.com)
+ *
+ * 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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 ClassNodeList_h
+#define ClassNodeList_h
+
+#include "core/dom/Element.h"
+#include "core/dom/LiveNodeList.h"
+#include "core/dom/Node.h"
+#include "core/dom/SpaceSplitString.h"
+
+namespace WebCore {
+
+class ClassNodeList : public LiveNodeList {
+public:
+    static PassRefPtr<ClassNodeList> create(PassRefPtr<Node> rootNode, const String& classNames)
+    {
+        return adoptRef(new ClassNodeList(rootNode, classNames));
+    }
+
+    virtual ~ClassNodeList();
+
+    bool nodeMatchesInlined(Element*) const;
+
+private:
+    ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames);
+
+    virtual bool nodeMatches(Element*) const;
+
+    SpaceSplitString m_classNames;
+    String m_originalClassNames;
+};
+
+inline bool ClassNodeList::nodeMatchesInlined(Element* testNode) const
+{
+    if (!testNode->hasClass())
+        return false;
+    if (!m_classNames.size())
+        return false;
+    // FIXME: DOM4 allows getElementsByClassName to return non StyledElement.
+    // https://bugs.webkit.org/show_bug.cgi?id=94718
+    if (!testNode->isStyledElement())
+        return false;
+    return testNode->classNames().containsAll(m_classNames);
+}
+
+} // namespace WebCore
+
+#endif // ClassNodeList_h
diff --git a/Source/core/dom/ClientRect.cpp b/Source/core/dom/ClientRect.cpp
new file mode 100644
index 0000000..bff5d80
--- /dev/null
+++ b/Source/core/dom/ClientRect.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "core/dom/ClientRect.h"
+
+namespace WebCore {
+
+ClientRect::ClientRect()
+{
+    ScriptWrappable::init(this);
+}
+
+ClientRect::ClientRect(const IntRect& rect)
+    : m_rect(rect)
+{
+    ScriptWrappable::init(this);
+}
+
+ClientRect::ClientRect(const FloatRect& rect)
+    : m_rect(rect)
+{
+    ScriptWrappable::init(this);
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/ClientRect.h b/Source/core/dom/ClientRect.h
new file mode 100644
index 0000000..329f34c
--- /dev/null
+++ b/Source/core/dom/ClientRect.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef ClientRect_h
+#define ClientRect_h
+
+#include "bindings/v8/ScriptWrappable.h"
+#include "core/platform/graphics/FloatRect.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+    class IntRect; 
+
+    class ClientRect : public ScriptWrappable, public RefCounted<ClientRect> {
+    public:
+        static PassRefPtr<ClientRect> create() { return adoptRef(new ClientRect); }
+        static PassRefPtr<ClientRect> create(const IntRect& rect) { return adoptRef(new ClientRect(rect)); }
+        static PassRefPtr<ClientRect> create(const FloatRect& rect) { return adoptRef(new ClientRect(rect)); }
+
+        float top() const { return m_rect.y(); }
+        float right() const { return m_rect.maxX(); }
+        float bottom() const { return m_rect.maxY(); }
+        float left() const { return m_rect.x(); }
+        float width() const { return m_rect.width(); }
+        float height() const { return m_rect.height(); }
+
+    private:
+        ClientRect();
+        explicit ClientRect(const IntRect&);
+        explicit ClientRect(const FloatRect&);
+
+        FloatRect m_rect;
+    }; 
+
+} // namespace WebCore
+
+#endif // ClientRect_h
diff --git a/Source/core/dom/ClientRect.idl b/Source/core/dom/ClientRect.idl
new file mode 100644
index 0000000..3dc5b03
--- /dev/null
+++ b/Source/core/dom/ClientRect.idl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+[
+    ImplementationLacksVTable
+] interface ClientRect {
+    readonly attribute float top;
+    readonly attribute float right;
+    readonly attribute float bottom;
+    readonly attribute float left;
+    readonly attribute float width;
+    readonly attribute float height;
+};
+
diff --git a/Source/core/dom/ClientRectList.cpp b/Source/core/dom/ClientRectList.cpp
new file mode 100644
index 0000000..f51c091
--- /dev/null
+++ b/Source/core/dom/ClientRectList.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "core/dom/ClientRectList.h"
+
+#include "core/dom/ClientRect.h"
+#include "core/dom/ExceptionCode.h"
+
+namespace WebCore {
+
+ClientRectList::ClientRectList()
+{
+}
+
+ClientRectList::ClientRectList(const Vector<FloatQuad>& quads)
+{
+    m_list.reserveInitialCapacity(quads.size());
+    for (size_t i = 0; i < quads.size(); ++i)
+        m_list.append(ClientRect::create(quads[i].enclosingBoundingBox()));
+}
+
+ClientRectList::~ClientRectList()
+{
+}
+
+unsigned ClientRectList::length() const
+{
+    return m_list.size();
+}
+
+ClientRect* ClientRectList::item(unsigned index)
+{
+    if (index >= m_list.size()) {
+        // FIXME: this should throw an exception.
+        // ec = INDEX_SIZE_ERR;
+        return 0;
+    }
+
+    return m_list[index].get();
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/ClientRectList.h b/Source/core/dom/ClientRectList.h
new file mode 100644
index 0000000..a8f6fd6
--- /dev/null
+++ b/Source/core/dom/ClientRectList.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef ClientRectList_h
+#define ClientRectList_h
+
+#include "core/platform/graphics/FloatQuad.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+    class ClientRect;
+
+    class ClientRectList : public RefCounted<ClientRectList> {
+    public:
+        static PassRefPtr<ClientRectList> create() { return adoptRef(new ClientRectList); }
+        static PassRefPtr<ClientRectList> create(const Vector<FloatQuad>& quads) { return adoptRef(new ClientRectList(quads)); }
+        ~ClientRectList();
+
+        unsigned length() const;
+        ClientRect* item(unsigned index);
+
+    private:
+        ClientRectList();
+        explicit ClientRectList(const Vector<FloatQuad>&);
+
+        Vector<RefPtr<ClientRect> > m_list;
+    }; 
+
+} // namespace WebCore
+
+#endif // ClientRectList_h
diff --git a/Source/core/dom/ClientRectList.idl b/Source/core/dom/ClientRectList.idl
new file mode 100644
index 0000000..8017c6b
--- /dev/null
+++ b/Source/core/dom/ClientRectList.idl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+[
+    ImplementationLacksVTable
+] interface ClientRectList {
+    readonly attribute unsigned long length;
+    getter ClientRect item([IsIndex,Default=Undefined] optional unsigned long index);
+    // FIXME: Fix list behavior to allow custom exceptions to be thrown.
+};
+
diff --git a/Source/core/dom/Clipboard.cpp b/Source/core/dom/Clipboard.cpp
new file mode 100644
index 0000000..37d9772
--- /dev/null
+++ b/Source/core/dom/Clipboard.cpp
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "core/dom/Clipboard.h"
+
+#include "core/fileapi/FileList.h"
+#include "core/loader/FrameLoader.h"
+#include "core/loader/cache/CachedImage.h"
+#include "core/page/Frame.h"
+#include "core/platform/graphics/Image.h"
+
+namespace WebCore {
+
+Clipboard::Clipboard(ClipboardAccessPolicy policy, ClipboardType clipboardType) 
+    : m_policy(policy)
+    , m_dropEffect("uninitialized")
+    , m_effectAllowed("uninitialized")
+    , m_dragStarted(false)
+    , m_clipboardType(clipboardType)
+    , m_dragImage(0)
+{
+}
+    
+void Clipboard::setAccessPolicy(ClipboardAccessPolicy policy)
+{
+    // once you go numb, can never go back
+    ASSERT(m_policy != ClipboardNumb || policy == ClipboardNumb);
+    m_policy = policy;
+}
+
+bool Clipboard::canReadTypes() const
+{
+    return m_policy == ClipboardReadable || m_policy == ClipboardTypesReadable || m_policy == ClipboardWritable;
+}
+
+bool Clipboard::canReadData() const
+{
+    return m_policy == ClipboardReadable || m_policy == ClipboardWritable;
+}
+
+bool Clipboard::canWriteData() const
+{
+    return m_policy == ClipboardWritable;
+}
+
+bool Clipboard::canSetDragImage() const
+{
+    return m_policy == ClipboardImageWritable || m_policy == ClipboardWritable;
+}
+
+// These "conversion" methods are called by both WebCore and WebKit, and never make sense to JS, so we don't
+// worry about security for these. They don't allow access to the pasteboard anyway.
+
+static DragOperation dragOpFromIEOp(const String& op)
+{
+    // yep, it's really just this fixed set
+    if (op == "uninitialized")
+        return DragOperationEvery;
+    if (op == "none")
+        return DragOperationNone;
+    if (op == "copy")
+        return DragOperationCopy;
+    if (op == "link")
+        return DragOperationLink;
+    if (op == "move")
+        return (DragOperation)(DragOperationGeneric | DragOperationMove);
+    if (op == "copyLink")
+        return (DragOperation)(DragOperationCopy | DragOperationLink);
+    if (op == "copyMove")
+        return (DragOperation)(DragOperationCopy | DragOperationGeneric | DragOperationMove);
+    if (op == "linkMove")
+        return (DragOperation)(DragOperationLink | DragOperationGeneric | DragOperationMove);
+    if (op == "all")
+        return DragOperationEvery;
+    return DragOperationPrivate;  // really a marker for "no conversion"
+}
+
+static String IEOpFromDragOp(DragOperation op)
+{
+    bool moveSet = !!((DragOperationGeneric | DragOperationMove) & op);
+    
+    if ((moveSet && (op & DragOperationCopy) && (op & DragOperationLink))
+        || (op == DragOperationEvery))
+        return "all";
+    if (moveSet && (op & DragOperationCopy))
+        return "copyMove";
+    if (moveSet && (op & DragOperationLink))
+        return "linkMove";
+    if ((op & DragOperationCopy) && (op & DragOperationLink))
+        return "copyLink";
+    if (moveSet)
+        return "move";
+    if (op & DragOperationCopy)
+        return "copy";
+    if (op & DragOperationLink)
+        return "link";
+    return "none";
+}
+
+DragOperation Clipboard::sourceOperation() const
+{
+    DragOperation op = dragOpFromIEOp(m_effectAllowed);
+    ASSERT(op != DragOperationPrivate);
+    return op;
+}
+
+DragOperation Clipboard::destinationOperation() const
+{
+    DragOperation op = dragOpFromIEOp(m_dropEffect);
+    ASSERT(op == DragOperationCopy || op == DragOperationNone || op == DragOperationLink || op == (DragOperation)(DragOperationGeneric | DragOperationMove) || op == DragOperationEvery);
+    return op;
+}
+
+void Clipboard::setSourceOperation(DragOperation op)
+{
+    ASSERT_ARG(op, op != DragOperationPrivate);
+    m_effectAllowed = IEOpFromDragOp(op);
+}
+
+void Clipboard::setDestinationOperation(DragOperation op)
+{
+    ASSERT_ARG(op, op == DragOperationCopy || op == DragOperationNone || op == DragOperationLink || op == DragOperationGeneric || op == DragOperationMove || op == (DragOperation)(DragOperationGeneric | DragOperationMove));
+    m_dropEffect = IEOpFromDragOp(op);
+}
+
+bool Clipboard::hasFileOfType(const String& type) const
+{
+    if (!canReadTypes())
+        return false;
+    
+    RefPtr<FileList> fileList = files();
+    if (fileList->isEmpty())
+        return false;
+    
+    for (unsigned int f = 0; f < fileList->length(); f++) {
+        if (equalIgnoringCase(fileList->item(f)->type(), type))
+            return true;
+    }
+    return false;
+}
+
+bool Clipboard::hasStringOfType(const String& type) const
+{
+    if (!canReadTypes())
+        return false;
+    
+    return types().contains(type); 
+}
+    
+void Clipboard::setDropEffect(const String &effect)
+{
+    if (!isForDragAndDrop())
+        return;
+
+    // The attribute must ignore any attempts to set it to a value other than none, copy, link, and move. 
+    if (effect != "none" && effect != "copy"  && effect != "link" && effect != "move")
+        return;
+
+    // FIXME: The spec actually allows this in all circumstances, even though there's no point in
+    // setting the drop effect when this condition is not true.
+    if (canReadTypes())
+        m_dropEffect = effect;
+}
+
+void Clipboard::setEffectAllowed(const String &effect)
+{
+    if (!isForDragAndDrop())
+        return;
+
+    if (dragOpFromIEOp(effect) == DragOperationPrivate) {
+        // This means that there was no conversion, and the effectAllowed that
+        // we are passed isn't a valid effectAllowed, so we should ignore it,
+        // and not set m_effectAllowed.
+
+        // The attribute must ignore any attempts to set it to a value other than 
+        // none, copy, copyLink, copyMove, link, linkMove, move, all, and uninitialized.
+        return;
+    }
+
+
+    if (canWriteData())
+        m_effectAllowed = effect;
+}
+    
+DragOperation convertDropZoneOperationToDragOperation(const String& dragOperation)
+{
+    if (dragOperation == "copy")
+        return DragOperationCopy;
+    if (dragOperation == "move")
+        return DragOperationMove;
+    if (dragOperation == "link")
+        return DragOperationLink;
+    return DragOperationNone;
+}
+
+String convertDragOperationToDropZoneOperation(DragOperation operation)
+{
+    switch (operation) {
+    case DragOperationCopy:
+        return String("copy");
+    case DragOperationMove:
+        return String("move");
+    case DragOperationLink:
+        return String("link");
+    default:
+        return String("copy");
+    }
+}
+
+bool Clipboard::hasDropZoneType(const String& keyword)
+{
+    if (keyword.startsWith("file:"))
+        return hasFileOfType(keyword.substring(5));
+
+    if (keyword.startsWith("string:"))
+        return hasStringOfType(keyword.substring(7));
+
+    return false;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/Clipboard.h b/Source/core/dom/Clipboard.h
new file mode 100644
index 0000000..667389f
--- /dev/null
+++ b/Source/core/dom/Clipboard.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Clipboard_h
+#define Clipboard_h
+
+#include "core/dom/ClipboardAccessPolicy.h"
+#include "core/dom/Node.h"
+#include "core/loader/cache/CachedResourceHandle.h"
+#include "core/page/DragActions.h"
+#include "core/platform/DragImage.h"
+#include "core/platform/graphics/IntPoint.h"
+
+namespace WebCore {
+
+    class DataTransferItemList;
+    class DragData;
+    class FileList;
+    class Frame;
+
+    // State available during IE's events for drag and drop and copy/paste
+    class Clipboard : public RefCounted<Clipboard> {
+    public:
+        // Whether this clipboard is serving a drag-drop or copy-paste request.
+        enum ClipboardType {
+            CopyAndPaste,
+            DragAndDrop,
+        };
+        
+        static PassRefPtr<Clipboard> create(ClipboardAccessPolicy, DragData*, Frame*);
+
+        virtual ~Clipboard() { }
+
+        bool isForCopyAndPaste() const { return m_clipboardType == CopyAndPaste; }
+        bool isForDragAndDrop() const { return m_clipboardType == DragAndDrop; }
+
+        String dropEffect() const { return dropEffectIsUninitialized() ? "none" : m_dropEffect; }
+        void setDropEffect(const String&);
+        bool dropEffectIsUninitialized() const { return m_dropEffect == "uninitialized"; }
+        String effectAllowed() const { return m_effectAllowed; }
+        void setEffectAllowed(const String&);
+    
+        virtual void clearData(const String& type) = 0;
+        virtual void clearAllData() = 0;
+        virtual String getData(const String& type) const = 0;
+        virtual bool setData(const String& type, const String& data) = 0;
+    
+        // extensions beyond IE's API
+        virtual ListHashSet<String> types() const = 0;
+        virtual PassRefPtr<FileList> files() const = 0;
+
+        IntPoint dragLocation() const { return m_dragLoc; }
+        CachedImage* dragImage() const { return m_dragImage.get(); }
+        virtual void setDragImage(CachedImage*, const IntPoint&) = 0;
+        Node* dragImageElement() const { return m_dragImageElement.get(); }
+        virtual void setDragImageElement(Node*, const IntPoint&) = 0;
+        
+        virtual DragImageRef createDragImage(IntPoint& dragLocation) const = 0;
+        virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*) = 0;
+        virtual void writeURL(const KURL&, const String&, Frame*) = 0;
+        virtual void writeRange(Range*, Frame*) = 0;
+        virtual void writePlainText(const String&) = 0;
+
+        virtual bool hasData() = 0;
+        
+        void setAccessPolicy(ClipboardAccessPolicy);
+        bool canReadTypes() const;
+        bool canReadData() const;
+        bool canWriteData() const;
+        // Note that the spec doesn't actually allow drag image modification outside the dragstart
+        // event. This capability is maintained for backwards compatiblity for ports that have
+        // supported this in the past. On many ports, attempting to set a drag image outside the
+        // dragstart operation is a no-op anyway.
+        bool canSetDragImage() const;
+
+        DragOperation sourceOperation() const;
+        DragOperation destinationOperation() const;
+        void setSourceOperation(DragOperation);
+        void setDestinationOperation(DragOperation);
+        
+        bool hasDropZoneType(const String&);
+        
+        void setDragHasStarted() { m_dragStarted = true; }
+
+        virtual PassRefPtr<DataTransferItemList> items() = 0;
+
+    protected:
+        Clipboard(ClipboardAccessPolicy, ClipboardType);
+
+        bool dragStarted() const { return m_dragStarted; }
+        
+    private:
+        bool hasFileOfType(const String&) const;
+        bool hasStringOfType(const String&) const;
+
+        // Instead of using this member directly, prefer to use the can*() methods above.
+        ClipboardAccessPolicy m_policy;
+        String m_dropEffect;
+        String m_effectAllowed;
+        bool m_dragStarted;
+        ClipboardType m_clipboardType;
+        
+    protected:
+        IntPoint m_dragLoc;
+        CachedResourceHandle<CachedImage> m_dragImage;
+        RefPtr<Node> m_dragImageElement;
+    };
+
+    DragOperation convertDropZoneOperationToDragOperation(const String& dragOperation);
+    String convertDragOperationToDropZoneOperation(DragOperation);
+    
+} // namespace WebCore
+
+#endif // Clipboard_h
diff --git a/Source/core/dom/Clipboard.idl b/Source/core/dom/Clipboard.idl
new file mode 100644
index 0000000..da58a66
--- /dev/null
+++ b/Source/core/dom/Clipboard.idl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+[
+    SkipVTableValidation
+] interface Clipboard {
+             [TreatReturnedNullStringAs=Undefined] attribute DOMString dropEffect;
+             [TreatReturnedNullStringAs=Undefined] attribute DOMString effectAllowed;
+    [CustomGetter] readonly attribute Array types;
+    readonly attribute FileList files;
+
+    [Custom, RaisesException] void clearData(optional DOMString type);
+    DOMString getData(DOMString type);
+    boolean setData(DOMString type, DOMString data);
+    [Custom, RaisesException] void setDragImage(HTMLImageElement image, long x, long y);
+
+    readonly attribute DataTransferItemList items;
+};
+
diff --git a/Source/core/dom/ClipboardAccessPolicy.h b/Source/core/dom/ClipboardAccessPolicy.h
new file mode 100644
index 0000000..7a54009
--- /dev/null
+++ b/Source/core/dom/ClipboardAccessPolicy.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+ 
+#ifndef ClipboardAccessPolicy_h
+#define ClipboardAccessPolicy_h
+
+namespace WebCore {
+
+enum ClipboardAccessPolicy {
+    ClipboardNumb, ClipboardImageWritable, ClipboardWritable, ClipboardTypesReadable, ClipboardReadable
+};
+
+} // namespace
+
+#endif
diff --git a/Source/core/dom/ClipboardEvent.cpp b/Source/core/dom/ClipboardEvent.cpp
new file mode 100644
index 0000000..bda69f2
--- /dev/null
+++ b/Source/core/dom/ClipboardEvent.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/ClipboardEvent.h"
+
+#include "core/dom/Clipboard.h"
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+ClipboardEvent::ClipboardEvent()
+{
+}
+
+ClipboardEvent::ClipboardEvent(const AtomicString& eventType, bool canBubble, bool cancelable, PassRefPtr<Clipboard> clipboard)
+    : Event(eventType, canBubble, cancelable), m_clipboard(clipboard)
+{
+}
+
+ClipboardEvent::~ClipboardEvent()
+{
+}
+
+const AtomicString& ClipboardEvent::interfaceName() const
+{
+    // Notice that there is no ClipboardEvent.idl.
+    return eventNames().interfaceForEvent;
+}
+
+bool ClipboardEvent::isClipboardEvent() const
+{
+    return true;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/ClipboardEvent.h b/Source/core/dom/ClipboardEvent.h
new file mode 100644
index 0000000..87bd13d
--- /dev/null
+++ b/Source/core/dom/ClipboardEvent.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ClipboardEvent_h
+#define ClipboardEvent_h
+
+#include "core/dom/Event.h"
+
+namespace WebCore {
+
+    class Clipboard;
+
+    class ClipboardEvent : public Event {
+    public:
+        virtual ~ClipboardEvent();
+
+        static PassRefPtr<ClipboardEvent> create()
+        {
+            return adoptRef(new ClipboardEvent);
+        }
+        static PassRefPtr<ClipboardEvent> create(const AtomicString& type, bool canBubbleArg, bool cancelableArg, PassRefPtr<Clipboard> clipboardArg)
+        {
+            return adoptRef(new ClipboardEvent(type, canBubbleArg, cancelableArg, clipboardArg));
+        }
+
+        Clipboard* clipboard() const { return m_clipboard.get(); }
+
+    private:
+        ClipboardEvent();
+        ClipboardEvent(const AtomicString& type, bool canBubbleArg, bool cancelableArg, PassRefPtr<Clipboard>);
+
+        virtual const AtomicString& interfaceName() const OVERRIDE;
+        virtual bool isClipboardEvent() const OVERRIDE;
+
+        RefPtr<Clipboard> m_clipboard;
+    };
+
+} // namespace WebCore
+
+#endif // ClipboardEvent_h
diff --git a/Source/core/dom/Comment.cpp b/Source/core/dom/Comment.cpp
new file mode 100644
index 0000000..5b8374f
--- /dev/null
+++ b/Source/core/dom/Comment.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/Comment.h"
+
+#include "core/dom/Document.h"
+
+namespace WebCore {
+
+inline Comment::Comment(Document* document, const String& text)
+    : CharacterData(document, text, CreateOther)
+{
+    ScriptWrappable::init(this);
+}
+
+PassRefPtr<Comment> Comment::create(Document* document, const String& text)
+{
+    return adoptRef(new Comment(document, text));
+}
+
+String Comment::nodeName() const
+{
+    return commentAtom.string();
+}
+
+Node::NodeType Comment::nodeType() const
+{
+    return COMMENT_NODE;
+}
+
+PassRefPtr<Node> Comment::cloneNode(bool /*deep*/)
+{
+    return create(document(), data());
+}
+
+bool Comment::childTypeAllowed(NodeType) const
+{
+    return false;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/Comment.h b/Source/core/dom/Comment.h
new file mode 100644
index 0000000..df79fbb
--- /dev/null
+++ b/Source/core/dom/Comment.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Comment_h
+#define Comment_h
+
+#include "core/dom/CharacterData.h"
+
+namespace WebCore {
+
+class Comment FINAL : public CharacterData {
+public:
+    static PassRefPtr<Comment> create(Document*, const String&);
+
+private:
+    Comment(Document*, const String&);
+
+    virtual String nodeName() const;
+    virtual NodeType nodeType() const;
+    virtual PassRefPtr<Node> cloneNode(bool deep);
+    virtual bool childTypeAllowed(NodeType) const;
+};
+
+} // namespace WebCore
+
+#endif // Comment_h
diff --git a/Source/core/dom/Comment.idl b/Source/core/dom/Comment.idl
new file mode 100644
index 0000000..5c07e2f
--- /dev/null
+++ b/Source/core/dom/Comment.idl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+interface Comment : CharacterData {
+};
+
diff --git a/Source/core/dom/ComposedShadowTreeWalker.cpp b/Source/core/dom/ComposedShadowTreeWalker.cpp
new file mode 100644
index 0000000..7b9ff2a
--- /dev/null
+++ b/Source/core/dom/ComposedShadowTreeWalker.cpp
@@ -0,0 +1,315 @@
+
+/*
+ * Copyright (C) 2012 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 "core/dom/ComposedShadowTreeWalker.h"
+
+#include "core/dom/Element.h"
+#include "core/dom/ElementShadow.h"
+#include "core/dom/PseudoElement.h"
+#include "core/html/shadow/ContentDistributor.h"
+#include "core/html/shadow/HTMLContentElement.h"
+#include "core/html/shadow/HTMLShadowElement.h"
+#include "core/html/shadow/InsertionPoint.h"
+
+namespace WebCore {
+
+static inline ElementShadow* shadowFor(const Node* node)
+{
+    if (node && node->isElementNode())
+        return toElement(node)->shadow();
+    return 0;
+}
+
+static inline bool nodeCanBeDistributed(const Node* node)
+{
+    ASSERT(node);
+    Node* parent = parentNodeForDistribution(node);
+    if (!parent)
+        return false;
+
+    if (ShadowRoot* shadowRoot = parent->isShadowRoot() ? toShadowRoot(parent) : 0)
+        return ScopeContentDistribution::assignedTo(shadowRoot);
+
+    if (parent->isElementNode() && toElement(parent)->shadow())
+        return true;
+
+    return false;
+}
+
+ComposedShadowTreeWalker ComposedShadowTreeWalker::fromFirstChild(const Node* node, Policy policy)
+{
+    ComposedShadowTreeWalker walker(node, policy);
+    walker.firstChild();
+    return walker;
+}
+
+void ComposedShadowTreeWalker::firstChild()
+{
+    assertPrecondition();
+    m_node = traverseChild(m_node, TraversalDirectionForward);
+    assertPostcondition();
+}
+
+Node* ComposedShadowTreeWalker::traverseFirstChild(const Node* node) const
+{
+    ASSERT(node);
+    return traverseChild(node, TraversalDirectionForward);
+}
+
+void ComposedShadowTreeWalker::lastChild()
+{
+    assertPrecondition();
+    m_node = traverseLastChild(m_node);
+    assertPostcondition();
+}
+
+Node* ComposedShadowTreeWalker::traverseLastChild(const Node* node) const
+{
+    ASSERT(node);
+    return traverseChild(node, TraversalDirectionBackward);
+}
+
+Node* ComposedShadowTreeWalker::traverseChild(const Node* node, TraversalDirection direction) const
+{
+    ASSERT(node);
+    if (canCrossUpperBoundary()) {
+        ElementShadow* shadow = shadowFor(node);
+        return shadow ? traverseLightChildren(shadow->youngestShadowRoot(), direction)
+            : traverseLightChildren(node, direction);
+    }
+    if (isShadowHost(node))
+        return 0;
+    return traverseLightChildren(node, direction);
+}
+
+Node* ComposedShadowTreeWalker::traverseLightChildren(const Node* node, TraversalDirection direction)
+{
+    ASSERT(node);
+    return traverseSiblings(direction == TraversalDirectionForward ? node->firstChild() : node->lastChild(), direction);
+}
+
+Node* ComposedShadowTreeWalker::traverseSiblings(const Node* node, TraversalDirection direction)
+{
+    for (const Node* sibling = node; sibling; sibling = (direction == TraversalDirectionForward ? sibling->nextSibling() : sibling->previousSibling())) {
+        if (Node* found = traverseNode(sibling, direction))
+            return found;
+    }
+    return 0;
+}
+
+Node* ComposedShadowTreeWalker::traverseNode(const Node* node, TraversalDirection direction)
+{
+    ASSERT(node);
+    if (!isActiveInsertionPoint(node))
+        return const_cast<Node*>(node);
+    const InsertionPoint* insertionPoint = toInsertionPoint(node);
+    if (Node* found = traverseDistributedNodes(direction == TraversalDirectionForward ? insertionPoint->first() : insertionPoint->last(), insertionPoint, direction))
+        return found;
+    return traverseLightChildren(node, direction);
+}
+
+void ComposedShadowTreeWalker::nextSibling()
+{
+    assertPrecondition();
+    m_node = traverseSiblingOrBackToInsertionPoint(m_node, TraversalDirectionForward);
+    assertPostcondition();
+}
+
+void ComposedShadowTreeWalker::previousSibling()
+{
+    assertPrecondition();
+    m_node = traverseSiblingOrBackToInsertionPoint(m_node, TraversalDirectionBackward);
+    assertPostcondition();
+}
+
+Node* ComposedShadowTreeWalker::traverseDistributedNodes(const Node* node, const InsertionPoint* insertionPoint, TraversalDirection direction)
+{
+    for (const Node* next = node; next; next = (direction == TraversalDirectionForward ? insertionPoint->nextTo(next) : insertionPoint->previousTo(next))) {
+        if (Node* found = traverseNode(next, direction))
+            return found;
+    }
+    return 0;
+}
+
+Node* ComposedShadowTreeWalker::traverseSiblingOrBackToInsertionPoint(const Node* node, TraversalDirection direction)
+{
+    ASSERT(node);
+
+    if (!nodeCanBeDistributed(node))
+        return traverseSiblingInCurrentTree(node, direction);
+
+    InsertionPoint* insertionPoint = resolveReprojection(node);
+    if (!insertionPoint)
+        return traverseSiblingInCurrentTree(node, direction);
+
+    if (Node* found = traverseDistributedNodes(direction == TraversalDirectionForward ? insertionPoint->nextTo(node) : insertionPoint->previousTo(node), insertionPoint, direction))
+        return found;
+    return traverseSiblingOrBackToInsertionPoint(insertionPoint, direction);
+}
+
+Node* ComposedShadowTreeWalker::traverseSiblingInCurrentTree(const Node* node, TraversalDirection direction)
+{
+    ASSERT(node);
+    if (Node* found = traverseSiblings(direction == TraversalDirectionForward ? node->nextSibling() : node->previousSibling(), direction))
+        return found;
+    if (Node* next = traverseBackToYoungerShadowRoot(node, direction))
+        return next;
+    return escapeFallbackContentElement(node, direction);
+}
+
+Node* ComposedShadowTreeWalker::traverseBackToYoungerShadowRoot(const Node* node, TraversalDirection direction)
+{
+    ASSERT(node);
+    if (node->parentNode() && node->parentNode()->isShadowRoot()) {
+        ShadowRoot* parentShadowRoot = toShadowRoot(node->parentNode());
+        if (!parentShadowRoot->isYoungest()) {
+            InsertionPoint* assignedInsertionPoint = ScopeContentDistribution::assignedTo(parentShadowRoot);
+            ASSERT(assignedInsertionPoint);
+            return traverseSiblingInCurrentTree(assignedInsertionPoint, direction);
+        }
+    }
+    return 0;
+}
+
+inline Node* ComposedShadowTreeWalker::escapeFallbackContentElement(const Node* node, TraversalDirection direction)
+{
+    ASSERT(node);
+    if (node->parentNode() && isActiveInsertionPoint(node->parentNode()))
+        return traverseSiblingOrBackToInsertionPoint(node->parentNode(), direction);
+    return 0;
+}
+
+inline Node* ComposedShadowTreeWalker::traverseNodeEscapingFallbackContents(const Node* node, ParentTraversalDetails* details) const
+{
+    ASSERT(node);
+    if (!node->isInsertionPoint())
+        return const_cast<Node*>(node);
+    const InsertionPoint* insertionPoint = toInsertionPoint(node);
+    return insertionPoint->hasDistribution() ? 0 :
+        insertionPoint->isActive() ? traverseParent(node, details) : const_cast<Node*>(node);
+}
+
+void ComposedShadowTreeWalker::parent()
+{
+    assertPrecondition();
+    m_node = traverseParent(m_node);
+    assertPostcondition();
+}
+
+// FIXME: Use an iterative algorithm so that it can be inlined.
+// https://bugs.webkit.org/show_bug.cgi?id=90415
+Node* ComposedShadowTreeWalker::traverseParent(const Node* node, ParentTraversalDetails* details) const
+{
+    if (node->isPseudoElement())
+        return node->parentOrShadowHostNode();
+
+    if (!canCrossUpperBoundary() && node->isShadowRoot()) {
+        ASSERT(toShadowRoot(node)->isYoungest());
+        return 0;
+    }
+
+    if (nodeCanBeDistributed(node)) {
+        if (InsertionPoint* insertionPoint = resolveReprojection(node)) {
+            if (details)
+                details->didTraverseInsertionPoint(insertionPoint);
+            return traverseParent(insertionPoint, details);
+        }
+
+        // The node is a non-distributed light child or older shadow's child.
+        if (details)
+            details->childWasOutOfComposition();
+    }
+    return traverseParentInCurrentTree(node, details);
+}
+
+inline Node* ComposedShadowTreeWalker::traverseParentInCurrentTree(const Node* node, ParentTraversalDetails* details) const
+{
+    if (Node* parent = node->parentNode())
+        return parent->isShadowRoot() ? traverseParentBackToYoungerShadowRootOrHost(toShadowRoot(parent), details) : traverseNodeEscapingFallbackContents(parent, details);
+    return 0;
+}
+
+Node* ComposedShadowTreeWalker::traverseParentBackToYoungerShadowRootOrHost(const ShadowRoot* shadowRoot, ParentTraversalDetails* details) const
+{
+    ASSERT(shadowRoot);
+    ASSERT(!ScopeContentDistribution::assignedTo(shadowRoot));
+
+    if (shadowRoot->isYoungest()) {
+        if (canCrossUpperBoundary()) {
+            if (details)
+                details->didTraverseShadowRoot(shadowRoot);
+            return shadowRoot->host();
+        }
+
+        return const_cast<ShadowRoot*>(shadowRoot);
+    }
+
+    return 0;
+}
+
+Node* ComposedShadowTreeWalker::traverseNextSibling(const Node* node)
+{
+    ASSERT(node);
+    return traverseSiblingOrBackToInsertionPoint(node, TraversalDirectionForward);
+}
+
+Node* ComposedShadowTreeWalker::traversePreviousSibling(const Node* node)
+{
+    ASSERT(node);
+    return traverseSiblingOrBackToInsertionPoint(node, TraversalDirectionBackward);
+}
+
+void ComposedShadowTreeWalker::next()
+{
+    assertPrecondition();
+    if (Node* next = traverseFirstChild(m_node))
+        m_node = next;
+    else if (Node* next = traverseNextSibling(m_node))
+        m_node = next;
+    else {
+        const Node* n = m_node;
+        while (n && !traverseNextSibling(n))
+            n = traverseParent(n);
+        m_node = n ? traverseNextSibling(n) : 0;
+    }
+    assertPostcondition();
+}
+
+void ComposedShadowTreeWalker::previous()
+{
+    assertPrecondition();
+    if (Node* n = traversePreviousSibling(m_node)) {
+        while (Node* child = traverseLastChild(n))
+            n = child;
+        m_node = n;
+    } else
+        parent();
+    assertPostcondition();
+}
+
+} // namespace
diff --git a/Source/core/dom/ComposedShadowTreeWalker.h b/Source/core/dom/ComposedShadowTreeWalker.h
new file mode 100644
index 0000000..1fd2aaa
--- /dev/null
+++ b/Source/core/dom/ComposedShadowTreeWalker.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2012 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 ComposedShadowTreeWalker_h
+#define ComposedShadowTreeWalker_h
+
+#include "core/dom/NodeRenderingTraversal.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/html/shadow/InsertionPoint.h"
+
+namespace WebCore {
+
+class Node;
+class ShadowRoot;
+
+// FIXME: Make some functions inline to optimise the performance.
+// https://bugs.webkit.org/show_bug.cgi?id=82702
+class ComposedShadowTreeWalker {
+public:
+    typedef NodeRenderingTraversal::ParentDetails ParentTraversalDetails;
+
+    enum Policy {
+        CrossUpperBoundary,
+        DoNotCrossUpperBoundary,
+    };
+
+    enum StartPolicy {
+        CanStartFromShadowBoundary,
+        CannotStartFromShadowBoundary
+    };
+
+    ComposedShadowTreeWalker(const Node*, Policy = CrossUpperBoundary, StartPolicy = CannotStartFromShadowBoundary);
+
+    // For a common use case such as:
+    // for (ComposedShadowTreeWalker walker = ComposedShadowTreeWalker::fromFirstChild(node); walker.get(); walker.nextSibling())
+    static ComposedShadowTreeWalker fromFirstChild(const Node*, Policy = CrossUpperBoundary);
+
+    Node* get() const { return const_cast<Node*>(m_node); }
+
+    void firstChild();
+    void lastChild();
+
+    void nextSibling();
+    void previousSibling();
+
+    void parent();
+
+    void next();
+    void previous();
+
+    Node* traverseParent(const Node*, ParentTraversalDetails* = 0) const;
+
+private:
+    ComposedShadowTreeWalker(const Node*, ParentTraversalDetails*);
+
+    enum TraversalDirection {
+        TraversalDirectionForward,
+        TraversalDirectionBackward
+    };
+
+    bool canCrossUpperBoundary() const { return m_policy == CrossUpperBoundary; }
+
+    void assertPrecondition() const
+    {
+#ifndef NDEBUG
+        ASSERT(m_node);
+        if (canCrossUpperBoundary())
+            ASSERT(!m_node->isShadowRoot());
+        else
+            ASSERT(!m_node->isShadowRoot() || toShadowRoot(m_node)->isYoungest());
+        ASSERT(!isActiveInsertionPoint(m_node));
+#endif
+    }
+
+    void assertPostcondition() const
+    {
+#ifndef NDEBUG
+        if (m_node)
+            assertPrecondition();
+#endif
+    }
+
+    static Node* traverseNode(const Node*, TraversalDirection);
+    static Node* traverseLightChildren(const Node*, TraversalDirection);
+
+    Node* traverseFirstChild(const Node*) const;
+    Node* traverseLastChild(const Node*) const;
+    Node* traverseChild(const Node*, TraversalDirection) const;
+
+    static Node* traverseNextSibling(const Node*);
+    static Node* traversePreviousSibling(const Node*);
+
+    static Node* traverseSiblingOrBackToInsertionPoint(const Node*, TraversalDirection);
+    static Node* traverseSiblingInCurrentTree(const Node*, TraversalDirection);
+
+    static Node* traverseSiblings(const Node*, TraversalDirection);
+    static Node* traverseDistributedNodes(const Node*, const InsertionPoint*, TraversalDirection);
+
+    static Node* traverseBackToYoungerShadowRoot(const Node*, TraversalDirection);
+    static Node* escapeFallbackContentElement(const Node*, TraversalDirection);
+
+    Node* traverseNodeEscapingFallbackContents(const Node*, ParentTraversalDetails* = 0) const;
+    Node* traverseParentInCurrentTree(const Node*, ParentTraversalDetails* = 0) const;
+    Node* traverseParentBackToYoungerShadowRootOrHost(const ShadowRoot*, ParentTraversalDetails* = 0) const;
+
+    const Node* m_node;
+    Policy m_policy;
+};
+
+inline ComposedShadowTreeWalker::ComposedShadowTreeWalker(const Node* node, Policy policy, StartPolicy startPolicy)
+    : m_node(node)
+    , m_policy(policy)
+{
+    UNUSED_PARAM(startPolicy);
+#ifndef NDEBUG
+    if (m_node && startPolicy == CannotStartFromShadowBoundary)
+        assertPrecondition();
+#endif
+}
+
+} // namespace
+
+#endif
diff --git a/Source/core/dom/CompositionEvent.cpp b/Source/core/dom/CompositionEvent.cpp
new file mode 100644
index 0000000..caad777
--- /dev/null
+++ b/Source/core/dom/CompositionEvent.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "core/dom/CompositionEvent.h"
+
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+CompositionEventInit::CompositionEventInit()
+{
+}
+
+CompositionEvent::CompositionEvent()
+{
+    ScriptWrappable::init(this);
+}
+
+CompositionEvent::CompositionEvent(const AtomicString& type, PassRefPtr<AbstractView> view, const String& data)
+    : UIEvent(type, true, true, view, 0)
+    , m_data(data)
+{
+    ScriptWrappable::init(this);
+}
+
+CompositionEvent::CompositionEvent(const AtomicString& type, const CompositionEventInit& initializer)
+    : UIEvent(type, initializer)
+    , m_data(initializer.data)
+{
+    ScriptWrappable::init(this);
+}
+
+CompositionEvent::~CompositionEvent()
+{
+}
+
+void CompositionEvent::initCompositionEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView> view, const String& data)
+{
+    if (dispatched())
+        return;
+
+    initUIEvent(type, canBubble, cancelable, view, 0);
+
+    m_data = data;
+}
+
+const AtomicString& CompositionEvent::interfaceName() const
+{
+    return eventNames().interfaceForCompositionEvent;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/CompositionEvent.h b/Source/core/dom/CompositionEvent.h
new file mode 100644
index 0000000..167b6d1
--- /dev/null
+++ b/Source/core/dom/CompositionEvent.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef CompositionEvent_h
+#define CompositionEvent_h
+
+#include "core/dom/UIEvent.h"
+
+namespace WebCore {
+
+struct CompositionEventInit : UIEventInit {
+    CompositionEventInit();
+
+    String data;
+};
+
+class CompositionEvent : public UIEvent {
+public:
+    static PassRefPtr<CompositionEvent> create()
+    {
+        return adoptRef(new CompositionEvent);
+    }
+
+    static PassRefPtr<CompositionEvent> create(const AtomicString& type, PassRefPtr<AbstractView> view, const String& data)
+    {
+        return adoptRef(new CompositionEvent(type, view, data));
+    }
+
+    static PassRefPtr<CompositionEvent> create(const AtomicString& type, const CompositionEventInit& initializer)
+    {
+        return adoptRef(new CompositionEvent(type, initializer));
+    }
+
+    virtual ~CompositionEvent();
+
+    void initCompositionEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>, const String& data);
+
+    String data() const { return m_data; }
+
+    virtual const AtomicString& interfaceName() const;
+
+private:
+    CompositionEvent();
+    CompositionEvent(const AtomicString& type, PassRefPtr<AbstractView>, const String&);
+    CompositionEvent(const AtomicString& type, const CompositionEventInit&);
+
+    String m_data;
+};
+
+} // namespace WebCore
+
+#endif // CompositionEvent_h
diff --git a/Source/core/dom/CompositionEvent.idl b/Source/core/dom/CompositionEvent.idl
new file mode 100644
index 0000000..61bfad0
--- /dev/null
+++ b/Source/core/dom/CompositionEvent.idl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+[
+    ConstructorTemplate=Event
+] interface CompositionEvent : UIEvent {
+
+    [InitializedByEventConstructor] readonly attribute DOMString data;
+
+    void initCompositionEvent([Default=Undefined] optional DOMString typeArg, 
+                              [Default=Undefined] optional boolean canBubbleArg, 
+                              [Default=Undefined] optional boolean cancelableArg, 
+                              [Default=Undefined] optional DOMWindow viewArg, 
+                              [Default=Undefined] optional DOMString dataArg);
+
+};
+
diff --git a/Source/core/dom/ContainerNode.cpp b/Source/core/dom/ContainerNode.cpp
new file mode 100644
index 0000000..a25bfb9
--- /dev/null
+++ b/Source/core/dom/ContainerNode.cpp
@@ -0,0 +1,954 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/ContainerNode.h"
+
+#include "HTMLNames.h"
+#include "core/accessibility/AXObjectCache.h"
+#include "core/dom/ChildListMutationScope.h"
+#include "core/dom/ContainerNodeAlgorithms.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/MutationEvent.h"
+#include "core/dom/NodeRenderStyle.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/dom/TemplateContentDocumentFragment.h"
+#include "core/html/shadow/InsertionPoint.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/loader/cache/MemoryCache.h"
+#include "core/page/Chrome.h"
+#include "core/page/ChromeClient.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/RenderBox.h"
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/RenderWidget.h"
+#include "core/rendering/RootInlineBox.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/Vector.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static void dispatchChildInsertionEvents(Node*);
+static void dispatchChildRemovalEvents(Node*);
+static void updateTreeAfterInsertion(ContainerNode*, Node*, AttachBehavior);
+
+typedef pair<RefPtr<Node>, unsigned> CallbackParameters;
+typedef pair<NodeCallback, CallbackParameters> CallbackInfo;
+typedef Vector<CallbackInfo> NodeCallbackQueue;
+
+static NodeCallbackQueue* s_postAttachCallbackQueue;
+
+static size_t s_attachDepth;
+static bool s_shouldReEnableMemoryCacheCallsAfterAttach;
+
+ChildNodesLazySnapshot* ChildNodesLazySnapshot::latestSnapshot = 0;
+
+#ifndef NDEBUG
+unsigned NoEventDispatchAssertion::s_count = 0;
+#endif
+
+static void collectChildrenAndRemoveFromOldParent(Node* node, NodeVector& nodes, ExceptionCode& ec)
+{
+    if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) {
+        nodes.append(node);
+        if (ContainerNode* oldParent = node->parentNode())
+            oldParent->removeChild(node, ec);
+        return;
+    }
+    getChildNodes(node, nodes);
+    toContainerNode(node)->removeChildren();
+}
+
+void ContainerNode::removeDetachedChildren()
+{
+    if (connectedSubframeCount()) {
+        for (Node* child = firstChild(); child; child = child->nextSibling())
+            child->updateAncestorConnectedSubframeCountForRemoval();
+    }
+    // FIXME: We should be able to ASSERT(!attached()) here: https://bugs.webkit.org/show_bug.cgi?id=107801
+    removeDetachedChildrenInContainer<Node, ContainerNode>(this);
+}
+
+void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent)
+{
+    NodeVector children;
+    getChildNodes(oldParent, children);
+
+    if (oldParent->document()->hasMutationObserversOfType(MutationObserver::ChildList)) {
+        ChildListMutationScope mutation(oldParent);
+        for (unsigned i = 0; i < children.size(); ++i)
+            mutation.willRemoveChild(children[i].get());
+    }
+
+    // FIXME: We need to do notifyMutationObserversNodeWillDetach() for each child,
+    // probably inside removeDetachedChildrenInContainer.
+
+    oldParent->removeDetachedChildren();
+
+    for (unsigned i = 0; i < children.size(); ++i) {
+        if (children[i]->attached())
+            children[i]->detach();
+        // FIXME: We need a no mutation event version of adoptNode.
+        RefPtr<Node> child = document()->adoptNode(children[i].release(), ASSERT_NO_EXCEPTION);
+        parserAppendChild(child.get());
+        // FIXME: Together with adoptNode above, the tree scope might get updated recursively twice
+        // (if the document changed or oldParent was in a shadow tree, AND *this is in a shadow tree).
+        // Can we do better?
+        treeScope()->adoptIfNeeded(child.get());
+        if (attached() && !child->attached())
+            child->attach();
+    }
+}
+
+ContainerNode::~ContainerNode()
+{
+    if (Document* document = documentInternal())
+        willBeDeletedFrom(document);
+    removeDetachedChildren();
+}
+
+static inline bool isChildTypeAllowed(ContainerNode* newParent, Node* child)
+{
+    if (!child->isDocumentFragment())
+        return newParent->childTypeAllowed(child->nodeType());
+
+    for (Node* node = child->firstChild(); node; node = node->nextSibling()) {
+        if (!newParent->childTypeAllowed(node->nodeType()))
+            return false;
+    }
+    return true;
+}
+
+static inline bool isInTemplateContent(const Node* node)
+{
+    Document* document = node->document();
+    return document && document == document->templateDocument();
+}
+
+static inline bool containsConsideringHostElements(const Node* newChild, const Node* newParent)
+{
+    return (newParent->isInShadowTree() || isInTemplateContent(newParent))
+        ? newChild->containsIncludingHostElements(newParent)
+        : newChild->contains(newParent);
+}
+
+static inline ExceptionCode checkAcceptChild(ContainerNode* newParent, Node* newChild, Node* oldChild)
+{
+    // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
+    if (!newChild)
+        return NOT_FOUND_ERR;
+
+    // Use common case fast path if possible.
+    if ((newChild->isElementNode() || newChild->isTextNode()) && newParent->isElementNode()) {
+        ASSERT(!newParent->isReadOnlyNode());
+        ASSERT(!newParent->isDocumentTypeNode());
+        ASSERT(isChildTypeAllowed(newParent, newChild));
+        if (containsConsideringHostElements(newChild, newParent))
+            return HIERARCHY_REQUEST_ERR;
+        return 0;
+    }
+
+    // This should never happen, but also protect release builds from tree corruption.
+    ASSERT(!newChild->isPseudoElement());
+    if (newChild->isPseudoElement())
+        return HIERARCHY_REQUEST_ERR;
+
+    if (newParent->isReadOnlyNode())
+        return NO_MODIFICATION_ALLOWED_ERR;
+    if (newChild->inDocument() && newChild->isDocumentTypeNode())
+        return HIERARCHY_REQUEST_ERR;
+    if (containsConsideringHostElements(newChild, newParent))
+        return HIERARCHY_REQUEST_ERR;
+
+    if (oldChild && newParent->isDocumentNode()) {
+        if (!toDocument(newParent)->canReplaceChild(newChild, oldChild))
+            return HIERARCHY_REQUEST_ERR;
+    } else if (!isChildTypeAllowed(newParent, newChild))
+        return HIERARCHY_REQUEST_ERR;
+
+    return 0;
+}
+
+static inline bool checkAcceptChildGuaranteedNodeTypes(ContainerNode* newParent, Node* newChild, ExceptionCode& ec)
+{
+    ASSERT(!newParent->isReadOnlyNode());
+    ASSERT(!newParent->isDocumentTypeNode());
+    ASSERT(isChildTypeAllowed(newParent, newChild));
+    if (newChild->contains(newParent)) {
+        ec = HIERARCHY_REQUEST_ERR;
+        return false;
+    }
+
+    return true;
+}
+
+static inline bool checkAddChild(ContainerNode* newParent, Node* newChild, ExceptionCode& ec)
+{
+    ec = checkAcceptChild(newParent, newChild, 0);
+    if (ec)
+        return false;
+
+    return true;
+}
+
+static inline bool checkReplaceChild(ContainerNode* newParent, Node* newChild, Node* oldChild, ExceptionCode& ec)
+{
+    ec = checkAcceptChild(newParent, newChild, oldChild);
+    if (ec)
+        return false;
+
+    return true;
+}
+
+bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, AttachBehavior attachBehavior)
+{
+    // Check that this node is not "floating".
+    // If it is, it can be deleted as a side effect of sending mutation events.
+    ASSERT(refCount() || parentOrShadowHostNode());
+
+    RefPtr<Node> protect(this);
+
+    ec = 0;
+
+    // insertBefore(node, 0) is equivalent to appendChild(node)
+    if (!refChild)
+        return appendChild(newChild, ec, attachBehavior);
+
+    // Make sure adding the new child is OK.
+    if (!checkAddChild(this, newChild.get(), ec))
+        return false;
+
+    // NOT_FOUND_ERR: Raised if refChild is not a child of this node
+    if (refChild->parentNode() != this) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    if (refChild->previousSibling() == newChild || refChild == newChild) // nothing to do
+        return true;
+
+    RefPtr<Node> next = refChild;
+
+    NodeVector targets;
+    collectChildrenAndRemoveFromOldParent(newChild.get(), targets, ec);
+    if (ec)
+        return false;
+    if (targets.isEmpty())
+        return true;
+
+    // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
+    if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), ec))
+        return false;
+
+    InspectorInstrumentation::willInsertDOMNode(document(), this);
+
+    ChildListMutationScope mutation(this);
+    for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
+        Node* child = it->get();
+
+        // Due to arbitrary code running in response to a DOM mutation event it's
+        // possible that "next" is no longer a child of "this".
+        // It's also possible that "child" has been inserted elsewhere.
+        // In either of those cases, we'll just stop.
+        if (next->parentNode() != this)
+            break;
+        if (child->parentNode())
+            break;
+
+        treeScope()->adoptIfNeeded(child);
+
+        insertBeforeCommon(next.get(), child);
+
+        updateTreeAfterInsertion(this, child, attachBehavior);
+    }
+
+    dispatchSubtreeModifiedEvent();
+    return true;
+}
+
+void ContainerNode::insertBeforeCommon(Node* nextChild, Node* newChild)
+{
+    NoEventDispatchAssertion assertNoEventDispatch;
+
+    ASSERT(newChild);
+    ASSERT(!newChild->parentNode()); // Use insertBefore if you need to handle reparenting (and want DOM mutation events).
+    ASSERT(!newChild->nextSibling());
+    ASSERT(!newChild->previousSibling());
+    ASSERT(!newChild->isShadowRoot());
+
+    Node* prev = nextChild->previousSibling();
+    ASSERT(m_lastChild != prev);
+    nextChild->setPreviousSibling(newChild);
+    if (prev) {
+        ASSERT(m_firstChild != nextChild);
+        ASSERT(prev->nextSibling() == nextChild);
+        prev->setNextSibling(newChild);
+    } else {
+        ASSERT(m_firstChild == nextChild);
+        m_firstChild = newChild;
+    }
+    newChild->setParentOrShadowHostNode(this);
+    newChild->setPreviousSibling(prev);
+    newChild->setNextSibling(nextChild);
+}
+
+void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node* nextChild)
+{
+    ASSERT(newChild);
+    ASSERT(nextChild);
+    ASSERT(nextChild->parentNode() == this);
+    ASSERT(!newChild->isDocumentFragment());
+    ASSERT(!hasTagName(HTMLNames::templateTag));
+
+    if (nextChild->previousSibling() == newChild || nextChild == newChild) // nothing to do
+        return;
+
+    if (document() != newChild->document())
+        document()->adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
+
+    insertBeforeCommon(nextChild, newChild.get());
+
+    newChild->updateAncestorConnectedSubframeCountForInsertion();
+
+    ChildListMutationScope(this).childAdded(newChild.get());
+
+    childrenChanged(true, newChild->previousSibling(), nextChild, 1);
+    ChildNodeInsertionNotifier(this).notify(newChild.get());
+}
+
+bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, AttachBehavior attachBehavior)
+{
+    // Check that this node is not "floating".
+    // If it is, it can be deleted as a side effect of sending mutation events.
+    ASSERT(refCount() || parentOrShadowHostNode());
+
+    RefPtr<Node> protect(this);
+
+    ec = 0;
+
+    if (oldChild == newChild) // nothing to do
+        return true;
+
+    if (!oldChild) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    // Make sure replacing the old child with the new is ok
+    if (!checkReplaceChild(this, newChild.get(), oldChild, ec))
+        return false;
+
+    // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
+    if (oldChild->parentNode() != this) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    ChildListMutationScope mutation(this);
+
+    RefPtr<Node> next = oldChild->nextSibling();
+
+    // Remove the node we're replacing
+    RefPtr<Node> removedChild = oldChild;
+    removeChild(oldChild, ec);
+    if (ec)
+        return false;
+
+    if (next && (next->previousSibling() == newChild || next == newChild)) // nothing to do
+        return true;
+
+    // Does this one more time because removeChild() fires a MutationEvent.
+    if (!checkReplaceChild(this, newChild.get(), oldChild, ec))
+        return false;
+
+    NodeVector targets;
+    collectChildrenAndRemoveFromOldParent(newChild.get(), targets, ec);
+    if (ec)
+        return false;
+
+    // Does this yet another check because collectChildrenAndRemoveFromOldParent() fires a MutationEvent.
+    if (!checkReplaceChild(this, newChild.get(), oldChild, ec))
+        return false;
+
+    InspectorInstrumentation::willInsertDOMNode(document(), this);
+
+    // Add the new child(ren)
+    for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
+        Node* child = it->get();
+
+        // Due to arbitrary code running in response to a DOM mutation event it's
+        // possible that "next" is no longer a child of "this".
+        // It's also possible that "child" has been inserted elsewhere.
+        // In either of those cases, we'll just stop.
+        if (next && next->parentNode() != this)
+            break;
+        if (child->parentNode())
+            break;
+
+        treeScope()->adoptIfNeeded(child);
+
+        // Add child before "next".
+        {
+            NoEventDispatchAssertion assertNoEventDispatch;
+            if (next)
+                insertBeforeCommon(next.get(), child);
+            else
+                appendChildToContainer(child, this);
+        }
+
+        updateTreeAfterInsertion(this, child, attachBehavior);
+    }
+
+    dispatchSubtreeModifiedEvent();
+    return true;
+}
+
+static void willRemoveChild(Node* child)
+{
+    ASSERT(child->parentNode());
+    ChildListMutationScope(child->parentNode()).willRemoveChild(child);
+    child->notifyMutationObserversNodeWillDetach();
+    dispatchChildRemovalEvents(child);
+    child->document()->nodeWillBeRemoved(child); // e.g. mutation event listener can create a new range.
+    ChildFrameDisconnector(child).disconnect();
+}
+
+static void willRemoveChildren(ContainerNode* container)
+{
+    NodeVector children;
+    getChildNodes(container, children);
+
+    container->document()->nodeChildrenWillBeRemoved(container);
+
+    ChildListMutationScope mutation(container);
+    for (NodeVector::const_iterator it = children.begin(); it != children.end(); it++) {
+        Node* child = it->get();
+        mutation.willRemoveChild(child);
+        child->notifyMutationObserversNodeWillDetach();
+
+        // fire removed from document mutation events.
+        dispatchChildRemovalEvents(child);
+    }
+
+    ChildFrameDisconnector(container).disconnect(ChildFrameDisconnector::DescendantsOnly);
+}
+
+void ContainerNode::disconnectDescendantFrames()
+{
+    ChildFrameDisconnector(this).disconnect();
+}
+
+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() || parentOrShadowHostNode());
+
+    RefPtr<Node> protect(this);
+
+    ec = 0;
+
+    // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+    if (isReadOnlyNode()) {
+        ec = NO_MODIFICATION_ALLOWED_ERR;
+        return false;
+    }
+
+    // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
+    if (!oldChild || oldChild->parentNode() != this) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    RefPtr<Node> child = oldChild;
+
+    document()->removeFocusedNodeOfSubtree(child.get());
+
+    document()->removeFullScreenElementOfSubtree(child.get());
+
+    // Events fired when blurring currently focused node might have moved this
+    // child into a different parent.
+    if (child->parentNode() != this) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    willRemoveChild(child.get());
+
+    // Mutation events might have moved this child into a different parent.
+    if (child->parentNode() != this) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    {
+        WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
+
+        Node* prev = child->previousSibling();
+        Node* next = child->nextSibling();
+        removeBetween(prev, next, child.get());
+        childrenChanged(false, prev, next, -1);
+        ChildNodeRemovalNotifier(this).notify(child.get());
+    }
+    dispatchSubtreeModifiedEvent();
+
+    return child;
+}
+
+void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node* oldChild)
+{
+    NoEventDispatchAssertion assertNoEventDispatch;
+
+    ASSERT(oldChild);
+    ASSERT(oldChild->parentNode() == this);
+
+    // Remove from rendering tree
+    if (oldChild->attached())
+        oldChild->detach();
+
+    if (nextChild)
+        nextChild->setPreviousSibling(previousChild);
+    if (previousChild)
+        previousChild->setNextSibling(nextChild);
+    if (m_firstChild == oldChild)
+        m_firstChild = nextChild;
+    if (m_lastChild == oldChild)
+        m_lastChild = previousChild;
+
+    oldChild->setPreviousSibling(0);
+    oldChild->setNextSibling(0);
+    oldChild->setParentOrShadowHostNode(0);
+
+    document()->adoptIfNeeded(oldChild);
+}
+
+void ContainerNode::parserRemoveChild(Node* oldChild)
+{
+    ASSERT(oldChild);
+    ASSERT(oldChild->parentNode() == this);
+    ASSERT(!oldChild->isDocumentFragment());
+
+    Node* prev = oldChild->previousSibling();
+    Node* next = oldChild->nextSibling();
+
+    oldChild->updateAncestorConnectedSubframeCountForRemoval();
+
+    ChildListMutationScope(this).willRemoveChild(oldChild);
+    oldChild->notifyMutationObserversNodeWillDetach();
+
+    removeBetween(prev, next, oldChild);
+
+    childrenChanged(true, prev, next, -1);
+    ChildNodeRemovalNotifier(this).notify(oldChild);
+}
+
+// this differs from other remove functions because it forcibly removes all the children,
+// regardless of read-only status or event exceptions, e.g.
+void ContainerNode::removeChildren()
+{
+    if (!m_firstChild)
+        return;
+
+    // The container node can be removed from event handlers.
+    RefPtr<ContainerNode> protect(this);
+
+    // exclude this node when looking for removed focusedNode since only children will be removed
+    document()->removeFocusedNodeOfSubtree(this, true);
+
+    document()->removeFullScreenElementOfSubtree(this, true);
+
+    // Do any prep work needed before actually starting to detach
+    // and remove... e.g. stop loading frames, fire unload events.
+    willRemoveChildren(protect.get());
+
+    NodeVector removedChildren;
+    {
+        WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
+        {
+            NoEventDispatchAssertion assertNoEventDispatch;
+            removedChildren.reserveInitialCapacity(childNodeCount());
+            while (m_firstChild) {
+                removedChildren.append(m_firstChild);
+                removeBetween(0, m_firstChild->nextSibling(), m_firstChild);
+            }
+        }
+
+        childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size()));
+        
+        for (size_t i = 0; i < removedChildren.size(); ++i)
+            ChildNodeRemovalNotifier(this).notify(removedChildren[i].get());
+    }
+
+    dispatchSubtreeModifiedEvent();
+}
+
+bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, AttachBehavior attachBehavior)
+{
+    RefPtr<ContainerNode> protect(this);
+
+    // Check that this node is not "floating".
+    // If it is, it can be deleted as a side effect of sending mutation events.
+    ASSERT(refCount() || parentOrShadowHostNode());
+
+    ec = 0;
+
+    // Make sure adding the new child is ok
+    if (!checkAddChild(this, newChild.get(), ec))
+        return false;
+
+    if (newChild == m_lastChild) // nothing to do
+        return newChild;
+
+    NodeVector targets;
+    collectChildrenAndRemoveFromOldParent(newChild.get(), targets, ec);
+    if (ec)
+        return false;
+
+    if (targets.isEmpty())
+        return true;
+
+    // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
+    if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), ec))
+        return false;
+
+    InspectorInstrumentation::willInsertDOMNode(document(), this);
+
+    // Now actually add the child(ren)
+    ChildListMutationScope mutation(this);
+    for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
+        Node* child = it->get();
+
+        // If the child has a parent again, just stop what we're doing, because
+        // that means someone is doing something with DOM mutation -- can't re-parent
+        // a child that already has a parent.
+        if (child->parentNode())
+            break;
+
+        treeScope()->adoptIfNeeded(child);
+
+        // Append child to the end of the list
+        {
+            NoEventDispatchAssertion assertNoEventDispatch;
+            appendChildToContainer(child, this);
+        }
+
+        updateTreeAfterInsertion(this, child, attachBehavior);
+    }
+
+    dispatchSubtreeModifiedEvent();
+    return true;
+}
+
+void ContainerNode::parserAppendChild(PassRefPtr<Node> newChild)
+{
+    ASSERT(newChild);
+    ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events).
+    ASSERT(!newChild->isDocumentFragment());
+    ASSERT(!hasTagName(HTMLNames::templateTag));
+
+    if (document() != newChild->document())
+        document()->adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
+
+    Node* last = m_lastChild;
+    {
+        NoEventDispatchAssertion assertNoEventDispatch;
+        // FIXME: This method should take a PassRefPtr.
+        appendChildToContainer(newChild.get(), this);
+        treeScope()->adoptIfNeeded(newChild.get());
+    }
+
+    newChild->updateAncestorConnectedSubframeCountForInsertion();
+
+    ChildListMutationScope(this).childAdded(newChild.get());
+
+    childrenChanged(true, last, 0, 1);
+    ChildNodeInsertionNotifier(this).notify(newChild.get());
+}
+
+void ContainerNode::suspendPostAttachCallbacks()
+{
+    if (!s_attachDepth) {
+        ASSERT(!s_shouldReEnableMemoryCacheCallsAfterAttach);
+        if (Page* page = document()->page()) {
+            // FIXME: How can this call be specific to one Page, while the
+            // s_attachDepth is a global? Doesn't make sense.
+            if (page->areMemoryCacheClientCallsEnabled()) {
+                page->setMemoryCacheClientCallsEnabled(false);
+                s_shouldReEnableMemoryCacheCallsAfterAttach = true;
+            }
+        }
+    }
+    ++s_attachDepth;
+}
+
+void ContainerNode::resumePostAttachCallbacks()
+{
+    if (s_attachDepth == 1) {
+        RefPtr<ContainerNode> protect(this);
+
+        if (s_postAttachCallbackQueue)
+            dispatchPostAttachCallbacks();
+        if (s_shouldReEnableMemoryCacheCallsAfterAttach) {
+            s_shouldReEnableMemoryCacheCallsAfterAttach = false;
+            if (Page* page = document()->page())
+                page->setMemoryCacheClientCallsEnabled(true);
+        }
+    }
+    --s_attachDepth;
+}
+
+void ContainerNode::queuePostAttachCallback(NodeCallback callback, Node* node, unsigned callbackData)
+{
+    if (!s_postAttachCallbackQueue)
+        s_postAttachCallbackQueue = new NodeCallbackQueue;
+    
+    s_postAttachCallbackQueue->append(CallbackInfo(callback, CallbackParameters(node, callbackData)));
+}
+
+bool ContainerNode::postAttachCallbacksAreSuspended()
+{
+    return s_attachDepth;
+}
+
+void ContainerNode::dispatchPostAttachCallbacks()
+{
+    // We recalculate size() each time through the loop because a callback
+    // can add more callbacks to the end of the queue.
+    for (size_t i = 0; i < s_postAttachCallbackQueue->size(); ++i) {
+        const CallbackInfo& info = (*s_postAttachCallbackQueue)[i];
+        NodeCallback callback = info.first;
+        CallbackParameters params = info.second;
+
+        callback(params.first.get(), params.second);
+    }
+    s_postAttachCallbackQueue->clear();
+}
+
+static void needsStyleRecalcCallback(Node* node, unsigned data)
+{
+    node->setNeedsStyleRecalc(static_cast<StyleChangeType>(data));
+}
+
+void ContainerNode::scheduleSetNeedsStyleRecalc(StyleChangeType changeType)
+{
+    if (postAttachCallbacksAreSuspended())
+        queuePostAttachCallback(needsStyleRecalcCallback, this, static_cast<unsigned>(changeType));
+    else
+        setNeedsStyleRecalc(changeType);
+}
+
+void ContainerNode::attach()
+{
+    attachChildren();
+    Node::attach();
+}
+
+void ContainerNode::detach()
+{
+    detachChildren();
+    clearChildNeedsStyleRecalc();
+    Node::detach();
+}
+
+void ContainerNode::childrenChanged(bool changedByParser, Node*, Node*, int childCountDelta)
+{
+    document()->incDOMTreeVersion();
+    if (!changedByParser && childCountDelta)
+        document()->updateRangesAfterChildrenChanged(this);
+    invalidateNodeListCachesInAncestors();
+}
+
+void ContainerNode::cloneChildNodes(ContainerNode *clone)
+{
+    ExceptionCode ec = 0;
+    for (Node* n = firstChild(); n && !ec; n = n->nextSibling())
+        clone->appendChild(n->cloneNode(true), ec);
+}
+
+
+void ContainerNode::setFocus(bool received)
+{
+    if (focused() == received)
+        return;
+
+    Node::setFocus(received);
+
+    // note that we need to recalc the style
+    setNeedsStyleRecalc();
+}
+
+void ContainerNode::setActive(bool down, bool pause)
+{
+    if (down == active()) return;
+
+    Node::setActive(down);
+
+    // note that we need to recalc the style
+    // FIXME: Move to Element
+    if (renderer()) {
+        if (renderStyle()->affectedByActive() || (isElementNode() && toElement(this)->childrenAffectedByActive()))
+            setNeedsStyleRecalc();
+        if (renderStyle()->hasAppearance())
+            renderer()->theme()->stateChanged(renderer(), PressedState);
+    }
+}
+
+void ContainerNode::setHovered(bool over)
+{
+    if (over == hovered()) return;
+
+    Node::setHovered(over);
+
+    // note that we need to recalc the style
+    // FIXME: Move to Element
+    if (renderer()) {
+        if (renderStyle()->affectedByHover() || (isElementNode() && toElement(this)->childrenAffectedByHover()))
+            setNeedsStyleRecalc();
+        if (renderer() && renderer()->style()->hasAppearance())
+            renderer()->theme()->stateChanged(renderer(), HoverState);
+    }
+}
+
+unsigned ContainerNode::childNodeCount() const
+{
+    unsigned count = 0;
+    Node *n;
+    for (n = firstChild(); n; n = n->nextSibling())
+        count++;
+    return count;
+}
+
+Node *ContainerNode::childNode(unsigned index) const
+{
+    unsigned i;
+    Node *n = firstChild();
+    for (i = 0; n != 0 && i < index; i++)
+        n = n->nextSibling();
+    return n;
+}
+
+void ContainerNode::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    Node::reportMemoryUsage(memoryObjectInfo);
+    info.ignoreMember(m_firstChild);
+    info.ignoreMember(m_lastChild);
+
+    // Report child nodes as direct members to make them look like a tree in the snapshot.
+    NodeVector children;
+    getChildNodes(const_cast<ContainerNode*>(this), children);
+    for (size_t i = 0; i < children.size(); ++i)
+        info.addMember(children[i], "child");
+}
+
+static void dispatchChildInsertionEvents(Node* child)
+{
+    if (child->isInShadowTree())
+        return;
+
+    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
+
+    RefPtr<Node> c = child;
+    RefPtr<Document> document = child->document();
+
+    if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
+        c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
+
+    // dispatch the DOMNodeInsertedIntoDocument event to all descendants
+    if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) {
+        for (; c; c = NodeTraversal::next(c.get(), child))
+            c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false));
+    }
+}
+
+static void dispatchChildRemovalEvents(Node* child)
+{
+    if (child->isInShadowTree()) {
+        InspectorInstrumentation::willRemoveDOMNode(child->document(), child);
+        return;
+    }
+
+    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
+
+    InspectorInstrumentation::willRemoveDOMNode(child->document(), child);
+
+    RefPtr<Node> c = child;
+    RefPtr<Document> document = child->document();
+
+    // dispatch pre-removal mutation events
+    if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER))
+        c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode()));
+
+    // dispatch the DOMNodeRemovedFromDocument event to all descendants
+    if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) {
+        for (; c; c = NodeTraversal::next(c.get(), child))
+            c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false));
+    }
+}
+
+static void updateTreeAfterInsertion(ContainerNode* parent, Node* child, AttachBehavior attachBehavior)
+{
+    ASSERT(parent->refCount());
+    ASSERT(child->refCount());
+
+    ChildListMutationScope(parent).childAdded(child);
+
+    parent->childrenChanged(false, child->previousSibling(), child->nextSibling(), 1);
+
+    ChildNodeInsertionNotifier(parent).notify(child);
+
+    // FIXME: Attachment should be the first operation in this function, but some code
+    // (for example, HTMLFormControlElement's autofocus support) requires this ordering.
+    if (parent->attached() && !child->attached() && child->parentNode() == parent) {
+        if (attachBehavior == AttachLazily)
+            child->lazyAttach();
+        else
+            child->attach();
+    }
+
+    dispatchChildInsertionEvents(child);
+}
+
+#ifndef NDEBUG
+bool childAttachedAllowedWhenAttachingChildren(ContainerNode* node)
+{
+    if (node->isShadowRoot())
+        return true;
+
+    if (node->isInsertionPoint())
+        return true;
+
+    if (node->isElementNode() && toElement(node)->shadow())
+        return true;
+
+    return false;
+}
+#endif
+
+} // namespace WebCore
diff --git a/Source/core/dom/ContainerNode.h b/Source/core/dom/ContainerNode.h
new file mode 100644
index 0000000..e96dc0f
--- /dev/null
+++ b/Source/core/dom/ContainerNode.h
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ContainerNode_h
+#define ContainerNode_h
+
+#include "core/dom/ExceptionCodePlaceholder.h"
+#include "core/dom/Node.h"
+
+#include <wtf/OwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class FloatPoint;
+    
+typedef void (*NodeCallback)(Node*, unsigned);
+
+namespace Private { 
+    template<class GenericNode, class GenericNodeContainer>
+    void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer*);
+};
+
+class NoEventDispatchAssertion {
+public:
+    NoEventDispatchAssertion()
+    {
+#ifndef NDEBUG
+        if (!isMainThread())
+            return;
+        s_count++;
+#endif
+    }
+
+    ~NoEventDispatchAssertion()
+    {
+#ifndef NDEBUG
+        if (!isMainThread())
+            return;
+        ASSERT(s_count);
+        s_count--;
+#endif
+    }
+
+#ifndef NDEBUG
+    static bool isEventDispatchForbidden()
+    {
+        if (!isMainThread())
+            return false;
+        return s_count;
+    }
+#endif
+
+private:
+#ifndef NDEBUG
+    static unsigned s_count;
+#endif
+};
+
+class ContainerNode : public Node {
+    friend class PostAttachCallbackDisabler;
+public:
+    virtual ~ContainerNode();
+
+    Node* firstChild() const { return m_firstChild; }
+    Node* lastChild() const { return m_lastChild; }
+    bool hasChildNodes() const { return m_firstChild; }
+
+    unsigned childNodeCount() const;
+    Node* childNode(unsigned index) const;
+
+    bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& = ASSERT_NO_EXCEPTION, AttachBehavior = AttachNow);
+    bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& = ASSERT_NO_EXCEPTION, AttachBehavior = AttachNow);
+    bool removeChild(Node* child, ExceptionCode& = ASSERT_NO_EXCEPTION);
+    bool appendChild(PassRefPtr<Node> newChild, ExceptionCode& = ASSERT_NO_EXCEPTION, AttachBehavior = AttachNow);
+
+    // These methods are only used during parsing.
+    // They don't send DOM mutation events or handle reparenting.
+    // However, arbitrary code may be run by beforeload handlers.
+    void parserAppendChild(PassRefPtr<Node>);
+    void parserRemoveChild(Node*);
+    void parserInsertBefore(PassRefPtr<Node> newChild, Node* refChild);
+
+    void removeChildren();
+    void takeAllChildrenFrom(ContainerNode*);
+
+    void cloneChildNodes(ContainerNode* clone);
+
+    virtual void attach() OVERRIDE;
+    virtual void detach() OVERRIDE;
+    virtual void setFocus(bool) OVERRIDE;
+    virtual void setActive(bool active = true, bool pause = false) OVERRIDE;
+    virtual void setHovered(bool = true) OVERRIDE;
+    virtual void scheduleSetNeedsStyleRecalc(StyleChangeType = FullStyleChange) OVERRIDE FINAL;
+
+    // -----------------------------------------------------------------------------
+    // Notification of document structure changes (see core/dom/Node.h for more notification methods)
+
+    // Notifies the node that it's list of children have changed (either by adding or removing child nodes), or a child
+    // node that is of the type CDATA_SECTION_NODE, TEXT_NODE or COMMENT_NODE has changed its value.
+    virtual void childrenChanged(bool createdByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
+
+    void attachChildren();
+    void attachChildrenLazily();
+    void detachChildren();
+    void detachChildrenIfNeeded();
+
+    void disconnectDescendantFrames();
+
+    virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const { return true; }
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+protected:
+    ContainerNode(Document*, ConstructionType = CreateContainer);
+
+    static void queuePostAttachCallback(NodeCallback, Node*, unsigned = 0);
+    static bool postAttachCallbacksAreSuspended();
+
+    template<class GenericNode, class GenericNodeContainer>
+    friend void appendChildToContainer(GenericNode* child, GenericNodeContainer*);
+
+    template<class GenericNode, class GenericNodeContainer>
+    friend void Private::addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer*);
+
+    void removeDetachedChildren();
+    void setFirstChild(Node* child) { m_firstChild = child; }
+    void setLastChild(Node* child) { m_lastChild = child; }
+
+private:
+    void removeBetween(Node* previousChild, Node* nextChild, Node* oldChild);
+    void insertBeforeCommon(Node* nextChild, Node* oldChild);
+
+    static void dispatchPostAttachCallbacks();
+    void suspendPostAttachCallbacks();
+    void resumePostAttachCallbacks();
+
+    Node* m_firstChild;
+    Node* m_lastChild;
+};
+
+#ifndef NDEBUG
+bool childAttachedAllowedWhenAttachingChildren(ContainerNode*);
+#endif
+
+inline ContainerNode* toContainerNode(Node* node)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isContainerNode());
+    return static_cast<ContainerNode*>(node);
+}
+
+inline const ContainerNode* toContainerNode(const Node* node)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isContainerNode());
+    return static_cast<const ContainerNode*>(node);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toContainerNode(const ContainerNode*);
+
+inline ContainerNode::ContainerNode(Document* document, ConstructionType type)
+    : Node(document, type)
+    , m_firstChild(0)
+    , m_lastChild(0)
+{
+}
+
+inline void ContainerNode::attachChildren()
+{
+    for (Node* child = firstChild(); child; child = child->nextSibling()) {
+        ASSERT(!child->attached() || childAttachedAllowedWhenAttachingChildren(this));
+        if (!child->attached())
+            child->attach();
+    }
+}
+
+inline void ContainerNode::attachChildrenLazily()
+{
+    for (Node* child = firstChild(); child; child = child->nextSibling())
+        if (!child->attached())
+            child->lazyAttach();
+}
+
+inline void ContainerNode::detachChildrenIfNeeded()
+{
+    for (Node* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->attached())
+            child->detach();
+    }
+}
+
+inline void ContainerNode::detachChildren()
+{
+    for (Node* child = firstChild(); child; child = child->nextSibling())
+        child->detach();
+}
+
+inline unsigned Node::childNodeCount() const
+{
+    if (!isContainerNode())
+        return 0;
+    return toContainerNode(this)->childNodeCount();
+}
+
+inline Node* Node::childNode(unsigned index) const
+{
+    if (!isContainerNode())
+        return 0;
+    return toContainerNode(this)->childNode(index);
+}
+
+inline Node* Node::firstChild() const
+{
+    if (!isContainerNode())
+        return 0;
+    return toContainerNode(this)->firstChild();
+}
+
+inline Node* Node::lastChild() const
+{
+    if (!isContainerNode())
+        return 0;
+    return toContainerNode(this)->lastChild();
+}
+
+inline Node* Node::highestAncestor() const
+{
+    Node* node = const_cast<Node*>(this);
+    Node* highest = node;
+    for (; node; node = node->parentNode())
+        highest = node;
+    return highest;
+}
+
+inline bool Node::needsShadowTreeWalker() const
+{
+    if (getFlag(NeedsShadowTreeWalkerFlag))
+        return true;
+    ContainerNode* parent = parentOrShadowHostNode();
+    return parent && parent->getFlag(NeedsShadowTreeWalkerFlag);
+}
+
+// This constant controls how much buffer is initially allocated
+// for a Node Vector that is used to store child Nodes of a given Node.
+// FIXME: Optimize the value.
+const int initialNodeVectorSize = 11;
+typedef Vector<RefPtr<Node>, initialNodeVectorSize> NodeVector;
+
+inline void getChildNodes(Node* node, NodeVector& nodes)
+{
+    ASSERT(!nodes.size());
+    for (Node* child = node->firstChild(); child; child = child->nextSibling())
+        nodes.append(child);
+}
+
+class ChildNodesLazySnapshot {
+    WTF_MAKE_NONCOPYABLE(ChildNodesLazySnapshot);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit ChildNodesLazySnapshot(Node* parentNode)
+        : m_currentNode(parentNode->firstChild())
+        , m_currentIndex(0)
+    {
+        m_nextSnapshot = latestSnapshot;
+        latestSnapshot = this;
+    }
+
+    ~ChildNodesLazySnapshot()
+    {
+        latestSnapshot = m_nextSnapshot;
+    }
+
+    // Returns 0 if there is no next Node.
+    PassRefPtr<Node> nextNode()
+    {
+        if (LIKELY(!hasSnapshot())) {
+            RefPtr<Node> node = m_currentNode;
+            if (node)
+                m_currentNode = node->nextSibling();
+            return node.release();
+        }
+        Vector<RefPtr<Node> >& nodeVector = *m_childNodes;
+        if (m_currentIndex >= nodeVector.size())
+            return 0;
+        return nodeVector[m_currentIndex++];
+    }
+
+    void takeSnapshot()
+    {
+        if (hasSnapshot())
+            return;
+        m_childNodes = adoptPtr(new Vector<RefPtr<Node> >());
+        Node* node = m_currentNode.get();
+        while (node) {
+            m_childNodes->append(node);
+            node = node->nextSibling();
+        }
+    }
+
+    ChildNodesLazySnapshot* nextSnapshot() { return m_nextSnapshot; }
+    bool hasSnapshot() { return !!m_childNodes.get(); }
+
+    static void takeChildNodesLazySnapshot()
+    {
+        ChildNodesLazySnapshot* snapshot = latestSnapshot;
+        while (snapshot && !snapshot->hasSnapshot()) {
+            snapshot->takeSnapshot();
+            snapshot = snapshot->nextSnapshot();
+        }
+    }
+
+private:
+    static ChildNodesLazySnapshot* latestSnapshot;
+
+    RefPtr<Node> m_currentNode;
+    unsigned m_currentIndex;
+    OwnPtr<Vector<RefPtr<Node> > > m_childNodes; // Lazily instantiated.
+    ChildNodesLazySnapshot* m_nextSnapshot;
+};
+
+class PostAttachCallbackDisabler {
+public:
+    PostAttachCallbackDisabler(ContainerNode* node)
+        : m_node(node)
+    {
+        ASSERT(m_node);
+        m_node->suspendPostAttachCallbacks();
+    }
+
+    ~PostAttachCallbackDisabler()
+    {
+        m_node->resumePostAttachCallbacks();
+    }
+
+private:
+    ContainerNode* m_node;
+};
+
+} // namespace WebCore
+
+#endif // ContainerNode_h
diff --git a/Source/core/dom/ContainerNodeAlgorithms.cpp b/Source/core/dom/ContainerNodeAlgorithms.cpp
new file mode 100644
index 0000000..5a3a513
--- /dev/null
+++ b/Source/core/dom/ContainerNodeAlgorithms.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/ContainerNodeAlgorithms.h"
+
+#include "core/dom/Element.h"
+#include "core/dom/ElementShadow.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+
+namespace WebCore {
+
+void ChildNodeInsertionNotifier::notifyDescendantInsertedIntoDocument(ContainerNode* node)
+{
+    ChildNodesLazySnapshot snapshot(node);
+    while (RefPtr<Node> child = snapshot.nextNode()) {
+        // If we have been removed from the document during this loop, then
+        // we don't want to tell the rest of our children that they've been
+        // inserted into the document because they haven't.
+        if (node->inDocument() && child->parentNode() == node)
+            notifyNodeInsertedIntoDocument(child.get());
+    }
+
+    if (!node->isElementNode())
+        return;
+
+    if (ElementShadow* shadow = toElement(node)->shadow()) {
+        ShadowRootVector roots(shadow);
+        for (size_t i = 0; i < roots.size(); ++i) {
+            if (node->inDocument() && roots[i]->host() == node)
+                notifyNodeInsertedIntoDocument(roots[i].get());
+        }
+    }
+}
+
+void ChildNodeInsertionNotifier::notifyDescendantInsertedIntoTree(ContainerNode* node)
+{
+    for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
+        if (child->isContainerNode())
+            notifyNodeInsertedIntoTree(toContainerNode(child));
+    }
+
+    for (ShadowRoot* root = node->youngestShadowRoot(); root; root = root->olderShadowRoot())
+        notifyNodeInsertedIntoTree(root);
+}
+
+void ChildNodeRemovalNotifier::notifyDescendantRemovedFromDocument(ContainerNode* node)
+{
+    ChildNodesLazySnapshot snapshot(node);
+    while (RefPtr<Node> child = snapshot.nextNode()) {
+        // If we have been added to the document during this loop, then we
+        // don't want to tell the rest of our children that they've been
+        // removed from the document because they haven't.
+        if (!node->inDocument() && child->parentNode() == node)
+            notifyNodeRemovedFromDocument(child.get());
+    }
+
+    if (!node->isElementNode())
+        return;
+
+    if (node->document()->cssTarget() == node)
+        node->document()->setCSSTarget(0);
+
+    if (ElementShadow* shadow = toElement(node)->shadow()) {
+        ShadowRootVector roots(shadow);
+        for (size_t i = 0; i < roots.size(); ++i) {
+            if (!node->inDocument() && roots[i]->host() == node)
+                notifyNodeRemovedFromDocument(roots[i].get());
+        }
+    }
+}
+
+void ChildNodeRemovalNotifier::notifyDescendantRemovedFromTree(ContainerNode* node)
+{
+    for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
+        if (child->isContainerNode())
+            notifyNodeRemovedFromTree(toContainerNode(child));
+    }
+
+    if (!node->isElementNode())
+        return;
+
+    if (ElementShadow* shadow = toElement(node)->shadow()) {
+        ShadowRootVector roots(shadow);
+        for (size_t i = 0; i < roots.size(); ++i)
+            notifyNodeRemovedFromTree(roots[i].get());
+    }
+}
+
+void ChildFrameDisconnector::collectFrameOwners(ElementShadow* shadow)
+{
+    for (ShadowRoot* root = shadow->youngestShadowRoot(); root; root = root->olderShadowRoot())
+        collectFrameOwners(root);
+}
+
+#ifndef NDEBUG
+unsigned assertConnectedSubrameCountIsConsistent(Node* node)
+{
+    unsigned count = 0;
+
+    if (node->isElementNode()) {
+        if (node->isFrameOwnerElement() && toFrameOwnerElement(node)->contentFrame())
+            count++;
+
+        if (ElementShadow* shadow = toElement(node)->shadow()) {
+            for (ShadowRoot* root = shadow->youngestShadowRoot(); root; root = root->olderShadowRoot())
+                count += assertConnectedSubrameCountIsConsistent(root);
+        }
+    }
+
+    for (Node* child = node->firstChild(); child; child = child->nextSibling())
+        count += assertConnectedSubrameCountIsConsistent(child);
+
+    // If we undercount there's possibly a security bug since we'd leave frames
+    // in subtrees outside the document.
+    ASSERT(node->connectedSubframeCount() >= count);
+
+    // If we overcount it's safe, but not optimal because it means we'll traverse
+    // through the document in ChildFrameDisconnector looking for frames that have
+    // already been disconnected.
+    ASSERT(node->connectedSubframeCount() == count);
+
+    return count;
+}
+#endif
+
+}
diff --git a/Source/core/dom/ContainerNodeAlgorithms.h b/Source/core/dom/ContainerNodeAlgorithms.h
new file mode 100644
index 0000000..5e09a6b
--- /dev/null
+++ b/Source/core/dom/ContainerNodeAlgorithms.h
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *           (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ContainerNodeAlgorithms_h
+#define ContainerNodeAlgorithms_h
+
+#include "core/dom/Document.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/page/Frame.h"
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+class ChildNodeInsertionNotifier {
+public:
+    explicit ChildNodeInsertionNotifier(ContainerNode* insertionPoint)
+        : m_insertionPoint(insertionPoint)
+    {
+    }
+
+    void notify(Node*);
+
+private:
+    void notifyDescendantInsertedIntoDocument(ContainerNode*);
+    void notifyDescendantInsertedIntoTree(ContainerNode*);
+    void notifyNodeInsertedIntoDocument(Node*);
+    void notifyNodeInsertedIntoTree(ContainerNode*);
+
+    ContainerNode* m_insertionPoint;
+    Vector< RefPtr<Node> > m_postInsertionNotificationTargets;
+};
+
+class ChildNodeRemovalNotifier {
+public:
+    explicit ChildNodeRemovalNotifier(ContainerNode* insertionPoint)
+        : m_insertionPoint(insertionPoint)
+    {
+    }
+
+    void notify(Node*);
+
+private:
+    void notifyDescendantRemovedFromDocument(ContainerNode*);
+    void notifyDescendantRemovedFromTree(ContainerNode*);
+    void notifyNodeRemovedFromDocument(Node*);
+    void notifyNodeRemovedFromTree(ContainerNode*);
+
+    ContainerNode* m_insertionPoint;
+};
+
+namespace Private {
+
+    template<class GenericNode, class GenericNodeContainer>
+    void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer*);
+
+}
+
+// Helper functions for TreeShared-derived classes, which have a 'Node' style interface
+// This applies to 'ContainerNode' and 'SVGElementInstance'
+template<class GenericNode, class GenericNodeContainer>
+inline void removeDetachedChildrenInContainer(GenericNodeContainer* container)
+{
+    // List of nodes to be deleted.
+    GenericNode* head = 0;
+    GenericNode* tail = 0;
+
+    Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContainer>(head, tail, container);
+
+    GenericNode* n;
+    GenericNode* next;
+    while ((n = head) != 0) {
+        ASSERT(n->m_deletionHasBegun);
+
+        next = n->nextSibling();
+        n->setNextSibling(0);
+
+        head = next;
+        if (next == 0)
+            tail = 0;
+
+        if (n->hasChildNodes())
+            Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContainer>(head, tail, static_cast<GenericNodeContainer*>(n));
+
+        delete n;
+    }
+}
+
+template<class GenericNode, class GenericNodeContainer>
+inline void appendChildToContainer(GenericNode* child, GenericNodeContainer* container)
+{
+    child->setParentOrShadowHostNode(container);
+
+    GenericNode* lastChild = container->lastChild();
+    if (lastChild) {
+        child->setPreviousSibling(lastChild);
+        lastChild->setNextSibling(child);
+    } else
+        container->setFirstChild(child);
+
+    container->setLastChild(child);
+}
+
+// Helper methods for removeDetachedChildrenInContainer, hidden from WebCore namespace
+namespace Private {
+
+    template<class GenericNode, class GenericNodeContainer, bool dispatchRemovalNotification>
+    struct NodeRemovalDispatcher {
+        static void dispatch(GenericNode*, GenericNodeContainer*)
+        {
+            // no-op, by default
+        }
+    };
+
+    template<class GenericNode, class GenericNodeContainer>
+    struct NodeRemovalDispatcher<GenericNode, GenericNodeContainer, true> {
+        static void dispatch(GenericNode* node, GenericNodeContainer* container)
+        {
+            // Clean up any TreeScope to a removed tree.
+            if (Document* containerDocument = container->ownerDocument())
+                containerDocument->adoptIfNeeded(node);
+            if (node->inDocument())
+                ChildNodeRemovalNotifier(container).notify(node);
+        }
+    };
+
+    template<class GenericNode>
+    struct ShouldDispatchRemovalNotification {
+        static const bool value = false;
+    };
+
+    template<>
+    struct ShouldDispatchRemovalNotification<Node> {
+        static const bool value = true;
+    };
+
+    template<class GenericNode, class GenericNodeContainer>
+    void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer* container)
+    {
+        // We have to tell all children that their parent has died.
+        GenericNode* next = 0;
+        for (GenericNode* n = container->firstChild(); n != 0; n = next) {
+            ASSERT(!n->m_deletionHasBegun);
+
+            next = n->nextSibling();
+            n->setNextSibling(0);
+            n->setParentOrShadowHostNode(0);
+            container->setFirstChild(next);
+            if (next)
+                next->setPreviousSibling(0);
+
+            if (!n->refCount()) {
+#ifndef NDEBUG
+                n->m_deletionHasBegun = true;
+#endif
+                // Add the node to the list of nodes to be deleted.
+                // Reuse the nextSibling pointer for this purpose.
+                if (tail)
+                    tail->setNextSibling(n);
+                else
+                    head = n;
+
+                tail = n;
+            } else {
+                RefPtr<GenericNode> protect(n); // removedFromDocument may remove remove all references to this node.
+                NodeRemovalDispatcher<GenericNode, GenericNodeContainer, ShouldDispatchRemovalNotification<GenericNode>::value>::dispatch(n, container);
+            }
+        }
+
+        container->setLastChild(0);
+    }
+
+} // namespace Private
+
+inline void ChildNodeInsertionNotifier::notifyNodeInsertedIntoDocument(Node* node)
+{
+    ASSERT(m_insertionPoint->inDocument());
+    RefPtr<Node> protect(node);
+    if (Node::InsertionShouldCallDidNotifySubtreeInsertions == node->insertedInto(m_insertionPoint))
+        m_postInsertionNotificationTargets.append(node);
+    if (node->isContainerNode())
+        notifyDescendantInsertedIntoDocument(toContainerNode(node));
+}
+
+inline void ChildNodeInsertionNotifier::notifyNodeInsertedIntoTree(ContainerNode* node)
+{
+    NoEventDispatchAssertion assertNoEventDispatch;
+    ASSERT(!m_insertionPoint->inDocument());
+
+    if (Node::InsertionShouldCallDidNotifySubtreeInsertions == node->insertedInto(m_insertionPoint))
+        m_postInsertionNotificationTargets.append(node);
+    notifyDescendantInsertedIntoTree(node);
+}
+
+inline void ChildNodeInsertionNotifier::notify(Node* node)
+{
+    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
+
+    InspectorInstrumentation::didInsertDOMNode(node->document(), node);
+
+    RefPtr<Document> protectDocument(node->document());
+    RefPtr<Node> protectNode(node);
+
+    if (m_insertionPoint->inDocument())
+        notifyNodeInsertedIntoDocument(node);
+    else if (node->isContainerNode())
+        notifyNodeInsertedIntoTree(toContainerNode(node));
+
+    for (size_t i = 0; i < m_postInsertionNotificationTargets.size(); ++i)
+        m_postInsertionNotificationTargets[i]->didNotifySubtreeInsertions(m_insertionPoint);
+}
+
+
+inline void ChildNodeRemovalNotifier::notifyNodeRemovedFromDocument(Node* node)
+{
+    ASSERT(m_insertionPoint->inDocument());
+    node->removedFrom(m_insertionPoint);
+
+    if (node->isContainerNode())
+        notifyDescendantRemovedFromDocument(toContainerNode(node));
+}
+
+inline void ChildNodeRemovalNotifier::notifyNodeRemovedFromTree(ContainerNode* node)
+{
+    NoEventDispatchAssertion assertNoEventDispatch;
+    ASSERT(!m_insertionPoint->inDocument());
+
+    node->removedFrom(m_insertionPoint);
+    notifyDescendantRemovedFromTree(node);
+}
+
+inline void ChildNodeRemovalNotifier::notify(Node* node)
+{
+    if (node->inDocument()) {
+        notifyNodeRemovedFromDocument(node);
+        node->document()->notifyRemovePendingSheetIfNeeded();
+    } else if (node->isContainerNode())
+        notifyNodeRemovedFromTree(toContainerNode(node));
+}
+
+class ChildFrameDisconnector {
+public:
+    enum DisconnectPolicy {
+        RootAndDescendants,
+        DescendantsOnly
+    };
+
+    explicit ChildFrameDisconnector(Node* root)
+        : m_root(root)
+    {
+    }
+
+    void disconnect(DisconnectPolicy = RootAndDescendants);
+
+private:
+    void collectFrameOwners(Node* root);
+    void collectFrameOwners(ElementShadow*);
+    void disconnectCollectedFrameOwners();
+
+    Vector<RefPtr<HTMLFrameOwnerElement>, 10> m_frameOwners;
+    Node* m_root;
+};
+
+#ifndef NDEBUG
+unsigned assertConnectedSubrameCountIsConsistent(Node*);
+#endif
+
+inline void ChildFrameDisconnector::collectFrameOwners(Node* root)
+{
+    if (!root->connectedSubframeCount())
+        return;
+
+    if (root->isHTMLElement() && root->isFrameOwnerElement())
+        m_frameOwners.append(toFrameOwnerElement(root));
+
+    for (Node* child = root->firstChild(); child; child = child->nextSibling())
+        collectFrameOwners(child);
+
+    ElementShadow* shadow = root->isElementNode() ? toElement(root)->shadow() : 0;
+    if (shadow)
+        collectFrameOwners(shadow);
+}
+
+inline void ChildFrameDisconnector::disconnectCollectedFrameOwners()
+{
+    // Must disable frame loading in the subtree so an unload handler cannot
+    // insert more frames and create loaded frames in detached subtrees.
+    SubframeLoadingDisabler disabler(m_root);
+
+    for (unsigned i = 0; i < m_frameOwners.size(); ++i) {
+        HTMLFrameOwnerElement* owner = m_frameOwners[i].get();
+        // Don't need to traverse up the tree for the first owner since no
+        // script could have moved it.
+        if (!i || m_root->containsIncludingShadowDOM(owner))
+            owner->disconnectContentFrame();
+    }
+}
+
+inline void ChildFrameDisconnector::disconnect(DisconnectPolicy policy)
+{
+#ifndef NDEBUG
+    assertConnectedSubrameCountIsConsistent(m_root);
+#endif
+
+    if (!m_root->connectedSubframeCount())
+        return;
+
+    if (policy == RootAndDescendants)
+        collectFrameOwners(m_root);
+    else {
+        for (Node* child = m_root->firstChild(); child; child = child->nextSibling())
+            collectFrameOwners(child);
+    }
+
+    disconnectCollectedFrameOwners();
+}
+
+} // namespace WebCore
+
+#endif // ContainerNodeAlgorithms_h
diff --git a/Source/core/dom/ContextDestructionObserver.cpp b/Source/core/dom/ContextDestructionObserver.cpp
new file mode 100644
index 0000000..eec9bda
--- /dev/null
+++ b/Source/core/dom/ContextDestructionObserver.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "core/dom/ContextDestructionObserver.h"
+
+#include "core/dom/ScriptExecutionContext.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+
+namespace WebCore {
+
+ContextDestructionObserver::ContextDestructionObserver(ScriptExecutionContext* scriptExecutionContext)
+    : m_scriptExecutionContext(0)
+{
+    observeContext(scriptExecutionContext);
+}
+
+ContextDestructionObserver::~ContextDestructionObserver()
+{
+    observeContext(0);
+}
+
+void ContextDestructionObserver::observeContext(ScriptExecutionContext* scriptExecutionContext)
+{
+    if (m_scriptExecutionContext) {
+        ASSERT(m_scriptExecutionContext->isContextThread());
+        m_scriptExecutionContext->willDestroyDestructionObserver(this);
+    }
+
+    m_scriptExecutionContext = scriptExecutionContext;
+
+    if (m_scriptExecutionContext) {
+        ASSERT(m_scriptExecutionContext->isContextThread());
+        m_scriptExecutionContext->didCreateDestructionObserver(this);
+    }
+}
+
+void ContextDestructionObserver::contextDestroyed()
+{
+    m_scriptExecutionContext = 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/ContextDestructionObserver.h b/Source/core/dom/ContextDestructionObserver.h
new file mode 100644
index 0000000..ca956ab
--- /dev/null
+++ b/Source/core/dom/ContextDestructionObserver.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef ContextDestructionObserver_h
+#define ContextDestructionObserver_h
+
+namespace WebCore {
+
+class ScriptExecutionContext;
+
+class ContextDestructionObserver {
+public:
+    explicit ContextDestructionObserver(ScriptExecutionContext*);
+    virtual void contextDestroyed();
+
+    ScriptExecutionContext* scriptExecutionContext() const { return m_scriptExecutionContext; }
+
+protected:
+    virtual ~ContextDestructionObserver();
+    void observeContext(ScriptExecutionContext*);
+
+    ScriptExecutionContext* m_scriptExecutionContext;
+};
+
+} // namespace WebCore
+
+#endif // ContextDestructionObserver_h
diff --git a/Source/core/dom/ContextFeatures.cpp b/Source/core/dom/ContextFeatures.cpp
new file mode 100644
index 0000000..ec125c9
--- /dev/null
+++ b/Source/core/dom/ContextFeatures.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2012 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 "core/dom/ContextFeatures.h"
+
+#include "core/dom/Document.h"
+#include "core/page/Page.h"
+#include "RuntimeEnabledFeatures.h"
+
+namespace WebCore {
+
+ContextFeaturesClient* ContextFeaturesClient::empty()
+{
+    DEFINE_STATIC_LOCAL(ContextFeaturesClient, empty, ());
+    return &empty;
+}
+
+const char* ContextFeatures::supplementName()
+{
+    return "ContextFeatures";
+}
+
+ContextFeatures* ContextFeatures::defaultSwitch()
+{
+    DEFINE_STATIC_LOCAL(RefPtr<ContextFeatures>, instance, (ContextFeatures::create(ContextFeaturesClient::empty())));
+    return instance.get();
+}
+
+bool ContextFeatures::dialogElementEnabled(Document* document)
+{
+    if (!document)
+        return RuntimeEnabledFeatures::dialogElementEnabled();
+    return document->contextFeatures()->isEnabled(document, DialogElement, RuntimeEnabledFeatures::dialogElementEnabled());
+}
+
+bool ContextFeatures::styleScopedEnabled(Document* document)
+{
+    if (!document)
+        return RuntimeEnabledFeatures::styleScopedEnabled();
+    return document->contextFeatures()->isEnabled(document, StyleScoped, RuntimeEnabledFeatures::styleScopedEnabled());
+}
+
+bool ContextFeatures::pagePopupEnabled(Document* document)
+{
+#if ENABLE(PAGE_POPUP)
+    if (!document)
+        return false;
+    return document->contextFeatures()->isEnabled(document, PagePopup, false);
+#else
+    UNUSED_PARAM(document);
+    return false;
+#endif
+}
+
+bool ContextFeatures::htmlNotificationsEnabled(Document* document)
+{
+#if ENABLE(LEGACY_NOTIFICATIONS)
+    if (!document)
+        return false;
+    return document->contextFeatures()->isEnabled(document, HTMLNotifications, false);
+#else
+    UNUSED_PARAM(document);
+    return false;
+#endif
+}
+
+bool ContextFeatures::mutationEventsEnabled(Document* document)
+{
+    ASSERT(document);
+    if (!document)
+        return true;
+    return document->contextFeatures()->isEnabled(document, MutationEvents, true);
+}
+
+bool ContextFeatures::pushStateEnabled(Document* document)
+{
+    return document->contextFeatures()->isEnabled(document, PushState, true);
+}
+
+void provideContextFeaturesTo(Page* page, ContextFeaturesClient* client)
+{
+    RefCountedSupplement<Page, ContextFeatures>::provideTo(page, ContextFeatures::supplementName(), ContextFeatures::create(client));
+}
+
+void provideContextFeaturesToDocumentFrom(Document* document, Page* page)
+{
+    ContextFeatures* provided = static_cast<ContextFeatures*>(RefCountedSupplement<Page, ContextFeatures>::from(page, ContextFeatures::supplementName()));
+    if (!provided)
+        return;
+    document->setContextFeatures(provided);
+}
+
+}
diff --git a/Source/core/dom/ContextFeatures.h b/Source/core/dom/ContextFeatures.h
new file mode 100644
index 0000000..3f56c11
--- /dev/null
+++ b/Source/core/dom/ContextFeatures.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2012 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 ContextFeatures_h
+#define ContextFeatures_h
+
+#include "core/platform/RefCountedSupplement.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class ContextFeaturesClient;
+class Document;
+class Page;
+
+class ContextFeatures : public RefCountedSupplement<Page, ContextFeatures> {
+public:
+    enum FeatureType {
+        DialogElement = 0,
+        StyleScoped,
+        PagePopup,
+        HTMLNotifications,
+        MutationEvents,
+        PushState,
+        FeatureTypeSize // Should be the last entry.
+    };
+
+    static const char* supplementName();
+    static ContextFeatures* defaultSwitch();
+    static PassRefPtr<ContextFeatures> create(ContextFeaturesClient*);
+
+    static bool dialogElementEnabled(Document*);
+    static bool styleScopedEnabled(Document*);
+    static bool pagePopupEnabled(Document*);
+    static bool htmlNotificationsEnabled(Document*);
+    static bool mutationEventsEnabled(Document*);
+    static bool pushStateEnabled(Document*);
+
+    bool isEnabled(Document*, FeatureType, bool) const;
+    void urlDidChange(Document*);
+
+private:
+    explicit ContextFeatures(ContextFeaturesClient* client)
+        : m_client(client)
+    { }
+
+    virtual void hostDestroyed() OVERRIDE;
+
+    ContextFeaturesClient* m_client;
+};
+
+inline void ContextFeatures::hostDestroyed()
+{
+    m_client = 0;
+}
+
+
+class ContextFeaturesClient {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static ContextFeaturesClient* empty();
+
+    virtual ~ContextFeaturesClient() { }
+    virtual bool isEnabled(Document*, ContextFeatures::FeatureType, bool defaultValue) { return defaultValue; }
+    virtual void urlDidChange(Document*) { }
+};
+
+void provideContextFeaturesTo(Page*, ContextFeaturesClient*);
+void provideContextFeaturesToDocumentFrom(Document*, Page*);
+
+inline PassRefPtr<ContextFeatures> ContextFeatures::create(ContextFeaturesClient* client)
+{
+    return adoptRef(new ContextFeatures(client));
+}
+
+inline bool ContextFeatures::isEnabled(Document* document, FeatureType type, bool defaultValue) const
+{
+    if (!m_client)
+        return defaultValue;
+    return m_client->isEnabled(document, type, defaultValue);
+}
+
+inline void ContextFeatures::urlDidChange(Document* document)
+{
+    if (m_client)
+        return;
+    m_client->urlDidChange(document);
+}
+
+} // namespace WebCore
+
+#endif // ContextFeatures_h
diff --git a/Source/core/dom/CrossThreadTask.h b/Source/core/dom/CrossThreadTask.h
new file mode 100644
index 0000000..0ab979d
--- /dev/null
+++ b/Source/core/dom/CrossThreadTask.h
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2009-2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CrossThreadTask_h
+#define CrossThreadTask_h
+
+#include <memory>
+#include "core/dom/ScriptExecutionContext.h"
+#include "core/platform/CrossThreadCopier.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/TypeTraits.h>
+
+namespace WebCore {
+
+// Traits for the CrossThreadTask.
+template<typename T> struct CrossThreadTaskTraits {
+    typedef const T& ParamType;
+};
+
+template<typename T> struct CrossThreadTaskTraits<T*> {
+    typedef T* ParamType;
+};
+
+template<typename T> struct CrossThreadTaskTraits<PassRefPtr<T> > {
+    typedef PassRefPtr<T> ParamType;
+};
+
+template<typename T> struct CrossThreadTaskTraits<PassOwnPtr<T> > {
+    typedef PassOwnPtr<T> ParamType;
+};
+
+template<typename P1, typename MP1>
+class CrossThreadTask1 : public ScriptExecutionContext::Task {
+public:
+    typedef void (*Method)(ScriptExecutionContext*, MP1);
+    typedef CrossThreadTask1<P1, MP1> CrossThreadTask;
+    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+
+    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1)
+    {
+        return adoptPtr(new CrossThreadTask(method, parameter1));
+    }
+
+private:
+    CrossThreadTask1(Method method, Param1 parameter1)
+        : m_method(method)
+        , m_parameter1(parameter1)
+    {
+    }
+
+    virtual void performTask(ScriptExecutionContext* context)
+    {
+        (*m_method)(context, m_parameter1);
+    }
+
+private:
+    Method m_method;
+    P1 m_parameter1;
+};
+
+template<typename P1, typename MP1, typename P2, typename MP2>
+class CrossThreadTask2 : public ScriptExecutionContext::Task {
+public:
+    typedef void (*Method)(ScriptExecutionContext*, MP1, MP2);
+    typedef CrossThreadTask2<P1, MP1, P2, MP2> CrossThreadTask;
+    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+    typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
+
+    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1, Param2 parameter2)
+    {
+        return adoptPtr(new CrossThreadTask(method, parameter1, parameter2));
+    }
+
+private:
+    CrossThreadTask2(Method method, Param1 parameter1, Param2 parameter2)
+        : m_method(method)
+        , m_parameter1(parameter1)
+        , m_parameter2(parameter2)
+    {
+    }
+
+    virtual void performTask(ScriptExecutionContext* context)
+    {
+        (*m_method)(context, m_parameter1, m_parameter2);
+    }
+
+private:
+    Method m_method;
+    P1 m_parameter1;
+    P2 m_parameter2;
+};
+
+template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
+class CrossThreadTask3 : public ScriptExecutionContext::Task {
+public:
+    typedef void (*Method)(ScriptExecutionContext*, MP1, MP2, MP3);
+    typedef CrossThreadTask3<P1, MP1, P2, MP2, P3, MP3> CrossThreadTask;
+    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+    typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
+    typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
+
+    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3)
+    {
+        return adoptPtr(new CrossThreadTask(method, parameter1, parameter2, parameter3));
+    }
+
+private:
+    CrossThreadTask3(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3)
+        : m_method(method)
+        , m_parameter1(parameter1)
+        , m_parameter2(parameter2)
+        , m_parameter3(parameter3)
+    {
+    }
+
+    virtual void performTask(ScriptExecutionContext* context)
+    {
+        (*m_method)(context, m_parameter1, m_parameter2, m_parameter3);
+    }
+
+private:
+    Method m_method;
+    P1 m_parameter1;
+    P2 m_parameter2;
+    P3 m_parameter3;
+};
+
+template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4>
+class CrossThreadTask4 : public ScriptExecutionContext::Task {
+public:
+    typedef void (*Method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4);
+    typedef CrossThreadTask4<P1, MP1, P2, MP2, P3, MP3, P4, MP4> CrossThreadTask;
+    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+    typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
+    typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
+    typedef typename CrossThreadTaskTraits<P4>::ParamType Param4;
+
+    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4)
+    {
+        return adoptPtr(new CrossThreadTask(method, parameter1, parameter2, parameter3, parameter4));
+    }
+
+private:
+    CrossThreadTask4(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4)
+        : m_method(method)
+        , m_parameter1(parameter1)
+        , m_parameter2(parameter2)
+        , m_parameter3(parameter3)
+        , m_parameter4(parameter4)
+    {
+    }
+
+    virtual void performTask(ScriptExecutionContext* context)
+    {
+        (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4);
+    }
+
+private:
+    Method m_method;
+    P1 m_parameter1;
+    P2 m_parameter2;
+    P3 m_parameter3;
+    P4 m_parameter4;
+};
+
+template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5>
+class CrossThreadTask5 : public ScriptExecutionContext::Task {
+public:
+    typedef void (*Method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5);
+    typedef CrossThreadTask5<P1, MP1, P2, MP2, P3, MP3, P4, MP4, P5, MP5> CrossThreadTask;
+    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+    typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
+    typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
+    typedef typename CrossThreadTaskTraits<P4>::ParamType Param4;
+    typedef typename CrossThreadTaskTraits<P5>::ParamType Param5;
+
+    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5)
+    {
+        return adoptPtr(new CrossThreadTask(method, parameter1, parameter2, parameter3, parameter4, parameter5));
+    }
+
+private:
+    CrossThreadTask5(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5)
+        : m_method(method)
+        , m_parameter1(parameter1)
+        , m_parameter2(parameter2)
+        , m_parameter3(parameter3)
+        , m_parameter4(parameter4)
+        , m_parameter5(parameter5)
+    {
+    }
+
+    virtual void performTask(ScriptExecutionContext* context)
+    {
+        (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4, m_parameter5);
+    }
+
+private:
+    Method m_method;
+    P1 m_parameter1;
+    P2 m_parameter2;
+    P3 m_parameter3;
+    P4 m_parameter4;
+    P5 m_parameter5;
+};
+
+template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6>
+class CrossThreadTask6 : public ScriptExecutionContext::Task {
+public:
+    typedef void (*Method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6);
+    typedef CrossThreadTask6<P1, MP1, P2, MP2, P3, MP3, P4, MP4, P5, MP5, P6, MP6> CrossThreadTask;
+    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+    typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
+    typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
+    typedef typename CrossThreadTaskTraits<P4>::ParamType Param4;
+    typedef typename CrossThreadTaskTraits<P5>::ParamType Param5;
+    typedef typename CrossThreadTaskTraits<P6>::ParamType Param6;
+
+    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6)
+    {
+        return adoptPtr(new CrossThreadTask(method, parameter1, parameter2, parameter3, parameter4, parameter5, parameter6));
+    }
+
+private:
+    CrossThreadTask6(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6)
+        : m_method(method)
+        , m_parameter1(parameter1)
+        , m_parameter2(parameter2)
+        , m_parameter3(parameter3)
+        , m_parameter4(parameter4)
+        , m_parameter5(parameter5)
+        , m_parameter6(parameter6)
+    {
+    }
+
+    virtual void performTask(ScriptExecutionContext* context)
+    {
+        (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4, m_parameter5, m_parameter6);
+    }
+
+private:
+    Method m_method;
+    P1 m_parameter1;
+    P2 m_parameter2;
+    P3 m_parameter3;
+    P4 m_parameter4;
+    P5 m_parameter5;
+    P6 m_parameter6;
+};
+
+template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6, typename P7, typename MP7>
+class CrossThreadTask7 : public ScriptExecutionContext::Task {
+public:
+    typedef void (*Method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6, MP7);
+    typedef CrossThreadTask7<P1, MP1, P2, MP2, P3, MP3, P4, MP4, P5, MP5, P6, MP6, P7, MP7> CrossThreadTask;
+    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+    typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
+    typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
+    typedef typename CrossThreadTaskTraits<P4>::ParamType Param4;
+    typedef typename CrossThreadTaskTraits<P5>::ParamType Param5;
+    typedef typename CrossThreadTaskTraits<P6>::ParamType Param6;
+    typedef typename CrossThreadTaskTraits<P7>::ParamType Param7;
+
+    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6, Param7 parameter7)
+    {
+        return adoptPtr(new CrossThreadTask(method, parameter1, parameter2, parameter3, parameter4, parameter5, parameter6, parameter7));
+    }
+
+private:
+    CrossThreadTask7(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6, Param7 parameter7)
+        : m_method(method)
+        , m_parameter1(parameter1)
+        , m_parameter2(parameter2)
+        , m_parameter3(parameter3)
+        , m_parameter4(parameter4)
+        , m_parameter5(parameter5)
+        , m_parameter6(parameter6)
+        , m_parameter7(parameter7)
+    {
+    }
+
+    virtual void performTask(ScriptExecutionContext* context)
+    {
+        (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4, m_parameter5, m_parameter6, m_parameter7);
+    }
+
+private:
+    Method m_method;
+    P1 m_parameter1;
+    P2 m_parameter2;
+    P3 m_parameter3;
+    P4 m_parameter4;
+    P5 m_parameter5;
+    P6 m_parameter6;
+    P7 m_parameter7;
+};
+
+template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6, typename P7, typename MP7, typename P8, typename MP8>
+class CrossThreadTask8 : public ScriptExecutionContext::Task {
+public:
+    typedef void (*Method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6, MP7, MP8);
+    typedef CrossThreadTask8<P1, MP1, P2, MP2, P3, MP3, P4, MP4, P5, MP5, P6, MP6, P7, MP7, P8, MP8> CrossThreadTask;
+    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+    typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
+    typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
+    typedef typename CrossThreadTaskTraits<P4>::ParamType Param4;
+    typedef typename CrossThreadTaskTraits<P5>::ParamType Param5;
+    typedef typename CrossThreadTaskTraits<P6>::ParamType Param6;
+    typedef typename CrossThreadTaskTraits<P7>::ParamType Param7;
+    typedef typename CrossThreadTaskTraits<P8>::ParamType Param8;
+    
+    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6, Param7 parameter7, Param8 parameter8)
+    {
+        return adoptPtr(new CrossThreadTask(method, parameter1, parameter2, parameter3, parameter4, parameter5, parameter6, parameter7, parameter8));
+    }
+    
+private:
+    CrossThreadTask8(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6, Param7 parameter7, Param8 parameter8)
+    : m_method(method)
+    , m_parameter1(parameter1)
+    , m_parameter2(parameter2)
+    , m_parameter3(parameter3)
+    , m_parameter4(parameter4)
+    , m_parameter5(parameter5)
+    , m_parameter6(parameter6)
+    , m_parameter7(parameter7)
+    , m_parameter8(parameter8)
+    {
+    }
+    
+    virtual void performTask(ScriptExecutionContext* context)
+    {
+        (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4, m_parameter5, m_parameter6, m_parameter7, m_parameter8);
+    }
+    
+private:
+    Method m_method;
+    P1 m_parameter1;
+    P2 m_parameter2;
+    P3 m_parameter3;
+    P4 m_parameter4;
+    P5 m_parameter5;
+    P6 m_parameter6;
+    P7 m_parameter7;
+    P8 m_parameter8;
+};
+
+template<typename P1, typename MP1>
+PassOwnPtr<ScriptExecutionContext::Task> createCallbackTask(
+    void (*method)(ScriptExecutionContext*, MP1),
+    const P1& parameter1)
+{
+    return CrossThreadTask1<typename CrossThreadCopier<P1>::Type, MP1>::create(
+        method,
+        CrossThreadCopier<P1>::copy(parameter1));
+}
+
+template<typename P1, typename MP1, typename P2, typename MP2>
+PassOwnPtr<ScriptExecutionContext::Task> createCallbackTask(
+    void (*method)(ScriptExecutionContext*, MP1, MP2),
+    const P1& parameter1, const P2& parameter2)
+{
+    return CrossThreadTask2<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2>::create(
+        method,
+        CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2));
+}
+
+template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
+PassOwnPtr<ScriptExecutionContext::Task> createCallbackTask(
+    void (*method)(ScriptExecutionContext*, MP1, MP2, MP3),
+    const P1& parameter1, const P2& parameter2, const P3& parameter3)
+{
+    return CrossThreadTask3<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3>::create(
+        method,
+        CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
+        CrossThreadCopier<P3>::copy(parameter3));
+}
+
+template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4>
+PassOwnPtr<ScriptExecutionContext::Task> createCallbackTask(
+    void (*method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4),
+    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4)
+{
+    return CrossThreadTask4<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3,
+        typename CrossThreadCopier<P4>::Type, MP4>::create(
+            method,
+            CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
+            CrossThreadCopier<P3>::copy(parameter3), CrossThreadCopier<P4>::copy(parameter4));
+}
+
+template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5>
+PassOwnPtr<ScriptExecutionContext::Task> createCallbackTask(
+    void (*method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5),
+    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5)
+{
+    return CrossThreadTask5<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3,
+        typename CrossThreadCopier<P4>::Type, MP4, typename CrossThreadCopier<P5>::Type, MP5>::create(
+            method,
+            CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
+            CrossThreadCopier<P3>::copy(parameter3), CrossThreadCopier<P4>::copy(parameter4),
+            CrossThreadCopier<P5>::copy(parameter5));
+}
+
+template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6>
+PassOwnPtr<ScriptExecutionContext::Task> createCallbackTask(
+    void (*method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6),
+    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5, const P6& parameter6)
+{
+    return CrossThreadTask6<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3,
+        typename CrossThreadCopier<P4>::Type, MP4, typename CrossThreadCopier<P5>::Type, MP5, typename CrossThreadCopier<P6>::Type, MP6>::create(
+            method,
+            CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
+            CrossThreadCopier<P3>::copy(parameter3), CrossThreadCopier<P4>::copy(parameter4),
+            CrossThreadCopier<P5>::copy(parameter5), CrossThreadCopier<P6>::copy(parameter6));
+}
+
+template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6, typename P7, typename MP7>
+PassOwnPtr<ScriptExecutionContext::Task> createCallbackTask(
+    void (*method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6, MP7),
+    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5, const P6& parameter6, const P7& parameter7)
+{
+    return CrossThreadTask7<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3,
+        typename CrossThreadCopier<P4>::Type, MP4, typename CrossThreadCopier<P5>::Type, MP5, typename CrossThreadCopier<P6>::Type, MP6,
+        typename CrossThreadCopier<P7>::Type, MP7>::create(
+            method,
+            CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
+            CrossThreadCopier<P3>::copy(parameter3), CrossThreadCopier<P4>::copy(parameter4),
+            CrossThreadCopier<P5>::copy(parameter5), CrossThreadCopier<P6>::copy(parameter6),
+            CrossThreadCopier<P7>::copy(parameter7));
+}
+
+template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6, typename P7, typename MP7, typename P8, typename MP8>
+PassOwnPtr<ScriptExecutionContext::Task> createCallbackTask(
+                                                            void (*method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6, MP7, MP8),
+                                                            const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5, const P6& parameter6, const P7& parameter7, const P8& parameter8)
+{
+    return CrossThreadTask8<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3,
+    typename CrossThreadCopier<P4>::Type, MP4, typename CrossThreadCopier<P5>::Type, MP5, typename CrossThreadCopier<P6>::Type, MP6,
+    typename CrossThreadCopier<P7>::Type, MP7, typename CrossThreadCopier<P8>::Type, MP8>::create(
+                                                       method,
+                                                       CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
+                                                       CrossThreadCopier<P3>::copy(parameter3), CrossThreadCopier<P4>::copy(parameter4),
+                                                       CrossThreadCopier<P5>::copy(parameter5), CrossThreadCopier<P6>::copy(parameter6),
+                                                       CrossThreadCopier<P7>::copy(parameter7), CrossThreadCopier<P8>::copy(parameter8));
+}
+
+} // namespace WebCore
+
+#endif // CrossThreadTask_h
diff --git a/Source/core/dom/CustomElementConstructor.cpp b/Source/core/dom/CustomElementConstructor.cpp
new file mode 100644
index 0000000..f664ecf
--- /dev/null
+++ b/Source/core/dom/CustomElementConstructor.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "core/dom/CustomElementConstructor.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+
+namespace WebCore {
+
+PassRefPtr<CustomElementConstructor> CustomElementConstructor::create(Document* document, const QualifiedName& tag, const AtomicString& typeExtension) {
+    return adoptRef(new CustomElementConstructor(document, tag, typeExtension));
+}
+
+CustomElementConstructor::CustomElementConstructor(Document* document, const QualifiedName& tag, const AtomicString& typeExtension)
+    : ContextDestructionObserver(document)
+    , m_tag(tag)
+    , m_typeExtension(typeExtension)
+{
+}
+
+Document* CustomElementConstructor::document() const {
+    return toDocument(m_scriptExecutionContext);
+}
+
+PassRefPtr<Element> CustomElementConstructor::createElement(ExceptionCode& ec) {
+    if (!document())
+        return 0;
+    return document()->createElementNS(m_tag.namespaceURI(), m_tag.localName(), m_typeExtension, ec);
+}
+
+}
diff --git a/Source/core/dom/CustomElementConstructor.h b/Source/core/dom/CustomElementConstructor.h
new file mode 100644
index 0000000..5a006c0
--- /dev/null
+++ b/Source/core/dom/CustomElementConstructor.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CustomElementConstructor_h
+#define CustomElementConstructor_h
+
+#include "core/dom/ContextDestructionObserver.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/QualifiedName.h"
+#include <wtf/Forward.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class Document;
+class Element;
+
+class CustomElementConstructor: public RefCounted<CustomElementConstructor>, public ContextDestructionObserver
+{
+public:
+    static PassRefPtr<CustomElementConstructor> create(Document* document, const QualifiedName& tagName, const AtomicString& typeExtension);
+    virtual ~CustomElementConstructor() {}
+
+    PassRefPtr<Element> createElement(ExceptionCode&);
+
+private:
+    explicit CustomElementConstructor(Document* document, const QualifiedName& tag, const AtomicString& typeExtension);
+    Document* document() const;
+
+    QualifiedName m_tag;
+    AtomicString m_typeExtension;
+};
+
+}
+
+#endif // CustomElementConstructor_h
diff --git a/Source/core/dom/CustomElementConstructor.idl b/Source/core/dom/CustomElementConstructor.idl
new file mode 100644
index 0000000..0460874
--- /dev/null
+++ b/Source/core/dom/CustomElementConstructor.idl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012, 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. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+[
+    EnabledAtRuntime=customDOMElements,
+    WrapAsFunction,
+    CustomCall
+] interface CustomElementConstructor {
+};
diff --git a/Source/core/dom/CustomElementDefinition.cpp b/Source/core/dom/CustomElementDefinition.cpp
new file mode 100644
index 0000000..803023d
--- /dev/null
+++ b/Source/core/dom/CustomElementDefinition.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "core/dom/CustomElementDefinition.h"
+
+#include "bindings/v8/CustomElementHelpers.h"
+#include <wtf/Assertions.h>
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#endif
+
+namespace WebCore {
+
+PassRefPtr<CustomElementDefinition> CustomElementDefinition::create(ScriptState* state, const AtomicString& type, const AtomicString& name, const AtomicString& namespaceURI, const ScriptValue& prototype)
+{
+    ASSERT(CustomElementHelpers::isValidPrototypeParameter(prototype, state));
+    ASSERT(name == type || QualifiedName(nullAtom, name, namespaceURI) == *CustomElementHelpers::findLocalName(prototype));
+#if ENABLE(SVG)
+    ASSERT(namespaceURI == HTMLNames::xhtmlNamespaceURI || namespaceURI == SVGNames::svgNamespaceURI);
+#else
+    ASSERT(namespaceURI == HTMLNames::xhtmlNamespaceURI);
+#endif
+
+    RefPtr<CustomElementDefinition> created = adoptRef(new CustomElementDefinition(type, name, namespaceURI, prototype));
+    return created.release();
+}
+
+CustomElementDefinition::CustomElementDefinition(const AtomicString& type, const AtomicString& name, const AtomicString& namespaceURI, const ScriptValue& prototype)
+    : m_prototype(prototype)
+    , m_type(type)
+    , m_tag(QualifiedName(nullAtom, name, namespaceURI))
+{
+}
+
+}
diff --git a/Source/core/dom/CustomElementDefinition.h b/Source/core/dom/CustomElementDefinition.h
new file mode 100644
index 0000000..a947239
--- /dev/null
+++ b/Source/core/dom/CustomElementDefinition.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CustomElementDefinition_h
+#define CustomElementDefinition_h
+
+#include "bindings/v8/ScriptValue.h"
+#include "core/dom/QualifiedName.h"
+#include "wtf/Forward.h"
+#include "wtf/PassRefPtr.h"
+#include "wtf/RefCounted.h"
+
+namespace WebCore {
+
+class ScriptState;
+
+class CustomElementDefinition : public RefCounted<CustomElementDefinition> {
+public:
+    static PassRefPtr<CustomElementDefinition> create(ScriptState*, const AtomicString& type, const AtomicString& name, const AtomicString& namespaceURI, const ScriptValue& prototype);
+
+    virtual ~CustomElementDefinition() {}
+
+    enum CustomElementKind {
+        CustomTag,
+        TypeExtension
+    };
+
+    // This specifies whether the custom element is in the HTML or SVG
+    // namespace.
+    const AtomicString& namespaceURI() const { return m_tag.namespaceURI(); }
+
+    // This uniquely identifies the Custom Element. For custom tags, this
+    // is the tag name and the same as "name". For type extensions, this
+    // is the value of the "is" attribute.
+    const AtomicString& type() const { return m_type; }
+
+    // This is the tag name of the Custom Element.
+    const AtomicString& name() const { return m_tag.localName(); }
+
+    // This is a convenience property derived from "namespaceURI" and
+    // "name". Custom Elements of this kind will have this tag
+    // name. This does not have a prefix.
+    const QualifiedName& tagQName() const { return m_tag; }
+
+    CustomElementKind kind() const { return isTypeExtension() ? TypeExtension : CustomTag; }
+    bool isTypeExtension() const { return type() != name(); }
+
+    const ScriptValue& prototype() { return m_prototype; }
+
+private:
+    CustomElementDefinition(const AtomicString& type, const AtomicString& name, const AtomicString& namespaceURI, const ScriptValue& prototype);
+
+    ScriptValue m_prototype;
+
+    AtomicString m_type;
+    QualifiedName m_tag;
+};
+
+}
+
+#endif // CustomElementDefinition_h
diff --git a/Source/core/dom/CustomElementRegistry.cpp b/Source/core/dom/CustomElementRegistry.cpp
new file mode 100644
index 0000000..779526a
--- /dev/null
+++ b/Source/core/dom/CustomElementRegistry.cpp
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2012 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.
+ * 3. 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 "core/dom/CustomElementRegistry.h"
+
+#include "HTMLNames.h"
+#include "RuntimeEnabledFeatures.h"
+#include "bindings/v8/CustomElementHelpers.h"
+#include "bindings/v8/Dictionary.h"
+#include "bindings/v8/ScriptValue.h"
+#include "core/dom/CustomElementDefinition.h"
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/html/HTMLElement.h"
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#include "core/svg/SVGElement.h"
+#endif
+
+namespace WebCore {
+
+CustomElementInvocation::CustomElementInvocation(PassRefPtr<Element> element)
+    : m_element(element)
+{
+}
+
+CustomElementInvocation::~CustomElementInvocation()
+{
+}
+
+void setTypeExtension(Element* element, const AtomicString& typeExtension)
+{
+    ASSERT(element);
+    if (!typeExtension.isEmpty())
+        element->setAttribute(HTMLNames::isAttr, typeExtension);
+}
+
+CustomElementRegistry::CustomElementRegistry(Document* document)
+    : ContextDestructionObserver(document)
+{
+}
+
+CustomElementRegistry::~CustomElementRegistry()
+{
+    deactivate();
+}
+
+static inline bool nameIncludesHyphen(const AtomicString& name)
+{
+    size_t hyphenPosition = name.find('-');
+    return (hyphenPosition != notFound);
+}
+
+bool CustomElementRegistry::isValidName(const AtomicString& name)
+{
+    if (!nameIncludesHyphen(name))
+        return false;
+
+    DEFINE_STATIC_LOCAL(Vector<AtomicString>, reservedNames, ());
+    if (reservedNames.isEmpty()) {
+#if ENABLE(SVG)
+        reservedNames.append(SVGNames::color_profileTag.localName());
+        reservedNames.append(SVGNames::font_faceTag.localName());
+        reservedNames.append(SVGNames::font_face_srcTag.localName());
+        reservedNames.append(SVGNames::font_face_uriTag.localName());
+        reservedNames.append(SVGNames::font_face_formatTag.localName());
+        reservedNames.append(SVGNames::font_face_nameTag.localName());
+        reservedNames.append(SVGNames::missing_glyphTag.localName());
+#endif
+    }
+
+    if (notFound != reservedNames.find(name))
+        return false;
+
+    return Document::isValidName(name.string());
+}
+
+PassRefPtr<CustomElementConstructor> CustomElementRegistry::registerElement(ScriptState* state, const AtomicString& userSuppliedName, const Dictionary& options, ExceptionCode& ec)
+{
+    RefPtr<CustomElementRegistry> protect(this);
+
+    if (!CustomElementHelpers::isFeatureAllowed(state))
+        return 0;
+
+    AtomicString name = userSuppliedName.lower();
+    if (!isValidName(name)) {
+        ec = INVALID_CHARACTER_ERR;
+        return 0;
+    }
+
+    ScriptValue prototypeValue;
+    if (!options.get("prototype", prototypeValue)) {
+        // FIXME: Implement the default value handling.
+        // Currently default value of the "prototype" parameter, which
+        // is HTMLSpanElement.prototype, has an ambiguity about its
+        // behavior. The spec should be fixed before WebKit implements
+        // it. https://www.w3.org/Bugs/Public/show_bug.cgi?id=20801
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    AtomicString namespaceURI;
+    if (!CustomElementHelpers::isValidPrototypeParameter(prototypeValue, state, namespaceURI)) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    if (namespaceURI.isNull()) {
+        ec = NAMESPACE_ERR;
+        return 0;
+    }
+
+    AtomicString type = name;
+    if (m_definitions.contains(type)) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    const QualifiedName* prototypeTagName = CustomElementHelpers::findLocalName(prototypeValue);
+    if (prototypeTagName)
+        name = prototypeTagName->localName();
+
+    // A script execution could happen in isValidPrototypeParameter(), which kills the document.
+    if (!document()) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    RefPtr<CustomElementDefinition> definition = CustomElementDefinition::create(state, type, name, namespaceURI, prototypeValue);
+
+    RefPtr<CustomElementConstructor> constructor = CustomElementConstructor::create(document(), definition->tagQName(), definition->isTypeExtension() ? definition->type() : nullAtom);
+    if (!CustomElementHelpers::initializeConstructorWrapper(constructor.get(), prototypeValue, state)) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    m_definitions.add(definition->type(), definition);
+
+    // Upgrade elements that were waiting for this definition.
+    CustomElementUpgradeCandidateMap::ElementSet upgradeCandidates = m_candidates.takeUpgradeCandidatesFor(definition.get());
+    CustomElementHelpers::upgradeWrappers(document(), upgradeCandidates, definition->prototype());
+    for (CustomElementUpgradeCandidateMap::ElementSet::iterator it = upgradeCandidates.begin(); it != upgradeCandidates.end(); ++it) {
+        (*it)->setNeedsStyleRecalc(); // :unresolved has changed
+        activate(CustomElementInvocation(*it));
+    }
+
+    return constructor.release();
+}
+
+bool CustomElementRegistry::isUnresolved(Element* element) const
+{
+    return m_candidates.contains(element);
+}
+
+PassRefPtr<CustomElementDefinition> CustomElementRegistry::findFor(Element* element) const
+{
+    ASSERT(element->document()->registry() == this);
+
+    if (!element->isCustomElement())
+        return 0;
+
+    // When a custom tag and a type extension are provided as element
+    // names at the same time, the custom tag takes precedence.
+    if (isCustomTagName(element->localName())) {
+        if (RefPtr<CustomElementDefinition> definition = findAndCheckNamespace(element->localName(), element->namespaceURI()))
+            return definition->isTypeExtension() ? 0 : definition.release();
+    }
+
+    // FIXME: Casually consulting the "is" attribute is dangerous if
+    // it could have changed since element creation.
+    const AtomicString& isValue = element->getAttribute(HTMLNames::isAttr);
+    if (RefPtr<CustomElementDefinition> definition = findAndCheckNamespace(isValue, element->namespaceURI()))
+        return definition->isTypeExtension() && definition->name() == element->localName() ? definition.release() : 0;
+
+    return 0;
+}
+
+PassRefPtr<CustomElementDefinition> CustomElementRegistry::findAndCheckNamespace(const AtomicString& type, const AtomicString& namespaceURI) const
+{
+    if (type.isNull())
+        return 0;
+    DefinitionMap::const_iterator it = m_definitions.find(type);
+    if (it == m_definitions.end())
+        return 0;
+    if (it->value->namespaceURI() != namespaceURI)
+        return 0;
+    return it->value;
+}
+
+PassRefPtr<Element> CustomElementRegistry::createCustomTagElement(const QualifiedName& tagName)
+{
+    if (!document())
+        return 0;
+
+    ASSERT(isCustomTagName(tagName.localName()));
+
+    RefPtr<Element> element;
+
+    if (HTMLNames::xhtmlNamespaceURI == tagName.namespaceURI())
+        element = HTMLElement::create(tagName, document());
+#if ENABLE(SVG)
+    else if (SVGNames::svgNamespaceURI == tagName.namespaceURI())
+        element = SVGElement::create(tagName, document());
+#endif
+    else
+        return Element::create(tagName, document());
+
+    element->setIsCustomElement();
+
+    RefPtr<CustomElementDefinition> definition = findAndCheckNamespace(tagName.localName(), tagName.namespaceURI());
+    if (!definition || definition->isTypeExtension()) {
+        // If a definition for a type extension was available, this
+        // custom tag element will be unresolved in perpetuity.
+        didCreateUnresolvedElement(CustomElementDefinition::CustomTag, tagName.localName(), element.get());
+    } else {
+        didCreateCustomTagElement(element.get());
+    }
+
+    return element.release();
+}
+
+void CustomElementRegistry::didGiveTypeExtension(Element* element, const AtomicString& type)
+{
+    if (!element->isHTMLElement() && !element->isSVGElement())
+        return;
+    element->setIsCustomElement();
+    RefPtr<CustomElementDefinition> definition = findFor(element);
+    if (!definition || !definition->isTypeExtension()) {
+        // If a definition for a custom tag was available, this type
+        // extension element will be unresolved in perpetuity.
+        didCreateUnresolvedElement(CustomElementDefinition::TypeExtension, type, element);
+    } else {
+        activate(CustomElementInvocation(element));
+    }
+}
+
+void CustomElementRegistry::didCreateCustomTagElement(Element* element)
+{
+    activate(CustomElementInvocation(element));
+}
+
+void CustomElementRegistry::didCreateUnresolvedElement(CustomElementDefinition::CustomElementKind kind, const AtomicString& type, Element* element)
+{
+    m_candidates.add(kind, type, element);
+}
+
+void CustomElementRegistry::customElementWasDestroyed(Element* element)
+{
+    ASSERT(element->isCustomElement());
+    m_candidates.remove(element);
+}
+
+void CustomElementRegistry::activate(const CustomElementInvocation& invocation)
+{
+    bool wasInactive = m_invocations.isEmpty();
+    m_invocations.append(invocation);
+    if (wasInactive)
+        activeCustomElementRegistries().add(this);
+}
+
+void CustomElementRegistry::deactivate()
+{
+    ASSERT(m_invocations.isEmpty());
+    if (activeCustomElementRegistries().contains(this))
+        activeCustomElementRegistries().remove(this);
+}
+
+inline Document* CustomElementRegistry::document() const
+{
+    return toDocument(m_scriptExecutionContext);
+}
+
+void CustomElementRegistry::deliverLifecycleCallbacks()
+{
+    ASSERT(!m_invocations.isEmpty());
+
+    if (!m_invocations.isEmpty()) {
+        Vector<CustomElementInvocation> invocations;
+        m_invocations.swap(invocations);
+        CustomElementHelpers::invokeReadyCallbacksIfNeeded(m_scriptExecutionContext, invocations);
+    }
+
+    ASSERT(m_invocations.isEmpty());
+    deactivate();
+}
+
+void CustomElementRegistry::deliverAllLifecycleCallbacks()
+{
+    while (!activeCustomElementRegistries().isEmpty()) {
+        Vector<RefPtr<CustomElementRegistry> > registries;
+        copyToVector(activeCustomElementRegistries(), registries);
+        activeCustomElementRegistries().clear();
+        for (size_t i = 0; i < registries.size(); ++i)
+            registries[i]->deliverLifecycleCallbacks();
+    }
+}
+
+}
diff --git a/Source/core/dom/CustomElementRegistry.h b/Source/core/dom/CustomElementRegistry.h
new file mode 100644
index 0000000..9ae6c86
--- /dev/null
+++ b/Source/core/dom/CustomElementRegistry.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2012 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.
+ * 3. 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 CustomElementRegistry_h
+#define CustomElementRegistry_h
+
+#include "bindings/v8/ScriptState.h"
+#include "core/dom/ContextDestructionObserver.h"
+#include "core/dom/CustomElementConstructor.h"
+#include "core/dom/CustomElementUpgradeCandidateMap.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/QualifiedName.h"
+#include "wtf/HashSet.h"
+#include "wtf/ListHashSet.h"
+#include "wtf/PassRefPtr.h"
+#include "wtf/RefCounted.h"
+#include "wtf/RefPtr.h"
+#include "wtf/Vector.h"
+#include "wtf/text/AtomicString.h"
+#include "wtf/text/AtomicStringHash.h"
+
+namespace WebCore {
+
+class CustomElementDefinition;
+class Dictionary;
+class Document;
+class Element;
+
+class CustomElementInvocation {
+public:
+    explicit CustomElementInvocation(PassRefPtr<Element>);
+    ~CustomElementInvocation();
+
+    Element* element() const { return m_element.get(); }
+
+private:
+    RefPtr<Element> m_element;
+};
+
+void setTypeExtension(Element*, const AtomicString& typeExtension);
+
+class CustomElementRegistry : public RefCounted<CustomElementRegistry>, public ContextDestructionObserver {
+    WTF_MAKE_NONCOPYABLE(CustomElementRegistry); WTF_MAKE_FAST_ALLOCATED;
+public:
+    class CallbackDeliveryScope {
+    public:
+        CallbackDeliveryScope() { }
+        ~CallbackDeliveryScope() { CustomElementRegistry::deliverAllLifecycleCallbacksIfNeeded(); }
+    };
+
+    explicit CustomElementRegistry(Document*);
+    ~CustomElementRegistry();
+
+    PassRefPtr<CustomElementConstructor> registerElement(WebCore::ScriptState*, const AtomicString& name, const Dictionary& options, ExceptionCode&);
+
+    bool isUnresolved(Element*) const;
+    PassRefPtr<CustomElementDefinition> findFor(Element*) const;
+    PassRefPtr<CustomElementDefinition> findAndCheckNamespace(const AtomicString& type, const AtomicString& namespaceURI) const;
+
+    PassRefPtr<Element> createCustomTagElement(const QualifiedName& localName);
+
+    Document* document() const;
+
+    void didGiveTypeExtension(Element*, const AtomicString&);
+    void customElementWasDestroyed(Element*);
+
+    static bool isCustomTagName(const AtomicString& name) { return isValidName(name); }
+
+    static void deliverAllLifecycleCallbacks();
+    static void deliverAllLifecycleCallbacksIfNeeded();
+
+private:
+    typedef HashMap<AtomicString, RefPtr<CustomElementDefinition> > DefinitionMap;
+    typedef ListHashSet<CustomElementRegistry*> InstanceSet;
+
+    static bool isValidName(const AtomicString&);
+
+    static InstanceSet& activeCustomElementRegistries();
+    void activate(const CustomElementInvocation&);
+    void deactivate();
+    void deliverLifecycleCallbacks();
+
+    void didCreateCustomTagElement(Element*);
+    void didCreateUnresolvedElement(CustomElementDefinition::CustomElementKind, const AtomicString& type, Element*);
+
+    DefinitionMap m_definitions;
+    CustomElementUpgradeCandidateMap m_candidates;
+
+    Vector<CustomElementInvocation> m_invocations;
+};
+
+inline void CustomElementRegistry::deliverAllLifecycleCallbacksIfNeeded()
+{
+    if (!activeCustomElementRegistries().isEmpty())
+        deliverAllLifecycleCallbacks();
+    ASSERT(activeCustomElementRegistries().isEmpty());
+}
+
+inline CustomElementRegistry::InstanceSet& CustomElementRegistry::activeCustomElementRegistries()
+{
+    DEFINE_STATIC_LOCAL(InstanceSet, activeInstances, ());
+    return activeInstances;
+}
+
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/core/dom/CustomElementUpgradeCandidateMap.cpp b/Source/core/dom/CustomElementUpgradeCandidateMap.cpp
new file mode 100644
index 0000000..6b9c543
--- /dev/null
+++ b/Source/core/dom/CustomElementUpgradeCandidateMap.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "core/dom/CustomElementUpgradeCandidateMap.h"
+
+namespace WebCore {
+
+void CustomElementUpgradeCandidateMap::add(CustomElementDefinition::CustomElementKind kind, const AtomicString& type, Element* element)
+{
+    m_unresolvedElements.add(element, RequiredDefinition(kind, type));
+
+    UnresolvedDefinitionMap::iterator it = m_unresolvedDefinitions.find(type);
+    if (it == m_unresolvedDefinitions.end())
+        it = m_unresolvedDefinitions.add(type, ElementSet()).iterator;
+    it->value.add(element);
+}
+
+bool CustomElementUpgradeCandidateMap::contains(Element* element) const
+{
+    return m_unresolvedElements.contains(element);
+}
+
+void CustomElementUpgradeCandidateMap::remove(Element* element)
+{
+    UnresolvedElementMap::iterator it = m_unresolvedElements.find(element);
+    if (it == m_unresolvedElements.end())
+        return;
+
+    const AtomicString& type = it->value.second;
+    m_unresolvedDefinitions.get(type).remove(element);
+    m_unresolvedElements.remove(it);
+}
+
+CustomElementUpgradeCandidateMap::ElementSet CustomElementUpgradeCandidateMap::takeUpgradeCandidatesFor(CustomElementDefinition* definition)
+{
+    UnresolvedDefinitionMap::iterator it = m_unresolvedDefinitions.find(definition->type());
+    if (it == m_unresolvedDefinitions.end())
+        return ElementSet();
+
+    const ElementSet& candidatesForThisType = it->value;
+    ElementSet matchingCandidates;
+
+    // Filter the set based on whether the definition matches
+    for (ElementSet::const_iterator candidate = candidatesForThisType.begin(); candidate != candidatesForThisType.end(); ++candidate) {
+        if (matches(definition, *candidate)) {
+            matchingCandidates.add(*candidate);
+            m_unresolvedElements.remove(*candidate);
+        }
+    }
+
+    m_unresolvedDefinitions.remove(it);
+    return matchingCandidates;
+}
+
+bool CustomElementUpgradeCandidateMap::matches(CustomElementDefinition* definition, Element* element)
+{
+    ASSERT(m_unresolvedElements.contains(element));
+    const RequiredDefinition& requirement = m_unresolvedElements.get(element);
+    return definition->kind() == requirement.first && definition->type() == requirement.second && definition->namespaceURI() == element->namespaceURI() && definition->name() == element->localName();
+}
+
+}
diff --git a/Source/core/dom/CustomElementUpgradeCandidateMap.h b/Source/core/dom/CustomElementUpgradeCandidateMap.h
new file mode 100644
index 0000000..84d3d91
--- /dev/null
+++ b/Source/core/dom/CustomElementUpgradeCandidateMap.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CustomElementUpgradeCandidateMap_h
+#define CustomElementUpgradeCandidateMap_h
+
+#include "core/dom/CustomElementDefinition.h"
+#include "core/dom/Element.h"
+#include "wtf/HashMap.h"
+#include "wtf/HashSet.h"
+#include "wtf/Noncopyable.h"
+#include "wtf/text/AtomicString.h"
+#include "wtf/text/AtomicStringHash.h"
+
+namespace WebCore {
+
+class CustomElementUpgradeCandidateMap {
+    WTF_MAKE_NONCOPYABLE(CustomElementUpgradeCandidateMap);
+public:
+    CustomElementUpgradeCandidateMap() { }
+
+    typedef HashSet<Element*> ElementSet;
+
+    void add(CustomElementDefinition::CustomElementKind, const AtomicString& type, Element*);
+    bool contains(Element*) const;
+    void remove(Element*);
+    ElementSet takeUpgradeCandidatesFor(CustomElementDefinition*);
+
+private:
+    typedef std::pair<CustomElementDefinition::CustomElementKind, AtomicString> RequiredDefinition;
+    typedef HashMap<Element*, RequiredDefinition> UnresolvedElementMap;
+    typedef HashMap<AtomicString, ElementSet> UnresolvedDefinitionMap;
+
+    bool matches(CustomElementDefinition*, Element*);
+
+    UnresolvedElementMap m_unresolvedElements;
+    UnresolvedDefinitionMap m_unresolvedDefinitions;
+};
+
+}
+
+#endif // CustomElementUpgradeCandidateMap_h
+
diff --git a/Source/core/dom/CustomEvent.cpp b/Source/core/dom/CustomEvent.cpp
new file mode 100644
index 0000000..c7e67b3
--- /dev/null
+++ b/Source/core/dom/CustomEvent.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/CustomEvent.h"
+
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+CustomEventInit::CustomEventInit()
+{
+}
+
+CustomEvent::CustomEvent()
+{
+    ScriptWrappable::init(this);
+}
+
+CustomEvent::CustomEvent(const AtomicString& type, const CustomEventInit& initializer)
+    : Event(type, initializer)
+    , m_detail(initializer.detail)
+{
+    ScriptWrappable::init(this);
+}
+
+CustomEvent::~CustomEvent()
+{
+}
+
+void CustomEvent::initCustomEvent(const AtomicString& type, bool canBubble, bool cancelable, const ScriptValue& detail)
+{
+    ASSERT(!m_serializedScriptValue.get());
+    if (dispatched())
+        return;
+
+    initEvent(type, canBubble, cancelable);
+
+    m_detail = detail;
+}
+
+void CustomEvent::initCustomEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> serializedScriptValue)
+{
+    ASSERT(m_detail.hasNoValue());
+    if (dispatched())
+        return;
+
+    initEvent(type, canBubble, cancelable);
+
+    m_serializedScriptValue = serializedScriptValue;
+}
+
+const AtomicString& CustomEvent::interfaceName() const
+{
+    return eventNames().interfaceForCustomEvent;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/CustomEvent.h b/Source/core/dom/CustomEvent.h
new file mode 100644
index 0000000..6afc0ae
--- /dev/null
+++ b/Source/core/dom/CustomEvent.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CustomEvent_h
+#define CustomEvent_h
+
+#include "bindings/v8/ScriptValue.h"
+#include "bindings/v8/SerializedScriptValue.h"
+#include "core/dom/Event.h"
+
+namespace WebCore {
+
+struct CustomEventInit : public EventInit {
+    CustomEventInit();
+
+    ScriptValue detail;
+};
+
+class CustomEvent : public Event {
+public:
+    virtual ~CustomEvent();
+
+    static PassRefPtr<CustomEvent> create()
+    {
+        return adoptRef(new CustomEvent);
+    }
+
+    static PassRefPtr<CustomEvent> create(const AtomicString& type, const CustomEventInit& initializer)
+    {
+        return adoptRef(new CustomEvent(type, initializer));
+    }
+
+    void initCustomEvent(const AtomicString& type, bool canBubble, bool cancelable, const ScriptValue& detail);
+    void initCustomEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue>);
+
+    virtual const AtomicString& interfaceName() const;
+
+    const ScriptValue& detail() const { return m_detail; }
+    PassRefPtr<SerializedScriptValue> serializedScriptValue() { return m_serializedScriptValue; }
+
+private:
+    CustomEvent();
+    CustomEvent(const AtomicString& type, const CustomEventInit& initializer);
+
+    ScriptValue m_detail;
+    RefPtr<SerializedScriptValue> m_serializedScriptValue;
+};
+
+} // namespace WebCore
+
+#endif // CustomEvent_h
diff --git a/Source/core/dom/CustomEvent.idl b/Source/core/dom/CustomEvent.idl
new file mode 100644
index 0000000..f4a67e4
--- /dev/null
+++ b/Source/core/dom/CustomEvent.idl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+[
+    ConstructorTemplate=Event
+] interface CustomEvent : Event {
+    [InitializedByEventConstructor, Custom] readonly attribute any detail;
+
+    void initCustomEvent([Default=Undefined] optional DOMString typeArg, 
+                         [Default=Undefined] optional boolean canBubbleArg, 
+                         [Default=Undefined] optional boolean cancelableArg, 
+                         [Default=Undefined] optional any detailArg);
+};
diff --git a/Source/core/dom/DOMCoreException.cpp b/Source/core/dom/DOMCoreException.cpp
new file mode 100644
index 0000000..6e3e76e
--- /dev/null
+++ b/Source/core/dom/DOMCoreException.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 GOOGLE AND ITS 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 APPLE OR ITS 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 "core/dom/DOMCoreException.h"
+
+namespace WebCore {
+
+static struct CoreException {
+    const char* const name;
+    const char* const description;
+} coreExceptions[] = {
+    { "IndexSizeError", "Index or size was negative, or greater than the allowed value." },
+    { 0, 0 }, // DOMStringSizeError
+    { "HierarchyRequestError", "A Node was inserted somewhere it doesn't belong." },
+    { "WrongDocumentError", "A Node was used in a different document than the one that created it (that doesn't support it)." },
+    { "InvalidCharacterError", "An invalid or illegal character was specified, such as in an XML name." },
+    { 0, 0 }, // NoDataAllowedError
+    { "NoModificationAllowedError", "An attempt was made to modify an object where modifications are not allowed." },
+    { "NotFoundError", "An attempt was made to reference a Node in a context where it does not exist." },
+    { "NotSupportedError", "The implementation did not support the requested type of object or operation." },
+    { "InUseAttributeError", "An attempt was made to add an attribute that is already in use elsewhere." },
+    { "InvalidStateError", "An attempt was made to use an object that is not, or is no longer, usable." },
+    { "SyntaxError", "An invalid or illegal string was specified." },
+    { "InvalidModificationError", "An attempt was made to modify the type of the underlying object." },
+    { "NamespaceError", "An attempt was made to create or change an object in a way which is incorrect with regard to namespaces." },
+    { "InvalidAccessError", "A parameter or an operation was not supported by the underlying object." },
+    { 0, 0 }, // ValidationError
+    { "TypeMismatchError", "The type of an object was incompatible with the expected type of the parameter associated to the object." },
+    { "SecurityError", "An attempt was made to break through the security policy of the user agent." },
+    // FIXME: Couldn't find a description in the HTML/DOM specifications for NETWORK_ERR, ABORT_ERR, URL_MISMATCH_ERR, and QUOTA_EXCEEDED_ERR
+    { "NetworkError", "A network error occurred." },
+    { "AbortError", "The user aborted a request." },
+    { "URLMismatchError", "A worker global scope represented an absolute URL that is not equal to the resulting absolute URL." },
+    { "QuotaExceededError", "An attempt was made to add something to storage that exceeded the quota." },
+    { "TimeoutError", "A timeout occurred." },
+    { "InvalidNodeTypeError", "The supplied node is invalid or has an invalid ancestor for this operation." },
+    { "DataCloneError", "An object could not be cloned." }
+};
+
+bool DOMCoreException::initializeDescription(ExceptionCode ec, ExceptionCodeDescription* description)
+{
+    description->typeName = "DOM";
+    description->code = ec;
+    description->type = DOMCoreExceptionType;
+
+    size_t tableSize = WTF_ARRAY_LENGTH(coreExceptions);
+    size_t tableIndex = ec - INDEX_SIZE_ERR;
+
+    description->name = tableIndex < tableSize ? coreExceptions[tableIndex].name : 0;
+    description->description = tableIndex < tableSize ? coreExceptions[tableIndex].description : 0;
+
+    return true;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/DOMCoreException.h b/Source/core/dom/DOMCoreException.h
new file mode 100644
index 0000000..64fd5cc
--- /dev/null
+++ b/Source/core/dom/DOMCoreException.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 DOMCoreException_h
+#define DOMCoreException_h
+
+#include "core/dom/ExceptionBase.h"
+
+namespace WebCore {
+
+class DOMCoreException : public ExceptionBase {
+public:
+    static PassRefPtr<DOMCoreException> create(const ExceptionCodeDescription& description)
+    {
+        return adoptRef(new DOMCoreException(description));
+    }
+
+    static bool initializeDescription(ExceptionCode, ExceptionCodeDescription*);
+
+private:
+    explicit DOMCoreException(const ExceptionCodeDescription& description)
+        : ExceptionBase(description)
+    {
+    }
+};
+
+} // namespace WebCore
+
+#endif // DOMCoreException_h
diff --git a/Source/core/dom/DOMCoreException.idl b/Source/core/dom/DOMCoreException.idl
new file mode 100644
index 0000000..2b6f16e
--- /dev/null
+++ b/Source/core/dom/DOMCoreException.idl
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+[
+    DoNotCheckConstants,
+    InterfaceName=DOMException,
+    ImplementationLacksVTable
+] exception DOMCoreException {
+
+    readonly attribute unsigned short   code;
+    readonly attribute DOMString        name;
+    readonly attribute DOMString        message;
+
+    // Override in a Mozilla compatible format
+    [NotEnumerable] DOMString toString();
+
+    // ExceptionCode
+    const unsigned short      INDEX_SIZE_ERR                 = 1;
+    const unsigned short      DOMSTRING_SIZE_ERR             = 2;
+    const unsigned short      HIERARCHY_REQUEST_ERR          = 3;
+    const unsigned short      WRONG_DOCUMENT_ERR             = 4;
+    const unsigned short      INVALID_CHARACTER_ERR          = 5;
+    const unsigned short      NO_DATA_ALLOWED_ERR            = 6;
+    const unsigned short      NO_MODIFICATION_ALLOWED_ERR    = 7;
+    const unsigned short      NOT_FOUND_ERR                  = 8;
+    const unsigned short      NOT_SUPPORTED_ERR              = 9;
+    const unsigned short      INUSE_ATTRIBUTE_ERR            = 10;
+    // Introduced in DOM Level 2:
+    const unsigned short      INVALID_STATE_ERR              = 11;
+    // Introduced in DOM Level 2:
+    const unsigned short      SYNTAX_ERR                     = 12;
+    // Introduced in DOM Level 2:
+    const unsigned short      INVALID_MODIFICATION_ERR       = 13;
+    // Introduced in DOM Level 2:
+    const unsigned short      NAMESPACE_ERR                  = 14;
+    // Introduced in DOM Level 2:
+    const unsigned short      INVALID_ACCESS_ERR             = 15;
+    // Introduced in DOM Level 3:
+    const unsigned short      VALIDATION_ERR                 = 16;
+    // Introduced in DOM Level 3:
+    const unsigned short      TYPE_MISMATCH_ERR              = 17;
+    // Introduced as an XHR extension:
+    const unsigned short      SECURITY_ERR                   = 18;
+    // Introduced in HTML5:
+    const unsigned short      NETWORK_ERR                    = 19;
+    const unsigned short      ABORT_ERR                      = 20;
+    const unsigned short      URL_MISMATCH_ERR               = 21;
+    const unsigned short      QUOTA_EXCEEDED_ERR             = 22;
+    // TIMEOUT_ERR is currently unused but was added for completeness.
+    const unsigned short      TIMEOUT_ERR                    = 23;
+    // INVALID_NODE_TYPE_ERR is currently unused but was added for completeness.
+    const unsigned short      INVALID_NODE_TYPE_ERR          = 24;
+    const unsigned short      DATA_CLONE_ERR                 = 25;
+};
+
diff --git a/Source/core/dom/DOMError.cpp b/Source/core/dom/DOMError.cpp
new file mode 100644
index 0000000..32ceeb5
--- /dev/null
+++ b/Source/core/dom/DOMError.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 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 "core/dom/DOMError.h"
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+DOMError::DOMError(const String& name)
+    : m_name(name)
+{
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/DOMError.h b/Source/core/dom/DOMError.h
new file mode 100644
index 0000000..ecfa66b
--- /dev/null
+++ b/Source/core/dom/DOMError.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 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 DOMError_h
+#define DOMError_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class DOMError : public RefCounted<DOMError> {
+public:
+    static PassRefPtr<DOMError> create(const String& name)
+    {
+        return adoptRef(new DOMError(name));
+    }
+
+    const String& name() const { return m_name; }
+
+private:
+    explicit DOMError(const String& name);
+
+    const String m_name;
+};
+
+} // namespace WebCore
+
+#endif // DOMError_h
diff --git a/Source/core/dom/DOMError.idl b/Source/core/dom/DOMError.idl
new file mode 100644
index 0000000..79a5881
--- /dev/null
+++ b/Source/core/dom/DOMError.idl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+[
+    ImplementationLacksVTable
+] interface  DOMError {
+    readonly attribute DOMString name;
+  };
+
diff --git a/Source/core/dom/DOMExceptions.in b/Source/core/dom/DOMExceptions.in
new file mode 100644
index 0000000..b27312b
--- /dev/null
+++ b/Source/core/dom/DOMExceptions.in
@@ -0,0 +1,8 @@
+namespace=Exception
+
+core/dom/DOMCoreException
+core/dom/EventException
+core/fileapi/FileException
+modules/webdatabase/SQLException
+core/svg/SVGException conditional=SVG
+core/xml/XPathException
diff --git a/Source/core/dom/DOMImplementation.cpp b/Source/core/dom/DOMImplementation.cpp
new file mode 100644
index 0000000..5481f20
--- /dev/null
+++ b/Source/core/dom/DOMImplementation.cpp
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig (sam@webkit.org)
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/DOMImplementation.h"
+
+#include "HTMLNames.h"
+#include "XMLNames.h"
+#include "core/css/CSSStyleSheet.h"
+#include "core/css/MediaList.h"
+#include "core/css/StyleSheetContents.h"
+#include "core/dom/ContextFeatures.h"
+#include "core/dom/DocumentType.h"
+#include "core/dom/Element.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/html/HTMLDocument.h"
+#include "core/html/HTMLViewSourceDocument.h"
+#include "core/html/ImageDocument.h"
+#include "core/html/MediaDocument.h"
+#include "core/html/PluginDocument.h"
+#include "core/html/TextDocument.h"
+#include "core/loader/FrameLoader.h"
+#include "core/loader/FrameLoaderClient.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/page/SecurityOrigin.h"
+#include "core/page/Settings.h"
+#include "core/platform/ContentType.h"
+#include "core/platform/MIMETypeRegistry.h"
+#include "core/platform/graphics/Image.h"
+#include "core/platform/graphics/MediaPlayer.h"
+#include "core/plugins/PluginData.h"
+#include <wtf/StdLibExtras.h>
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#include "core/svg/SVGDocument.h"
+#endif
+
+namespace WebCore {
+
+typedef HashSet<String, CaseFoldingHash> FeatureSet;
+
+static void addString(FeatureSet& set, const char* string)
+{
+    set.add(string);
+}
+
+class DOMImplementationSupportsTypeClient : public MediaPlayerSupportsTypeClient {
+public:
+    DOMImplementationSupportsTypeClient(bool needsHacks, const String& host)
+        : m_needsHacks(needsHacks)
+        , m_host(host)
+    {
+    }
+
+private:
+    virtual bool mediaPlayerNeedsSiteSpecificHacks() const OVERRIDE { return m_needsHacks; }
+    virtual String mediaPlayerDocumentHost() const OVERRIDE { return m_host; }
+
+    bool m_needsHacks;
+    String m_host;
+};
+
+#if ENABLE(SVG)
+
+static bool isSVG10Feature(const String &feature, const String &version)
+{
+    if (!version.isEmpty() && version != "1.0")
+        return false;
+
+    static bool initialized = false;
+    DEFINE_STATIC_LOCAL(FeatureSet, svgFeatures, ());
+    if (!initialized) {
+#if ENABLE(SVG_FONTS)
+        addString(svgFeatures, "svg");
+        addString(svgFeatures, "svg.static");
+#endif
+//      addString(svgFeatures, "svg.animation");
+//      addString(svgFeatures, "svg.dynamic");
+//      addString(svgFeatures, "svg.dom.animation");
+//      addString(svgFeatures, "svg.dom.dynamic");
+#if ENABLE(SVG_FONTS)
+        addString(svgFeatures, "dom");
+        addString(svgFeatures, "dom.svg");
+        addString(svgFeatures, "dom.svg.static");
+#endif
+//      addString(svgFeatures, "svg.all");
+//      addString(svgFeatures, "dom.svg.all");
+        initialized = true;
+    }
+    return feature.startsWith("org.w3c.", false)
+        && svgFeatures.contains(feature.right(feature.length() - 8));
+}
+
+static bool isSVG11Feature(const String &feature, const String &version)
+{
+    if (!version.isEmpty() && version != "1.1")
+        return false;
+
+    static bool initialized = false;
+    DEFINE_STATIC_LOCAL(FeatureSet, svgFeatures, ());
+    if (!initialized) {
+        // Sadly, we cannot claim to implement any of the SVG 1.1 generic feature sets
+        // lack of Font and Filter support.
+        // http://bugs.webkit.org/show_bug.cgi?id=15480
+#if ENABLE(SVG_FONTS)
+        addString(svgFeatures, "SVG");
+        addString(svgFeatures, "SVGDOM");
+        addString(svgFeatures, "SVG-static");
+        addString(svgFeatures, "SVGDOM-static");
+#endif
+        addString(svgFeatures, "SVG-animation");
+        addString(svgFeatures, "SVGDOM-animation");
+//      addString(svgFeatures, "SVG-dynamic);
+//      addString(svgFeatures, "SVGDOM-dynamic);
+        addString(svgFeatures, "CoreAttribute");
+        addString(svgFeatures, "Structure");
+        addString(svgFeatures, "BasicStructure");
+        addString(svgFeatures, "ContainerAttribute");
+        addString(svgFeatures, "ConditionalProcessing");
+        addString(svgFeatures, "Image");
+        addString(svgFeatures, "Style");
+        addString(svgFeatures, "ViewportAttribute");
+        addString(svgFeatures, "Shape");
+        addString(svgFeatures, "Text");
+        addString(svgFeatures, "BasicText");
+        addString(svgFeatures, "PaintAttribute");
+        addString(svgFeatures, "BasicPaintAttribute");
+        addString(svgFeatures, "OpacityAttribute");
+        addString(svgFeatures, "GraphicsAttribute");
+        addString(svgFeatures, "BaseGraphicsAttribute");
+        addString(svgFeatures, "Marker");
+//      addString(svgFeatures, "ColorProfile"); // requires color-profile, bug 6037
+        addString(svgFeatures, "Gradient");
+        addString(svgFeatures, "Pattern");
+        addString(svgFeatures, "Clip");
+        addString(svgFeatures, "BasicClip");
+        addString(svgFeatures, "Mask");
+        addString(svgFeatures, "Filter");
+        addString(svgFeatures, "BasicFilter");
+        addString(svgFeatures, "DocumentEventsAttribute");
+        addString(svgFeatures, "GraphicalEventsAttribute");
+//      addString(svgFeatures, "AnimationEventsAttribute");
+        addString(svgFeatures, "Cursor");
+        addString(svgFeatures, "Hyperlinking");
+        addString(svgFeatures, "XlinkAttribute");
+        addString(svgFeatures, "ExternalResourcesRequired");
+        addString(svgFeatures, "View");
+        addString(svgFeatures, "Script");
+        addString(svgFeatures, "Animation"); 
+#if ENABLE(SVG_FONTS)
+        addString(svgFeatures, "Font");
+        addString(svgFeatures, "BasicFont");
+#endif
+        addString(svgFeatures, "Extensibility");
+        initialized = true;
+    }
+    return feature.startsWith("http://www.w3.org/tr/svg11/feature#", false)
+        && svgFeatures.contains(feature.right(feature.length() - 35));
+}
+#endif
+
+static bool isEvents2Feature(const String &feature, const String &version)
+{
+    if (!version.isEmpty() && version != "2.0")
+        return false;
+
+    static bool initialized = false;
+    DEFINE_STATIC_LOCAL(FeatureSet, events2Features, ());
+    if (!initialized) {
+        addString(events2Features, "Events");
+        addString(events2Features, "HTMLEvents");
+        addString(events2Features, "MouseEvents");
+        addString(events2Features, "MutationEvents");
+        addString(events2Features, "UIEvents");
+        initialized = true;
+    }
+    return events2Features.contains(feature);
+}
+
+static bool isEvents3Feature(const String &feature, const String &version)
+{
+    if (!version.isEmpty() && version != "3.0")
+        return false;
+
+    static bool initialized = false;
+    DEFINE_STATIC_LOCAL(FeatureSet, events3Features, ());
+    if (!initialized) {
+        // FIXME: We probably support many of these features.
+//        addString(events3Features, "CompositionEvents");
+//        addString(events3Features, "Events");
+//        addString(events3Features, "FocusEvents");
+//        addString(events3Features, "HTMLEvents");
+//        addString(events3Features, "KeyboardEvents");
+//        addString(events3Features, "MouseEvents");
+//        addString(events3Features, "MutationEvents");
+//        addString(events3Features, "MutationNameEvents");
+        addString(events3Features, "TextEvents");
+//        addString(events3Features, "UIEvents");
+//        addString(events3Features, "WheelEvents");
+        initialized = true;
+    }
+    // FIXME: We do not yet support Events 3 "extended feature strings".
+    return events3Features.contains(feature);
+}
+
+DOMImplementation::DOMImplementation(Document* document)
+    : m_document(document)
+{
+    ScriptWrappable::init(this);
+}
+
+bool DOMImplementation::hasFeature(const String& feature, const String& version)
+{
+    String lower = feature.lower();
+    if (lower == "core" || lower == "html" || lower == "xml" || lower == "xhtml")
+        return version.isEmpty() || version == "1.0" || version == "2.0";
+    if (lower == "css"
+            || lower == "css2"
+            || lower == "range"
+            || lower == "stylesheets"
+            || lower == "traversal"
+            || lower == "views")
+        return version.isEmpty() || version == "2.0";
+    if (isEvents2Feature(feature, version))
+        return true;
+    if (lower == "xpath")
+        return version.isEmpty() || version == "3.0";
+    if (isEvents3Feature(feature, version))
+        return true;
+
+#if ENABLE(SVG)
+    if (isSVG11Feature(feature, version))
+        return true;
+    if (isSVG10Feature(feature, version))
+        return true;
+#endif
+
+    return false;
+}
+
+PassRefPtr<DocumentType> DOMImplementation::createDocumentType(const String& qualifiedName,
+    const String& publicId, const String& systemId, ExceptionCode& ec)
+{
+    String prefix, localName;
+    if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
+        return 0;
+
+    return DocumentType::create(0, qualifiedName, publicId, systemId);
+}
+
+DOMImplementation* DOMImplementation::getInterface(const String& /*feature*/)
+{
+    return 0;
+}
+
+PassRefPtr<Document> DOMImplementation::createDocument(const String& namespaceURI,
+    const String& qualifiedName, DocumentType* doctype, ExceptionCode& ec)
+{
+    RefPtr<Document> doc;
+#if ENABLE(SVG)
+    if (namespaceURI == SVGNames::svgNamespaceURI)
+        doc = SVGDocument::create(0, KURL());
+    else
+#endif
+    if (namespaceURI == HTMLNames::xhtmlNamespaceURI)
+        doc = Document::createXHTML(0, KURL());
+    else
+        doc = Document::create(0, KURL());
+
+    doc->setSecurityOrigin(m_document->securityOrigin());
+    doc->setContextFeatures(m_document->contextFeatures());
+
+    RefPtr<Node> documentElement;
+    if (!qualifiedName.isEmpty()) {
+        documentElement = doc->createElementNS(namespaceURI, qualifiedName, ec);
+        if (ec)
+            return 0;
+    }
+
+    // WRONG_DOCUMENT_ERR: Raised if doctype has already been used with a different document or was
+    // created from a different implementation.
+    // Hixie's interpretation of the DOM Core spec suggests we should prefer
+    // other exceptions to WRONG_DOCUMENT_ERR (based on order mentioned in spec),
+    // but this matches the new DOM Core spec (http://www.w3.org/TR/domcore/).
+    if (doctype && doctype->document()) {
+        ec = WRONG_DOCUMENT_ERR;
+        return 0;
+    }
+
+    if (doctype)
+        doc->appendChild(doctype);
+    if (documentElement)
+        doc->appendChild(documentElement.release());
+
+    return doc.release();
+}
+
+PassRefPtr<CSSStyleSheet> DOMImplementation::createCSSStyleSheet(const String&, const String& media, ExceptionCode&)
+{
+    // FIXME: Title should be set.
+    // FIXME: Media could have wrong syntax, in which case we should generate an exception.
+    RefPtr<CSSStyleSheet> sheet = CSSStyleSheet::create(StyleSheetContents::create());
+    sheet->setMediaQueries(MediaQuerySet::createAllowingDescriptionSyntax(media));
+    return sheet;
+}
+
+bool DOMImplementation::isXMLMIMEType(const String& mimeType)
+{
+    if (mimeType == "text/xml" || mimeType == "application/xml" || mimeType == "text/xsl")
+        return true;
+
+    // Per RFCs 3023 and 2045 a mime type is of the form:
+    // ^[0-9a-zA-Z_\\-+~!$\\^{}|.%'`#&*]+/[0-9a-zA-Z_\\-+~!$\\^{}|.%'`#&*]+\+xml$
+
+    int length = mimeType.length();
+    if (length < 7)
+        return false;
+
+    if (mimeType[0] == '/' ||
+        mimeType[length - 5] == '/' ||
+        mimeType[length - 4] != '+' ||
+        mimeType[length - 3] != 'x' ||
+        mimeType[length - 2] != 'm' ||
+        mimeType[length - 1] != 'l')
+        return false;
+
+    bool hasSlash = false;
+    for (int i = 0; i < length - 4; ++i) {
+        UChar ch = mimeType[i];
+        if (ch >= '0' && ch <= '9')
+            continue;
+        if (ch >= 'a' && ch <= 'z')
+            continue;
+        if (ch >= 'A' && ch <= 'Z')
+            continue;
+        switch (ch) {
+        case '_':
+        case '-':
+        case '+':
+        case '~':
+        case '!':
+        case '$':
+        case '^':
+        case '{':
+        case '}':
+        case '|':
+        case '.':
+        case '%':
+        case '\'':
+        case '`':
+        case '#':
+        case '&':
+        case '*':
+            continue;
+        case '/':
+            if (hasSlash)
+                return false;
+            hasSlash = true;
+            continue;
+        default:
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool DOMImplementation::isTextMIMEType(const String& mimeType)
+{
+    if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType)
+        || mimeType == "application/json" // Render JSON as text/plain.
+        || (mimeType.startsWith("text/") && mimeType != "text/html"
+            && mimeType != "text/xml" && mimeType != "text/xsl"))
+        return true;
+
+    return false;
+}
+
+PassRefPtr<HTMLDocument> DOMImplementation::createHTMLDocument(const String& title)
+{
+    RefPtr<HTMLDocument> d = HTMLDocument::create(0, KURL());
+    d->open();
+    d->write("<!doctype html><html><body></body></html>");
+    if (!title.isNull())
+        d->setTitle(title);
+    d->setSecurityOrigin(m_document->securityOrigin());
+    d->setContextFeatures(m_document->contextFeatures());
+    return d.release();
+}
+
+PassRefPtr<Document> DOMImplementation::createDocument(const String& type, Frame* frame, const KURL& url, bool inViewSourceMode)
+{
+    if (inViewSourceMode)
+        return HTMLViewSourceDocument::create(frame, url, type);
+
+    // Plugins cannot take HTML and XHTML from us, and we don't even need to initialize the plugin database for those.
+    if (type == "text/html")
+        return HTMLDocument::create(frame, url);
+    if (type == "application/xhtml+xml")
+        return Document::createXHTML(frame, url);
+
+    PluginData* pluginData = 0;
+    if (frame && frame->page() && frame->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin))
+        pluginData = frame->page()->pluginData();
+
+    // PDF is one image type for which a plugin can override built-in support.
+    // We do not want QuickTime to take over all image types, obviously.
+    if ((type == "application/pdf" || type == "text/pdf") && pluginData && pluginData->supportsMimeType(type))
+        return PluginDocument::create(frame, url);
+    if (Image::supportsType(type))
+        return ImageDocument::create(frame, url);
+
+     // Check to see if the type can be played by our MediaPlayer, if so create a MediaDocument
+    // Key system is not applicable here.
+    DOMImplementationSupportsTypeClient client(frame && frame->settings() && frame->settings()->needsSiteSpecificQuirks(), url.host());
+    if (MediaPlayer::supportsType(ContentType(type), String(), url, &client))
+         return MediaDocument::create(frame, url);
+
+    // Everything else except text/plain can be overridden by plugins. In particular, Adobe SVG Viewer should be used for SVG, if installed.
+    // Disallowing plug-ins to use text/plain prevents plug-ins from hijacking a fundamental type that the browser is expected to handle,
+    // and also serves as an optimization to prevent loading the plug-in database in the common case.
+    if (type != "text/plain" && pluginData && pluginData->supportsMimeType(type)) 
+        return PluginDocument::create(frame, url);
+    if (isTextMIMEType(type))
+        return TextDocument::create(frame, url);
+
+#if ENABLE(SVG)
+    if (type == "image/svg+xml")
+        return SVGDocument::create(frame, url);
+#endif
+    if (isXMLMIMEType(type))
+        return Document::create(frame, url);
+
+    return HTMLDocument::create(frame, url);
+}
+
+}
diff --git a/Source/core/dom/DOMImplementation.h b/Source/core/dom/DOMImplementation.h
new file mode 100644
index 0000000..918e766
--- /dev/null
+++ b/Source/core/dom/DOMImplementation.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef DOMImplementation_h
+#define DOMImplementation_h
+
+#include "core/dom/Document.h"
+#include "core/platform/graphics/MediaPlayer.h"
+#include <wtf/Forward.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class CSSStyleSheet;
+class Document;
+class DocumentType;
+class Frame;
+class HTMLDocument;
+class KURL;
+
+typedef int ExceptionCode;
+
+class DOMImplementation : public ScriptWrappable {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<DOMImplementation> create(Document* document) { return adoptPtr(new DOMImplementation(document)); }
+    
+    void ref() { m_document->ref(); }
+    void deref() { m_document->deref(); }
+    Document* document() { return m_document; }
+
+    // DOM methods & attributes for DOMImplementation
+    static bool hasFeature(const String& feature, const String& version);
+    PassRefPtr<DocumentType> createDocumentType(const String& qualifiedName, const String& publicId, const String& systemId, ExceptionCode&);
+    PassRefPtr<Document> createDocument(const String& namespaceURI, const String& qualifiedName, DocumentType*, ExceptionCode&);
+
+    DOMImplementation* getInterface(const String& feature);
+
+    // From the DOMImplementationCSS interface
+    static PassRefPtr<CSSStyleSheet> createCSSStyleSheet(const String& title, const String& media, ExceptionCode&);
+
+    // From the HTMLDOMImplementation interface
+    PassRefPtr<HTMLDocument> createHTMLDocument(const String& title);
+
+    // Other methods (not part of DOM)
+    static PassRefPtr<Document> createDocument(const String& MIMEType, Frame*, const KURL&, bool inViewSourceMode);
+
+    static bool isXMLMIMEType(const String& MIMEType);
+    static bool isTextMIMEType(const String& MIMEType);
+
+private:
+    explicit DOMImplementation(Document*);
+
+    Document* m_document;
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/core/dom/DOMImplementation.idl b/Source/core/dom/DOMImplementation.idl
new file mode 100644
index 0000000..960e2df
--- /dev/null
+++ b/Source/core/dom/DOMImplementation.idl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+[
+    GenerateIsReachable=ImplDocument,
+    ImplementationLacksVTable
+] interface DOMImplementation {
+
+    // DOM Level 1
+
+     boolean hasFeature([Default=Undefined] optional DOMString feature, 
+                                      [TreatNullAs=NullString,Default=Undefined] optional DOMString version);
+
+    // DOM Level 2
+
+     [RaisesException] DocumentType createDocumentType([TreatNullAs=NullString, TreatUndefinedAs=NullString,Default=Undefined] optional DOMString qualifiedName,
+                                                   [TreatNullAs=NullString, TreatUndefinedAs=NullString,Default=Undefined] optional DOMString publicId,
+                                                   [TreatNullAs=NullString, TreatUndefinedAs=NullString,Default=Undefined] optional DOMString systemId);
+     [RaisesException] Document createDocument([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI, 
+                                           [TreatNullAs=NullString,Default=Undefined] optional DOMString qualifiedName, 
+                                           [TreatNullAs=NullString,Default=Undefined] optional DocumentType doctype);
+
+    // DOMImplementationCSS interface from DOM Level 2 CSS
+
+     [RaisesException] CSSStyleSheet createCSSStyleSheet([Default=Undefined] optional DOMString title,
+                                                     [Default=Undefined] optional DOMString media);
+
+    // HTMLDOMImplementation interface from DOM Level 2 HTML
+
+    HTMLDocument createHTMLDocument([Default=NullString] optional DOMString title);
+};
+
diff --git a/Source/core/dom/DOMNamedFlowCollection.cpp b/Source/core/dom/DOMNamedFlowCollection.cpp
new file mode 100644
index 0000000..b882120
--- /dev/null
+++ b/Source/core/dom/DOMNamedFlowCollection.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 HOLDER 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 "core/dom/DOMNamedFlowCollection.h"
+
+#include "RuntimeEnabledFeatures.h"
+#include "core/dom/NamedFlow.h"
+#include "core/dom/NamedFlowCollection.h"
+
+namespace WebCore {
+
+DOMNamedFlowCollection::DOMNamedFlowCollection(const Vector<NamedFlow*>& namedFlows)
+{
+    ASSERT(RuntimeEnabledFeatures::cssRegionsEnabled());
+    for (Vector<NamedFlow*>::const_iterator it = namedFlows.begin(); it != namedFlows.end(); ++it)
+        m_namedFlows.add(*it);
+}
+
+unsigned long DOMNamedFlowCollection::length() const
+{
+    return m_namedFlows.size();
+}
+
+PassRefPtr<NamedFlow> DOMNamedFlowCollection::item(unsigned long index) const
+{
+    if (index >= static_cast<unsigned long>(m_namedFlows.size()))
+        return 0;
+    DOMNamedFlowSet::const_iterator it = m_namedFlows.begin();
+    for (unsigned long i = 0; i < index; ++i)
+        ++it;
+    return *it;
+}
+
+PassRefPtr<NamedFlow> DOMNamedFlowCollection::namedItem(const AtomicString& name) const
+{
+    DOMNamedFlowSet::const_iterator it = m_namedFlows.find<String, DOMNamedFlowHashTranslator>(name);
+    if (it != m_namedFlows.end())
+        return *it;
+    return 0;
+}
+
+bool DOMNamedFlowCollection::hasNamedItem(const AtomicString& name) const
+{
+    return namedItem(name);
+}
+
+// The HashFunctions object used by the HashSet to compare between RefPtr<NamedFlows>.
+// It is safe to set safeToCompareToEmptyOrDeleted because the HashSet will never contain null pointers or deleted values.
+struct DOMNamedFlowCollection::DOMNamedFlowHashFunctions {
+    static unsigned hash(PassRefPtr<NamedFlow> key) { return DefaultHash<String>::Hash::hash(key->name()); }
+    static bool equal(PassRefPtr<NamedFlow> a, PassRefPtr<NamedFlow> b) { return a->name() == b->name(); }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+// The HashTranslator is used to lookup a RefPtr<NamedFlow> in the set using a name.
+struct DOMNamedFlowCollection::DOMNamedFlowHashTranslator {
+    static unsigned hash(const String& key) { return DefaultHash<String>::Hash::hash(key); }
+    static bool equal(PassRefPtr<NamedFlow> a, const String& b) { return a->name() == b; }
+};
+} // namespace WebCore
+
+
+
diff --git a/Source/core/dom/DOMNamedFlowCollection.h b/Source/core/dom/DOMNamedFlowCollection.h
new file mode 100644
index 0000000..739fad3
--- /dev/null
+++ b/Source/core/dom/DOMNamedFlowCollection.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 HOLDER 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 DOMNamedFlowCollection_h
+#define DOMNamedFlowCollection_h
+
+#include "core/dom/NamedFlowCollection.h"
+#include <wtf/ListHashSet.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Document;
+class NamedFlow;
+
+class DOMNamedFlowCollection : public RefCounted<DOMNamedFlowCollection> {
+public:
+    static PassRefPtr<DOMNamedFlowCollection> create(const Vector<NamedFlow*>& namedFlows)
+    {
+        return adoptRef(new DOMNamedFlowCollection(namedFlows));
+    }
+
+    unsigned long length() const;
+    PassRefPtr<NamedFlow> item(unsigned long index) const;
+    PassRefPtr<NamedFlow> namedItem(const AtomicString& name) const;
+
+    bool hasNamedItem(const AtomicString& name) const;
+
+private:
+    struct DOMNamedFlowHashFunctions;
+    struct DOMNamedFlowHashTranslator;
+
+    typedef ListHashSet<RefPtr<NamedFlow>, 1, DOMNamedFlowHashFunctions> DOMNamedFlowSet;
+    explicit DOMNamedFlowCollection(const Vector<NamedFlow*>&);
+    DOMNamedFlowSet m_namedFlows;
+};
+
+} // namespace WebCore
+#endif
+
diff --git a/Source/core/dom/DOMNamedFlowCollection.idl b/Source/core/dom/DOMNamedFlowCollection.idl
new file mode 100644
index 0000000..6225e98
--- /dev/null
+++ b/Source/core/dom/DOMNamedFlowCollection.idl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 HOLDER 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.
+ */
+
+[
+    EnabledAtRuntime=cssRegions,
+    InterfaceName=WebKitNamedFlowCollection,
+    ImplementationLacksVTable
+] interface DOMNamedFlowCollection {
+    readonly attribute unsigned long length;
+    getter NamedFlow item(unsigned long index);
+    getter NamedFlow namedItem(DOMString name);
+};
diff --git a/Source/core/dom/DOMStringList.cpp b/Source/core/dom/DOMStringList.cpp
new file mode 100644
index 0000000..bca4934
--- /dev/null
+++ b/Source/core/dom/DOMStringList.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 "core/dom/DOMStringList.h"
+
+namespace WebCore {
+
+String DOMStringList::item(unsigned index) const
+{
+    if (index >= m_strings.size())
+        return String();
+    return m_strings[index];
+}
+
+bool DOMStringList::contains(const String& string) const
+{
+    // FIXME: Currently, all consumers of DOMStringList store fairly small lists and thus an O(n)
+    //        algorithm is OK.  But this may need to be optimized if larger amounts of data are
+    //        stored in m_strings.
+    size_t count = m_strings.size();
+    for (size_t i = 0; i < count; ++i) {
+        if (m_strings[i] == string)
+            return true;
+    }
+    return false;
+}
+
+void DOMStringList::sort()
+{
+    std::sort(m_strings.begin(), m_strings.end(), WTF::codePointCompareLessThan);
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/DOMStringList.h b/Source/core/dom/DOMStringList.h
new file mode 100644
index 0000000..d365799
--- /dev/null
+++ b/Source/core/dom/DOMStringList.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 DOMStringList_h
+#define DOMStringList_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+// FIXME: Some consumers of this class may benefit from lazily fetching items rather
+//        than creating the list statically as is currently the only option.
+class DOMStringList : public RefCounted<DOMStringList> {
+public:
+    static PassRefPtr<DOMStringList> create()
+    {
+        return adoptRef(new DOMStringList());
+    }
+
+    bool isEmpty() const { return m_strings.isEmpty(); }
+    void clear() { m_strings.clear(); }
+    void append(const String& string) { m_strings.append(string); }
+    void sort();
+
+    // Implements the IDL.
+    size_t length() const { return m_strings.size(); }
+    String item(unsigned index) const;
+    bool contains(const String& str) const;
+
+    operator const Vector<String>&() const { return m_strings; }
+
+private:
+    DOMStringList() { }
+
+    Vector<String> m_strings;
+};
+
+} // namespace WebCore
+
+#endif // DOMStringList_h
+
diff --git a/Source/core/dom/DOMStringList.idl b/Source/core/dom/DOMStringList.idl
new file mode 100644
index 0000000..5109dc6
--- /dev/null
+++ b/Source/core/dom/DOMStringList.idl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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.
+ */
+
+[
+    ImplementationLacksVTable
+] interface DOMStringList {
+    readonly attribute unsigned long length;
+    [TreatReturnedNullStringAs=Null] getter DOMString item([Default=Undefined] optional unsigned long index);
+    boolean contains([Default=Undefined] optional DOMString string);
+};
+
diff --git a/Source/core/dom/DOMStringMap.cpp b/Source/core/dom/DOMStringMap.cpp
new file mode 100644
index 0000000..b15e419
--- /dev/null
+++ b/Source/core/dom/DOMStringMap.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "core/dom/DOMStringMap.h"
+
+namespace WebCore {
+
+DOMStringMap::~DOMStringMap()
+{
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/DOMStringMap.h b/Source/core/dom/DOMStringMap.h
new file mode 100644
index 0000000..f731761
--- /dev/null
+++ b/Source/core/dom/DOMStringMap.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 DOMStringMap_h
+#define DOMStringMap_h
+
+#include "bindings/v8/ScriptWrappable.h"
+#include <wtf/Noncopyable.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Element;
+typedef int ExceptionCode;
+
+class DOMStringMap : public ScriptWrappable {
+    WTF_MAKE_NONCOPYABLE(DOMStringMap); WTF_MAKE_FAST_ALLOCATED;
+public:
+    virtual ~DOMStringMap();
+
+    virtual void ref() = 0;
+    virtual void deref() = 0;
+
+    virtual void getNames(Vector<String>&) = 0;
+    virtual String item(const String& name) = 0;
+    virtual bool contains(const String& name) = 0;
+    virtual void setItem(const String& name, const String& value, ExceptionCode&) = 0;
+    virtual void deleteItem(const String& name, ExceptionCode&) = 0;
+
+    virtual Element* element() = 0;
+
+protected:
+    DOMStringMap()
+    {
+        ScriptWrappable::init(this);
+    }
+};
+
+} // namespace WebCore
+
+#endif // DOMStringMap_h
diff --git a/Source/core/dom/DOMStringMap.idl b/Source/core/dom/DOMStringMap.idl
new file mode 100644
index 0000000..e200cc8
--- /dev/null
+++ b/Source/core/dom/DOMStringMap.idl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+[
+    GenerateIsReachable=ImplElementRoot,
+    CustomNamedGetter,
+    CustomDeleteProperty,
+    CustomEnumerateProperty,
+    CustomNamedSetter,
+    SkipVTableValidation
+] interface DOMStringMap {
+};
+
diff --git a/Source/core/dom/DOMTimeStamp.h b/Source/core/dom/DOMTimeStamp.h
new file mode 100644
index 0000000..ff61520
--- /dev/null
+++ b/Source/core/dom/DOMTimeStamp.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DOMTimeStamp_h
+#define DOMTimeStamp_h
+
+namespace WebCore {
+
+typedef unsigned long long DOMTimeStamp;
+
+inline DOMTimeStamp convertSecondsToDOMTimeStamp(double seconds)
+{
+    return static_cast<DOMTimeStamp>(seconds * 1000.0);
+}
+
+inline double convertDOMTimeStampToSeconds(DOMTimeStamp milliseconds)
+{
+    return milliseconds / 1000.0;
+}
+
+} // namespace WebCore
+
+#endif // DOMTimeStamp_h
diff --git a/Source/core/dom/DataTransferItem.cpp b/Source/core/dom/DataTransferItem.cpp
new file mode 100644
index 0000000..7d79f11
--- /dev/null
+++ b/Source/core/dom/DataTransferItem.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/DataTransferItem.h"
+
+namespace WebCore {
+
+const char DataTransferItem::kindString[] = "string";
+const char DataTransferItem::kindFile[] = "file";
+
+} // namespace WebCore
+
diff --git a/Source/core/dom/DataTransferItem.h b/Source/core/dom/DataTransferItem.h
new file mode 100644
index 0000000..b540c7d
--- /dev/null
+++ b/Source/core/dom/DataTransferItem.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DataTransferItem_h
+#define DataTransferItem_h
+
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class Blob;
+class File;
+class StringCallback;
+class ScriptExecutionContext;
+
+class DataTransferItem : public RefCounted<DataTransferItem> {
+public:
+    virtual ~DataTransferItem() { }
+
+    static const char kindString[];
+    static const char kindFile[];
+
+    virtual String kind() const = 0;
+    virtual String type() const = 0;
+
+    virtual void getAsString(PassRefPtr<StringCallback>) const = 0;
+    virtual PassRefPtr<Blob> getAsFile() const = 0;
+};
+
+} // namespace WebCore
+
+#endif // DataTransferItem_h
diff --git a/Source/core/dom/DataTransferItem.idl b/Source/core/dom/DataTransferItem.idl
new file mode 100644
index 0000000..227e5a5
--- /dev/null
+++ b/Source/core/dom/DataTransferItem.idl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    ImplementationLacksVTable
+] interface DataTransferItem {
+    readonly attribute DOMString kind;
+    readonly attribute DOMString type;
+
+    void getAsString([Default=Undefined] optional StringCallback callback);
+    Blob getAsFile();
+};
+
diff --git a/Source/core/dom/DataTransferItemList.h b/Source/core/dom/DataTransferItemList.h
new file mode 100644
index 0000000..fa12510
--- /dev/null
+++ b/Source/core/dom/DataTransferItemList.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DataTransferItemList_h
+#define DataTransferItemList_h
+
+#include "core/dom/DataTransferItem.h"
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class Clipboard;
+class File;
+
+typedef int ExceptionCode;
+
+class DataTransferItemList : public RefCounted<DataTransferItemList> {
+public:
+    virtual ~DataTransferItemList() { }
+
+    virtual size_t length() const = 0;
+    virtual PassRefPtr<DataTransferItem> item(unsigned long index) = 0;
+    virtual void deleteItem(unsigned long index, ExceptionCode&) = 0;
+    virtual void clear() = 0;
+    virtual void add(const String& data, const String& type, ExceptionCode&) = 0;
+    virtual void add(PassRefPtr<File>) = 0;
+};
+
+} // namespace WebCore
+
+#endif // DataTransferItemList_h
diff --git a/Source/core/dom/DataTransferItemList.idl b/Source/core/dom/DataTransferItemList.idl
new file mode 100644
index 0000000..0217784
--- /dev/null
+++ b/Source/core/dom/DataTransferItemList.idl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    ImplementationLacksVTable
+] interface DataTransferItemList {
+    readonly attribute long length;
+    getter DataTransferItem item([Default=Undefined] optional unsigned long index);
+
+    void clear();
+    void add(File? file);
+    [RaisesException] void add([Default=Undefined] optional DOMString data, 
+             [Default=Undefined] optional DOMString type);
+};
+
diff --git a/Source/core/dom/DatasetDOMStringMap.cpp b/Source/core/dom/DatasetDOMStringMap.cpp
new file mode 100644
index 0000000..c16bdf5
--- /dev/null
+++ b/Source/core/dom/DatasetDOMStringMap.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "core/dom/DatasetDOMStringMap.h"
+
+#include "core/dom/Attribute.h"
+#include "core/dom/Element.h"
+#include "core/dom/ExceptionCode.h"
+#include <wtf/ASCIICType.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+static bool isValidAttributeName(const String& name)
+{
+    if (!name.startsWith("data-"))
+        return false;
+
+    const UChar* characters = name.characters();
+    unsigned length = name.length();
+    for (unsigned i = 5; i < length; ++i) {
+        if (isASCIIUpper(characters[i]))
+            return false;
+    }
+
+    return true;
+}
+
+static String convertAttributeNameToPropertyName(const String& name)
+{
+    StringBuilder stringBuilder;
+
+    const UChar* characters = name.characters();
+    unsigned length = name.length();
+    for (unsigned i = 5; i < length; ++i) {
+        UChar character = characters[i];
+        if (character != '-')
+            stringBuilder.append(character);
+        else {
+            if ((i + 1 < length) && isASCIILower(characters[i + 1])) {
+                stringBuilder.append(toASCIIUpper(characters[i + 1]));
+                ++i;
+            } else
+                stringBuilder.append(character);
+        }
+    }
+
+    return stringBuilder.toString();
+}
+
+static bool propertyNameMatchesAttributeName(const String& propertyName, const String& attributeName)
+{
+    if (!attributeName.startsWith("data-"))
+        return false;
+
+    const UChar* property = propertyName.characters();
+    const UChar* attribute = attributeName.characters();
+    unsigned propertyLength = propertyName.length();
+    unsigned attributeLength = attributeName.length();
+   
+    unsigned a = 5;
+    unsigned p = 0;
+    bool wordBoundary = false;
+    while (a < attributeLength && p < propertyLength) {
+        if (attribute[a] == '-' && a + 1 < attributeLength && attribute[a + 1] != '-')
+            wordBoundary = true;
+        else {
+            if ((wordBoundary ? toASCIIUpper(attribute[a]) : attribute[a]) != property[p])
+                return false;
+            p++;
+            wordBoundary = false;
+        }
+        a++;
+    }
+
+    return (a == attributeLength && p == propertyLength);
+}
+
+static bool isValidPropertyName(const String& name)
+{
+    const UChar* characters = name.characters();
+    unsigned length = name.length();
+    for (unsigned i = 0; i < length; ++i) {
+        if (characters[i] == '-' && (i + 1 < length) && isASCIILower(characters[i + 1]))
+            return false;
+    }
+    return true;
+}
+
+static String convertPropertyNameToAttributeName(const String& name)
+{
+    StringBuilder builder;
+    builder.append("data-");
+
+    const UChar* characters = name.characters();
+    unsigned length = name.length();
+    for (unsigned i = 0; i < length; ++i) {
+        UChar character = characters[i];
+        if (isASCIIUpper(character)) {
+            builder.append('-');
+            builder.append(toASCIILower(character));
+        } else
+            builder.append(character);
+    }
+
+    return builder.toString();
+}
+
+void DatasetDOMStringMap::ref()
+{
+    m_element->ref();
+}
+
+void DatasetDOMStringMap::deref()
+{
+    m_element->deref();
+}
+
+void DatasetDOMStringMap::getNames(Vector<String>& names)
+{
+    if (!m_element->hasAttributes())
+        return;
+
+    unsigned length = m_element->attributeCount();
+    for (unsigned i = 0; i < length; i++) {
+        const Attribute* attribute = m_element->attributeItem(i);
+        if (isValidAttributeName(attribute->localName()))
+            names.append(convertAttributeNameToPropertyName(attribute->localName()));
+    }
+}
+
+String DatasetDOMStringMap::item(const String& name)
+{
+    if (!m_element->hasAttributes())
+        return String();
+
+    unsigned length = m_element->attributeCount();
+    for (unsigned i = 0; i < length; i++) {
+        const Attribute* attribute = m_element->attributeItem(i);
+        if (propertyNameMatchesAttributeName(name, attribute->localName()))
+            return attribute->value();
+    }
+
+    return String();
+}
+
+bool DatasetDOMStringMap::contains(const String& name)
+{
+    if (!m_element->hasAttributes())
+        return false;
+
+    unsigned length = m_element->attributeCount();
+    for (unsigned i = 0; i < length; i++) {
+        const Attribute* attribute = m_element->attributeItem(i);
+        if (propertyNameMatchesAttributeName(name, attribute->localName()))
+            return true;
+    }
+
+    return false;
+}
+
+void DatasetDOMStringMap::setItem(const String& name, const String& value, ExceptionCode& ec)
+{
+    if (!isValidPropertyName(name)) {
+        ec = SYNTAX_ERR;
+        return;
+    }
+
+    m_element->setAttribute(convertPropertyNameToAttributeName(name), value, ec);
+}
+
+void DatasetDOMStringMap::deleteItem(const String& name, ExceptionCode& ec)
+{
+    if (!isValidPropertyName(name)) {
+        ec = SYNTAX_ERR;
+        return;
+    }
+
+    m_element->removeAttribute(convertPropertyNameToAttributeName(name));
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/DatasetDOMStringMap.h b/Source/core/dom/DatasetDOMStringMap.h
new file mode 100644
index 0000000..8788b6e
--- /dev/null
+++ b/Source/core/dom/DatasetDOMStringMap.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 DatasetDOMStringMap_h
+#define DatasetDOMStringMap_h
+
+#include "core/dom/DOMStringMap.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class Element;
+
+class DatasetDOMStringMap : public DOMStringMap {
+public:
+    static PassOwnPtr<DatasetDOMStringMap> create(Element* element)
+    {
+        return adoptPtr(new DatasetDOMStringMap(element));
+    }
+
+    virtual void ref();
+    virtual void deref();
+
+    virtual void getNames(Vector<String>&);
+    virtual String item(const String& name);
+    virtual bool contains(const String& name);
+    virtual void setItem(const String& name, const String& value, ExceptionCode&);
+    virtual void deleteItem(const String& name, ExceptionCode&);
+
+    virtual Element* element() { return m_element; }
+
+private:
+    explicit DatasetDOMStringMap(Element* element)
+        : m_element(element)
+    {
+    }
+
+    Element* m_element;
+};
+
+} // namespace WebCore
+
+#endif // DatasetDOMStringMap_h
diff --git a/Source/core/dom/DecodedDataDocumentParser.cpp b/Source/core/dom/DecodedDataDocumentParser.cpp
new file mode 100644
index 0000000..9f25650
--- /dev/null
+++ b/Source/core/dom/DecodedDataDocumentParser.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 "core/dom/DecodedDataDocumentParser.h"
+
+#include "core/loader/DocumentWriter.h"
+#include "core/loader/TextResourceDecoder.h"
+#include "core/platform/text/SegmentedString.h"
+
+namespace WebCore {
+
+DecodedDataDocumentParser::DecodedDataDocumentParser(Document* document)
+    : DocumentParser(document)
+{
+}
+
+void DecodedDataDocumentParser::appendBytes(DocumentWriter* writer, const char* data, size_t length)
+{
+    if (!length)
+        return;
+
+    String decoded = writer->createDecoderIfNeeded()->decode(data, length);
+    if (decoded.isEmpty())
+        return;
+
+    writer->reportDataReceived();
+    append(decoded.releaseImpl());
+}
+
+void DecodedDataDocumentParser::flush(DocumentWriter* writer)
+{
+    String remainingData = writer->createDecoderIfNeeded()->flush();
+    if (remainingData.isEmpty())
+        return;
+
+    writer->reportDataReceived();
+    append(remainingData.releaseImpl());
+}
+
+};
diff --git a/Source/core/dom/DecodedDataDocumentParser.h b/Source/core/dom/DecodedDataDocumentParser.h
new file mode 100644
index 0000000..4e61a93
--- /dev/null
+++ b/Source/core/dom/DecodedDataDocumentParser.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 DecodedDataDocumentParser_h
+#define DecodedDataDocumentParser_h
+
+#include "core/dom/DocumentParser.h"
+
+namespace WebCore {
+
+class DecodedDataDocumentParser : public DocumentParser {
+public:
+    // Only used by the XMLDocumentParser to communicate back to
+    // XMLHttpRequest if the responseXML was well formed.
+    virtual bool wellFormed() const { return true; }
+
+protected:
+    explicit DecodedDataDocumentParser(Document*);
+
+private:
+    // append is used by DocumentWriter::replaceDocument.
+    virtual void append(PassRefPtr<StringImpl>) = 0;
+
+    // appendBytes and flush are used by DocumentWriter (the loader).
+    virtual void appendBytes(DocumentWriter*, const char* bytes, size_t length);
+    virtual void flush(DocumentWriter*);
+};
+
+}
+
+#endif // DecodedDataDocumentParser_h
diff --git a/Source/core/dom/DeviceOrientationClient.h b/Source/core/dom/DeviceOrientationClient.h
new file mode 100644
index 0000000..14de526
--- /dev/null
+++ b/Source/core/dom/DeviceOrientationClient.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ * Copyright (C) 2012 Samsung Electronics. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 DeviceOrientationClient_h
+#define DeviceOrientationClient_h
+
+#include "core/page/DeviceClient.h"
+
+namespace WebCore {
+
+class DeviceOrientationController;
+class DeviceOrientationData;
+class Page;
+
+class DeviceOrientationClient : public DeviceClient {
+public:
+    virtual ~DeviceOrientationClient() {}
+    virtual void setController(DeviceOrientationController*) = 0;
+    virtual DeviceOrientationData* lastOrientation() const = 0;
+    virtual void deviceOrientationControllerDestroyed() = 0;
+};
+
+void provideDeviceOrientationTo(Page*, DeviceOrientationClient*);
+
+} // namespace WebCore
+
+#endif // DeviceOrientationClient_h
diff --git a/Source/core/dom/DeviceOrientationController.cpp b/Source/core/dom/DeviceOrientationController.cpp
new file mode 100644
index 0000000..bc9df50
--- /dev/null
+++ b/Source/core/dom/DeviceOrientationController.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ * Copyright (C) 2012 Samsung Electronics. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 "core/dom/DeviceOrientationController.h"
+
+#include "core/dom/DeviceOrientationClient.h"
+#include "core/dom/DeviceOrientationData.h"
+#include "core/dom/DeviceOrientationEvent.h"
+#include "core/inspector/InspectorInstrumentation.h"
+
+namespace WebCore {
+
+DeviceOrientationController::DeviceOrientationController(Page* page, DeviceOrientationClient* client)
+    : DeviceController(client)
+    , m_page(page)
+{
+    ASSERT(m_client);
+    deviceOrientationClient()->setController(this);
+}
+
+PassOwnPtr<DeviceOrientationController> DeviceOrientationController::create(Page* page, DeviceOrientationClient* client)
+{
+    return adoptPtr(new DeviceOrientationController(page, client));
+}
+
+void DeviceOrientationController::didChangeDeviceOrientation(DeviceOrientationData* orientation)
+{
+    orientation = InspectorInstrumentation::overrideDeviceOrientation(m_page, orientation);
+    dispatchDeviceEvent(DeviceOrientationEvent::create(eventNames().deviceorientationEvent, orientation));
+}
+
+DeviceOrientationClient* DeviceOrientationController::deviceOrientationClient()
+{
+    return static_cast<DeviceOrientationClient*>(m_client);
+}
+
+bool DeviceOrientationController::hasLastData()
+{
+    return deviceOrientationClient()->lastOrientation();
+}
+
+PassRefPtr<Event> DeviceOrientationController::getLastEvent()
+{
+    return DeviceOrientationEvent::create(eventNames().deviceorientationEvent, deviceOrientationClient()->lastOrientation());
+}
+
+const char* DeviceOrientationController::supplementName()
+{
+    return "DeviceOrientationController";
+}
+
+DeviceOrientationController* DeviceOrientationController::from(Page* page)
+{
+    return static_cast<DeviceOrientationController*>(Supplement<Page>::from(page, supplementName()));
+}
+
+bool DeviceOrientationController::isActiveAt(Page* page)
+{
+    if (DeviceOrientationController* self = DeviceOrientationController::from(page))
+        return self->isActive();
+    return false;
+}
+
+void provideDeviceOrientationTo(Page* page, DeviceOrientationClient* client)
+{
+    DeviceOrientationController::provideTo(page, DeviceOrientationController::supplementName(), DeviceOrientationController::create(page, client));
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/DeviceOrientationController.h b/Source/core/dom/DeviceOrientationController.h
new file mode 100644
index 0000000..922a54d
--- /dev/null
+++ b/Source/core/dom/DeviceOrientationController.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ * Copyright (C) 2012 Samsung Electronics. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 DeviceOrientationController_h
+#define DeviceOrientationController_h
+
+#include "core/page/DeviceController.h"
+#include <wtf/HashCountedSet.h>
+
+namespace WebCore {
+
+class DeviceOrientationClient;
+class DeviceOrientationData;
+
+class DeviceOrientationController : public DeviceController {
+public:
+    ~DeviceOrientationController() { };
+
+    static PassOwnPtr<DeviceOrientationController> create(Page*, DeviceOrientationClient*);
+
+    void didChangeDeviceOrientation(DeviceOrientationData*);
+    DeviceOrientationClient* deviceOrientationClient();
+
+    virtual bool hasLastData() OVERRIDE;
+    virtual PassRefPtr<Event> getLastEvent() OVERRIDE;
+
+    static const char* supplementName();
+    static DeviceOrientationController* from(Page*);
+    static bool isActiveAt(Page*);
+
+private:
+    DeviceOrientationController(Page*, DeviceOrientationClient*);
+
+    Page* m_page;
+};
+
+} // namespace WebCore
+
+#endif // DeviceOrientationController_h
diff --git a/Source/core/dom/DeviceOrientationData.cpp b/Source/core/dom/DeviceOrientationData.cpp
new file mode 100644
index 0000000..781a466
--- /dev/null
+++ b/Source/core/dom/DeviceOrientationData.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 "core/dom/DeviceOrientationData.h"
+
+namespace WebCore {
+
+PassRefPtr<DeviceOrientationData> DeviceOrientationData::create()
+{
+    return adoptRef(new DeviceOrientationData);
+}
+
+PassRefPtr<DeviceOrientationData> DeviceOrientationData::create(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma, bool canProvideAbsolute, bool absolute)
+{
+    return adoptRef(new DeviceOrientationData(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma, canProvideAbsolute, absolute));
+}
+
+
+DeviceOrientationData::DeviceOrientationData()
+    : m_canProvideAlpha(false)
+    , m_canProvideBeta(false)
+    , m_canProvideGamma(false)
+    , m_canProvideAbsolute(false)
+    , m_alpha(0)
+    , m_beta(0)
+    , m_gamma(0)
+    , m_absolute(false)
+{
+}
+
+DeviceOrientationData::DeviceOrientationData(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma, bool canProvideAbsolute, bool absolute)
+    : m_canProvideAlpha(canProvideAlpha)
+    , m_canProvideBeta(canProvideBeta)
+    , m_canProvideGamma(canProvideGamma)
+    , m_canProvideAbsolute(canProvideAbsolute)
+    , m_alpha(alpha)
+    , m_beta(beta)
+    , m_gamma(gamma)
+    , m_absolute(absolute)
+{
+}
+
+double DeviceOrientationData::alpha() const
+{
+    return m_alpha;
+}
+
+double DeviceOrientationData::beta() const
+{
+    return m_beta;
+}
+
+double DeviceOrientationData::gamma() const
+{
+    return m_gamma;
+}
+
+bool DeviceOrientationData::absolute() const
+{
+    return m_absolute;
+}
+
+bool DeviceOrientationData::canProvideAlpha() const
+{
+    return m_canProvideAlpha;
+}
+
+bool DeviceOrientationData::canProvideBeta() const
+{
+    return m_canProvideBeta;
+}
+
+bool DeviceOrientationData::canProvideGamma() const
+{
+    return m_canProvideGamma;
+}
+
+bool DeviceOrientationData::canProvideAbsolute() const
+{
+    return m_canProvideAbsolute;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/DeviceOrientationData.h b/Source/core/dom/DeviceOrientationData.h
new file mode 100644
index 0000000..1df9b65
--- /dev/null
+++ b/Source/core/dom/DeviceOrientationData.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 DeviceOrientationData_h
+#define DeviceOrientationData_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class DeviceOrientationData : public RefCounted<DeviceOrientationData> {
+public:
+    static PassRefPtr<DeviceOrientationData> create();
+    static PassRefPtr<DeviceOrientationData> create(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma, bool canProvideAbsolute = false, bool absolute = false);
+
+    double alpha() const;
+    double beta() const;
+    double gamma() const;
+    bool absolute() const;
+    bool canProvideAlpha() const;
+    bool canProvideBeta() const;
+    bool canProvideGamma() const;
+    bool canProvideAbsolute() const;
+
+private:
+    DeviceOrientationData();
+    DeviceOrientationData(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma, bool canProvideAbsolute, bool absolute);
+
+    bool m_canProvideAlpha;
+    bool m_canProvideBeta;
+    bool m_canProvideGamma;
+    bool m_canProvideAbsolute;
+    double m_alpha;
+    double m_beta;
+    double m_gamma;
+    bool m_absolute;
+};
+
+} // namespace WebCore
+
+#endif // DeviceOrientationData_h
diff --git a/Source/core/dom/DeviceOrientationEvent.cpp b/Source/core/dom/DeviceOrientationEvent.cpp
new file mode 100644
index 0000000..5875edc
--- /dev/null
+++ b/Source/core/dom/DeviceOrientationEvent.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 "core/dom/DeviceOrientationEvent.h"
+
+#include "core/dom/DeviceOrientationData.h"
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+DeviceOrientationEvent::~DeviceOrientationEvent()
+{
+}
+
+DeviceOrientationEvent::DeviceOrientationEvent()
+    : m_orientation(DeviceOrientationData::create())
+{
+    ScriptWrappable::init(this);
+}
+
+DeviceOrientationEvent::DeviceOrientationEvent(const AtomicString& eventType, DeviceOrientationData* orientation)
+    : Event(eventType, false, false) // Can't bubble, not cancelable
+    , m_orientation(orientation)
+{
+    ScriptWrappable::init(this);
+}
+
+void DeviceOrientationEvent::initDeviceOrientationEvent(const AtomicString& type, bool bubbles, bool cancelable, DeviceOrientationData* orientation)
+{
+    if (dispatched())
+        return;
+
+    initEvent(type, bubbles, cancelable);
+    m_orientation = orientation;
+}
+
+double DeviceOrientationEvent::alpha(bool& isNull) const
+{
+    if (m_orientation->canProvideAlpha())
+        return m_orientation->alpha();
+
+    isNull = true;
+    return 0;
+}
+
+double DeviceOrientationEvent::beta(bool& isNull) const
+{
+    if (m_orientation->canProvideBeta())
+        return m_orientation->beta();
+
+    isNull = true;
+    return 0;
+}
+
+double DeviceOrientationEvent::gamma(bool& isNull) const
+{
+    if (m_orientation->canProvideGamma())
+        return m_orientation->gamma();
+
+    isNull = true;
+    return 0;
+}
+
+bool DeviceOrientationEvent::absolute(bool& isNull) const
+{
+    if (m_orientation->canProvideAbsolute())
+        return m_orientation->absolute();
+
+    isNull = true;
+    return 0;
+}
+
+const AtomicString& DeviceOrientationEvent::interfaceName() const
+{
+    return eventNames().interfaceForDeviceOrientationEvent;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/DeviceOrientationEvent.h b/Source/core/dom/DeviceOrientationEvent.h
new file mode 100644
index 0000000..dc55e67
--- /dev/null
+++ b/Source/core/dom/DeviceOrientationEvent.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 DeviceOrientationEvent_h
+#define DeviceOrientationEvent_h
+
+#include "core/dom/Event.h"
+
+namespace WebCore {
+
+class DeviceOrientationData;
+
+class DeviceOrientationEvent : public Event {
+public:
+    ~DeviceOrientationEvent();
+    static PassRefPtr<DeviceOrientationEvent> create()
+    {
+        return adoptRef(new DeviceOrientationEvent);
+    }
+    static PassRefPtr<DeviceOrientationEvent> create(const AtomicString& eventType, DeviceOrientationData* orientation)
+    {
+        return adoptRef(new DeviceOrientationEvent(eventType, orientation));
+    }
+
+    void initDeviceOrientationEvent(const AtomicString& type, bool bubbles, bool cancelable, DeviceOrientationData*);
+
+    DeviceOrientationData* orientation() const { return m_orientation.get(); }
+
+    double alpha(bool& isNull) const;
+    double beta(bool& isNull) const;
+    double gamma(bool& isNull) const;
+    bool absolute(bool& isNull) const;
+
+    virtual const AtomicString& interfaceName() const;
+
+private:
+    DeviceOrientationEvent();
+    DeviceOrientationEvent(const AtomicString& eventType, DeviceOrientationData*);
+
+    RefPtr<DeviceOrientationData> m_orientation;
+};
+
+} // namespace WebCore
+
+#endif // DeviceOrientationEvent_h
diff --git a/Source/core/dom/DeviceOrientationEvent.idl b/Source/core/dom/DeviceOrientationEvent.idl
new file mode 100644
index 0000000..286f2bb
--- /dev/null
+++ b/Source/core/dom/DeviceOrientationEvent.idl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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.
+ */
+
+interface DeviceOrientationEvent : Event {
+    readonly attribute double? alpha;
+    readonly attribute double? beta;
+    readonly attribute double? gamma;
+    readonly attribute boolean? absolute;
+    [Custom] void initDeviceOrientationEvent([Default=Undefined] optional DOMString type, 
+                                             [Default=Undefined] optional boolean bubbles, 
+                                             [Default=Undefined] optional boolean cancelable, 
+                                             [Default=Undefined] optional double alpha, 
+                                             [Default=Undefined] optional double beta, 
+                                             [Default=Undefined] optional double gamma,
+                                             [Default=Undefined] optional boolean absolute);
+};
diff --git a/Source/core/dom/Document.cpp b/Source/core/dom/Document.cpp
new file mode 100644
index 0000000..d2102fb
--- /dev/null
+++ b/Source/core/dom/Document.cpp
@@ -0,0 +1,5663 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/Document.h"
+
+#include "CSSValueKeywords.h"
+#include "HTMLElementFactory.h"
+#include "HTMLNames.h"
+#include "RuntimeEnabledFeatures.h"
+#include "XMLNSNames.h"
+#include "XMLNames.h"
+#include "bindings/v8/Dictionary.h"
+#include "bindings/v8/ScriptController.h"
+#include "bindings/v8/ScriptEventListener.h"
+#include "core/accessibility/AXObjectCache.h"
+#include "core/css/CSSParser.h"
+#include "core/css/CSSStyleDeclaration.h"
+#include "core/css/CSSStyleSheet.h"
+#include "core/css/FontLoader.h"
+#include "core/css/MediaQueryList.h"
+#include "core/css/MediaQueryMatcher.h"
+#include "core/css/StylePropertySet.h"
+#include "core/css/StyleResolver.h"
+#include "core/css/StyleSheetContents.h"
+#include "core/css/StyleSheetList.h"
+#include "core/dom/Attr.h"
+#include "core/dom/Attribute.h"
+#include "core/dom/CDATASection.h"
+#include "core/dom/Comment.h"
+#include "core/dom/ContextFeatures.h"
+#include "core/dom/CustomElementConstructor.h"
+#include "core/dom/CustomElementRegistry.h"
+#include "core/dom/DOMImplementation.h"
+#include "core/dom/DOMNamedFlowCollection.h"
+#include "core/dom/DocumentEventQueue.h"
+#include "core/dom/DocumentFragment.h"
+#include "core/dom/DocumentMarkerController.h"
+#include "core/dom/DocumentSharedObjectPool.h"
+#include "core/dom/DocumentStyleSheetCollection.h"
+#include "core/dom/DocumentType.h"
+#include "core/dom/Element.h"
+#include "core/dom/ElementShadow.h"
+#include "core/dom/EntityReference.h"
+#include "core/dom/Event.h"
+#include "core/dom/EventFactory.h"
+#include "core/dom/EventListener.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/ExceptionCodePlaceholder.h"
+#include "core/dom/HashChangeEvent.h"
+#include "core/dom/NameNodeList.h"
+#include "core/dom/NamedFlowCollection.h"
+#include "core/dom/NodeFilter.h"
+#include "core/dom/NodeIterator.h"
+#include "core/dom/NodeRareData.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/dom/NodeWithIndex.h"
+#include "core/dom/PageTransitionEvent.h"
+#include "core/dom/PopStateEvent.h"
+#include "core/dom/ProcessingInstruction.h"
+#include "core/dom/QualifiedName.h"
+#include "core/dom/RegisteredEventListener.h"
+#include "core/dom/RequestAnimationFrameCallback.h"
+#include "core/dom/ScopedEventQueue.h"
+#include "core/dom/ScriptElement.h"
+#include "core/dom/ScriptRunner.h"
+#include "core/dom/ScriptedAnimationController.h"
+#include "core/dom/SelectorQuery.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/dom/TouchList.h"
+#include "core/dom/TransformSource.h"
+#include "core/dom/TreeWalker.h"
+#include "core/dom/UserActionElementSet.h"
+#include "core/dom/VisitedLinkState.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/editing/Editor.h"
+#include "core/editing/FrameSelection.h"
+#include "core/editing/htmlediting.h"
+#include "core/html/FormController.h"
+#include "core/html/HTMLAllCollection.h"
+#include "core/html/HTMLAnchorElement.h"
+#include "core/html/HTMLBodyElement.h"
+#include "core/html/HTMLCanvasElement.h"
+#include "core/html/HTMLCollection.h"
+#include "core/html/HTMLDocument.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/html/HTMLHeadElement.h"
+#include "core/html/HTMLIFrameElement.h"
+#include "core/html/HTMLLinkElement.h"
+#include "core/html/HTMLMapElement.h"
+#include "core/html/HTMLNameCollection.h"
+#include "core/html/HTMLStyleElement.h"
+#include "core/html/HTMLTitleElement.h"
+#include "core/html/PluginDocument.h"
+#include "core/html/parser/HTMLParserIdioms.h"
+#include "core/html/parser/NestingLevelIncrementer.h"
+#include "core/inspector/InspectorCounters.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/ScriptCallStack.h"
+#include "core/loader/CookieJar.h"
+#include "core/loader/DocumentLoader.h"
+#include "core/loader/FrameLoader.h"
+#include "core/loader/FrameLoaderClient.h"
+#include "core/loader/ImageLoader.h"
+#include "core/loader/Prerenderer.h"
+#include "core/loader/ResourceLoader.h"
+#include "core/loader/TextResourceDecoder.h"
+#include "core/loader/cache/CachedCSSStyleSheet.h"
+#include "core/loader/cache/CachedResourceLoader.h"
+#include "core/page/Chrome.h"
+#include "core/page/ChromeClient.h"
+#include "core/page/ContentSecurityPolicy.h"
+#include "core/page/DOMSecurityPolicy.h"
+#include "core/page/DOMSelection.h"
+#include "core/page/DOMWindow.h"
+#include "core/page/EventHandler.h"
+#include "core/page/FocusController.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameTree.h"
+#include "core/page/FrameView.h"
+#include "core/page/History.h"
+#include "core/page/MouseEventWithHitTestResults.h"
+#include "core/page/Page.h"
+#include "core/page/PageConsole.h"
+#include "core/page/PageGroup.h"
+#include "core/page/PointerLockController.h"
+#include "core/page/SecurityOrigin.h"
+#include "core/page/SecurityPolicy.h"
+#include "core/page/Settings.h"
+#include "core/page/UserContentURLPattern.h"
+#include "core/page/animation/AnimationController.h"
+#include "core/page/scrolling/ScrollingCoordinator.h"
+#include "core/platform/DateComponents.h"
+#include "core/platform/HistogramSupport.h"
+#include "core/platform/Language.h"
+#include "core/platform/Logging.h"
+#include "core/platform/PlatformKeyboardEvent.h"
+#include "core/platform/SchemeRegistry.h"
+#include "core/platform/Timer.h"
+#include "core/platform/chromium/TraceEvent.h"
+#include "core/platform/network/HTTPParsers.h"
+#include "core/platform/text/PlatformLocale.h"
+#include "core/platform/text/SegmentedString.h"
+#include "core/rendering/FlowThreadController.h"
+#include "core/rendering/HitTestRequest.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderArena.h"
+#include "core/rendering/RenderFullScreen.h"
+#include "core/rendering/RenderLayerCompositor.h"
+#include "core/rendering/RenderNamedFlowThread.h"
+#include "core/rendering/RenderTextControl.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/RenderWidget.h"
+#include "core/rendering/TextAutosizer.h"
+#include "core/workers/SharedWorkerRepository.h"
+#include "core/xml/XMLHttpRequest.h"
+#include "core/xml/XPathEvaluator.h"
+#include "core/xml/XPathExpression.h"
+#include "core/xml/XPathNSResolver.h"
+#include "core/xml/XPathResult.h"
+#include "core/xml/XSLTProcessor.h"
+#include "core/xml/parser/XMLDocumentParser.h"
+#include "modules/geolocation/GeolocationController.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/HashFunctions.h>
+#include <wtf/MainThread.h>
+#include <wtf/MemoryInstrumentationHashCountedSet.h>
+#include <wtf/MemoryInstrumentationHashMap.h>
+#include <wtf/MemoryInstrumentationHashSet.h>
+#include <wtf/MemoryInstrumentationVector.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/text/StringBuffer.h>
+
+#if ENABLE(SVG)
+#include "SVGElementFactory.h"
+#include "SVGNames.h"
+#include "core/svg/SVGDocumentExtensions.h"
+#include "core/svg/SVGSVGElement.h"
+#include "core/svg/SVGStyleElement.h"
+#endif
+
+#include "core/page/CaptionUserPreferences.h"
+
+using namespace std;
+using namespace WTF;
+using namespace Unicode;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+// #define INSTRUMENT_LAYOUT_SCHEDULING 1
+
+static const double cDefaultIncrementalRenderingSuppressionTimeoutInSeconds = 5;
+
+static const unsigned cMaxWriteRecursionDepth = 21;
+
+// This amount of time must have elapsed before we will even consider scheduling a layout without a delay.
+// FIXME: For faster machines this value can really be lowered to 200.  250 is adequate, but a little high
+// for dual G5s. :)
+static const int cLayoutScheduleThreshold = 250;
+
+// DOM Level 2 says (letters added):
+//
+// a) Name start characters must have one of the categories Ll, Lu, Lo, Lt, Nl.
+// b) Name characters other than Name-start characters must have one of the categories Mc, Me, Mn, Lm, or Nd.
+// c) Characters in the compatibility area (i.e. with character code greater than #xF900 and less than #xFFFE) are not allowed in XML names.
+// d) Characters which have a font or compatibility decomposition (i.e. those with a "compatibility formatting tag" in field 5 of the database -- marked by field 5 beginning with a "<") are not allowed.
+// e) The following characters are treated as name-start characters rather than name characters, because the property file classifies them as Alphabetic: [#x02BB-#x02C1], #x0559, #x06E5, #x06E6.
+// f) Characters #x20DD-#x20E0 are excluded (in accordance with Unicode, section 5.14).
+// g) Character #x00B7 is classified as an extender, because the property list so identifies it.
+// h) Character #x0387 is added as a name character, because #x00B7 is its canonical equivalent.
+// i) Characters ':' and '_' are allowed as name-start characters.
+// j) Characters '-' and '.' are allowed as name characters.
+//
+// It also contains complete tables. If we decide it's better, we could include those instead of the following code.
+
+static inline bool isValidNameStart(UChar32 c)
+{
+    // rule (e) above
+    if ((c >= 0x02BB && c <= 0x02C1) || c == 0x559 || c == 0x6E5 || c == 0x6E6)
+        return true;
+
+    // rule (i) above
+    if (c == ':' || c == '_')
+        return true;
+
+    // rules (a) and (f) above
+    const uint32_t nameStartMask = Letter_Lowercase | Letter_Uppercase | Letter_Other | Letter_Titlecase | Number_Letter;
+    if (!(Unicode::category(c) & nameStartMask))
+        return false;
+
+    // rule (c) above
+    if (c >= 0xF900 && c < 0xFFFE)
+        return false;
+
+    // rule (d) above
+    DecompositionType decompType = decompositionType(c);
+    if (decompType == DecompositionFont || decompType == DecompositionCompat)
+        return false;
+
+    return true;
+}
+
+static inline bool isValidNamePart(UChar32 c)
+{
+    // rules (a), (e), and (i) above
+    if (isValidNameStart(c))
+        return true;
+
+    // rules (g) and (h) above
+    if (c == 0x00B7 || c == 0x0387)
+        return true;
+
+    // rule (j) above
+    if (c == '-' || c == '.')
+        return true;
+
+    // rules (b) and (f) above
+    const uint32_t otherNamePartMask = Mark_NonSpacing | Mark_Enclosing | Mark_SpacingCombining | Letter_Modifier | Number_DecimalDigit;
+    if (!(Unicode::category(c) & otherNamePartMask))
+        return false;
+
+    // rule (c) above
+    if (c >= 0xF900 && c < 0xFFFE)
+        return false;
+
+    // rule (d) above
+    DecompositionType decompType = decompositionType(c);
+    if (decompType == DecompositionFont || decompType == DecompositionCompat)
+        return false;
+
+    return true;
+}
+
+static bool shouldInheritSecurityOriginFromOwner(const KURL& url)
+{
+    // http://www.whatwg.org/specs/web-apps/current-work/#origin-0
+    //
+    // If a Document has the address "about:blank"
+    //     The origin of the Document is the origin it was assigned when its browsing context was created.
+    //
+    // Note: We generalize this to all "blank" URLs and invalid URLs because we
+    // treat all of these URLs as about:blank.
+    //
+    return url.isEmpty() || url.isBlankURL();
+}
+
+static Widget* widgetForNode(Node* focusedNode)
+{
+    if (!focusedNode)
+        return 0;
+    RenderObject* renderer = focusedNode->renderer();
+    if (!renderer || !renderer->isWidget())
+        return 0;
+    return toRenderWidget(renderer)->widget();
+}
+
+static bool acceptsEditingFocus(Node* node)
+{
+    ASSERT(node);
+    ASSERT(node->rendererIsEditable());
+
+    Node* root = node->rootEditableElement();
+    Frame* frame = node->document()->frame();
+    if (!frame || !root)
+        return false;
+
+    return frame->editor()->shouldBeginEditing(rangeOfContents(root).get());
+}
+
+static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame* targetFrame)
+{
+    // targetFrame can be 0 when we're trying to navigate a top-level frame
+    // that has a 0 opener.
+    if (!targetFrame)
+        return false;
+
+    const bool isLocalActiveOrigin = activeSecurityOrigin->isLocal();
+    for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree()->parent()) {
+        Document* ancestorDocument = ancestorFrame->document();
+        // FIXME: Should be an ASSERT? Frames should alway have documents.
+        if (!ancestorDocument)
+            return true;
+
+        const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securityOrigin();
+        if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin))
+            return true;
+
+        // Allow file URL descendant navigation even when allowFileAccessFromFileURLs is false.
+        // FIXME: It's a bit strange to special-case local origins here. Should we be doing
+        // something more general instead?
+        if (isLocalActiveOrigin && ancestorSecurityOrigin->isLocal())
+            return true;
+    }
+
+    return false;
+}
+
+static void printNavigationErrorMessage(Frame* frame, const KURL& activeURL, const char* reason)
+{
+    String message = "Unsafe JavaScript attempt to initiate navigation for frame with URL '" + frame->document()->url().string() + "' from frame with URL '" + activeURL.string() + "'. " + reason + "\n";
+
+    // FIXME: should we print to the console of the document performing the navigation instead?
+    frame->document()->domWindow()->printErrorMessage(message);
+}
+
+uint64_t Document::s_globalTreeVersion = 0;
+
+Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
+    : ContainerNode(0, CreateDocument)
+    , TreeScope(this)
+    , m_styleResolverThrowawayTimer(this, &Document::styleResolverThrowawayTimerFired)
+    , m_lastStyleResolverAccessTime(0)
+    , m_activeParserCount(0)
+    , m_contextFeatures(ContextFeatures::defaultSwitch())
+    , m_compatibilityMode(NoQuirksMode)
+    , m_compatibilityModeLocked(false)
+    , m_domTreeVersion(++s_globalTreeVersion)
+    , m_mutationObserverTypes(0)
+    , m_styleSheetCollection(DocumentStyleSheetCollection::create(this))
+    , m_visitedLinkState(VisitedLinkState::create(this))
+    , m_readyState(Complete)
+    , m_styleRecalcTimer(this, &Document::styleRecalcTimerFired)
+    , m_pendingStyleRecalcShouldForce(false)
+    , m_frameElementsShouldIgnoreScrolling(false)
+    , m_containsValidityStyleRules(false)
+    , m_updateFocusAppearanceRestoresSelection(false)
+    , m_ignoreDestructiveWriteCount(0)
+    , m_titleSetExplicitly(false)
+    , m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired)
+    , m_loadEventFinished(false)
+    , m_startTime(currentTime())
+    , m_overMinimumLayoutThreshold(false)
+    , m_scriptRunner(ScriptRunner::create(this))
+    , m_xmlVersion("1.0")
+    , m_xmlStandalone(StandaloneUnspecified)
+    , m_hasXMLDeclaration(0)
+    , m_designMode(inherit)
+    , m_hasAnnotatedRegions(false)
+    , m_annotatedRegionsDirty(false)
+    , m_createRenderers(true)
+    , m_accessKeyMapValid(false)
+    , m_useSecureKeyboardEntryWhenActive(false)
+    , m_isXHTML(isXHTML)
+    , m_isHTML(isHTML)
+    , m_isViewSource(false)
+    , m_sawElementsInKnownNamespaces(false)
+    , m_isSrcdocDocument(false)
+    , m_renderer(0)
+    , m_eventQueue(DocumentEventQueue::create(this))
+    , m_weakFactory(this)
+    , m_idAttributeName(idAttr)
+    , m_areKeysEnabledInFullScreen(0)
+    , m_fullScreenRenderer(0)
+    , m_fullScreenChangeDelayTimer(this, &Document::fullScreenChangeDelayTimerFired)
+    , m_isAnimatingFullScreen(false)
+    , m_loadEventDelayCount(0)
+    , m_loadEventDelayTimer(this, &Document::loadEventDelayTimerFired)
+    , m_referrerPolicy(ReferrerPolicyDefault)
+    , m_directionSetOnDocumentElement(false)
+    , m_writingModeSetOnDocumentElement(false)
+    , m_writeRecursionIsTooDeep(false)
+    , m_writeRecursionDepth(0)
+    , m_wheelEventHandlerCount(0)
+    , m_lastHandledUserGestureTimestamp(0)
+    , m_pendingTasksTimer(this, &Document::pendingTasksTimerFired)
+    , m_scheduledTasksAreSuspended(false)
+    , m_sharedObjectPoolClearTimer(this, &Document::sharedObjectPoolClearTimerFired)
+#ifndef NDEBUG
+    , m_didDispatchViewportPropertiesChanged(false)
+#endif
+    , m_templateDocumentHost(0)
+    , m_fontloader(0)
+    , m_didAssociateFormControlsTimer(this, &Document::didAssociateFormControlsTimerFired)
+{
+    ScriptWrappable::init(this);
+    m_printing = false;
+    m_paginatedForScreen = false;
+
+    m_ignoreAutofocus = false;
+
+    m_frame = frame;
+    if (m_frame)
+        provideContextFeaturesToDocumentFrom(this, m_frame->page());
+
+    // We depend on the url getting immediately set in subframes, but we
+    // also depend on the url NOT getting immediately set in opened windows.
+    // See fast/dom/early-frame-url.html
+    // and fast/dom/location-new-window-no-crash.html, respectively.
+    // FIXME: Can/should we unify this behavior?
+    if ((frame && frame->ownerElement()) || !url.isEmpty())
+        setURL(url);
+
+    m_markers = adoptPtr(new DocumentMarkerController);
+
+    if (m_frame)
+        m_cachedResourceLoader = m_frame->loader()->activeDocumentLoader()->cachedResourceLoader();
+    if (!m_cachedResourceLoader)
+        m_cachedResourceLoader = CachedResourceLoader::create(0);
+    m_cachedResourceLoader->setDocument(this);
+
+    m_prerenderer = Prerenderer::create(this);
+    m_textAutosizer = TextAutosizer::create(this);
+    m_visuallyOrdered = false;
+    m_bParsing = false;
+    m_wellFormed = false;
+
+    m_textColor = Color::black;
+    m_listenerTypes = 0;
+    m_inStyleRecalc = false;
+    m_closeAfterStyleRecalc = false;
+
+    m_gotoAnchorNeededAfterStylesheetsLoad = false;
+
+    m_didCalculateStyleResolver = false;
+    m_ignorePendingStylesheets = false;
+    m_needsNotifyRemoveAllPendingStylesheet = false;
+    m_hasNodesWithPlaceholderStyle = false;
+    m_pendingSheetLayout = NoLayoutWithPendingSheets;
+
+    m_cssTarget = 0;
+
+    resetLinkColor();
+    resetVisitedLinkColor();
+    resetActiveLinkColor();
+
+    m_processingLoadEvent = false;
+
+    initSecurityContext();
+    initDNSPrefetch();
+
+    static int docID = 0;
+    m_docID = docID++;
+
+    for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_nodeListCounts); i++)
+        m_nodeListCounts[i] = 0;
+
+    InspectorCounters::incrementCounter(InspectorCounters::DocumentCounter);
+}
+
+static void histogramMutationEventUsage(const unsigned short& listenerTypes)
+{
+    HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMSubtreeModified", static_cast<bool>(listenerTypes & Document::DOMSUBTREEMODIFIED_LISTENER), 2);
+    HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeInserted", static_cast<bool>(listenerTypes & Document::DOMNODEINSERTED_LISTENER), 2);
+    HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeRemoved", static_cast<bool>(listenerTypes & Document::DOMNODEREMOVED_LISTENER), 2);
+    HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeRemovedFromDocument", static_cast<bool>(listenerTypes & Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER), 2);
+    HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeInsertedIntoDocument", static_cast<bool>(listenerTypes & Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER), 2);
+    HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMCharacterDataModified", static_cast<bool>(listenerTypes & Document::DOMCHARACTERDATAMODIFIED_LISTENER), 2);
+}
+
+static bool isAttributeOnAllOwners(const WebCore::QualifiedName& attribute, const WebCore::QualifiedName& prefixedAttribute, const HTMLFrameOwnerElement* owner)
+{
+    if (!owner)
+        return true;
+    do {
+        if (!(owner->hasAttribute(attribute) || owner->hasAttribute(prefixedAttribute)))
+            return false;
+    } while ((owner = owner->document()->ownerElement()));
+    return true;
+}
+
+Document::~Document()
+{
+    ASSERT(!renderer());
+    ASSERT(m_ranges.isEmpty());
+    ASSERT(!m_styleRecalcTimer.isActive());
+    ASSERT(!m_parentTreeScope);
+    ASSERT(!hasGuardRefCount());
+
+    if (m_templateDocument)
+        m_templateDocument->setTemplateDocumentHost(0); // balanced in templateDocument().
+
+    if (Document* ownerDocument = this->ownerDocument())
+        ownerDocument->didRemoveEventTargetNode(this);
+    // FIXME: Should we reset m_domWindow when we detach from the Frame?
+    if (m_domWindow)
+        m_domWindow->reset();
+
+    m_scriptRunner.clear();
+
+    histogramMutationEventUsage(m_listenerTypes);
+
+    removeAllEventListeners();
+
+    // 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
+    // has a reference to the Document.  If you hit this ASSERT, then that
+    // assumption is wrong.  DocumentParser::detach() should ensure that even
+    // if the DocumentParser outlives the Document it won't cause badness.
+    ASSERT(!m_parser || m_parser->refCount() == 1);
+    detachParser();
+
+    m_renderArena.clear();
+
+    if (this == topDocument())
+        clearAXObjectCache();
+
+    m_decoder = 0;
+
+    if (m_styleSheetList)
+        m_styleSheetList->detachFromDocument();
+
+    m_styleSheetCollection.clear();
+
+    if (m_elemSheet)
+        m_elemSheet->clearOwnerNode();
+
+    clearStyleResolver(); // We need to destory CSSFontSelector before destroying m_cachedResourceLoader.
+
+    // It's possible for multiple Documents to end up referencing the same CachedResourceLoader (e.g., SVGImages
+    // load the initial empty document and the SVGDocument with the same DocumentLoader).
+    if (m_cachedResourceLoader->document() == this)
+        m_cachedResourceLoader->setDocument(0);
+    m_cachedResourceLoader.clear();
+
+    // We must call clearRareData() here since a Document class inherits TreeScope
+    // as well as Node. See a comment on TreeScope.h for the reason.
+    if (hasRareData())
+        clearRareData();
+
+    ASSERT(!m_listsInvalidatedAtDocument.size());
+
+    for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_nodeListCounts); i++)
+        ASSERT(!m_nodeListCounts[i]);
+
+    clearDocumentScope();
+
+    InspectorCounters::decrementCounter(InspectorCounters::DocumentCounter);
+}
+
+void Document::dispose()
+{
+    ASSERT(!m_deletionHasBegun);
+    // 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_activeElement = 0;
+    m_titleElement = 0;
+    m_documentElement = 0;
+    m_contextFeatures = ContextFeatures::defaultSwitch();
+    m_userActionElements.documentDidRemoveLastRef();
+    m_fullScreenElement = 0;
+    m_fullScreenElementStack.clear();
+
+    detachParser();
+
+    m_registry.clear();
+
+    // removeDetachedChildren() doesn't always unregister IDs,
+    // so tear down scope information upfront to avoid having stale references in the map.
+    destroyTreeScopeData();
+    removeDetachedChildren();
+
+    m_markers->detach();
+
+    m_cssCanvasElements.clear();
+
+    // FIXME: consider using ActiveDOMObject.
+    if (m_scriptedAnimationController)
+        m_scriptedAnimationController->clearDocumentPointer();
+    m_scriptedAnimationController.clear();
+}
+
+Element* Document::getElementById(const AtomicString& id) const
+{
+    return TreeScope::getElementById(id);
+}
+
+Element* Document::getElementByAccessKey(const String& key)
+{
+    if (key.isEmpty())
+        return 0;
+    if (!m_accessKeyMapValid) {
+        buildAccessKeyMap(this);
+        m_accessKeyMapValid = true;
+    }
+    return m_elementsByAccessKey.get(key.impl());
+}
+
+void Document::buildAccessKeyMap(TreeScope* scope)
+{
+    ASSERT(scope);
+    Node* rootNode = scope->rootNode();
+    for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) {
+        const AtomicString& accessKey = element->getAttribute(accesskeyAttr);
+        if (!accessKey.isEmpty())
+            m_elementsByAccessKey.set(accessKey.impl(), element);
+
+        for (ShadowRoot* root = element->youngestShadowRoot(); root; root = root->olderShadowRoot())
+            buildAccessKeyMap(root);
+    }
+}
+
+void Document::invalidateAccessKeyMap()
+{
+    m_accessKeyMapValid = false;
+    m_elementsByAccessKey.clear();
+}
+
+SelectorQueryCache* Document::selectorQueryCache()
+{
+    if (!m_selectorQueryCache)
+        m_selectorQueryCache = adoptPtr(new SelectorQueryCache());
+    return m_selectorQueryCache.get();
+}
+
+MediaQueryMatcher* Document::mediaQueryMatcher()
+{
+    if (!m_mediaQueryMatcher)
+        m_mediaQueryMatcher = MediaQueryMatcher::create(this);
+    return m_mediaQueryMatcher.get();
+}
+
+void Document::setCompatibilityMode(CompatibilityMode mode)
+{
+    if (m_compatibilityModeLocked || mode == m_compatibilityMode)
+        return;
+    bool wasInQuirksMode = inQuirksMode();
+    m_compatibilityMode = mode;
+    selectorQueryCache()->invalidate();
+    if (inQuirksMode() != wasInQuirksMode) {
+        // All user stylesheets have to reparse using the different mode.
+        m_styleSheetCollection->clearPageUserSheet();
+        m_styleSheetCollection->invalidateInjectedStyleSheetCache();
+    }
+}
+
+String Document::compatMode() const
+{
+    return inQuirksMode() ? "BackCompat" : "CSS1Compat";
+}
+
+void Document::resetLinkColor()
+{
+    m_linkColor = Color(0, 0, 238);
+}
+
+void Document::resetVisitedLinkColor()
+{
+    m_visitedLinkColor = Color(85, 26, 139);
+}
+
+void Document::resetActiveLinkColor()
+{
+    m_activeLinkColor.setNamedColor("red");
+}
+
+void Document::setDocType(PassRefPtr<DocumentType> docType)
+{
+    // This should never be called more than once.
+    ASSERT(!m_docType || !docType);
+    m_docType = docType;
+    if (m_docType) {
+        this->adoptIfNeeded(m_docType.get());
+        if (m_docType->publicId().startsWith("-//wapforum//dtd xhtml mobile 1.", /* caseSensitive */ false))
+            processViewport("width=device-width, height=device-height", ViewportArguments::XHTMLMobileProfile);
+    }
+    // Doctype affects the interpretation of the stylesheets.
+    clearStyleResolver();
+}
+
+DOMImplementation* Document::implementation()
+{
+    if (!m_implementation)
+        m_implementation = DOMImplementation::create(this);
+    return m_implementation.get();
+}
+
+bool Document::hasManifest() const
+{
+    return documentElement() && documentElement()->hasTagName(htmlTag) && documentElement()->hasAttribute(manifestAttr);
+}
+
+void Document::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
+{
+    ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
+
+    Element* newDocumentElement = ElementTraversal::firstWithin(this);
+    if (newDocumentElement == m_documentElement)
+        return;
+    m_documentElement = newDocumentElement;
+    // The root style used for media query matching depends on the document element.
+    clearStyleResolver();
+}
+
+PassRefPtr<Element> Document::createElement(const AtomicString& name, ExceptionCode& ec)
+{
+    if (!isValidName(name)) {
+        ec = INVALID_CHARACTER_ERR;
+        return 0;
+    }
+
+    if (m_isXHTML)
+        return HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, name, xhtmlNamespaceURI), this, 0, false);
+
+    return createElement(QualifiedName(nullAtom, name, nullAtom), false);
+}
+
+PassRefPtr<Element> Document::createElement(const AtomicString& localName, const AtomicString& typeExtension, ExceptionCode& ec)
+{
+    if (!isValidName(localName)) {
+        ec = INVALID_CHARACTER_ERR;
+        return 0;
+    }
+
+    RefPtr<Element> element;
+
+    if (CustomElementRegistry::isCustomTagName(localName))
+        element = ensureCustomElementRegistry()->createCustomTagElement(QualifiedName(nullAtom, localName, xhtmlNamespaceURI));
+    else
+        element = createElement(localName, ec);
+
+    if (!typeExtension.isNull()) {
+        setTypeExtension(element.get(), typeExtension);
+        ensureCustomElementRegistry()->didGiveTypeExtension(element.get(), typeExtension);
+    }
+
+    return element;
+}
+
+PassRefPtr<Element> Document::createElementNS(const AtomicString& namespaceURI, const String& qualifiedName, const AtomicString& typeExtension, ExceptionCode& ec)
+{
+    String prefix, localName;
+    if (!parseQualifiedName(qualifiedName, prefix, localName, ec))
+        return 0;
+
+    QualifiedName qName(prefix, localName, namespaceURI);
+    if (!hasValidNamespaceForElements(qName)) {
+        ec = NAMESPACE_ERR;
+        return 0;
+    }
+
+    RefPtr<Element> element;
+    if (CustomElementRegistry::isCustomTagName(qName.localName()))
+        element = ensureCustomElementRegistry()->createCustomTagElement(qName);
+    else
+        element = createElementNS(namespaceURI, qualifiedName, ec);
+
+    if (!typeExtension.isNull()) {
+        setTypeExtension(element.get(), typeExtension);
+        ensureCustomElementRegistry()->didGiveTypeExtension(element.get(), typeExtension);
+    }
+
+    return element;
+}
+
+PassRefPtr<CustomElementConstructor> Document::registerElement(WebCore::ScriptState* state, const AtomicString& name, ExceptionCode& ec)
+{
+    return registerElement(state, name, Dictionary(), ec);
+}
+
+PassRefPtr<CustomElementConstructor> Document::registerElement(WebCore::ScriptState* state, const AtomicString& name, const Dictionary& options, ExceptionCode& ec)
+{
+    if (!isHTMLDocument() && !isXHTMLDocument()) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+
+    return ensureCustomElementRegistry()->registerElement(state, name, options, ec);
+}
+
+CustomElementRegistry* Document::ensureCustomElementRegistry()
+{
+    if (!m_registry) {
+        ASSERT(isHTMLDocument() || isXHTMLDocument());
+        m_registry = adoptRef(new CustomElementRegistry(this));
+    }
+    return m_registry.get();
+}
+
+PassRefPtr<DocumentFragment> Document::createDocumentFragment()
+{
+    return DocumentFragment::create(document());
+}
+
+PassRefPtr<Text> Document::createTextNode(const String& data)
+{
+    return Text::create(this, data);
+}
+
+PassRefPtr<Comment> Document::createComment(const String& data)
+{
+    return Comment::create(this, data);
+}
+
+PassRefPtr<CDATASection> Document::createCDATASection(const String& data, ExceptionCode& ec)
+{
+    if (isHTMLDocument()) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+    return CDATASection::create(this, data);
+}
+
+PassRefPtr<ProcessingInstruction> Document::createProcessingInstruction(const String& target, const String& data, ExceptionCode& ec)
+{
+    if (!isValidName(target)) {
+        ec = INVALID_CHARACTER_ERR;
+        return 0;
+    }
+    if (isHTMLDocument()) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+    return ProcessingInstruction::create(this, target, data);
+}
+
+PassRefPtr<EntityReference> Document::createEntityReference(const String& name, ExceptionCode& ec)
+{
+    if (!isValidName(name)) {
+        ec = INVALID_CHARACTER_ERR;
+        return 0;
+    }
+    if (isHTMLDocument()) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+    return EntityReference::create(this, name);
+}
+
+PassRefPtr<Text> Document::createEditingTextNode(const String& text)
+{
+    return Text::createEditingText(this, text);
+}
+
+PassRefPtr<CSSStyleDeclaration> Document::createCSSStyleDeclaration()
+{
+    return StylePropertySet::create()->ensureCSSStyleDeclaration();
+}
+
+PassRefPtr<Node> Document::importNode(Node* importedNode, bool deep, ExceptionCode& ec)
+{
+    ec = 0;
+
+    if (!importedNode) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+
+    switch (importedNode->nodeType()) {
+    case TEXT_NODE:
+        return createTextNode(importedNode->nodeValue());
+    case CDATA_SECTION_NODE:
+        return createCDATASection(importedNode->nodeValue(), ec);
+    case ENTITY_REFERENCE_NODE:
+        return createEntityReference(importedNode->nodeName(), ec);
+    case PROCESSING_INSTRUCTION_NODE:
+        return createProcessingInstruction(importedNode->nodeName(), importedNode->nodeValue(), ec);
+    case COMMENT_NODE:
+        return createComment(importedNode->nodeValue());
+    case ELEMENT_NODE: {
+        Element* oldElement = toElement(importedNode);
+        // FIXME: The following check might be unnecessary. Is it possible that
+        // oldElement has mismatched prefix/namespace?
+        if (!hasValidNamespaceForElements(oldElement->tagQName())) {
+            ec = NAMESPACE_ERR;
+            return 0;
+        }
+        RefPtr<Element> newElement = createElement(oldElement->tagQName(), false);
+
+        newElement->cloneDataFromElement(*oldElement);
+
+        if (deep) {
+            for (Node* oldChild = oldElement->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
+                RefPtr<Node> newChild = importNode(oldChild, true, ec);
+                if (ec)
+                    return 0;
+                newElement->appendChild(newChild.release(), ec);
+                if (ec)
+                    return 0;
+            }
+        }
+
+        return newElement.release();
+    }
+    case ATTRIBUTE_NODE:
+        return Attr::create(this, QualifiedName(nullAtom, static_cast<Attr*>(importedNode)->name(), nullAtom), static_cast<Attr*>(importedNode)->value());
+    case DOCUMENT_FRAGMENT_NODE: {
+        if (importedNode->isShadowRoot()) {
+            // ShadowRoot nodes should not be explicitly importable.
+            // Either they are imported along with their host node, or created implicitly.
+            break;
+        }
+        DocumentFragment* oldFragment = static_cast<DocumentFragment*>(importedNode);
+        RefPtr<DocumentFragment> newFragment = createDocumentFragment();
+        if (deep) {
+            for (Node* oldChild = oldFragment->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
+                RefPtr<Node> newChild = importNode(oldChild, true, ec);
+                if (ec)
+                    return 0;
+                newFragment->appendChild(newChild.release(), ec);
+                if (ec)
+                    return 0;
+            }
+        }
+
+        return newFragment.release();
+    }
+    case ENTITY_NODE:
+    case NOTATION_NODE:
+        // FIXME: It should be possible to import these node types, however in DOM3 the DocumentType is readonly, so there isn't much sense in doing that.
+        // Ability to add these imported nodes to a DocumentType will be considered for addition to a future release of the DOM.
+    case DOCUMENT_NODE:
+    case DOCUMENT_TYPE_NODE:
+    case XPATH_NAMESPACE_NODE:
+        break;
+    }
+    ec = NOT_SUPPORTED_ERR;
+    return 0;
+}
+
+
+PassRefPtr<Node> Document::adoptNode(PassRefPtr<Node> source, ExceptionCode& ec)
+{
+    if (!source) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+
+    if (source->isReadOnlyNode()) {
+        ec = NO_MODIFICATION_ALLOWED_ERR;
+        return 0;
+    }
+
+    EventQueueScope scope;
+
+    switch (source->nodeType()) {
+    case ENTITY_NODE:
+    case NOTATION_NODE:
+    case DOCUMENT_NODE:
+    case DOCUMENT_TYPE_NODE:
+    case XPATH_NAMESPACE_NODE:
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    case ATTRIBUTE_NODE: {
+        Attr* attr = static_cast<Attr*>(source.get());
+        if (attr->ownerElement())
+            attr->ownerElement()->removeAttributeNode(attr, ec);
+        attr->setSpecified(true);
+        break;
+    }
+    default:
+        if (source->isShadowRoot()) {
+            // ShadowRoot cannot disconnect itself from the host node.
+            ec = HIERARCHY_REQUEST_ERR;
+            return 0;
+        }
+
+        if (source->isFrameOwnerElement()) {
+            HTMLFrameOwnerElement* frameOwnerElement = toFrameOwnerElement(source.get());
+            if (frame() && frame()->tree()->isDescendantOf(frameOwnerElement->contentFrame())) {
+                ec = HIERARCHY_REQUEST_ERR;
+                return 0;
+            }
+        }
+        if (source->parentNode()) {
+            source->parentNode()->removeChild(source.get(), ec);
+            if (ec)
+                return 0;
+        }
+    }
+
+    this->adoptIfNeeded(source.get());
+
+    return source;
+}
+
+bool Document::hasValidNamespaceForElements(const QualifiedName& qName)
+{
+    // These checks are from DOM Core Level 2, createElementNS
+    // http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-DocCrElNS
+    if (!qName.prefix().isEmpty() && qName.namespaceURI().isNull()) // createElementNS(null, "html:div")
+        return false;
+    if (qName.prefix() == xmlAtom && qName.namespaceURI() != XMLNames::xmlNamespaceURI) // createElementNS("http://www.example.com", "xml:lang")
+        return false;
+
+    // Required by DOM Level 3 Core and unspecified by DOM Level 2 Core:
+    // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
+    // createElementNS("http://www.w3.org/2000/xmlns/", "foo:bar"), createElementNS(null, "xmlns:bar")
+    if ((qName.prefix() == xmlnsAtom && qName.namespaceURI() != XMLNSNames::xmlnsNamespaceURI) || (qName.prefix() != xmlnsAtom && qName.namespaceURI() == XMLNSNames::xmlnsNamespaceURI))
+        return false;
+
+    return true;
+}
+
+bool Document::hasValidNamespaceForAttributes(const QualifiedName& qName)
+{
+    // Spec: DOM Level 2 Core: http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-ElSetAttrNS
+    if (qName.prefix().isEmpty() && qName.localName() == xmlnsAtom) {
+        // Note: The case of an "xmlns" qualified name with a namespace of
+        // xmlnsNamespaceURI is specifically allowed (See <http://www.w3.org/2000/xmlns/>).
+        return qName.namespaceURI() == XMLNSNames::xmlnsNamespaceURI;
+    }
+    return hasValidNamespaceForElements(qName);
+}
+
+// FIXME: This should really be in a possible ElementFactory class
+PassRefPtr<Element> Document::createElement(const QualifiedName& qName, bool createdByParser)
+{
+    RefPtr<Element> e;
+
+    // FIXME: Use registered namespaces and look up in a hash to find the right factory.
+    if (qName.namespaceURI() == xhtmlNamespaceURI)
+        e = HTMLElementFactory::createHTMLElement(qName, this, 0, createdByParser);
+#if ENABLE(SVG)
+    else if (qName.namespaceURI() == SVGNames::svgNamespaceURI)
+        e = SVGElementFactory::createSVGElement(qName, this, createdByParser);
+#endif
+
+    if (e)
+        m_sawElementsInKnownNamespaces = true;
+    else
+        e = Element::create(qName, document());
+
+    // <image> uses imgTag so we need a special rule.
+    ASSERT((qName.matches(imageTag) && e->tagQName().matches(imgTag) && e->tagQName().prefix() == qName.prefix()) || qName == e->tagQName());
+
+    return e.release();
+}
+
+bool Document::regionBasedColumnsEnabled() const
+{
+    return settings() && settings()->regionBasedColumnsEnabled();
+}
+
+bool Document::cssStickyPositionEnabled() const
+{
+    return settings() && settings()->cssStickyPositionEnabled();
+}
+
+bool Document::cssCompositingEnabled() const
+{
+    return RuntimeEnabledFeatures::cssCompositingEnabled();
+}
+
+bool Document::cssGridLayoutEnabled() const
+{
+    return settings() && settings()->cssGridLayoutEnabled();
+}
+
+PassRefPtr<DOMNamedFlowCollection> Document::webkitGetNamedFlows()
+{
+    if (!RuntimeEnabledFeatures::cssRegionsEnabled() || !renderer())
+        return 0;
+
+    updateStyleIfNeeded();
+
+    return namedFlows()->createCSSOMSnapshot();
+}
+
+NamedFlowCollection* Document::namedFlows()
+{
+    if (!m_namedFlows)
+        m_namedFlows = NamedFlowCollection::create(this);
+
+    return m_namedFlows.get();
+}
+
+PassRefPtr<Element> Document::createElementNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode& ec)
+{
+    String prefix, localName;
+    if (!parseQualifiedName(qualifiedName, prefix, localName, ec))
+        return 0;
+
+    QualifiedName qName(prefix, localName, namespaceURI);
+    if (!hasValidNamespaceForElements(qName)) {
+        ec = NAMESPACE_ERR;
+        return 0;
+    }
+
+    return createElement(qName, false);
+}
+
+String Document::readyState() const
+{
+    DEFINE_STATIC_LOCAL(const String, loading, (ASCIILiteral("loading")));
+    DEFINE_STATIC_LOCAL(const String, interactive, (ASCIILiteral("interactive")));
+    DEFINE_STATIC_LOCAL(const String, complete, (ASCIILiteral("complete")));
+
+    switch (m_readyState) {
+    case Loading:
+        return loading;
+    case Interactive:
+        return interactive;
+    case Complete:
+        return complete;
+    }
+
+    ASSERT_NOT_REACHED();
+    return String();
+}
+
+void Document::setReadyState(ReadyState readyState)
+{
+    if (readyState == m_readyState)
+        return;
+
+    switch (readyState) {
+    case Loading:
+        if (!m_documentTiming.domLoading)
+            m_documentTiming.domLoading = monotonicallyIncreasingTime();
+        break;
+    case Interactive:
+        if (!m_documentTiming.domInteractive)
+            m_documentTiming.domInteractive = monotonicallyIncreasingTime();
+        break;
+    case Complete:
+        if (!m_documentTiming.domComplete)
+            m_documentTiming.domComplete = monotonicallyIncreasingTime();
+        break;
+    }
+
+    m_readyState = readyState;
+    dispatchEvent(Event::create(eventNames().readystatechangeEvent, false, false));
+}
+
+String Document::encoding() const
+{
+    if (TextResourceDecoder* d = decoder())
+        return d->encoding().domName();
+    return String();
+}
+
+String Document::defaultCharset() const
+{
+    if (Settings* settings = this->settings())
+        return settings->defaultTextEncodingName();
+    return String();
+}
+
+void Document::setCharset(const String& charset)
+{
+    if (!decoder())
+        return;
+    decoder()->setEncoding(charset, TextResourceDecoder::UserChosenEncoding);
+}
+
+void Document::setContentLanguage(const String& language)
+{
+    if (m_contentLanguage == language)
+        return;
+    m_contentLanguage = language;
+
+    // Recalculate style so language is used when selecting the initial font.
+    styleResolverChanged(DeferRecalcStyle);
+}
+
+void Document::setXMLVersion(const String& version, ExceptionCode& ec)
+{
+    if (!implementation()->hasFeature("XML", String())) {
+        ec = NOT_SUPPORTED_ERR;
+        return;
+    }
+
+    if (!XMLDocumentParser::supportsXMLVersion(version)) {
+        ec = NOT_SUPPORTED_ERR;
+        return;
+    }
+
+    m_xmlVersion = version;
+}
+
+void Document::setXMLStandalone(bool standalone, ExceptionCode& ec)
+{
+    if (!implementation()->hasFeature("XML", String())) {
+        ec = NOT_SUPPORTED_ERR;
+        return;
+    }
+
+    m_xmlStandalone = standalone ? Standalone : NotStandalone;
+}
+
+KURL Document::baseURI() const
+{
+    return m_baseURL;
+}
+
+void Document::setContent(const String& content)
+{
+    open();
+    // FIXME: This should probably use insert(), but that's (intentionally)
+    // not implemented for the XML parser as it's normally synonymous with
+    // document.write(). append() will end up yielding, but close() will
+    // pump the tokenizer syncrhonously and finish the parse.
+    m_parser->pinToMainThread();
+    m_parser->append(content.impl());
+    close();
+}
+
+String Document::suggestedMIMEType() const
+{
+    if (isXHTMLDocument())
+        return "application/xhtml+xml";
+    if (isSVGDocument())
+        return "image/svg+xml";
+    if (xmlStandalone())
+        return "text/xml";
+    if (isHTMLDocument())
+        return "text/html";
+
+    if (DocumentLoader* documentLoader = loader())
+        return documentLoader->responseMIMEType();
+    return String();
+}
+
+Element* Document::elementFromPoint(int x, int y) const
+{
+    if (!renderer())
+        return 0;
+
+    return TreeScope::elementFromPoint(x, y);
+}
+
+PassRefPtr<Range> Document::caretRangeFromPoint(int x, int y)
+{
+    if (!renderer())
+        return 0;
+    LayoutPoint localPoint;
+    Node* node = nodeFromPoint(this, x, y, &localPoint);
+    if (!node)
+        return 0;
+
+    Node* shadowAncestorNode = ancestorInThisScope(node);
+    if (shadowAncestorNode != node) {
+        unsigned offset = shadowAncestorNode->nodeIndex();
+        ContainerNode* container = shadowAncestorNode->parentNode();
+        return Range::create(this, container, offset, container, offset);
+    }
+
+    RenderObject* renderer = node->renderer();
+    if (!renderer)
+        return 0;
+    VisiblePosition visiblePosition = renderer->positionForPoint(localPoint);
+    if (visiblePosition.isNull())
+        return 0;
+
+    Position rangeCompliantPosition = visiblePosition.deepEquivalent().parentAnchoredEquivalent();
+    return Range::create(this, rangeCompliantPosition, rangeCompliantPosition);
+}
+
+/*
+ * Performs three operations:
+ *  1. Convert control characters to spaces
+ *  2. Trim leading and trailing spaces
+ *  3. Collapse internal whitespace.
+ */
+template <typename CharacterType>
+static inline StringWithDirection canonicalizedTitle(Document* document, const StringWithDirection& titleWithDirection)
+{
+    const String& title = titleWithDirection.string();
+    const CharacterType* characters = title.getCharacters<CharacterType>();
+    unsigned length = title.length();
+    unsigned i;
+
+    StringBuffer<CharacterType> buffer(length);
+    unsigned builderIndex = 0;
+
+    // Skip leading spaces and leading characters that would convert to spaces
+    for (i = 0; i < length; ++i) {
+        CharacterType c = characters[i];
+        if (!(c <= 0x20 || c == 0x7F))
+            break;
+    }
+
+    if (i == length)
+        return StringWithDirection();
+
+    // Replace control characters with spaces, and backslashes with currency symbols, and collapse whitespace.
+    bool previousCharWasWS = false;
+    for (; i < length; ++i) {
+        CharacterType c = characters[i];
+        if (c <= 0x20 || c == 0x7F || (WTF::Unicode::category(c) & (WTF::Unicode::Separator_Line | WTF::Unicode::Separator_Paragraph))) {
+            if (previousCharWasWS)
+                continue;
+            buffer[builderIndex++] = ' ';
+            previousCharWasWS = true;
+        } else {
+            buffer[builderIndex++] = c;
+            previousCharWasWS = false;
+        }
+    }
+
+    // Strip trailing spaces
+    while (builderIndex > 0) {
+        --builderIndex;
+        if (buffer[builderIndex] != ' ')
+            break;
+    }
+
+    if (!builderIndex && buffer[builderIndex] == ' ')
+        return StringWithDirection();
+
+    buffer.shrink(builderIndex + 1);
+
+    // Replace the backslashes with currency symbols if the encoding requires it.
+    document->displayBufferModifiedByEncoding(buffer.characters(), buffer.length());
+
+    return StringWithDirection(String::adopt(buffer), titleWithDirection.direction());
+}
+
+void Document::updateTitle(const StringWithDirection& title)
+{
+    if (m_rawTitle == title)
+        return;
+
+    m_rawTitle = title;
+
+    if (m_rawTitle.string().isEmpty())
+        m_title = StringWithDirection();
+    else {
+        if (m_rawTitle.string().is8Bit())
+            m_title = canonicalizedTitle<LChar>(this, m_rawTitle);
+        else
+            m_title = canonicalizedTitle<UChar>(this, m_rawTitle);
+    }
+    if (Frame* f = frame())
+        f->loader()->setTitle(m_title);
+}
+
+void Document::setTitle(const String& title)
+{
+    // Title set by JavaScript -- overrides any title elements.
+    m_titleSetExplicitly = true;
+    if (!isHTMLDocument() && !isXHTMLDocument())
+        m_titleElement = 0;
+    else if (!m_titleElement) {
+        if (HTMLElement* headElement = head()) {
+            m_titleElement = createElement(titleTag, false);
+            headElement->appendChild(m_titleElement, ASSERT_NO_EXCEPTION);
+        }
+    }
+
+    // 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(title);
+    }
+}
+
+void Document::setTitleElement(const StringWithDirection& title, Element* titleElement)
+{
+    if (titleElement != m_titleElement) {
+        if (m_titleElement || m_titleSetExplicitly)
+            // Only allow the first title element to change the title -- others have no effect.
+            return;
+        m_titleElement = titleElement;
+    }
+
+    updateTitle(title);
+}
+
+void Document::removeTitle(Element* titleElement)
+{
+    if (m_titleElement != titleElement)
+        return;
+
+    m_titleElement = 0;
+    m_titleSetExplicitly = false;
+
+    // Update title based on first title element in the head, if one exists.
+    if (HTMLElement* headElement = head()) {
+        for (Node* e = headElement->firstChild(); e; e = e->nextSibling())
+            if (e->hasTagName(titleTag)) {
+                HTMLTitleElement* titleElement = static_cast<HTMLTitleElement*>(e);
+                setTitleElement(titleElement->textWithDirection(), titleElement);
+                break;
+            }
+    }
+
+    if (!m_titleElement)
+        updateTitle(StringWithDirection());
+}
+
+PageVisibilityState Document::visibilityState() const
+{
+    // The visibility of the document is inherited from the visibility of the
+    // page. If there is no page associated with the document, we will assume
+    // that the page is hidden, as specified by the spec:
+    // http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html#dom-document-hidden
+    if (!m_frame || !m_frame->page())
+        return PageVisibilityStateHidden;
+    return m_frame->page()->visibilityState();
+}
+
+String Document::webkitVisibilityState() const
+{
+    return pageVisibilityStateString(visibilityState());
+}
+
+bool Document::webkitHidden() const
+{
+    return visibilityState() != PageVisibilityStateVisible;
+}
+
+void Document::dispatchVisibilityStateChangeEvent()
+{
+    dispatchEvent(Event::create(eventNames().webkitvisibilitychangeEvent, false, false));
+}
+
+DOMSecurityPolicy* Document::securityPolicy()
+{
+    if (!m_domSecurityPolicy)
+        m_domSecurityPolicy = DOMSecurityPolicy::create(this);
+    return m_domSecurityPolicy.get();
+}
+
+String Document::nodeName() const
+{
+    return "#document";
+}
+
+Node::NodeType Document::nodeType() const
+{
+    return DOCUMENT_NODE;
+}
+
+FormController* Document::formController()
+{
+    if (!m_formController)
+        m_formController = FormController::create();
+    return m_formController.get();
+}
+
+Vector<String> Document::formElementsState() const
+{
+    if (!m_formController)
+        return Vector<String>();
+    return m_formController->formElementsState();
+}
+
+void Document::setStateForNewFormElements(const Vector<String>& stateVector)
+{
+    if (!stateVector.size() && !m_formController)
+        return;
+    formController()->setStateForNewFormElements(stateVector);
+}
+
+FrameView* Document::view() const
+{
+    return m_frame ? m_frame->view() : 0;
+}
+
+Page* Document::page() const
+{
+    return m_frame ? m_frame->page() : 0;
+}
+
+Settings* Document::settings() const
+{
+    return m_frame ? m_frame->settings() : 0;
+}
+
+PassRefPtr<Range> Document::createRange()
+{
+    return Range::create(this);
+}
+
+PassRefPtr<NodeIterator> Document::createNodeIterator(Node* root, unsigned whatToShow,
+    PassRefPtr<NodeFilter> filter, bool expandEntityReferences, ExceptionCode& ec)
+{
+    if (!root) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+    return NodeIterator::create(root, whatToShow, filter, expandEntityReferences);
+}
+
+PassRefPtr<TreeWalker> Document::createTreeWalker(Node* root, unsigned whatToShow,
+    PassRefPtr<NodeFilter> filter, bool expandEntityReferences, ExceptionCode& ec)
+{
+    if (!root) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+    return TreeWalker::create(root, whatToShow, filter, expandEntityReferences);
+}
+
+void Document::scheduleForcedStyleRecalc()
+{
+    m_pendingStyleRecalcShouldForce = true;
+    scheduleStyleRecalc();
+}
+
+void Document::scheduleStyleRecalc()
+{
+    if (shouldDisplaySeamlesslyWithParent()) {
+        // When we're seamless, our parent document manages our style recalcs.
+        ownerElement()->setNeedsStyleRecalc();
+        ownerElement()->document()->scheduleStyleRecalc();
+        return;
+    }
+
+    if (m_styleRecalcTimer.isActive())
+        return;
+
+    ASSERT(childNeedsStyleRecalc() || m_pendingStyleRecalcShouldForce);
+
+    // FIXME: Why on earth is this here? This is clearly misplaced.
+    invalidateAccessKeyMap();
+
+    m_styleRecalcTimer.startOneShot(0);
+
+    InspectorInstrumentation::didScheduleStyleRecalculation(this);
+}
+
+void Document::unscheduleStyleRecalc()
+{
+    ASSERT(!childNeedsStyleRecalc());
+
+    m_styleRecalcTimer.stop();
+    m_pendingStyleRecalcShouldForce = false;
+}
+
+bool Document::hasPendingStyleRecalc() const
+{
+    return m_styleRecalcTimer.isActive() && !m_inStyleRecalc;
+}
+
+bool Document::hasPendingForcedStyleRecalc() const
+{
+    return m_styleRecalcTimer.isActive() && m_pendingStyleRecalcShouldForce;
+}
+
+void Document::styleRecalcTimerFired(Timer<Document>*)
+{
+    updateStyleIfNeeded();
+}
+
+bool Document::childNeedsAndNotInStyleRecalc()
+{
+    return childNeedsStyleRecalc() && !m_inStyleRecalc;
+}
+
+void Document::recalcStyle(StyleChange change)
+{
+    // we should not enter style recalc while painting
+    ASSERT(!view() || !view()->isPainting());
+    if (view() && view()->isPainting())
+        return;
+
+    if (m_inStyleRecalc)
+        return; // Guard against re-entrancy. -dwh
+
+    TRACE_EVENT0("webkit", "Document::recalcStyle");
+
+    // FIXME: We should update style on our ancestor chain before proceeding (especially for seamless),
+    // however doing so currently causes several tests to crash, as Frame::setDocument calls Document::attach
+    // before setting the DOMWindow on the Frame, or the SecurityOrigin on the document. The attach, in turn
+    // resolves style (here) and then when we resolve style on the parent chain, we may end up
+    // re-attaching our containing iframe, which when asked HTMLFrameElementBase::isURLAllowed
+    // hits a null-dereference due to security code always assuming the document has a SecurityOrigin.
+
+    if (m_styleSheetCollection->needsUpdateActiveStylesheetsOnStyleRecalc())
+        m_styleSheetCollection->updateActiveStyleSheets(DocumentStyleSheetCollection::FullUpdate);
+
+    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willRecalculateStyle(this);
+
+    if (m_elemSheet && m_elemSheet->contents()->usesRemUnits())
+        m_styleSheetCollection->setUsesRemUnit(true);
+
+    m_inStyleRecalc = true;
+    {
+        PostAttachCallbackDisabler disabler(this);
+        WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
+
+        RefPtr<FrameView> frameView = view();
+        if (frameView) {
+            frameView->pauseScheduledEvents();
+            frameView->beginDeferredRepaints();
+        }
+
+        ASSERT(!renderer() || renderArena());
+        if (!renderer() || !renderArena())
+            goto bailOut;
+
+        if (m_pendingStyleRecalcShouldForce)
+            change = Force;
+
+        // Recalculating the root style (on the document) is not needed in the common case.
+        if ((change == Force) || (shouldDisplaySeamlesslyWithParent() && (change >= Inherit))) {
+            // style selector may set this again during recalc
+            m_hasNodesWithPlaceholderStyle = false;
+
+            RefPtr<RenderStyle> documentStyle = StyleResolver::styleForDocument(this, m_styleResolver ? m_styleResolver->fontSelector() : 0);
+            StyleChange ch = Node::diff(documentStyle.get(), renderer()->style(), this);
+            if (ch != NoChange)
+                renderer()->setStyle(documentStyle.release());
+        }
+
+        for (Node* n = firstChild(); n; n = n->nextSibling()) {
+            if (!n->isElementNode())
+                continue;
+            Element* element = toElement(n);
+            if (change >= Inherit || element->childNeedsStyleRecalc() || element->needsStyleRecalc())
+                element->recalcStyle(change);
+        }
+
+        if (view())
+            view()->updateCompositingLayersAfterStyleChange();
+
+    bailOut:
+        clearNeedsStyleRecalc();
+        clearChildNeedsStyleRecalc();
+        unscheduleStyleRecalc();
+
+        m_inStyleRecalc = false;
+
+        // Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc.
+        if (m_styleResolver)
+            m_styleSheetCollection->resetCSSFeatureFlags();
+
+        if (frameView) {
+            frameView->resumeScheduledEvents();
+            frameView->endDeferredRepaints();
+        }
+    }
+
+    // If we wanted to call implicitClose() during recalcStyle, do so now that we're finished.
+    if (m_closeAfterStyleRecalc) {
+        m_closeAfterStyleRecalc = false;
+        implicitClose();
+    }
+
+    InspectorInstrumentation::didRecalculateStyle(cookie);
+}
+
+void Document::updateStyleIfNeeded()
+{
+    ASSERT(isMainThread());
+    ASSERT(!view() || (!view()->isInLayout() && !view()->isPainting()));
+
+    if (!m_pendingStyleRecalcShouldForce && !childNeedsStyleRecalc())
+        return;
+
+    AnimationUpdateBlock animationUpdateBlock(m_frame ? m_frame->animation() : 0);
+    recalcStyle(NoChange);
+}
+
+void Document::updateLayout()
+{
+    ASSERT(isMainThread());
+
+    FrameView* frameView = view();
+    if (frameView && frameView->isInLayout()) {
+        // View layout should not be re-entrant.
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    if (Element* oe = ownerElement())
+        oe->document()->updateLayout();
+
+    updateStyleIfNeeded();
+
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+
+    // Only do a layout if changes have occurred that make it necessary.
+    if (frameView && renderer() && (frameView->layoutPending() || renderer()->needsLayout()))
+        frameView->layout();
+}
+
+// FIXME: This is a bad idea and needs to be removed eventually.
+// Other browsers load stylesheets before they continue parsing the web page.
+// Since we don't, we can run JavaScript code that needs answers before the
+// stylesheets are loaded. Doing a layout ignoring the pending stylesheets
+// lets us get reasonable answers. The long term solution to this problem is
+// to instead suspend JavaScript execution.
+void Document::updateLayoutIgnorePendingStylesheets()
+{
+    bool oldIgnore = m_ignorePendingStylesheets;
+
+    if (!haveStylesheetsLoaded()) {
+        m_ignorePendingStylesheets = true;
+        // FIXME: We are willing to attempt to suppress painting with outdated style info only once.  Our assumption is that it would be
+        // dangerous to try to stop it a second time, after page content has already been loaded and displayed
+        // with accurate style information.  (Our suppression involves blanking the whole page at the
+        // moment.  If it were more refined, we might be able to do something better.)
+        // It's worth noting though that this entire method is a hack, since what we really want to do is
+        // suspend JS instead of doing a layout with inaccurate information.
+        HTMLElement* bodyElement = body();
+        if (bodyElement && !bodyElement->renderer() && m_pendingSheetLayout == NoLayoutWithPendingSheets) {
+            m_pendingSheetLayout = DidLayoutWithPendingSheets;
+            styleResolverChanged(RecalcStyleImmediately);
+        } else if (m_hasNodesWithPlaceholderStyle)
+            // If new nodes have been added or style recalc has been done with style sheets still pending, some nodes
+            // may not have had their real style calculated yet. Normally this gets cleaned when style sheets arrive
+            // but here we need up-to-date style immediately.
+            recalcStyle(Force);
+    }
+
+    updateLayout();
+
+    m_ignorePendingStylesheets = oldIgnore;
+}
+
+PassRefPtr<RenderStyle> Document::styleForElementIgnoringPendingStylesheets(Element* element)
+{
+    ASSERT_ARG(element, element->document() == this);
+
+    bool oldIgnore = m_ignorePendingStylesheets;
+    m_ignorePendingStylesheets = true;
+    RefPtr<RenderStyle> style = styleResolver()->styleForElement(element, element->parentNode() ? element->parentNode()->computedStyle() : 0);
+    m_ignorePendingStylesheets = oldIgnore;
+    return style.release();
+}
+
+PassRefPtr<RenderStyle> Document::styleForPage(int pageIndex)
+{
+    RefPtr<RenderStyle> style = styleResolver()->styleForPage(pageIndex);
+    return style.release();
+}
+
+bool Document::isPageBoxVisible(int pageIndex)
+{
+    RefPtr<RenderStyle> style = styleForPage(pageIndex);
+    return style->visibility() != HIDDEN; // display property doesn't apply to @page.
+}
+
+void Document::pageSizeAndMarginsInPixels(int pageIndex, IntSize& pageSize, int& marginTop, int& marginRight, int& marginBottom, int& marginLeft)
+{
+    RefPtr<RenderStyle> style = styleForPage(pageIndex);
+    RenderView* view = renderView();
+
+    int width = pageSize.width();
+    int height = pageSize.height();
+    switch (style->pageSizeType()) {
+    case PAGE_SIZE_AUTO:
+        break;
+    case PAGE_SIZE_AUTO_LANDSCAPE:
+        if (width < height)
+            std::swap(width, height);
+        break;
+    case PAGE_SIZE_AUTO_PORTRAIT:
+        if (width > height)
+            std::swap(width, height);
+        break;
+    case PAGE_SIZE_RESOLVED: {
+        LengthSize size = style->pageSize();
+        ASSERT(size.width().isFixed());
+        ASSERT(size.height().isFixed());
+        width = valueForLength(size.width(), 0, view);
+        height = valueForLength(size.height(), 0, view);
+        break;
+    }
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    pageSize = IntSize(width, height);
+
+    // The percentage is calculated with respect to the width even for margin top and bottom.
+    // http://www.w3.org/TR/CSS2/box.html#margin-properties
+    marginTop = style->marginTop().isAuto() ? marginTop : intValueForLength(style->marginTop(), width, view);
+    marginRight = style->marginRight().isAuto() ? marginRight : intValueForLength(style->marginRight(), width, view);
+    marginBottom = style->marginBottom().isAuto() ? marginBottom : intValueForLength(style->marginBottom(), width, view);
+    marginLeft = style->marginLeft().isAuto() ? marginLeft : intValueForLength(style->marginLeft(), width, view);
+}
+
+void Document::setIsViewSource(bool isViewSource)
+{
+    m_isViewSource = isViewSource;
+    if (!m_isViewSource)
+        return;
+
+    setSecurityOrigin(SecurityOrigin::createUnique());
+    didUpdateSecurityOrigin();
+}
+
+void Document::createStyleResolver()
+{
+    bool matchAuthorAndUserStyles = true;
+    if (Settings* docSettings = settings())
+        matchAuthorAndUserStyles = docSettings->authorAndUserStylesEnabled();
+    m_styleResolver = adoptPtr(new StyleResolver(this, matchAuthorAndUserStyles));
+    m_styleSheetCollection->combineCSSFeatureFlags();
+}
+
+void Document::clearStyleResolver()
+{
+    m_styleResolver.clear();
+}
+
+void Document::attach()
+{
+    ASSERT(!attached());
+    ASSERT(!m_axObjectCache || this != topDocument());
+
+    if (!m_renderArena)
+        m_renderArena = adoptPtr(new RenderArena);
+
+    // Create the rendering tree
+    setRenderer(new (m_renderArena.get()) RenderView(this));
+    renderView()->setIsInWindow(true);
+
+    recalcStyle(Force);
+
+    RenderObject* render = renderer();
+    setRenderer(0);
+
+    ContainerNode::attach();
+
+    setRenderer(render);
+}
+
+void Document::detach()
+{
+    ASSERT(attached());
+
+    if (page())
+        page()->pointerLockController()->documentDetached(this);
+
+    if (this == topDocument())
+        clearAXObjectCache();
+
+    stopActiveDOMObjects();
+    m_eventQueue->close();
+    m_fullScreenChangeEventTargetQueue.clear();
+    m_fullScreenErrorEventTargetQueue.clear();
+
+    // FIXME: consider using ActiveDOMObject.
+    if (m_scriptedAnimationController)
+        m_scriptedAnimationController->clearDocumentPointer();
+    m_scriptedAnimationController.clear();
+
+    RenderObject* render = renderer();
+
+    documentWillBecomeInactive();
+
+    SharedWorkerRepository::documentDetached(this);
+
+    if (m_frame) {
+        FrameView* view = m_frame->view();
+        if (view)
+            view->detachCustomScrollbars();
+
+    }
+
+    // indicate destruction mode,  i.e. attached() but renderer == 0
+    setRenderer(0);
+
+    if (m_fullScreenRenderer)
+        setFullScreenRenderer(0);
+
+    m_hoverNode = 0;
+    m_focusedNode = 0;
+    m_activeElement = 0;
+
+    ContainerNode::detach();
+
+    unscheduleStyleRecalc();
+
+    if (render)
+        render->destroy();
+
+    if (m_touchEventTargets && m_touchEventTargets->size() && parentDocument())
+        parentDocument()->didRemoveEventTargetNode(this);
+
+    // This is required, as our Frame might delete itself as soon as it detaches
+    // us. However, this violates Node::detach() semantics, as it's never
+    // possible to re-attach. Eventually Document::detach() should be renamed,
+    // or this setting of the frame to 0 could be made explicit in each of the
+    // callers of Document::detach().
+    m_frame = 0;
+    m_renderArena.clear();
+
+    if (m_mediaQueryMatcher)
+        m_mediaQueryMatcher->documentDestroyed();
+}
+
+void Document::prepareForDestruction()
+{
+    disconnectDescendantFrames();
+    if (DOMWindow* window = this->domWindow())
+        window->willDetachDocumentFromFrame();
+    detach();
+}
+
+void Document::removeAllEventListeners()
+{
+    EventTarget::removeAllEventListeners();
+
+    if (DOMWindow* domWindow = this->domWindow())
+        domWindow->removeAllEventListeners();
+    for (Node* node = firstChild(); node; node = NodeTraversal::next(node))
+        node->removeAllEventListeners();
+}
+
+void Document::suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension why)
+{
+    ScriptExecutionContext::suspendActiveDOMObjects(why);
+}
+
+void Document::resumeActiveDOMObjects()
+{
+    ScriptExecutionContext::resumeActiveDOMObjects();
+}
+
+void Document::clearAXObjectCache()
+{
+    ASSERT(topDocument() == this);
+    // Clear the cache member variable before calling delete because attempts
+    // are made to access it during destruction.
+    m_axObjectCache.clear();
+}
+
+AXObjectCache* Document::existingAXObjectCache() const
+{
+    if (!AXObjectCache::accessibilityEnabled())
+        return 0;
+
+    // If the renderer is gone then we are in the process of destruction.
+    // This method will be called before m_frame = 0.
+    if (!topDocument()->renderer())
+        return 0;
+
+    return topDocument()->m_axObjectCache.get();
+}
+
+AXObjectCache* Document::axObjectCache() const
+{
+    if (!AXObjectCache::accessibilityEnabled())
+        return 0;
+
+    // The only document that actually has a AXObjectCache is the top-level
+    // document.  This is because we need to be able to get from any WebCoreAXObject
+    // to any other WebCoreAXObject on the same page.  Using a single cache allows
+    // lookups across nested webareas (i.e. multiple documents).
+    Document* topDocument = this->topDocument();
+
+    // If the document has already been detached, do not make a new axObjectCache.
+    if (!topDocument->renderer())
+        return 0;
+
+    ASSERT(topDocument == this || !m_axObjectCache);
+    if (!topDocument->m_axObjectCache)
+        topDocument->m_axObjectCache = adoptPtr(new AXObjectCache(topDocument));
+    return topDocument->m_axObjectCache.get();
+}
+
+void Document::setVisuallyOrdered()
+{
+    m_visuallyOrdered = true;
+    if (renderer())
+        renderer()->style()->setRTLOrdering(VisualOrder);
+}
+
+PassRefPtr<DocumentParser> Document::createParser()
+{
+    // FIXME: this should probably pass the frame instead
+    return XMLDocumentParser::create(this, view());
+}
+
+ScriptableDocumentParser* Document::scriptableDocumentParser() const
+{
+    return parser() ? parser()->asScriptableDocumentParser() : 0;
+}
+
+void Document::open(Document* ownerDocument)
+{
+    if (ownerDocument) {
+        setURL(ownerDocument->url());
+        m_cookieURL = ownerDocument->cookieURL();
+        setSecurityOrigin(ownerDocument->securityOrigin());
+    }
+
+    if (m_frame) {
+        if (ScriptableDocumentParser* parser = scriptableDocumentParser()) {
+            if (parser->isParsing()) {
+                // FIXME: HTML5 doesn't tell us to check this, it might not be correct.
+                if (parser->isExecutingScript())
+                    return;
+
+                if (!parser->wasCreatedByScript() && parser->hasInsertionPoint())
+                    return;
+            }
+        }
+
+        if (m_frame->loader()->state() == FrameStateProvisional)
+            m_frame->loader()->stopAllLoaders();
+    }
+
+    removeAllEventListeners();
+    implicitOpen();
+    if (ScriptableDocumentParser* parser = scriptableDocumentParser())
+        parser->setWasCreatedByScript(true);
+
+    if (DOMWindow* domWindow = this->domWindow())
+        domWindow->removeAllEventListeners();
+
+    if (m_frame)
+        m_frame->loader()->didExplicitOpen();
+}
+
+void Document::detachParser()
+{
+    if (!m_parser)
+        return;
+    m_parser->detach();
+    m_parser.clear();
+}
+
+void Document::cancelParsing()
+{
+    if (!m_parser)
+        return;
+
+    // We have to clear the parser to avoid possibly triggering
+    // the onload handler when closing as a side effect of a cancel-style
+    // change, such as opening a new document or closing the window while
+    // still parsing
+    detachParser();
+    explicitClose();
+}
+
+void Document::implicitOpen()
+{
+    cancelParsing();
+
+    removeChildren();
+
+    setCompatibilityMode(NoQuirksMode);
+
+    // Documents rendered seamlessly should start out requiring a stylesheet
+    // collection update in order to ensure they inherit all the relevant data
+    // from their parent.
+    if (shouldDisplaySeamlesslyWithParent())
+        styleResolverChanged(DeferRecalcStyle);
+
+    m_parser = createParser();
+    setParsing(true);
+    setReadyState(Loading);
+}
+
+HTMLElement* Document::body() const
+{
+    Node* de = documentElement();
+    if (!de)
+        return 0;
+
+    // try to prefer a FRAMESET element over BODY
+    Node* body = 0;
+    for (Node* i = de->firstChild(); i; i = i->nextSibling()) {
+        if (i->hasTagName(framesetTag))
+            return toHTMLElement(i);
+
+        if (i->hasTagName(bodyTag) && !body)
+            body = i;
+    }
+    return toHTMLElement(body);
+}
+
+void Document::setBody(PassRefPtr<HTMLElement> prpNewBody, ExceptionCode& ec)
+{
+    RefPtr<HTMLElement> newBody = prpNewBody;
+
+    if (!newBody || !documentElement() || !newBody->hasTagName(bodyTag)) {
+        ec = HIERARCHY_REQUEST_ERR;
+        return;
+    }
+
+    if (newBody->document() && newBody->document() != this) {
+        ec = 0;
+        RefPtr<Node> node = importNode(newBody.get(), true, ec);
+        if (ec)
+            return;
+
+        newBody = toHTMLElement(node.get());
+    }
+
+    HTMLElement* b = body();
+    if (!b)
+        documentElement()->appendChild(newBody.release(), ec);
+    else
+        documentElement()->replaceChild(newBody.release(), b, ec);
+}
+
+HTMLHeadElement* Document::head()
+{
+    Node* de = documentElement();
+    if (!de)
+        return 0;
+
+    for (Node* e = de->firstChild(); e; e = e->nextSibling())
+        if (e->hasTagName(headTag))
+            return static_cast<HTMLHeadElement*>(e);
+
+    return 0;
+}
+
+void Document::close()
+{
+    // FIXME: We should follow the specification more closely:
+    //        http://www.whatwg.org/specs/web-apps/current-work/#dom-document-close
+
+    if (!scriptableDocumentParser() || !scriptableDocumentParser()->wasCreatedByScript() || !scriptableDocumentParser()->isParsing())
+        return;
+
+    explicitClose();
+}
+
+void Document::explicitClose()
+{
+    if (RefPtr<DocumentParser> parser = m_parser)
+        parser->finish();
+
+    if (!m_frame) {
+        // Because we have no frame, we don't know if all loading has completed,
+        // so we just call implicitClose() immediately. FIXME: This might fire
+        // the load event prematurely <http://bugs.webkit.org/show_bug.cgi?id=14568>.
+        implicitClose();
+        return;
+    }
+
+    m_frame->loader()->checkCompleted();
+}
+
+void Document::implicitClose()
+{
+    // If we're in the middle of recalcStyle, we need to defer the close until the style information is accurate and all elements are re-attached.
+    if (m_inStyleRecalc) {
+        m_closeAfterStyleRecalc = true;
+        return;
+    }
+
+    bool wasLocationChangePending = frame() && frame()->navigationScheduler()->locationChangePending();
+    bool doload = !parsing() && m_parser && !m_processingLoadEvent && !wasLocationChangePending;
+
+    if (!doload)
+        return;
+
+    // Call to dispatchWindowLoadEvent can blow us from underneath.
+    RefPtr<Document> protect(this);
+
+    m_processingLoadEvent = true;
+
+    ScriptableDocumentParser* parser = scriptableDocumentParser();
+    m_wellFormed = parser && parser->wellFormed();
+
+    // We have to clear the parser, in case someone document.write()s from the
+    // onLoad event handler, as in Radar 3206524.
+    detachParser();
+
+    Frame* f = frame();
+    if (f)
+        f->animation()->resumeAnimationsForDocument(this);
+
+    ImageLoader::dispatchPendingBeforeLoadEvents();
+    ImageLoader::dispatchPendingLoadEvents();
+    ImageLoader::dispatchPendingErrorEvents();
+
+    HTMLLinkElement::dispatchPendingLoadEvents();
+    HTMLStyleElement::dispatchPendingLoadEvents();
+
+#if ENABLE(SVG)
+    // To align the HTML load event and the SVGLoad event for the outermost <svg> element, fire it from
+    // here, instead of doing it from SVGElement::finishedParsingChildren (if externalResourcesRequired="false",
+    // which is the default, for ='true' its fired at a later time, once all external resources finished loading).
+    if (svgExtensions())
+        accessSVGExtensions()->dispatchSVGLoadEventToOutermostSVGElements();
+#endif
+
+    dispatchWindowLoadEvent();
+    enqueuePageshowEvent(PageshowEventNotPersisted);
+    enqueuePopstateEvent(m_pendingStateObject ? m_pendingStateObject.release() : SerializedScriptValue::nullValue());
+
+    if (f)
+        f->loader()->handledOnloadEvents();
+#ifdef INSTRUMENT_LAYOUT_SCHEDULING
+    if (!ownerElement())
+        printf("onload fired at %d\n", elapsedTime());
+#endif
+
+    // An event handler may have removed the frame
+    if (!frame()) {
+        m_processingLoadEvent = false;
+        return;
+    }
+
+    // Make sure both the initial layout and reflow happen after the onload
+    // fires. This will improve onload scores, and other browsers do it.
+    // If they wanna cheat, we can too. -dwh
+
+    if (frame()->navigationScheduler()->locationChangePending() && elapsedTime() < cLayoutScheduleThreshold) {
+        // Just bail out. Before or during the onload we were shifted to another page.
+        // The old i-Bench suite does this. When this happens don't bother painting or laying out.
+        m_processingLoadEvent = false;
+        view()->unscheduleRelayout();
+        return;
+    }
+
+    frame()->loader()->checkCallImplicitClose();
+    RenderObject* renderObject = renderer();
+
+    // We used to force a synchronous display and flush here.  This really isn't
+    // necessary and can in fact be actively harmful if pages are loading at a rate of > 60fps
+    // (if your platform is syncing flushes and limiting them to 60fps).
+    m_overMinimumLayoutThreshold = true;
+    if (!ownerElement() || (ownerElement()->renderer() && !ownerElement()->renderer()->needsLayout())) {
+        updateStyleIfNeeded();
+
+        // Always do a layout after loading if needed.
+        if (view() && renderObject && (!renderObject->firstChild() || renderObject->needsLayout()))
+            view()->layout();
+    }
+
+    m_processingLoadEvent = false;
+
+    if (f && renderObject && AXObjectCache::accessibilityEnabled()) {
+        // The AX cache may have been cleared at this point, but we need to make sure it contains an
+        // AX object to send the notification to. getOrCreate will make sure that an valid AX object
+        // exists in the cache (we ignore the return value because we don't need it here). This is
+        // only safe to call when a layout is not in progress, so it can not be used in postNotification.
+        if (AXObjectCache* cache = axObjectCache()) {
+            cache->getOrCreate(renderObject);
+            if (this == topDocument())
+                cache->postNotification(renderObject, AXObjectCache::AXLoadComplete, true);
+            else {
+                // AXLoadComplete can only be posted on the top document, so if it's a document
+                // in an iframe that just finished loading, post AXLayoutComplete instead.
+                cache->postNotification(renderObject, AXObjectCache::AXLayoutComplete, true);
+            }
+        }
+    }
+
+#if ENABLE(SVG)
+    if (svgExtensions())
+        accessSVGExtensions()->startAnimations();
+#endif
+}
+
+void Document::setParsing(bool b)
+{
+    m_bParsing = b;
+
+    if (m_bParsing && !m_sharedObjectPool)
+        m_sharedObjectPool = DocumentSharedObjectPool::create();
+
+    if (!m_bParsing && view())
+        view()->scheduleRelayout();
+
+#ifdef INSTRUMENT_LAYOUT_SCHEDULING
+    if (!ownerElement() && !m_bParsing)
+        printf("Parsing finished at %d\n", elapsedTime());
+#endif
+}
+
+bool Document::shouldScheduleLayout()
+{
+    // This function will only be called when FrameView thinks a layout is needed.
+    // This enforces a couple extra rules.
+    //
+    //    (a) Only schedule a layout once the stylesheets are loaded.
+    //    (b) Only schedule layout once we have a body element.
+
+    return (haveStylesheetsLoaded() && body())
+        || (documentElement() && !documentElement()->hasTagName(htmlTag));
+}
+
+bool Document::isLayoutTimerActive()
+{
+    return view() && view()->layoutPending() && !minimumLayoutDelay();
+}
+
+int Document::minimumLayoutDelay()
+{
+    if (m_overMinimumLayoutThreshold)
+        return 0;
+
+    int elapsed = elapsedTime();
+    m_overMinimumLayoutThreshold = elapsed > cLayoutScheduleThreshold;
+
+    // We'll want to schedule the timer to fire at the minimum layout threshold.
+    return max(0, cLayoutScheduleThreshold - elapsed);
+}
+
+int Document::elapsedTime() const
+{
+    return static_cast<int>((currentTime() - m_startTime) * 1000);
+}
+
+void Document::write(const SegmentedString& text, Document* ownerDocument)
+{
+    NestingLevelIncrementer nestingLevelIncrementer(m_writeRecursionDepth);
+
+    m_writeRecursionIsTooDeep = (m_writeRecursionDepth > 1) && m_writeRecursionIsTooDeep;
+    m_writeRecursionIsTooDeep = (m_writeRecursionDepth > cMaxWriteRecursionDepth) || m_writeRecursionIsTooDeep;
+
+    if (m_writeRecursionIsTooDeep)
+       return;
+
+#ifdef INSTRUMENT_LAYOUT_SCHEDULING
+    if (!ownerElement())
+        printf("Beginning a document.write at %d\n", elapsedTime());
+#endif
+
+    bool hasInsertionPoint = m_parser && m_parser->hasInsertionPoint();
+    if (!hasInsertionPoint && m_ignoreDestructiveWriteCount)
+        return;
+
+    if (!hasInsertionPoint)
+        open(ownerDocument);
+
+    ASSERT(m_parser);
+    m_parser->insert(text);
+
+#ifdef INSTRUMENT_LAYOUT_SCHEDULING
+    if (!ownerElement())
+        printf("Ending a document.write at %d\n", elapsedTime());
+#endif
+}
+
+void Document::write(const String& text, Document* ownerDocument)
+{
+    write(SegmentedString(text), ownerDocument);
+}
+
+void Document::writeln(const String& text, Document* ownerDocument)
+{
+    write(text, ownerDocument);
+    write("\n", ownerDocument);
+}
+
+const KURL& Document::virtualURL() const
+{
+    return m_url;
+}
+
+KURL Document::virtualCompleteURL(const String& url) const
+{
+    return completeURL(url);
+}
+
+double Document::timerAlignmentInterval() const
+{
+    Page* p = page();
+    if (!p)
+        return ScriptExecutionContext::timerAlignmentInterval();
+    return p->timerAlignmentInterval();
+}
+
+EventTarget* Document::errorEventTarget()
+{
+    return domWindow();
+}
+
+void Document::logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, PassRefPtr<ScriptCallStack> callStack)
+{
+    addMessage(JSMessageSource, ErrorMessageLevel, errorMessage, sourceURL, lineNumber, callStack);
+}
+
+void Document::setURL(const KURL& url)
+{
+    const KURL& newURL = url.isEmpty() ? blankURL() : url;
+    if (newURL == m_url)
+        return;
+
+    m_url = newURL;
+    m_documentURI = m_url.string();
+    updateBaseURL();
+    contextFeatures()->urlDidChange(this);
+}
+
+void Document::updateBaseURL()
+{
+    KURL oldBaseURL = m_baseURL;
+    // DOM 3 Core: When the Document supports the feature "HTML" [DOM Level 2 HTML], the base URI is computed using
+    // first the value of the href attribute of the HTML BASE element if any, and the value of the documentURI attribute
+    // from the Document interface otherwise.
+    if (!m_baseElementURL.isEmpty())
+        m_baseURL = m_baseElementURL;
+    else if (!m_baseURLOverride.isEmpty())
+        m_baseURL = m_baseURLOverride;
+    else {
+        // The documentURI attribute is read-only from JavaScript, but writable from Objective C, so we need to retain
+        // this fallback behavior. We use a null base URL, since the documentURI attribute is an arbitrary string
+        // and DOM 3 Core does not specify how it should be resolved.
+        // FIXME: Now that we don't support Objective-C this can probably be removed.
+        m_baseURL = KURL(ParsedURLString, documentURI());
+    }
+    selectorQueryCache()->invalidate();
+
+    if (!m_baseURL.isValid())
+        m_baseURL = KURL();
+
+    if (m_elemSheet) {
+        // Element sheet is silly. It never contains anything.
+        ASSERT(!m_elemSheet->contents()->ruleCount());
+        bool usesRemUnits = m_elemSheet->contents()->usesRemUnits();
+        m_elemSheet = CSSStyleSheet::createInline(this, m_baseURL);
+        // FIXME: So we are not really the parser. The right fix is to eliminate the element sheet completely.
+        m_elemSheet->contents()->parserSetUsesRemUnits(usesRemUnits);
+    }
+
+    if (!equalIgnoringFragmentIdentifier(oldBaseURL, m_baseURL)) {
+        // Base URL change changes any relative visited links.
+        // FIXME: There are other URLs in the tree that would need to be re-evaluated on dynamic base URL change. Style should be invalidated too.
+        for (Element* element = ElementTraversal::firstWithin(this); element; element = ElementTraversal::next(element)) {
+            if (element->hasTagName(aTag))
+                static_cast<HTMLAnchorElement*>(element)->invalidateCachedVisitedLinkHash();
+        }
+    }
+}
+
+void Document::setBaseURLOverride(const KURL& url)
+{
+    m_baseURLOverride = url;
+    updateBaseURL();
+}
+
+void Document::processBaseElement()
+{
+    // Find the first href attribute in a base element and the first target attribute in a base element.
+    const AtomicString* href = 0;
+    const AtomicString* target = 0;
+    for (Element* element = ElementTraversal::firstWithin(this); element && (!href || !target); element = ElementTraversal::next(element)) {
+        if (element->hasTagName(baseTag)) {
+            if (!href) {
+                const AtomicString& value = element->fastGetAttribute(hrefAttr);
+                if (!value.isNull())
+                    href = &value;
+            }
+            if (!target) {
+                const AtomicString& value = element->fastGetAttribute(targetAttr);
+                if (!value.isNull())
+                    target = &value;
+            }
+            if (contentSecurityPolicy()->isActive())
+                UseCounter::count(this, UseCounter::ContentSecurityPolicyWithBaseElement);
+        }
+    }
+
+    // FIXME: Since this doesn't share code with completeURL it may not handle encodings correctly.
+    KURL baseElementURL;
+    if (href) {
+        String strippedHref = stripLeadingAndTrailingHTMLSpaces(*href);
+        if (!strippedHref.isEmpty())
+            baseElementURL = KURL(url(), strippedHref);
+    }
+    if (m_baseElementURL != baseElementURL && contentSecurityPolicy()->allowBaseURI(baseElementURL)) {
+        m_baseElementURL = baseElementURL;
+        updateBaseURL();
+    }
+
+    m_baseTarget = target ? *target : nullAtom;
+}
+
+String Document::userAgent(const KURL& url) const
+{
+    return frame() ? frame()->loader()->userAgent(url) : String();
+}
+
+void Document::disableEval(const String& errorMessage)
+{
+    if (!frame())
+        return;
+
+    frame()->script()->disableEval(errorMessage);
+}
+
+bool Document::canNavigate(Frame* targetFrame)
+{
+    if (!m_frame)
+        return false;
+
+    // FIXME: We shouldn't call this function without a target frame, but
+    // fast/forms/submit-to-blank-multiple-times.html depends on this function
+    // returning true when supplied with a 0 targetFrame.
+    if (!targetFrame)
+        return true;
+
+    // Frame-busting is generally allowed, but blocked for sandboxed frames lacking the 'allow-top-navigation' flag.
+    if (!isSandboxed(SandboxTopNavigation) && targetFrame == m_frame->tree()->top())
+        return true;
+
+    if (isSandboxed(SandboxNavigation)) {
+        if (targetFrame->tree()->isDescendantOf(m_frame))
+            return true;
+
+        const char* reason = "The frame attempting navigation is sandboxed, and is therefore disallowed from navigating its ancestors.";
+        if (isSandboxed(SandboxTopNavigation) && targetFrame == m_frame->tree()->top())
+            reason = "The frame attempting navigation of the top-level window is sandboxed, but the 'allow-top-navigation' flag is not set.";
+
+        printNavigationErrorMessage(targetFrame, url(), reason);
+        return false;
+    }
+
+    // This is the normal case. A document can navigate its decendant frames,
+    // or, more generally, a document can navigate a frame if the document is
+    // in the same origin as any of that frame's ancestors (in the frame
+    // hierarchy).
+    //
+    // See http://www.adambarth.com/papers/2008/barth-jackson-mitchell.pdf for
+    // historical information about this security check.
+    if (canAccessAncestor(securityOrigin(), targetFrame))
+        return true;
+
+    // Top-level frames are easier to navigate than other frames because they
+    // display their URLs in the address bar (in most browsers). However, there
+    // are still some restrictions on navigation to avoid nuisance attacks.
+    // Specifically, a document can navigate a top-level frame if that frame
+    // opened the document or if the document is the same-origin with any of
+    // the top-level frame's opener's ancestors (in the frame hierarchy).
+    //
+    // In both of these cases, the document performing the navigation is in
+    // some way related to the frame being navigate (e.g., by the "opener"
+    // and/or "parent" relation). Requiring some sort of relation prevents a
+    // document from navigating arbitrary, unrelated top-level frames.
+    if (!targetFrame->tree()->parent()) {
+        if (targetFrame == m_frame->loader()->opener())
+            return true;
+
+        if (canAccessAncestor(securityOrigin(), targetFrame->loader()->opener()))
+            return true;
+    }
+
+    printNavigationErrorMessage(targetFrame, url(), "The frame attempting navigation is neither same-origin with the target, nor is it the target's parent or opener.");
+    return false;
+}
+
+Frame* Document::findUnsafeParentScrollPropagationBoundary()
+{
+    Frame* currentFrame = m_frame;
+    Frame* ancestorFrame = currentFrame->tree()->parent();
+
+    while (ancestorFrame) {
+        if (!ancestorFrame->document()->securityOrigin()->canAccess(securityOrigin()))
+            return currentFrame;
+        currentFrame = ancestorFrame;
+        ancestorFrame = ancestorFrame->tree()->parent();
+    }
+    return 0;
+}
+
+
+void Document::seamlessParentUpdatedStylesheets()
+{
+    styleResolverChanged(RecalcStyleImmediately);
+}
+
+void Document::didRemoveAllPendingStylesheet()
+{
+    m_needsNotifyRemoveAllPendingStylesheet = false;
+
+    styleResolverChanged(RecalcStyleIfNeeded);
+
+    if (ScriptableDocumentParser* parser = scriptableDocumentParser())
+        parser->executeScriptsWaitingForStylesheets();
+
+    if (m_gotoAnchorNeededAfterStylesheetsLoad && view())
+        view()->scrollToFragment(m_url);
+}
+
+CSSStyleSheet* Document::elementSheet()
+{
+    if (!m_elemSheet)
+        m_elemSheet = CSSStyleSheet::createInline(this, m_baseURL);
+    return m_elemSheet.get();
+}
+
+int Document::nodeAbsIndex(Node *node)
+{
+    ASSERT(node->document() == this);
+
+    int absIndex = 0;
+    for (Node* n = node; n && n != this; n = NodeTraversal::previous(n))
+        absIndex++;
+    return absIndex;
+}
+
+Node* Document::nodeWithAbsIndex(int absIndex)
+{
+    Node* n = this;
+    for (int i = 0; n && (i < absIndex); i++)
+        n = NodeTraversal::next(n);
+    return n;
+}
+
+void Document::processHttpEquiv(const String& equiv, const String& content)
+{
+    ASSERT(!equiv.isNull() && !content.isNull());
+
+    Frame* frame = this->frame();
+
+    if (equalIgnoringCase(equiv, "default-style")) {
+        // The preferred style set has been overridden as per section
+        // 14.3.2 of the HTML4.0 specification.  We need to update the
+        // sheet used variable and then update our style selector.
+        // For more info, see the test at:
+        // http://www.hixie.ch/tests/evil/css/import/main/preferred.html
+        // -dwh
+        m_styleSheetCollection->setSelectedStylesheetSetName(content);
+        m_styleSheetCollection->setPreferredStylesheetSetName(content);
+        styleResolverChanged(DeferRecalcStyle);
+    } else if (equalIgnoringCase(equiv, "refresh")) {
+        double delay;
+        String url;
+        if (frame && parseHTTPRefresh(content, true, delay, url)) {
+            if (url.isEmpty())
+                url = m_url.string();
+            else
+                url = completeURL(url).string();
+            frame->navigationScheduler()->scheduleRedirect(delay, url);
+        }
+    } else if (equalIgnoringCase(equiv, "set-cookie")) {
+        // FIXME: make setCookie work on XML documents too; e.g. in case of <html:meta .....>
+        if (isHTMLDocument()) {
+            // Exception (for sandboxed documents) ignored.
+            toHTMLDocument(this)->setCookie(content, IGNORE_EXCEPTION);
+        }
+    } else if (equalIgnoringCase(equiv, "content-language"))
+        setContentLanguage(content);
+    else if (equalIgnoringCase(equiv, "x-dns-prefetch-control"))
+        parseDNSPrefetchControlHeader(content);
+    else if (equalIgnoringCase(equiv, "x-frame-options")) {
+        if (frame) {
+            FrameLoader* frameLoader = frame->loader();
+            unsigned long requestIdentifier = 0;
+            if (frameLoader->activeDocumentLoader() && frameLoader->activeDocumentLoader()->mainResourceLoader())
+                requestIdentifier = frameLoader->activeDocumentLoader()->mainResourceLoader()->identifier();
+            if (frameLoader->shouldInterruptLoadForXFrameOptions(content, url(), requestIdentifier)) {
+                String message = "Refused to display '" + url().elidedString() + "' in a frame because it set 'X-Frame-Options' to '" + content + "'.";
+                frameLoader->stopAllLoaders();
+                // Stopping the loader isn't enough, as we're already parsing the document; to honor the header's
+                // intent, we must navigate away from the possibly partially-rendered document to a location that
+                // doesn't inherit the parent's SecurityOrigin.
+                frame->navigationScheduler()->scheduleLocationChange(securityOrigin(), SecurityOrigin::urlWithUniqueSecurityOrigin(), String());
+                addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, message, requestIdentifier);
+            }
+        }
+    } else if (equalIgnoringCase(equiv, "content-security-policy"))
+        contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::Enforce);
+    else if (equalIgnoringCase(equiv, "content-security-policy-report-only"))
+        contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::Report);
+    else if (equalIgnoringCase(equiv, "x-webkit-csp"))
+        contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::PrefixedEnforce);
+    else if (equalIgnoringCase(equiv, "x-webkit-csp-report-only"))
+        contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::PrefixedReport);
+}
+
+// Though isspace() considers \t and \v to be whitespace, Win IE doesn't.
+static bool isSeparator(UChar c)
+{
+    return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' || c == ',' || c == '\0';
+}
+
+void Document::processArguments(const String& features, void* data, ArgumentsCallback callback)
+{
+    // Tread lightly in this code -- it was specifically designed to mimic Win IE's parsing behavior.
+    int keyBegin, keyEnd;
+    int valueBegin, valueEnd;
+
+    int i = 0;
+    int length = features.length();
+    String buffer = features.lower();
+    while (i < length) {
+        // skip to first non-separator, but don't skip past the end of the string
+        while (isSeparator(buffer[i])) {
+            if (i >= length)
+                break;
+            i++;
+        }
+        keyBegin = i;
+
+        // skip to first separator
+        while (!isSeparator(buffer[i]))
+            i++;
+        keyEnd = i;
+
+        // skip to first '=', but don't skip past a ',' or the end of the string
+        while (buffer[i] != '=') {
+            if (buffer[i] == ',' || i >= length)
+                break;
+            i++;
+        }
+
+        // skip to first non-separator, but don't skip past a ',' or the end of the string
+        while (isSeparator(buffer[i])) {
+            if (buffer[i] == ',' || i >= length)
+                break;
+            i++;
+        }
+        valueBegin = i;
+
+        // skip to first separator
+        while (!isSeparator(buffer[i]))
+            i++;
+        valueEnd = i;
+
+        ASSERT_WITH_SECURITY_IMPLICATION(i <= length);
+
+        String keyString = buffer.substring(keyBegin, keyEnd - keyBegin);
+        String valueString = buffer.substring(valueBegin, valueEnd - valueBegin);
+        callback(keyString, valueString, this, data);
+    }
+}
+
+void Document::processViewport(const String& features, ViewportArguments::Type origin)
+{
+    ASSERT(!features.isNull());
+
+    if (origin < m_viewportArguments.type)
+        return;
+
+    m_viewportArguments = ViewportArguments(origin);
+    processArguments(features, (void*)&m_viewportArguments, &setViewportFeature);
+
+    updateViewportArguments();
+}
+
+void Document::updateViewportArguments()
+{
+    if (page() && page()->mainFrame() == frame()) {
+#ifndef NDEBUG
+        m_didDispatchViewportPropertiesChanged = true;
+#endif
+        page()->chrome()->dispatchViewportPropertiesDidChange(m_viewportArguments);
+    }
+}
+
+void Document::processReferrerPolicy(const String& policy)
+{
+    ASSERT(!policy.isNull());
+
+    m_referrerPolicy = ReferrerPolicyDefault;
+
+    if (equalIgnoringCase(policy, "never"))
+        m_referrerPolicy = ReferrerPolicyNever;
+    else if (equalIgnoringCase(policy, "always"))
+        m_referrerPolicy = ReferrerPolicyAlways;
+    else if (equalIgnoringCase(policy, "origin"))
+        m_referrerPolicy = ReferrerPolicyOrigin;
+}
+
+MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& request, const LayoutPoint& documentPoint, const PlatformMouseEvent& event)
+{
+    ASSERT(!renderer() || renderer()->isRenderView());
+
+    if (!renderer())
+        return MouseEventWithHitTestResults(event, HitTestResult(LayoutPoint()));
+
+    HitTestResult result(documentPoint);
+    renderView()->hitTest(request, result);
+
+    if (!request.readOnly())
+        updateHoverActiveState(request, result.innerElement());
+
+    return MouseEventWithHitTestResults(event, result);
+}
+
+// DOM Section 1.1.1
+bool Document::childTypeAllowed(NodeType type) const
+{
+    switch (type) {
+    case ATTRIBUTE_NODE:
+    case CDATA_SECTION_NODE:
+    case DOCUMENT_FRAGMENT_NODE:
+    case DOCUMENT_NODE:
+    case ENTITY_NODE:
+    case ENTITY_REFERENCE_NODE:
+    case NOTATION_NODE:
+    case TEXT_NODE:
+    case XPATH_NAMESPACE_NODE:
+        return false;
+    case COMMENT_NODE:
+    case PROCESSING_INSTRUCTION_NODE:
+        return true;
+    case DOCUMENT_TYPE_NODE:
+    case ELEMENT_NODE:
+        // Documents may contain no more than one of each of these.
+        // (One Element and one DocumentType.)
+        for (Node* c = firstChild(); c; c = c->nextSibling())
+            if (c->nodeType() == type)
+                return false;
+        return true;
+    }
+    return false;
+}
+
+bool Document::canReplaceChild(Node* newChild, Node* oldChild)
+{
+    if (!oldChild)
+        // ContainerNode::replaceChild will raise a NOT_FOUND_ERR.
+        return true;
+
+    if (oldChild->nodeType() == newChild->nodeType())
+        return true;
+
+    int numDoctypes = 0;
+    int numElements = 0;
+
+    // First, check how many doctypes and elements we have, not counting
+    // the child we're about to remove.
+    for (Node* c = firstChild(); c; c = c->nextSibling()) {
+        if (c == oldChild)
+            continue;
+
+        switch (c->nodeType()) {
+        case DOCUMENT_TYPE_NODE:
+            numDoctypes++;
+            break;
+        case ELEMENT_NODE:
+            numElements++;
+            break;
+        default:
+            break;
+        }
+    }
+
+    // Then, see how many doctypes and elements might be added by the new child.
+    if (newChild->nodeType() == DOCUMENT_FRAGMENT_NODE) {
+        for (Node* c = newChild->firstChild(); c; c = c->nextSibling()) {
+            switch (c->nodeType()) {
+            case ATTRIBUTE_NODE:
+            case CDATA_SECTION_NODE:
+            case DOCUMENT_FRAGMENT_NODE:
+            case DOCUMENT_NODE:
+            case ENTITY_NODE:
+            case ENTITY_REFERENCE_NODE:
+            case NOTATION_NODE:
+            case TEXT_NODE:
+            case XPATH_NAMESPACE_NODE:
+                return false;
+            case COMMENT_NODE:
+            case PROCESSING_INSTRUCTION_NODE:
+                break;
+            case DOCUMENT_TYPE_NODE:
+                numDoctypes++;
+                break;
+            case ELEMENT_NODE:
+                numElements++;
+                break;
+            }
+        }
+    } else {
+        switch (newChild->nodeType()) {
+        case ATTRIBUTE_NODE:
+        case CDATA_SECTION_NODE:
+        case DOCUMENT_FRAGMENT_NODE:
+        case DOCUMENT_NODE:
+        case ENTITY_NODE:
+        case ENTITY_REFERENCE_NODE:
+        case NOTATION_NODE:
+        case TEXT_NODE:
+        case XPATH_NAMESPACE_NODE:
+            return false;
+        case COMMENT_NODE:
+        case PROCESSING_INSTRUCTION_NODE:
+            return true;
+        case DOCUMENT_TYPE_NODE:
+            numDoctypes++;
+            break;
+        case ELEMENT_NODE:
+            numElements++;
+            break;
+        }
+    }
+
+    if (numElements > 1 || numDoctypes > 1)
+        return false;
+
+    return true;
+}
+
+PassRefPtr<Node> Document::cloneNode(bool /*deep*/)
+{
+    // Spec says cloning Document nodes is "implementation dependent"
+    // so we do not support it...
+    return 0;
+}
+
+StyleSheetList* Document::styleSheets()
+{
+    if (!m_styleSheetList)
+        m_styleSheetList = StyleSheetList::create(this);
+    return m_styleSheetList.get();
+}
+
+String Document::preferredStylesheetSet() const
+{
+    return m_styleSheetCollection->preferredStylesheetSetName();
+}
+
+String Document::selectedStylesheetSet() const
+{
+    return m_styleSheetCollection->selectedStylesheetSetName();
+}
+
+void Document::setSelectedStylesheetSet(const String& aString)
+{
+    m_styleSheetCollection->setSelectedStylesheetSetName(aString);
+    styleResolverChanged(DeferRecalcStyle);
+}
+
+void Document::evaluateMediaQueryList()
+{
+    if (m_mediaQueryMatcher)
+        m_mediaQueryMatcher->styleResolverChanged();
+}
+
+void Document::styleResolverChanged(StyleResolverUpdateFlag updateFlag)
+{
+    // Don't bother updating, since we haven't loaded all our style info yet
+    // and haven't calculated the style selector for the first time.
+    if (!attached() || (!m_didCalculateStyleResolver && !haveStylesheetsLoaded())) {
+        m_styleResolver.clear();
+        return;
+    }
+    m_didCalculateStyleResolver = true;
+
+#ifdef INSTRUMENT_LAYOUT_SCHEDULING
+    if (!ownerElement())
+        printf("Beginning update of style selector at time %d.\n", elapsedTime());
+#endif
+
+    DocumentStyleSheetCollection::UpdateFlag styleSheetUpdate = (updateFlag == RecalcStyleIfNeeded)
+        ? DocumentStyleSheetCollection::OptimizedUpdate
+        : DocumentStyleSheetCollection::FullUpdate;
+    bool stylesheetChangeRequiresStyleRecalc = m_styleSheetCollection->updateActiveStyleSheets(styleSheetUpdate);
+
+    if (updateFlag == DeferRecalcStyle) {
+        scheduleForcedStyleRecalc();
+        return;
+    }
+
+    if (didLayoutWithPendingStylesheets() && !m_styleSheetCollection->hasPendingSheets()) {
+        m_pendingSheetLayout = IgnoreLayoutWithPendingSheets;
+        if (renderer())
+            renderView()->repaintViewAndCompositedLayers();
+    }
+
+    if (!stylesheetChangeRequiresStyleRecalc)
+        return;
+
+    // This recalcStyle initiates a new recalc cycle. We need to bracket it to
+    // make sure animations get the correct update time
+    {
+        AnimationUpdateBlock animationUpdateBlock(m_frame ? m_frame->animation() : 0);
+        recalcStyle(Force);
+    }
+
+#ifdef INSTRUMENT_LAYOUT_SCHEDULING
+    if (!ownerElement())
+        printf("Finished update of style selector at time %d\n", elapsedTime());
+#endif
+
+    if (renderer()) {
+        renderer()->setNeedsLayoutAndPrefWidthsRecalc();
+        if (view())
+            view()->scheduleRelayout();
+    }
+
+    evaluateMediaQueryList();
+}
+
+void Document::notifySeamlessChildDocumentsOfStylesheetUpdate() const
+{
+    // If we're not in a frame yet any potential child documents won't have a StyleResolver to update.
+    if (!frame())
+        return;
+
+    // Seamless child frames are expected to notify their seamless children recursively, so we only do direct children.
+    for (Frame* child = frame()->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
+        Document* childDocument = child->document();
+        if (childDocument->shouldDisplaySeamlesslyWithParent()) {
+            ASSERT(childDocument->seamlessParentIFrame()->document() == this);
+            childDocument->seamlessParentUpdatedStylesheets();
+        }
+    }
+}
+
+void Document::setHoverNode(PassRefPtr<Node> newHoverNode)
+{
+    m_hoverNode = newHoverNode;
+}
+
+void Document::setActiveElement(PassRefPtr<Element> newActiveElement)
+{
+    if (!newActiveElement) {
+        m_activeElement.clear();
+        return;
+    }
+
+    m_activeElement = newActiveElement;
+}
+
+void Document::focusedNodeRemoved()
+{
+    setFocusedNode(0);
+}
+
+void Document::removeFocusedNodeOfSubtree(Node* node, bool amongChildrenOnly)
+{
+    if (!m_focusedNode)
+        return;
+
+    Node* focusedNode = node->treeScope()->focusedNode();
+    if (!focusedNode)
+        return;
+
+    bool nodeInSubtree = false;
+    if (amongChildrenOnly)
+        nodeInSubtree = focusedNode->isDescendantOf(node);
+    else
+        nodeInSubtree = (focusedNode == node) || focusedNode->isDescendantOf(node);
+
+    if (nodeInSubtree)
+        document()->focusedNodeRemoved();
+}
+
+void Document::hoveredNodeDetached(Node* node)
+{
+    if (!m_hoverNode || (node != m_hoverNode && (!m_hoverNode->isTextNode() || node != m_hoverNode->parentNode())))
+        return;
+
+    m_hoverNode = node->parentNode();
+    while (m_hoverNode && !m_hoverNode->renderer())
+        m_hoverNode = m_hoverNode->parentNode();
+    if (frame())
+        frame()->eventHandler()->scheduleHoverStateUpdate();
+}
+
+void Document::activeChainNodeDetached(Node* node)
+{
+    if (!m_activeElement || (node != m_activeElement && (!m_activeElement->isTextNode() || node != m_activeElement->parentNode())))
+        return;
+
+    m_activeElement = node->parentElement();
+    while (m_activeElement && !m_activeElement->renderer())
+        m_activeElement = m_activeElement->parentElement();
+}
+
+const Vector<AnnotatedRegionValue>& Document::annotatedRegions() const
+{
+    return m_annotatedRegions;
+}
+
+void Document::setAnnotatedRegions(const Vector<AnnotatedRegionValue>& regions)
+{
+    m_annotatedRegions = regions;
+    setAnnotatedRegionsDirty(false);
+}
+
+bool Document::setFocusedNode(PassRefPtr<Node> prpNewFocusedNode, FocusDirection direction)
+{
+    RefPtr<Node> newFocusedNode = prpNewFocusedNode;
+
+    // Make sure newFocusedNode is actually in this document
+    if (newFocusedNode && (newFocusedNode->document() != this))
+        return true;
+
+    if (m_focusedNode == newFocusedNode)
+        return true;
+
+    bool focusChangeBlocked = false;
+    RefPtr<Node> oldFocusedNode = m_focusedNode;
+    m_focusedNode = 0;
+
+    // Remove focus from the existing focus node (if any)
+    if (oldFocusedNode) {
+        ASSERT(!oldFocusedNode->inDetach());
+
+        if (oldFocusedNode->active())
+            oldFocusedNode->setActive(false);
+
+        oldFocusedNode->setFocus(false);
+
+        // Dispatch a change event for text fields or textareas that have been edited
+        if (oldFocusedNode->isElementNode()) {
+            Element* element = toElement(oldFocusedNode.get());
+            if (element->wasChangedSinceLastFormControlChangeEvent())
+                element->dispatchFormControlChangeEvent();
+        }
+
+        // Dispatch the blur event and let the node do any other blur related activities (important for text fields)
+        oldFocusedNode->dispatchBlurEvent(newFocusedNode);
+
+        if (m_focusedNode) {
+            // handler shifted focus
+            focusChangeBlocked = true;
+            newFocusedNode = 0;
+        }
+
+        oldFocusedNode->dispatchFocusOutEvent(eventNames().focusoutEvent, newFocusedNode); // DOM level 3 name for the bubbling blur event.
+        // FIXME: We should remove firing DOMFocusOutEvent event when we are sure no content depends
+        // on it, probably when <rdar://problem/8503958> is resolved.
+        oldFocusedNode->dispatchFocusOutEvent(eventNames().DOMFocusOutEvent, newFocusedNode); // DOM level 2 name for compatibility.
+
+        if (m_focusedNode) {
+            // handler shifted focus
+            focusChangeBlocked = true;
+            newFocusedNode = 0;
+        }
+        if (oldFocusedNode == this && oldFocusedNode->hasOneRef())
+            return true;
+
+        if (oldFocusedNode->isRootEditableElement())
+            frame()->editor()->didEndEditing();
+
+        if (view()) {
+            Widget* oldWidget = widgetForNode(oldFocusedNode.get());
+            if (oldWidget)
+                oldWidget->setFocus(false);
+            else
+                view()->setFocus(false);
+        }
+    }
+
+    if (newFocusedNode && newFocusedNode->isFocusable()) {
+        if (newFocusedNode->isRootEditableElement() && !acceptsEditingFocus(newFocusedNode.get())) {
+            // delegate blocks focus change
+            focusChangeBlocked = true;
+            goto SetFocusedNodeDone;
+        }
+        // Set focus on the new node
+        m_focusedNode = newFocusedNode;
+
+        // Dispatch the focus event and let the node do any other focus related activities (important for text fields)
+        m_focusedNode->dispatchFocusEvent(oldFocusedNode, direction);
+
+        if (m_focusedNode != newFocusedNode) {
+            // handler shifted focus
+            focusChangeBlocked = true;
+            goto SetFocusedNodeDone;
+        }
+
+        m_focusedNode->dispatchFocusInEvent(eventNames().focusinEvent, oldFocusedNode); // DOM level 3 bubbling focus event.
+
+        if (m_focusedNode != newFocusedNode) {
+            // handler shifted focus
+            focusChangeBlocked = true;
+            goto SetFocusedNodeDone;
+        }
+
+        // FIXME: We should remove firing DOMFocusInEvent event when we are sure no content depends
+        // on it, probably when <rdar://problem/8503958> is m.
+        m_focusedNode->dispatchFocusInEvent(eventNames().DOMFocusInEvent, oldFocusedNode); // DOM level 2 for compatibility.
+
+        if (m_focusedNode != newFocusedNode) {
+            // handler shifted focus
+            focusChangeBlocked = true;
+            goto SetFocusedNodeDone;
+        }
+        m_focusedNode->setFocus(true);
+
+        if (m_focusedNode->isRootEditableElement())
+            frame()->editor()->didBeginEditing();
+
+        // eww, I suck. set the qt focus correctly
+        // ### find a better place in the code for this
+        if (view()) {
+            Widget* focusWidget = widgetForNode(m_focusedNode.get());
+            if (focusWidget) {
+                // Make sure a widget has the right size before giving it focus.
+                // Otherwise, we are testing edge cases of the Widget code.
+                // Specifically, in WebCore this does not work well for text fields.
+                updateLayout();
+                // Re-get the widget in case updating the layout changed things.
+                focusWidget = widgetForNode(m_focusedNode.get());
+            }
+            if (focusWidget)
+                focusWidget->setFocus(true);
+            else
+                view()->setFocus(true);
+        }
+    }
+
+    if (!focusChangeBlocked && m_focusedNode) {
+        // Create the AXObject cache in a focus change because Chromium relies on it.
+        if (AXObjectCache* cache = axObjectCache())
+            cache->handleFocusedUIElementChanged(oldFocusedNode.get(), newFocusedNode.get());
+    }
+
+    if (!focusChangeBlocked)
+        page()->chrome()->focusedNodeChanged(m_focusedNode.get());
+
+SetFocusedNodeDone:
+    updateStyleIfNeeded();
+    return !focusChangeBlocked;
+}
+
+void Document::getFocusableNodes(Vector<RefPtr<Node> >& nodes)
+{
+    updateLayout();
+
+    for (Node* node = firstChild(); node; node = NodeTraversal::next(node)) {
+        if (node->isFocusable())
+            nodes.append(node);
+    }
+}
+
+void Document::setCSSTarget(Element* n)
+{
+    if (m_cssTarget)
+        m_cssTarget->didAffectSelector(AffectedSelectorTarget);
+    m_cssTarget = n;
+    if (n)
+        n->didAffectSelector(AffectedSelectorTarget);
+}
+
+void Document::registerNodeList(LiveNodeListBase* list)
+{
+    if (list->hasIdNameCache())
+        m_nodeListCounts[InvalidateOnIdNameAttrChange]++;
+    m_nodeListCounts[list->invalidationType()]++;
+    if (list->isRootedAtDocument())
+        m_listsInvalidatedAtDocument.add(list);
+}
+
+void Document::unregisterNodeList(LiveNodeListBase* list)
+{
+    if (list->hasIdNameCache())
+        m_nodeListCounts[InvalidateOnIdNameAttrChange]--;
+    m_nodeListCounts[list->invalidationType()]--;
+    if (list->isRootedAtDocument()) {
+        ASSERT(m_listsInvalidatedAtDocument.contains(list));
+        m_listsInvalidatedAtDocument.remove(list);
+    }
+}
+
+void Document::attachNodeIterator(NodeIterator* ni)
+{
+    m_nodeIterators.add(ni);
+}
+
+void Document::detachNodeIterator(NodeIterator* ni)
+{
+    // The node iterator can be detached without having been attached if its root node didn't have a document
+    // when the iterator was created, but has it now.
+    m_nodeIterators.remove(ni);
+}
+
+void Document::moveNodeIteratorsToNewDocument(Node* node, Document* newDocument)
+{
+    HashSet<NodeIterator*> nodeIteratorsList = m_nodeIterators;
+    HashSet<NodeIterator*>::const_iterator nodeIteratorsEnd = nodeIteratorsList.end();
+    for (HashSet<NodeIterator*>::const_iterator it = nodeIteratorsList.begin(); it != nodeIteratorsEnd; ++it) {
+        if ((*it)->root() == node) {
+            detachNodeIterator(*it);
+            newDocument->attachNodeIterator(*it);
+        }
+    }
+}
+
+void Document::updateRangesAfterChildrenChanged(ContainerNode* container)
+{
+    if (!m_ranges.isEmpty()) {
+        HashSet<Range*>::const_iterator end = m_ranges.end();
+        for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
+            (*it)->nodeChildrenChanged(container);
+    }
+}
+
+void Document::nodeChildrenWillBeRemoved(ContainerNode* container)
+{
+    if (!m_ranges.isEmpty()) {
+        HashSet<Range*>::const_iterator end = m_ranges.end();
+        for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
+            (*it)->nodeChildrenWillBeRemoved(container);
+    }
+
+    HashSet<NodeIterator*>::const_iterator nodeIteratorsEnd = m_nodeIterators.end();
+    for (HashSet<NodeIterator*>::const_iterator it = m_nodeIterators.begin(); it != nodeIteratorsEnd; ++it) {
+        for (Node* n = container->firstChild(); n; n = n->nextSibling())
+            (*it)->nodeWillBeRemoved(n);
+    }
+
+    if (Frame* frame = this->frame()) {
+        for (Node* n = container->firstChild(); n; n = n->nextSibling()) {
+            frame->eventHandler()->nodeWillBeRemoved(n);
+            frame->selection()->nodeWillBeRemoved(n);
+            frame->page()->dragCaretController()->nodeWillBeRemoved(n);
+        }
+    }
+}
+
+void Document::nodeWillBeRemoved(Node* n)
+{
+    HashSet<NodeIterator*>::const_iterator nodeIteratorsEnd = m_nodeIterators.end();
+    for (HashSet<NodeIterator*>::const_iterator it = m_nodeIterators.begin(); it != nodeIteratorsEnd; ++it)
+        (*it)->nodeWillBeRemoved(n);
+
+    if (!m_ranges.isEmpty()) {
+        HashSet<Range*>::const_iterator rangesEnd = m_ranges.end();
+        for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != rangesEnd; ++it)
+            (*it)->nodeWillBeRemoved(n);
+    }
+
+    if (Frame* frame = this->frame()) {
+        frame->eventHandler()->nodeWillBeRemoved(n);
+        frame->selection()->nodeWillBeRemoved(n);
+        frame->page()->dragCaretController()->nodeWillBeRemoved(n);
+    }
+}
+
+void Document::textInserted(Node* text, unsigned offset, unsigned length)
+{
+    if (!m_ranges.isEmpty()) {
+        HashSet<Range*>::const_iterator end = m_ranges.end();
+        for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
+            (*it)->textInserted(text, offset, length);
+    }
+
+    // Update the markers for spelling and grammar checking.
+    m_markers->shiftMarkers(text, offset, length);
+}
+
+void Document::textRemoved(Node* text, unsigned offset, unsigned length)
+{
+    if (!m_ranges.isEmpty()) {
+        HashSet<Range*>::const_iterator end = m_ranges.end();
+        for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
+            (*it)->textRemoved(text, offset, length);
+    }
+
+    // Update the markers for spelling and grammar checking.
+    m_markers->removeMarkers(text, offset, length);
+    m_markers->shiftMarkers(text, offset + length, 0 - length);
+}
+
+void Document::textNodesMerged(Text* oldNode, unsigned offset)
+{
+    if (!m_ranges.isEmpty()) {
+        NodeWithIndex oldNodeWithIndex(oldNode);
+        HashSet<Range*>::const_iterator end = m_ranges.end();
+        for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
+            (*it)->textNodesMerged(oldNodeWithIndex, offset);
+    }
+
+    // FIXME: This should update markers for spelling and grammar checking.
+}
+
+void Document::textNodeSplit(Text* oldNode)
+{
+    if (!m_ranges.isEmpty()) {
+        HashSet<Range*>::const_iterator end = m_ranges.end();
+        for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
+            (*it)->textNodeSplit(oldNode);
+    }
+
+    // FIXME: This should update markers for spelling and grammar checking.
+}
+
+void Document::createDOMWindow()
+{
+    ASSERT(m_frame);
+    ASSERT(!m_domWindow);
+
+    m_domWindow = DOMWindow::create(this);
+
+    ASSERT(m_domWindow->document() == this);
+    ASSERT(m_domWindow->frame() == m_frame);
+}
+
+void Document::takeDOMWindowFrom(Document* document)
+{
+    ASSERT(m_frame);
+    ASSERT(!m_domWindow);
+    ASSERT(document->domWindow());
+
+    m_domWindow = document->m_domWindow.release();
+    m_domWindow->didSecureTransitionTo(this);
+
+    ASSERT(m_domWindow->document() == this);
+    ASSERT(m_domWindow->frame() == m_frame);
+}
+
+void Document::setWindowAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener)
+{
+    DOMWindow* domWindow = this->domWindow();
+    if (!domWindow)
+        return;
+    domWindow->setAttributeEventListener(eventType, listener);
+}
+
+EventListener* Document::getWindowAttributeEventListener(const AtomicString& eventType)
+{
+    DOMWindow* domWindow = this->domWindow();
+    if (!domWindow)
+        return 0;
+    return domWindow->getAttributeEventListener(eventType);
+}
+
+void Document::dispatchWindowEvent(PassRefPtr<Event> event,  PassRefPtr<EventTarget> target)
+{
+    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
+    DOMWindow* domWindow = this->domWindow();
+    if (!domWindow)
+        return;
+    domWindow->dispatchEvent(event, target);
+}
+
+void Document::dispatchWindowLoadEvent()
+{
+    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
+    DOMWindow* domWindow = this->domWindow();
+    if (!domWindow)
+        return;
+    domWindow->dispatchLoadEvent();
+    m_loadEventFinished = true;
+}
+
+void Document::enqueueWindowEvent(PassRefPtr<Event> event)
+{
+    event->setTarget(domWindow());
+    m_eventQueue->enqueueEvent(event);
+}
+
+void Document::enqueueDocumentEvent(PassRefPtr<Event> event)
+{
+    event->setTarget(this);
+    m_eventQueue->enqueueEvent(event);
+}
+
+PassRefPtr<Event> Document::createEvent(const String& eventType, ExceptionCode& ec)
+{
+    RefPtr<Event> event = EventFactory::create(eventType);
+    if (event)
+        return event.release();
+
+    ec = NOT_SUPPORTED_ERR;
+    return 0;
+}
+
+void Document::addMutationEventListenerTypeIfEnabled(ListenerType listenerType)
+{
+    if (ContextFeatures::mutationEventsEnabled(this))
+        addListenerType(listenerType);
+}
+
+void Document::addListenerTypeIfNeeded(const AtomicString& eventType)
+{
+    if (eventType == eventNames().DOMSubtreeModifiedEvent)
+        addMutationEventListenerTypeIfEnabled(DOMSUBTREEMODIFIED_LISTENER);
+    else if (eventType == eventNames().DOMNodeInsertedEvent)
+        addMutationEventListenerTypeIfEnabled(DOMNODEINSERTED_LISTENER);
+    else if (eventType == eventNames().DOMNodeRemovedEvent)
+        addMutationEventListenerTypeIfEnabled(DOMNODEREMOVED_LISTENER);
+    else if (eventType == eventNames().DOMNodeRemovedFromDocumentEvent)
+        addMutationEventListenerTypeIfEnabled(DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
+    else if (eventType == eventNames().DOMNodeInsertedIntoDocumentEvent)
+        addMutationEventListenerTypeIfEnabled(DOMNODEINSERTEDINTODOCUMENT_LISTENER);
+    else if (eventType == eventNames().DOMCharacterDataModifiedEvent)
+        addMutationEventListenerTypeIfEnabled(DOMCHARACTERDATAMODIFIED_LISTENER);
+    else if (eventType == eventNames().overflowchangedEvent)
+        addListenerType(OVERFLOWCHANGED_LISTENER);
+    else if (eventType == eventNames().webkitAnimationStartEvent)
+        addListenerType(ANIMATIONSTART_LISTENER);
+    else if (eventType == eventNames().webkitAnimationEndEvent)
+        addListenerType(ANIMATIONEND_LISTENER);
+    else if (eventType == eventNames().webkitAnimationIterationEvent)
+        addListenerType(ANIMATIONITERATION_LISTENER);
+    else if (eventType == eventNames().webkitTransitionEndEvent || eventType == eventNames().transitionendEvent)
+        addListenerType(TRANSITIONEND_LISTENER);
+    else if (eventType == eventNames().beforeloadEvent)
+        addListenerType(BEFORELOAD_LISTENER);
+    else if (eventType == eventNames().scrollEvent)
+        addListenerType(SCROLL_LISTENER);
+}
+
+CSSStyleDeclaration* Document::getOverrideStyle(Element*, const String&)
+{
+    return 0;
+}
+
+HTMLFrameOwnerElement* Document::ownerElement() const
+{
+    if (!frame())
+        return 0;
+    return frame()->ownerElement();
+}
+
+String Document::cookie(ExceptionCode& ec) const
+{
+    if (page() && !page()->settings()->cookieEnabled())
+        return String();
+
+    // FIXME: The HTML5 DOM spec states that this attribute can raise an
+    // INVALID_STATE_ERR exception on getting if the Document has no
+    // browsing context.
+
+    if (!securityOrigin()->canAccessCookies()) {
+        ec = SECURITY_ERR;
+        return String();
+    }
+
+    KURL cookieURL = this->cookieURL();
+    if (cookieURL.isEmpty())
+        return String();
+
+    return cookies(this, cookieURL);
+}
+
+void Document::setCookie(const String& value, ExceptionCode& ec)
+{
+    if (page() && !page()->settings()->cookieEnabled())
+        return;
+
+    // FIXME: The HTML5 DOM spec states that this attribute can raise an
+    // INVALID_STATE_ERR exception on setting if the Document has no
+    // browsing context.
+
+    if (!securityOrigin()->canAccessCookies()) {
+        ec = SECURITY_ERR;
+        return;
+    }
+
+    KURL cookieURL = this->cookieURL();
+    if (cookieURL.isEmpty())
+        return;
+
+    setCookies(this, cookieURL, value);
+}
+
+String Document::referrer() const
+{
+    if (frame())
+        return frame()->loader()->referrer();
+    return String();
+}
+
+String Document::domain() const
+{
+    return securityOrigin()->domain();
+}
+
+void Document::setDomain(const String& newDomain, ExceptionCode& ec)
+{
+    if (SchemeRegistry::isDomainRelaxationForbiddenForURLScheme(securityOrigin()->protocol())) {
+        ec = SECURITY_ERR;
+        return;
+    }
+
+    // Both NS and IE specify that changing the domain is only allowed when
+    // the new domain is a suffix of the old domain.
+
+    // FIXME: We should add logging indicating why a domain was not allowed.
+
+    // If the new domain is the same as the old domain, still call
+    // securityOrigin()->setDomainForDOM. This will change the
+    // security check behavior. For example, if a page loaded on port 8000
+    // assigns its current domain using document.domain, the page will
+    // allow other pages loaded on different ports in the same domain that
+    // have also assigned to access this page.
+    if (equalIgnoringCase(domain(), newDomain)) {
+        securityOrigin()->setDomainFromDOM(newDomain);
+        if (m_frame)
+            m_frame->script()->updateSecurityOrigin();
+        return;
+    }
+
+    int oldLength = domain().length();
+    int newLength = newDomain.length();
+    // e.g. newDomain = webkit.org (10) and domain() = www.webkit.org (14)
+    if (newLength >= oldLength) {
+        ec = SECURITY_ERR;
+        return;
+    }
+
+    String test = domain();
+    // Check that it's a subdomain, not e.g. "ebkit.org"
+    if (test[oldLength - newLength - 1] != '.') {
+        ec = SECURITY_ERR;
+        return;
+    }
+
+    // Now test is "webkit.org" from domain()
+    // and we check that it's the same thing as newDomain
+    test.remove(0, oldLength - newLength);
+    if (test != newDomain) {
+        ec = SECURITY_ERR;
+        return;
+    }
+
+    securityOrigin()->setDomainFromDOM(newDomain);
+    if (m_frame)
+        m_frame->script()->updateSecurityOrigin();
+}
+
+// http://www.whatwg.org/specs/web-apps/current-work/#dom-document-lastmodified
+String Document::lastModified() const
+{
+    DateComponents date;
+    bool foundDate = false;
+    if (m_frame) {
+        String httpLastModified;
+        if (DocumentLoader* documentLoader = loader())
+            httpLastModified = documentLoader->response().httpHeaderField("Last-Modified");
+        if (!httpLastModified.isEmpty()) {
+            date.setMillisecondsSinceEpochForDateTime(parseDate(httpLastModified));
+            foundDate = true;
+        }
+    }
+    // FIXME: If this document came from the file system, the HTML5
+    // specificiation tells us to read the last modification date from the file
+    // system.
+    if (!foundDate)
+        date.setMillisecondsSinceEpochForDateTime(currentTimeMS());
+    return String::format("%02d/%02d/%04d %02d:%02d:%02d", date.month() + 1, date.monthDay(), date.fullYear(), date.hour(), date.minute(), date.second());
+}
+
+static bool isValidNameNonASCII(const LChar* characters, unsigned length)
+{
+    if (!isValidNameStart(characters[0]))
+        return false;
+
+    for (unsigned i = 1; i < length; ++i) {
+        if (!isValidNamePart(characters[i]))
+            return false;
+    }
+
+    return true;
+}
+
+static bool isValidNameNonASCII(const UChar* characters, unsigned length)
+{
+    unsigned i = 0;
+
+    UChar32 c;
+    U16_NEXT(characters, i, length, c)
+    if (!isValidNameStart(c))
+        return false;
+
+    while (i < length) {
+        U16_NEXT(characters, i, length, c)
+        if (!isValidNamePart(c))
+            return false;
+    }
+
+    return true;
+}
+
+template<typename CharType>
+static inline bool isValidNameASCII(const CharType* characters, unsigned length)
+{
+    CharType c = characters[0];
+    if (!(isASCIIAlpha(c) || c == ':' || c == '_'))
+        return false;
+
+    for (unsigned i = 1; i < length; ++i) {
+        c = characters[i];
+        if (!(isASCIIAlphanumeric(c) || c == ':' || c == '_' || c == '-' || c == '.'))
+            return false;
+    }
+
+    return true;
+}
+
+bool Document::isValidName(const String& name)
+{
+    unsigned length = name.length();
+    if (!length)
+        return false;
+
+    if (name.is8Bit()) {
+        const LChar* characters = name.characters8();
+
+        if (isValidNameASCII(characters, length))
+            return true;
+
+        return isValidNameNonASCII(characters, length);
+    }
+
+    const UChar* characters = name.characters16();
+
+    if (isValidNameASCII(characters, length))
+        return true;
+
+    return isValidNameNonASCII(characters, length);
+}
+
+bool Document::parseQualifiedName(const String& qualifiedName, String& prefix, String& localName, ExceptionCode& ec)
+{
+    unsigned length = qualifiedName.length();
+
+    if (!length) {
+        ec = INVALID_CHARACTER_ERR;
+        return false;
+    }
+
+    bool nameStart = true;
+    bool sawColon = false;
+    int colonPos = 0;
+
+    const UChar* s = qualifiedName.characters();
+    for (unsigned i = 0; i < length;) {
+        UChar32 c;
+        U16_NEXT(s, i, length, c)
+        if (c == ':') {
+            if (sawColon) {
+                ec = NAMESPACE_ERR;
+                return false; // multiple colons: not allowed
+            }
+            nameStart = true;
+            sawColon = true;
+            colonPos = i - 1;
+        } else if (nameStart) {
+            if (!isValidNameStart(c)) {
+                ec = INVALID_CHARACTER_ERR;
+                return false;
+            }
+            nameStart = false;
+        } else {
+            if (!isValidNamePart(c)) {
+                ec = INVALID_CHARACTER_ERR;
+                return false;
+            }
+        }
+    }
+
+    if (!sawColon) {
+        prefix = String();
+        localName = qualifiedName;
+    } else {
+        prefix = qualifiedName.substring(0, colonPos);
+        if (prefix.isEmpty()) {
+            ec = NAMESPACE_ERR;
+            return false;
+        }
+        localName = qualifiedName.substring(colonPos + 1);
+    }
+
+    if (localName.isEmpty()) {
+        ec = NAMESPACE_ERR;
+        return false;
+    }
+
+    return true;
+}
+
+void Document::setDecoder(PassRefPtr<TextResourceDecoder> decoder)
+{
+    m_decoder = decoder;
+}
+
+KURL Document::completeURL(const String& url, const KURL& baseURLOverride) const
+{
+    // Always return a null URL when passed a null string.
+    // FIXME: Should we change the KURL constructor to have this behavior?
+    // See also [CSS]StyleSheet::completeURL(const String&)
+    if (url.isNull())
+        return KURL();
+    const KURL& baseURL = ((baseURLOverride.isEmpty() || baseURLOverride == blankURL()) && parentDocument()) ? parentDocument()->baseURL() : baseURLOverride;
+    if (!m_decoder)
+        return KURL(baseURL, url);
+    return KURL(baseURL, url, m_decoder->encoding());
+}
+
+KURL Document::completeURL(const String& url) const
+{
+    return completeURL(url, m_baseURL);
+}
+
+void Document::documentWillBecomeInactive()
+{
+    if (renderer())
+        renderView()->setIsInWindow(false);
+}
+
+void Document::registerForCaptionPreferencesChangedCallbacks(Element* e)
+{
+    if (page())
+        page()->group().captionPreferences()->setInterestedInCaptionPreferenceChanges();
+
+    m_captionPreferencesChangedElements.add(e);
+}
+
+void Document::unregisterForCaptionPreferencesChangedCallbacks(Element* e)
+{
+    m_captionPreferencesChangedElements.remove(e);
+}
+
+void Document::captionPreferencesChanged()
+{
+    HashSet<Element*>::iterator end = m_captionPreferencesChangedElements.end();
+    for (HashSet<Element*>::iterator it = m_captionPreferencesChangedElements.begin(); it != end; ++it)
+        (*it)->captionPreferencesChanged();
+}
+
+void Document::setShouldCreateRenderers(bool f)
+{
+    m_createRenderers = f;
+}
+
+bool Document::shouldCreateRenderers()
+{
+    return m_createRenderers;
+}
+
+// Support for Javascript execCommand, and related methods
+
+static Editor::Command command(Document* document, const String& commandName, bool userInterface = false)
+{
+    Frame* frame = document->frame();
+    if (!frame || frame->document() != document)
+        return Editor::Command();
+
+    document->updateStyleIfNeeded();
+
+    return frame->editor()->command(commandName,
+        userInterface ? CommandFromDOMWithUserInterface : CommandFromDOM);
+}
+
+bool Document::execCommand(const String& commandName, bool userInterface, const String& value)
+{
+    return command(this, commandName, userInterface).execute(value);
+}
+
+bool Document::queryCommandEnabled(const String& commandName)
+{
+    return command(this, commandName).isEnabled();
+}
+
+bool Document::queryCommandIndeterm(const String& commandName)
+{
+    return command(this, commandName).state() == MixedTriState;
+}
+
+bool Document::queryCommandState(const String& commandName)
+{
+    return command(this, commandName).state() == TrueTriState;
+}
+
+bool Document::queryCommandSupported(const String& commandName)
+{
+    return command(this, commandName).isSupported();
+}
+
+String Document::queryCommandValue(const String& commandName)
+{
+    return command(this, commandName).value();
+}
+
+KURL Document::openSearchDescriptionURL()
+{
+    static const char* const openSearchMIMEType = "application/opensearchdescription+xml";
+    static const char* const openSearchRelation = "search";
+
+    // FIXME: Why do only top-level frames have openSearchDescriptionURLs?
+    if (!frame() || frame()->tree()->parent())
+        return KURL();
+
+    // FIXME: Why do we need to wait for FrameStateComplete?
+    if (frame()->loader()->state() != FrameStateComplete)
+        return KURL();
+
+    if (!head())
+        return KURL();
+
+    RefPtr<HTMLCollection> children = head()->children();
+    for (unsigned i = 0; Node* child = children->item(i); i++) {
+        if (!child->hasTagName(linkTag))
+            continue;
+        HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(child);
+        if (!equalIgnoringCase(linkElement->type(), openSearchMIMEType) || !equalIgnoringCase(linkElement->rel(), openSearchRelation))
+            continue;
+        if (linkElement->href().isEmpty())
+            continue;
+        return linkElement->href();
+    }
+
+    return KURL();
+}
+
+void Document::applyXSLTransform(ProcessingInstruction* pi)
+{
+    RefPtr<XSLTProcessor> processor = XSLTProcessor::create();
+    processor->setXSLStyleSheet(static_cast<XSLStyleSheet*>(pi->sheet()));
+    String resultMIMEType;
+    String newSource;
+    String resultEncoding;
+    if (!processor->transformToString(this, resultMIMEType, newSource, resultEncoding))
+        return;
+    // FIXME: If the transform failed we should probably report an error (like Mozilla does).
+    Frame* ownerFrame = frame();
+    processor->createDocumentFromSource(newSource, resultEncoding, resultMIMEType, this, ownerFrame);
+    InspectorInstrumentation::frameDocumentUpdated(ownerFrame);
+}
+
+void Document::setTransformSource(PassOwnPtr<TransformSource> source)
+{
+    m_transformSource = source;
+}
+
+void Document::setDesignMode(InheritedBool value)
+{
+    m_designMode = value;
+    for (Frame* frame = m_frame; frame && frame->document(); frame = frame->tree()->traverseNext(m_frame))
+        frame->document()->scheduleForcedStyleRecalc();
+}
+
+Document::InheritedBool Document::getDesignMode() const
+{
+    return m_designMode;
+}
+
+bool Document::inDesignMode() const
+{
+    for (const Document* d = this; d; d = d->parentDocument()) {
+        if (d->m_designMode != inherit)
+            return d->m_designMode;
+    }
+    return false;
+}
+
+Document* Document::parentDocument() const
+{
+    if (!m_frame)
+        return 0;
+    Frame* parent = m_frame->tree()->parent();
+    if (!parent)
+        return 0;
+    return parent->document();
+}
+
+Document* Document::topDocument() const
+{
+    Document* doc = const_cast<Document *>(this);
+    Element* element;
+    while ((element = doc->ownerElement()))
+        doc = element->document();
+
+    return doc;
+}
+
+PassRefPtr<Attr> Document::createAttribute(const String& name, ExceptionCode& ec)
+{
+    return createAttributeNS(String(), name, ec, true);
+}
+
+PassRefPtr<Attr> Document::createAttributeNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode& ec, bool shouldIgnoreNamespaceChecks)
+{
+    String prefix, localName;
+    if (!parseQualifiedName(qualifiedName, prefix, localName, ec))
+        return 0;
+
+    QualifiedName qName(prefix, localName, namespaceURI);
+
+    if (!shouldIgnoreNamespaceChecks && !hasValidNamespaceForAttributes(qName)) {
+        ec = NAMESPACE_ERR;
+        return 0;
+    }
+
+    return Attr::create(this, qName, emptyString());
+}
+
+#if ENABLE(SVG)
+const SVGDocumentExtensions* Document::svgExtensions()
+{
+    return m_svgExtensions.get();
+}
+
+SVGDocumentExtensions* Document::accessSVGExtensions()
+{
+    if (!m_svgExtensions)
+        m_svgExtensions = adoptPtr(new SVGDocumentExtensions(this));
+    return m_svgExtensions.get();
+}
+
+bool Document::hasSVGRootNode() const
+{
+    return documentElement() && documentElement()->hasTagName(SVGNames::svgTag);
+}
+#endif
+
+PassRefPtr<HTMLCollection> Document::ensureCachedCollection(CollectionType type)
+{
+    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLCollection>(this, type);
+}
+
+PassRefPtr<HTMLCollection> Document::images()
+{
+    return ensureCachedCollection(DocImages);
+}
+
+PassRefPtr<HTMLCollection> Document::applets()
+{
+    return ensureCachedCollection(DocApplets);
+}
+
+PassRefPtr<HTMLCollection> Document::embeds()
+{
+    return ensureCachedCollection(DocEmbeds);
+}
+
+PassRefPtr<HTMLCollection> Document::plugins()
+{
+    // This is an alias for embeds() required for the JS DOM bindings.
+    return ensureCachedCollection(DocEmbeds);
+}
+
+PassRefPtr<HTMLCollection> Document::scripts()
+{
+    return ensureCachedCollection(DocScripts);
+}
+
+PassRefPtr<HTMLCollection> Document::links()
+{
+    return ensureCachedCollection(DocLinks);
+}
+
+PassRefPtr<HTMLCollection> Document::forms()
+{
+    return ensureCachedCollection(DocForms);
+}
+
+PassRefPtr<HTMLCollection> Document::anchors()
+{
+    return ensureCachedCollection(DocAnchors);
+}
+
+PassRefPtr<HTMLCollection> Document::all()
+{
+    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLAllCollection>(this, DocAll);
+}
+
+PassRefPtr<HTMLCollection> Document::windowNamedItems(const AtomicString& name)
+{
+    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLNameCollection>(this, WindowNamedItems, name);
+}
+
+PassRefPtr<HTMLCollection> Document::documentNamedItems(const AtomicString& name)
+{
+    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLNameCollection>(this, DocumentNamedItems, name);
+}
+
+void Document::finishedParsing()
+{
+    ASSERT(!scriptableDocumentParser() || !m_parser->isParsing());
+    ASSERT(!scriptableDocumentParser() || m_readyState != Loading);
+    setParsing(false);
+    if (!m_documentTiming.domContentLoadedEventStart)
+        m_documentTiming.domContentLoadedEventStart = monotonicallyIncreasingTime();
+    dispatchEvent(Event::create(eventNames().DOMContentLoadedEvent, true, false));
+    if (!m_documentTiming.domContentLoadedEventEnd)
+        m_documentTiming.domContentLoadedEventEnd = monotonicallyIncreasingTime();
+
+    if (RefPtr<Frame> f = frame()) {
+        // FrameLoader::finishedParsing() might end up calling Document::implicitClose() if all
+        // resource loads are complete. HTMLObjectElements can start loading their resources from
+        // post attach callbacks triggered by recalcStyle().  This means if we parse out an <object>
+        // tag and then reach the end of the document without updating styles, we might not have yet
+        // started the resource load and might fire the window load event too early.  To avoid this
+        // we force the styles to be up to date before calling FrameLoader::finishedParsing().
+        // See https://bugs.webkit.org/show_bug.cgi?id=36864 starting around comment 35.
+        updateStyleIfNeeded();
+
+        f->loader()->finishedParsing();
+
+        InspectorInstrumentation::domContentLoadedEventFired(f.get());
+    }
+
+    // Schedule dropping of the DocumentSharedObjectPool. We keep it alive for a while after parsing finishes
+    // so that dynamically inserted content can also benefit from sharing optimizations.
+    // Note that we don't refresh the timer on pool access since that could lead to huge caches being kept
+    // alive indefinitely by something innocuous like JS setting .innerHTML repeatedly on a timer.
+    static const int timeToKeepSharedObjectPoolAliveAfterParsingFinishedInSeconds = 10;
+    m_sharedObjectPoolClearTimer.startOneShot(timeToKeepSharedObjectPoolAliveAfterParsingFinishedInSeconds);
+
+    // Parser should have picked up all preloads by now
+    m_cachedResourceLoader->clearPreloads();
+}
+
+void Document::sharedObjectPoolClearTimerFired(Timer<Document>*)
+{
+    m_sharedObjectPool.clear();
+}
+
+void Document::didAccessStyleResolver()
+{
+    static const int timeBeforeThrowingAwayStyleResolverAfterLastUseInSeconds = 60;
+    static const int holdOffTimeBeforeReschedulingTimerInSeconds = 5;
+
+    double currentTime = WTF::currentTime();
+
+    if (currentTime > m_lastStyleResolverAccessTime + holdOffTimeBeforeReschedulingTimerInSeconds) {
+        m_styleResolverThrowawayTimer.startOneShot(timeBeforeThrowingAwayStyleResolverAfterLastUseInSeconds);
+        m_lastStyleResolverAccessTime = currentTime;
+    }
+}
+
+void Document::styleResolverThrowawayTimerFired(Timer<Document>*)
+{
+    ASSERT(!m_inStyleRecalc);
+    clearStyleResolver();
+}
+
+PassRefPtr<XPathExpression> Document::createExpression(const String& expression,
+                                                       XPathNSResolver* resolver,
+                                                       ExceptionCode& ec)
+{
+    if (!m_xpathEvaluator)
+        m_xpathEvaluator = XPathEvaluator::create();
+    return m_xpathEvaluator->createExpression(expression, resolver, ec);
+}
+
+PassRefPtr<XPathNSResolver> Document::createNSResolver(Node* nodeResolver)
+{
+    if (!m_xpathEvaluator)
+        m_xpathEvaluator = XPathEvaluator::create();
+    return m_xpathEvaluator->createNSResolver(nodeResolver);
+}
+
+PassRefPtr<XPathResult> Document::evaluate(const String& expression,
+                                           Node* contextNode,
+                                           XPathNSResolver* resolver,
+                                           unsigned short type,
+                                           XPathResult* result,
+                                           ExceptionCode& ec)
+{
+    if (!m_xpathEvaluator)
+        m_xpathEvaluator = XPathEvaluator::create();
+    return m_xpathEvaluator->evaluate(expression, contextNode, resolver, type, result, ec);
+}
+
+const Vector<IconURL>& Document::shortcutIconURLs()
+{
+    // Include any icons where type = link, rel = "shortcut icon".
+    return iconURLs(Favicon);
+}
+
+const Vector<IconURL>& Document::iconURLs(int iconTypesMask)
+{
+    m_iconURLs.clear();
+
+    if (!head() || !(head()->children()))
+        return m_iconURLs;
+
+    RefPtr<HTMLCollection> children = head()->children();
+    unsigned int length = children->length();
+    for (unsigned int i = 0; i < length; ++i) {
+        Node* child = children->item(i);
+        if (!child->hasTagName(linkTag))
+            continue;
+        HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(child);
+        if (!(linkElement->iconType() & iconTypesMask))
+            continue;
+        if (linkElement->href().isEmpty())
+            continue;
+
+        // Put it at the front to ensure that icons seen later take precedence as required by the spec.
+        IconURL newURL(linkElement->href(), linkElement->iconSizes(), linkElement->type(), linkElement->iconType());
+        m_iconURLs.prepend(newURL);
+    }
+
+    return m_iconURLs;
+}
+
+void Document::addIconURL(const String& url, const String&, const String&, IconType iconType)
+{
+    if (url.isEmpty())
+        return;
+
+    Frame* f = frame();
+    if (!f)
+        return;
+
+    f->loader()->didChangeIcons(iconType);
+}
+
+void Document::setUseSecureKeyboardEntryWhenActive(bool usesSecureKeyboard)
+{
+    if (m_useSecureKeyboardEntryWhenActive == usesSecureKeyboard)
+        return;
+
+    m_useSecureKeyboardEntryWhenActive = usesSecureKeyboard;
+    m_frame->selection()->updateSecureKeyboardEntryIfActive();
+}
+
+bool Document::useSecureKeyboardEntryWhenActive() const
+{
+    return m_useSecureKeyboardEntryWhenActive;
+}
+
+static bool isEligibleForSeamless(Document* parent, Document* child)
+{
+    // It should not matter what we return for the top-most document.
+    if (!parent)
+        return false;
+    if (parent->isSandboxed(SandboxSeamlessIframes))
+        return false;
+    if (child->isSrcdocDocument())
+        return true;
+    if (parent->securityOrigin()->canAccess(child->securityOrigin()))
+        return true;
+    return parent->securityOrigin()->canRequest(child->url());
+}
+
+void Document::initSecurityContext()
+{
+    if (haveInitializedSecurityOrigin()) {
+        ASSERT(securityOrigin());
+        return;
+    }
+
+    if (!m_frame) {
+        // No source for a security context.
+        // This can occur via document.implementation.createDocument().
+        m_cookieURL = KURL(ParsedURLString, emptyString());
+        setSecurityOrigin(SecurityOrigin::createUnique());
+        setContentSecurityPolicy(ContentSecurityPolicy::create(this));
+        return;
+    }
+
+    // In the common case, create the security context from the currently
+    // loading URL with a fresh content security policy.
+    m_cookieURL = m_url;
+    enforceSandboxFlags(m_frame->loader()->effectiveSandboxFlags());
+    setSecurityOrigin(isSandboxed(SandboxOrigin) ? SecurityOrigin::createUnique() : SecurityOrigin::create(m_url));
+    setContentSecurityPolicy(ContentSecurityPolicy::create(this));
+
+    if (Settings* settings = this->settings()) {
+        if (!settings->webSecurityEnabled()) {
+            // Web security is turned off. We should let this document access every other document. This is used primary by testing
+            // harnesses for web sites.
+            securityOrigin()->grantUniversalAccess();
+        } else if (securityOrigin()->isLocal()) {
+            if (settings->allowUniversalAccessFromFileURLs()) {
+                // Some clients want local URLs to have universal access, but that setting is dangerous for other clients.
+                securityOrigin()->grantUniversalAccess();
+            } else if (!settings->allowFileAccessFromFileURLs()) {
+                // Some clients want local URLs to have even tighter restrictions by default, and not be able to access other local files.
+                // FIXME 81578: The naming of this is confusing. Files with restricted access to other local files
+                // still can have other privileges that can be remembered, thereby not making them unique origins.
+                securityOrigin()->enforceFilePathSeparation();
+            }
+        }
+    }
+
+    Document* parentDocument = ownerElement() ? ownerElement()->document() : 0;
+    if (parentDocument && m_frame->loader()->shouldTreatURLAsSrcdocDocument(url())) {
+        m_isSrcdocDocument = true;
+        setBaseURLOverride(parentDocument->baseURL());
+    }
+
+    // FIXME: What happens if we inherit the security origin? This check may need to be later.
+    // <iframe seamless src="about:blank"> likely won't work as-is.
+    m_mayDisplaySeamlesslyWithParent = isEligibleForSeamless(parentDocument, this);
+
+    if (!shouldInheritSecurityOriginFromOwner(m_url))
+        return;
+
+    // If we do not obtain a meaningful origin from the URL, then we try to
+    // find one via the frame hierarchy.
+
+    Frame* ownerFrame = m_frame->tree()->parent();
+    if (!ownerFrame)
+        ownerFrame = m_frame->loader()->opener();
+
+    if (!ownerFrame) {
+        didFailToInitializeSecurityOrigin();
+        return;
+    }
+
+    if (isSandboxed(SandboxOrigin)) {
+        // If we're supposed to inherit our security origin from our owner,
+        // but we're also sandboxed, the only thing we inherit is the ability
+        // to load local resources. This lets about:blank iframes in file://
+        // URL documents load images and other resources from the file system.
+        if (ownerFrame->document()->securityOrigin()->canLoadLocalResources())
+            securityOrigin()->grantLoadLocalResources();
+        return;
+    }
+
+    m_cookieURL = ownerFrame->document()->cookieURL();
+    // We alias the SecurityOrigins to match Firefox, see Bug 15313
+    // https://bugs.webkit.org/show_bug.cgi?id=15313
+    setSecurityOrigin(ownerFrame->document()->securityOrigin());
+}
+
+void Document::initContentSecurityPolicy()
+{
+    if (!m_frame->tree()->parent() || (!shouldInheritSecurityOriginFromOwner(m_url) && !isPluginDocument()))
+        return;
+
+    contentSecurityPolicy()->copyStateFrom(m_frame->tree()->parent()->document()->contentSecurityPolicy());
+}
+
+void Document::didUpdateSecurityOrigin()
+{
+    if (!m_frame)
+        return;
+    m_frame->script()->updateSecurityOrigin();
+}
+
+bool Document::isContextThread() const
+{
+    return isMainThread();
+}
+
+void Document::updateURLForPushOrReplaceState(const KURL& url)
+{
+    Frame* f = frame();
+    if (!f)
+        return;
+
+    setURL(url);
+    f->loader()->setOutgoingReferrer(url);
+
+    if (DocumentLoader* documentLoader = loader())
+        documentLoader->replaceRequestURLForSameDocumentNavigation(url);
+}
+
+void Document::statePopped(PassRefPtr<SerializedScriptValue> stateObject)
+{
+    if (!frame())
+        return;
+
+    // Per step 11 of section 6.5.9 (history traversal) of the HTML5 spec, we
+    // defer firing of popstate until we're in the complete state.
+    if (m_readyState == Complete)
+        enqueuePopstateEvent(stateObject);
+    else
+        m_pendingStateObject = stateObject;
+}
+
+void Document::updateFocusAppearanceSoon(bool restorePreviousSelection)
+{
+    m_updateFocusAppearanceRestoresSelection = restorePreviousSelection;
+    if (!m_updateFocusAppearanceTimer.isActive())
+        m_updateFocusAppearanceTimer.startOneShot(0);
+}
+
+void Document::cancelFocusAppearanceUpdate()
+{
+    m_updateFocusAppearanceTimer.stop();
+}
+
+void Document::updateFocusAppearanceTimerFired(Timer<Document>*)
+{
+    Node* node = focusedNode();
+    if (!node)
+        return;
+    if (!node->isElementNode())
+        return;
+
+    updateLayout();
+
+    Element* element = toElement(node);
+    if (element->isFocusable())
+        element->updateFocusAppearance(m_updateFocusAppearanceRestoresSelection);
+}
+
+void Document::attachRange(Range* range)
+{
+    ASSERT(!m_ranges.contains(range));
+    m_ranges.add(range);
+}
+
+void Document::detachRange(Range* range)
+{
+    // We don't ASSERT m_ranges.contains(range) to allow us to call this
+    // unconditionally to fix: https://bugs.webkit.org/show_bug.cgi?id=26044
+    m_ranges.remove(range);
+}
+
+CanvasRenderingContext* Document::getCSSCanvasContext(const String& type, const String& name, int width, int height)
+{
+    HTMLCanvasElement* element = getCSSCanvasElement(name);
+    if (!element)
+        return 0;
+    element->setSize(IntSize(width, height));
+    return element->getContext(type);
+}
+
+HTMLCanvasElement* Document::getCSSCanvasElement(const String& name)
+{
+    RefPtr<HTMLCanvasElement>& element = m_cssCanvasElements.add(name, 0).iterator->value;
+    if (!element)
+        element = HTMLCanvasElement::create(this);
+    return element.get();
+}
+
+void Document::initDNSPrefetch()
+{
+    Settings* settings = this->settings();
+
+    m_haveExplicitlyDisabledDNSPrefetch = false;
+    m_isDNSPrefetchEnabled = settings && settings->dnsPrefetchingEnabled() && securityOrigin()->protocol() == "http";
+
+    // Inherit DNS prefetch opt-out from parent frame
+    if (Document* parent = parentDocument()) {
+        if (!parent->isDNSPrefetchEnabled())
+            m_isDNSPrefetchEnabled = false;
+    }
+}
+
+void Document::parseDNSPrefetchControlHeader(const String& dnsPrefetchControl)
+{
+    if (equalIgnoringCase(dnsPrefetchControl, "on") && !m_haveExplicitlyDisabledDNSPrefetch) {
+        m_isDNSPrefetchEnabled = true;
+        return;
+    }
+
+    m_isDNSPrefetchEnabled = false;
+    m_haveExplicitlyDisabledDNSPrefetch = true;
+}
+
+void Document::addConsoleMessage(MessageSource source, MessageLevel level, const String& message, unsigned long requestIdentifier)
+{
+    if (!isContextThread()) {
+        postTask(AddConsoleMessageTask::create(source, level, message));
+        return;
+    }
+
+    if (Page* page = this->page())
+        page->console()->addMessage(source, level, message, requestIdentifier, this);
+}
+
+void Document::addMessage(MessageSource source, MessageLevel level, const String& message, const String& sourceURL, unsigned lineNumber, PassRefPtr<ScriptCallStack> callStack, ScriptState* state, unsigned long requestIdentifier)
+{
+    if (!isContextThread()) {
+        postTask(AddConsoleMessageTask::create(source, level, message));
+        return;
+    }
+
+    if (Page* page = this->page())
+        page->console()->addMessage(source, level, message, sourceURL, lineNumber, callStack, state, requestIdentifier);
+}
+
+const SecurityOrigin* Document::topOrigin() const
+{
+    return topDocument()->securityOrigin();
+}
+
+struct PerformTaskContext {
+    WTF_MAKE_NONCOPYABLE(PerformTaskContext); WTF_MAKE_FAST_ALLOCATED;
+public:
+    PerformTaskContext(WeakPtr<Document> document, PassOwnPtr<ScriptExecutionContext::Task> task)
+        : documentReference(document)
+        , task(task)
+    {
+    }
+
+    WeakPtr<Document> documentReference;
+    OwnPtr<ScriptExecutionContext::Task> task;
+};
+
+void Document::didReceiveTask(void* untypedContext)
+{
+    ASSERT(isMainThread());
+
+    OwnPtr<PerformTaskContext> context = adoptPtr(static_cast<PerformTaskContext*>(untypedContext));
+    ASSERT(context);
+
+    Document* document = context->documentReference.get();
+    if (!document)
+        return;
+
+    Page* page = document->page();
+    if ((page && page->defersLoading()) || !document->m_pendingTasks.isEmpty()) {
+        document->m_pendingTasks.append(context->task.release());
+        return;
+    }
+
+    context->task->performTask(document);
+}
+
+void Document::postTask(PassOwnPtr<Task> task)
+{
+    callOnMainThread(didReceiveTask, new PerformTaskContext(m_weakFactory.createWeakPtr(), task));
+}
+
+void Document::pendingTasksTimerFired(Timer<Document>*)
+{
+    while (!m_pendingTasks.isEmpty()) {
+        OwnPtr<Task> task = m_pendingTasks[0].release();
+        m_pendingTasks.remove(0);
+        task->performTask(this);
+    }
+}
+
+void Document::suspendScheduledTasks(ActiveDOMObject::ReasonForSuspension reason)
+{
+    ASSERT(!m_scheduledTasksAreSuspended);
+
+    suspendScriptedAnimationControllerCallbacks();
+    suspendActiveDOMObjects(reason);
+    scriptRunner()->suspend();
+    m_pendingTasksTimer.stop();
+    if (m_parser)
+        m_parser->suspendScheduledTasks();
+
+    m_scheduledTasksAreSuspended = true;
+}
+
+void Document::resumeScheduledTasks()
+{
+    ASSERT(m_scheduledTasksAreSuspended);
+
+    if (m_parser)
+        m_parser->resumeScheduledTasks();
+    if (!m_pendingTasks.isEmpty())
+        m_pendingTasksTimer.startOneShot(0);
+    scriptRunner()->resume();
+    resumeActiveDOMObjects();
+    resumeScriptedAnimationControllerCallbacks();
+
+    m_scheduledTasksAreSuspended = false;
+}
+
+void Document::suspendScriptedAnimationControllerCallbacks()
+{
+    if (m_scriptedAnimationController)
+        m_scriptedAnimationController->suspend();
+}
+
+void Document::resumeScriptedAnimationControllerCallbacks()
+{
+    if (m_scriptedAnimationController)
+        m_scriptedAnimationController->resume();
+}
+
+String Document::displayStringModifiedByEncoding(const String& str) const
+{
+    if (m_decoder)
+        return m_decoder->encoding().displayString(str.impl());
+    return str;
+}
+
+PassRefPtr<StringImpl> Document::displayStringModifiedByEncoding(PassRefPtr<StringImpl> str) const
+{
+    if (m_decoder)
+        return m_decoder->encoding().displayString(str);
+    return str;
+}
+
+template <typename CharacterType>
+void Document::displayBufferModifiedByEncodingInternal(CharacterType* buffer, unsigned len) const
+{
+    if (m_decoder)
+        m_decoder->encoding().displayBuffer(buffer, len);
+}
+
+// Generate definitions for both character types
+template void Document::displayBufferModifiedByEncodingInternal<LChar>(LChar*, unsigned) const;
+template void Document::displayBufferModifiedByEncodingInternal<UChar>(UChar*, unsigned) const;
+
+void Document::enqueuePageshowEvent(PageshowEventPersistence persisted)
+{
+    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36334 Pageshow event needs to fire asynchronously.
+    dispatchWindowEvent(PageTransitionEvent::create(eventNames().pageshowEvent, persisted), this);
+}
+
+void Document::enqueueHashchangeEvent(const String& oldURL, const String& newURL)
+{
+    enqueueWindowEvent(HashChangeEvent::create(oldURL, newURL));
+}
+
+void Document::enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject)
+{
+    if (!ContextFeatures::pushStateEnabled(this))
+        return;
+
+    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36202 Popstate event needs to fire asynchronously
+    dispatchWindowEvent(PopStateEvent::create(stateObject, domWindow() ? domWindow()->history() : 0));
+}
+
+bool Document::fullScreenIsAllowedForElement(Element* element) const
+{
+    ASSERT(element);
+    return isAttributeOnAllOwners(allowfullscreenAttr, webkitallowfullscreenAttr, element->document()->ownerElement());
+}
+
+void Document::requestFullScreenForElement(Element* element, unsigned short flags, FullScreenCheckType checkType)
+{
+    // The Mozilla Full Screen API <https://wiki.mozilla.org/Gecko:FullScreenAPI> has different requirements
+    // for full screen mode, and do not have the concept of a full screen element stack.
+    bool inLegacyMozillaMode = (flags & Element::LEGACY_MOZILLA_REQUEST);
+
+    do {
+        if (!element)
+            element = documentElement();
+
+        // 1. If any of the following conditions are true, terminate these steps and queue a task to fire
+        // an event named fullscreenerror with its bubbles attribute set to true on the context object's
+        // node document:
+
+        // The context object is not in a document.
+        if (!element->inDocument())
+            break;
+
+        // The context object's node document, or an ancestor browsing context's document does not have
+        // the fullscreen enabled flag set.
+        if (checkType == EnforceIFrameAllowFullScreenRequirement && !fullScreenIsAllowedForElement(element))
+            break;
+
+        // The context object's node document fullscreen element stack is not empty and its top element
+        // is not an ancestor of the context object. (NOTE: Ignore this requirement if the request was
+        // made via the legacy Mozilla-style API.)
+        if (!m_fullScreenElementStack.isEmpty() && !inLegacyMozillaMode) {
+            Element* lastElementOnStack = m_fullScreenElementStack.last().get();
+            if (lastElementOnStack == element || !lastElementOnStack->contains(element))
+                break;
+        }
+
+        // A descendant browsing context's document has a non-empty fullscreen element stack.
+        bool descendentHasNonEmptyStack = false;
+        for (Frame* descendant = frame() ? frame()->tree()->traverseNext() : 0; descendant; descendant = descendant->tree()->traverseNext()) {
+            if (descendant->document()->webkitFullscreenElement()) {
+                descendentHasNonEmptyStack = true;
+                break;
+            }
+        }
+        if (descendentHasNonEmptyStack && !inLegacyMozillaMode)
+            break;
+
+        // This algorithm is not allowed to show a pop-up:
+        //   An algorithm is allowed to show a pop-up if, in the task in which the algorithm is running, either:
+        //   - an activation behavior is currently being processed whose click event was trusted, or
+        //   - the event listener for a trusted click event is being handled.
+        if (!ScriptController::processingUserGesture())
+            break;
+
+        // There is a previously-established user preference, security risk, or platform limitation.
+        if (!page() || !page()->settings()->fullScreenEnabled())
+            break;
+
+        // 2. Let doc be element's node document. (i.e. "this")
+        Document* currentDoc = this;
+
+        // 3. Let docs be all doc's ancestor browsing context's documents (if any) and doc.
+        Deque<Document*> docs;
+
+        do {
+            docs.prepend(currentDoc);
+            currentDoc = currentDoc->ownerElement() ? currentDoc->ownerElement()->document() : 0;
+        } while (currentDoc);
+
+        // 4. For each document in docs, run these substeps:
+        Deque<Document*>::iterator current = docs.begin(), following = docs.begin();
+
+        do {
+            ++following;
+
+            // 1. Let following document be the document after document in docs, or null if there is no
+            // such document.
+            Document* currentDoc = *current;
+            Document* followingDoc = following != docs.end() ? *following : 0;
+
+            // 2. If following document is null, push context object on document's fullscreen element
+            // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute
+            // set to true on the document.
+            if (!followingDoc) {
+                currentDoc->pushFullscreenElementStack(element);
+                addDocumentToFullScreenChangeEventQueue(currentDoc);
+                continue;
+            }
+
+            // 3. Otherwise, if document's fullscreen element stack is either empty or its top element
+            // is not following document's browsing context container,
+            Element* topElement = currentDoc->webkitFullscreenElement();
+            if (!topElement || topElement != followingDoc->ownerElement()) {
+                // ...push following document's browsing context container on document's fullscreen element
+                // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute
+                // set to true on document.
+                currentDoc->pushFullscreenElementStack(followingDoc->ownerElement());
+                addDocumentToFullScreenChangeEventQueue(currentDoc);
+                continue;
+            }
+
+            // 4. Otherwise, do nothing for this document. It stays the same.
+        } while (++current != docs.end());
+
+        // 5. Return, and run the remaining steps asynchronously.
+        // 6. Optionally, perform some animation.
+        m_areKeysEnabledInFullScreen = flags & Element::ALLOW_KEYBOARD_INPUT;
+        page()->chrome()->client()->enterFullScreenForElement(element);
+
+        // 7. Optionally, display a message indicating how the user can exit displaying the context object fullscreen.
+        return;
+    } while (0);
+
+    m_fullScreenErrorEventTargetQueue.append(element ? element : documentElement());
+    m_fullScreenChangeDelayTimer.startOneShot(0);
+}
+
+void Document::webkitCancelFullScreen()
+{
+    // The Mozilla "cancelFullScreen()" API behaves like the W3C "fully exit fullscreen" behavior, which
+    // is defined as:
+    // "To fully exit fullscreen act as if the exitFullscreen() method was invoked on the top-level browsing
+    // context's document and subsequently empty that document's fullscreen element stack."
+    if (!topDocument()->webkitFullscreenElement())
+        return;
+
+    // To achieve that aim, remove all the elements from the top document's stack except for the first before
+    // calling webkitExitFullscreen():
+    Vector<RefPtr<Element> > replacementFullscreenElementStack;
+    replacementFullscreenElementStack.append(topDocument()->webkitFullscreenElement());
+    topDocument()->m_fullScreenElementStack.swap(replacementFullscreenElementStack);
+
+    topDocument()->webkitExitFullscreen();
+}
+
+void Document::webkitExitFullscreen()
+{
+    // The exitFullscreen() method must run these steps:
+
+    // 1. Let doc be the context object. (i.e. "this")
+    Document* currentDoc = this;
+
+    // 2. If doc's fullscreen element stack is empty, terminate these steps.
+    if (m_fullScreenElementStack.isEmpty())
+        return;
+
+    // 3. Let descendants be all the doc's descendant browsing context's documents with a non-empty fullscreen
+    // element stack (if any), ordered so that the child of the doc is last and the document furthest
+    // away from the doc is first.
+    Deque<RefPtr<Document> > descendants;
+    for (Frame* descendant = frame() ? frame()->tree()->traverseNext() : 0; descendant; descendant = descendant->tree()->traverseNext()) {
+        if (descendant->document()->webkitFullscreenElement())
+            descendants.prepend(descendant->document());
+    }
+
+    // 4. For each descendant in descendants, empty descendant's fullscreen element stack, and queue a
+    // task to fire an event named fullscreenchange with its bubbles attribute set to true on descendant.
+    for (Deque<RefPtr<Document> >::iterator i = descendants.begin(); i != descendants.end(); ++i) {
+        (*i)->clearFullscreenElementStack();
+        addDocumentToFullScreenChangeEventQueue(i->get());
+    }
+
+    // 5. While doc is not null, run these substeps:
+    Element* newTop = 0;
+    while (currentDoc) {
+        // 1. Pop the top element of doc's fullscreen element stack.
+        currentDoc->popFullscreenElementStack();
+
+        //    If doc's fullscreen element stack is non-empty and the element now at the top is either
+        //    not in a document or its node document is not doc, repeat this substep.
+        newTop = currentDoc->webkitFullscreenElement();
+        if (newTop && (!newTop->inDocument() || newTop->document() != currentDoc))
+            continue;
+
+        // 2. Queue a task to fire an event named fullscreenchange with its bubbles attribute set to true
+        // on doc.
+        addDocumentToFullScreenChangeEventQueue(currentDoc);
+
+        // 3. If doc's fullscreen element stack is empty and doc's browsing context has a browsing context
+        // container, set doc to that browsing context container's node document.
+        if (!newTop && currentDoc->ownerElement()) {
+            currentDoc = currentDoc->ownerElement()->document();
+            continue;
+        }
+
+        // 4. Otherwise, set doc to null.
+        currentDoc = 0;
+    }
+
+    // 6. Return, and run the remaining steps asynchronously.
+    // 7. Optionally, perform some animation.
+
+    if (!page())
+        return;
+
+    // Only exit out of full screen window mode if there are no remaining elements in the
+    // full screen stack.
+    if (!newTop) {
+        page()->chrome()->client()->exitFullScreenForElement(m_fullScreenElement.get());
+        return;
+    }
+
+    // Otherwise, notify the chrome of the new full screen element.
+    page()->chrome()->client()->enterFullScreenForElement(newTop);
+}
+
+bool Document::webkitFullscreenEnabled() const
+{
+    // 4. The fullscreenEnabled attribute must return true if the context object and all ancestor
+    // browsing context's documents have their fullscreen enabled flag set, or false otherwise.
+
+    // Top-level browsing contexts are implied to have their allowFullScreen attribute set.
+    return isAttributeOnAllOwners(allowfullscreenAttr, webkitallowfullscreenAttr, ownerElement());
+}
+
+void Document::webkitWillEnterFullScreenForElement(Element* element)
+{
+    if (!attached())
+        return;
+
+    ASSERT(element);
+
+    // Protect against being called after the document has been removed from the page.
+    if (!page())
+        return;
+
+    ASSERT(page()->settings()->fullScreenEnabled());
+
+    if (m_fullScreenRenderer)
+        m_fullScreenRenderer->unwrapRenderer();
+
+    m_fullScreenElement = element;
+
+#if USE(NATIVE_FULLSCREEN_VIDEO)
+    if (element && element->isMediaElement())
+        return;
+#endif
+
+    // Create a placeholder block for a the full-screen element, to keep the page from reflowing
+    // when the element is removed from the normal flow.  Only do this for a RenderBox, as only
+    // a box will have a frameRect.  The placeholder will be created in setFullScreenRenderer()
+    // during layout.
+    RenderObject* renderer = m_fullScreenElement->renderer();
+    bool shouldCreatePlaceholder = renderer && renderer->isBox();
+    if (shouldCreatePlaceholder) {
+        m_savedPlaceholderFrameRect = toRenderBox(renderer)->frameRect();
+        m_savedPlaceholderRenderStyle = RenderStyle::clone(renderer->style());
+    }
+
+    if (m_fullScreenElement != documentElement())
+        RenderFullScreen::wrapRenderer(renderer, renderer ? renderer->parent() : 0, this);
+
+    m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true);
+
+    recalcStyle(Force);
+}
+
+void Document::webkitDidEnterFullScreenForElement(Element*)
+{
+    if (!m_fullScreenElement)
+        return;
+
+    if (!attached())
+        return;
+
+    m_fullScreenElement->didBecomeFullscreenElement();
+
+    m_fullScreenChangeDelayTimer.startOneShot(0);
+}
+
+void Document::webkitWillExitFullScreenForElement(Element*)
+{
+    if (!m_fullScreenElement)
+        return;
+
+    if (!attached())
+        return;
+
+    m_fullScreenElement->willStopBeingFullscreenElement();
+}
+
+void Document::webkitDidExitFullScreenForElement(Element*)
+{
+    if (!m_fullScreenElement)
+        return;
+
+    if (!attached())
+        return;
+
+    m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
+
+    m_areKeysEnabledInFullScreen = false;
+
+    if (m_fullScreenRenderer)
+        m_fullScreenRenderer->unwrapRenderer();
+
+    m_fullScreenElement = 0;
+    scheduleForcedStyleRecalc();
+
+    // When webkitCancelFullScreen is called, we call webkitExitFullScreen on the topDocument(). That
+    // means that the events will be queued there. So if we have no events here, start the timer on
+    // the exiting document.
+    Document* exitingDocument = this;
+    if (m_fullScreenChangeEventTargetQueue.isEmpty() && m_fullScreenErrorEventTargetQueue.isEmpty())
+        exitingDocument = topDocument();
+    exitingDocument->m_fullScreenChangeDelayTimer.startOneShot(0);
+}
+
+void Document::setFullScreenRenderer(RenderFullScreen* renderer)
+{
+    if (renderer == m_fullScreenRenderer)
+        return;
+
+    if (renderer && m_savedPlaceholderRenderStyle)
+        renderer->createPlaceholder(m_savedPlaceholderRenderStyle.release(), m_savedPlaceholderFrameRect);
+    else if (renderer && m_fullScreenRenderer && m_fullScreenRenderer->placeholder()) {
+        RenderBlock* placeholder = m_fullScreenRenderer->placeholder();
+        renderer->createPlaceholder(RenderStyle::clone(placeholder->style()), placeholder->frameRect());
+    }
+
+    if (m_fullScreenRenderer)
+        m_fullScreenRenderer->destroy();
+    ASSERT(!m_fullScreenRenderer);
+
+    m_fullScreenRenderer = renderer;
+}
+
+void Document::fullScreenRendererDestroyed()
+{
+    m_fullScreenRenderer = 0;
+}
+
+void Document::setFullScreenRendererSize(const IntSize& size)
+{
+    ASSERT(m_fullScreenRenderer);
+    if (!m_fullScreenRenderer)
+        return;
+
+    if (m_fullScreenRenderer) {
+        RefPtr<RenderStyle> newStyle = RenderStyle::clone(m_fullScreenRenderer->style());
+        newStyle->setWidth(Length(size.width(), WebCore::Fixed));
+        newStyle->setHeight(Length(size.height(), WebCore::Fixed));
+        newStyle->setTop(Length(0, WebCore::Fixed));
+        newStyle->setLeft(Length(0, WebCore::Fixed));
+        m_fullScreenRenderer->setStyle(newStyle);
+        updateLayout();
+    }
+}
+
+void Document::setFullScreenRendererBackgroundColor(Color backgroundColor)
+{
+    if (!m_fullScreenRenderer)
+        return;
+
+    RefPtr<RenderStyle> newStyle = RenderStyle::clone(m_fullScreenRenderer->style());
+    newStyle->setBackgroundColor(backgroundColor);
+    m_fullScreenRenderer->setStyle(newStyle);
+}
+
+void Document::fullScreenChangeDelayTimerFired(Timer<Document>*)
+{
+    // Since we dispatch events in this function, it's possible that the
+    // document will be detached and GC'd. We protect it here to make sure we
+    // can finish the function successfully.
+    RefPtr<Document> protectDocument(this);
+    Deque<RefPtr<Node> > changeQueue;
+    m_fullScreenChangeEventTargetQueue.swap(changeQueue);
+    Deque<RefPtr<Node> > errorQueue;
+    m_fullScreenErrorEventTargetQueue.swap(errorQueue);
+
+    while (!changeQueue.isEmpty()) {
+        RefPtr<Node> node = changeQueue.takeFirst();
+        if (!node)
+            node = documentElement();
+        // The dispatchEvent below may have blown away our documentElement.
+        if (!node)
+            continue;
+
+        // If the element was removed from our tree, also message the documentElement. Since we may
+        // have a document hierarchy, check that node isn't in another document.
+        if (!contains(node.get()) && !node->inDocument())
+            changeQueue.append(documentElement());
+
+        node->dispatchEvent(Event::create(eventNames().webkitfullscreenchangeEvent, true, false));
+    }
+
+    while (!errorQueue.isEmpty()) {
+        RefPtr<Node> node = errorQueue.takeFirst();
+        if (!node)
+            node = documentElement();
+        // The dispatchEvent below may have blown away our documentElement.
+        if (!node)
+            continue;
+
+        // If the element was removed from our tree, also message the documentElement. Since we may
+        // have a document hierarchy, check that node isn't in another document.
+        if (!contains(node.get()) && !node->inDocument())
+            errorQueue.append(documentElement());
+
+        node->dispatchEvent(Event::create(eventNames().webkitfullscreenerrorEvent, true, false));
+    }
+}
+
+void Document::fullScreenElementRemoved()
+{
+    m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
+    webkitCancelFullScreen();
+}
+
+void Document::removeFullScreenElementOfSubtree(Node* node, bool amongChildrenOnly)
+{
+    if (!m_fullScreenElement)
+        return;
+
+    bool elementInSubtree = false;
+    if (amongChildrenOnly)
+        elementInSubtree = m_fullScreenElement->isDescendantOf(node);
+    else
+        elementInSubtree = (m_fullScreenElement == node) || m_fullScreenElement->isDescendantOf(node);
+
+    if (elementInSubtree)
+        fullScreenElementRemoved();
+}
+
+bool Document::isAnimatingFullScreen() const
+{
+    return m_isAnimatingFullScreen;
+}
+
+void Document::setAnimatingFullScreen(bool flag)
+{
+    if (m_isAnimatingFullScreen == flag)
+        return;
+    m_isAnimatingFullScreen = flag;
+
+    if (m_fullScreenElement && m_fullScreenElement->isDescendantOf(this)) {
+        m_fullScreenElement->setNeedsStyleRecalc();
+        scheduleForcedStyleRecalc();
+    }
+}
+
+void Document::clearFullscreenElementStack()
+{
+    m_fullScreenElementStack.clear();
+}
+
+void Document::popFullscreenElementStack()
+{
+    if (m_fullScreenElementStack.isEmpty())
+        return;
+
+    m_fullScreenElementStack.removeLast();
+}
+
+void Document::pushFullscreenElementStack(Element* element)
+{
+    m_fullScreenElementStack.append(element);
+}
+
+void Document::addDocumentToFullScreenChangeEventQueue(Document* doc)
+{
+    ASSERT(doc);
+    Node* target = doc->webkitFullscreenElement();
+    if (!target)
+        target = doc->webkitCurrentFullScreenElement();
+    if (!target)
+        target = doc;
+    m_fullScreenChangeEventTargetQueue.append(target);
+}
+
+void Document::addToTopLayer(Element* element)
+{
+    if (element->isInTopLayer())
+        return;
+    ASSERT(!m_topLayerElements.contains(element));
+    m_topLayerElements.append(element);
+    element->setIsInTopLayer(true);
+}
+
+void Document::removeFromTopLayer(Element* element)
+{
+    if (!element->isInTopLayer())
+        return;
+    size_t position = m_topLayerElements.find(element);
+    ASSERT(position != notFound);
+    m_topLayerElements.remove(position);
+    element->setIsInTopLayer(false);
+}
+
+void Document::webkitExitPointerLock()
+{
+    if (!page())
+        return;
+    if (Element* target = page()->pointerLockController()->element()) {
+        if (target->document() != this)
+            return;
+    }
+    page()->pointerLockController()->requestPointerUnlock();
+}
+
+Element* Document::webkitPointerLockElement() const
+{
+    if (!page() || page()->pointerLockController()->lockPending())
+        return 0;
+    if (Element* element = page()->pointerLockController()->element()) {
+        if (element->document() == this)
+            return element;
+    }
+    return 0;
+}
+
+void Document::decrementLoadEventDelayCount()
+{
+    ASSERT(m_loadEventDelayCount);
+    --m_loadEventDelayCount;
+
+    if (frame() && !m_loadEventDelayCount && !m_loadEventDelayTimer.isActive())
+        m_loadEventDelayTimer.startOneShot(0);
+}
+
+void Document::loadEventDelayTimerFired(Timer<Document>*)
+{
+    if (frame())
+        frame()->loader()->checkCompleted();
+}
+
+int Document::requestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback> callback)
+{
+    if (!m_scriptedAnimationController) {
+        m_scriptedAnimationController = ScriptedAnimationController::create(this);
+        // We need to make sure that we don't start up the animation controller on a background tab, for example.
+        if (!page())
+            m_scriptedAnimationController->suspend();
+    }
+
+    return m_scriptedAnimationController->registerCallback(callback);
+}
+
+void Document::cancelAnimationFrame(int id)
+{
+    if (!m_scriptedAnimationController)
+        return;
+    m_scriptedAnimationController->cancelCallback(id);
+}
+
+void Document::serviceScriptedAnimations(double monotonicAnimationStartTime)
+{
+    if (!m_scriptedAnimationController)
+        return;
+    m_scriptedAnimationController->serviceScriptedAnimations(monotonicAnimationStartTime);
+}
+
+PassRefPtr<Touch> Document::createTouch(DOMWindow* window, EventTarget* target, int identifier, int pageX, int pageY, int screenX, int screenY, int radiusX, int radiusY, float rotationAngle, float force, ExceptionCode&) const
+{
+    // FIXME: It's not clear from the documentation at
+    // http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/DocumentAdditionsReference/DocumentAdditions/DocumentAdditions.html
+    // when this method should throw and nor is it by inspection of iOS behavior. It would be nice to verify any cases where it throws under iOS
+    // and implement them here. See https://bugs.webkit.org/show_bug.cgi?id=47819
+    Frame* frame = window ? window->frame() : this->frame();
+    return Touch::create(frame, target, identifier, screenX, screenY, pageX, pageY, radiusX, radiusY, rotationAngle, force);
+}
+
+static void wheelEventHandlerCountChanged(Document* document)
+{
+    Page* page = document->page();
+    if (!page)
+        return;
+
+    ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
+    if (!scrollingCoordinator)
+        return;
+
+    FrameView* frameView = document->view();
+    if (!frameView)
+        return;
+
+    scrollingCoordinator->frameViewWheelEventHandlerCountChanged(frameView);
+}
+
+void Document::didAddWheelEventHandler()
+{
+    ++m_wheelEventHandlerCount;
+    Frame* mainFrame = page() ? page()->mainFrame() : 0;
+    if (mainFrame)
+        mainFrame->notifyChromeClientWheelEventHandlerCountChanged();
+
+    wheelEventHandlerCountChanged(this);
+}
+
+void Document::didRemoveWheelEventHandler()
+{
+    ASSERT(m_wheelEventHandlerCount > 0);
+    --m_wheelEventHandlerCount;
+    Frame* mainFrame = page() ? page()->mainFrame() : 0;
+    if (mainFrame)
+        mainFrame->notifyChromeClientWheelEventHandlerCountChanged();
+
+    wheelEventHandlerCountChanged(this);
+}
+
+void Document::didAddTouchEventHandler(Node* handler)
+{
+    if (!m_touchEventTargets.get())
+        m_touchEventTargets = adoptPtr(new TouchEventTargetSet);
+    m_touchEventTargets->add(handler);
+    if (Document* parent = parentDocument()) {
+        parent->didAddTouchEventHandler(this);
+        return;
+    }
+    if (Page* page = this->page()) {
+        if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
+            scrollingCoordinator->touchEventTargetRectsDidChange(this);
+        if (m_touchEventTargets->size() == 1)
+            page->chrome()->client()->needTouchEvents(true);
+    }
+}
+
+void Document::didRemoveTouchEventHandler(Node* handler)
+{
+    if (!m_touchEventTargets.get())
+        return;
+    ASSERT(m_touchEventTargets->contains(handler));
+    m_touchEventTargets->remove(handler);
+    if (Document* parent = parentDocument()) {
+        parent->didRemoveTouchEventHandler(this);
+        return;
+    }
+
+    Page* page = this->page();
+    if (!page)
+        return;
+    if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
+        scrollingCoordinator->touchEventTargetRectsDidChange(this);
+    if (m_touchEventTargets->size())
+        return;
+    for (const Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
+        if (frame->document() && frame->document()->hasTouchEventHandlers())
+            return;
+    }
+    page->chrome()->client()->needTouchEvents(false);
+}
+
+void Document::didRemoveEventTargetNode(Node* handler)
+{
+    if (m_touchEventTargets) {
+        m_touchEventTargets->removeAll(handler);
+        if ((handler == this || m_touchEventTargets->isEmpty()) && parentDocument())
+            parentDocument()->didRemoveEventTargetNode(this);
+    }
+}
+
+void Document::resetLastHandledUserGestureTimestamp()
+{
+    m_lastHandledUserGestureTimestamp = currentTime();
+}
+
+HTMLIFrameElement* Document::seamlessParentIFrame() const
+{
+    if (!shouldDisplaySeamlesslyWithParent())
+        return 0;
+
+    HTMLFrameOwnerElement* ownerElement = this->ownerElement();
+    ASSERT(ownerElement->hasTagName(iframeTag));
+    return static_cast<HTMLIFrameElement*>(ownerElement);
+}
+
+bool Document::shouldDisplaySeamlesslyWithParent() const
+{
+    if (!RuntimeEnabledFeatures::seamlessIFramesEnabled())
+        return false;
+    HTMLFrameOwnerElement* ownerElement = this->ownerElement();
+    if (!ownerElement)
+        return false;
+    return m_mayDisplaySeamlesslyWithParent && ownerElement->hasTagName(iframeTag) && ownerElement->fastHasAttribute(seamlessAttr);
+}
+
+DocumentLoader* Document::loader() const
+{
+    if (!m_frame)
+        return 0;
+
+    DocumentLoader* loader = m_frame->loader()->documentLoader();
+    if (!loader)
+        return 0;
+
+    if (m_frame->document() != this)
+        return 0;
+
+    return loader;
+}
+
+IntSize Document::viewportSize() const
+{
+    if (!view())
+        return IntSize();
+    return view()->visibleContentRect(ScrollableArea::IncludeScrollbars).size();
+}
+
+#if ENABLE(CSS_DEVICE_ADAPTATION)
+IntSize Document::initialViewportSize() const
+{
+    if (!view())
+        return IntSize();
+    return view()->initialViewportSize();
+}
+#endif
+
+Node* eventTargetNodeForDocument(Document* doc)
+{
+    if (!doc)
+        return 0;
+    Node* node = doc->focusedNode();
+    if (!node && doc->isPluginDocument()) {
+        PluginDocument* pluginDocument = toPluginDocument(doc);
+        node =  pluginDocument->pluginNode();
+    }
+    if (!node && doc->isHTMLDocument())
+        node = doc->body();
+    if (!node)
+        node = doc->documentElement();
+    return node;
+}
+
+void Document::adjustFloatQuadsForScrollAndAbsoluteZoom(Vector<FloatQuad>& quads, RenderObject* renderer)
+{
+    if (!view())
+        return;
+
+    LayoutRect visibleContentRect = view()->visibleContentRect();
+    for (size_t i = 0; i < quads.size(); ++i) {
+        quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
+        adjustFloatQuadForAbsoluteZoom(quads[i], renderer);
+    }
+}
+
+void Document::adjustFloatRectForScrollAndAbsoluteZoom(FloatRect& rect, RenderObject* renderer)
+{
+    if (!view())
+        return;
+
+    LayoutRect visibleContentRect = view()->visibleContentRect();
+    rect.move(-visibleContentRect.x(), -visibleContentRect.y());
+    adjustFloatRectForAbsoluteZoom(rect, renderer);
+}
+
+bool Document::hasActiveParser()
+{
+    return m_activeParserCount || (m_parser && m_parser->processingData());
+}
+
+void Document::decrementActiveParserCount()
+{
+    --m_activeParserCount;
+    if (!frame())
+        return;
+    // FIXME: This should always be enabled, but it seems to cause
+    // http/tests/security/feed-urls-from-remote.html to timeout on Mac WK1
+    // see http://webkit.org/b/110554 and http://webkit.org/b/110401
+    loader()->checkLoadComplete();
+    frame()->loader()->checkLoadComplete();
+}
+
+void Document::setContextFeatures(PassRefPtr<ContextFeatures> features)
+{
+    m_contextFeatures = features;
+}
+
+static RenderObject* nearestCommonHoverAncestor(RenderObject* obj1, RenderObject* obj2)
+{
+    if (!obj1 || !obj2)
+        return 0;
+
+    for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAncestor()) {
+        for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hoverAncestor()) {
+            if (currObj1 == currObj2)
+                return currObj1;
+        }
+    }
+
+    return 0;
+}
+
+void Document::updateHoverActiveState(const HitTestRequest& request, Element* innerElement)
+{
+    ASSERT(!request.readOnly());
+
+    Element* innerElementInDocument = innerElement;
+    while (innerElementInDocument && innerElementInDocument->document() != this) {
+        innerElementInDocument->document()->updateHoverActiveState(request, innerElementInDocument);
+        innerElementInDocument = innerElementInDocument->document()->ownerElement();
+    }
+
+    Element* oldActiveElement = activeElement();
+    if (oldActiveElement && !request.active()) {
+        // We are clearing the :active chain because the mouse has been released.
+        for (RenderObject* curr = oldActiveElement->renderer(); curr; curr = curr->parent()) {
+            if (curr->node()) {
+                ASSERT(!curr->node()->isTextNode());
+                curr->node()->setActive(false);
+                m_userActionElements.setInActiveChain(curr->node(), false);
+            }
+        }
+        setActiveElement(0);
+    } else {
+        Element* newActiveElement = innerElementInDocument;
+        if (!oldActiveElement && newActiveElement && request.active() && !request.touchMove()) {
+            // We are setting the :active chain and freezing it. If future moves happen, they
+            // will need to reference this chain.
+            for (RenderObject* curr = newActiveElement->renderer(); curr; curr = curr->parent()) {
+                if (curr->node() && !curr->isText())
+                    m_userActionElements.setInActiveChain(curr->node(), true);
+            }
+
+            setActiveElement(newActiveElement);
+        }
+    }
+    // If the mouse has just been pressed, set :active on the chain. Those (and only those)
+    // nodes should remain :active until the mouse is released.
+    bool allowActiveChanges = !oldActiveElement && activeElement();
+
+    // If the mouse is down and if this is a mouse move event, we want to restrict changes in
+    // :hover/:active to only apply to elements that are in the :active chain that we froze
+    // at the time the mouse went down.
+    bool mustBeInActiveChain = request.active() && request.move();
+
+    RefPtr<Node> oldHoverNode = hoverNode();
+
+    // A touch release does not set a new hover target; setting the element we're working with to 0
+    // will clear the chain of hovered elements all the way to the top of the tree.
+    if (request.touchRelease())
+        innerElementInDocument = 0;
+
+    // Check to see if the hovered node has changed.
+    // If it hasn't, we do not need to do anything.
+    Node* newHoverNode = innerElementInDocument;
+    while (newHoverNode && !newHoverNode->renderer())
+        newHoverNode = newHoverNode->parentOrShadowHostNode();
+
+    // Update our current hover node.
+    setHoverNode(newHoverNode);
+
+    // We have two different objects. Fetch their renderers.
+    RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0;
+    RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0;
+
+    // Locate the common ancestor render object for the two renderers.
+    RenderObject* ancestor = nearestCommonHoverAncestor(oldHoverObj, newHoverObj);
+
+    Vector<RefPtr<Node>, 32> nodesToRemoveFromChain;
+    Vector<RefPtr<Node>, 32> nodesToAddToChain;
+
+    if (oldHoverObj != newHoverObj) {
+        // The old hover path only needs to be cleared up to (and not including) the common ancestor;
+        for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) {
+            if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain()))
+                nodesToRemoveFromChain.append(curr->node());
+        }
+    }
+
+    // Now set the hover state for our new object up to the root.
+    for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) {
+        if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain()))
+            nodesToAddToChain.append(curr->node());
+    }
+
+    size_t removeCount = nodesToRemoveFromChain.size();
+    for (size_t i = 0; i < removeCount; ++i)
+        nodesToRemoveFromChain[i]->setHovered(false);
+
+    size_t addCount = nodesToAddToChain.size();
+    for (size_t i = 0; i < addCount; ++i) {
+        if (allowActiveChanges)
+            nodesToAddToChain[i]->setActive(true);
+        nodesToAddToChain[i]->setHovered(true);
+    }
+
+    updateStyleIfNeeded();
+}
+
+void Document::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    ContainerNode::reportMemoryUsage(memoryObjectInfo);
+    TreeScope::reportMemoryUsage(memoryObjectInfo);
+    ScriptExecutionContext::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_styleResolver, "styleResolver");
+    info.addMember(m_url, "url");
+    info.addMember(m_baseURL, "baseURL");
+    info.addMember(m_baseURLOverride, "baseURLOverride");
+    info.addMember(m_baseElementURL, "baseElementURL");
+    info.addMember(m_cookieURL, "cookieURL");
+    info.addMember(m_firstPartyForCookies, "firstPartyForCookies");
+    info.addMember(m_documentURI, "documentURI");
+    info.addMember(m_baseTarget, "baseTarget");
+    info.addMember(m_docType, "docType");
+    info.addMember(m_implementation, "implementation");
+    info.addMember(m_elemSheet, "elemSheet");
+    info.addMember(m_frame, "frame");
+    info.addMember(m_cachedResourceLoader, "cachedResourceLoader");
+    info.addMember(m_styleSheetCollection, "styleSheetCollection");
+    info.addMember(m_styleSheetList, "styleSheetList");
+    info.addMember(m_formController, "formController");
+    info.addMember(m_nodeIterators, "nodeIterators");
+    info.addMember(m_ranges, "ranges");
+    info.addMember(m_title.string(), "title.string()");
+    info.addMember(m_rawTitle.string(), "rawTitle.string()");
+    info.addMember(m_xmlEncoding, "xmlEncoding");
+    info.addMember(m_xmlVersion, "xmlVersion");
+    info.addMember(m_contentLanguage, "contentLanguage");
+    info.addMember(m_annotatedRegions, "annotatedRegions");
+    info.addMember(m_cssCanvasElements, "cssCanvasElements");
+    info.addMember(m_iconURLs, "iconURLs");
+    info.addMember(m_elementsByAccessKey, "elementsByAccessKey");
+    info.addMember(m_eventQueue, "eventQueue");
+    info.addMember(m_pendingTasks, "pendingTasks");
+    info.addMember(m_prerenderer, "prerenderer");
+    info.addMember(m_listsInvalidatedAtDocument, "listsInvalidatedAtDocument");
+    info.addMember(m_styleResolverThrowawayTimer, "styleResolverThrowawayTimer");
+    info.addMember(m_domWindow, "domWindow");
+    info.addMember(m_parser, "parser");
+    info.addMember(m_contextFeatures, "contextFeatures");
+    info.addMember(m_focusedNode, "focusedNode");
+    info.addMember(m_hoverNode, "hoverNode");
+    info.addMember(m_documentElement, "documentElement");
+    info.addMember(m_visitedLinkState, "visitedLinkState");
+    info.addMember(m_styleRecalcTimer, "styleRecalcTimer");
+    info.addMember(m_titleElement, "titleElement");
+    info.ignoreMember(m_renderArena);
+    info.addMember(m_axObjectCache, "axObjectCache");
+    info.addMember(m_markers, "markers");
+    info.addMember(m_cssTarget, "cssTarget");
+    info.addMember(m_updateFocusAppearanceTimer, "updateFocusAppearanceTimer");
+    info.addMember(m_pendingStateObject, "pendingStateObject");
+    info.addMember(m_scriptRunner, "scriptRunner");
+    info.addMember(m_transformSource, "transformSource");
+    info.addMember(m_transformSourceDocument, "transformSourceDocument");
+    info.addMember(m_decoder, "decoder");
+    info.addMember(m_xpathEvaluator, "xpathEvaluator");
+#if ENABLE(SVG)
+    info.addMember(m_svgExtensions, "svgExtensions");
+#endif
+    info.addMember(m_selectorQueryCache, "selectorQueryCache");
+    info.addMember(m_renderer, "renderer");
+    info.addMember(m_weakFactory, "weakFactory");
+    info.addMember(m_idAttributeName, "idAttributeName");
+    info.addMember(m_fullScreenElement, "fullScreenElement");
+    info.addMember(m_fullScreenElementStack, "fullScreenElementStack");
+    info.addMember(m_fullScreenRenderer, "fullScreenRenderer");
+    info.addMember(m_fullScreenChangeDelayTimer, "fullScreenChangeDelayTimer");
+    info.addMember(m_fullScreenChangeEventTargetQueue, "fullScreenChangeEventTargetQueue");
+    info.addMember(m_fullScreenErrorEventTargetQueue, "fullScreenErrorEventTargetQueue");
+    info.addMember(m_savedPlaceholderRenderStyle, "savedPlaceholderRenderStyle");
+    info.addMember(m_topLayerElements, "topLayerElements");
+    info.addMember(m_loadEventDelayTimer, "loadEventDelayTimer");
+    info.addMember(m_viewportArguments, "viewportArguments");
+    info.addMember(m_documentTiming, "documentTiming");
+    info.addMember(m_mediaQueryMatcher, "mediaQueryMatcher");
+    info.addMember(m_touchEventTargets, "touchEventTargets");
+    info.addMember(m_scriptedAnimationController, "scriptedAnimationController");
+    info.addMember(m_pendingTasksTimer, "pendingTasksTimer");
+    info.addMember(m_textAutosizer, "textAutosizer");
+    info.addMember(m_namedFlows, "namedFlows");
+    info.addMember(m_domSecurityPolicy, "domSecurityPolicy");
+    info.addMember(m_sharedObjectPoolClearTimer, "sharedObjectPoolClearTimer");
+    info.addMember(m_sharedObjectPool, "sharedObjectPool");
+    info.addMember(m_localeCache, "localeCache");
+    info.addMember(m_templateDocument, "templateDocument");
+    info.addMember(m_templateDocumentHost, "templateDocumentHost");
+    info.addMember(m_activeElement, "activeElement");
+}
+
+bool Document::haveStylesheetsLoaded() const
+{
+    return !m_styleSheetCollection->hasPendingSheets() || m_ignorePendingStylesheets;
+}
+
+Locale& Document::getCachedLocale(const AtomicString& locale)
+{
+    AtomicString localeKey = locale;
+    if (locale.isEmpty() || !RuntimeEnabledFeatures::langAttributeAwareFormControlUIEnabled())
+        localeKey = defaultLanguage();
+    LocaleIdentifierToLocaleMap::AddResult result = m_localeCache.add(localeKey, nullptr);
+    if (result.isNewEntry)
+        result.iterator->value = Locale::create(localeKey);
+    return *(result.iterator->value);
+}
+
+Document* Document::ensureTemplateDocument()
+{
+    if (const Document* document = templateDocument())
+        return const_cast<Document*>(document);
+
+    if (isHTMLDocument())
+        m_templateDocument = HTMLDocument::create(0, blankURL());
+    else
+        m_templateDocument = Document::create(0, blankURL());
+
+    m_templateDocument->setTemplateDocumentHost(this); // balanced in dtor.
+
+    return m_templateDocument.get();
+}
+
+PassRefPtr<FontLoader> Document::fontloader()
+{
+    if (!m_fontloader)
+        m_fontloader = FontLoader::create(this);
+    return m_fontloader;
+}
+
+void Document::didAssociateFormControl(Element* element)
+{
+    if (!frame() || !frame()->page())
+        return;
+    m_associatedFormControls.add(element);
+    if (!m_didAssociateFormControlsTimer.isActive())
+        m_didAssociateFormControlsTimer.startOneShot(0);
+}
+
+void Document::didAssociateFormControlsTimerFired(Timer<Document>* timer)
+{
+    ASSERT_UNUSED(timer, timer == &m_didAssociateFormControlsTimer);
+    if (!frame() || !frame()->page())
+        return;
+
+    Vector<RefPtr<Element> > associatedFormControls;
+    copyToVector(m_associatedFormControls, associatedFormControls);
+
+    frame()->page()->chrome()->client()->didAssociateFormControls(associatedFormControls);
+    m_associatedFormControls.clear();
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/Document.h b/Source/core/dom/Document.h
new file mode 100644
index 0000000..b5949b1
--- /dev/null
+++ b/Source/core/dom/Document.h
@@ -0,0 +1,1515 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Document_h
+#define Document_h
+
+#include "core/dom/ContainerNode.h"
+#include "core/dom/DOMTimeStamp.h"
+#include "core/dom/DocumentEventQueue.h"
+#include "core/dom/DocumentTiming.h"
+#include "core/dom/IconURL.h"
+#include "core/dom/MutationObserver.h"
+#include "core/dom/QualifiedName.h"
+#include "core/dom/ScriptExecutionContext.h"
+#include "core/dom/TreeScope.h"
+#include "core/dom/UserActionElementSet.h"
+#include "core/dom/ViewportArguments.h"
+#include "core/html/CollectionType.h"
+#include "core/inspector/InspectorCounters.h"
+#include "core/page/FocusDirection.h"
+#include "core/page/PageVisibilityState.h"
+#include "core/platform/PlatformScreen.h"
+#include "core/platform/ReferrerPolicy.h"
+#include "core/platform/Timer.h"
+#include "core/platform/graphics/Color.h"
+#include "core/platform/graphics/IntRect.h"
+#include "core/platform/text/StringWithDirection.h"
+#include "core/rendering/HitTestRequest.h"
+#include <wtf/Deque.h>
+#include <wtf/FixedArray.h>
+#include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/WeakPtr.h>
+
+namespace WebCore {
+
+class AXObjectCache;
+class Attr;
+class CDATASection;
+class CSSStyleDeclaration;
+class CSSStyleSheet;
+class CachedCSSStyleSheet;
+class CachedResourceLoader;
+class CachedScript;
+class CanvasRenderingContext;
+class CharacterData;
+class Comment;
+class ContextFeatures;
+class CustomElementConstructor;
+class CustomElementRegistry;
+class DOMImplementation;
+class DOMNamedFlowCollection;
+class DOMSecurityPolicy;
+class DOMSelection;
+class DOMWindow;
+class Database;
+class DatabaseThread;
+class DocumentFragment;
+class DocumentLoader;
+class DocumentMarkerController;
+class DocumentParser;
+class DocumentSharedObjectPool;
+class DocumentStyleSheetCollection;
+class DocumentType;
+class Element;
+class EntityReference;
+class Event;
+class EventListener;
+class FloatRect;
+class FloatQuad;
+class FormController;
+class Frame;
+class FrameView;
+class HTMLCanvasElement;
+class HTMLCollection;
+class HTMLAllCollection;
+class HTMLDocument;
+class HTMLElement;
+class HTMLFrameOwnerElement;
+class HTMLHeadElement;
+class HTMLIFrameElement;
+class HTMLMapElement;
+class HTMLNameCollection;
+class HitTestRequest;
+class HitTestResult;
+class IntPoint;
+class LayoutPoint;
+class LayoutRect;
+class LiveNodeListBase;
+class DOMWrapperWorld;
+class JSNode;
+class Locale;
+class MediaQueryList;
+class MediaQueryMatcher;
+class MouseEventWithHitTestResults;
+class NamedFlowCollection;
+class NodeFilter;
+class NodeIterator;
+class Page;
+class PlatformMouseEvent;
+class Prerenderer;
+class ProcessingInstruction;
+class Range;
+class RegisteredEventListener;
+class RenderArena;
+class RenderFullScreen;
+class RenderView;
+class RequestAnimationFrameCallback;
+class ScriptElementData;
+class ScriptRunner;
+class ScriptableDocumentParser;
+class ScriptedAnimationController;
+class SecurityOrigin;
+class SegmentedString;
+class SelectorQueryCache;
+class SerializedScriptValue;
+class Settings;
+class StyleResolver;
+class StyleSheet;
+class StyleSheetContents;
+class StyleSheetList;
+class Text;
+class TextAutosizer;
+class TextResourceDecoder;
+class Touch;
+class TouchList;
+class TransformSource;
+class TreeWalker;
+class VisitedLinkState;
+class XMLHttpRequest;
+class XPathEvaluator;
+class XPathExpression;
+class XPathNSResolver;
+class XPathResult;
+
+#if ENABLE(SVG)
+class SVGDocumentExtensions;
+#endif
+
+struct AnnotatedRegionValue;
+
+class FontLoader;
+
+typedef int ExceptionCode;
+
+enum PageshowEventPersistence {
+    PageshowEventNotPersisted = 0,
+    PageshowEventPersisted = 1
+};
+
+enum StyleResolverUpdateFlag { RecalcStyleImmediately, DeferRecalcStyle, RecalcStyleIfNeeded };
+
+enum NodeListInvalidationType {
+    DoNotInvalidateOnAttributeChanges = 0,
+    InvalidateOnClassAttrChange,
+    InvalidateOnIdNameAttrChange,
+    InvalidateOnNameAttrChange,
+    InvalidateOnForAttrChange,
+    InvalidateForFormControls,
+    InvalidateOnHRefAttrChange,
+    InvalidateOnItemAttrChange,
+    InvalidateOnAnyAttrChange,
+};
+const int numNodeListInvalidationTypes = InvalidateOnAnyAttrChange + 1;
+
+typedef HashCountedSet<Node*> TouchEventTargetSet;
+
+class Document : public ContainerNode, public TreeScope, public ScriptExecutionContext {
+public:
+    static PassRefPtr<Document> create(Frame* frame, const KURL& url)
+    {
+        return adoptRef(new Document(frame, url, false, false));
+    }
+    static PassRefPtr<Document> createXHTML(Frame* frame, const KURL& url)
+    {
+        return adoptRef(new Document(frame, url, true, false));
+    }
+    virtual ~Document();
+
+    MediaQueryMatcher* mediaQueryMatcher();
+
+    using ContainerNode::ref;
+    using ContainerNode::deref;
+
+    Element* getElementById(const AtomicString& id) const;
+
+    virtual bool canContainRangeEndPoint() const { return true; }
+
+    Element* getElementByAccessKey(const String& key);
+    void invalidateAccessKeyMap();
+
+    SelectorQueryCache* selectorQueryCache();
+
+    // DOM methods & attributes for Document
+
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(change);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(click);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(drop);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(select);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(submit);
+
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(blur);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(focus);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(load);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(readystatechange);
+
+    // WebKit extensions
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(reset);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(selectionchange);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenerror);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitpointerlockchange);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitpointerlockerror);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitvisibilitychange);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(securitypolicyviolation);
+
+    void setViewportArguments(const ViewportArguments& viewportArguments) { m_viewportArguments = viewportArguments; }
+    ViewportArguments viewportArguments() const { return m_viewportArguments; }
+#ifndef NDEBUG
+    bool didDispatchViewportPropertiesChanged() const { return m_didDispatchViewportPropertiesChanged; }
+#endif
+
+    void setReferrerPolicy(ReferrerPolicy referrerPolicy) { m_referrerPolicy = referrerPolicy; }
+    ReferrerPolicy referrerPolicy() const { return m_referrerPolicy; }
+
+    DocumentType* doctype() const { return m_docType.get(); }
+
+    DOMImplementation* implementation();
+    
+    Element* documentElement() const
+    {
+        return m_documentElement.get();
+    }
+
+    bool hasManifest() const;
+    
+    virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&);
+    PassRefPtr<DocumentFragment> createDocumentFragment();
+    PassRefPtr<Text> createTextNode(const String& data);
+    PassRefPtr<Comment> createComment(const String& data);
+    PassRefPtr<CDATASection> createCDATASection(const String& data, ExceptionCode&);
+    PassRefPtr<ProcessingInstruction> createProcessingInstruction(const String& target, const String& data, ExceptionCode&);
+    PassRefPtr<Attr> createAttribute(const String& name, ExceptionCode&);
+    PassRefPtr<Attr> createAttributeNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode&, bool shouldIgnoreNamespaceChecks = false);
+    PassRefPtr<EntityReference> createEntityReference(const String& name, ExceptionCode&);
+    PassRefPtr<Node> importNode(Node* importedNode, ExceptionCode& ec) { return importNode(importedNode, true, ec); }
+    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);
+
+    bool cssStickyPositionEnabled() const;
+    bool cssCompositingEnabled() const;
+    PassRefPtr<DOMNamedFlowCollection> webkitGetNamedFlows();
+
+    NamedFlowCollection* namedFlows();
+
+    bool regionBasedColumnsEnabled() const;
+
+    bool cssGridLayoutEnabled() const;
+
+    /**
+     * Retrieve all nodes that intersect a rect in the window's document, until it is fully enclosed by
+     * the boundaries of a node.
+     *
+     * @param centerX x reference for the rectangle in CSS pixels
+     * @param centerY y reference for the rectangle in CSS pixels
+     * @param topPadding How much to expand the top of the rectangle
+     * @param rightPadding How much to expand the right of the rectangle
+     * @param bottomPadding How much to expand the bottom of the rectangle
+     * @param leftPadding How much to expand the left of the rectangle
+     */
+    PassRefPtr<NodeList> nodesFromRect(int centerX, int centerY,
+        unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding,
+        HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent) const;
+    Element* elementFromPoint(int x, int y) const;
+    PassRefPtr<Range> caretRangeFromPoint(int x, int y);
+
+    String readyState() const;
+
+    String defaultCharset() const;
+
+    String inputEncoding() const { return Document::encoding(); }
+    String charset() const { return Document::encoding(); }
+    String characterSet() const { return Document::encoding(); }
+
+    String encoding() const;
+
+    void setCharset(const String&);
+
+    void setContent(const String&);
+
+    String suggestedMIMEType() const;
+
+    String contentLanguage() const { return m_contentLanguage; }
+    void setContentLanguage(const String&);
+
+    String xmlEncoding() const { return m_xmlEncoding; }
+    String xmlVersion() const { return m_xmlVersion; }
+    enum StandaloneStatus { StandaloneUnspecified, Standalone, NotStandalone };
+    bool xmlStandalone() const { return m_xmlStandalone == Standalone; }
+    StandaloneStatus xmlStandaloneStatus() const { return static_cast<StandaloneStatus>(m_xmlStandalone); }
+    bool hasXMLDeclaration() const { return m_hasXMLDeclaration; }
+
+    void setXMLEncoding(const String& encoding) { m_xmlEncoding = encoding; } // read-only property, only to be set from XMLDocumentParser
+    void setXMLVersion(const String&, ExceptionCode&);
+    void setXMLStandalone(bool, ExceptionCode&);
+    void setHasXMLDeclaration(bool hasXMLDeclaration) { m_hasXMLDeclaration = hasXMLDeclaration ? 1 : 0; }
+
+    String documentURI() const { return m_documentURI; }
+
+    virtual KURL baseURI() const;
+
+    String webkitVisibilityState() const;
+    bool webkitHidden() const;
+    void dispatchVisibilityStateChangeEvent();
+
+    DOMSecurityPolicy* securityPolicy();
+
+    PassRefPtr<Node> adoptNode(PassRefPtr<Node> source, ExceptionCode&);
+
+    PassRefPtr<HTMLCollection> images();
+    PassRefPtr<HTMLCollection> embeds();
+    PassRefPtr<HTMLCollection> plugins(); // an alias for embeds() required for the JS DOM bindings.
+    PassRefPtr<HTMLCollection> applets();
+    PassRefPtr<HTMLCollection> links();
+    PassRefPtr<HTMLCollection> forms();
+    PassRefPtr<HTMLCollection> anchors();
+    PassRefPtr<HTMLCollection> scripts();
+    PassRefPtr<HTMLCollection> all();
+
+    PassRefPtr<HTMLCollection> windowNamedItems(const AtomicString& name);
+    PassRefPtr<HTMLCollection> documentNamedItems(const AtomicString& name);
+
+    // Other methods (not part of DOM)
+    bool isHTMLDocument() const { return m_isHTML; }
+    bool isXHTMLDocument() const { return m_isXHTML; }
+    virtual bool isImageDocument() const { return false; }
+#if ENABLE(SVG)
+    virtual bool isSVGDocument() const { return false; }
+    bool hasSVGRootNode() const;
+#else
+    static bool isSVGDocument() { return false; }
+    static bool hasSVGRootNode() { return false; }
+#endif
+    virtual bool isPluginDocument() const { return false; }
+    virtual bool isMediaDocument() const { return false; }
+    virtual bool isFrameSet() const { return false; }
+
+    bool isSrcdocDocument() const { return m_isSrcdocDocument; }
+
+    StyleResolver* styleResolverIfExists() const { return m_styleResolver.get(); }
+
+    bool isViewSource() const { return m_isViewSource; }
+    void setIsViewSource(bool);
+
+    bool sawElementsInKnownNamespaces() const { return m_sawElementsInKnownNamespaces; }
+
+    StyleResolver* styleResolver()
+    { 
+        if (!m_styleResolver)
+            createStyleResolver();
+        return m_styleResolver.get();
+    }
+
+    void notifyRemovePendingSheetIfNeeded();
+
+    bool haveStylesheetsLoaded() const;
+
+    // This is a DOM function.
+    StyleSheetList* styleSheets();
+
+    DocumentStyleSheetCollection* styleSheetCollection() { return m_styleSheetCollection.get(); }
+
+    bool gotoAnchorNeededAfterStylesheetsLoad() { return m_gotoAnchorNeededAfterStylesheetsLoad; }
+    void setGotoAnchorNeededAfterStylesheetsLoad(bool b) { m_gotoAnchorNeededAfterStylesheetsLoad = b; }
+
+    /**
+     * Called when one or more stylesheets in the document may have been added, removed or changed.
+     *
+     * Creates a new style resolver and assign it to this document. This is done by iterating through all nodes in
+     * document (or those before <BODY> in a HTML document), searching for stylesheets. Stylesheets can be contained in
+     * <LINK>, <STYLE> or <BODY> elements, as well as processing instructions (XML documents only). A list is
+     * constructed from these which is used to create the a new style selector which collates all of the stylesheets
+     * found and is used to calculate the derived styles for all rendering objects.
+     */
+    void styleResolverChanged(StyleResolverUpdateFlag);
+
+    void didAccessStyleResolver();
+
+    void evaluateMediaQueryList();
+
+    // Never returns 0.
+    FormController* formController();
+    Vector<String> formElementsState() const;
+    void setStateForNewFormElements(const Vector<String>&);
+
+    FrameView* view() const; // can be NULL
+    Frame* frame() const { return m_frame; } // can be NULL
+    Page* page() const; // can be NULL
+    Settings* settings() const; // can be NULL
+
+    PassRefPtr<Range> createRange();
+
+    PassRefPtr<NodeIterator> createNodeIterator(Node* root, unsigned whatToShow,
+        PassRefPtr<NodeFilter>, bool expandEntityReferences, ExceptionCode&);
+
+    PassRefPtr<TreeWalker> createTreeWalker(Node* root, unsigned whatToShow,
+        PassRefPtr<NodeFilter>, bool expandEntityReferences, ExceptionCode&);
+
+    // Special support for editing
+    PassRefPtr<CSSStyleDeclaration> createCSSStyleDeclaration();
+    PassRefPtr<Text> createEditingTextNode(const String&);
+
+    void recalcStyle(StyleChange = NoChange);
+    bool childNeedsAndNotInStyleRecalc();
+    void updateStyleIfNeeded();
+    void updateLayout();
+    void updateLayoutIgnorePendingStylesheets();
+    PassRefPtr<RenderStyle> styleForElementIgnoringPendingStylesheets(Element*);
+    PassRefPtr<RenderStyle> styleForPage(int pageIndex);
+
+    // Returns true if page box (margin boxes and page borders) is visible.
+    bool isPageBoxVisible(int pageIndex);
+
+    // Returns the preferred page size and margins in pixels, assuming 96
+    // pixels per inch. pageSize, marginTop, marginRight, marginBottom,
+    // marginLeft must be initialized to the default values that are used if
+    // auto is specified.
+    void pageSizeAndMarginsInPixels(int pageIndex, IntSize& pageSize, int& marginTop, int& marginRight, int& marginBottom, int& marginLeft);
+
+    CachedResourceLoader* cachedResourceLoader() { return m_cachedResourceLoader.get(); }
+
+    virtual void attach();
+    virtual void detach();
+    void prepareForDestruction();
+
+    // Override ScriptExecutionContext methods to do additional work
+    virtual void suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension) OVERRIDE;
+    virtual void resumeActiveDOMObjects() OVERRIDE;
+
+    RenderArena* renderArena() { return m_renderArena.get(); }
+
+    // Implemented in RenderView.h to avoid a cyclic header dependency this just
+    // returns renderer so callers can avoid verbose casts.
+    RenderView* renderView() const;
+
+    // Shadow the implementations on Node to provide faster access for documents.
+    RenderObject* renderer() const { return m_renderer; }
+    void setRenderer(RenderObject* renderer)
+    {
+        m_renderer = renderer;
+        Node::setRenderer(renderer);
+    }
+
+    AXObjectCache* existingAXObjectCache() const;
+    AXObjectCache* axObjectCache() const;
+    void clearAXObjectCache();
+
+    // to get visually ordered hebrew and arabic pages right
+    void setVisuallyOrdered();
+    bool visuallyOrdered() const { return m_visuallyOrdered; }
+    
+    DocumentLoader* loader() const;
+
+    void open(Document* ownerDocument = 0);
+    void implicitOpen();
+
+    // close() is the DOM API document.close()
+    void close();
+    // In some situations (see the code), we ignore document.close().
+    // explicitClose() bypass these checks and actually tries to close the
+    // input stream.
+    void explicitClose();
+    // implicitClose() actually does the work of closing the input stream.
+    void implicitClose();
+
+    void cancelParsing();
+
+    void write(const SegmentedString& text, Document* ownerDocument = 0);
+    void write(const String& text, Document* ownerDocument = 0);
+    void writeln(const String& text, Document* ownerDocument = 0);
+
+    bool wellFormed() const { return m_wellFormed; }
+
+    const KURL& url() const { return m_url; }
+    void setURL(const KURL&);
+
+    // To understand how these concepts relate to one another, please see the
+    // comments surrounding their declaration.
+    const KURL& baseURL() const { return m_baseURL; }
+    void setBaseURLOverride(const KURL&);
+    const KURL& baseURLOverride() const { return m_baseURLOverride; }
+    const KURL& baseElementURL() const { return m_baseElementURL; }
+    const String& baseTarget() const { return m_baseTarget; }
+    void processBaseElement();
+
+    KURL completeURL(const String&) const;
+    KURL completeURL(const String&, const KURL& baseURLOverride) const;
+
+    virtual String userAgent(const KURL&) const;
+
+    virtual void disableEval(const String& errorMessage);
+
+    bool canNavigate(Frame* targetFrame);
+    Frame* findUnsafeParentScrollPropagationBoundary();
+
+    CSSStyleSheet* elementSheet();
+    
+    virtual PassRefPtr<DocumentParser> createParser();
+    DocumentParser* parser() const { return m_parser.get(); }
+    ScriptableDocumentParser* scriptableDocumentParser() const;
+    
+    bool printing() const { return m_printing; }
+    void setPrinting(bool p) { m_printing = p; }
+
+    bool paginatedForScreen() const { return m_paginatedForScreen; }
+    void setPaginatedForScreen(bool p) { m_paginatedForScreen = p; }
+    
+    bool paginated() const { return printing() || paginatedForScreen(); }
+
+    enum CompatibilityMode { QuirksMode, LimitedQuirksMode, NoQuirksMode };
+
+    void setCompatibilityMode(CompatibilityMode m);
+    void lockCompatibilityMode() { m_compatibilityModeLocked = true; }
+    CompatibilityMode compatibilityMode() const { return m_compatibilityMode; }
+
+    String compatMode() const;
+
+    bool inQuirksMode() const { return m_compatibilityMode == QuirksMode; }
+    bool inLimitedQuirksMode() const { return m_compatibilityMode == LimitedQuirksMode; }
+    bool inNoQuirksMode() const { return m_compatibilityMode == NoQuirksMode; }
+
+    enum ReadyState {
+        Loading,
+        Interactive,
+        Complete
+    };
+    void setReadyState(ReadyState);
+    void setParsing(bool);
+    bool parsing() const { return m_bParsing; }
+    int minimumLayoutDelay();
+
+    bool shouldScheduleLayout();
+    bool isLayoutTimerActive();
+    int elapsedTime() const;
+    
+    void setTextColor(const Color& color) { m_textColor = color; }
+    Color textColor() const { return m_textColor; }
+
+    const Color& linkColor() const { return m_linkColor; }
+    const Color& visitedLinkColor() const { return m_visitedLinkColor; }
+    const Color& activeLinkColor() const { return m_activeLinkColor; }
+    void setLinkColor(const Color& c) { m_linkColor = c; }
+    void setVisitedLinkColor(const Color& c) { m_visitedLinkColor = c; }
+    void setActiveLinkColor(const Color& c) { m_activeLinkColor = c; }
+    void resetLinkColor();
+    void resetVisitedLinkColor();
+    void resetActiveLinkColor();
+    VisitedLinkState* visitedLinkState() const { return m_visitedLinkState.get(); }
+
+    MouseEventWithHitTestResults prepareMouseEvent(const HitTestRequest&, const LayoutPoint&, const PlatformMouseEvent&);
+
+    /* Newly proposed CSS3 mechanism for selecting alternate
+       stylesheets using the DOM. May be subject to change as
+       spec matures. - dwh
+    */
+    String preferredStylesheetSet() const;
+    String selectedStylesheetSet() const;
+    void setSelectedStylesheetSet(const String&);
+
+    bool setFocusedNode(PassRefPtr<Node>, FocusDirection = FocusDirectionNone);
+    Node* focusedNode() const { return m_focusedNode.get(); }
+    UserActionElementSet& userActionElements()  { return m_userActionElements; }
+    const UserActionElementSet& userActionElements() const { return m_userActionElements; }
+
+    void getFocusableNodes(Vector<RefPtr<Node> >&);
+    
+    // The m_ignoreAutofocus flag specifies whether or not the document has been changed by the user enough 
+    // for WebCore to ignore the autofocus attribute on any form controls
+    bool ignoreAutofocus() const { return m_ignoreAutofocus; };
+    void setIgnoreAutofocus(bool shouldIgnore = true) { m_ignoreAutofocus = shouldIgnore; };
+
+    void setHoverNode(PassRefPtr<Node>);
+    Node* hoverNode() const { return m_hoverNode.get(); }
+
+    void setActiveElement(PassRefPtr<Element>);
+    Element* activeElement() const { return m_activeElement.get(); }
+
+    void focusedNodeRemoved();
+    void removeFocusedNodeOfSubtree(Node*, bool amongChildrenOnly = false);
+    void hoveredNodeDetached(Node*);
+    void activeChainNodeDetached(Node*);
+
+    void updateHoverActiveState(const HitTestRequest&, Element*);
+
+    // Updates for :target (CSS3 selector).
+    void setCSSTarget(Element*);
+    Element* cssTarget() const { return m_cssTarget; }
+    
+    void scheduleForcedStyleRecalc();
+    void scheduleStyleRecalc();
+    void unscheduleStyleRecalc();
+    bool hasPendingStyleRecalc() const;
+    bool hasPendingForcedStyleRecalc() const;
+    void styleRecalcTimerFired(Timer<Document>*);
+
+    void registerNodeList(LiveNodeListBase*);
+    void unregisterNodeList(LiveNodeListBase*);
+    bool shouldInvalidateNodeListCaches(const QualifiedName* attrName = 0) const;
+    void invalidateNodeListCaches(const QualifiedName* attrName);
+
+    void attachNodeIterator(NodeIterator*);
+    void detachNodeIterator(NodeIterator*);
+    void moveNodeIteratorsToNewDocument(Node*, Document*);
+
+    void attachRange(Range*);
+    void detachRange(Range*);
+
+    void updateRangesAfterChildrenChanged(ContainerNode*);
+    // nodeChildrenWillBeRemoved is used when removing all node children at once.
+    void nodeChildrenWillBeRemoved(ContainerNode*);
+    // nodeWillBeRemoved is only safe when removing one node at a time.
+    void nodeWillBeRemoved(Node*);
+    bool canReplaceChild(Node* newChild, Node* oldChild);
+
+    void textInserted(Node*, unsigned offset, unsigned length);
+    void textRemoved(Node*, unsigned offset, unsigned length);
+    void textNodesMerged(Text* oldNode, unsigned offset);
+    void textNodeSplit(Text* oldNode);
+
+    void createDOMWindow();
+    void takeDOMWindowFrom(Document*);
+
+    DOMWindow* domWindow() const { return m_domWindow.get(); }
+    // In DOM Level 2, the Document's DOMWindow is called the defaultView.
+    DOMWindow* defaultView() const { return domWindow(); } 
+
+    // Helper functions for forwarding DOMWindow event related tasks to the DOMWindow if it exists.
+    void setWindowAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener>);
+    EventListener* getWindowAttributeEventListener(const AtomicString& eventType);
+    void dispatchWindowEvent(PassRefPtr<Event>, PassRefPtr<EventTarget> = 0);
+    void dispatchWindowLoadEvent();
+
+    PassRefPtr<Event> createEvent(const String& eventType, ExceptionCode&);
+
+    // keep track of what types of event listeners are registered, so we don't
+    // dispatch events unnecessarily
+    enum ListenerType {
+        DOMSUBTREEMODIFIED_LISTENER          = 1,
+        DOMNODEINSERTED_LISTENER             = 1 << 1,
+        DOMNODEREMOVED_LISTENER              = 1 << 2,
+        DOMNODEREMOVEDFROMDOCUMENT_LISTENER  = 1 << 3,
+        DOMNODEINSERTEDINTODOCUMENT_LISTENER = 1 << 4,
+        DOMCHARACTERDATAMODIFIED_LISTENER    = 1 << 5,
+        OVERFLOWCHANGED_LISTENER             = 1 << 6,
+        ANIMATIONEND_LISTENER                = 1 << 7,
+        ANIMATIONSTART_LISTENER              = 1 << 8,
+        ANIMATIONITERATION_LISTENER          = 1 << 9,
+        TRANSITIONEND_LISTENER               = 1 << 10,
+        BEFORELOAD_LISTENER                  = 1 << 11,
+        SCROLL_LISTENER                      = 1 << 12
+        // 3 bits remaining
+    };
+
+    bool hasListenerType(ListenerType listenerType) const { return (m_listenerTypes & listenerType); }
+    void addListenerTypeIfNeeded(const AtomicString& eventType);
+
+    bool hasMutationObserversOfType(MutationObserver::MutationType type) const
+    {
+        return m_mutationObserverTypes & type;
+    }
+    bool hasMutationObservers() const { return m_mutationObserverTypes; }
+    void addMutationObserverTypes(MutationObserverOptions types) { m_mutationObserverTypes |= types; }
+
+    CSSStyleDeclaration* getOverrideStyle(Element*, const String& pseudoElt);
+
+    int nodeAbsIndex(Node*);
+    Node* nodeWithAbsIndex(int absIndex);
+
+    /**
+     * Handles a HTTP header equivalent set by a meta tag using <meta http-equiv="..." content="...">. This is called
+     * when a meta tag is encountered during document parsing, and also when a script dynamically changes or adds a meta
+     * tag. This enables scripts to use meta tags to perform refreshes and set expiry dates in addition to them being
+     * specified in a HTML file.
+     *
+     * @param equiv The http header name (value of the meta tag's "equiv" attribute)
+     * @param content The header value (value of the meta tag's "content" attribute)
+     */
+    void processHttpEquiv(const String& equiv, const String& content);
+    void processViewport(const String& features, ViewportArguments::Type origin);
+    void updateViewportArguments();
+    void processReferrerPolicy(const String& policy);
+
+    // Returns the owning element in the parent document.
+    // Returns 0 if this is the top level document.
+    HTMLFrameOwnerElement* ownerElement() const;
+
+    HTMLIFrameElement* seamlessParentIFrame() const;
+    bool shouldDisplaySeamlesslyWithParent() const;
+
+    // Used by DOM bindings; no direction known.
+    String title() const { return m_title.string(); }
+    void setTitle(const String&);
+
+    void setTitleElement(const StringWithDirection&, Element* titleElement);
+    void removeTitle(Element* titleElement);
+
+    String cookie(ExceptionCode&) const;
+    void setCookie(const String&, ExceptionCode&);
+
+    String referrer() const;
+
+    String domain() const;
+    void setDomain(const String& newDomain, ExceptionCode&);
+
+    String lastModified() const;
+
+    // The cookieURL is used to query the cookie database for this document's
+    // cookies. For example, if the cookie URL is http://example.com, we'll
+    // use the non-Secure cookies for example.com when computing
+    // document.cookie.
+    //
+    // Q: How is the cookieURL different from the document's URL?
+    // A: The two URLs are the same almost all the time.  However, if one
+    //    document inherits the security context of another document, it
+    //    inherits its cookieURL but not its URL.
+    //
+    const KURL& cookieURL() const { return m_cookieURL; }
+    void setCookieURL(const KURL& url) { m_cookieURL = url; }
+
+    // The firstPartyForCookies is used to compute whether this document
+    // appears in a "third-party" context for the purpose of third-party
+    // cookie blocking.  The document is in a third-party context if the
+    // cookieURL and the firstPartyForCookies are from different hosts.
+    //
+    // Note: Some ports (including possibly Apple's) only consider the
+    //       document in a third-party context if the cookieURL and the
+    //       firstPartyForCookies have a different registry-controlled
+    //       domain.
+    //
+    const KURL& firstPartyForCookies() const { return m_firstPartyForCookies; }
+    void setFirstPartyForCookies(const KURL& url) { m_firstPartyForCookies = url; }
+    
+    // The following implements the rule from HTML 4 for what valid names are.
+    // To get this right for all the XML cases, we probably have to improve this or move it
+    // and make it sensitive to the type of document.
+    static bool isValidName(const String&);
+
+    // The following breaks a qualified name into a prefix and a local name.
+    // It also does a validity check, and returns false if the qualified name
+    // is invalid.  It also sets ExceptionCode when name is invalid.
+    static bool parseQualifiedName(const String& qualifiedName, String& prefix, String& localName, ExceptionCode&);
+
+    // Checks to make sure prefix and namespace do not conflict (per DOM Core 3)
+    static bool hasValidNamespaceForElements(const QualifiedName&);
+    static bool hasValidNamespaceForAttributes(const QualifiedName&);
+
+    HTMLElement* body() const;
+    void setBody(PassRefPtr<HTMLElement>, ExceptionCode&);
+
+    HTMLHeadElement* head();
+
+    DocumentMarkerController* markers() const { return m_markers.get(); }
+
+    bool directionSetOnDocumentElement() const { return m_directionSetOnDocumentElement; }
+    bool writingModeSetOnDocumentElement() const { return m_writingModeSetOnDocumentElement; }
+    void setDirectionSetOnDocumentElement(bool b) { m_directionSetOnDocumentElement = b; }
+    void setWritingModeSetOnDocumentElement(bool b) { m_writingModeSetOnDocumentElement = b; }
+
+    bool execCommand(const String& command, bool userInterface = false, const String& value = String());
+    bool queryCommandEnabled(const String& command);
+    bool queryCommandIndeterm(const String& command);
+    bool queryCommandState(const String& command);
+    bool queryCommandSupported(const String& command);
+    String queryCommandValue(const String& command);
+
+    KURL openSearchDescriptionURL();
+
+    // designMode support
+    enum InheritedBool { off = false, on = true, inherit };    
+    void setDesignMode(InheritedBool value);
+    InheritedBool getDesignMode() const;
+    bool inDesignMode() const;
+
+    Document* parentDocument() const;
+    Document* topDocument() const;
+
+    int docID() const { return m_docID; }
+    
+    ScriptRunner* scriptRunner() { return m_scriptRunner.get(); }
+
+    void applyXSLTransform(ProcessingInstruction* pi);
+    PassRefPtr<Document> transformSourceDocument() { return m_transformSourceDocument; }
+    void setTransformSourceDocument(Document* doc) { m_transformSourceDocument = doc; }
+
+    void setTransformSource(PassOwnPtr<TransformSource>);
+    TransformSource* transformSource() const { return m_transformSource.get(); }
+
+    void incDOMTreeVersion() { m_domTreeVersion = ++s_globalTreeVersion; }
+    uint64_t domTreeVersion() const { return m_domTreeVersion; }
+
+    void setDocType(PassRefPtr<DocumentType>);
+
+    // XPathEvaluator methods
+    PassRefPtr<XPathExpression> createExpression(const String& expression,
+                                                 XPathNSResolver* resolver,
+                                                 ExceptionCode& ec);
+    PassRefPtr<XPathNSResolver> createNSResolver(Node *nodeResolver);
+    PassRefPtr<XPathResult> evaluate(const String& expression,
+                                     Node* contextNode,
+                                     XPathNSResolver* resolver,
+                                     unsigned short type,
+                                     XPathResult* result,
+                                     ExceptionCode& ec);
+
+    enum PendingSheetLayout { NoLayoutWithPendingSheets, DidLayoutWithPendingSheets, IgnoreLayoutWithPendingSheets };
+
+    bool didLayoutWithPendingStylesheets() const { return m_pendingSheetLayout == DidLayoutWithPendingSheets; }
+
+    bool hasNodesWithPlaceholderStyle() const { return m_hasNodesWithPlaceholderStyle; }
+    void setHasNodesWithPlaceholderStyle() { m_hasNodesWithPlaceholderStyle = true; }
+
+    const Vector<IconURL>& shortcutIconURLs();
+    const Vector<IconURL>& iconURLs(int iconTypesMask);
+    void addIconURL(const String& url, const String& mimeType, const String& size, IconType);
+
+    void setUseSecureKeyboardEntryWhenActive(bool);
+    bool useSecureKeyboardEntryWhenActive() const;
+
+    void updateFocusAppearanceSoon(bool restorePreviousSelection);
+    void cancelFocusAppearanceUpdate();
+        
+    // Extension for manipulating canvas drawing contexts for use in CSS
+    CanvasRenderingContext* getCSSCanvasContext(const String& type, const String& name, int width, int height);
+    HTMLCanvasElement* getCSSCanvasElement(const String& name);
+
+    bool isDNSPrefetchEnabled() const { return m_isDNSPrefetchEnabled; }
+    void parseDNSPrefetchControlHeader(const String&);
+
+    virtual void postTask(PassOwnPtr<Task>); // Executes the task on context's thread asynchronously.
+
+    virtual void suspendScriptedAnimationControllerCallbacks();
+    virtual void resumeScriptedAnimationControllerCallbacks();
+    
+    virtual void finishedParsing();
+
+    void documentWillBecomeInactive();
+
+    void registerForCaptionPreferencesChangedCallbacks(Element*);
+    void unregisterForCaptionPreferencesChangedCallbacks(Element*);
+    void captionPreferencesChanged();
+
+    void setShouldCreateRenderers(bool);
+    bool shouldCreateRenderers();
+
+    void setDecoder(PassRefPtr<TextResourceDecoder>);
+    TextResourceDecoder* decoder() const { return m_decoder.get(); }
+
+    String displayStringModifiedByEncoding(const String&) const;
+    PassRefPtr<StringImpl> displayStringModifiedByEncoding(PassRefPtr<StringImpl>) const;
+    void displayBufferModifiedByEncoding(LChar* buffer, unsigned len) const
+    {
+        displayBufferModifiedByEncodingInternal(buffer, len);
+    }
+    void displayBufferModifiedByEncoding(UChar* buffer, unsigned len) const
+    {
+        displayBufferModifiedByEncodingInternal(buffer, len);
+    }
+
+    // Quirk for the benefit of Apple's Dictionary application.
+    void setFrameElementsShouldIgnoreScrolling(bool ignore) { m_frameElementsShouldIgnoreScrolling = ignore; }
+    bool frameElementsShouldIgnoreScrolling() const { return m_frameElementsShouldIgnoreScrolling; }
+
+    void setAnnotatedRegionsDirty(bool f) { m_annotatedRegionsDirty = f; }
+    bool annotatedRegionsDirty() const { return m_annotatedRegionsDirty; }
+    bool hasAnnotatedRegions () const { return m_hasAnnotatedRegions; }
+    void setHasAnnotatedRegions(bool f) { m_hasAnnotatedRegions = f; }
+    const Vector<AnnotatedRegionValue>& annotatedRegions() const;
+    void setAnnotatedRegions(const Vector<AnnotatedRegionValue>&);
+
+    virtual void removeAllEventListeners();
+
+#if ENABLE(SVG)
+    const SVGDocumentExtensions* svgExtensions();
+    SVGDocumentExtensions* accessSVGExtensions();
+#endif
+
+    void initSecurityContext();
+    void initContentSecurityPolicy();
+
+    void updateURLForPushOrReplaceState(const KURL&);
+    void statePopped(PassRefPtr<SerializedScriptValue>);
+
+    bool processingLoadEvent() const { return m_processingLoadEvent; }
+    bool loadEventFinished() const { return m_loadEventFinished; }
+
+    virtual bool isContextThread() const;
+    virtual bool isJSExecutionForbidden() const { return false; }
+
+    bool containsValidityStyleRules() const { return m_containsValidityStyleRules; }
+    void setContainsValidityStyleRules() { m_containsValidityStyleRules = true; }
+
+    void enqueueWindowEvent(PassRefPtr<Event>);
+    void enqueueDocumentEvent(PassRefPtr<Event>);
+    void enqueuePageshowEvent(PageshowEventPersistence);
+    void enqueueHashchangeEvent(const String& oldURL, const String& newURL);
+    void enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject);
+    virtual DocumentEventQueue* eventQueue() const { return m_eventQueue.get(); }
+
+    const QualifiedName& idAttributeName() const { return m_idAttributeName; }
+    
+    bool webkitIsFullScreen() const { return m_fullScreenElement.get(); }
+    bool webkitFullScreenKeyboardInputAllowed() const { return m_fullScreenElement.get() && m_areKeysEnabledInFullScreen; }
+    Element* webkitCurrentFullScreenElement() const { return m_fullScreenElement.get(); }
+    
+    enum FullScreenCheckType {
+        EnforceIFrameAllowFullScreenRequirement,
+        ExemptIFrameAllowFullScreenRequirement,
+    };
+
+    void requestFullScreenForElement(Element*, unsigned short flags, FullScreenCheckType);
+    void webkitCancelFullScreen();
+    
+    void webkitWillEnterFullScreenForElement(Element*);
+    void webkitDidEnterFullScreenForElement(Element*);
+    void webkitWillExitFullScreenForElement(Element*);
+    void webkitDidExitFullScreenForElement(Element*);
+    
+    void setFullScreenRenderer(RenderFullScreen*);
+    RenderFullScreen* fullScreenRenderer() const { return m_fullScreenRenderer; }
+    void fullScreenRendererDestroyed();
+    
+    void setFullScreenRendererSize(const IntSize&);
+    void setFullScreenRendererBackgroundColor(Color);
+    
+    void fullScreenChangeDelayTimerFired(Timer<Document>*);
+    bool fullScreenIsAllowedForElement(Element*) const;
+    void fullScreenElementRemoved();
+    void removeFullScreenElementOfSubtree(Node*, bool amongChildrenOnly = false);
+    bool isAnimatingFullScreen() const;
+    void setAnimatingFullScreen(bool);
+
+    // W3C API
+    bool webkitFullscreenEnabled() const;
+    Element* webkitFullscreenElement() const { return !m_fullScreenElementStack.isEmpty() ? m_fullScreenElementStack.last().get() : 0; }
+    void webkitExitFullscreen();
+
+    void webkitExitPointerLock();
+    Element* webkitPointerLockElement() const;
+
+    // Used to allow element that loads data without going through a FrameLoader to delay the 'load' event.
+    void incrementLoadEventDelayCount() { ++m_loadEventDelayCount; }
+    void decrementLoadEventDelayCount();
+    bool isDelayingLoadEvent() const { return m_loadEventDelayCount; }
+
+    PassRefPtr<Touch> createTouch(DOMWindow*, EventTarget*, int identifier, int pageX, int pageY, int screenX, int screenY, int radiusX, int radiusY, float rotationAngle, float force, ExceptionCode&) const;
+
+    const DocumentTiming* timing() const { return &m_documentTiming; }
+
+    int requestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback>);
+    void cancelAnimationFrame(int id);
+    void serviceScriptedAnimations(double monotonicAnimationStartTime);
+
+    virtual EventTarget* errorEventTarget();
+    virtual void logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, PassRefPtr<ScriptCallStack>);
+
+    void initDNSPrefetch();
+
+    unsigned wheelEventHandlerCount() const { return m_wheelEventHandlerCount; }
+    void didAddWheelEventHandler();
+    void didRemoveWheelEventHandler();
+
+    double lastHandledUserGestureTimestamp() const { return m_lastHandledUserGestureTimestamp; }
+    void resetLastHandledUserGestureTimestamp();
+
+    bool hasTouchEventHandlers() const { return (m_touchEventTargets.get()) ? m_touchEventTargets->size() : false; }
+
+    void didAddTouchEventHandler(Node*);
+    void didRemoveTouchEventHandler(Node*);
+
+    void didRemoveEventTargetNode(Node*);
+
+    const TouchEventTargetSet* touchEventTargets() const { return m_touchEventTargets.get(); }
+
+    bool isInDocumentWrite() { return m_writeRecursionDepth > 0; }
+
+    void suspendScheduledTasks(ActiveDOMObject::ReasonForSuspension);
+    void resumeScheduledTasks();
+
+    IntSize viewportSize() const;
+
+#if ENABLE(CSS_DEVICE_ADAPTATION)
+    IntSize initialViewportSize() const;
+#endif
+
+    Prerenderer* prerenderer() { return m_prerenderer.get(); }
+
+    TextAutosizer* textAutosizer() { return m_textAutosizer.get(); }
+
+    PassRefPtr<Element> createElement(const AtomicString& localName, const AtomicString& typeExtension, ExceptionCode&);
+    PassRefPtr<Element> createElementNS(const AtomicString& namespaceURI, const String& qualifiedName, const AtomicString& typeExtension, ExceptionCode&);
+    PassRefPtr<CustomElementConstructor> registerElement(WebCore::ScriptState*, const AtomicString& name, ExceptionCode&);
+    PassRefPtr<CustomElementConstructor> registerElement(WebCore::ScriptState*, const AtomicString& name, const Dictionary& options, ExceptionCode&);
+    CustomElementRegistry* registry() const { return m_registry.get(); }
+    CustomElementRegistry* ensureCustomElementRegistry();
+
+    void adjustFloatQuadsForScrollAndAbsoluteZoom(Vector<FloatQuad>&, RenderObject*);
+    void adjustFloatRectForScrollAndAbsoluteZoom(FloatRect&, RenderObject*);
+
+    bool hasActiveParser();
+    unsigned activeParserCount() { return m_activeParserCount; }
+    void incrementActiveParserCount() { ++m_activeParserCount; }
+    void decrementActiveParserCount();
+
+    void setContextFeatures(PassRefPtr<ContextFeatures>);
+    ContextFeatures* contextFeatures() { return m_contextFeatures.get(); }
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+    DocumentSharedObjectPool* sharedObjectPool() { return m_sharedObjectPool.get(); }
+
+    void didRemoveAllPendingStylesheet();
+    void setNeedsNotifyRemoveAllPendingStylesheet() { m_needsNotifyRemoveAllPendingStylesheet = true; }
+    void clearStyleResolver();
+    void notifySeamlessChildDocumentsOfStylesheetUpdate() const;
+
+    bool inStyleRecalc() { return m_inStyleRecalc; }
+
+    // Return a Locale for the default locale if the argument is null or empty.
+    Locale& getCachedLocale(const AtomicString& locale = nullAtom);
+
+    void addToTopLayer(Element*);
+    void removeFromTopLayer(Element*);
+    const Vector<RefPtr<Element> >& topLayerElements() const { return m_topLayerElements; }
+    Element* activeModalDialog() const { return !m_topLayerElements.isEmpty() ? m_topLayerElements.last().get() : 0; }
+
+    const Document* templateDocument() const;
+    Document* ensureTemplateDocument();
+    void setTemplateDocumentHost(Document* templateDocumentHost) { m_templateDocumentHost = templateDocumentHost; }
+    Document* templateDocumentHost() { return m_templateDocumentHost; }
+
+    void didAssociateFormControl(Element*);
+
+    virtual void addConsoleMessage(MessageSource, MessageLevel, const String& message, unsigned long requestIdentifier = 0);
+
+    virtual const SecurityOrigin* topOrigin() const OVERRIDE;
+
+    PassRefPtr<FontLoader> fontloader();
+
+protected:
+    Document(Frame*, const KURL&, bool isXHTML, bool isHTML);
+
+    virtual void didUpdateSecurityOrigin() OVERRIDE;
+
+    void clearXMLVersion() { m_xmlVersion = String(); }
+
+private:
+    friend class Node;
+    friend class IgnoreDestructiveWriteCountIncrementer;
+
+    virtual void dispose() OVERRIDE;
+
+    void detachParser();
+
+    typedef void (*ArgumentsCallback)(const String& keyString, const String& valueString, Document*, void* data);
+    void processArguments(const String& features, void* data, ArgumentsCallback);
+
+    virtual bool isDocument() const OVERRIDE { return true; }
+
+    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) const;
+    virtual PassRefPtr<Node> cloneNode(bool deep);
+
+    virtual void refScriptExecutionContext() { ref(); }
+    virtual void derefScriptExecutionContext() { deref(); }
+
+    virtual const KURL& virtualURL() const; // Same as url(), but needed for ScriptExecutionContext to implement it without a performance loss for direct calls.
+    virtual KURL virtualCompleteURL(const String&) const; // Same as completeURL() for the same reason as above.
+
+    virtual void addMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, PassRefPtr<ScriptCallStack>, ScriptState* = 0, unsigned long requestIdentifier = 0);
+
+    virtual double timerAlignmentInterval() const;
+
+    void updateTitle(const StringWithDirection&);
+    void updateFocusAppearanceTimerFired(Timer<Document>*);
+    void updateBaseURL();
+
+    void buildAccessKeyMap(TreeScope* root);
+
+    void createStyleResolver();
+
+    void seamlessParentUpdatedStylesheets();
+
+    PassRefPtr<NodeList> handleZeroPadding(const HitTestRequest&, HitTestResult&) const;
+
+    void loadEventDelayTimerFired(Timer<Document>*);
+
+    void pendingTasksTimerFired(Timer<Document>*);
+
+    static void didReceiveTask(void*);
+    
+    template <typename CharacterType>
+    void displayBufferModifiedByEncodingInternal(CharacterType*, unsigned) const;
+
+    PageVisibilityState visibilityState() const;
+
+    PassRefPtr<HTMLCollection> ensureCachedCollection(CollectionType);
+
+    void clearFullscreenElementStack();
+    void popFullscreenElementStack();
+    void pushFullscreenElementStack(Element*);
+    void addDocumentToFullScreenChangeEventQueue(Document*);
+
+    void addListenerType(ListenerType listenerType) { m_listenerTypes |= listenerType; }
+    void addMutationEventListenerTypeIfEnabled(ListenerType);
+
+    void didAssociateFormControlsTimerFired(Timer<Document>*);
+
+    void styleResolverThrowawayTimerFired(Timer<Document>*);
+    Timer<Document> m_styleResolverThrowawayTimer;
+    double m_lastStyleResolverAccessTime;
+
+    OwnPtr<StyleResolver> m_styleResolver;
+    bool m_didCalculateStyleResolver;
+    bool m_hasDirtyStyleResolver;
+    bool m_hasNodesWithPlaceholderStyle;
+    bool m_needsNotifyRemoveAllPendingStylesheet;
+    // But sometimes you need to ignore pending stylesheet count to
+    // force an immediate layout when requested by JS.
+    bool m_ignorePendingStylesheets;
+
+    // If we do ignore the pending stylesheet count, then we need to add a boolean
+    // to track that this happened so that we can do a full repaint when the stylesheets
+    // do eventually load.
+    PendingSheetLayout m_pendingSheetLayout;
+
+    Frame* m_frame;
+    RefPtr<DOMWindow> m_domWindow;
+
+    RefPtr<CachedResourceLoader> m_cachedResourceLoader;
+    RefPtr<DocumentParser> m_parser;
+    unsigned m_activeParserCount;
+    RefPtr<ContextFeatures> m_contextFeatures;
+
+    bool m_wellFormed;
+
+    // Document URLs.
+    KURL m_url; // Document.URL: The URL from which this document was retrieved.
+    KURL m_baseURL; // Node.baseURI: The URL to use when resolving relative URLs.
+    KURL m_baseURLOverride; // An alternative base URL that takes precedence over m_baseURL (but not m_baseElementURL).
+    KURL m_baseElementURL; // The URL set by the <base> element.
+    KURL m_cookieURL; // The URL to use for cookie access.
+    KURL m_firstPartyForCookies; // The policy URL for third-party cookie blocking.
+
+    // Document.documentURI:
+    // Although URL-like, Document.documentURI can actually be set to any
+    // string by content.  Document.documentURI affects m_baseURL unless the
+    // document contains a <base> element, in which case the <base> element
+    // takes precedence.
+    String m_documentURI;
+
+    String m_baseTarget;
+
+    RefPtr<DocumentType> m_docType;
+    OwnPtr<DOMImplementation> m_implementation;
+
+    RefPtr<CSSStyleSheet> m_elemSheet;
+
+    bool m_printing;
+    bool m_paginatedForScreen;
+
+    bool m_ignoreAutofocus;
+
+    CompatibilityMode m_compatibilityMode;
+    bool m_compatibilityModeLocked; // This is cheaper than making setCompatibilityMode virtual.
+
+    Color m_textColor;
+
+    RefPtr<Node> m_focusedNode;
+    RefPtr<Node> m_hoverNode;
+    RefPtr<Element> m_activeElement;
+    RefPtr<Element> m_documentElement;
+    UserActionElementSet m_userActionElements;
+
+    uint64_t m_domTreeVersion;
+    static uint64_t s_globalTreeVersion;
+    
+    HashSet<NodeIterator*> m_nodeIterators;
+    HashSet<Range*> m_ranges;
+
+    unsigned short m_listenerTypes;
+
+    MutationObserverOptions m_mutationObserverTypes;
+
+    OwnPtr<DocumentStyleSheetCollection> m_styleSheetCollection;
+    RefPtr<StyleSheetList> m_styleSheetList;
+
+    OwnPtr<FormController> m_formController;
+
+    Color m_linkColor;
+    Color m_visitedLinkColor;
+    Color m_activeLinkColor;
+    OwnPtr<VisitedLinkState> m_visitedLinkState;
+
+    bool m_loadingSheet;
+    bool m_visuallyOrdered;
+    ReadyState m_readyState;
+    bool m_bParsing;
+    
+    Timer<Document> m_styleRecalcTimer;
+    bool m_pendingStyleRecalcShouldForce;
+    bool m_inStyleRecalc;
+    bool m_closeAfterStyleRecalc;
+
+    bool m_gotoAnchorNeededAfterStylesheetsLoad;
+    bool m_isDNSPrefetchEnabled;
+    bool m_haveExplicitlyDisabledDNSPrefetch;
+    bool m_frameElementsShouldIgnoreScrolling;
+    bool m_containsValidityStyleRules;
+    bool m_updateFocusAppearanceRestoresSelection;
+
+    // http://www.whatwg.org/specs/web-apps/current-work/#ignore-destructive-writes-counter
+    unsigned m_ignoreDestructiveWriteCount;
+
+    StringWithDirection m_title;
+    StringWithDirection m_rawTitle;
+    bool m_titleSetExplicitly;
+    RefPtr<Element> m_titleElement;
+
+    OwnPtr<RenderArena> m_renderArena;
+
+    OwnPtr<AXObjectCache> m_axObjectCache;
+    OwnPtr<DocumentMarkerController> m_markers;
+    
+    Timer<Document> m_updateFocusAppearanceTimer;
+
+    Element* m_cssTarget;
+
+    // FIXME: Merge these 2 variables into an enum. Also, FrameLoader::m_didCallImplicitClose
+    // is almost a duplication of this data, so that should probably get merged in too.
+    // FIXME: Document::m_processingLoadEvent and DocumentLoader::m_wasOnloadHandled are roughly the same
+    // and should be merged.
+    bool m_processingLoadEvent;
+    bool m_loadEventFinished;
+
+    RefPtr<SerializedScriptValue> m_pendingStateObject;
+    double m_startTime;
+    bool m_overMinimumLayoutThreshold;
+    
+    OwnPtr<ScriptRunner> m_scriptRunner;
+
+    OwnPtr<TransformSource> m_transformSource;
+    RefPtr<Document> m_transformSourceDocument;
+
+    int m_docID; // A unique document identifier used for things like document-specific mapped attributes.
+
+    String m_xmlEncoding;
+    String m_xmlVersion;
+    unsigned m_xmlStandalone : 2;
+    unsigned m_hasXMLDeclaration : 1;
+
+    String m_contentLanguage;
+
+    RefPtr<TextResourceDecoder> m_decoder;
+
+    InheritedBool m_designMode;
+
+    HashSet<LiveNodeListBase*> m_listsInvalidatedAtDocument;
+    unsigned m_nodeListCounts[numNodeListInvalidationTypes];
+
+    RefPtr<XPathEvaluator> m_xpathEvaluator;
+
+#if ENABLE(SVG)
+    OwnPtr<SVGDocumentExtensions> m_svgExtensions;
+#endif
+
+    Vector<AnnotatedRegionValue> m_annotatedRegions;
+    bool m_hasAnnotatedRegions;
+    bool m_annotatedRegionsDirty;
+
+    HashMap<String, RefPtr<HTMLCanvasElement> > m_cssCanvasElements;
+
+    bool m_createRenderers;
+    Vector<IconURL> m_iconURLs;
+
+    HashSet<Element*> m_captionPreferencesChangedElements;
+
+    HashMap<StringImpl*, Element*, CaseFoldingHash> m_elementsByAccessKey;
+    bool m_accessKeyMapValid;
+
+    OwnPtr<SelectorQueryCache> m_selectorQueryCache;
+
+    bool m_useSecureKeyboardEntryWhenActive;
+
+    bool m_isXHTML;
+    bool m_isHTML;
+
+    bool m_isViewSource;
+    bool m_sawElementsInKnownNamespaces;
+    bool m_isSrcdocDocument;
+
+    RenderObject* m_renderer;
+    RefPtr<DocumentEventQueue> m_eventQueue;
+
+    WeakPtrFactory<Document> m_weakFactory;
+
+    QualifiedName m_idAttributeName;
+
+    bool m_areKeysEnabledInFullScreen;
+    RefPtr<Element> m_fullScreenElement;
+    Vector<RefPtr<Element> > m_fullScreenElementStack;
+    RenderFullScreen* m_fullScreenRenderer;
+    Timer<Document> m_fullScreenChangeDelayTimer;
+    Deque<RefPtr<Node> > m_fullScreenChangeEventTargetQueue;
+    Deque<RefPtr<Node> > m_fullScreenErrorEventTargetQueue;
+    bool m_isAnimatingFullScreen;
+    LayoutRect m_savedPlaceholderFrameRect;
+    RefPtr<RenderStyle> m_savedPlaceholderRenderStyle;
+
+    Vector<RefPtr<Element> > m_topLayerElements;
+
+    int m_loadEventDelayCount;
+    Timer<Document> m_loadEventDelayTimer;
+
+    ViewportArguments m_viewportArguments;
+
+    ReferrerPolicy m_referrerPolicy;
+
+    bool m_directionSetOnDocumentElement;
+    bool m_writingModeSetOnDocumentElement;
+
+    DocumentTiming m_documentTiming;
+    RefPtr<MediaQueryMatcher> m_mediaQueryMatcher;
+    bool m_writeRecursionIsTooDeep;
+    unsigned m_writeRecursionDepth;
+    
+    unsigned m_wheelEventHandlerCount;
+    OwnPtr<TouchEventTargetSet> m_touchEventTargets;
+
+    double m_lastHandledUserGestureTimestamp;
+
+    RefPtr<ScriptedAnimationController> m_scriptedAnimationController;
+
+    Timer<Document> m_pendingTasksTimer;
+    Vector<OwnPtr<Task> > m_pendingTasks;
+
+    OwnPtr<Prerenderer> m_prerenderer;
+
+    OwnPtr<TextAutosizer> m_textAutosizer;
+
+    RefPtr<CustomElementRegistry> m_registry;
+
+    bool m_scheduledTasksAreSuspended;
+    
+    RefPtr<NamedFlowCollection> m_namedFlows;
+
+    RefPtr<DOMSecurityPolicy> m_domSecurityPolicy;
+
+    void sharedObjectPoolClearTimerFired(Timer<Document>*);
+    Timer<Document> m_sharedObjectPoolClearTimer;
+
+    OwnPtr<DocumentSharedObjectPool> m_sharedObjectPool;
+
+#ifndef NDEBUG
+    bool m_didDispatchViewportPropertiesChanged;
+#endif
+
+    typedef HashMap<AtomicString, OwnPtr<Locale> > LocaleIdentifierToLocaleMap;
+    LocaleIdentifierToLocaleMap m_localeCache;
+
+    RefPtr<Document> m_templateDocument;
+    Document* m_templateDocumentHost; // Manually managed weakref (backpointer from m_templateDocument).
+
+    RefPtr<FontLoader> m_fontloader;
+
+    Timer<Document> m_didAssociateFormControlsTimer;
+    HashSet<RefPtr<Element> > m_associatedFormControls;
+
+};
+
+inline void Document::notifyRemovePendingSheetIfNeeded()
+{
+    if (m_needsNotifyRemoveAllPendingStylesheet)
+        didRemoveAllPendingStylesheet();
+}
+
+inline const Document* Document::templateDocument() const
+{
+    // If DOCUMENT does not have a browsing context, Let TEMPLATE CONTENTS OWNER be DOCUMENT and abort these steps.
+    if (!m_frame)
+        return this;
+
+    return m_templateDocument.get();
+}
+
+inline Document* toDocument(ScriptExecutionContext* scriptExecutionContext)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!scriptExecutionContext || scriptExecutionContext->isDocument());
+    return static_cast<Document*>(scriptExecutionContext);
+}
+
+inline const Document* toDocument(const ScriptExecutionContext* scriptExecutionContext)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!scriptExecutionContext || scriptExecutionContext->isDocument());
+    return static_cast<const Document*>(scriptExecutionContext);
+}
+
+inline Document* toDocument(Node* node)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isDocumentNode());
+    return static_cast<Document*>(node);
+}
+
+inline const Document* toDocument(const Node* node)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isDocumentNode());
+    return static_cast<const Document*>(node);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toDocument(const Document*);
+
+// Put these methods here, because they require the Document definition, but we really want to inline them.
+
+inline bool Node::isDocumentNode() const
+{
+    return this == documentInternal();
+}
+
+inline Node::Node(Document* document, ConstructionType type)
+    : m_nodeFlags(type)
+    , m_parentOrShadowHostNode(0)
+    , m_treeScope(document)
+    , m_previous(0)
+    , m_next(0)
+{
+    ScriptWrappable::init(this);
+    if (!m_treeScope)
+        m_treeScope = TreeScope::noDocumentInstance();
+    m_treeScope->guardRef();
+
+#if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS)
+    trackForDebugging();
+#endif
+    InspectorCounters::incrementCounter(InspectorCounters::NodeCounter);
+}
+
+Node* eventTargetNodeForDocument(Document*);
+
+} // namespace WebCore
+
+#endif // Document_h
diff --git a/Source/core/dom/Document.idl b/Source/core/dom/Document.idl
new file mode 100644
index 0000000..985097c
--- /dev/null
+++ b/Source/core/dom/Document.idl
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2006, 2007, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+[
+    CustomToV8
+] interface Document : Node {
+
+    // DOM Level 1 Core
+    readonly attribute DocumentType doctype;
+    readonly attribute DOMImplementation implementation;
+    readonly attribute Element documentElement;
+
+    [DeliverCustomElementCallbacks, PerWorldBindings, ActivityLog=AccessForIsolatedWorlds, RaisesException] Element createElement([TreatNullAs=NullString,Default=Undefined] optional DOMString tagName);
+    DocumentFragment   createDocumentFragment();
+    [PerWorldBindings] Text createTextNode([Default=Undefined] optional DOMString data);
+    Comment createComment([Default=Undefined] optional DOMString data);
+    [RaisesException] CDATASection createCDATASection([Default=Undefined] optional DOMString data);
+    [RaisesException] ProcessingInstruction createProcessingInstruction([Default=Undefined] optional DOMString target,
+                                                                                 [Default=Undefined] optional DOMString data);
+    [RaisesException] Attr createAttribute([Default=Undefined] optional DOMString name);
+    [RaisesException] EntityReference createEntityReference([Default=Undefined] optional DOMString name);
+    [PerWorldBindings] NodeList           getElementsByTagName([Default=Undefined] optional DOMString tagname);
+
+    // Introduced in DOM Level 2:
+
+    [DeliverCustomElementCallbacks, PerWorldBindings, ActivityLog=AccessForIsolatedWorlds, RaisesException] Node importNode([Default=Undefined] optional Node importedNode,
+                    optional boolean deep);
+    [DeliverCustomElementCallbacks, PerWorldBindings, ActivityLog=AccessForIsolatedWorlds, RaisesException] Element createElementNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
+                            [TreatNullAs=NullString,Default=Undefined] optional DOMString qualifiedName);
+    [RaisesException] Attr createAttributeNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
+                                                                          [TreatNullAs=NullString,Default=Undefined] optional DOMString qualifiedName);
+     NodeList getElementsByTagNameNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
+                                                   [Default=Undefined] optional DOMString localName);
+    [PerWorldBindings] Element            getElementById([Default=Undefined] optional DOMString elementId);
+
+    // DOM Level 3 Core
+
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString inputEncoding;
+
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString xmlEncoding;
+             [TreatReturnedNullStringAs=Null, TreatNullAs=NullString, SetterRaisesException] attribute DOMString xmlVersion;
+             [SetterRaisesException] attribute boolean xmlStandalone;
+
+    [RaisesException] Node               adoptNode([Default=Undefined] optional Node source);
+
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString documentURI;
+
+    // DOM Level 2 Events (DocumentEvents interface)
+
+    [RaisesException] Event              createEvent([Default=Undefined] optional DOMString eventType);
+
+    // DOM Level 2 Tranversal and Range (DocumentRange interface)
+
+    Range              createRange();
+
+    // DOM Level 2 Tranversal and Range (DocumentTraversal interface)
+
+     [RaisesException] NodeIterator createNodeIterator([Default=Undefined] optional Node root,
+                                                   [Default=Undefined] optional unsigned long whatToShow,
+                                                   [Default=Undefined] optional NodeFilter filter,
+                                                   [Default=Undefined] optional boolean expandEntityReferences);
+     [RaisesException] TreeWalker createTreeWalker([Default=Undefined] optional Node root,
+                                               [Default=Undefined] optional unsigned long whatToShow,
+                                               [Default=Undefined] optional NodeFilter filter,
+                                               [Default=Undefined] optional boolean expandEntityReferences);
+
+    // DOM Level 2 Abstract Views (DocumentView interface)
+
+    readonly attribute DOMWindow defaultView;
+
+    // DOM Level 2 Style (DocumentStyle interface)
+
+    readonly attribute StyleSheetList styleSheets;
+
+    // DOM Level 2 Style (DocumentCSS interface)
+
+     CSSStyleDeclaration getOverrideStyle([Default=Undefined] optional Element element,
+                                                        [Default=Undefined] optional DOMString pseudoElement);
+
+    // DOM Level 3 XPath (XPathEvaluator interface)
+     [RaisesException] XPathExpression createExpression([Default=Undefined] optional DOMString expression,
+                                                    [Default=Undefined] optional XPathNSResolver resolver);
+    XPathNSResolver    createNSResolver(Node nodeResolver);
+    [Custom, RaisesException] XPathResult evaluate([Default=Undefined] optional DOMString expression,
+                                                  [Default=Undefined] optional Node contextNode,
+                                                  [Default=Undefined] optional XPathNSResolver resolver,
+                                                  [Default=Undefined] optional unsigned short type,
+                                                  [Default=Undefined] optional XPathResult inResult);
+
+    // Common extensions
+    [DeliverCustomElementCallbacks]
+    boolean            execCommand([Default=Undefined] optional DOMString command,
+                                   [Default=Undefined] optional boolean userInterface,
+                                   [TreatNullAs=NullString, TreatUndefinedAs=NullString,Default=Undefined] optional DOMString value);
+
+    boolean            queryCommandEnabled([Default=Undefined] optional DOMString command);
+    boolean            queryCommandIndeterm([Default=Undefined] optional DOMString command);
+    boolean            queryCommandState([Default=Undefined] optional DOMString command);
+    boolean            queryCommandSupported([Default=Undefined] optional DOMString command);
+    DOMString          queryCommandValue([Default=Undefined] optional DOMString command);
+
+    // Moved down from HTMLDocument
+
+             [TreatNullAs=NullString] attribute DOMString title;
+    readonly attribute DOMString referrer;
+             [TreatNullAs=NullString, SetterRaisesException] attribute DOMString domain;
+    readonly attribute DOMString URL;
+
+             [TreatNullAs=NullString, GetterRaisesException, SetterRaisesException] attribute DOMString cookie;
+
+             [SetterRaisesException] attribute HTMLElement body;
+
+    readonly attribute HTMLHeadElement head;
+    readonly attribute HTMLCollection images;
+    readonly attribute HTMLCollection applets;
+    readonly attribute HTMLCollection links;
+    readonly attribute HTMLCollection forms;
+    readonly attribute HTMLCollection anchors;
+    readonly attribute DOMString lastModified;
+
+    [PerWorldBindings] NodeList getElementsByName([Default=Undefined] optional DOMString elementName);
+
+    [Custom, PerWorldBindings, ActivityLog=AccessForIsolatedWorlds] attribute Location location;
+
+    // IE extensions
+
+             [TreatReturnedNullStringAs=Undefined, TreatNullAs=NullString] attribute DOMString charset;
+    [TreatReturnedNullStringAs=Undefined] readonly attribute DOMString defaultCharset;
+    [TreatReturnedNullStringAs=Undefined] readonly attribute DOMString readyState;
+
+    Element            elementFromPoint([Default=Undefined] optional long x,
+                                        [Default=Undefined] optional long y);
+    Range              caretRangeFromPoint([Default=Undefined] optional long x,
+                                           [Default=Undefined] optional long y);
+
+    // Mozilla extensions
+    DOMSelection       getSelection();
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString characterSet;
+
+    // WebKit extensions
+
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString preferredStylesheetSet;
+             [TreatReturnedNullStringAs=Null, TreatNullAs=NullString] attribute DOMString selectedStylesheetSet;
+
+    CanvasRenderingContext getCSSCanvasContext(DOMString contextId, DOMString name, long width, long height);
+
+    // HTML 5
+    NodeList getElementsByClassName([Default=Undefined] optional DOMString tagname);
+
+    readonly attribute DOMString compatMode;
+
+    // NodeSelector - Selector API
+    [RaisesException] Element querySelector(DOMString selectors);
+    [RaisesException] NodeList querySelectorAll(DOMString selectors);
+
+    // Mozilla version
+    [EnabledAtRuntime=fullscreen] readonly attribute boolean webkitIsFullScreen;
+    [EnabledAtRuntime=fullscreen] readonly attribute boolean webkitFullScreenKeyboardInputAllowed;
+    [EnabledAtRuntime=fullscreen] readonly attribute Element webkitCurrentFullScreenElement;
+    [EnabledAtRuntime=fullscreen] void webkitCancelFullScreen();
+
+    // W3C version
+    [EnabledAtRuntime=fullscreen] readonly attribute boolean webkitFullscreenEnabled;
+    [EnabledAtRuntime=fullscreen] readonly attribute Element webkitFullscreenElement;
+    [EnabledAtRuntime=fullscreen] void webkitExitFullscreen();
+
+    void webkitExitPointerLock();
+    readonly attribute Element webkitPointerLockElement;
+
+    [EnabledAtRuntime=cssRegions] DOMNamedFlowCollection webkitGetNamedFlows();
+
+    [EnabledAtRuntime=fontLoadEvents] readonly attribute FontLoader fontloader;
+
+    // Event handler DOM attributes
+    [NotEnumerable] attribute EventListener onabort;
+    [NotEnumerable] attribute EventListener onblur;
+    [NotEnumerable] attribute EventListener onchange;
+    [NotEnumerable] attribute EventListener onclick;
+    [NotEnumerable] attribute EventListener oncontextmenu;
+    [NotEnumerable] attribute EventListener ondblclick;
+    [NotEnumerable] attribute EventListener ondrag;
+    [NotEnumerable] attribute EventListener ondragend;
+    [NotEnumerable] attribute EventListener ondragenter;
+    [NotEnumerable] attribute EventListener ondragleave;
+    [NotEnumerable] attribute EventListener ondragover;
+    [NotEnumerable] attribute EventListener ondragstart;
+    [NotEnumerable] attribute EventListener ondrop;
+    [NotEnumerable] attribute EventListener onerror;
+    [NotEnumerable] attribute EventListener onfocus;
+    [NotEnumerable] attribute EventListener oninput;
+    [NotEnumerable] attribute EventListener oninvalid;
+    [NotEnumerable] attribute EventListener onkeydown;
+    [NotEnumerable] attribute EventListener onkeypress;
+    [NotEnumerable] attribute EventListener onkeyup;
+    [NotEnumerable] attribute EventListener onload;
+    [NotEnumerable] attribute EventListener onmousedown;
+    [NotEnumerable] attribute EventListener onmousemove;
+    [NotEnumerable] attribute EventListener onmouseout;
+    [NotEnumerable] attribute EventListener onmouseover;
+    [NotEnumerable] attribute EventListener onmouseup;
+    [NotEnumerable] attribute EventListener onmousewheel;
+    [NotEnumerable] attribute EventListener onreadystatechange;
+    [NotEnumerable] attribute EventListener onscroll;
+    [NotEnumerable] attribute EventListener onselect;
+    [NotEnumerable] attribute EventListener onsubmit;
+
+    // attribute [NotEnumerable] EventListener oncanplay;
+    // attribute [NotEnumerable] EventListener oncanplaythrough;
+    // attribute [NotEnumerable] EventListener ondurationchange;
+    // attribute [NotEnumerable] EventListener onemptied;
+    // attribute [NotEnumerable] EventListener onended;
+    // attribute [NotEnumerable] EventListener onloadeddata;
+    // attribute [NotEnumerable] EventListener onloadedmetadata;
+    // attribute [NotEnumerable] EventListener onloadstart;
+    // attribute [NotEnumerable] EventListener onpause;
+    // attribute [NotEnumerable] EventListener onplay;
+    // attribute [NotEnumerable] EventListener onplaying;
+    // attribute [NotEnumerable] EventListener onprogress;
+    // attribute [NotEnumerable] EventListener onratechange;
+    // attribute [NotEnumerable] EventListener onseeked;
+    // attribute [NotEnumerable] EventListener onseeking;
+    // attribute [NotEnumerable] EventListener onshow;
+    // attribute [NotEnumerable] EventListener onstalled;
+    // attribute [NotEnumerable] EventListener onsuspend;
+    // attribute [NotEnumerable] EventListener ontimeupdate;
+    // attribute [NotEnumerable] EventListener onvolumechange;
+    // attribute [NotEnumerable] EventListener onwaiting;
+
+    // WebKit extensions
+    [NotEnumerable] attribute EventListener onbeforecut;
+    [NotEnumerable] attribute EventListener oncut;
+    [NotEnumerable] attribute EventListener onbeforecopy;
+    [NotEnumerable] attribute EventListener oncopy;
+    [NotEnumerable] attribute EventListener onbeforepaste;
+    [NotEnumerable] attribute EventListener onpaste;
+    [NotEnumerable] attribute EventListener onreset;
+    [NotEnumerable] attribute EventListener onsearch;
+    [NotEnumerable] attribute EventListener onselectstart;
+    [NotEnumerable] attribute EventListener onselectionchange;
+    [NotEnumerable,EnabledAtRuntime=touch] attribute EventListener ontouchstart;
+    [NotEnumerable,EnabledAtRuntime=touch] attribute EventListener ontouchmove;
+    [NotEnumerable,EnabledAtRuntime=touch] attribute EventListener ontouchend;
+    [NotEnumerable,EnabledAtRuntime=touch] attribute EventListener ontouchcancel;
+    [NotEnumerable] attribute EventListener onwebkitfullscreenchange;
+    [NotEnumerable] attribute EventListener onwebkitfullscreenerror;
+    [NotEnumerable] attribute EventListener onwebkitpointerlockchange;
+    [NotEnumerable] attribute EventListener onwebkitpointerlockerror;
+    [NotEnumerable, EnabledAtRuntime=experimentalContentSecurityPolicyFeatures] attribute EventListener onsecuritypolicyviolation;
+
+    [EnabledAtRuntime=touch, RaisesException] Touch createTouch([Default=Undefined] optional DOMWindow window,
+                                                     [Default=Undefined] optional EventTarget target,
+                                                     [Default=Undefined] optional long identifier,
+                                                     [Default=Undefined] optional long pageX,
+                                                     [Default=Undefined] optional long pageY,
+                                                     [Default=Undefined] optional long screenX,
+                                                     [Default=Undefined] optional long screenY,
+                                                     [Default=Undefined] optional long webkitRadiusX,
+                                                     [Default=Undefined] optional long webkitRadiusY,
+                                                     [Default=Undefined] optional float webkitRotationAngle,
+                                                     [Default=Undefined] optional float webkitForce);
+    [EnabledAtRuntime=touch, Custom, RaisesException] TouchList createTouchList();
+
+    [EnabledAtRuntime=customDOMElements, ImplementedAs=registerElement, CallWith=ScriptState, DeliverCustomElementCallbacks, RaisesException] CustomElementConstructor webkitRegister(DOMString name, optional Dictionary options);
+    [DeliverCustomElementCallbacks, PerWorldBindings, ActivityLog=AccessForIsolatedWorlds, RaisesException] Element createElement(DOMString localName, [TreatNullAs=NullString] DOMString typeExtension);
+    [DeliverCustomElementCallbacks, PerWorldBindings, ActivityLog=AccessForIsolatedWorlds, RaisesException] Element createElementNS([TreatNullAs=NullString] DOMString namespaceURI, DOMString qualifiedName,
+                            [TreatNullAs=NullString] DOMString typeExtension);
+
+    // Page visibility API.
+    readonly attribute DOMString webkitVisibilityState;
+    readonly attribute boolean webkitHidden;
+
+    // Security Policy API: http://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html#script-interfaces
+    [EnabledAtRuntime=experimentalContentSecurityPolicyFeatures] readonly attribute DOMSecurityPolicy securityPolicy;
+
+};
+
diff --git a/Source/core/dom/DocumentEventQueue.cpp b/Source/core/dom/DocumentEventQueue.cpp
new file mode 100644
index 0000000..4e160d0
--- /dev/null
+++ b/Source/core/dom/DocumentEventQueue.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "core/dom/DocumentEventQueue.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/Event.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/ScriptExecutionContext.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/page/DOMWindow.h"
+#include "core/page/SuspendableTimer.h"
+#include <wtf/MemoryInstrumentationHashSet.h>
+#include <wtf/MemoryInstrumentationListHashSet.h>
+
+namespace WebCore {
+    
+class DocumentEventQueueTimer : public SuspendableTimer {
+    WTF_MAKE_NONCOPYABLE(DocumentEventQueueTimer);
+public:
+    DocumentEventQueueTimer(DocumentEventQueue* eventQueue, ScriptExecutionContext* context)
+        : SuspendableTimer(context)
+        , m_eventQueue(eventQueue) { }
+
+    virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const OVERRIDE
+    {
+        MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+        SuspendableTimer::reportMemoryUsage(memoryObjectInfo);
+        info.addWeakPointer(m_eventQueue);
+    }
+
+private:
+    virtual void fired() { m_eventQueue->pendingEventTimerFired(); }
+    DocumentEventQueue* m_eventQueue;
+};
+
+PassRefPtr<DocumentEventQueue> DocumentEventQueue::create(ScriptExecutionContext* context)
+{
+    return adoptRef(new DocumentEventQueue(context));
+}
+
+DocumentEventQueue::DocumentEventQueue(ScriptExecutionContext* context)
+    : m_pendingEventTimer(adoptPtr(new DocumentEventQueueTimer(this, context)))
+    , m_isClosed(false)
+{
+    m_pendingEventTimer->suspendIfNeeded();
+}
+
+DocumentEventQueue::~DocumentEventQueue()
+{
+}
+
+bool DocumentEventQueue::enqueueEvent(PassRefPtr<Event> event)
+{
+    if (m_isClosed)
+        return false;
+
+    ASSERT(event->target());
+    bool wasAdded = m_queuedEvents.add(event).isNewEntry;
+    ASSERT_UNUSED(wasAdded, wasAdded); // It should not have already been in the list.
+    
+    if (!m_pendingEventTimer->isActive())
+        m_pendingEventTimer->startOneShot(0);
+
+    return true;
+}
+
+void DocumentEventQueue::enqueueOrDispatchScrollEvent(PassRefPtr<Node> target, ScrollEventTargetType targetType)
+{
+    if (!target->document()->hasListenerType(Document::SCROLL_LISTENER))
+        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 (!m_nodesWithQueuedScrollEvents.add(target.get()).isNewEntry)
+        return;
+
+    scrollEvent->setTarget(target);
+    enqueueEvent(scrollEvent.release());
+}
+
+void DocumentEventQueue::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    info.addMember(m_pendingEventTimer, "pendingEventTimer");
+    info.addMember(m_queuedEvents, "queuedEvents");
+    info.addMember(m_nodesWithQueuedScrollEvents, "nodesWithQueuedScrollEvents");
+}
+
+bool DocumentEventQueue::cancelEvent(Event* event)
+{
+    bool found = m_queuedEvents.contains(event);
+    m_queuedEvents.remove(event);
+    if (m_queuedEvents.isEmpty())
+        m_pendingEventTimer->stop();
+    return found;
+}
+
+void DocumentEventQueue::close()
+{
+    m_isClosed = true;
+    m_pendingEventTimer->stop();
+    m_queuedEvents.clear();
+}
+
+void DocumentEventQueue::pendingEventTimerFired()
+{
+    ASSERT(!m_pendingEventTimer->isActive());
+    ASSERT(!m_queuedEvents.isEmpty());
+
+    m_nodesWithQueuedScrollEvents.clear();
+
+    // Insert a marker for where we should stop.
+    ASSERT(!m_queuedEvents.contains(0));
+    bool wasAdded = m_queuedEvents.add(0).isNewEntry;
+    ASSERT_UNUSED(wasAdded, wasAdded); // It should not have already been in the list.
+
+    RefPtr<DocumentEventQueue> protector(this);
+
+    while (!m_queuedEvents.isEmpty()) {
+        ListHashSet<RefPtr<Event>, 16>::iterator iter = m_queuedEvents.begin();
+        RefPtr<Event> event = *iter;
+        m_queuedEvents.remove(iter);
+        if (!event)
+            break;
+        dispatchEvent(event.get());
+    }
+}
+
+void DocumentEventQueue::dispatchEvent(PassRefPtr<Event> event)
+{
+    EventTarget* eventTarget = event->target();
+    if (eventTarget->toDOMWindow())
+        eventTarget->toDOMWindow()->dispatchEvent(event, 0);
+    else
+        eventTarget->dispatchEvent(event);
+}
+
+}
diff --git a/Source/core/dom/DocumentEventQueue.h b/Source/core/dom/DocumentEventQueue.h
new file mode 100644
index 0000000..233192a
--- /dev/null
+++ b/Source/core/dom/DocumentEventQueue.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef DocumentEventQueue_h
+#define DocumentEventQueue_h
+
+#include "core/dom/EventQueue.h"
+#include <wtf/Forward.h>
+#include <wtf/HashSet.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Event;
+class DocumentEventQueueTimer;
+class Node;
+class ScriptExecutionContext;
+
+class DocumentEventQueue : public RefCounted<DocumentEventQueue>, public EventQueue {
+public:
+    enum ScrollEventTargetType {
+        ScrollEventDocumentTarget,
+        ScrollEventElementTarget
+    };
+
+    static PassRefPtr<DocumentEventQueue> create(ScriptExecutionContext*);
+    virtual ~DocumentEventQueue();
+
+    // EventQueue
+    virtual bool enqueueEvent(PassRefPtr<Event>) OVERRIDE;
+    virtual bool cancelEvent(Event*) OVERRIDE;
+    virtual void close() OVERRIDE;
+
+    void enqueueOrDispatchScrollEvent(PassRefPtr<Node>, ScrollEventTargetType);
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+private:
+    explicit DocumentEventQueue(ScriptExecutionContext*);
+
+    void pendingEventTimerFired();
+    void dispatchEvent(PassRefPtr<Event>);
+
+    OwnPtr<DocumentEventQueueTimer> m_pendingEventTimer;
+    ListHashSet<RefPtr<Event>, 16> m_queuedEvents;
+    HashSet<Node*> m_nodesWithQueuedScrollEvents;
+    bool m_isClosed;
+
+    friend class DocumentEventQueueTimer;    
+};
+
+}
+
+#endif // DocumentEventQueue_h
diff --git a/Source/core/dom/DocumentFragment.cpp b/Source/core/dom/DocumentFragment.cpp
new file mode 100644
index 0000000..037b207
--- /dev/null
+++ b/Source/core/dom/DocumentFragment.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/DocumentFragment.h"
+
+#include "core/dom/Document.h"
+#include "core/html/parser/HTMLDocumentParser.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/xml/parser/XMLDocumentParser.h"
+
+namespace WebCore {
+
+DocumentFragment::DocumentFragment(Document* document, ConstructionType constructionType)
+    : ContainerNode(document, constructionType)
+{
+    ScriptWrappable::init(this);
+}
+
+PassRefPtr<DocumentFragment> DocumentFragment::create(Document* document)
+{
+    ASSERT(document);
+    return adoptRef(new DocumentFragment(document, Node::CreateDocumentFragment));
+}
+
+String DocumentFragment::nodeName() const
+{
+    return "#document-fragment";
+}
+
+Node::NodeType DocumentFragment::nodeType() const
+{
+    return DOCUMENT_FRAGMENT_NODE;
+}
+
+bool DocumentFragment::childTypeAllowed(NodeType type) const
+{
+    switch (type) {
+        case ELEMENT_NODE:
+        case PROCESSING_INSTRUCTION_NODE:
+        case COMMENT_NODE:
+        case TEXT_NODE:
+        case CDATA_SECTION_NODE:
+        case ENTITY_REFERENCE_NODE:
+            return true;
+        default:
+            return false;
+    }
+}
+
+PassRefPtr<Node> DocumentFragment::cloneNode(bool deep)
+{
+    RefPtr<DocumentFragment> clone = create(document());
+    if (deep)
+        cloneChildNodes(clone.get());
+    return clone.release();
+}
+
+void DocumentFragment::parseHTML(const String& source, Element* contextElement, ParserContentPolicy parserContentPolicy)
+{
+    HTMLDocumentParser::parseDocumentFragment(source, this, contextElement, parserContentPolicy);
+}
+
+bool DocumentFragment::parseXML(const String& source, Element* contextElement, ParserContentPolicy parserContentPolicy)
+{
+    return XMLDocumentParser::parseDocumentFragment(source, this, contextElement, parserContentPolicy);
+}
+
+}
diff --git a/Source/core/dom/DocumentFragment.h b/Source/core/dom/DocumentFragment.h
new file mode 100644
index 0000000..bb2fbb3
--- /dev/null
+++ b/Source/core/dom/DocumentFragment.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef DocumentFragment_h
+#define DocumentFragment_h
+
+#include "core/dom/ContainerNode.h"
+#include "core/dom/FragmentScriptingPermission.h"
+
+namespace WebCore {
+
+class DocumentFragment : public ContainerNode {
+public:
+    static PassRefPtr<DocumentFragment> create(Document*);
+
+    void parseHTML(const String&, Element* contextElement, ParserContentPolicy = AllowScriptingContent);
+    bool parseXML(const String&, Element* contextElement, ParserContentPolicy = AllowScriptingContent);
+    
+    virtual bool canContainRangeEndPoint() const { return true; }
+    virtual bool isTemplateContent() const { return false; }
+
+protected:
+    DocumentFragment(Document*, ConstructionType = CreateContainer);
+    virtual String nodeName() const;
+
+private:
+    virtual NodeType nodeType() const;
+    virtual PassRefPtr<Node> cloneNode(bool deep);
+    virtual bool childTypeAllowed(NodeType) const;
+};
+
+} //namespace
+
+#endif
diff --git a/Source/core/dom/DocumentFragment.idl b/Source/core/dom/DocumentFragment.idl
new file mode 100644
index 0000000..e8cd287
--- /dev/null
+++ b/Source/core/dom/DocumentFragment.idl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+[
+    SkipVTableValidation
+] interface DocumentFragment : Node {
+    // NodeSelector - Selector API
+    [RaisesException] Element querySelector(DOMString selectors);
+    [RaisesException] NodeList querySelectorAll(DOMString selectors);
+};
+
diff --git a/Source/core/dom/DocumentMarker.cpp b/Source/core/dom/DocumentMarker.cpp
new file mode 100644
index 0000000..aa7d4b0
--- /dev/null
+++ b/Source/core/dom/DocumentMarker.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/DocumentMarker.h"
+
+namespace WebCore {
+
+DocumentMarkerDetails::~DocumentMarkerDetails()
+{
+}
+
+class DocumentMarkerDescription : public DocumentMarkerDetails {
+public:
+    static PassRefPtr<DocumentMarkerDescription> create(const String&);
+
+    const String& description() const { return m_description; }
+    virtual bool isDescription() const { return true; }
+
+private:
+    DocumentMarkerDescription(const String& description)
+        : m_description(description)
+    {
+    }
+
+    String m_description;
+};
+
+PassRefPtr<DocumentMarkerDescription> DocumentMarkerDescription::create(const String& description)
+{
+    return adoptRef(new DocumentMarkerDescription(description));
+}
+
+inline DocumentMarkerDescription* toDocumentMarkerDescription(DocumentMarkerDetails* details)
+{
+    if (details && details->isDescription())
+        return static_cast<DocumentMarkerDescription*>(details);
+    return 0;
+}
+
+
+class DocumentMarkerTextMatch : public DocumentMarkerDetails {
+public:
+    static PassRefPtr<DocumentMarkerTextMatch> instanceFor(bool);
+
+    bool activeMatch() const { return m_match; }
+    virtual bool isTextMatch() const { return true; }
+
+private:
+    explicit DocumentMarkerTextMatch(bool match)
+        : m_match(match)
+    {
+    }
+
+    bool m_match;
+};
+
+PassRefPtr<DocumentMarkerTextMatch> DocumentMarkerTextMatch::instanceFor(bool match)
+{
+    DEFINE_STATIC_LOCAL(RefPtr<DocumentMarkerTextMatch>, trueInstance, (adoptRef(new DocumentMarkerTextMatch(true))));
+    DEFINE_STATIC_LOCAL(RefPtr<DocumentMarkerTextMatch>, falseInstance, (adoptRef(new DocumentMarkerTextMatch(false))));
+    return match ? trueInstance : falseInstance;
+}
+
+inline DocumentMarkerTextMatch* toDocumentMarkerTextMatch(DocumentMarkerDetails* details)
+{
+    if (details && details->isTextMatch())
+        return static_cast<DocumentMarkerTextMatch*>(details);
+    return 0;
+}
+
+
+DocumentMarker::DocumentMarker() 
+    : m_type(Spelling)
+    , m_startOffset(0)
+    , m_endOffset(0)
+    , m_hash(0)
+{
+}
+
+DocumentMarker::DocumentMarker(MarkerType type, unsigned startOffset, unsigned endOffset)
+    : m_type(type)
+    , m_startOffset(startOffset)
+    , m_endOffset(endOffset)
+    , m_hash(0)
+{
+}
+
+DocumentMarker::DocumentMarker(MarkerType type, unsigned startOffset, unsigned endOffset, const String& description)
+    : m_type(type)
+    , m_startOffset(startOffset)
+    , m_endOffset(endOffset)
+    , m_details(description.isEmpty() ? 0 : DocumentMarkerDescription::create(description))
+    , m_hash(0)
+{
+}
+
+DocumentMarker::DocumentMarker(MarkerType type, unsigned startOffset, unsigned endOffset, const String& description, uint32_t hash)
+    : m_type(type)
+    , m_startOffset(startOffset)
+    , m_endOffset(endOffset)
+    , m_details(description.isEmpty() ? 0 : DocumentMarkerDescription::create(description))
+    , m_hash(hash)
+{
+}
+
+DocumentMarker::DocumentMarker(unsigned startOffset, unsigned endOffset, bool activeMatch)
+    : m_type(DocumentMarker::TextMatch)
+    , m_startOffset(startOffset)
+    , m_endOffset(endOffset)
+    , m_details(DocumentMarkerTextMatch::instanceFor(activeMatch))
+    , m_hash(0)
+{
+}
+
+DocumentMarker::DocumentMarker(MarkerType type, unsigned startOffset, unsigned endOffset, PassRefPtr<DocumentMarkerDetails> details)
+    : m_type(type)
+    , m_startOffset(startOffset)
+    , m_endOffset(endOffset)
+    , m_details(details)
+    , m_hash(0)
+{
+}
+
+void DocumentMarker::shiftOffsets(int delta)
+{
+    m_startOffset += delta;
+    m_endOffset +=  delta;
+}
+
+void DocumentMarker::setActiveMatch(bool active)
+{
+    m_details = DocumentMarkerTextMatch::instanceFor(active);
+}
+
+const String& DocumentMarker::description() const
+{
+    if (DocumentMarkerDescription* details = toDocumentMarkerDescription(m_details.get()))
+        return details->description();
+    return emptyString();
+}
+
+bool DocumentMarker::activeMatch() const
+{
+    if (DocumentMarkerTextMatch* details = toDocumentMarkerTextMatch(m_details.get()))
+        return details->activeMatch();
+    return false;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/DocumentMarker.h b/Source/core/dom/DocumentMarker.h
new file mode 100644
index 0000000..ce63fa6
--- /dev/null
+++ b/Source/core/dom/DocumentMarker.h
@@ -0,0 +1,154 @@
+/*
+ * This file is part of the DOM implementation for WebCore.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef DocumentMarker_h
+#define DocumentMarker_h
+
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class DocumentMarkerDetails;
+
+// A range of a node within a document that is "marked", such as the range of a misspelled word.
+// It optionally includes a description that could be displayed in the user interface.
+// It also optionally includes a flag specifying whether the match is active, which is ignored
+// for all types other than type TextMatch.
+class DocumentMarker {
+public:
+    enum MarkerType {
+        Spelling = 1 << 0,
+        Grammar = 1 << 1,
+        TextMatch = 1 << 2,
+        // 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
+        // marker. For instance, after some text has been corrected, it will have both Replacement
+        // and CorrectionIndicator. However, if user further modifies such text, we would remove
+        // CorrectionIndicator marker, but retain Replacement marker.
+        CorrectionIndicator = 1 << 4,
+        // Correction suggestion has been offered, but got rejected by user.
+        RejectedCorrection = 1 << 5,
+        // 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,
+        // This marker indicates user has deleted an autocorrection starting at the end of the
+        // range that bears this marker. In some platforms, if the user later inserts the same original
+        // word again at this position, it will not be autocorrected again. The description of this
+        // marker is the original word before autocorrection was applied.
+        DeletedAutocorrection = 1 << 8,
+        // This marker indicates that the range of text spanned by the marker is entered by voice dictation,
+        // and it has alternative text.
+        DictationAlternatives = 1 << 9
+    };
+
+    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 | DeletedAutocorrection | DictationAlternatives)
+        {
+        }
+    };
+
+    DocumentMarker();
+    DocumentMarker(MarkerType, unsigned startOffset, unsigned endOffset);
+    DocumentMarker(MarkerType, unsigned startOffset, unsigned endOffset, const String& description);
+    DocumentMarker(MarkerType, unsigned startOffset, unsigned endOffset, const String& description, uint32_t hash);
+    DocumentMarker(unsigned startOffset, unsigned endOffset, bool activeMatch);
+    DocumentMarker(MarkerType, unsigned startOffset, unsigned endOffset, PassRefPtr<DocumentMarkerDetails>);
+
+    MarkerType type() const { return m_type; }
+    unsigned startOffset() const { return m_startOffset; }
+    unsigned endOffset() const { return m_endOffset; }
+    uint32_t hash() const { return m_hash; }
+
+    const String& description() const;
+    bool activeMatch() const;
+    DocumentMarkerDetails* details() const;
+
+    void setActiveMatch(bool);
+    void clearDetails() { m_details.clear(); }
+
+    // Offset modifications are done by DocumentMarkerController.
+    // Other classes should not call following setters.
+    void setStartOffset(unsigned offset) { m_startOffset = offset; }
+    void setEndOffset(unsigned offset) { m_endOffset = offset; }
+    void shiftOffsets(int delta);
+
+    bool operator==(const DocumentMarker& o) const
+    {
+        return type() == o.type() && startOffset() == o.startOffset() && endOffset() == o.endOffset();
+    }
+
+    bool operator!=(const DocumentMarker& o) const
+    {
+        return !(*this == o);
+    }
+
+private:
+    MarkerType m_type;
+    unsigned m_startOffset;
+    unsigned m_endOffset;
+    RefPtr<DocumentMarkerDetails> m_details;
+    uint32_t m_hash;
+};
+
+inline DocumentMarkerDetails* DocumentMarker::details() const
+{
+    return m_details.get();
+}
+
+class DocumentMarkerDetails : public RefCounted<DocumentMarkerDetails>
+{
+public:
+    DocumentMarkerDetails() { }
+    virtual ~DocumentMarkerDetails();
+    virtual bool isDescription() const { return false; }
+    virtual bool isTextMatch() const { return false; }
+};
+
+} // namespace WebCore
+
+#endif // DocumentMarker_h
diff --git a/Source/core/dom/DocumentMarkerController.cpp b/Source/core/dom/DocumentMarkerController.cpp
new file mode 100644
index 0000000..90d3a15
--- /dev/null
+++ b/Source/core/dom/DocumentMarkerController.cpp
@@ -0,0 +1,715 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/DocumentMarkerController.h"
+
+#include "core/dom/Node.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/dom/Range.h"
+#include "core/dom/RenderedDocumentMarker.h"
+#include "core/editing/TextIterator.h"
+#include "core/rendering/RenderObject.h"
+
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+namespace WebCore {
+
+inline bool DocumentMarkerController::possiblyHasMarkers(DocumentMarker::MarkerTypes types)
+{
+    return m_possiblyExistingMarkerTypes.intersects(types);
+}
+
+DocumentMarkerController::DocumentMarkerController()
+    : m_possiblyExistingMarkerTypes(0)
+{
+}
+
+void DocumentMarkerController::detach()
+{
+    m_possiblyExistingMarkerTypes = 0;
+    if (m_markers.isEmpty())
+        return;
+    deleteAllValues(m_markers);
+    m_markers.clear();
+}
+
+void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type, const String& description, uint32_t hash)
+{
+    // Use a TextIterator to visit the potentially multiple nodes the range covers.
+    for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
+        RefPtr<Range> textPiece = markedText.range();
+        addMarker(textPiece->startContainer(), DocumentMarker(type, textPiece->startOffset(), textPiece->endOffset(), description, hash));
+    }
+}
+
+void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type, const String& description)
+{
+    // Use a TextIterator to visit the potentially multiple nodes the range covers.
+    for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
+        RefPtr<Range> textPiece = markedText.range();
+        addMarker(textPiece->startContainer(), DocumentMarker(type, textPiece->startOffset(), textPiece->endOffset(), description));
+    }
+}
+
+void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type)
+{
+    // Use a TextIterator to visit the potentially multiple nodes the range covers.
+    for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
+        RefPtr<Range> textPiece = markedText.range();
+        addMarker(textPiece->startContainer(), DocumentMarker(type, textPiece->startOffset(), textPiece->endOffset()));
+    }
+
+}
+
+void DocumentMarkerController::addMarkerToNode(Node* node, unsigned startOffset, unsigned length, DocumentMarker::MarkerType type)
+{
+    addMarker(node, DocumentMarker(type, startOffset, startOffset + length));
+}
+
+void DocumentMarkerController::addMarkerToNode(Node* node, unsigned startOffset, unsigned length, DocumentMarker::MarkerType type, PassRefPtr<DocumentMarkerDetails> details)
+{
+    addMarker(node, DocumentMarker(type, startOffset, startOffset + length, details));
+}
+
+
+void DocumentMarkerController::addTextMatchMarker(const Range* range, bool activeMatch)
+{
+    // Use a TextIterator to visit the potentially multiple nodes the range covers.
+    for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
+        RefPtr<Range> textPiece = markedText.range();
+        unsigned startOffset = textPiece->startOffset();
+        unsigned endOffset = textPiece->endOffset();
+        addMarker(textPiece->startContainer(), DocumentMarker(startOffset, endOffset, activeMatch));
+        if (endOffset > startOffset) {
+            // Rendered rects for markers in WebKit are not populated until each time
+            // the markers are painted. However, we need it to happen sooner, because
+            // the whole purpose of tickmarks on the scrollbar is to show where
+            // matches off-screen are (that haven't been painted yet).
+            Node* node = textPiece->startContainer();
+            Vector<DocumentMarker*> markers = markersFor(node);
+            static_cast<RenderedDocumentMarker*>(markers[markers.size() - 1])->setRenderedRect(range->boundingBox());
+        }
+    }
+}
+
+void DocumentMarkerController::removeMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
+{
+    for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
+        if (!possiblyHasMarkers(markerTypes))
+            return;
+        ASSERT(!m_markers.isEmpty());
+
+        RefPtr<Range> textPiece = markedText.range();
+        int startOffset = textPiece->startOffset();
+        int endOffset = textPiece->endOffset();
+        removeMarkers(textPiece->startContainer(), startOffset, endOffset - startOffset, markerTypes, shouldRemovePartiallyOverlappingMarker);
+    }
+}
+
+// Markers are stored in order sorted by their start offset.
+// Markers of the same type do not overlap each other.
+
+void DocumentMarkerController::addMarker(Node* node, const DocumentMarker& newMarker) 
+{
+    ASSERT(newMarker.endOffset() >= newMarker.startOffset());
+    if (newMarker.endOffset() == newMarker.startOffset())
+        return;
+
+    m_possiblyExistingMarkerTypes.add(newMarker.type());
+
+    MarkerList* list = m_markers.get(node);
+
+    if (!list) {
+        list = new MarkerList;
+        list->append(RenderedDocumentMarker(newMarker));
+        m_markers.set(node, list);
+    } else {
+        RenderedDocumentMarker toInsert(newMarker);
+        size_t numMarkers = list->size();
+        size_t i;
+        // Iterate over all markers whose start offset is less than or equal to the new marker's.
+        // If one of them is of the same type as the new marker and touches it or intersects with it
+        // (there is at most one), remove it and adjust the new marker's start offset to encompass it.
+        for (i = 0; i < numMarkers; ++i) {
+            DocumentMarker marker = list->at(i);
+            if (marker.startOffset() > toInsert.startOffset())
+                break;
+            if (marker.type() == toInsert.type() && marker.endOffset() >= toInsert.startOffset()) {
+                toInsert.setStartOffset(marker.startOffset());
+                list->remove(i);
+                numMarkers--;
+                break;
+            }
+        }
+        size_t j = i;
+        // Iterate over all markers whose end offset is less than or equal to the new marker's,
+        // removing markers of the same type as the new marker which touch it or intersect with it,
+        // adjusting the new marker's end offset to cover them if necessary.
+        while (j < numMarkers) {
+            DocumentMarker marker = list->at(j);
+            if (marker.startOffset() > toInsert.endOffset())
+                break;
+            if (marker.type() == toInsert.type()) {
+                list->remove(j);
+                if (toInsert.endOffset() <= marker.endOffset()) {
+                    toInsert.setEndOffset(marker.endOffset());
+                    break;
+                }
+                numMarkers--;
+            } else
+                j++;
+        }
+        // At this point i points to the node before which we want to insert.
+        list->insert(i, RenderedDocumentMarker(toInsert));
+    }
+
+    // repaint the affected node
+    if (node->renderer())
+        node->renderer()->repaint();
+}
+
+// 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)
+{
+    if (length <= 0)
+        return;
+
+    if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
+        return;
+    ASSERT(!m_markers.isEmpty());
+
+    MarkerList* list = m_markers.get(srcNode);
+    if (!list)
+        return;
+
+    bool docDirty = false;
+    unsigned endOffset = startOffset + length - 1;
+    for (size_t i = 0; i != list->size(); ++i) {
+        DocumentMarker marker = list->at(i);
+
+        // stop if we are now past the specified range
+        if (marker.startOffset() > endOffset)
+            break;
+
+        // skip marker that is before the specified range or is the wrong type
+        if (marker.endOffset() < startOffset)
+            continue;
+
+        // pin the marker to the specified range and apply the shift delta
+        docDirty = true;
+        if (marker.startOffset() < startOffset)
+            marker.setStartOffset(startOffset);
+        if (marker.endOffset() > endOffset)
+            marker.setEndOffset(endOffset);
+        marker.shiftOffsets(delta);
+
+        addMarker(dstNode, marker);
+    }
+
+    // repaint the affected node
+    if (docDirty && dstNode->renderer())
+        dstNode->renderer()->repaint();
+}
+
+void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
+{
+    if (length <= 0)
+        return;
+
+    if (!possiblyHasMarkers(markerTypes))
+        return;
+    ASSERT(!(m_markers.isEmpty()));
+
+    MarkerList* list = m_markers.get(node);
+    if (!list)
+        return;
+
+    bool docDirty = false;
+    unsigned endOffset = startOffset + length;
+    for (size_t i = 0; i < list->size();) {
+        DocumentMarker marker = list->at(i);
+
+        // markers are returned in order, so stop if we are now past the specified range
+        if (marker.startOffset() >= endOffset)
+            break;
+
+        // skip marker that is wrong type or before target
+        if (marker.endOffset() <= startOffset || !markerTypes.contains(marker.type())) {
+            i++;
+            continue;
+        }
+
+        // at this point we know that marker and target intersect in some way
+        docDirty = true;
+
+        // pitch the old marker
+        list->remove(i);
+
+        if (shouldRemovePartiallyOverlappingMarker)
+            // Stop here. Don't add resulting slices back.
+            continue;
+
+        // add either of the resulting slices that are left after removing target
+        if (startOffset > marker.startOffset()) {
+            DocumentMarker newLeft = marker;
+            newLeft.setEndOffset(startOffset);
+            list->insert(i, RenderedDocumentMarker(newLeft));
+            // i now points to the newly-inserted node, but we want to skip that one
+            i++;
+        }
+        if (marker.endOffset() > endOffset) {
+            DocumentMarker newRight = marker;
+            newRight.setStartOffset(endOffset);
+            list->insert(i, RenderedDocumentMarker(newRight));
+            // i now points to the newly-inserted node, but we want to skip that one
+            i++;
+        }
+    }
+
+    if (list->isEmpty()) {
+        m_markers.remove(node);
+        delete list;
+    }
+    
+    if (m_markers.isEmpty())
+        m_possiblyExistingMarkerTypes = 0;
+
+    // repaint the affected node
+    if (docDirty && node->renderer())
+        node->renderer()->repaint();
+}
+
+DocumentMarker* DocumentMarkerController::markerContainingPoint(const LayoutPoint& point, DocumentMarker::MarkerType markerType)
+{
+    if (!possiblyHasMarkers(markerType))
+        return 0;
+    ASSERT(!(m_markers.isEmpty()));
+
+    // outer loop: process each node that contains any markers
+    MarkerMap::iterator end = m_markers.end();
+    for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
+        // inner loop; process each marker in this node
+        MarkerList* list = nodeIterator->value;
+        unsigned markerCount = list->size();
+        for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
+            RenderedDocumentMarker& marker = list->at(markerIndex);
+
+            // skip marker that is wrong type
+            if (marker.type() != markerType)
+                continue;
+
+            if (marker.contains(point))
+                return &marker;
+        }
+    }
+
+    return 0;
+}
+
+Vector<DocumentMarker*> DocumentMarkerController::markersFor(Node* node, DocumentMarker::MarkerTypes markerTypes)
+{
+    Vector<DocumentMarker*> result;
+    MarkerList* list = m_markers.get(node);
+    if (!list)
+        return result;
+
+    for (size_t i = 0; i < list->size(); ++i) {
+        if (markerTypes.contains(list->at(i).type()))
+            result.append(&(list->at(i)));
+    }
+
+    return result;
+}
+
+// FIXME: Should be removed after all relevant patches are landed
+Vector<DocumentMarker> DocumentMarkerController::markersForNode(Node* node)
+{
+    Vector<DocumentMarker> result;
+    MarkerList* list = m_markers.get(node);
+    if (!list)
+        return result;
+
+    for (size_t i = 0; i < list->size(); ++i)
+        result.append(list->at(i));
+
+    return result;
+}
+
+Vector<DocumentMarker*> DocumentMarkerController::markers()
+{
+    Vector<DocumentMarker*> result;
+    for (MarkerMap::iterator i = m_markers.begin(); i != m_markers.end(); ++i) {
+        for (size_t j = 0; j < i->value->size(); ++j)
+            result.append(&(i->value->at(j)));
+    }
+    return result;
+}
+
+Vector<DocumentMarker*> DocumentMarkerController::markersInRange(Range* range, DocumentMarker::MarkerTypes markerTypes)
+{
+    if (!possiblyHasMarkers(markerTypes))
+        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 = NodeTraversal::next(node)) {
+        Vector<DocumentMarker*> markers = markersFor(node);
+        Vector<DocumentMarker*>::const_iterator end = markers.end();
+        for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) {
+            DocumentMarker* marker = *it;
+            if (!markerTypes.contains(marker->type()))
+                continue;
+            if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset()))
+                continue;
+            if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->endOffset()))
+                continue;
+            foundMarkers.append(marker);
+        }
+    }
+    return foundMarkers;
+}
+
+Vector<IntRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker::MarkerType markerType)
+{
+    Vector<IntRect> result;
+
+    if (!possiblyHasMarkers(markerType))
+        return result;
+    ASSERT(!(m_markers.isEmpty()));
+
+    // outer loop: process each node
+    MarkerMap::iterator end = m_markers.end();
+    for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
+        // inner loop; process each marker in this node
+        MarkerList* list = nodeIterator->value;
+        unsigned markerCount = list->size();
+        for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
+            const RenderedDocumentMarker& marker = list->at(markerIndex);
+
+            // skip marker that is wrong type
+            if (marker.type() != markerType)
+                continue;
+
+            if (!marker.isRendered())
+                continue;
+
+            result.append(marker.renderedRect());
+        }
+    }
+
+    return result;
+}
+
+void DocumentMarkerController::removeMarkers(Node* node, DocumentMarker::MarkerTypes markerTypes)
+{
+    if (!possiblyHasMarkers(markerTypes))
+        return;
+    ASSERT(!m_markers.isEmpty());
+    
+    MarkerMap::iterator iterator = m_markers.find(node);
+    if (iterator != m_markers.end())
+        removeMarkersFromList(node, iterator->value, markerTypes);
+}
+
+void DocumentMarkerController::removeMarkers(DocumentMarker::MarkerTypes markerTypes)
+{
+    if (!possiblyHasMarkers(markerTypes))
+        return;
+    ASSERT(!m_markers.isEmpty());
+
+    // outer loop: process each markered node in the document
+    MarkerMap markerMapCopy = m_markers;
+    MarkerMap::iterator end = markerMapCopy.end();
+    for (MarkerMap::iterator i = markerMapCopy.begin(); i != end; ++i)
+        removeMarkersFromList(i->key.get(), i->value, markerTypes);
+    m_possiblyExistingMarkerTypes.remove(markerTypes);
+}
+
+// This function may release node and vectorPair.
+void DocumentMarkerController::removeMarkersFromList(Node* node, MarkerList* list, DocumentMarker::MarkerTypes markerTypes)
+{
+    if (markerTypes == DocumentMarker::AllMarkers()) {
+        delete list;
+        m_markers.remove(node);
+        if (RenderObject* renderer = node->renderer())
+            renderer->repaint();
+    } else {
+        bool needsRepaint = false;
+        for (size_t i = 0; i != list->size();) {
+            DocumentMarker marker = list->at(i);
+
+            // skip nodes that are not of the specified type
+            if (!markerTypes.contains(marker.type())) {
+                ++i;
+                continue;
+            }
+
+            // pitch the old marker
+            list->remove(i);
+            needsRepaint = true;
+            // i now is the index of the next marker
+        }
+
+        // Redraw the node if it changed. Do this before the node is removed from m_markers, since
+        // m_markers might contain the last reference to the node.
+        if (needsRepaint) {
+            RenderObject* renderer = node->renderer();
+            if (renderer)
+                renderer->repaint();
+        }
+
+        // delete the node's list if it is now empty
+        if (list->isEmpty()) {
+            m_markers.remove(node);
+            delete list;
+        }
+    }
+    if (m_markers.isEmpty())
+        m_possiblyExistingMarkerTypes = 0;
+}
+
+void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes markerTypes)
+{
+    if (!possiblyHasMarkers(markerTypes))
+        return;
+    ASSERT(!m_markers.isEmpty());
+
+    // outer loop: process each markered node in the document
+    MarkerMap::iterator end = m_markers.end();
+    for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
+        Node* node = i->key.get();
+
+        // inner loop: process each marker in the current node
+        MarkerList* list = i->value;
+        bool nodeNeedsRepaint = false;
+        for (size_t i = 0; i != list->size(); ++i) {
+            DocumentMarker marker = list->at(i);
+
+            // skip nodes that are not of the specified type
+            if (markerTypes.contains(marker.type())) {
+                nodeNeedsRepaint = true;
+                break;
+            }
+        }
+
+        if (!nodeNeedsRepaint)
+            continue;
+
+        // cause the node to be redrawn
+        if (RenderObject* renderer = node->renderer())
+            renderer->repaint();
+    }
+}
+
+void DocumentMarkerController::invalidateRenderedRectsForMarkersInRect(const LayoutRect& r)
+{
+    // outer loop: process each markered node in the document
+    MarkerMap::iterator end = m_markers.end();
+    for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
+
+        // inner loop: process each rect in the current node
+        MarkerList* list = i->value;
+        for (size_t listIndex = 0; listIndex < list->size(); ++listIndex)
+            list->at(listIndex).invalidate(r);
+    }
+}
+
+void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, int delta)
+{
+    if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
+        return;
+    ASSERT(!m_markers.isEmpty());
+
+    MarkerList* list = m_markers.get(node);
+    if (!list)
+        return;
+
+    bool docDirty = false;
+    for (size_t i = 0; i != list->size(); ++i) {
+        RenderedDocumentMarker& marker = list->at(i);
+        if (marker.startOffset() >= startOffset) {
+            ASSERT((int)marker.startOffset() + delta >= 0);
+            marker.shiftOffsets(delta);
+            docDirty = true;
+
+            // Marker moved, so previously-computed rendered rectangle is now invalid
+            marker.invalidate();
+        }
+    }
+
+    // repaint the affected node
+    if (docDirty && node->renderer())
+        node->renderer()->repaint();
+}
+
+void DocumentMarkerController::setMarkersActive(Range* range, bool active)
+{
+    if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
+        return;
+    ASSERT(!m_markers.isEmpty());
+
+    Node* startContainer = range->startContainer();
+    Node* endContainer = range->endContainer();
+
+    Node* pastLastNode = range->pastLastNode();
+
+    for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(node)) {
+        int startOffset = node == startContainer ? range->startOffset() : 0;
+        int endOffset = node == endContainer ? range->endOffset() : INT_MAX;
+        setMarkersActive(node, startOffset, endOffset, active);
+    }
+}
+
+void DocumentMarkerController::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active)
+{
+    MarkerList* list = m_markers.get(node);
+    if (!list)
+        return;
+
+    bool docDirty = false;
+    for (size_t i = 0; i != list->size(); ++i) {
+        DocumentMarker& marker = list->at(i);
+
+        // Markers are returned in order, so stop if we are now past the specified range.
+        if (marker.startOffset() >= endOffset)
+            break;
+
+        // Skip marker that is wrong type or before target.
+        if (marker.endOffset() < startOffset || marker.type() != DocumentMarker::TextMatch)
+            continue;
+
+        marker.setActiveMatch(active);
+        docDirty = true;
+    }
+
+    // repaint the affected node
+    if (docDirty && node->renderer())
+        node->renderer()->repaint();
+}
+
+bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes)
+{
+    if (!possiblyHasMarkers(markerTypes))
+        return false;
+    ASSERT(!m_markers.isEmpty());
+
+    Node* startContainer = range->startContainer();
+    ASSERT(startContainer);
+    Node* endContainer = range->endContainer();
+    ASSERT(endContainer);
+
+    Node* pastLastNode = range->pastLastNode();
+    for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(node)) {
+        Vector<DocumentMarker*> markers = markersFor(node);
+        Vector<DocumentMarker*>::const_iterator end = markers.end();
+        for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) {
+            DocumentMarker* marker = *it;
+            if (!markerTypes.contains(marker->type()))
+                continue;
+            if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset()))
+                continue;
+            if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->endOffset()))
+                continue;
+            return true;
+        }
+    }
+    return false;
+}
+
+void DocumentMarkerController::clearDescriptionOnMarkersIntersectingRange(Range* range, DocumentMarker::MarkerTypes markerTypes)
+{
+    if (!possiblyHasMarkers(markerTypes))
+        return;
+    ASSERT(!m_markers.isEmpty());
+
+    Node* startContainer = range->startContainer();
+    Node* endContainer = range->endContainer();
+
+    Node* pastLastNode = range->pastLastNode();
+    for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(node)) {
+        unsigned startOffset = node == startContainer ? range->startOffset() : 0;
+        unsigned endOffset = node == endContainer ? static_cast<unsigned>(range->endOffset()) : std::numeric_limits<unsigned>::max();
+        MarkerList* list = m_markers.get(node);
+        if (!list)
+            continue;
+
+        for (size_t i = 0; i < list->size(); ++i) {
+            DocumentMarker& marker = list->at(i);
+
+            // markers are returned in order, so stop if we are now past the specified range
+            if (marker.startOffset() >= endOffset)
+                break;
+
+            // skip marker that is wrong type or before target
+            if (marker.endOffset() <= startOffset || !markerTypes.contains(marker.type())) {
+                i++;
+                continue;
+            }
+
+            marker.clearDetails();
+        }
+    }
+}
+
+#ifndef NDEBUG
+void DocumentMarkerController::showMarkers() const
+{
+    fprintf(stderr, "%d nodes have markers:\n", m_markers.size());
+    MarkerMap::const_iterator end = m_markers.end();
+    for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
+        Node* node = nodeIterator->key.get();
+        fprintf(stderr, "%p", node);
+        MarkerList* list = nodeIterator->value;
+        for (unsigned markerIndex = 0; markerIndex < list->size(); ++markerIndex) {
+            const DocumentMarker& marker = list->at(markerIndex);
+            fprintf(stderr, " %d:[%d:%d](%d)", marker.type(), marker.startOffset(), marker.endOffset(), marker.activeMatch());
+        }
+
+        fprintf(stderr, "\n");
+    }
+}
+#endif
+
+} // namespace WebCore
+
+
+#ifndef NDEBUG
+void showDocumentMarkers(const WebCore::DocumentMarkerController* controller)
+{
+    if (controller)
+        controller->showMarkers();
+}
+#endif
diff --git a/Source/core/dom/DocumentMarkerController.h b/Source/core/dom/DocumentMarkerController.h
new file mode 100644
index 0000000..095c295
--- /dev/null
+++ b/Source/core/dom/DocumentMarkerController.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef DocumentMarkerController_h
+#define DocumentMarkerController_h
+
+#include "core/dom/DocumentMarker.h"
+#include "core/platform/graphics/IntRect.h"
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class LayoutPoint;
+class LayoutRect;
+class Node;
+class Range;
+class RenderedDocumentMarker;
+
+class DocumentMarkerController {
+    WTF_MAKE_NONCOPYABLE(DocumentMarkerController); WTF_MAKE_FAST_ALLOCATED;
+public:
+
+    DocumentMarkerController();
+    ~DocumentMarkerController() { detach(); }
+
+    void detach();
+    void addMarker(Range*, DocumentMarker::MarkerType);
+    void addMarker(Range*, DocumentMarker::MarkerType, const String& description);
+    void addMarker(Range*, DocumentMarker::MarkerType, const String& description, uint32_t hash);
+    void addMarkerToNode(Node*, unsigned startOffset, unsigned length, DocumentMarker::MarkerType);
+    void addMarkerToNode(Node*, unsigned startOffset, unsigned length, DocumentMarker::MarkerType, PassRefPtr<DocumentMarkerDetails>);
+    void addTextMatchMarker(const Range*, bool activeMatch);
+
+    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(DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers());
+    void removeMarkers(Node*, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers());
+    void repaintMarkers(DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers());
+    void invalidateRenderedRectsForMarkersInRect(const LayoutRect&);
+    void shiftMarkers(Node*, unsigned startOffset, int delta);
+    void setMarkersActive(Range*, bool);
+    void setMarkersActive(Node*, unsigned startOffset, unsigned endOffset, bool);
+
+    DocumentMarker* markerContainingPoint(const LayoutPoint&, DocumentMarker::MarkerType);
+    Vector<DocumentMarker*> markersFor(Node*, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers());
+    Vector<DocumentMarker*> markersInRange(Range*, DocumentMarker::MarkerTypes);
+    Vector<DocumentMarker> markersForNode(Node*);
+    Vector<DocumentMarker*> markers();
+    Vector<IntRect> renderedRectsForMarkers(DocumentMarker::MarkerType);
+    void clearDescriptionOnMarkersIntersectingRange(Range*, DocumentMarker::MarkerTypes);
+
+#ifndef NDEBUG
+    void showMarkers() const;
+#endif
+
+private:
+    void addMarker(Node*, const DocumentMarker&);
+
+    typedef Vector<RenderedDocumentMarker> MarkerList;
+    typedef HashMap<RefPtr<Node>, MarkerList*> MarkerMap;
+    bool possiblyHasMarkers(DocumentMarker::MarkerTypes);
+    void removeMarkersFromList(Node*, MarkerList*, DocumentMarker::MarkerTypes);
+
+    MarkerMap m_markers;
+    // Provide a quick way to determine whether a particular marker type is absent without going through the map.
+    DocumentMarker::MarkerTypes m_possiblyExistingMarkerTypes;
+};
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+void showDocumentMarkers(const WebCore::DocumentMarkerController*);
+#endif
+
+#endif // DocumentMarkerController_h
diff --git a/Source/core/dom/DocumentOrderedMap.cpp b/Source/core/dom/DocumentOrderedMap.cpp
new file mode 100644
index 0000000..5c41c8d
--- /dev/null
+++ b/Source/core/dom/DocumentOrderedMap.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/DocumentOrderedMap.h"
+
+#include "HTMLNames.h"
+#include "core/dom/Element.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/dom/TreeScope.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/html/HTMLMapElement.h"
+#include <wtf/MemoryInstrumentationHashCountedSet.h>
+#include <wtf/MemoryInstrumentationHashMap.h>
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+inline bool keyMatchesId(AtomicStringImpl* key, Element* element)
+{
+    return element->getIdAttribute().impl() == key;
+}
+
+inline bool keyMatchesMapName(AtomicStringImpl* key, Element* element)
+{
+    return element->hasTagName(mapTag) && static_cast<HTMLMapElement*>(element)->getName().impl() == key;
+}
+
+inline bool keyMatchesLowercasedMapName(AtomicStringImpl* key, Element* element)
+{
+    return element->hasTagName(mapTag) && static_cast<HTMLMapElement*>(element)->getName().lower().impl() == key;
+}
+
+inline bool keyMatchesLabelForAttribute(AtomicStringImpl* key, Element* element)
+{
+    return element->hasTagName(labelTag) && element->getAttribute(forAttr).impl() == key;
+}
+
+void DocumentOrderedMap::clear()
+{
+    m_map.clear();
+    m_duplicateCounts.clear();
+}
+
+void DocumentOrderedMap::add(AtomicStringImpl* key, Element* element)
+{
+    ASSERT(key);
+    ASSERT(element);
+
+    if (!m_duplicateCounts.contains(key)) {
+        // Fast path. The key is not already in m_duplicateCounts, so we assume that it's
+        // also not already in m_map and try to add it. If that add succeeds, we're done.
+        Map::AddResult addResult = m_map.add(key, element);
+        if (addResult.isNewEntry)
+            return;
+
+        // The add failed, so this key was already cached in m_map.
+        // There are multiple elements with this key. Remove the m_map
+        // cache for this key so get searches for it next time it is called.
+        m_map.remove(addResult.iterator);
+        m_duplicateCounts.add(key);
+    } else {
+        // There are multiple elements with this key. Remove the m_map
+        // cache for this key so get will search for it next time it is called.
+        Map::iterator cachedItem = m_map.find(key);
+        if (cachedItem != m_map.end()) {
+            m_map.remove(cachedItem);
+            m_duplicateCounts.add(key);
+        }
+    }
+
+    m_duplicateCounts.add(key);
+}
+
+void DocumentOrderedMap::remove(AtomicStringImpl* key, Element* element)
+{
+    ASSERT(key);
+    ASSERT(element);
+
+    m_map.checkConsistency();
+    Map::iterator cachedItem = m_map.find(key);
+    if (cachedItem != m_map.end() && cachedItem->value == element)
+        m_map.remove(cachedItem);
+    else
+        m_duplicateCounts.remove(key);
+}
+
+template<bool keyMatches(AtomicStringImpl*, Element*)>
+inline Element* DocumentOrderedMap::get(AtomicStringImpl* key, const TreeScope* scope) const
+{
+    ASSERT(key);
+    ASSERT(scope);
+
+    m_map.checkConsistency();
+
+    Element* element = m_map.get(key);
+    if (element)
+        return element;
+
+    if (m_duplicateCounts.contains(key)) {
+        // We know there's at least one node that matches; iterate to find the first one.
+        for (element = ElementTraversal::firstWithin(scope->rootNode()); element; element = ElementTraversal::next(element)) {
+            if (!keyMatches(key, element))
+                continue;
+            m_duplicateCounts.remove(key);
+            m_map.set(key, element);
+            return element;
+        }
+        ASSERT_NOT_REACHED();
+    }
+
+    return 0;
+}
+
+Element* DocumentOrderedMap::getElementById(AtomicStringImpl* key, const TreeScope* scope) const
+{
+    return get<keyMatchesId>(key, scope);
+}
+
+Element* DocumentOrderedMap::getElementByMapName(AtomicStringImpl* key, const TreeScope* scope) const
+{
+    return get<keyMatchesMapName>(key, scope);
+}
+
+Element* DocumentOrderedMap::getElementByLowercasedMapName(AtomicStringImpl* key, const TreeScope* scope) const
+{
+    return get<keyMatchesLowercasedMapName>(key, scope);
+}
+
+Element* DocumentOrderedMap::getElementByLabelForAttribute(AtomicStringImpl* key, const TreeScope* scope) const
+{
+    return get<keyMatchesLabelForAttribute>(key, scope);
+}
+
+void DocumentOrderedMap::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    info.addMember(m_map, "map");
+    info.addMember(m_duplicateCounts, "duplicateCounts");
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/DocumentOrderedMap.h b/Source/core/dom/DocumentOrderedMap.h
new file mode 100644
index 0000000..f7deb3b
--- /dev/null
+++ b/Source/core/dom/DocumentOrderedMap.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DocumentOrderedMap_h
+#define DocumentOrderedMap_h
+
+#include <wtf/HashCountedSet.h>
+#include <wtf/HashMap.h>
+#include <wtf/text/AtomicStringImpl.h>
+
+namespace WebCore {
+
+class Element;
+class TreeScope;
+
+class DocumentOrderedMap {
+public:
+    void add(AtomicStringImpl*, Element*);
+    void remove(AtomicStringImpl*, Element*);
+    void clear();
+
+    bool contains(AtomicStringImpl*) const;
+    bool containsMultiple(AtomicStringImpl*) const;
+    // concrete instantiations of the get<>() method template
+    Element* getElementById(AtomicStringImpl*, const TreeScope*) const;
+    Element* getElementByMapName(AtomicStringImpl*, const TreeScope*) const;
+    Element* getElementByLowercasedMapName(AtomicStringImpl*, const TreeScope*) const;
+    Element* getElementByLabelForAttribute(AtomicStringImpl*, const TreeScope*) const;
+
+    void checkConsistency() const;
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+private:
+    template<bool keyMatches(AtomicStringImpl*, Element*)> Element* get(AtomicStringImpl*, const TreeScope*) const;
+
+    typedef HashMap<AtomicStringImpl*, Element*> Map;
+
+    // We maintain the invariant that m_duplicateCounts is the count of all elements with a given key
+    // excluding the one referenced in m_map, if any. This means it one less than the total count
+    // when the first node with a given key is cached, otherwise the same as the total count.
+    mutable Map m_map;
+    mutable HashCountedSet<AtomicStringImpl*> m_duplicateCounts;
+};
+
+inline bool DocumentOrderedMap::contains(AtomicStringImpl* id) const
+{
+    return m_map.contains(id) || m_duplicateCounts.contains(id);
+}
+
+inline bool DocumentOrderedMap::containsMultiple(AtomicStringImpl* id) const
+{
+    return m_duplicateCounts.contains(id);
+}
+
+} // namespace WebCore
+
+#endif // DocumentOrderedMap_h
diff --git a/Source/core/dom/DocumentParser.cpp b/Source/core/dom/DocumentParser.cpp
new file mode 100644
index 0000000..9a834eb
--- /dev/null
+++ b/Source/core/dom/DocumentParser.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 "core/dom/DocumentParser.h"
+
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+DocumentParser::DocumentParser(Document* document)
+    : m_state(ParsingState)
+    , m_documentWasLoadedAsPartOfNavigation(false)
+    , m_document(document)
+{
+    ASSERT(document);
+}
+
+DocumentParser::~DocumentParser()
+{
+    // Document is expected to call detach() before releasing its ref.
+    // This ASSERT is slightly awkward for parsers with a fragment case
+    // as there is no Document to release the ref.
+    ASSERT(!m_document);
+}
+
+void DocumentParser::startParsing()
+{
+    m_state = ParsingState;
+}
+
+void DocumentParser::prepareToStopParsing()
+{
+    ASSERT(m_state == ParsingState);
+    m_state = StoppingState;
+}
+
+void DocumentParser::stopParsing()
+{
+    m_state = StoppedState;
+}
+
+void DocumentParser::detach()
+{
+    m_state = DetachedState;
+    m_document = 0;
+}
+
+void DocumentParser::suspendScheduledTasks()
+{
+}
+
+void DocumentParser::resumeScheduledTasks()
+{
+}
+
+};
+
diff --git a/Source/core/dom/DocumentParser.h b/Source/core/dom/DocumentParser.h
new file mode 100644
index 0000000..f65d369
--- /dev/null
+++ b/Source/core/dom/DocumentParser.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2000 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef DocumentParser_h
+#define DocumentParser_h
+
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class Document;
+class DocumentWriter;
+class SegmentedString;
+class ScriptableDocumentParser;
+
+class DocumentParser : public RefCounted<DocumentParser> {
+public:
+    virtual ~DocumentParser();
+
+    virtual ScriptableDocumentParser* asScriptableDocumentParser() { return 0; }
+
+    // http://www.whatwg.org/specs/web-apps/current-work/#insertion-point
+    virtual bool hasInsertionPoint() { return true; }
+
+    // insert is used by document.write.
+    virtual void insert(const SegmentedString&) = 0;
+
+    // appendBytes and flush are used by DocumentWriter (the loader).
+    virtual void appendBytes(DocumentWriter*, const char* bytes, size_t length) = 0;
+    virtual void flush(DocumentWriter*) = 0;
+
+    virtual void pinToMainThread() { }
+
+    // FIXME: append() should be private, but DocumentWriter::replaceDocument uses it for now.
+    // FIXME: This really should take a PassOwnPtr to signify that it expects to take
+    // ownership of the buffer. The parser expects the PassRefPtr to hold the only ref of the StringImpl.
+    virtual void append(PassRefPtr<StringImpl>) = 0;
+
+    virtual void finish() = 0;
+
+    // FIXME: processingData() is only used by DocumentLoader::isLoadingInAPISense
+    // and is very unclear as to what it actually means.  The LegacyHTMLDocumentParser
+    // used to implement it.
+    virtual bool processingData() const { return false; }
+
+    // document() will return 0 after detach() is called.
+    Document* document() const { ASSERT(m_document); return m_document; }
+
+    bool isParsing() const { return m_state == ParsingState; }
+    bool isStopping() const { return m_state == StoppingState; }
+    bool isStopped() const { return m_state >= StoppedState; }
+    bool isDetached() const { return m_state == DetachedState; }
+
+    // FIXME: Is this necessary? Does XMLDocumentParserLibxml2 really need to set this?
+    virtual void startParsing();
+
+    // prepareToStop() is used when the EOF token is encountered and parsing is to be
+    // stopped normally.
+    virtual void prepareToStopParsing();
+
+    // stopParsing() is used when a load is canceled/stopped.
+    // stopParsing() is currently different from detach(), but shouldn't be.
+    // It should NOT be ok to call any methods on DocumentParser after either
+    // detach() or stopParsing() but right now only detach() will ASSERT.
+    virtual void stopParsing();
+
+    // Document is expected to detach the parser before releasing its ref.
+    // After detach, m_document is cleared.  The parser will unwind its
+    // callstacks, but not produce any more nodes.
+    // It is impossible for the parser to touch the rest of WebCore after
+    // detach is called.
+    virtual void detach();
+
+    void setDocumentWasLoadedAsPartOfNavigation() { m_documentWasLoadedAsPartOfNavigation = true; }
+    bool documentWasLoadedAsPartOfNavigation() const { return m_documentWasLoadedAsPartOfNavigation; }
+
+    // FIXME: The names are not very accurate :(
+    virtual void suspendScheduledTasks();
+    virtual void resumeScheduledTasks();
+
+protected:
+    explicit DocumentParser(Document*);
+
+private:
+    enum ParserState {
+        ParsingState,
+        StoppingState,
+        StoppedState,
+        DetachedState
+    };
+    ParserState m_state;
+    bool m_documentWasLoadedAsPartOfNavigation;
+
+    // Every DocumentParser needs a pointer back to the document.
+    // m_document will be 0 after the parser is stopped.
+    Document* m_document;
+};
+
+} // namespace WebCore
+
+#endif // DocumentParser_h
diff --git a/Source/core/dom/DocumentSharedObjectPool.cpp b/Source/core/dom/DocumentSharedObjectPool.cpp
new file mode 100644
index 0000000..985f04c
--- /dev/null
+++ b/Source/core/dom/DocumentSharedObjectPool.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2012, 2013 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/DocumentSharedObjectPool.h"
+
+#include "core/dom/Element.h"
+
+namespace WebCore {
+
+class ShareableElementDataCacheKey {
+public:
+    ShareableElementDataCacheKey(const Attribute* attributes, unsigned attributeCount)
+        : m_attributes(attributes)
+        , m_attributeCount(attributeCount)
+    { }
+
+    bool operator!=(const ShareableElementDataCacheKey& other) const
+    {
+        if (m_attributeCount != other.m_attributeCount)
+            return true;
+        return memcmp(m_attributes, other.m_attributes, sizeof(Attribute) * m_attributeCount);
+    }
+
+    unsigned hash() const
+    {
+        return StringHasher::hashMemory(m_attributes, m_attributeCount * sizeof(Attribute));
+    }
+
+private:
+    const Attribute* m_attributes;
+    unsigned m_attributeCount;
+};
+
+class ShareableElementDataCacheEntry {
+public:
+    ShareableElementDataCacheEntry(const ShareableElementDataCacheKey& k, PassRefPtr<ShareableElementData> v)
+        : key(k)
+        , value(v)
+    { }
+
+    ShareableElementDataCacheKey key;
+    RefPtr<ShareableElementData> value;
+};
+
+PassRefPtr<ShareableElementData> DocumentSharedObjectPool::cachedShareableElementDataWithAttributes(const Vector<Attribute>& attributes)
+{
+    ASSERT(!attributes.isEmpty());
+
+    ShareableElementDataCacheKey cacheKey(attributes.data(), attributes.size());
+    unsigned cacheHash = cacheKey.hash();
+
+    ShareableElementDataCache::iterator cacheIterator = m_shareableElementDataCache.add(cacheHash, nullptr).iterator;
+    if (cacheIterator->value && cacheIterator->value->key != cacheKey)
+        cacheHash = 0;
+
+    RefPtr<ShareableElementData> elementData;
+    if (cacheHash && cacheIterator->value)
+        elementData = cacheIterator->value->value;
+    else
+        elementData = ShareableElementData::createWithAttributes(attributes);
+
+    if (!cacheHash || cacheIterator->value)
+        return elementData.release();
+
+    cacheIterator->value = adoptPtr(new ShareableElementDataCacheEntry(ShareableElementDataCacheKey(elementData->m_attributeArray, elementData->length()), elementData));
+
+    return elementData.release();
+}
+
+DocumentSharedObjectPool::DocumentSharedObjectPool()
+{
+}
+
+DocumentSharedObjectPool::~DocumentSharedObjectPool()
+{
+}
+
+}
diff --git a/Source/core/dom/DocumentSharedObjectPool.h b/Source/core/dom/DocumentSharedObjectPool.h
new file mode 100644
index 0000000..a3b24d7
--- /dev/null
+++ b/Source/core/dom/DocumentSharedObjectPool.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012, 2013 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef DocumentSharedObjectPool_h
+#define DocumentSharedObjectPool_h
+
+#include <wtf/HashMap.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+class Attribute;
+class ShareableElementData;
+class ShareableElementDataCacheEntry;
+
+class DocumentSharedObjectPool {
+public:
+    static PassOwnPtr<DocumentSharedObjectPool> create() { return adoptPtr(new DocumentSharedObjectPool); }
+    ~DocumentSharedObjectPool();
+
+    PassRefPtr<ShareableElementData> cachedShareableElementDataWithAttributes(const Vector<Attribute>&);
+
+private:
+    DocumentSharedObjectPool();
+
+    typedef HashMap<unsigned, OwnPtr<ShareableElementDataCacheEntry>, AlreadyHashed> ShareableElementDataCache;
+    ShareableElementDataCache m_shareableElementDataCache;
+};
+
+}
+
+#endif
diff --git a/Source/core/dom/DocumentStyleSheetCollection.cpp b/Source/core/dom/DocumentStyleSheetCollection.cpp
new file mode 100644
index 0000000..7f7bfd3
--- /dev/null
+++ b/Source/core/dom/DocumentStyleSheetCollection.cpp
@@ -0,0 +1,509 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/DocumentStyleSheetCollection.h"
+
+#include "HTMLNames.h"
+#include "SVGNames.h"
+#include "bindings/v8/DOMWrapperWorld.h"
+#include "core/css/CSSStyleSheet.h"
+#include "core/css/SelectorChecker.h"
+#include "core/css/StyleInvalidationAnalysis.h"
+#include "core/css/StyleResolver.h"
+#include "core/css/StyleSheetContents.h"
+#include "core/css/StyleSheetList.h"
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/ProcessingInstruction.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/html/HTMLIFrameElement.h"
+#include "core/html/HTMLLinkElement.h"
+#include "core/html/HTMLStyleElement.h"
+#include "core/page/Page.h"
+#include "core/page/PageGroup.h"
+#include "core/page/Settings.h"
+#include "core/page/UserContentURLPattern.h"
+#include "core/svg/SVGStyleElement.h"
+#include <wtf/MemoryInstrumentationListHashSet.h>
+#include <wtf/MemoryInstrumentationVector.h>
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+DocumentStyleSheetCollection::DocumentStyleSheetCollection(Document* document)
+    : m_document(document)
+    , m_pendingStylesheets(0)
+    , m_injectedStyleSheetCacheValid(false)
+    , m_hadActiveLoadingStylesheet(false)
+    , m_needsUpdateActiveStylesheetsOnStyleRecalc(false)
+    , m_usesSiblingRules(false)
+    , m_usesSiblingRulesOverride(false)
+    , m_usesFirstLineRules(false)
+    , m_usesFirstLetterRules(false)
+    , m_usesBeforeAfterRules(false)
+    , m_usesBeforeAfterRulesOverride(false)
+    , m_usesRemUnits(false)
+{
+}
+
+DocumentStyleSheetCollection::~DocumentStyleSheetCollection()
+{
+    if (m_pageUserSheet)
+        m_pageUserSheet->clearOwnerNode();
+    for (unsigned i = 0; i < m_injectedUserStyleSheets.size(); ++i)
+        m_injectedUserStyleSheets[i]->clearOwnerNode();
+    for (unsigned i = 0; i < m_injectedAuthorStyleSheets.size(); ++i)
+        m_injectedAuthorStyleSheets[i]->clearOwnerNode();
+    for (unsigned i = 0; i < m_userStyleSheets.size(); ++i)
+        m_userStyleSheets[i]->clearOwnerNode();
+    for (unsigned i = 0; i < m_authorStyleSheets.size(); ++i)
+        m_authorStyleSheets[i]->clearOwnerNode();
+}
+
+void DocumentStyleSheetCollection::combineCSSFeatureFlags()
+{
+    // Delay resetting the flags until after next style recalc since unapplying the style may not work without these set (this is true at least with before/after).
+    StyleResolver* styleResolver = m_document->styleResolver();
+    m_usesSiblingRules = m_usesSiblingRules || styleResolver->usesSiblingRules();
+    m_usesFirstLineRules = m_usesFirstLineRules || styleResolver->usesFirstLineRules();
+    m_usesBeforeAfterRules = m_usesBeforeAfterRules || styleResolver->usesBeforeAfterRules();
+}
+
+void DocumentStyleSheetCollection::resetCSSFeatureFlags()
+{
+    StyleResolver* styleResolver = m_document->styleResolver();
+    m_usesSiblingRules = styleResolver->usesSiblingRules();
+    m_usesFirstLineRules = styleResolver->usesFirstLineRules();
+    m_usesBeforeAfterRules = styleResolver->usesBeforeAfterRules();
+}
+
+CSSStyleSheet* DocumentStyleSheetCollection::pageUserSheet()
+{
+    if (m_pageUserSheet)
+        return m_pageUserSheet.get();
+    
+    Page* owningPage = m_document->page();
+    if (!owningPage)
+        return 0;
+    
+    String userSheetText = owningPage->userStyleSheet();
+    if (userSheetText.isEmpty())
+        return 0;
+    
+    // Parse the sheet and cache it.
+    m_pageUserSheet = CSSStyleSheet::createInline(m_document, m_document->settings()->userStyleSheetLocation());
+    m_pageUserSheet->contents()->setIsUserStyleSheet(true);
+    m_pageUserSheet->contents()->parseString(userSheetText);
+    return m_pageUserSheet.get();
+}
+
+void DocumentStyleSheetCollection::clearPageUserSheet()
+{
+    if (m_pageUserSheet) {
+        m_pageUserSheet = 0;
+        m_document->styleResolverChanged(DeferRecalcStyle);
+    }
+}
+
+void DocumentStyleSheetCollection::updatePageUserSheet()
+{
+    clearPageUserSheet();
+    if (pageUserSheet())
+        m_document->styleResolverChanged(RecalcStyleImmediately);
+}
+
+const Vector<RefPtr<CSSStyleSheet> >& DocumentStyleSheetCollection::injectedUserStyleSheets() const
+{
+    updateInjectedStyleSheetCache();
+    return m_injectedUserStyleSheets;
+}
+
+const Vector<RefPtr<CSSStyleSheet> >& DocumentStyleSheetCollection::injectedAuthorStyleSheets() const
+{
+    updateInjectedStyleSheetCache();
+    return m_injectedAuthorStyleSheets;
+}
+
+void DocumentStyleSheetCollection::updateInjectedStyleSheetCache() const
+{
+    if (m_injectedStyleSheetCacheValid)
+        return;
+    m_injectedStyleSheetCacheValid = true;
+    m_injectedUserStyleSheets.clear();
+    m_injectedAuthorStyleSheets.clear();
+
+    Page* owningPage = m_document->page();
+    if (!owningPage)
+        return;
+
+    const PageGroup& pageGroup = owningPage->group();
+    const UserStyleSheetVector& sheets = pageGroup.userStyleSheets();
+    for (unsigned i = 0; i < sheets.size(); ++i) {
+        const UserStyleSheet* sheet = sheets[i].get();
+        if (sheet->injectedFrames() == InjectInTopFrameOnly && m_document->ownerElement())
+            continue;
+        if (!UserContentURLPattern::matchesPatterns(m_document->url(), sheet->whitelist(), sheet->blacklist()))
+            continue;
+        RefPtr<CSSStyleSheet> groupSheet = CSSStyleSheet::createInline(const_cast<Document*>(m_document), sheet->url());
+        bool isUserStyleSheet = sheet->level() == UserStyleUserLevel;
+        if (isUserStyleSheet)
+            m_injectedUserStyleSheets.append(groupSheet);
+        else
+            m_injectedAuthorStyleSheets.append(groupSheet);
+        groupSheet->contents()->setIsUserStyleSheet(isUserStyleSheet);
+        groupSheet->contents()->parseString(sheet->source());
+    }
+}
+
+void DocumentStyleSheetCollection::invalidateInjectedStyleSheetCache()
+{
+    m_injectedStyleSheetCacheValid = false;
+    m_document->styleResolverChanged(DeferRecalcStyle);
+}
+
+void DocumentStyleSheetCollection::addAuthorSheet(PassRefPtr<StyleSheetContents> authorSheet)
+{
+    ASSERT(!authorSheet->isUserStyleSheet());
+    m_authorStyleSheets.append(CSSStyleSheet::create(authorSheet, m_document));
+    m_document->styleResolverChanged(RecalcStyleImmediately);
+}
+
+void DocumentStyleSheetCollection::addUserSheet(PassRefPtr<StyleSheetContents> userSheet)
+{
+    ASSERT(userSheet->isUserStyleSheet());
+    m_userStyleSheets.append(CSSStyleSheet::create(userSheet, m_document));
+    m_document->styleResolverChanged(RecalcStyleImmediately);
+}
+
+// This method is called whenever a top-level stylesheet has finished loading.
+void DocumentStyleSheetCollection::removePendingSheet(RemovePendingSheetNotificationType notification)
+{
+    // Make sure we knew this sheet was pending, and that our count isn't out of sync.
+    ASSERT(m_pendingStylesheets > 0);
+
+    m_pendingStylesheets--;
+    
+#ifdef INSTRUMENT_LAYOUT_SCHEDULING
+    if (!ownerElement())
+        printf("Stylesheet loaded at time %d. %d stylesheets still remain.\n", elapsedTime(), m_pendingStylesheets);
+#endif
+
+    if (m_pendingStylesheets)
+        return;
+
+    if (notification == RemovePendingSheetNotifyLater) {
+        m_document->setNeedsNotifyRemoveAllPendingStylesheet();
+        return;
+    }
+    
+    m_document->didRemoveAllPendingStylesheet();
+}
+
+void DocumentStyleSheetCollection::addStyleSheetCandidateNode(Node* node, bool createdByParser)
+{
+    if (!node->inDocument())
+        return;
+    
+    // Until the <body> exists, we have no choice but to compare document positions,
+    // since styles outside of the body and head continue to be shunted into the head
+    // (and thus can shift to end up before dynamically added DOM content that is also
+    // outside the body).
+    if ((createdByParser && m_document->body()) || m_styleSheetCandidateNodes.isEmpty()) {
+        m_styleSheetCandidateNodes.add(node);
+        return;
+    }
+
+    // Determine an appropriate insertion point.
+    StyleSheetCandidateListHashSet::iterator begin = m_styleSheetCandidateNodes.begin();
+    StyleSheetCandidateListHashSet::iterator end = m_styleSheetCandidateNodes.end();
+    StyleSheetCandidateListHashSet::iterator it = end;
+    Node* followingNode = 0;
+    do {
+        --it;
+        Node* n = *it;
+        unsigned short position = n->compareDocumentPositionInternal(node, Node::TreatShadowTreesAsComposed);
+        if (position & Node::DOCUMENT_POSITION_FOLLOWING) {
+            m_styleSheetCandidateNodes.insertBefore(followingNode, node);
+            return;
+        }
+        followingNode = n;
+    } while (it != begin);
+    
+    m_styleSheetCandidateNodes.insertBefore(followingNode, node);
+}
+
+void DocumentStyleSheetCollection::removeStyleSheetCandidateNode(Node* node)
+{
+    m_styleSheetCandidateNodes.remove(node);
+}
+
+void DocumentStyleSheetCollection::collectActiveStyleSheets(Vector<RefPtr<StyleSheet> >& sheets)
+{
+    if (m_document->settings() && !m_document->settings()->authorAndUserStylesEnabled())
+        return;
+
+    StyleSheetCandidateListHashSet::iterator begin = m_styleSheetCandidateNodes.begin();
+    StyleSheetCandidateListHashSet::iterator end = m_styleSheetCandidateNodes.end();
+    for (StyleSheetCandidateListHashSet::iterator it = begin; it != end; ++it) {
+        Node* n = *it;
+        StyleSheet* sheet = 0;
+        if (n->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
+            // Processing instruction (XML documents only).
+            // We don't support linking to embedded CSS stylesheets, see <https://bugs.webkit.org/show_bug.cgi?id=49281> for discussion.
+            ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(n);
+            sheet = pi->sheet();
+            // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806>
+            if (pi->isXSL() && !m_document->transformSourceDocument()) {
+                // Don't apply XSL transforms until loading is finished.
+                if (!m_document->parsing())
+                    m_document->applyXSLTransform(pi);
+                return;
+            }
+        } else if ((n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag)))
+#if ENABLE(SVG)
+                   ||  (n->isSVGElement() && n->hasTagName(SVGNames::styleTag))
+#endif
+                   ) {
+            Element* e = toElement(n);
+            AtomicString title = e->getAttribute(titleAttr);
+            bool enabledViaScript = false;
+            if (e->hasLocalName(linkTag)) {
+                // <LINK> element
+                HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(n);
+                if (linkElement->isDisabled())
+                    continue;
+                enabledViaScript = linkElement->isEnabledViaScript();
+                if (linkElement->styleSheetIsLoading()) {
+                    // it is loading but we should still decide which style sheet set to use
+                    if (!enabledViaScript && !title.isEmpty() && m_preferredStylesheetSetName.isEmpty()) {
+                        const AtomicString& rel = e->getAttribute(relAttr);
+                        if (!rel.contains("alternate")) {
+                            m_preferredStylesheetSetName = title;
+                            m_selectedStylesheetSetName = title;
+                        }
+                    }
+                    continue;
+                }
+                if (!linkElement->sheet())
+                    title = nullAtom;
+            }
+            // Get the current preferred styleset. This is the
+            // set of sheets that will be enabled.
+#if ENABLE(SVG)
+            if (n->isSVGElement() && n->hasTagName(SVGNames::styleTag))
+                sheet = static_cast<SVGStyleElement*>(n)->sheet();
+            else
+#endif
+            if (e->hasLocalName(linkTag))
+                sheet = static_cast<HTMLLinkElement*>(n)->sheet();
+            else
+                // <STYLE> element
+                sheet = static_cast<HTMLStyleElement*>(n)->sheet();
+            // Check to see if this sheet belongs to a styleset
+            // (thus making it PREFERRED or ALTERNATE rather than
+            // PERSISTENT).
+            AtomicString rel = e->getAttribute(relAttr);
+            if (!enabledViaScript && !title.isEmpty()) {
+                // Yes, we have a title.
+                if (m_preferredStylesheetSetName.isEmpty()) {
+                    // No preferred set has been established. If
+                    // we are NOT an alternate sheet, then establish
+                    // us as the preferred set. Otherwise, just ignore
+                    // this sheet.
+                    if (e->hasLocalName(styleTag) || !rel.contains("alternate"))
+                        m_preferredStylesheetSetName = m_selectedStylesheetSetName = title;
+                }
+                if (title != m_preferredStylesheetSetName)
+                    sheet = 0;
+            }
+
+            if (rel.contains("alternate") && title.isEmpty())
+                sheet = 0;
+        }
+        if (sheet)
+            sheets.append(sheet);
+    }
+}
+
+void DocumentStyleSheetCollection::analyzeStyleSheetChange(UpdateFlag updateFlag, const Vector<RefPtr<CSSStyleSheet> >& newStylesheets, StyleResolverUpdateType& styleResolverUpdateType, bool& requiresFullStyleRecalc)
+{
+    styleResolverUpdateType = Reconstruct;
+    requiresFullStyleRecalc = true;
+    
+    // Stylesheets of <style> elements that @import stylesheets are active but loading. We need to trigger a full recalc when such loads are done.
+    bool hasActiveLoadingStylesheet = false;
+    unsigned newStylesheetCount = newStylesheets.size();
+    for (unsigned i = 0; i < newStylesheetCount; ++i) {
+        if (newStylesheets[i]->isLoading())
+            hasActiveLoadingStylesheet = true;
+    }
+    if (m_hadActiveLoadingStylesheet && !hasActiveLoadingStylesheet) {
+        m_hadActiveLoadingStylesheet = false;
+        return;
+    }
+    m_hadActiveLoadingStylesheet = hasActiveLoadingStylesheet;
+
+    if (updateFlag != OptimizedUpdate)
+        return;
+    if (!m_document->styleResolverIfExists())
+        return;
+
+    // Find out which stylesheets are new.
+    unsigned oldStylesheetCount = m_activeAuthorStyleSheets.size();
+    if (newStylesheetCount < oldStylesheetCount)
+        return;
+    Vector<StyleSheetContents*> addedSheets;
+    unsigned newIndex = 0;
+    for (unsigned oldIndex = 0; oldIndex < oldStylesheetCount; ++oldIndex) {
+        if (newIndex >= newStylesheetCount)
+            return;
+        while (m_activeAuthorStyleSheets[oldIndex] != newStylesheets[newIndex]) {
+            addedSheets.append(newStylesheets[newIndex]->contents());
+            ++newIndex;
+            if (newIndex == newStylesheetCount)
+                return;
+        }
+        ++newIndex;
+    }
+    bool hasInsertions = !addedSheets.isEmpty();
+    while (newIndex < newStylesheetCount) {
+        addedSheets.append(newStylesheets[newIndex]->contents());
+        ++newIndex;
+    }
+    // If all new sheets were added at the end of the list we can just add them to existing StyleResolver.
+    // If there were insertions we need to re-add all the stylesheets so rules are ordered correctly.
+    styleResolverUpdateType = hasInsertions ? Reset : Additive;
+
+    // If we are already parsing the body and so may have significant amount of elements, put some effort into trying to avoid style recalcs.
+    if (!m_document->body() || m_document->hasNodesWithPlaceholderStyle())
+        return;
+    StyleInvalidationAnalysis invalidationAnalysis(addedSheets);
+    if (invalidationAnalysis.dirtiesAllStyle())
+        return;
+    invalidationAnalysis.invalidateStyle(m_document);
+    requiresFullStyleRecalc = false;
+}
+
+static bool styleSheetsUseRemUnits(const Vector<RefPtr<CSSStyleSheet> >& sheets)
+{
+    for (unsigned i = 0; i < sheets.size(); ++i) {
+        if (sheets[i]->contents()->usesRemUnits())
+            return true;
+    }
+    return false;
+}
+
+static void filterEnabledCSSStyleSheets(Vector<RefPtr<CSSStyleSheet> >& result, const Vector<RefPtr<StyleSheet> >& sheets)
+{
+    for (unsigned i = 0; i < sheets.size(); ++i) {
+        if (!sheets[i]->isCSSStyleSheet())
+            continue;
+        if (sheets[i]->disabled())
+            continue;
+        result.append(static_cast<CSSStyleSheet*>(sheets[i].get()));
+    }
+}
+
+static void collectActiveCSSStyleSheetsFromSeamlessParents(Vector<RefPtr<CSSStyleSheet> >& sheets, Document* document)
+{
+    HTMLIFrameElement* seamlessParentIFrame = document->seamlessParentIFrame();
+    if (!seamlessParentIFrame)
+        return;
+    sheets.append(seamlessParentIFrame->document()->styleSheetCollection()->activeAuthorStyleSheets());
+}
+
+bool DocumentStyleSheetCollection::updateActiveStyleSheets(UpdateFlag updateFlag)
+{
+    if (m_document->inStyleRecalc()) {
+        // SVG <use> element may manage to invalidate style selector in the middle of a style recalc.
+        // https://bugs.webkit.org/show_bug.cgi?id=54344
+        // FIXME: This should be fixed in SVG and the call site replaced by ASSERT(!m_inStyleRecalc).
+        m_needsUpdateActiveStylesheetsOnStyleRecalc = true;
+        m_document->scheduleForcedStyleRecalc();
+        return false;
+
+    }
+    if (!m_document->renderer() || !m_document->attached())
+        return false;
+
+    Vector<RefPtr<StyleSheet> > activeStyleSheets;
+    collectActiveStyleSheets(activeStyleSheets);
+
+    Vector<RefPtr<CSSStyleSheet> > activeCSSStyleSheets;
+    activeCSSStyleSheets.append(injectedAuthorStyleSheets());
+    activeCSSStyleSheets.append(documentAuthorStyleSheets());
+    collectActiveCSSStyleSheetsFromSeamlessParents(activeCSSStyleSheets, m_document);
+    filterEnabledCSSStyleSheets(activeCSSStyleSheets, activeStyleSheets);
+
+    StyleResolverUpdateType styleResolverUpdateType;
+    bool requiresFullStyleRecalc;
+    analyzeStyleSheetChange(updateFlag, activeCSSStyleSheets, styleResolverUpdateType, requiresFullStyleRecalc);
+
+    if (styleResolverUpdateType == Reconstruct)
+        m_document->clearStyleResolver();
+    else {
+        StyleResolver* styleResolver = m_document->styleResolver();
+        if (styleResolverUpdateType == Reset) {
+            styleResolver->ruleSets().resetAuthorStyle();
+            styleResolver->appendAuthorStyleSheets(0, activeCSSStyleSheets);
+        } else {
+            ASSERT(styleResolverUpdateType == Additive);
+            styleResolver->appendAuthorStyleSheets(m_activeAuthorStyleSheets.size(), activeCSSStyleSheets);
+        }
+        resetCSSFeatureFlags();
+    }
+    m_activeAuthorStyleSheets.swap(activeCSSStyleSheets);
+    InspectorInstrumentation::activeStyleSheetsUpdated(m_document, activeStyleSheets);
+    m_styleSheetsForStyleSheetList.swap(activeStyleSheets);
+
+    m_usesRemUnits = styleSheetsUseRemUnits(m_activeAuthorStyleSheets);
+    m_needsUpdateActiveStylesheetsOnStyleRecalc = false;
+
+    m_document->notifySeamlessChildDocumentsOfStylesheetUpdate();
+
+    return requiresFullStyleRecalc;
+}
+
+void DocumentStyleSheetCollection::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    info.addMember(m_pageUserSheet, "pageUserSheet");
+    info.addMember(m_injectedUserStyleSheets, "injectedUserStyleSheets");
+    info.addMember(m_injectedAuthorStyleSheets, "injectedAuthorStyleSheets");
+    info.addMember(m_userStyleSheets, "userStyleSheets");
+    info.addMember(m_authorStyleSheets, "authorStyleSheets");
+    info.addMember(m_activeAuthorStyleSheets, "activeAuthorStyleSheets");
+    info.addMember(m_styleSheetsForStyleSheetList, "styleSheetsForStyleSheetList");
+    info.addMember(m_styleSheetCandidateNodes, "styleSheetCandidateNodes");
+    info.addMember(m_preferredStylesheetSetName, "preferredStylesheetSetName");
+    info.addMember(m_selectedStylesheetSetName, "selectedStylesheetSetName");
+    info.addMember(m_document, "document");
+}
+
+}
diff --git a/Source/core/dom/DocumentStyleSheetCollection.h b/Source/core/dom/DocumentStyleSheetCollection.h
new file mode 100644
index 0000000..51997fa
--- /dev/null
+++ b/Source/core/dom/DocumentStyleSheetCollection.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef DocumentStyleSheetCollection_h
+#define DocumentStyleSheetCollection_h
+
+#include <wtf/FastAllocBase.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class CSSStyleSheet;
+class Document;
+class Node;
+class StyleSheet;
+class StyleSheetContents;
+class StyleSheetList;
+
+class DocumentStyleSheetCollection {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<DocumentStyleSheetCollection> create(Document* document) { return adoptPtr(new DocumentStyleSheetCollection(document)); }
+
+    ~DocumentStyleSheetCollection();
+
+    const Vector<RefPtr<StyleSheet> >& styleSheetsForStyleSheetList() const { return m_styleSheetsForStyleSheetList; }
+
+    const Vector<RefPtr<CSSStyleSheet> >& activeAuthorStyleSheets() const { return m_activeAuthorStyleSheets; }
+
+    CSSStyleSheet* pageUserSheet();
+    const Vector<RefPtr<CSSStyleSheet> >& documentUserStyleSheets() const { return m_userStyleSheets; }
+    const Vector<RefPtr<CSSStyleSheet> >& documentAuthorStyleSheets() const { return m_authorStyleSheets; }
+    const Vector<RefPtr<CSSStyleSheet> >& injectedUserStyleSheets() const;
+    const Vector<RefPtr<CSSStyleSheet> >& injectedAuthorStyleSheets() const;
+
+    void addStyleSheetCandidateNode(Node*, bool createdByParser);
+    void removeStyleSheetCandidateNode(Node*);
+
+    void clearPageUserSheet();
+    void updatePageUserSheet();
+    void invalidateInjectedStyleSheetCache();
+    void updateInjectedStyleSheetCache() const;
+
+    void addAuthorSheet(PassRefPtr<StyleSheetContents> authorSheet);
+    void addUserSheet(PassRefPtr<StyleSheetContents> userSheet);
+
+    bool needsUpdateActiveStylesheetsOnStyleRecalc() const { return m_needsUpdateActiveStylesheetsOnStyleRecalc; }
+
+    enum UpdateFlag { FullUpdate, OptimizedUpdate };
+    bool updateActiveStyleSheets(UpdateFlag);
+
+    String preferredStylesheetSetName() const { return m_preferredStylesheetSetName; }
+    String selectedStylesheetSetName() const { return m_selectedStylesheetSetName; }
+    void setPreferredStylesheetSetName(const String& name) { m_preferredStylesheetSetName = name; }
+    void setSelectedStylesheetSetName(const String& name) { m_selectedStylesheetSetName = name; }
+
+    void addPendingSheet() { m_pendingStylesheets++; }
+    enum RemovePendingSheetNotificationType {
+        RemovePendingSheetNotifyImmediately,
+        RemovePendingSheetNotifyLater
+    };
+    void removePendingSheet(RemovePendingSheetNotificationType = RemovePendingSheetNotifyImmediately);
+
+    bool hasPendingSheets() const { return m_pendingStylesheets > 0; }
+
+    bool usesSiblingRules() const { return m_usesSiblingRules || m_usesSiblingRulesOverride; }
+    void setUsesSiblingRulesOverride(bool b) { m_usesSiblingRulesOverride = b; }
+    bool usesFirstLineRules() const { return m_usesFirstLineRules; }
+    bool usesFirstLetterRules() const { return m_usesFirstLetterRules; }
+    void setUsesFirstLetterRules(bool b) { m_usesFirstLetterRules = b; }
+    bool usesBeforeAfterRules() const { return m_usesBeforeAfterRules || m_usesBeforeAfterRulesOverride; }
+    void setUsesBeforeAfterRulesOverride(bool b) { m_usesBeforeAfterRulesOverride = b; }
+    bool usesRemUnits() const { return m_usesRemUnits; }
+    void setUsesRemUnit(bool b) { m_usesRemUnits = b; }
+
+    void combineCSSFeatureFlags();
+    void resetCSSFeatureFlags();
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+private:
+    DocumentStyleSheetCollection(Document*);
+
+    void collectActiveStyleSheets(Vector<RefPtr<StyleSheet> >&);
+    enum StyleResolverUpdateType {
+        Reconstruct,
+        Reset,
+        Additive
+    };
+    void analyzeStyleSheetChange(UpdateFlag, const Vector<RefPtr<CSSStyleSheet> >& newStylesheets, StyleResolverUpdateType&, bool& requiresFullStyleRecalc);
+
+    Document* m_document;
+
+    Vector<RefPtr<StyleSheet> > m_styleSheetsForStyleSheetList;
+    Vector<RefPtr<CSSStyleSheet> > m_activeAuthorStyleSheets;
+
+    // Track the number of currently loading top-level stylesheets needed for rendering.
+    // Sheets loaded using the @import directive are not included in this count.
+    // We use this count of pending sheets to detect when we can begin attaching
+    // elements and when it is safe to execute scripts.
+    int m_pendingStylesheets;
+
+    RefPtr<CSSStyleSheet> m_pageUserSheet;
+
+    mutable Vector<RefPtr<CSSStyleSheet> > m_injectedUserStyleSheets;
+    mutable Vector<RefPtr<CSSStyleSheet> > m_injectedAuthorStyleSheets;
+    mutable bool m_injectedStyleSheetCacheValid;
+
+    Vector<RefPtr<CSSStyleSheet> > m_userStyleSheets;
+    Vector<RefPtr<CSSStyleSheet> > m_authorStyleSheets;
+
+    bool m_hadActiveLoadingStylesheet;
+    bool m_needsUpdateActiveStylesheetsOnStyleRecalc;
+
+    typedef ListHashSet<Node*, 32> StyleSheetCandidateListHashSet;
+    StyleSheetCandidateListHashSet m_styleSheetCandidateNodes;
+
+    String m_preferredStylesheetSetName;
+    String m_selectedStylesheetSetName;
+
+    bool m_usesSiblingRules;
+    bool m_usesSiblingRulesOverride;
+    bool m_usesFirstLineRules;
+    bool m_usesFirstLetterRules;
+    bool m_usesBeforeAfterRules;
+    bool m_usesBeforeAfterRulesOverride;
+    bool m_usesRemUnits;
+};
+
+}
+
+#endif
+
diff --git a/Source/core/dom/DocumentTiming.h b/Source/core/dom/DocumentTiming.h
new file mode 100644
index 0000000..89e2fb9
--- /dev/null
+++ b/Source/core/dom/DocumentTiming.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 GOOGLE 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 GOOGLE 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 DocumentTiming_h
+#define DocumentTiming_h
+
+namespace WebCore {
+
+struct DocumentTiming {
+    DocumentTiming()
+        : domLoading(0.0)
+        , domInteractive(0.0)
+        , domContentLoadedEventStart(0.0)
+        , domContentLoadedEventEnd(0.0)
+        , domComplete(0.0)
+    {
+    }
+
+    double domLoading;
+    double domInteractive;
+    double domContentLoadedEventStart;
+    double domContentLoadedEventEnd;
+    double domComplete;
+};
+
+}
+
+#endif
diff --git a/Source/core/dom/DocumentType.cpp b/Source/core/dom/DocumentType.cpp
new file mode 100644
index 0000000..e85936b
--- /dev/null
+++ b/Source/core/dom/DocumentType.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/DocumentType.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/NamedNodeMap.h"
+
+namespace WebCore {
+
+DocumentType::DocumentType(Document* document, const String& name, const String& publicId, const String& systemId)
+    : Node(document, CreateOther)
+    , m_name(name)
+    , m_publicId(publicId)
+    , m_systemId(systemId)
+{
+    ScriptWrappable::init(this);
+}
+
+KURL DocumentType::baseURI() const
+{
+    return KURL();
+}
+
+String DocumentType::nodeName() const
+{
+    return name();
+}
+
+Node::NodeType DocumentType::nodeType() const
+{
+    return DOCUMENT_TYPE_NODE;
+}
+
+PassRefPtr<Node> DocumentType::cloneNode(bool /*deep*/)
+{
+    return create(document(), m_name, m_publicId, m_systemId);
+}
+
+Node::InsertionNotificationRequest DocumentType::insertedInto(ContainerNode* insertionPoint)
+{
+    Node::insertedInto(insertionPoint);
+    if (!insertionPoint->inDocument())
+        return InsertionDone;
+
+    // Our document node can be null if we were created by a DOMImplementation.  We use the parent() instead.
+    ASSERT(parentNode() && parentNode()->isDocumentNode());
+    if (parentNode() && parentNode()->isDocumentNode()) {
+        Document* doc = toDocument(parentNode());
+        if (!doc->doctype())
+            doc->setDocType(this);
+    }
+
+    return InsertionDone;
+}
+
+void DocumentType::removedFrom(ContainerNode* insertionPoint)
+{
+    if (insertionPoint->inDocument() && document() && document()->doctype() == this)
+        document()->setDocType(0);
+    Node::removedFrom(insertionPoint);
+}
+
+}
diff --git a/Source/core/dom/DocumentType.h b/Source/core/dom/DocumentType.h
new file mode 100644
index 0000000..aefc21d
--- /dev/null
+++ b/Source/core/dom/DocumentType.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef DocumentType_h
+#define DocumentType_h
+
+#include "core/dom/Node.h"
+
+namespace WebCore {
+
+class NamedNodeMap;
+
+class DocumentType FINAL : public Node {
+public:
+    static PassRefPtr<DocumentType> create(Document* document, const String& name, const String& publicId, const String& systemId)
+    {
+        return adoptRef(new DocumentType(document, name, publicId, systemId));
+    }
+
+    // FIXME: We never fill m_entities and m_notations. Current implementation of NamedNodeMap doesn't work without an associated Element yet.
+    NamedNodeMap* entities() const { return m_entities.get(); }
+    NamedNodeMap* notations() const { return m_notations.get(); }
+
+    const String& name() const { return m_name; }
+    const String& publicId() const { return m_publicId; }
+    const String& systemId() const { return m_systemId; }
+    const String& internalSubset() const { return m_subset; }
+
+private:
+    DocumentType(Document*, const String& name, const String& publicId, const String& systemId);
+
+    virtual KURL baseURI() const;
+    virtual String nodeName() const;
+    virtual NodeType nodeType() const;
+    virtual PassRefPtr<Node> cloneNode(bool deep);
+
+    virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
+    virtual void removedFrom(ContainerNode*) OVERRIDE;
+
+    OwnPtr<NamedNodeMap> m_entities;
+    OwnPtr<NamedNodeMap> m_notations;
+
+    String m_name;
+    String m_publicId;
+    String m_systemId;
+    String m_subset;
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/core/dom/DocumentType.idl b/Source/core/dom/DocumentType.idl
new file mode 100644
index 0000000..5cd61a9
--- /dev/null
+++ b/Source/core/dom/DocumentType.idl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+interface DocumentType : Node {
+
+    // DOM Level 1
+
+    readonly attribute DOMString name;
+    readonly attribute NamedNodeMap entities;
+    readonly attribute NamedNodeMap notations;
+
+    // DOM Level 2
+
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString publicId;
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString systemId;
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString internalSubset;        
+
+    // DOM 4
+    [RaisesException] void remove();
+};
+
diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp
new file mode 100644
index 0000000..1ea9515
--- /dev/null
+++ b/Source/core/dom/Element.cpp
@@ -0,0 +1,3123 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Peter Kelly (pmk@post.com)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ *           (C) 2007 David Smith (catfish.man@gmail.com)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
+ *           (C) 2007 Eric Seidel (eric@webkit.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/Element.h"
+
+#include "HTMLNames.h"
+#include "XMLNSNames.h"
+#include "XMLNames.h"
+#include "core/accessibility/AXObjectCache.h"
+#include "core/css/CSSParser.h"
+#include "core/css/CSSSelectorList.h"
+#include "core/css/StylePropertySet.h"
+#include "core/css/StyleResolver.h"
+#include "core/dom/Attr.h"
+#include "core/dom/ClientRect.h"
+#include "core/dom/ClientRectList.h"
+#include "core/dom/CustomElementRegistry.h"
+#include "core/dom/DatasetDOMStringMap.h"
+#include "core/dom/Document.h"
+#include "core/dom/DocumentFragment.h"
+#include "core/dom/DocumentSharedObjectPool.h"
+#include "core/dom/ElementRareData.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/MutationObserverInterestGroup.h"
+#include "core/dom/MutationRecord.h"
+#include "core/dom/NamedNodeMap.h"
+#include "core/dom/NodeList.h"
+#include "core/dom/NodeRenderStyle.h"
+#include "core/dom/NodeRenderingContext.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/dom/PseudoElement.h"
+#include "core/dom/SelectorQuery.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/dom/Text.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/editing/FrameSelection.h"
+#include "core/editing/TextIterator.h"
+#include "core/editing/htmlediting.h"
+#include "core/html/ClassList.h"
+#include "core/html/DOMTokenList.h"
+#include "core/html/HTMLCollection.h"
+#include "core/html/HTMLDocument.h"
+#include "core/html/HTMLElement.h"
+#include "core/html/HTMLFormControlsCollection.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/html/HTMLLabelElement.h"
+#include "core/html/HTMLOptionsCollection.h"
+#include "core/html/HTMLTableRowsCollection.h"
+#include "core/html/VoidCallback.h"
+#include "core/html/parser/HTMLParserIdioms.h"
+#include "core/html/shadow/InsertionPoint.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/page/FocusController.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/page/PointerLockController.h"
+#include "core/page/Settings.h"
+#include "core/rendering/FlowThreadController.h"
+#include "core/rendering/RenderRegion.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/RenderWidget.h"
+#include <wtf/BitVector.h>
+#include <wtf/MemoryInstrumentationVector.h>
+#include <wtf/text/CString.h>
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#include "core/svg/SVGDocumentExtensions.h"
+#include "core/svg/SVGElement.h"
+#endif
+
+namespace WebCore {
+
+using namespace HTMLNames;
+using namespace XMLNames;
+
+static inline bool shouldIgnoreAttributeCase(const Element* e)
+{
+    return e && e->document()->isHTMLDocument() && e->isHTMLElement();
+}
+    
+class StyleResolverParentPusher {
+public:
+    StyleResolverParentPusher(Element* parent)
+        : m_parent(parent)
+        , m_pushedStyleResolver(0)
+    {
+    }
+    void push()
+    {
+        if (m_pushedStyleResolver)
+            return;
+        m_pushedStyleResolver = m_parent->document()->styleResolver();
+        m_pushedStyleResolver->pushParentElement(m_parent);
+    }
+    ~StyleResolverParentPusher()
+    {
+
+        if (!m_pushedStyleResolver)
+            return;
+
+        // This tells us that our pushed style selector is in a bad state,
+        // so we should just bail out in that scenario.
+        ASSERT(m_pushedStyleResolver == m_parent->document()->styleResolver());
+        if (m_pushedStyleResolver != m_parent->document()->styleResolver())
+            return;
+
+        m_pushedStyleResolver->popParentElement(m_parent);
+    }
+
+private:
+    Element* m_parent;
+    StyleResolver* m_pushedStyleResolver;
+};
+
+typedef Vector<RefPtr<Attr> > AttrNodeList;
+typedef HashMap<Element*, OwnPtr<AttrNodeList> > AttrNodeListMap;
+
+static AttrNodeListMap& attrNodeListMap()
+{
+    DEFINE_STATIC_LOCAL(AttrNodeListMap, map, ());
+    return map;
+}
+
+static AttrNodeList* attrNodeListForElement(Element* element)
+{
+    if (!element->hasSyntheticAttrChildNodes())
+        return 0;
+    ASSERT(attrNodeListMap().contains(element));
+    return attrNodeListMap().get(element);
+}
+
+static AttrNodeList* ensureAttrNodeListForElement(Element* element)
+{
+    if (element->hasSyntheticAttrChildNodes()) {
+        ASSERT(attrNodeListMap().contains(element));
+        return attrNodeListMap().get(element);
+    }
+    ASSERT(!attrNodeListMap().contains(element));
+    element->setHasSyntheticAttrChildNodes(true);
+    AttrNodeListMap::AddResult result = attrNodeListMap().add(element, adoptPtr(new AttrNodeList));
+    return result.iterator->value.get();
+}
+
+static void removeAttrNodeListForElement(Element* element)
+{
+    ASSERT(element->hasSyntheticAttrChildNodes());
+    ASSERT(attrNodeListMap().contains(element));
+    attrNodeListMap().remove(element);
+    element->setHasSyntheticAttrChildNodes(false);
+}
+
+static Attr* findAttrNodeInList(AttrNodeList* attrNodeList, const QualifiedName& name)
+{
+    for (unsigned i = 0; i < attrNodeList->size(); ++i) {
+        if (attrNodeList->at(i)->qualifiedName() == name)
+            return attrNodeList->at(i).get();
+    }
+    return 0;
+}
+
+// Need a template since ElementShadow is not a Node, but has the style recalc methods.
+template<class T>
+static inline bool shouldRecalcStyle(Node::StyleChange change, const T* node)
+{
+    return change >= Node::Inherit || node->childNeedsStyleRecalc() || node->needsStyleRecalc();
+}
+
+PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* document)
+{
+    return adoptRef(new Element(tagName, document, CreateElement));
+}
+
+Element::~Element()
+{
+#ifndef NDEBUG
+    if (document() && document()->renderer()) {
+        // When the document is not destroyed, an element that was part of a named flow
+        // content nodes should have been removed from the content nodes collection
+        // and the inNamedFlow flag reset.
+        ASSERT(!inNamedFlow());
+    }
+#endif
+
+    if (hasRareData()) {
+        ElementRareData* data = elementRareData();
+        data->setPseudoElement(BEFORE, 0);
+        data->setPseudoElement(AFTER, 0);
+        data->clearShadow();
+    }
+
+    if (isCustomElement() && document() && document()->registry()) {
+        document()->registry()->customElementWasDestroyed(this);
+    }
+
+    if (hasSyntheticAttrChildNodes())
+        detachAllAttrNodesFromElement();
+
+#if ENABLE(SVG)
+    if (hasPendingResources()) {
+        document()->accessSVGExtensions()->removeElementFromPendingResources(this);
+        ASSERT(!hasPendingResources());
+    }
+#endif
+}
+
+inline ElementRareData* Element::elementRareData() const
+{
+    ASSERT(hasRareData());
+    return static_cast<ElementRareData*>(rareData());
+}
+
+inline ElementRareData* Element::ensureElementRareData()
+{
+    return static_cast<ElementRareData*>(ensureRareData());
+}
+
+void Element::clearTabIndexExplicitlyIfNeeded()
+{
+    if (hasRareData())
+        elementRareData()->clearTabIndexExplicitly();
+}
+
+void Element::setTabIndexExplicitly(short tabIndex)
+{
+    ensureElementRareData()->setTabIndexExplicitly(tabIndex);
+}
+
+bool Element::supportsFocus() const
+{
+    return hasRareData() && elementRareData()->tabIndexSetExplicitly();
+}
+
+short Element::tabIndex() const
+{
+    return hasRareData() ? elementRareData()->tabIndex() : 0;
+}
+
+DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, blur);
+DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, error);
+DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, focus);
+DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, load);
+
+PassRefPtr<Node> Element::cloneNode(bool deep)
+{
+    return deep ? cloneElementWithChildren() : cloneElementWithoutChildren();
+}
+
+PassRefPtr<Element> Element::cloneElementWithChildren()
+{
+    RefPtr<Element> clone = cloneElementWithoutChildren();
+    cloneChildNodes(clone.get());
+    return clone.release();
+}
+
+PassRefPtr<Element> Element::cloneElementWithoutChildren()
+{
+    RefPtr<Element> clone = cloneElementWithoutAttributesAndChildren();
+    // This will catch HTML elements in the wrong namespace that are not correctly copied.
+    // This is a sanity check as HTML overloads some of the DOM methods.
+    ASSERT(isHTMLElement() == clone->isHTMLElement());
+
+    clone->cloneDataFromElement(*this);
+    return clone.release();
+}
+
+PassRefPtr<Element> Element::cloneElementWithoutAttributesAndChildren()
+{
+    return document()->createElement(tagQName(), false);
+}
+
+PassRefPtr<Attr> Element::detachAttribute(size_t index)
+{
+    ASSERT(elementData());
+
+    const Attribute* attribute = elementData()->attributeItem(index);
+    ASSERT(attribute);
+
+    RefPtr<Attr> attrNode = attrIfExists(attribute->name());
+    if (attrNode)
+        detachAttrNodeFromElementWithValue(attrNode.get(), attribute->value());
+    else
+        attrNode = Attr::create(document(), attribute->name(), attribute->value());
+
+    removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
+    return attrNode.release();
+}
+
+void Element::removeAttribute(const QualifiedName& name)
+{
+    if (!elementData())
+        return;
+
+    size_t index = elementData()->getAttributeItemIndex(name);
+    if (index == notFound)
+        return;
+
+    removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
+}
+
+void Element::setBooleanAttribute(const QualifiedName& name, bool value)
+{
+    if (value)
+        setAttribute(name, emptyAtom);
+    else
+        removeAttribute(name);
+}
+
+NamedNodeMap* Element::attributes() const
+{
+    ElementRareData* rareData = const_cast<Element*>(this)->ensureElementRareData();
+    if (NamedNodeMap* attributeMap = rareData->attributeMap())
+        return attributeMap;
+
+    rareData->setAttributeMap(NamedNodeMap::create(const_cast<Element*>(this)));
+    return rareData->attributeMap();
+}
+
+Node::NodeType Element::nodeType() const
+{
+    return ELEMENT_NODE;
+}
+
+bool Element::hasAttribute(const QualifiedName& name) const
+{
+    return hasAttributeNS(name.namespaceURI(), name.localName());
+}
+
+void Element::synchronizeAllAttributes() const
+{
+    if (!elementData())
+        return;
+    if (elementData()->m_styleAttributeIsDirty) {
+        ASSERT(isStyledElement());
+        static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
+    }
+#if ENABLE(SVG)
+    if (elementData()->m_animatedSVGAttributesAreDirty) {
+        ASSERT(isSVGElement());
+        toSVGElement(this)->synchronizeAnimatedSVGAttribute(anyQName());
+    }
+#endif
+}
+
+inline void Element::synchronizeAttribute(const QualifiedName& name) const
+{
+    if (!elementData())
+        return;
+    if (UNLIKELY(name == styleAttr && elementData()->m_styleAttributeIsDirty)) {
+        ASSERT(isStyledElement());
+        static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
+        return;
+    }
+#if ENABLE(SVG)
+    if (UNLIKELY(elementData()->m_animatedSVGAttributesAreDirty)) {
+        ASSERT(isSVGElement());
+        toSVGElement(this)->synchronizeAnimatedSVGAttribute(name);
+    }
+#endif
+}
+
+inline void Element::synchronizeAttribute(const AtomicString& localName) const
+{
+    // This version of synchronizeAttribute() is streamlined for the case where you don't have a full QualifiedName,
+    // e.g when called from DOM API.
+    if (!elementData())
+        return;
+    if (elementData()->m_styleAttributeIsDirty && equalPossiblyIgnoringCase(localName, styleAttr.localName(), shouldIgnoreAttributeCase(this))) {
+        ASSERT(isStyledElement());
+        static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
+        return;
+    }
+#if ENABLE(SVG)
+    if (elementData()->m_animatedSVGAttributesAreDirty) {
+        // We're not passing a namespace argument on purpose. SVGNames::*Attr are defined w/o namespaces as well.
+        ASSERT(isSVGElement());
+        static_cast<const SVGElement*>(this)->synchronizeAnimatedSVGAttribute(QualifiedName(nullAtom, localName, nullAtom));
+    }
+#endif
+}
+
+const AtomicString& Element::getAttribute(const QualifiedName& name) const
+{
+    if (!elementData())
+        return nullAtom;
+    synchronizeAttribute(name);
+    if (const Attribute* attribute = getAttributeItem(name))
+        return attribute->value();
+    return nullAtom;
+}
+
+void Element::scrollIntoView(bool alignToTop) 
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+
+    if (!renderer())
+        return;
+
+    LayoutRect bounds = boundingBox();
+    // Align to the top / bottom and to the closest edge.
+    if (alignToTop)
+        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
+    else
+        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways);
+}
+
+void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+
+    if (!renderer())
+        return;
+
+    LayoutRect bounds = boundingBox();
+    if (centerIfNeeded)
+        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
+    else
+        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
+}
+
+void Element::scrollByUnits(int units, ScrollGranularity granularity)
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+
+    if (!renderer())
+        return;
+
+    if (!renderer()->hasOverflowClip())
+        return;
+
+    ScrollDirection direction = ScrollDown;
+    if (units < 0) {
+        direction = ScrollUp;
+        units = -units;
+    }
+    Node* stopNode = this;
+    toRenderBox(renderer())->scroll(direction, granularity, units, &stopNode);
+}
+
+void Element::scrollByLines(int lines)
+{
+    scrollByUnits(lines, ScrollByLine);
+}
+
+void Element::scrollByPages(int pages)
+{
+    scrollByUnits(pages, ScrollByPage);
+}
+
+static float localZoomForRenderer(RenderObject* renderer)
+{
+    // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
+    // other out, but the alternative is that we'd have to crawl up the whole render tree every
+    // time (or store an additional bit in the RenderStyle to indicate that a zoom was specified).
+    float zoomFactor = 1;
+    if (renderer->style()->effectiveZoom() != 1) {
+        // Need to find the nearest enclosing RenderObject that set up
+        // a differing zoom, and then we divide our result by it to eliminate the zoom.
+        RenderObject* prev = renderer;
+        for (RenderObject* curr = prev->parent(); curr; curr = curr->parent()) {
+            if (curr->style()->effectiveZoom() != prev->style()->effectiveZoom()) {
+                zoomFactor = prev->style()->zoom();
+                break;
+            }
+            prev = curr;
+        }
+        if (prev->isRenderView())
+            zoomFactor = prev->style()->zoom();
+    }
+    return zoomFactor;
+}
+
+static int adjustForLocalZoom(LayoutUnit value, RenderObject* renderer)
+{
+    float zoomFactor = localZoomForRenderer(renderer);
+    if (zoomFactor == 1)
+        return value;
+    return lroundf(value / zoomFactor);
+}
+
+int Element::offsetLeft()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+    if (RenderBoxModelObject* renderer = renderBoxModelObject())
+        return adjustForLocalZoom(renderer->pixelSnappedOffsetLeft(), renderer);
+    return 0;
+}
+
+int Element::offsetTop()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+    if (RenderBoxModelObject* renderer = renderBoxModelObject())
+        return adjustForLocalZoom(renderer->pixelSnappedOffsetTop(), renderer);
+    return 0;
+}
+
+int Element::offsetWidth()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+    if (RenderBoxModelObject* renderer = renderBoxModelObject())
+        return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedOffsetWidth(), renderer).round();
+    return 0;
+}
+
+int Element::offsetHeight()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+    if (RenderBoxModelObject* renderer = renderBoxModelObject())
+        return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedOffsetHeight(), renderer).round();
+    return 0;
+}
+
+Element* Element::bindingsOffsetParent()
+{
+    Element* element = offsetParent();
+    if (!element || !element->isInShadowTree())
+        return element;
+    return element->containingShadowRoot()->type() == ShadowRoot::UserAgentShadowRoot ? 0 : element;
+}
+
+Element* Element::offsetParent()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+    if (RenderObject* renderer = this->renderer())
+        return renderer->offsetParent();
+    return 0;
+}
+
+int Element::clientLeft()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+
+    if (RenderBox* renderer = renderBox())
+        return adjustForAbsoluteZoom(roundToInt(renderer->clientLeft()), renderer);
+    return 0;
+}
+
+int Element::clientTop()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+
+    if (RenderBox* renderer = renderBox())
+        return adjustForAbsoluteZoom(roundToInt(renderer->clientTop()), renderer);
+    return 0;
+}
+
+int Element::clientWidth()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+
+    // When in strict mode, clientWidth for the document element should return the width of the containing frame.
+    // When in quirks mode, clientWidth for the body element should return the width of the containing frame.
+    bool inQuirksMode = document()->inQuirksMode();
+    if ((!inQuirksMode && document()->documentElement() == this) ||
+        (inQuirksMode && isHTMLElement() && document()->body() == this)) {
+        if (FrameView* view = document()->view()) {
+            if (RenderView* renderView = document()->renderView())
+                return adjustForAbsoluteZoom(view->layoutWidth(), renderView);
+        }
+    }
+    
+    if (RenderBox* renderer = renderBox())
+        return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedClientWidth(), renderer).round();
+    return 0;
+}
+
+int Element::clientHeight()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+
+    // When in strict mode, clientHeight for the document element should return the height of the containing frame.
+    // When in quirks mode, clientHeight for the body element should return the height of the containing frame.
+    bool inQuirksMode = document()->inQuirksMode();     
+
+    if ((!inQuirksMode && document()->documentElement() == this) ||
+        (inQuirksMode && isHTMLElement() && document()->body() == this)) {
+        if (FrameView* view = document()->view()) {
+            if (RenderView* renderView = document()->renderView())
+                return adjustForAbsoluteZoom(view->layoutHeight(), renderView);
+        }
+    }
+    
+    if (RenderBox* renderer = renderBox())
+        return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedClientHeight(), renderer).round();
+    return 0;
+}
+
+int Element::scrollLeft()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+    if (RenderBox* rend = renderBox())
+        return adjustForAbsoluteZoom(rend->scrollLeft(), rend);
+    return 0;
+}
+
+int Element::scrollTop()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+    if (RenderBox* rend = renderBox())
+        return adjustForAbsoluteZoom(rend->scrollTop(), rend);
+    return 0;
+}
+
+void Element::setScrollLeft(int newLeft)
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+    if (RenderBox* rend = renderBox())
+        rend->setScrollLeft(static_cast<int>(newLeft * rend->style()->effectiveZoom()));
+}
+
+void Element::setScrollTop(int newTop)
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+    if (RenderBox* rend = renderBox())
+        rend->setScrollTop(static_cast<int>(newTop * rend->style()->effectiveZoom()));
+}
+
+int Element::scrollWidth()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+    if (RenderBox* rend = renderBox())
+        return adjustForAbsoluteZoom(rend->scrollWidth(), rend);
+    return 0;
+}
+
+int Element::scrollHeight()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+    if (RenderBox* rend = renderBox())
+        return adjustForAbsoluteZoom(rend->scrollHeight(), rend);
+    return 0;
+}
+
+IntRect Element::boundsInRootViewSpace()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+
+    FrameView* view = document()->view();
+    if (!view)
+        return IntRect();
+
+    Vector<FloatQuad> quads;
+#if ENABLE(SVG)
+    if (isSVGElement() && renderer()) {
+        // Get the bounding rectangle from the SVG model.
+        SVGElement* svgElement = toSVGElement(this);
+        FloatRect localRect;
+        if (svgElement->getBoundingBox(localRect))
+            quads.append(renderer()->localToAbsoluteQuad(localRect));
+    } else
+#endif
+    {
+        // Get the bounding rectangle from the box model.
+        if (renderBoxModelObject())
+            renderBoxModelObject()->absoluteQuads(quads);
+    }
+
+    if (quads.isEmpty())
+        return IntRect();
+
+    IntRect result = quads[0].enclosingBoundingBox();
+    for (size_t i = 1; i < quads.size(); ++i)
+        result.unite(quads[i].enclosingBoundingBox());
+
+    result = view->contentsToRootView(result);
+    return result;
+}
+
+PassRefPtr<ClientRectList> Element::getClientRects()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+
+    RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
+    if (!renderBoxModelObject)
+        return ClientRectList::create();
+
+    // FIXME: Handle SVG elements.
+    // FIXME: Handle table/inline-table with a caption.
+
+    Vector<FloatQuad> quads;
+    renderBoxModelObject->absoluteQuads(quads);
+    document()->adjustFloatQuadsForScrollAndAbsoluteZoom(quads, renderBoxModelObject);
+    return ClientRectList::create(quads);
+}
+
+PassRefPtr<ClientRect> Element::getBoundingClientRect()
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+
+    Vector<FloatQuad> quads;
+#if ENABLE(SVG)
+    if (isSVGElement() && renderer() && !renderer()->isSVGRoot()) {
+        // Get the bounding rectangle from the SVG model.
+        SVGElement* svgElement = toSVGElement(this);
+        FloatRect localRect;
+        if (svgElement->getBoundingBox(localRect))
+            quads.append(renderer()->localToAbsoluteQuad(localRect));
+    } else
+#endif
+    {
+        // Get the bounding rectangle from the box model.
+        if (renderBoxModelObject())
+            renderBoxModelObject()->absoluteQuads(quads);
+    }
+
+    if (quads.isEmpty())
+        return ClientRect::create();
+
+    FloatRect result = quads[0].boundingBox();
+    for (size_t i = 1; i < quads.size(); ++i)
+        result.unite(quads[i].boundingBox());
+
+    document()->adjustFloatRectForScrollAndAbsoluteZoom(result, renderer());
+    return ClientRect::create(result);
+}
+    
+IntRect Element::screenRect() const
+{
+    if (!renderer())
+        return IntRect();
+    // FIXME: this should probably respect transforms
+    return document()->view()->contentsToScreen(renderer()->absoluteBoundingBoxRectIgnoringTransforms());
+}
+
+const AtomicString& Element::getAttribute(const AtomicString& localName) const
+{
+    if (!elementData())
+        return nullAtom;
+    synchronizeAttribute(localName);
+    if (const Attribute* attribute = elementData()->getAttributeItem(localName, shouldIgnoreAttributeCase(this)))
+        return attribute->value();
+    return nullAtom;
+}
+
+const AtomicString& Element::getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const
+{
+    return getAttribute(QualifiedName(nullAtom, localName, namespaceURI));
+}
+
+void Element::setAttribute(const AtomicString& localName, const AtomicString& value, ExceptionCode& ec)
+{
+    if (!Document::isValidName(localName)) {
+        ec = INVALID_CHARACTER_ERR;
+        return;
+    }
+
+    synchronizeAttribute(localName);
+    const AtomicString& caseAdjustedLocalName = shouldIgnoreAttributeCase(this) ? localName.lower() : localName;
+
+    size_t index = elementData() ? elementData()->getAttributeItemIndex(caseAdjustedLocalName, false) : notFound;
+    const QualifiedName& qName = index != notFound ? attributeItem(index)->name() : QualifiedName(nullAtom, caseAdjustedLocalName, nullAtom);
+    setAttributeInternal(index, qName, value, NotInSynchronizationOfLazyAttribute);
+}
+
+void Element::setAttribute(const QualifiedName& name, const AtomicString& value)
+{
+    synchronizeAttribute(name);
+    size_t index = elementData() ? elementData()->getAttributeItemIndex(name) : notFound;
+    setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute);
+}
+
+void Element::setSynchronizedLazyAttribute(const QualifiedName& name, const AtomicString& value)
+{
+    size_t index = elementData() ? elementData()->getAttributeItemIndex(name) : notFound;
+    setAttributeInternal(index, name, value, InSynchronizationOfLazyAttribute);
+}
+
+inline void Element::setAttributeInternal(size_t index, const QualifiedName& name, const AtomicString& newValue, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
+{
+    if (newValue.isNull()) {
+        if (index != notFound)
+            removeAttributeInternal(index, inSynchronizationOfLazyAttribute);
+        return;
+    }
+
+    if (index == notFound) {
+        addAttributeInternal(name, newValue, inSynchronizationOfLazyAttribute);
+        return;
+    }
+
+    if (!inSynchronizationOfLazyAttribute)
+        willModifyAttribute(name, attributeItem(index)->value(), newValue);
+
+    if (newValue != attributeItem(index)->value()) {
+        // If there is an Attr node hooked to this attribute, the Attr::setValue() call below
+        // will write into the ElementData.
+        // FIXME: Refactor this so it makes some sense.
+        if (RefPtr<Attr> attrNode = inSynchronizationOfLazyAttribute ? 0 : attrIfExists(name))
+            attrNode->setValue(newValue);
+        else
+            ensureUniqueElementData()->attributeItem(index)->setValue(newValue);
+    }
+
+    if (!inSynchronizationOfLazyAttribute)
+        didModifyAttribute(name, newValue);
+}
+
+static inline AtomicString makeIdForStyleResolution(const AtomicString& value, bool inQuirksMode)
+{
+    if (inQuirksMode)
+        return value.lower();
+    return value;
+}
+
+static bool checkNeedsStyleInvalidationForIdChange(const AtomicString& oldId, const AtomicString& newId, StyleResolver* styleResolver)
+{
+    ASSERT(newId != oldId);
+    if (!oldId.isEmpty() && styleResolver->hasSelectorForId(oldId))
+        return true;
+    if (!newId.isEmpty() && styleResolver->hasSelectorForId(newId))
+        return true;
+    return false;
+}
+
+void Element::attributeChanged(const QualifiedName& name, const AtomicString& newValue, AttributeModificationReason)
+{
+    if (ElementShadow* parentElementShadow = shadowOfParentForDistribution(this)) {
+        if (shouldInvalidateDistributionWhenAttributeChanged(parentElementShadow, name, newValue))
+            parentElementShadow->invalidateDistribution();
+    }
+
+    parseAttribute(name, newValue);
+
+    document()->incDOMTreeVersion();
+
+    StyleResolver* styleResolver = document()->styleResolverIfExists();
+    bool testShouldInvalidateStyle = attached() && styleResolver && styleChangeType() < FullStyleChange;
+    bool shouldInvalidateStyle = false;
+
+    if (isIdAttributeName(name)) {
+        AtomicString oldId = elementData()->idForStyleResolution();
+        AtomicString newId = makeIdForStyleResolution(newValue, document()->inQuirksMode());
+        if (newId != oldId) {
+            elementData()->setIdForStyleResolution(newId);
+            shouldInvalidateStyle = testShouldInvalidateStyle && checkNeedsStyleInvalidationForIdChange(oldId, newId, styleResolver);
+        }
+    } else if (name == classAttr)
+        classAttributeChanged(newValue);
+    else if (name == HTMLNames::nameAttr)
+        setHasName(!newValue.isNull());
+    else if (name == HTMLNames::pseudoAttr)
+        shouldInvalidateStyle |= testShouldInvalidateStyle && isInShadowTree();
+
+    invalidateNodeListCachesInAncestors(&name, this);
+
+    // If there is currently no StyleResolver, we can't be sure that this attribute change won't affect style.
+    shouldInvalidateStyle |= !styleResolver;
+
+    if (shouldInvalidateStyle)
+        setNeedsStyleRecalc();
+
+    if (AXObjectCache* cache = document()->existingAXObjectCache())
+        cache->handleAttributeChanged(name, this);
+}
+
+inline void Element::attributeChangedFromParserOrByCloning(const QualifiedName& name, const AtomicString& newValue, AttributeModificationReason reason)
+{
+    if (RuntimeEnabledFeatures::customDOMElementsEnabled() && name == isAttr) {
+        document()->ensureCustomElementRegistry()->didGiveTypeExtension(this, newValue);
+    }
+    attributeChanged(name, newValue, reason);
+}
+
+template <typename CharacterType>
+static inline bool classStringHasClassName(const CharacterType* characters, unsigned length)
+{
+    ASSERT(length > 0);
+
+    unsigned i = 0;
+    do {
+        if (isNotHTMLSpace(characters[i]))
+            break;
+        ++i;
+    } while (i < length);
+
+    return i < length;
+}
+
+static inline bool classStringHasClassName(const AtomicString& newClassString)
+{
+    unsigned length = newClassString.length();
+
+    if (!length)
+        return false;
+
+    if (newClassString.is8Bit())
+        return classStringHasClassName(newClassString.characters8(), length);
+    return classStringHasClassName(newClassString.characters16(), length);
+}
+
+template<typename Checker>
+static bool checkSelectorForClassChange(const SpaceSplitString& changedClasses, const Checker& checker)
+{
+    unsigned changedSize = changedClasses.size();
+    for (unsigned i = 0; i < changedSize; ++i) {
+        if (checker.hasSelectorForClass(changedClasses[i]))
+            return true;
+    }
+    return false;
+}
+
+template<typename Checker>
+static bool checkSelectorForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses, const Checker& checker)
+{
+    unsigned oldSize = oldClasses.size();
+    if (!oldSize)
+        return checkSelectorForClassChange(newClasses, checker);
+    BitVector remainingClassBits;
+    remainingClassBits.ensureSize(oldSize);
+    // Class vectors tend to be very short. This is faster than using a hash table.
+    unsigned newSize = newClasses.size();
+    for (unsigned i = 0; i < newSize; ++i) {
+        for (unsigned j = 0; j < oldSize; ++j) {
+            if (newClasses[i] == oldClasses[j]) {
+                remainingClassBits.quickSet(j);
+                continue;
+            }
+        }
+        if (checker.hasSelectorForClass(newClasses[i]))
+            return true;
+    }
+    for (unsigned i = 0; i < oldSize; ++i) {
+        // If the bit is not set the the corresponding class has been removed.
+        if (remainingClassBits.quickGet(i))
+            continue;
+        if (checker.hasSelectorForClass(oldClasses[i]))
+            return true;
+    }
+    return false;
+}
+
+void Element::classAttributeChanged(const AtomicString& newClassString)
+{
+    StyleResolver* styleResolver = document()->styleResolverIfExists();
+    bool testShouldInvalidateStyle = attached() && styleResolver && styleChangeType() < FullStyleChange;
+    bool shouldInvalidateStyle = false;
+
+    if (classStringHasClassName(newClassString)) {
+        const bool shouldFoldCase = document()->inQuirksMode();
+        const SpaceSplitString oldClasses = elementData()->classNames();
+        elementData()->setClass(newClassString, shouldFoldCase);
+        const SpaceSplitString& newClasses = elementData()->classNames();
+        shouldInvalidateStyle = testShouldInvalidateStyle && checkSelectorForClassChange(oldClasses, newClasses, *styleResolver);
+    } else {
+        const SpaceSplitString& oldClasses = elementData()->classNames();
+        shouldInvalidateStyle = testShouldInvalidateStyle && checkSelectorForClassChange(oldClasses, *styleResolver);
+        elementData()->clearClass();
+    }
+
+    if (hasRareData())
+        elementRareData()->clearClassListValueForQuirksMode();
+
+    if (shouldInvalidateStyle)
+        setNeedsStyleRecalc();
+}
+
+bool Element::shouldInvalidateDistributionWhenAttributeChanged(ElementShadow* elementShadow, const QualifiedName& name, const AtomicString& newValue)
+{
+    ASSERT(elementShadow);
+    const SelectRuleFeatureSet& featureSet = elementShadow->distributor().ensureSelectFeatureSet(elementShadow);
+
+    if (isIdAttributeName(name)) {
+        AtomicString oldId = elementData()->idForStyleResolution();
+        AtomicString newId = makeIdForStyleResolution(newValue, document()->inQuirksMode());
+        if (newId != oldId) {
+            if (!oldId.isEmpty() && featureSet.hasSelectorForId(oldId))
+                return true;
+            if (!newId.isEmpty() && featureSet.hasSelectorForId(newId))
+                return true;
+        }
+    }
+
+    if (name == HTMLNames::classAttr) {
+        const AtomicString& newClassString = newValue;
+        if (classStringHasClassName(newClassString)) {
+            const bool shouldFoldCase = document()->inQuirksMode();
+            const SpaceSplitString& oldClasses = elementData()->classNames();
+            const SpaceSplitString newClasses(newClassString, shouldFoldCase);
+            if (checkSelectorForClassChange(oldClasses, newClasses, featureSet))
+                return true;
+        } else {
+            const SpaceSplitString& oldClasses = elementData()->classNames();
+            if (checkSelectorForClassChange(oldClasses, featureSet))
+                return true;
+        }
+    }
+
+    return featureSet.hasSelectorForAttribute(name.localName());
+}
+
+// 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
+// code or configuration change if a new event handler is defined.
+
+static inline bool isEventHandlerAttribute(const Attribute& attribute)
+{
+    return attribute.name().namespaceURI().isNull() && attribute.name().localName().startsWith("on");
+}
+
+bool Element::isJavaScriptURLAttribute(const Attribute& attribute) const
+{
+    return isURLAttribute(attribute) && protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(attribute.value()));
+}
+
+void Element::stripScriptingAttributes(Vector<Attribute>& attributeVector) const
+{
+    size_t destination = 0;
+    for (size_t source = 0; source < attributeVector.size(); ++source) {
+        if (isEventHandlerAttribute(attributeVector[source])
+            || isJavaScriptURLAttribute(attributeVector[source])
+            || isHTMLContentAttribute(attributeVector[source]))
+            continue;
+
+        if (source != destination)
+            attributeVector[destination] = attributeVector[source];
+
+        ++destination;
+    }
+    attributeVector.shrink(destination);
+}
+
+void Element::parserSetAttributes(const Vector<Attribute>& attributeVector)
+{
+    ASSERT(!inDocument());
+    ASSERT(!parentNode());
+    ASSERT(!m_elementData);
+
+    if (attributeVector.isEmpty())
+        return;
+
+    if (document() && document()->sharedObjectPool())
+        m_elementData = document()->sharedObjectPool()->cachedShareableElementDataWithAttributes(attributeVector);
+    else
+        m_elementData = ShareableElementData::createWithAttributes(attributeVector);
+
+    // Use attributeVector instead of m_elementData because attributeChanged might modify m_elementData.
+    for (unsigned i = 0; i < attributeVector.size(); ++i)
+        attributeChangedFromParserOrByCloning(attributeVector[i].name(), attributeVector[i].value(), ModifiedDirectly);
+}
+
+bool Element::hasAttributes() const
+{
+    synchronizeAllAttributes();
+    return elementData() && elementData()->length();
+}
+
+bool Element::hasEquivalentAttributes(const Element* other) const
+{
+    synchronizeAllAttributes();
+    other->synchronizeAllAttributes();
+    if (elementData() == other->elementData())
+        return true;
+    if (elementData())
+        return elementData()->isEquivalent(other->elementData());
+    if (other->elementData())
+        return other->elementData()->isEquivalent(elementData());
+    return true;
+}
+
+String Element::nodeName() const
+{
+    return m_tagName.toString();
+}
+
+String Element::nodeNamePreservingCase() const
+{
+    return m_tagName.toString();
+}
+
+void Element::setPrefix(const AtomicString& prefix, ExceptionCode& ec)
+{
+    ec = 0;
+    checkSetPrefix(prefix, ec);
+    if (ec)
+        return;
+
+    m_tagName.setPrefix(prefix.isEmpty() ? AtomicString() : prefix);
+}
+
+KURL Element::baseURI() const
+{
+    const AtomicString& baseAttribute = getAttribute(baseAttr);
+    KURL base(KURL(), baseAttribute);
+    if (!base.protocol().isEmpty())
+        return base;
+
+    ContainerNode* parent = parentNode();
+    if (!parent)
+        return base;
+
+    const KURL& parentBase = parent->baseURI();
+    if (parentBase.isNull())
+        return base;
+
+    return KURL(parentBase, baseAttribute);
+}
+
+const AtomicString& Element::imageSourceURL() const
+{
+    return getAttribute(srcAttr);
+}
+
+bool Element::rendererIsNeeded(const NodeRenderingContext& context)
+{
+    return context.style()->display() != NONE;
+}
+
+RenderObject* Element::createRenderer(RenderArena*, RenderStyle* style)
+{
+    return RenderObject::createObject(this, style);
+}
+
+#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
+bool Element::isDateTimeFieldElement() const
+{
+    return false;
+}
+#endif
+
+bool Element::wasChangedSinceLastFormControlChangeEvent() const
+{
+    return false;
+}
+
+void Element::setChangedSinceLastFormControlChangeEvent(bool)
+{
+}
+
+bool Element::isDisabledFormControl() const
+{
+    // FIXME: disabled and inert are separate concepts in the spec, but now we treat them as the same.
+    // For example, an inert, non-disabled form control should not be grayed out.
+    if (isInert())
+        return true;
+    return false;
+}
+
+bool Element::isInert() const
+{
+    Element* dialog = document()->activeModalDialog();
+    return dialog && !containsIncludingShadowDOM(dialog) && !dialog->containsIncludingShadowDOM(this);
+}
+
+Node::InsertionNotificationRequest Element::insertedInto(ContainerNode* insertionPoint)
+{
+    // need to do superclass processing first so inDocument() is true
+    // by the time we reach updateId
+    ContainerNode::insertedInto(insertionPoint);
+
+    if (containsFullScreenElement() && parentElement() && !parentElement()->containsFullScreenElement())
+        setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true);
+
+    if (Element* before = pseudoElement(BEFORE))
+        before->insertedInto(insertionPoint);
+
+    if (Element* after = pseudoElement(AFTER))
+        after->insertedInto(insertionPoint);
+
+    if (!insertionPoint->isInTreeScope())
+        return InsertionDone;
+
+    if (hasRareData())
+        elementRareData()->clearClassListValueForQuirksMode();
+
+    TreeScope* scope = insertionPoint->treeScope();
+    if (scope != treeScope())
+        return InsertionDone;
+
+    const AtomicString& idValue = getIdAttribute();
+    if (!idValue.isNull())
+        updateId(scope, nullAtom, idValue);
+
+    const AtomicString& nameValue = getNameAttribute();
+    if (!nameValue.isNull())
+        updateName(nullAtom, nameValue);
+
+    if (hasTagName(labelTag)) {
+        if (scope->shouldCacheLabelsByForAttribute())
+            updateLabel(scope, nullAtom, fastGetAttribute(forAttr));
+    }
+
+    return InsertionDone;
+}
+
+void Element::removedFrom(ContainerNode* insertionPoint)
+{
+#if ENABLE(SVG)
+    bool wasInDocument = insertionPoint->document();
+#endif
+
+    if (Element* before = pseudoElement(BEFORE))
+        before->removedFrom(insertionPoint);
+
+    if (Element* after = pseudoElement(AFTER))
+        after->removedFrom(insertionPoint);
+
+    document()->removeFromTopLayer(this);
+    if (containsFullScreenElement())
+        setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
+
+    if (document()->page())
+        document()->page()->pointerLockController()->elementRemoved(this);
+
+    setSavedLayerScrollOffset(IntSize());
+
+    if (insertionPoint->isInTreeScope() && treeScope() == document()) {
+        const AtomicString& idValue = getIdAttribute();
+        if (!idValue.isNull())
+            updateId(insertionPoint->treeScope(), idValue, nullAtom);
+
+        const AtomicString& nameValue = getNameAttribute();
+        if (!nameValue.isNull())
+            updateName(nameValue, nullAtom);
+
+        if (hasTagName(labelTag)) {
+            TreeScope* treeScope = insertionPoint->treeScope();
+            if (treeScope->shouldCacheLabelsByForAttribute())
+                updateLabel(treeScope, fastGetAttribute(forAttr), nullAtom);
+        }
+    }
+
+    ContainerNode::removedFrom(insertionPoint);
+#if ENABLE(SVG)
+    if (wasInDocument && hasPendingResources())
+        document()->accessSVGExtensions()->removeElementFromPendingResources(this);
+#endif
+}
+
+void Element::createRendererIfNeeded()
+{
+    NodeRenderingContext(this).createRendererForElementIfNeeded();
+}
+
+void Element::attach()
+{
+    PostAttachCallbackDisabler callbackDisabler(this);
+    StyleResolverParentPusher parentPusher(this);
+    WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
+
+    createRendererIfNeeded();
+
+    if (parentElement() && parentElement()->isInCanvasSubtree())
+        setIsInCanvasSubtree(true);
+
+    createPseudoElementIfNeeded(BEFORE);
+
+    // When a shadow root exists, it does the work of attaching the children.
+    if (ElementShadow* shadow = this->shadow()) {
+        parentPusher.push();
+        shadow->attach();
+    } else if (firstChild())
+        parentPusher.push();
+
+    ContainerNode::attach();
+
+    createPseudoElementIfNeeded(AFTER);
+
+    if (hasRareData()) {   
+        ElementRareData* data = elementRareData();
+        if (data->needsFocusAppearanceUpdateSoonAfterAttach()) {
+            if (isFocusable() && document()->focusedNode() == this)
+                document()->updateFocusAppearanceSoon(false /* don't restore selection */);
+            data->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
+        }
+    }
+}
+
+void Element::unregisterNamedFlowContentNode()
+{
+    if (RuntimeEnabledFeatures::cssRegionsEnabled() && inNamedFlow() && document()->renderView())
+        document()->renderView()->flowThreadController()->unregisterNamedFlowContentNode(this);
+}
+
+void Element::detach()
+{
+    WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
+    unregisterNamedFlowContentNode();
+    cancelFocusAppearanceUpdate();
+    if (hasRareData()) {
+        ElementRareData* data = elementRareData();
+        data->setPseudoElement(BEFORE, 0);
+        data->setPseudoElement(AFTER, 0);
+        data->setIsInCanvasSubtree(false);
+        data->resetComputedStyle();
+        data->resetDynamicRestyleObservations();
+    }
+
+    if (ElementShadow* shadow = this->shadow()) {
+        detachChildrenIfNeeded();
+        shadow->detach();
+    }
+    ContainerNode::detach();
+}
+
+bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle)
+{
+    ASSERT(currentStyle == renderStyle());
+    ASSERT(renderer());
+
+    if (!currentStyle)
+        return false;
+
+    const PseudoStyleCache* pseudoStyleCache = currentStyle->cachedPseudoStyles();
+    if (!pseudoStyleCache)
+        return false;
+
+    size_t cacheSize = pseudoStyleCache->size();
+    for (size_t i = 0; i < cacheSize; ++i) {
+        RefPtr<RenderStyle> newPseudoStyle;
+        PseudoId pseudoId = pseudoStyleCache->at(i)->styleType();
+        if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
+            newPseudoStyle = renderer()->uncachedFirstLineStyle(newStyle);
+        else
+            newPseudoStyle = renderer()->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId), newStyle, newStyle);
+        if (!newPseudoStyle)
+            return true;
+        if (*newPseudoStyle != *pseudoStyleCache->at(i)) {
+            if (pseudoId < FIRST_INTERNAL_PSEUDOID)
+                newStyle->setHasPseudoStyle(pseudoId);
+            newStyle->addCachedPseudoStyle(newPseudoStyle);
+            if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) {
+                // FIXME: We should do an actual diff to determine whether a repaint vs. layout
+                // is needed, but for now just assume a layout will be required.  The diff code
+                // in RenderObject::setStyle would need to be factored out so that it could be reused.
+                renderer()->setNeedsLayoutAndPrefWidthsRecalc();
+            }
+            return true;
+        }
+    }
+    return false;
+}
+
+PassRefPtr<RenderStyle> Element::styleForRenderer()
+{
+    if (hasCustomStyleCallbacks()) {
+        if (RefPtr<RenderStyle> style = customStyleForRenderer())
+            return style.release();
+    }
+
+    return document()->styleResolver()->styleForElement(this);
+}
+
+void Element::recalcStyle(StyleChange change)
+{
+    if (hasCustomStyleCallbacks())
+        willRecalcStyle(change);
+
+    // Ref currentStyle in case it would otherwise be deleted when setting the new style in the renderer.
+    RefPtr<RenderStyle> currentStyle(renderStyle());
+    bool hasParentStyle = parentNodeForRenderingAndStyle() ? static_cast<bool>(parentNodeForRenderingAndStyle()->renderStyle()) : false;
+    bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules();
+    bool hasIndirectAdjacentRules = childrenAffectedByForwardPositionalRules();
+
+    if ((change > NoChange || needsStyleRecalc())) {
+        if (hasRareData())
+            elementRareData()->resetComputedStyle();
+    }
+    if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) {
+        StyleChange localChange = Detach;
+        RefPtr<RenderStyle> newStyle;
+        if (currentStyle) {
+            // FIXME: This still recalcs style twice when changing display types, but saves
+            // us from recalcing twice when going from none -> anything else which is more
+            // common, especially during lazy attach.
+            newStyle = styleForRenderer();
+            localChange = Node::diff(currentStyle.get(), newStyle.get(), document());
+        }
+        if (localChange == Detach) {
+            // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along.
+            reattach();
+            // attach recalculates the style for all children. No need to do it twice.
+            clearNeedsStyleRecalc();
+            clearChildNeedsStyleRecalc();
+
+            if (hasCustomStyleCallbacks())
+                didRecalcStyle(change);
+            return;
+        }
+
+        if (RenderObject* renderer = this->renderer()) {
+            if (localChange != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get()) || (change == Force && renderer->requiresForcedStyleRecalcPropagation()) || styleChangeType() == SyntheticStyleChange)
+                renderer->setAnimatableStyle(newStyle.get());
+            else if (needsStyleRecalc()) {
+                // Although no change occurred, we use the new style so that the cousin style sharing code won't get
+                // fooled into believing this style is the same.
+                renderer->setStyleInternal(newStyle.get());
+            }
+        }
+
+        // If "rem" units are used anywhere in the document, and if the document element's font size changes, then go ahead and force font updating
+        // all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway).
+        if (document()->styleSheetCollection()->usesRemUnits() && document()->documentElement() == this && localChange != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) {
+            // Cached RenderStyles may depend on the re units.
+            document()->styleResolver()->invalidateMatchedPropertiesCache();
+            change = Force;
+        }
+
+        if (change != Force) {
+            if (styleChangeType() >= FullStyleChange)
+                change = Force;
+            else
+                change = localChange;
+        }
+    }
+    StyleResolverParentPusher parentPusher(this);
+
+    // FIXME: This does not care about sibling combinators. Will be necessary in XBL2 world.
+    if (ElementShadow* shadow = this->shadow()) {
+        if (shouldRecalcStyle(change, shadow)) {
+            parentPusher.push();
+            shadow->recalcStyle(change);
+        }
+    }
+
+    if (shouldRecalcStyle(change, this))
+        updatePseudoElement(BEFORE, change);
+
+    // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
+    // For now we will just worry about the common case, since it's a lot trickier to get the second case right
+    // without doing way too much re-resolution.
+    bool forceCheckOfNextElementSibling = false;
+    bool forceCheckOfAnyElementSibling = false;
+    for (Node *n = firstChild(); n; n = n->nextSibling()) {
+        if (n->isTextNode()) {
+            toText(n)->recalcTextStyle(change);
+            continue;
+        } 
+        if (!n->isElementNode()) 
+            continue;
+        Element* element = toElement(n);
+        bool childRulesChanged = element->needsStyleRecalc() && element->styleChangeType() == FullStyleChange;
+        if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling))
+            element->setNeedsStyleRecalc();
+        if (shouldRecalcStyle(change, element)) {
+            parentPusher.push();
+            element->recalcStyle(change);
+        }
+        forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
+        forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);
+    }
+
+    if (shouldRecalcStyle(change, this))
+        updatePseudoElement(AFTER, change);
+
+    clearNeedsStyleRecalc();
+    clearChildNeedsStyleRecalc();
+    
+    if (hasCustomStyleCallbacks())
+        didRecalcStyle(change);
+    InspectorInstrumentation::didRecalculateStyleForElement(this);
+}
+
+ElementShadow* Element::shadow() const
+{
+    return hasRareData() ? elementRareData()->shadow() : 0;
+}
+
+ElementShadow* Element::ensureShadow()
+{
+    return ensureElementRareData()->ensureShadow();
+}
+
+void Element::didAffectSelector(AffectedSelectorMask mask)
+{
+    setNeedsStyleRecalc();
+    if (ElementShadow* elementShadow = shadowOfParentForDistribution(this))
+        elementShadow->didAffectSelector(mask);
+}
+
+PassRefPtr<ShadowRoot> Element::createShadowRoot(ExceptionCode& ec)
+{
+    if (alwaysCreateUserAgentShadowRoot())
+        ensureUserAgentShadowRoot();
+
+    if (RuntimeEnabledFeatures::authorShadowDOMForAnyElementEnabled())
+        return ensureShadow()->addShadowRoot(this, ShadowRoot::AuthorShadowRoot);
+
+    // Since some elements recreates shadow root dynamically, multiple shadow
+    // subtrees won't work well in that element. Until they are fixed, we disable
+    // adding author shadow root for them.
+    if (!areAuthorShadowsAllowed()) {
+        ec = HIERARCHY_REQUEST_ERR;
+        return 0;
+    }
+    return ensureShadow()->addShadowRoot(this, ShadowRoot::AuthorShadowRoot);
+}
+
+ShadowRoot* Element::shadowRoot() const
+{
+    ElementShadow* elementShadow = shadow();
+    if (!elementShadow)
+        return 0;
+    ShadowRoot* shadowRoot = elementShadow->youngestShadowRoot();
+    if (shadowRoot->type() == ShadowRoot::AuthorShadowRoot)
+        return shadowRoot;
+    return 0;
+}
+
+ShadowRoot* Element::userAgentShadowRoot() const
+{
+    if (ElementShadow* elementShadow = shadow()) {
+        if (ShadowRoot* shadowRoot = elementShadow->oldestShadowRoot()) {
+            ASSERT(shadowRoot->type() == ShadowRoot::UserAgentShadowRoot);
+            return shadowRoot;
+        }
+    }
+
+    return 0;
+}
+
+ShadowRoot* Element::ensureUserAgentShadowRoot()
+{
+    if (ShadowRoot* shadowRoot = userAgentShadowRoot())
+        return shadowRoot;
+    ShadowRoot* shadowRoot = ensureShadow()->addShadowRoot(this, ShadowRoot::UserAgentShadowRoot);
+    didAddUserAgentShadowRoot(shadowRoot);
+    return shadowRoot;
+}
+
+const AtomicString& Element::shadowPseudoId() const
+{
+    return pseudo();
+}
+
+bool Element::childTypeAllowed(NodeType type) const
+{
+    switch (type) {
+    case ELEMENT_NODE:
+    case TEXT_NODE:
+    case COMMENT_NODE:
+    case PROCESSING_INSTRUCTION_NODE:
+    case CDATA_SECTION_NODE:
+    case ENTITY_REFERENCE_NODE:
+        return true;
+    default:
+        break;
+    }
+    return false;
+}
+
+static void checkForEmptyStyleChange(Element* element, RenderStyle* style)
+{
+    if (!style && !element->styleAffectedByEmpty())
+        return;
+
+    if (!style || (element->styleAffectedByEmpty() && (!style->emptyState() || element->hasChildNodes())))
+        element->setNeedsStyleRecalc();
+}
+
+static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback,
+                                        Node* beforeChange, Node* afterChange, int childCountDelta)
+{
+    // :empty selector.
+    checkForEmptyStyleChange(e, style);
+    
+    if (!style || (e->needsStyleRecalc() && e->childrenAffectedByPositionalRules()))
+        return;
+
+    // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
+    // In the DOM case, we only need to do something if |afterChange| is not 0.
+    // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
+    if (e->childrenAffectedByFirstChildRules() && afterChange) {
+        // Find our new first child.
+        Node* newFirstChild = 0;
+        for (newFirstChild = e->firstChild(); newFirstChild && !newFirstChild->isElementNode(); newFirstChild = newFirstChild->nextSibling()) {};
+        
+        // Find the first element node following |afterChange|
+        Node* firstElementAfterInsertion = 0;
+        for (firstElementAfterInsertion = afterChange;
+             firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
+             firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
+        
+        // This is the insert/append case.
+        if (newFirstChild != firstElementAfterInsertion && firstElementAfterInsertion && firstElementAfterInsertion->attached() &&
+            firstElementAfterInsertion->renderStyle() && firstElementAfterInsertion->renderStyle()->firstChildState())
+            firstElementAfterInsertion->setNeedsStyleRecalc();
+            
+        // We also have to handle node removal.
+        if (childCountDelta < 0 && newFirstChild == firstElementAfterInsertion && newFirstChild && (!newFirstChild->renderStyle() || !newFirstChild->renderStyle()->firstChildState()))
+            newFirstChild->setNeedsStyleRecalc();
+    }
+
+    // :last-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
+    // In the DOM case, we only need to do something if |afterChange| is not 0.
+    if (e->childrenAffectedByLastChildRules() && beforeChange) {
+        // Find our new last child.
+        Node* newLastChild = 0;
+        for (newLastChild = e->lastChild(); newLastChild && !newLastChild->isElementNode(); newLastChild = newLastChild->previousSibling()) {};
+        
+        // Find the last element node going backwards from |beforeChange|
+        Node* lastElementBeforeInsertion = 0;
+        for (lastElementBeforeInsertion = beforeChange;
+             lastElementBeforeInsertion && !lastElementBeforeInsertion->isElementNode();
+             lastElementBeforeInsertion = lastElementBeforeInsertion->previousSibling()) {};
+        
+        if (newLastChild != lastElementBeforeInsertion && lastElementBeforeInsertion && lastElementBeforeInsertion->attached() &&
+            lastElementBeforeInsertion->renderStyle() && lastElementBeforeInsertion->renderStyle()->lastChildState())
+            lastElementBeforeInsertion->setNeedsStyleRecalc();
+            
+        // We also have to handle node removal.  The parser callback case is similar to node removal as well in that we need to change the last child
+        // to match now.
+        if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && (!newLastChild->renderStyle() || !newLastChild->renderStyle()->lastChildState()))
+            newLastChild->setNeedsStyleRecalc();
+    }
+
+    // The + selector.  We need to invalidate the first element following the insertion point.  It is the only possible element
+    // that could be affected by this DOM change.
+    if (e->childrenAffectedByDirectAdjacentRules() && afterChange) {
+        Node* firstElementAfterInsertion = 0;
+        for (firstElementAfterInsertion = afterChange;
+             firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
+             firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
+        if (firstElementAfterInsertion && firstElementAfterInsertion->attached())
+            firstElementAfterInsertion->setNeedsStyleRecalc();
+    }
+
+    // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type.
+    // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
+    // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
+    // backward case.
+    // |afterChange| is 0 in the parser callback case, so we won't do any work for the forward case if we don't have to.
+    // For performance reasons we just mark the parent node as changed, since we don't want to make childrenChanged O(n^2) by crawling all our kids
+    // here.  recalcStyle will then force a walk of the children when it sees that this has happened.
+    if ((e->childrenAffectedByForwardPositionalRules() && afterChange)
+        || (e->childrenAffectedByBackwardPositionalRules() && beforeChange))
+        e->setNeedsStyleRecalc();
+}
+
+void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
+{
+    ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
+    if (changedByParser)
+        checkForEmptyStyleChange(this, renderStyle());
+    else
+        checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);
+
+    if (ElementShadow * shadow = this->shadow())
+        shadow->invalidateDistribution();
+}
+
+void Element::removeAllEventListeners()
+{
+    ContainerNode::removeAllEventListeners();
+    if (ElementShadow* shadow = this->shadow())
+        shadow->removeAllEventListeners();
+}
+
+void Element::beginParsingChildren()
+{
+    clearIsParsingChildrenFinished();
+    StyleResolver* styleResolver = document()->styleResolverIfExists();
+    if (styleResolver && attached())
+        styleResolver->pushParentElement(this);
+}
+
+void Element::finishParsingChildren()
+{
+    ContainerNode::finishParsingChildren();
+    setIsParsingChildrenFinished();
+    checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);
+    if (StyleResolver* styleResolver = document()->styleResolverIfExists())
+        styleResolver->popParentElement(this);
+}
+
+#ifndef NDEBUG
+void Element::formatForDebugger(char* buffer, unsigned length) const
+{
+    StringBuilder result;
+    String s;
+
+    result.append(nodeName());
+
+    s = getIdAttribute();
+    if (s.length() > 0) {
+        if (result.length() > 0)
+            result.appendLiteral("; ");
+        result.appendLiteral("id=");
+        result.append(s);
+    }
+
+    s = getAttribute(classAttr);
+    if (s.length() > 0) {
+        if (result.length() > 0)
+            result.appendLiteral("; ");
+        result.appendLiteral("class=");
+        result.append(s);
+    }
+
+    strncpy(buffer, result.toString().utf8().data(), length - 1);
+}
+#endif
+
+const Vector<RefPtr<Attr> >& Element::attrNodeList()
+{
+    ASSERT(hasSyntheticAttrChildNodes());
+    return *attrNodeListForElement(this);
+}
+
+PassRefPtr<Attr> Element::setAttributeNode(Attr* attrNode, ExceptionCode& ec)
+{
+    if (!attrNode) {
+        ec = TYPE_MISMATCH_ERR;
+        return 0;
+    }
+
+    RefPtr<Attr> oldAttrNode = attrIfExists(attrNode->qualifiedName());
+    if (oldAttrNode.get() == attrNode)
+        return attrNode; // This Attr is already attached to the element.
+
+    // INUSE_ATTRIBUTE_ERR: Raised if node is an Attr that is already an attribute of another Element object.
+    // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
+    if (attrNode->ownerElement()) {
+        ec = INUSE_ATTRIBUTE_ERR;
+        return 0;
+    }
+
+    synchronizeAllAttributes();
+    UniqueElementData* elementData = ensureUniqueElementData();
+
+    size_t index = elementData->getAttributeItemIndex(attrNode->qualifiedName());
+    if (index != notFound) {
+        if (oldAttrNode)
+            detachAttrNodeFromElementWithValue(oldAttrNode.get(), elementData->attributeItem(index)->value());
+        else
+            oldAttrNode = Attr::create(document(), attrNode->qualifiedName(), elementData->attributeItem(index)->value());
+    }
+
+    setAttributeInternal(index, attrNode->qualifiedName(), attrNode->value(), NotInSynchronizationOfLazyAttribute);
+
+    attrNode->attachToElement(this);
+    ensureAttrNodeListForElement(this)->append(attrNode);
+
+    return oldAttrNode.release();
+}
+
+PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
+{
+    return setAttributeNode(attr, ec);
+}
+
+PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
+{
+    if (!attr) {
+        ec = TYPE_MISMATCH_ERR;
+        return 0;
+    }
+    if (attr->ownerElement() != this) {
+        ec = NOT_FOUND_ERR;
+        return 0;
+    }
+
+    ASSERT(document() == attr->document());
+
+    synchronizeAttribute(attr->qualifiedName());
+
+    size_t index = elementData()->getAttributeItemIndex(attr->qualifiedName());
+    if (index == notFound) {
+        ec = NOT_FOUND_ERR;
+        return 0;
+    }
+
+    return detachAttribute(index);
+}
+
+bool Element::parseAttributeName(QualifiedName& out, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionCode& ec)
+{
+    String prefix, localName;
+    if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
+        return false;
+    ASSERT(!ec);
+
+    QualifiedName qName(prefix, localName, namespaceURI);
+
+    if (!Document::hasValidNamespaceForAttributes(qName)) {
+        ec = NAMESPACE_ERR;
+        return false;
+    }
+
+    out = qName;
+    return true;
+}
+
+void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec)
+{
+    QualifiedName parsedName = anyName;
+    if (!parseAttributeName(parsedName, namespaceURI, qualifiedName, ec))
+        return;
+    setAttribute(parsedName, value);
+}
+
+void Element::removeAttributeInternal(size_t index, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(index < attributeCount());
+
+    UniqueElementData* elementData = ensureUniqueElementData();
+
+    QualifiedName name = elementData->attributeItem(index)->name();
+    AtomicString valueBeingRemoved = elementData->attributeItem(index)->value();
+
+    if (!inSynchronizationOfLazyAttribute) {
+        if (!valueBeingRemoved.isNull())
+            willModifyAttribute(name, valueBeingRemoved, nullAtom);
+    }
+
+    if (RefPtr<Attr> attrNode = attrIfExists(name))
+        detachAttrNodeFromElementWithValue(attrNode.get(), elementData->attributeItem(index)->value());
+
+    elementData->removeAttribute(index);
+
+    if (!inSynchronizationOfLazyAttribute)
+        didRemoveAttribute(name);
+}
+
+void Element::addAttributeInternal(const QualifiedName& name, const AtomicString& value, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
+{
+    if (!inSynchronizationOfLazyAttribute)
+        willModifyAttribute(name, nullAtom, value);
+    ensureUniqueElementData()->addAttribute(name, value);
+    if (!inSynchronizationOfLazyAttribute)
+        didAddAttribute(name, value);
+}
+
+void Element::removeAttribute(const AtomicString& name)
+{
+    if (!elementData())
+        return;
+
+    AtomicString localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
+    size_t index = elementData()->getAttributeItemIndex(localName, false);
+    if (index == notFound) {
+        if (UNLIKELY(localName == styleAttr) && elementData()->m_styleAttributeIsDirty && isStyledElement())
+            static_cast<StyledElement*>(this)->removeAllInlineStyleProperties();
+        return;
+    }
+
+    removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
+}
+
+void Element::removeAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName)
+{
+    removeAttribute(QualifiedName(nullAtom, localName, namespaceURI));
+}
+
+PassRefPtr<Attr> Element::getAttributeNode(const AtomicString& localName)
+{
+    if (!elementData())
+        return 0;
+    synchronizeAttribute(localName);
+    const Attribute* attribute = elementData()->getAttributeItem(localName, shouldIgnoreAttributeCase(this));
+    if (!attribute)
+        return 0;
+    return ensureAttr(attribute->name());
+}
+
+PassRefPtr<Attr> Element::getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName)
+{
+    if (!elementData())
+        return 0;
+    QualifiedName qName(nullAtom, localName, namespaceURI);
+    synchronizeAttribute(qName);
+    const Attribute* attribute = elementData()->getAttributeItem(qName);
+    if (!attribute)
+        return 0;
+    return ensureAttr(attribute->name());
+}
+
+bool Element::hasAttribute(const AtomicString& localName) const
+{
+    if (!elementData())
+        return false;
+    synchronizeAttribute(localName);
+    return elementData()->getAttributeItem(shouldIgnoreAttributeCase(this) ? localName.lower() : localName, false);
+}
+
+bool Element::hasAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const
+{
+    if (!elementData())
+        return false;
+    QualifiedName qName(nullAtom, localName, namespaceURI);
+    synchronizeAttribute(qName);
+    return elementData()->getAttributeItem(qName);
+}
+
+CSSStyleDeclaration *Element::style()
+{
+    return 0;
+}
+
+void Element::focus(bool restorePreviousSelection, FocusDirection direction)
+{
+    if (!inDocument())
+        return;
+
+    Document* doc = document();
+    if (doc->focusedNode() == this)
+        return;
+
+    // If the stylesheets have already been loaded we can reliably check isFocusable.
+    // If not, we continue and set the focused node on the focus controller below so
+    // that it can be updated soon after attach. 
+    if (doc->haveStylesheetsLoaded()) {
+        doc->updateLayoutIgnorePendingStylesheets();
+        if (!isFocusable())
+            return;
+    }
+
+    if (!supportsFocus())
+        return;
+
+    RefPtr<Node> protect;
+    if (Page* page = doc->page()) {
+        // Focus and change event handlers can cause us to lose our last ref.
+        // If a focus event handler changes the focus to a different node it
+        // does not make sense to continue and update appearence.
+        protect = this;
+        if (!page->focusController()->setFocusedNode(this, doc->frame(), direction))
+            return;
+    }
+
+    // Setting the focused node above might have invalidated the layout due to scripts.
+    doc->updateLayoutIgnorePendingStylesheets();
+
+    if (!isFocusable()) {
+        ensureElementRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(true);
+        return;
+    }
+        
+    cancelFocusAppearanceUpdate();
+    updateFocusAppearance(restorePreviousSelection);
+}
+
+void Element::updateFocusAppearance(bool /*restorePreviousSelection*/)
+{
+    if (isRootEditableElement()) {
+        Frame* frame = document()->frame();
+        if (!frame)
+            return;
+        
+        // When focusing an editable element in an iframe, don't reset the selection if it already contains a selection.
+        if (this == frame->selection()->rootEditableElement())
+            return;
+
+        // FIXME: We should restore the previous selection if there is one.
+        VisibleSelection newSelection = VisibleSelection(firstPositionInOrBeforeNode(this), DOWNSTREAM);
+        
+        if (frame->selection()->shouldChangeSelection(newSelection)) {
+            frame->selection()->setSelection(newSelection);
+            frame->selection()->revealSelection();
+        }
+    } else if (renderer() && !renderer()->isWidget())
+        renderer()->scrollRectToVisible(boundingBox());
+}
+
+void Element::blur()
+{
+    cancelFocusAppearanceUpdate();
+    Document* doc = document();
+    if (treeScope()->focusedNode() == this) {
+        if (doc->frame())
+            doc->frame()->page()->focusController()->setFocusedNode(0, doc->frame());
+        else
+            doc->setFocusedNode(0);
+    }
+}
+
+String Element::innerText()
+{
+    // We need to update layout, since plainText uses line boxes in the render tree.
+    document()->updateLayoutIgnorePendingStylesheets();
+
+    if (!renderer())
+        return textContent(true);
+
+    return plainText(rangeOfContents(const_cast<Element*>(this)).get());
+}
+
+String Element::outerText()
+{
+    // Getting outerText is the same as getting innerText, only
+    // setting is different. You would think this should get the plain
+    // text for the outer range, but this is wrong, <br> for instance
+    // would return different values for inner and outer text by such
+    // a rule, but it doesn't in WinIE, and we want to match that.
+    return innerText();
+}
+
+String Element::title() const
+{
+    return String();
+}
+
+const AtomicString& Element::pseudo() const
+{
+    return getAttribute(pseudoAttr);
+}
+
+void Element::setPseudo(const AtomicString& value)
+{
+    setAttribute(pseudoAttr, value);
+}
+
+LayoutSize Element::minimumSizeForResizing() const
+{
+    return hasRareData() ? elementRareData()->minimumSizeForResizing() : defaultMinimumSizeForResizing();
+}
+
+void Element::setMinimumSizeForResizing(const LayoutSize& size)
+{
+    if (!hasRareData() && size == defaultMinimumSizeForResizing())
+        return;
+    ensureElementRareData()->setMinimumSizeForResizing(size);
+}
+
+RenderStyle* Element::computedStyle(PseudoId pseudoElementSpecifier)
+{
+    if (PseudoElement* element = pseudoElement(pseudoElementSpecifier))
+        return element->computedStyle();
+
+    // FIXME: Find and use the renderer from the pseudo element instead of the actual element so that the 'length'
+    // properties, which are only known by the renderer because it did the layout, will be correct and so that the
+    // values returned for the ":selection" pseudo-element will be correct.
+    if (RenderStyle* usedStyle = renderStyle()) {
+        if (pseudoElementSpecifier) {
+            RenderStyle* cachedPseudoStyle = usedStyle->getCachedPseudoStyle(pseudoElementSpecifier);
+            return cachedPseudoStyle ? cachedPseudoStyle : usedStyle;
+         } else
+            return usedStyle;
+    }
+
+    if (!attached())
+        // FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
+        // document tree and figure out when to destroy the computed style for such elements.
+        return 0;
+
+    ElementRareData* data = ensureElementRareData();
+    if (!data->computedStyle())
+        data->setComputedStyle(document()->styleForElementIgnoringPendingStylesheets(this));
+    return pseudoElementSpecifier ? data->computedStyle()->getCachedPseudoStyle(pseudoElementSpecifier) : data->computedStyle();
+}
+
+void Element::setStyleAffectedByEmpty()
+{
+    ensureElementRareData()->setStyleAffectedByEmpty(true);
+}
+
+void Element::setChildrenAffectedByHover(bool value)
+{
+    if (value || hasRareData())
+        ensureElementRareData()->setChildrenAffectedByHover(value);
+}
+
+void Element::setChildrenAffectedByActive(bool value)
+{
+    if (value || hasRareData())
+        ensureElementRareData()->setChildrenAffectedByActive(value);
+}
+
+void Element::setChildrenAffectedByDrag(bool value)
+{
+    if (value || hasRareData())
+        ensureElementRareData()->setChildrenAffectedByDrag(value);
+}
+
+void Element::setChildrenAffectedByFirstChildRules()
+{
+    ensureElementRareData()->setChildrenAffectedByFirstChildRules(true);
+}
+
+void Element::setChildrenAffectedByLastChildRules()
+{
+    ensureElementRareData()->setChildrenAffectedByLastChildRules(true);
+}
+
+void Element::setChildrenAffectedByDirectAdjacentRules()
+{
+    ensureElementRareData()->setChildrenAffectedByDirectAdjacentRules(true);
+}
+
+void Element::setChildrenAffectedByForwardPositionalRules()
+{
+    ensureElementRareData()->setChildrenAffectedByForwardPositionalRules(true);
+}
+
+void Element::setChildrenAffectedByBackwardPositionalRules()
+{
+    ensureElementRareData()->setChildrenAffectedByBackwardPositionalRules(true);
+}
+
+void Element::setChildIndex(unsigned index)
+{
+    ElementRareData* rareData = ensureElementRareData();
+    if (RenderStyle* style = renderStyle())
+        style->setUnique();
+    rareData->setChildIndex(index);
+}
+
+bool Element::hasFlagsSetDuringStylingOfChildren() const
+{
+    if (!hasRareData())
+        return false;
+    return rareDataChildrenAffectedByHover()
+        || rareDataChildrenAffectedByActive()
+        || rareDataChildrenAffectedByDrag()
+        || rareDataChildrenAffectedByFirstChildRules()
+        || rareDataChildrenAffectedByLastChildRules()
+        || rareDataChildrenAffectedByDirectAdjacentRules()
+        || rareDataChildrenAffectedByForwardPositionalRules()
+        || rareDataChildrenAffectedByBackwardPositionalRules();
+}
+
+bool Element::rareDataStyleAffectedByEmpty() const
+{
+    ASSERT(hasRareData());
+    return elementRareData()->styleAffectedByEmpty();
+}
+
+bool Element::rareDataChildrenAffectedByHover() const
+{
+    ASSERT(hasRareData());
+    return elementRareData()->childrenAffectedByHover();
+}
+
+bool Element::rareDataChildrenAffectedByActive() const
+{
+    ASSERT(hasRareData());
+    return elementRareData()->childrenAffectedByActive();
+}
+
+bool Element::rareDataChildrenAffectedByDrag() const
+{
+    ASSERT(hasRareData());
+    return elementRareData()->childrenAffectedByDrag();
+}
+
+bool Element::rareDataChildrenAffectedByFirstChildRules() const
+{
+    ASSERT(hasRareData());
+    return elementRareData()->childrenAffectedByFirstChildRules();
+}
+
+bool Element::rareDataChildrenAffectedByLastChildRules() const
+{
+    ASSERT(hasRareData());
+    return elementRareData()->childrenAffectedByLastChildRules();
+}
+
+bool Element::rareDataChildrenAffectedByDirectAdjacentRules() const
+{
+    ASSERT(hasRareData());
+    return elementRareData()->childrenAffectedByDirectAdjacentRules();
+}
+
+bool Element::rareDataChildrenAffectedByForwardPositionalRules() const
+{
+    ASSERT(hasRareData());
+    return elementRareData()->childrenAffectedByForwardPositionalRules();
+}
+
+bool Element::rareDataChildrenAffectedByBackwardPositionalRules() const
+{
+    ASSERT(hasRareData());
+    return elementRareData()->childrenAffectedByBackwardPositionalRules();
+}
+
+unsigned Element::rareDataChildIndex() const
+{
+    ASSERT(hasRareData());
+    return elementRareData()->childIndex();
+}
+
+void Element::setIsInCanvasSubtree(bool isInCanvasSubtree)
+{
+    ensureElementRareData()->setIsInCanvasSubtree(isInCanvasSubtree);
+}
+
+bool Element::isInCanvasSubtree() const
+{
+    return hasRareData() && elementRareData()->isInCanvasSubtree();
+}
+
+bool Element::isUnresolvedCustomElement()
+{
+    return isCustomElement() && document()->registry()->isUnresolved(this);
+}
+
+AtomicString Element::computeInheritedLanguage() const
+{
+    const Node* n = this;
+    AtomicString value;
+    // The language property is inherited, so we iterate over the parents to find the first language.
+    do {
+        if (n->isElementNode()) {
+            if (const ElementData* elementData = toElement(n)->elementData()) {
+                // Spec: xml:lang takes precedence -- http://www.w3.org/TR/xhtml1/#C_7
+                if (const Attribute* attribute = elementData->getAttributeItem(XMLNames::langAttr))
+                    value = attribute->value();
+                else if (const Attribute* attribute = elementData->getAttributeItem(HTMLNames::langAttr))
+                    value = attribute->value();
+            }
+        } else if (n->isDocumentNode()) {
+            // checking the MIME content-language
+            value = toDocument(n)->contentLanguage();
+        }
+
+        n = n->parentNode();
+    } while (n && value.isNull());
+
+    return value;
+}
+
+Locale& Element::locale() const
+{
+    return document()->getCachedLocale(computeInheritedLanguage());
+}
+
+void Element::cancelFocusAppearanceUpdate()
+{
+    if (hasRareData())
+        elementRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
+    if (document()->focusedNode() == this)
+        document()->cancelFocusAppearanceUpdate();
+}
+
+void Element::normalizeAttributes()
+{
+    if (!hasAttributes())
+        return;
+    for (unsigned i = 0; i < attributeCount(); ++i) {
+        if (RefPtr<Attr> attr = attrIfExists(attributeItem(i)->name()))
+            attr->normalize();
+    }
+}
+
+void Element::updatePseudoElement(PseudoId pseudoId, StyleChange change)
+{
+    PseudoElement* element = pseudoElement(pseudoId);
+    if (element && (needsStyleRecalc() || shouldRecalcStyle(change, element))) {
+        // PseudoElement styles hang off their parent element's style so if we needed
+        // a style recalc we should Force one on the pseudo.
+        element->recalcStyle(needsStyleRecalc() ? Force : change);
+
+        // Wait until our parent is not displayed or pseudoElementRendererIsNeeded
+        // is false, otherwise we could continously create and destroy PseudoElements
+        // when RenderObject::isChildAllowed on our parent returns false for the
+        // PseudoElement's renderer for each style recalc.
+        if (!renderer() || !pseudoElementRendererIsNeeded(renderer()->getCachedPseudoStyle(pseudoId)))
+            setPseudoElement(pseudoId, 0);
+    } else if (change >= Inherit || needsStyleRecalc())
+        createPseudoElementIfNeeded(pseudoId);
+}
+
+void Element::createPseudoElementIfNeeded(PseudoId pseudoId)
+{
+    if (!document()->styleSheetCollection()->usesBeforeAfterRules())
+        return;
+
+    if (!renderer() || !pseudoElementRendererIsNeeded(renderer()->getCachedPseudoStyle(pseudoId)))
+        return;
+
+    if (!renderer()->canHaveGeneratedChildren())
+        return;
+
+    ASSERT(!isPseudoElement());
+    RefPtr<PseudoElement> element = PseudoElement::create(this, pseudoId);
+    element->attach();
+    setPseudoElement(pseudoId, element.release());
+}
+
+bool Element::hasPseudoElements() const
+{
+    return hasRareData() && elementRareData()->hasPseudoElements();
+}
+
+PseudoElement* Element::pseudoElement(PseudoId pseudoId) const
+{
+    return hasRareData() ? elementRareData()->pseudoElement(pseudoId) : 0;
+}
+
+void Element::setPseudoElement(PseudoId pseudoId, PassRefPtr<PseudoElement> element)
+{
+    ensureElementRareData()->setPseudoElement(pseudoId, element);
+    resetNeedsShadowTreeWalker();
+}
+
+RenderObject* Element::pseudoElementRenderer(PseudoId pseudoId) const
+{
+    if (PseudoElement* element = pseudoElement(pseudoId))
+        return element->renderer();
+    return 0;
+}
+
+// ElementTraversal API
+Element* Element::firstElementChild() const
+{
+    return ElementTraversal::firstWithin(this);
+}
+
+Element* Element::lastElementChild() const
+{
+    Node* n = lastChild();
+    while (n && !n->isElementNode())
+        n = n->previousSibling();
+    return toElement(n);
+}
+
+unsigned Element::childElementCount() const
+{
+    unsigned count = 0;
+    Node* n = firstChild();
+    while (n) {
+        count += n->isElementNode();
+        n = n->nextSibling();
+    }
+    return count;
+}
+
+bool Element::matchesReadOnlyPseudoClass() const
+{
+    return false;
+}
+
+bool Element::matchesReadWritePseudoClass() const
+{
+    return false;
+}
+
+bool Element::webkitMatchesSelector(const String& selector, ExceptionCode& ec)
+{
+    if (selector.isEmpty()) {
+        ec = SYNTAX_ERR;
+        return false;
+    }
+
+    SelectorQuery* selectorQuery = document()->selectorQueryCache()->add(selector, document(), ec);
+    if (!selectorQuery)
+        return false;
+    return selectorQuery->matches(this);
+}
+
+bool Element::shouldAppearIndeterminate() const
+{
+    return false;
+}
+
+DOMTokenList* Element::classList()
+{
+    ElementRareData* data = ensureElementRareData();
+    if (!data->classList())
+        data->setClassList(ClassList::create(this));
+    return data->classList();
+}
+
+DOMStringMap* Element::dataset()
+{
+    ElementRareData* data = ensureElementRareData();
+    if (!data->dataset())
+        data->setDataset(DatasetDOMStringMap::create(this));
+    return data->dataset();
+}
+
+KURL Element::getURLAttribute(const QualifiedName& name) const
+{
+#if !ASSERT_DISABLED
+    if (elementData()) {
+        if (const Attribute* attribute = getAttributeItem(name))
+            ASSERT(isURLAttribute(*attribute));
+    }
+#endif
+    return document()->completeURL(stripLeadingAndTrailingHTMLSpaces(getAttribute(name)));
+}
+
+KURL Element::getNonEmptyURLAttribute(const QualifiedName& name) const
+{
+#if !ASSERT_DISABLED
+    if (elementData()) {
+        if (const Attribute* attribute = getAttributeItem(name))
+            ASSERT(isURLAttribute(*attribute));
+    }
+#endif
+    String value = stripLeadingAndTrailingHTMLSpaces(getAttribute(name));
+    if (value.isEmpty())
+        return KURL();
+    return document()->completeURL(value);
+}
+
+int Element::getIntegralAttribute(const QualifiedName& attributeName) const
+{
+    return getAttribute(attributeName).string().toInt();
+}
+
+void Element::setIntegralAttribute(const QualifiedName& attributeName, int value)
+{
+    // FIXME: Need an AtomicString version of String::number.
+    setAttribute(attributeName, String::number(value));
+}
+
+unsigned Element::getUnsignedIntegralAttribute(const QualifiedName& attributeName) const
+{
+    return getAttribute(attributeName).string().toUInt();
+}
+
+void Element::setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value)
+{
+    // FIXME: Need an AtomicString version of String::number.
+    setAttribute(attributeName, String::number(value));
+}
+
+#if ENABLE(SVG)
+bool Element::childShouldCreateRenderer(const NodeRenderingContext& childContext) const
+{
+    // Only create renderers for SVG elements whose parents are SVG elements, or for proper <svg xmlns="svgNS"> subdocuments.
+    if (childContext.node()->isSVGElement())
+        return childContext.node()->hasTagName(SVGNames::svgTag) || isSVGElement();
+
+    return ContainerNode::childShouldCreateRenderer(childContext);
+}
+#endif
+
+void Element::webkitRequestFullscreen()
+{
+    document()->requestFullScreenForElement(this, ALLOW_KEYBOARD_INPUT, Document::EnforceIFrameAllowFullScreenRequirement);
+}
+
+void Element::webkitRequestFullScreen(unsigned short flags)
+{
+    document()->requestFullScreenForElement(this, (flags | LEGACY_MOZILLA_REQUEST), Document::EnforceIFrameAllowFullScreenRequirement);
+}
+
+bool Element::containsFullScreenElement() const
+{
+    return hasRareData() && elementRareData()->containsFullScreenElement();
+}
+
+void Element::setContainsFullScreenElement(bool flag)
+{
+    ensureElementRareData()->setContainsFullScreenElement(flag);
+    setNeedsStyleRecalc(SyntheticStyleChange);
+}
+
+static Element* parentCrossingFrameBoundaries(Element* element)
+{
+    ASSERT(element);
+    return element->parentElement() ? element->parentElement() : element->document()->ownerElement();
+}
+
+void Element::setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool flag)
+{
+    Element* element = this;
+    while ((element = parentCrossingFrameBoundaries(element)))
+        element->setContainsFullScreenElement(flag);
+}
+
+bool Element::isInTopLayer() const
+{
+    return hasRareData() && elementRareData()->isInTopLayer();
+}
+
+void Element::setIsInTopLayer(bool inTopLayer)
+{
+    if (isInTopLayer() == inTopLayer)
+        return;
+    ensureElementRareData()->setIsInTopLayer(inTopLayer);
+
+    // We must ensure a reattach occurs so the renderer is inserted in the correct sibling order under RenderView according to its
+    // top layer position, or in its usual place if not in the top layer.
+    reattachIfAttached();
+}
+
+void Element::webkitRequestPointerLock()
+{
+    if (document()->page())
+        document()->page()->pointerLockController()->requestPointerLock(this);
+}
+
+SpellcheckAttributeState Element::spellcheckAttributeState() const
+{
+    const AtomicString& value = getAttribute(HTMLNames::spellcheckAttr);
+    if (value == nullAtom)
+        return SpellcheckAttributeDefault;
+    if (equalIgnoringCase(value, "true") || equalIgnoringCase(value, ""))
+        return SpellcheckAttributeTrue;
+    if (equalIgnoringCase(value, "false"))
+        return SpellcheckAttributeFalse;
+
+    return SpellcheckAttributeDefault;
+}
+
+bool Element::isSpellCheckingEnabled() const
+{
+    for (const Element* element = this; element; element = element->parentOrShadowHostElement()) {
+        switch (element->spellcheckAttributeState()) {
+        case SpellcheckAttributeTrue:
+            return true;
+        case SpellcheckAttributeFalse:
+            return false;
+        case SpellcheckAttributeDefault:
+            break;
+        }
+    }
+
+    return true;
+}
+
+RenderRegion* Element::renderRegion() const
+{
+    if (renderer() && renderer()->isRenderRegion())
+        return toRenderRegion(renderer());
+
+    return 0;
+}
+
+const AtomicString& Element::webkitRegionOverset() const
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+
+    DEFINE_STATIC_LOCAL(AtomicString, undefinedState, ("undefined", AtomicString::ConstructFromLiteral));
+    if (!RuntimeEnabledFeatures::cssRegionsEnabled() || !renderRegion())
+        return undefinedState;
+
+    switch (renderRegion()->regionState()) {
+    case RenderRegion::RegionFit: {
+        DEFINE_STATIC_LOCAL(AtomicString, fitState, ("fit", AtomicString::ConstructFromLiteral));
+        return fitState;
+    }
+    case RenderRegion::RegionEmpty: {
+        DEFINE_STATIC_LOCAL(AtomicString, emptyState, ("empty", AtomicString::ConstructFromLiteral));
+        return emptyState;
+    }
+    case RenderRegion::RegionOverset: {
+        DEFINE_STATIC_LOCAL(AtomicString, overflowState, ("overset", AtomicString::ConstructFromLiteral));
+        return overflowState;
+    }
+    case RenderRegion::RegionUndefined:
+        return undefinedState;
+    }
+
+    ASSERT_NOT_REACHED();
+    return undefinedState;
+}
+
+Vector<RefPtr<Range> > Element::webkitGetRegionFlowRanges() const
+{
+    document()->updateLayoutIgnorePendingStylesheets();
+
+    Vector<RefPtr<Range> > rangeObjects;
+    if (RuntimeEnabledFeatures::cssRegionsEnabled() && renderer() && renderer()->isRenderRegion()) {
+        RenderRegion* region = toRenderRegion(renderer());
+        if (region->isValid())
+            region->getRanges(rangeObjects);
+    }
+
+    return rangeObjects;
+}
+
+#ifndef NDEBUG
+bool Element::fastAttributeLookupAllowed(const QualifiedName& name) const
+{
+    if (name == HTMLNames::styleAttr)
+        return false;
+
+#if ENABLE(SVG)
+    if (isSVGElement())
+        return !static_cast<const SVGElement*>(this)->isAnimatableAttribute(name);
+#endif
+
+    return true;
+}
+#endif
+
+#ifdef DUMP_NODE_STATISTICS
+bool Element::hasNamedNodeMap() const
+{
+    return hasRareData() && elementRareData()->attributeMap();
+}
+#endif
+
+inline void Element::updateName(const AtomicString& oldName, const AtomicString& newName)
+{
+    if (!inDocument() || isInShadowTree())
+        return;
+
+    if (oldName == newName)
+        return;
+
+    if (shouldRegisterAsNamedItem())
+        updateNamedItemRegistration(oldName, newName);
+}
+
+inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
+{
+    if (!isInTreeScope())
+        return;
+
+    if (oldId == newId)
+        return;
+
+    updateId(treeScope(), oldId, newId);
+}
+
+inline void Element::updateId(TreeScope* scope, const AtomicString& oldId, const AtomicString& newId)
+{
+    ASSERT(isInTreeScope());
+    ASSERT(oldId != newId);
+
+    if (!oldId.isEmpty())
+        scope->removeElementById(oldId, this);
+    if (!newId.isEmpty())
+        scope->addElementById(newId, this);
+
+    if (shouldRegisterAsExtraNamedItem())
+        updateExtraNamedItemRegistration(oldId, newId);
+}
+
+void Element::updateLabel(TreeScope* scope, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue)
+{
+    ASSERT(hasTagName(labelTag));
+
+    if (!inDocument())
+        return;
+
+    if (oldForAttributeValue == newForAttributeValue)
+        return;
+
+    if (!oldForAttributeValue.isEmpty())
+        scope->removeLabel(oldForAttributeValue, static_cast<HTMLLabelElement*>(this));
+    if (!newForAttributeValue.isEmpty())
+        scope->addLabel(newForAttributeValue, static_cast<HTMLLabelElement*>(this));
+}
+
+void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
+{
+    if (isIdAttributeName(name))
+        updateId(oldValue, newValue);
+    else if (name == HTMLNames::nameAttr)
+        updateName(oldValue, newValue);
+    else if (name == HTMLNames::forAttr && hasTagName(labelTag)) {
+        TreeScope* scope = treeScope();
+        if (scope->shouldCacheLabelsByForAttribute())
+            updateLabel(scope, oldValue, newValue);
+    }
+
+    if (oldValue != newValue) {
+        if (attached() && document()->styleResolver() && document()->styleResolver()->hasSelectorForAttribute(name.localName()))
+           setNeedsStyleRecalc();
+    }
+
+    if (OwnPtr<MutationObserverInterestGroup> recipients = MutationObserverInterestGroup::createForAttributesMutation(this, name))
+        recipients->enqueueMutationRecord(MutationRecord::createAttributes(this, name, oldValue));
+
+    InspectorInstrumentation::willModifyDOMAttr(document(), this, oldValue, newValue);
+}
+
+void Element::didAddAttribute(const QualifiedName& name, const AtomicString& value)
+{
+    attributeChanged(name, value);
+    InspectorInstrumentation::didModifyDOMAttr(document(), this, name.localName(), value);
+    dispatchSubtreeModifiedEvent();
+}
+
+void Element::didModifyAttribute(const QualifiedName& name, const AtomicString& value)
+{
+    attributeChanged(name, value);
+    InspectorInstrumentation::didModifyDOMAttr(document(), this, name.localName(), value);
+    // Do not dispatch a DOMSubtreeModified event here; see bug 81141.
+}
+
+void Element::didRemoveAttribute(const QualifiedName& name)
+{
+    attributeChanged(name, nullAtom);
+    InspectorInstrumentation::didRemoveDOMAttr(document(), this, name.localName());
+    dispatchSubtreeModifiedEvent();
+}
+
+
+void Element::updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName)
+{
+    if (!document()->isHTMLDocument())
+        return;
+
+    if (!oldName.isEmpty())
+        toHTMLDocument(document())->removeNamedItem(oldName);
+
+    if (!newName.isEmpty())
+        toHTMLDocument(document())->addNamedItem(newName);
+}
+
+void Element::updateExtraNamedItemRegistration(const AtomicString& oldId, const AtomicString& newId)
+{
+    if (!document()->isHTMLDocument())
+        return;
+
+    if (!oldId.isEmpty())
+        toHTMLDocument(document())->removeExtraNamedItem(oldId);
+
+    if (!newId.isEmpty())
+        toHTMLDocument(document())->addExtraNamedItem(newId);
+}
+
+PassRefPtr<HTMLCollection> Element::ensureCachedHTMLCollection(CollectionType type)
+{
+    if (HTMLCollection* collection = cachedHTMLCollection(type))
+        return collection;
+
+    RefPtr<HTMLCollection> collection;
+    if (type == TableRows) {
+        ASSERT(hasTagName(tableTag));
+        return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLTableRowsCollection>(this, type);
+    } else if (type == SelectOptions) {
+        ASSERT(hasTagName(selectTag));
+        return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLOptionsCollection>(this, type);
+    } else if (type == FormControls) {
+        ASSERT(hasTagName(formTag) || hasTagName(fieldsetTag));
+        return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLFormControlsCollection>(this, type);
+    }
+    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLCollection>(this, type);
+}
+
+HTMLCollection* Element::cachedHTMLCollection(CollectionType type)
+{
+    return hasRareData() && rareData()->nodeLists() ? rareData()->nodeLists()->cacheWithAtomicName<HTMLCollection>(type) : 0;
+}
+
+IntSize Element::savedLayerScrollOffset() const
+{
+    return hasRareData() ? elementRareData()->savedLayerScrollOffset() : IntSize();
+}
+
+void Element::setSavedLayerScrollOffset(const IntSize& size)
+{
+    if (size.isZero() && !hasRareData())
+        return;
+    ensureElementRareData()->setSavedLayerScrollOffset(size);
+}
+
+PassRefPtr<Attr> Element::attrIfExists(const QualifiedName& name)
+{
+    if (AttrNodeList* attrNodeList = attrNodeListForElement(this))
+        return findAttrNodeInList(attrNodeList, name);
+    return 0;
+}
+
+PassRefPtr<Attr> Element::ensureAttr(const QualifiedName& name)
+{
+    AttrNodeList* attrNodeList = ensureAttrNodeListForElement(this);
+    RefPtr<Attr> attrNode = findAttrNodeInList(attrNodeList, name);
+    if (!attrNode) {
+        attrNode = Attr::create(this, name);
+        treeScope()->adoptIfNeeded(attrNode.get());
+        attrNodeList->append(attrNode);
+    }
+    return attrNode.release();
+}
+
+void Element::detachAttrNodeFromElementWithValue(Attr* attrNode, const AtomicString& value)
+{
+    ASSERT(hasSyntheticAttrChildNodes());
+    attrNode->detachFromElementWithValue(value);
+
+    AttrNodeList* attrNodeList = attrNodeListForElement(this);
+    for (unsigned i = 0; i < attrNodeList->size(); ++i) {
+        if (attrNodeList->at(i)->qualifiedName() == attrNode->qualifiedName()) {
+            attrNodeList->remove(i);
+            if (attrNodeList->isEmpty())
+                removeAttrNodeListForElement(this);
+            return;
+        }
+    }
+    ASSERT_NOT_REACHED();
+}
+
+void Element::detachAllAttrNodesFromElement()
+{
+    AttrNodeList* attrNodeList = attrNodeListForElement(this);
+    ASSERT(attrNodeList);
+
+    for (unsigned i = 0; i < attributeCount(); ++i) {
+        const Attribute* attribute = attributeItem(i);
+        if (RefPtr<Attr> attrNode = findAttrNodeInList(attrNodeList, attribute->name()))
+            attrNode->detachFromElementWithValue(attribute->value());
+    }
+
+    removeAttrNodeListForElement(this);
+}
+
+void Element::willRecalcStyle(StyleChange)
+{
+    ASSERT(hasCustomStyleCallbacks());
+}
+
+void Element::didRecalcStyle(StyleChange)
+{
+    ASSERT(hasCustomStyleCallbacks());
+}
+
+
+PassRefPtr<RenderStyle> Element::customStyleForRenderer()
+{
+    ASSERT(hasCustomStyleCallbacks());
+    return 0;
+}
+
+void Element::cloneAttributesFromElement(const Element& other)
+{
+    if (hasSyntheticAttrChildNodes())
+        detachAllAttrNodesFromElement();
+
+    other.synchronizeAllAttributes();
+    if (!other.m_elementData) {
+        m_elementData.clear();
+        return;
+    }
+
+    const AtomicString& oldID = getIdAttribute();
+    const AtomicString& newID = other.getIdAttribute();
+
+    if (!oldID.isNull() || !newID.isNull())
+        updateId(oldID, newID);
+
+    const AtomicString& oldName = getNameAttribute();
+    const AtomicString& newName = other.getNameAttribute();
+
+    if (!oldName.isNull() || !newName.isNull())
+        updateName(oldName, newName);
+
+    // If 'other' has a mutable ElementData, convert it to an immutable one so we can share it between both elements.
+    // We can only do this if there is no CSSOM wrapper for other's inline style, and there are no presentation attributes.
+    if (other.m_elementData->isUnique()
+        && !other.m_elementData->presentationAttributeStyle()
+        && (!other.m_elementData->inlineStyle() || !other.m_elementData->inlineStyle()->hasCSSOMWrapper()))
+        const_cast<Element&>(other).m_elementData = static_cast<const UniqueElementData*>(other.m_elementData.get())->makeShareableCopy();
+
+    if (!other.m_elementData->isUnique())
+        m_elementData = other.m_elementData;
+    else
+        m_elementData = other.m_elementData->makeUniqueCopy();
+
+    for (unsigned i = 0; i < m_elementData->length(); ++i) {
+        const Attribute* attribute = const_cast<const ElementData*>(m_elementData.get())->attributeItem(i);
+        attributeChangedFromParserOrByCloning(attribute->name(), attribute->value(), ModifiedByCloning);
+    }
+}
+
+void Element::cloneDataFromElement(const Element& other)
+{
+    cloneAttributesFromElement(other);
+    copyNonAttributePropertiesFromElement(other);
+}
+
+void Element::createUniqueElementData()
+{
+    if (!m_elementData)
+        m_elementData = UniqueElementData::create();
+    else {
+        ASSERT(!m_elementData->isUnique());
+        m_elementData = static_cast<ShareableElementData*>(m_elementData.get())->makeUniqueCopy();
+    }
+}
+
+void Element::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    ContainerNode::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_tagName, "tagName");
+    info.addMember(m_elementData, "elementData");
+}
+
+#if ENABLE(SVG)
+bool Element::hasPendingResources() const
+{
+    return hasRareData() && elementRareData()->hasPendingResources();
+}
+
+void Element::setHasPendingResources()
+{
+    ensureElementRareData()->setHasPendingResources(true);
+}
+
+void Element::clearHasPendingResources()
+{
+    ensureElementRareData()->setHasPendingResources(false);
+}
+#endif
+
+void ElementData::deref()
+{
+    if (!derefBase())
+        return;
+
+    if (m_isUnique)
+        delete static_cast<UniqueElementData*>(this);
+    else
+        delete static_cast<ShareableElementData*>(this);
+}
+
+ElementData::ElementData()
+    : m_isUnique(true)
+    , m_arraySize(0)
+    , m_presentationAttributeStyleIsDirty(false)
+    , m_styleAttributeIsDirty(false)
+#if ENABLE(SVG)
+    , m_animatedSVGAttributesAreDirty(false)
+#endif
+{
+}
+
+ElementData::ElementData(unsigned arraySize)
+    : m_isUnique(false)
+    , m_arraySize(arraySize)
+    , m_presentationAttributeStyleIsDirty(false)
+    , m_styleAttributeIsDirty(false)
+#if ENABLE(SVG)
+    , m_animatedSVGAttributesAreDirty(false)
+#endif
+{
+}
+
+struct SameSizeAsElementData : public RefCounted<SameSizeAsElementData> {
+    unsigned bitfield;
+    void* refPtrs[3];
+};
+
+COMPILE_ASSERT(sizeof(ElementData) == sizeof(SameSizeAsElementData), element_attribute_data_should_stay_small);
+
+static size_t sizeForShareableElementDataWithAttributeCount(unsigned count)
+{
+    return sizeof(ShareableElementData) + sizeof(Attribute) * count;
+}
+
+PassRefPtr<ShareableElementData> ShareableElementData::createWithAttributes(const Vector<Attribute>& attributes)
+{
+    void* slot = WTF::fastMalloc(sizeForShareableElementDataWithAttributeCount(attributes.size()));
+    return adoptRef(new (slot) ShareableElementData(attributes));
+}
+
+PassRefPtr<UniqueElementData> UniqueElementData::create()
+{
+    return adoptRef(new UniqueElementData);
+}
+
+ShareableElementData::ShareableElementData(const Vector<Attribute>& attributes)
+    : ElementData(attributes.size())
+{
+    for (unsigned i = 0; i < m_arraySize; ++i)
+        new (&m_attributeArray[i]) Attribute(attributes[i]);
+}
+
+ShareableElementData::~ShareableElementData()
+{
+    for (unsigned i = 0; i < m_arraySize; ++i)
+        m_attributeArray[i].~Attribute();
+}
+
+ShareableElementData::ShareableElementData(const UniqueElementData& other)
+    : ElementData(other, false)
+{
+    ASSERT(!other.m_presentationAttributeStyle);
+
+    if (other.m_inlineStyle) {
+        ASSERT(!other.m_inlineStyle->hasCSSOMWrapper());
+        m_inlineStyle = other.m_inlineStyle->immutableCopyIfNeeded();
+    }
+
+    for (unsigned i = 0; i < m_arraySize; ++i)
+        new (&m_attributeArray[i]) Attribute(other.m_attributeVector.at(i));
+}
+
+ElementData::ElementData(const ElementData& other, bool isUnique)
+    : m_isUnique(isUnique)
+    , m_arraySize(isUnique ? 0 : other.length())
+    , m_presentationAttributeStyleIsDirty(other.m_presentationAttributeStyleIsDirty)
+    , m_styleAttributeIsDirty(other.m_styleAttributeIsDirty)
+#if ENABLE(SVG)
+    , m_animatedSVGAttributesAreDirty(other.m_animatedSVGAttributesAreDirty)
+#endif
+    , m_classNames(other.m_classNames)
+    , m_idForStyleResolution(other.m_idForStyleResolution)
+{
+    // NOTE: The inline style is copied by the subclass copy constructor since we don't know what to do with it here.
+}
+
+UniqueElementData::UniqueElementData()
+{
+}
+
+UniqueElementData::UniqueElementData(const UniqueElementData& other)
+    : ElementData(other, true)
+    , m_presentationAttributeStyle(other.m_presentationAttributeStyle)
+    , m_attributeVector(other.m_attributeVector)
+{
+    m_inlineStyle = other.m_inlineStyle ? other.m_inlineStyle->copy() : 0;
+}
+
+UniqueElementData::UniqueElementData(const ShareableElementData& other)
+    : ElementData(other, true)
+{
+    // An ShareableElementData should never have a mutable inline StylePropertySet attached.
+    ASSERT(!other.m_inlineStyle || !other.m_inlineStyle->isMutable());
+    m_inlineStyle = other.m_inlineStyle;
+
+    m_attributeVector.reserveCapacity(other.length());
+    for (unsigned i = 0; i < other.length(); ++i)
+        m_attributeVector.uncheckedAppend(other.m_attributeArray[i]);
+}
+
+PassRefPtr<UniqueElementData> ElementData::makeUniqueCopy() const
+{
+    if (isUnique())
+        return adoptRef(new UniqueElementData(static_cast<const UniqueElementData&>(*this)));
+    return adoptRef(new UniqueElementData(static_cast<const ShareableElementData&>(*this)));
+}
+
+PassRefPtr<ShareableElementData> UniqueElementData::makeShareableCopy() const
+{
+    void* slot = WTF::fastMalloc(sizeForShareableElementDataWithAttributeCount(m_attributeVector.size()));
+    return adoptRef(new (slot) ShareableElementData(*this));
+}
+
+void UniqueElementData::addAttribute(const QualifiedName& attributeName, const AtomicString& value)
+{
+    m_attributeVector.append(Attribute(attributeName, value));
+}
+
+void UniqueElementData::removeAttribute(size_t index)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(index < length());
+    m_attributeVector.remove(index);
+}
+
+bool ElementData::isEquivalent(const ElementData* other) const
+{
+    if (!other)
+        return isEmpty();
+
+    unsigned len = length();
+    if (len != other->length())
+        return false;
+
+    for (unsigned i = 0; i < len; i++) {
+        const Attribute* attribute = attributeItem(i);
+        const Attribute* otherAttr = other->getAttributeItem(attribute->name());
+        if (!otherAttr || attribute->value() != otherAttr->value())
+            return false;
+    }
+
+    return true;
+}
+
+void ElementData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    size_t actualSize = m_isUnique ? sizeof(ElementData) : sizeForShareableElementDataWithAttributeCount(m_arraySize);
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM, actualSize);
+    info.addMember(m_inlineStyle, "inlineStyle");
+    info.addMember(m_classNames, "classNames");
+    info.addMember(m_idForStyleResolution, "idForStyleResolution");
+    if (m_isUnique) {
+        const UniqueElementData* uniqueThis = static_cast<const UniqueElementData*>(this);
+        info.addMember(uniqueThis->m_presentationAttributeStyle, "presentationAttributeStyle");
+        info.addMember(uniqueThis->m_attributeVector, "attributeVector");
+    }
+    for (unsigned i = 0, len = length(); i < len; i++)
+        info.addMember(*attributeItem(i), "*attributeItem");
+}
+
+size_t ElementData::getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const
+{
+    // Continue to checking case-insensitively and/or full namespaced names if necessary:
+    for (unsigned i = 0; i < length(); ++i) {
+        const Attribute* attribute = attributeItem(i);
+        if (!attribute->name().hasPrefix()) {
+            if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attribute->localName()))
+                return i;
+        } else {
+            // FIXME: Would be faster to do this comparison without calling toString, which
+            // generates a temporary string by concatenation. But this branch is only reached
+            // if the attribute name has a prefix, which is rare in HTML.
+            if (equalPossiblyIgnoringCase(name, attribute->name().toString(), shouldIgnoreAttributeCase))
+                return i;
+        }
+    }
+    return notFound;
+}
+
+Attribute* UniqueElementData::getAttributeItem(const QualifiedName& name)
+{
+    for (unsigned i = 0; i < length(); ++i) {
+        if (m_attributeVector.at(i).name().matches(name))
+            return &m_attributeVector.at(i);
+    }
+    return 0;
+}
+
+Attribute* UniqueElementData::attributeItem(unsigned index)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(index < length());
+    return &m_attributeVector.at(index);
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/Element.h b/Source/core/dom/Element.h
new file mode 100644
index 0000000..0edd20f
--- /dev/null
+++ b/Source/core/dom/Element.h
@@ -0,0 +1,1007 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Peter Kelly (pmk@post.com)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Element_h
+#define Element_h
+
+#include "HTMLNames.h"
+#include "core/dom/Attribute.h"
+#include "core/dom/Document.h"
+#include "core/dom/FragmentScriptingPermission.h"
+#include "core/dom/SpaceSplitString.h"
+#include "core/html/CollectionType.h"
+#include "core/platform/ScrollTypes.h"
+
+namespace WebCore {
+
+class Attr;
+class ClientRect;
+class ClientRectList;
+class DOMStringMap;
+class DOMTokenList;
+class Element;
+class ElementRareData;
+class ElementShadow;
+class ShareableElementData;
+class IntSize;
+class Locale;
+class UniqueElementData;
+class PseudoElement;
+class RenderRegion;
+class ShadowRoot;
+class StylePropertySet;
+
+class ElementData : public RefCounted<ElementData> {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    // Override RefCounted's deref() to ensure operator delete is called on
+    // the appropriate subclass type.
+    void deref();
+
+    void clearClass() const { m_classNames.clear(); }
+    void setClass(const AtomicString& className, bool shouldFoldCase) const { m_classNames.set(className, shouldFoldCase); }
+    const SpaceSplitString& classNames() const { return m_classNames; }
+
+    const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; }
+    void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyleResolution = newId; }
+
+    const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); }
+
+    const StylePropertySet* presentationAttributeStyle() const;
+
+    size_t length() const;
+    bool isEmpty() const { return !length(); }
+
+    const Attribute* attributeItem(unsigned index) const;
+    const Attribute* getAttributeItem(const QualifiedName&) const;
+    size_t getAttributeItemIndex(const QualifiedName&) const;
+    size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
+
+    bool hasID() const { return !m_idForStyleResolution.isNull(); }
+    bool hasClass() const { return !m_classNames.isNull(); }
+
+    bool isEquivalent(const ElementData* other) const;
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+    bool isUnique() const { return m_isUnique; }
+
+protected:
+    ElementData();
+    ElementData(unsigned arraySize);
+    ElementData(const ElementData&, bool isUnique);
+
+    unsigned m_isUnique : 1;
+    unsigned m_arraySize : 28;
+    mutable unsigned m_presentationAttributeStyleIsDirty : 1;
+    mutable unsigned m_styleAttributeIsDirty : 1;
+#if ENABLE(SVG)
+    mutable unsigned m_animatedSVGAttributesAreDirty : 1;
+#endif
+
+    mutable RefPtr<StylePropertySet> m_inlineStyle;
+    mutable SpaceSplitString m_classNames;
+    mutable AtomicString m_idForStyleResolution;
+
+private:
+    friend class Element;
+    friend class StyledElement;
+    friend class ShareableElementData;
+    friend class UniqueElementData;
+#if ENABLE(SVG)
+    friend class SVGElement;
+#endif
+
+    const Attribute* attributeBase() const;
+    const Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
+    size_t getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
+
+    PassRefPtr<UniqueElementData> makeUniqueCopy() const;
+};
+
+#if COMPILER(MSVC)
+#pragma warning(push)
+#pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning
+#endif
+
+class ShareableElementData : public ElementData {
+    // This is needed because we malloc() space for a ShareableElementData plus
+    // optional following attributes, as a performance tweak.
+    NEW_DELETE_SAME_AS_MALLOC_FREE;
+public:
+    static PassRefPtr<ShareableElementData> createWithAttributes(const Vector<Attribute>&);
+
+    explicit ShareableElementData(const Vector<Attribute>&);
+    explicit ShareableElementData(const UniqueElementData&);
+    ~ShareableElementData();
+
+    Attribute m_attributeArray[0];
+};
+
+#if COMPILER(MSVC)
+#pragma warning(pop)
+#endif
+
+class UniqueElementData : public ElementData {
+public:
+    static PassRefPtr<UniqueElementData> create();
+    PassRefPtr<ShareableElementData> makeShareableCopy() const;
+
+    // These functions do no error/duplicate checking.
+    void addAttribute(const QualifiedName&, const AtomicString&);
+    void removeAttribute(size_t index);
+
+    Attribute* attributeItem(unsigned index);
+    Attribute* getAttributeItem(const QualifiedName&);
+
+    UniqueElementData();
+    explicit UniqueElementData(const ShareableElementData&);
+    explicit UniqueElementData(const UniqueElementData&);
+
+    mutable RefPtr<StylePropertySet> m_presentationAttributeStyle;
+    Vector<Attribute, 4> m_attributeVector;
+};
+
+enum AffectedSelectorType {
+    AffectedSelectorChecked = 1,
+    AffectedSelectorEnabled = 1 << 1,
+    AffectedSelectorDisabled = 1 << 2,
+    AffectedSelectorIndeterminate = 1 << 3,
+    AffectedSelectorLink = 1 << 4,
+    AffectedSelectorTarget = 1 << 5,
+    AffectedSelectorVisited = 1 << 6
+};
+typedef int AffectedSelectorMask;
+
+enum SpellcheckAttributeState {
+    SpellcheckAttributeTrue,
+    SpellcheckAttributeFalse,
+    SpellcheckAttributeDefault
+};
+
+class Element : public ContainerNode {
+public:
+    static PassRefPtr<Element> create(const QualifiedName&, Document*);
+    virtual ~Element();
+
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(change);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(click);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(drop);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(select);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(submit);
+
+    // These four attribute event handler attributes are overridden by HTMLBodyElement
+    // and HTMLFrameSetElement to forward to the DOMWindow.
+    DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur);
+    DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error);
+    DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus);
+    DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load);
+
+    // WebKit extensions
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(reset);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenerror);
+
+    bool hasAttribute(const QualifiedName&) const;
+    const AtomicString& getAttribute(const QualifiedName&) const;
+    void setAttribute(const QualifiedName&, const AtomicString& value);
+    void setSynchronizedLazyAttribute(const QualifiedName&, const AtomicString& value);
+    void removeAttribute(const QualifiedName&);
+
+    // Typed getters and setters for language bindings.
+    int getIntegralAttribute(const QualifiedName& attributeName) const;
+    void setIntegralAttribute(const QualifiedName& attributeName, int value);
+    unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const;
+    void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value);
+
+    // Call this to get the value of an attribute that is known not to be the style
+    // attribute or one of the SVG animatable attributes.
+    bool fastHasAttribute(const QualifiedName&) const;
+    const AtomicString& fastGetAttribute(const QualifiedName&) const;
+#ifndef NDEBUG
+    bool fastAttributeLookupAllowed(const QualifiedName&) const;
+#endif
+
+#ifdef DUMP_NODE_STATISTICS
+    bool hasNamedNodeMap() const;
+#endif
+    bool hasAttributes() const;
+    // This variant will not update the potentially invalid attributes. To be used when not interested
+    // in style attribute or one of the SVG animation attributes.
+    bool hasAttributesWithoutUpdate() const;
+
+    bool hasAttribute(const AtomicString& name) const;
+    bool hasAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const;
+
+    const AtomicString& getAttribute(const AtomicString& name) const;
+    const AtomicString& getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const;
+
+    void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
+    static bool parseAttributeName(QualifiedName&, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionCode&);
+    void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&);
+
+    bool isIdAttributeName(const QualifiedName&) const;
+    const AtomicString& getIdAttribute() const;
+    void setIdAttribute(const AtomicString&);
+
+    const AtomicString& getNameAttribute() const;
+    const AtomicString& getClassAttribute() const;
+
+    // Call this to get the value of the id attribute for style resolution purposes.
+    // The value will already be lowercased if the document is in compatibility mode,
+    // so this function is not suitable for non-style uses.
+    const AtomicString& idForStyleResolution() const;
+
+    // Internal methods that assume the existence of attribute storage, one should use hasAttributes()
+    // before calling them.
+    size_t attributeCount() const;
+    const Attribute* attributeItem(unsigned index) const;
+    const Attribute* getAttributeItem(const QualifiedName&) const;
+    size_t getAttributeItemIndex(const QualifiedName& name) const { return elementData()->getAttributeItemIndex(name); }
+    size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const { return elementData()->getAttributeItemIndex(name, shouldIgnoreAttributeCase); }
+
+    void scrollIntoView(bool alignToTop = true);
+    void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
+
+    void scrollByLines(int lines);
+    void scrollByPages(int pages);
+
+    int offsetLeft();
+    int offsetTop();
+    int offsetWidth();
+    int offsetHeight();
+
+    // FIXME: Replace uses of offsetParent in the platform with calls
+    // to the render layer and merge bindingsOffsetParent and offsetParent.
+    Element* bindingsOffsetParent();
+
+    Element* offsetParent();
+    int clientLeft();
+    int clientTop();
+    int clientWidth();
+    int clientHeight();
+    virtual int scrollLeft();
+    virtual int scrollTop();
+    virtual void setScrollLeft(int);
+    virtual void setScrollTop(int);
+    virtual int scrollWidth();
+    virtual int scrollHeight();
+
+    IntRect boundsInRootViewSpace();
+
+    PassRefPtr<ClientRectList> getClientRects();
+    PassRefPtr<ClientRect> getBoundingClientRect();
+    
+    // Returns the absolute bounding box translated into screen coordinates:
+    IntRect screenRect() const;
+
+    void removeAttribute(const AtomicString& name);
+    void removeAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName);
+
+    PassRefPtr<Attr> detachAttribute(size_t index);
+
+    PassRefPtr<Attr> getAttributeNode(const AtomicString& name);
+    PassRefPtr<Attr> getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName);
+    PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&);
+    PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&);
+    PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&);
+
+    PassRefPtr<Attr> attrIfExists(const QualifiedName&);
+    PassRefPtr<Attr> ensureAttr(const QualifiedName&);
+
+    const Vector<RefPtr<Attr> >& attrNodeList();
+
+    virtual CSSStyleDeclaration* style();
+
+    const QualifiedName& tagQName() const { return m_tagName; }
+    String tagName() const { return nodeName(); }
+    bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
+    
+    // A fast function for checking the local name against another atomic string.
+    bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
+    bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); }
+
+    const AtomicString& localName() const { return m_tagName.localName(); }
+    const AtomicString& prefix() const { return m_tagName.prefix(); }
+    const AtomicString& namespaceURI() const { return m_tagName.namespaceURI(); }
+
+    virtual KURL baseURI() const OVERRIDE FINAL;
+
+    virtual String nodeName() const;
+
+    PassRefPtr<Element> cloneElementWithChildren();
+    PassRefPtr<Element> cloneElementWithoutChildren();
+
+    void normalizeAttributes();
+    String nodeNamePreservingCase() const;
+
+    void setBooleanAttribute(const QualifiedName& name, bool);
+
+    // For exposing to DOM only.
+    NamedNodeMap* attributes() const;
+
+    enum AttributeModificationReason {
+        ModifiedDirectly,
+        ModifiedByCloning
+    };
+
+    // This method is called whenever an attribute is added, changed or removed.
+    virtual void attributeChanged(const QualifiedName&, const AtomicString&, AttributeModificationReason = ModifiedDirectly);
+    virtual void parseAttribute(const QualifiedName&, const AtomicString&) { }
+
+    // Only called by the parser immediately after element construction.
+    void parserSetAttributes(const Vector<Attribute>&);
+
+    // Remove attributes that might introduce scripting from the vector leaving the element unchanged.
+    void stripScriptingAttributes(Vector<Attribute>&) const;
+
+    const ElementData* elementData() const { return m_elementData.get(); }
+    UniqueElementData* ensureUniqueElementData();
+
+    void synchronizeAllAttributes() const;
+
+    // Clones attributes only.
+    void cloneAttributesFromElement(const Element&);
+
+    // Clones all attribute-derived data, including subclass specifics (through copyNonAttributeProperties.)
+    void cloneDataFromElement(const Element&);
+
+    bool hasEquivalentAttributes(const Element* other) const;
+
+    virtual void copyNonAttributePropertiesFromElement(const Element&) { }
+
+    virtual void attach();
+    virtual void detach();
+    virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
+    virtual bool rendererIsNeeded(const NodeRenderingContext&);
+    void recalcStyle(StyleChange = NoChange);
+    void didAffectSelector(AffectedSelectorMask);
+
+    ElementShadow* shadow() const;
+    ElementShadow* ensureShadow();
+    PassRefPtr<ShadowRoot> createShadowRoot(ExceptionCode&);
+    ShadowRoot* shadowRoot() const;
+
+    bool hasAuthorShadowRoot() const { return shadowRoot(); }
+
+    ShadowRoot* userAgentShadowRoot() const;
+    ShadowRoot* ensureUserAgentShadowRoot();
+
+    virtual const AtomicString& shadowPseudoId() const;
+
+    RenderStyle* computedStyle(PseudoId = NOPSEUDO);
+
+    // Methods for indicating the style is affected by dynamic updates (e.g., children changing, our position changing in our sibling list, etc.)
+    bool styleAffectedByEmpty() const { return hasRareData() && rareDataStyleAffectedByEmpty(); }
+    bool childrenAffectedByHover() const { return hasRareData() && rareDataChildrenAffectedByHover(); }
+    bool childrenAffectedByActive() const { return hasRareData() && rareDataChildrenAffectedByActive(); }
+    bool childrenAffectedByDrag() const { return hasRareData() && rareDataChildrenAffectedByDrag(); }
+    bool childrenAffectedByPositionalRules() const { return hasRareData() && (rareDataChildrenAffectedByForwardPositionalRules() || rareDataChildrenAffectedByBackwardPositionalRules()); }
+    bool childrenAffectedByFirstChildRules() const { return hasRareData() && rareDataChildrenAffectedByFirstChildRules(); }
+    bool childrenAffectedByLastChildRules() const { return hasRareData() && rareDataChildrenAffectedByLastChildRules(); }
+    bool childrenAffectedByDirectAdjacentRules() const { return hasRareData() && rareDataChildrenAffectedByDirectAdjacentRules(); }
+    bool childrenAffectedByForwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByForwardPositionalRules(); }
+    bool childrenAffectedByBackwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByBackwardPositionalRules(); }
+    unsigned childIndex() const { return hasRareData() ? rareDataChildIndex() : 0; }
+
+    bool hasFlagsSetDuringStylingOfChildren() const;
+
+    void setStyleAffectedByEmpty();
+    void setChildrenAffectedByHover(bool);
+    void setChildrenAffectedByActive(bool);
+    void setChildrenAffectedByDrag(bool);
+    void setChildrenAffectedByFirstChildRules();
+    void setChildrenAffectedByLastChildRules();
+    void setChildrenAffectedByDirectAdjacentRules();
+    void setChildrenAffectedByForwardPositionalRules();
+    void setChildrenAffectedByBackwardPositionalRules();
+    void setChildIndex(unsigned);
+
+    void setIsInCanvasSubtree(bool);
+    bool isInCanvasSubtree() const;
+
+    bool isUnresolvedCustomElement();
+
+    AtomicString computeInheritedLanguage() const;
+    Locale& locale() const;
+
+    virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
+
+    virtual bool isURLAttribute(const Attribute&) const { return false; }
+    virtual bool isHTMLContentAttribute(const Attribute&) const { return false; }
+
+    KURL getURLAttribute(const QualifiedName&) const;
+    KURL getNonEmptyURLAttribute(const QualifiedName&) const;
+
+    virtual const AtomicString& imageSourceURL() const;
+    virtual String target() const { return String(); }
+
+    virtual void focus(bool restorePreviousSelection = true, FocusDirection = FocusDirectionNone);
+    virtual void updateFocusAppearance(bool restorePreviousSelection);
+    virtual void blur();
+
+    String innerText();
+    String outerText();
+ 
+    virtual String title() const;
+
+    const AtomicString& pseudo() const;
+    void setPseudo(const AtomicString&);
+
+    LayoutSize minimumSizeForResizing() const;
+    void setMinimumSizeForResizing(const LayoutSize&);
+
+    virtual void didBecomeFullscreenElement() { }
+    virtual void willStopBeingFullscreenElement() { }
+
+    virtual void captionPreferencesChanged() { }
+
+    bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); }
+    virtual void finishParsingChildren();
+    virtual void beginParsingChildren() OVERRIDE FINAL;
+
+    bool hasPseudoElements() const;
+    PseudoElement* pseudoElement(PseudoId) const;
+    RenderObject* pseudoElementRenderer(PseudoId) const;
+    bool childNeedsShadowWalker() const;
+    void didShadowTreeAwareChildrenChange();
+
+    // ElementTraversal API
+    Element* firstElementChild() const;
+    Element* lastElementChild() const;
+    Element* previousElementSibling() const;
+    Element* nextElementSibling() const;
+    unsigned childElementCount() const;
+
+    virtual bool matchesReadOnlyPseudoClass() const;
+    virtual bool matchesReadWritePseudoClass() const;
+    bool webkitMatchesSelector(const String& selectors, ExceptionCode&);
+    virtual bool shouldAppearIndeterminate() const;
+
+    DOMTokenList* classList();
+
+    DOMStringMap* dataset();
+
+    static bool isMathMLElement() { return false; }
+    virtual bool isMediaElement() const { return false; }
+
+#if ENABLE(INPUT_SPEECH)
+    virtual bool isInputFieldSpeechButtonElement() const { return false; }
+#endif
+#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
+    virtual bool isDateTimeFieldElement() const;
+#endif
+
+    virtual bool isFormControlElement() const { return false; }
+    virtual bool isSpinButtonElement() const { return false; }
+    virtual bool isTextFormControl() const { return false; }
+    virtual bool isOptionalFormControl() const { return false; }
+    virtual bool isRequiredFormControl() const { return false; }
+    virtual bool isDefaultButtonForForm() const { return false; }
+    virtual bool willValidate() const { return false; }
+    virtual bool isValidFormControlElement() { return false; }
+    virtual bool isInRange() const { return false; }
+    virtual bool isOutOfRange() const { return false; }
+    virtual bool isFrameElementBase() const { return false; }
+    virtual bool isTextFieldDecoration() const { return false; }
+
+    virtual bool canContainRangeEndPoint() const { return true; }
+
+    virtual const AtomicString& formControlType() const { return nullAtom; }
+
+    virtual bool wasChangedSinceLastFormControlChangeEvent() const;
+    virtual void setChangedSinceLastFormControlChangeEvent(bool);
+    virtual void dispatchFormControlChangeEvent() { }
+
+    // Used for disabled form elements; if true, prevents mouse events from being dispatched
+    // to event listeners, and prevents DOMActivate events from being sent at all.
+    virtual bool isDisabledFormControl() const;
+
+    bool isInert() const;
+
+#if ENABLE(SVG)
+    virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const;
+    bool hasPendingResources() const;
+    void setHasPendingResources();
+    void clearHasPendingResources();
+    virtual void buildPendingResource() { };
+#endif
+
+    enum {
+        ALLOW_KEYBOARD_INPUT = 1 << 0,
+        LEGACY_MOZILLA_REQUEST = 1 << 1,
+    };
+    
+    void webkitRequestFullScreen(unsigned short flags);
+    bool containsFullScreenElement() const;
+    void setContainsFullScreenElement(bool);
+    void setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool);
+
+    // W3C API
+    void webkitRequestFullscreen();
+
+    bool isInTopLayer() const;
+    void setIsInTopLayer(bool);
+
+    void webkitRequestPointerLock();
+
+    bool isSpellCheckingEnabled() const;
+
+    PassRefPtr<RenderStyle> styleForRenderer();
+
+    RenderRegion* renderRegion() const;
+    const AtomicString& webkitRegionOverset() const;
+    Vector<RefPtr<Range> > webkitGetRegionFlowRanges() const;
+
+    bool hasID() const;
+    bool hasClass() const;
+    const SpaceSplitString& classNames() const;
+
+    IntSize savedLayerScrollOffset() const;
+    void setSavedLayerScrollOffset(const IntSize&);
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+protected:
+    Element(const QualifiedName& tagName, Document* document, ConstructionType type)
+        : ContainerNode(document, type)
+        , m_tagName(tagName)
+    {
+        ScriptWrappable::init(this);
+    }
+
+    virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
+    virtual void removedFrom(ContainerNode*) OVERRIDE;
+    virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE;
+    virtual void removeAllEventListeners() OVERRIDE FINAL;
+
+    virtual void willRecalcStyle(StyleChange);
+    virtual void didRecalcStyle(StyleChange);
+    virtual PassRefPtr<RenderStyle> customStyleForRenderer();
+
+    virtual bool shouldRegisterAsNamedItem() const { return false; }
+    virtual bool shouldRegisterAsExtraNamedItem() const { return false; }
+
+    void clearTabIndexExplicitlyIfNeeded();    
+    void setTabIndexExplicitly(short);
+    virtual bool supportsFocus() const OVERRIDE;
+    virtual short tabIndex() const OVERRIDE;
+
+    PassRefPtr<HTMLCollection> ensureCachedHTMLCollection(CollectionType);
+    HTMLCollection* cachedHTMLCollection(CollectionType);
+
+    // classAttributeChanged() exists to share code between
+    // parseAttribute (called via setAttribute()) and
+    // svgAttributeChanged (called when element.className.baseValue is set)
+    void classAttributeChanged(const AtomicString& newClassString);
+
+private:
+    void updatePseudoElement(PseudoId, StyleChange);
+    void createPseudoElementIfNeeded(PseudoId);
+    void setPseudoElement(PseudoId, PassRefPtr<PseudoElement>);
+
+    virtual bool areAuthorShadowsAllowed() const { return true; }
+    virtual void didAddUserAgentShadowRoot(ShadowRoot*) { }
+    virtual bool alwaysCreateUserAgentShadowRoot() const { return false; }
+
+    // FIXME: Remove the need for Attr to call willModifyAttribute/didModifyAttribute.
+    friend class Attr;
+
+    enum SynchronizationOfLazyAttribute { NotInSynchronizationOfLazyAttribute = 0, InSynchronizationOfLazyAttribute };
+
+    void didAddAttribute(const QualifiedName&, const AtomicString&);
+    void willModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue);
+    void didModifyAttribute(const QualifiedName&, const AtomicString&);
+    void didRemoveAttribute(const QualifiedName&);
+
+    void synchronizeAttribute(const QualifiedName&) const;
+    void synchronizeAttribute(const AtomicString& localName) const;
+
+    void updateId(const AtomicString& oldId, const AtomicString& newId);
+    void updateId(TreeScope*, const AtomicString& oldId, const AtomicString& newId);
+    void updateName(const AtomicString& oldName, const AtomicString& newName);
+    void updateLabel(TreeScope*, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue);
+
+    void scrollByUnits(int units, ScrollGranularity);
+
+    virtual void setPrefix(const AtomicString&, ExceptionCode&) OVERRIDE FINAL;
+    virtual NodeType nodeType() const OVERRIDE FINAL;
+    virtual bool childTypeAllowed(NodeType) const OVERRIDE FINAL;
+
+    void setAttributeInternal(size_t index, const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute);
+    void addAttributeInternal(const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute);
+    void removeAttributeInternal(size_t index, SynchronizationOfLazyAttribute);
+    void attributeChangedFromParserOrByCloning(const QualifiedName&, const AtomicString&, AttributeModificationReason);
+
+#ifndef NDEBUG
+    virtual void formatForDebugger(char* buffer, unsigned length) const;
+#endif
+
+    bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
+
+    void cancelFocusAppearanceUpdate();
+
+    virtual const AtomicString& virtualPrefix() const OVERRIDE FINAL { return prefix(); }
+    virtual const AtomicString& virtualLocalName() const OVERRIDE FINAL { return localName(); }
+    virtual const AtomicString& virtualNamespaceURI() const OVERRIDE FINAL { return namespaceURI(); }
+    virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); }
+    
+    // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
+    // are used instead.
+    virtual PassRefPtr<Node> cloneNode(bool deep) OVERRIDE;
+    virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren();
+
+    QualifiedName m_tagName;
+    bool rareDataStyleAffectedByEmpty() const;
+    bool rareDataChildrenAffectedByHover() const;
+    bool rareDataChildrenAffectedByActive() const;
+    bool rareDataChildrenAffectedByDrag() const;
+    bool rareDataChildrenAffectedByFirstChildRules() const;
+    bool rareDataChildrenAffectedByLastChildRules() const;
+    bool rareDataChildrenAffectedByDirectAdjacentRules() const;
+    bool rareDataChildrenAffectedByForwardPositionalRules() const;
+    bool rareDataChildrenAffectedByBackwardPositionalRules() const;
+    unsigned rareDataChildIndex() const;
+
+    SpellcheckAttributeState spellcheckAttributeState() const;
+
+    void updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName);
+    void updateExtraNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName);
+
+    void unregisterNamedFlowContentNode();
+
+    void createUniqueElementData();
+
+    bool shouldInvalidateDistributionWhenAttributeChanged(ElementShadow*, const QualifiedName&, const AtomicString&);
+
+    ElementRareData* elementRareData() const;
+    ElementRareData* ensureElementRareData();
+
+    void detachAllAttrNodesFromElement();
+    void detachAttrNodeFromElementWithValue(Attr*, const AtomicString& value);
+
+    void createRendererIfNeeded();
+
+    bool isJavaScriptURLAttribute(const Attribute&) const;
+
+    RefPtr<ElementData> m_elementData;
+};
+    
+inline Element* toElement(Node* node)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isElementNode());
+    return static_cast<Element*>(node);
+}
+
+inline const Element* toElement(const Node* node)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isElementNode());
+    return static_cast<const Element*>(node);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toElement(const Element*);
+
+inline bool isDisabledFormControl(const Node* node)
+{
+    return node->isElementNode() && toElement(node)->isDisabledFormControl();
+}
+
+inline bool Node::hasTagName(const QualifiedName& name) const
+{
+    return isElementNode() && toElement(this)->hasTagName(name);
+}
+    
+inline bool Node::hasLocalName(const AtomicString& name) const
+{
+    return isElementNode() && toElement(this)->hasLocalName(name);
+}
+
+inline bool Node::hasAttributes() const
+{
+    return isElementNode() && toElement(this)->hasAttributes();
+}
+
+inline NamedNodeMap* Node::attributes() const
+{
+    return isElementNode() ? toElement(this)->attributes() : 0;
+}
+
+inline Element* Node::parentElement() const
+{
+    ContainerNode* parent = parentNode();
+    return parent && parent->isElementNode() ? toElement(parent) : 0;
+}
+
+inline Element* Element::previousElementSibling() const
+{
+    Node* n = previousSibling();
+    while (n && !n->isElementNode())
+        n = n->previousSibling();
+    return static_cast<Element*>(n);
+}
+
+inline Element* Element::nextElementSibling() const
+{
+    Node* n = nextSibling();
+    while (n && !n->isElementNode())
+        n = n->nextSibling();
+    return static_cast<Element*>(n);
+}
+
+inline bool Element::fastHasAttribute(const QualifiedName& name) const
+{
+    ASSERT(fastAttributeLookupAllowed(name));
+    return elementData() && getAttributeItem(name);
+}
+
+inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const
+{
+    ASSERT(fastAttributeLookupAllowed(name));
+    if (elementData()) {
+        if (const Attribute* attribute = getAttributeItem(name))
+            return attribute->value();
+    }
+    return nullAtom;
+}
+
+inline bool Element::hasAttributesWithoutUpdate() const
+{
+    return elementData() && !elementData()->isEmpty();
+}
+
+inline const AtomicString& Element::idForStyleResolution() const
+{
+    ASSERT(hasID());
+    return elementData()->idForStyleResolution();
+}
+
+inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const
+{
+    // 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 false, a false negative, if the prefixes
+    // don't match but the local name and namespace both do. However, since this has been like this
+    // for a while and the code paths may be hot, we'll have to measure performance if we fix it.
+    return attributeName == document()->idAttributeName();
+}
+
+inline const AtomicString& Element::getIdAttribute() const
+{
+    return hasID() ? fastGetAttribute(document()->idAttributeName()) : nullAtom;
+}
+
+inline const AtomicString& Element::getNameAttribute() const
+{
+    return hasName() ? fastGetAttribute(HTMLNames::nameAttr) : nullAtom;
+}
+
+inline const AtomicString& Element::getClassAttribute() const
+{
+    if (!hasClass())
+        return nullAtom;
+#if ENABLE(SVG)
+    if (isSVGElement())
+        return getAttribute(HTMLNames::classAttr);
+#endif
+    return fastGetAttribute(HTMLNames::classAttr);
+}
+
+inline void Element::setIdAttribute(const AtomicString& value)
+{
+    setAttribute(document()->idAttributeName(), value);
+}
+
+inline const SpaceSplitString& Element::classNames() const
+{
+    ASSERT(hasClass());
+    ASSERT(elementData());
+    return elementData()->classNames();
+}
+
+inline size_t Element::attributeCount() const
+{
+    ASSERT(elementData());
+    return elementData()->length();
+}
+
+inline const Attribute* Element::attributeItem(unsigned index) const
+{
+    ASSERT(elementData());
+    return elementData()->attributeItem(index);
+}
+
+inline const Attribute* Element::getAttributeItem(const QualifiedName& name) const
+{
+    ASSERT(elementData());
+    return elementData()->getAttributeItem(name);
+}
+
+inline bool Element::hasID() const
+{
+    return elementData() && elementData()->hasID();
+}
+
+inline bool Element::hasClass() const
+{
+    return elementData() && elementData()->hasClass();
+}
+
+inline UniqueElementData* Element::ensureUniqueElementData()
+{
+    if (!elementData() || !elementData()->isUnique())
+        createUniqueElementData();
+    return static_cast<UniqueElementData*>(m_elementData.get());
+}
+
+// Put here to make them inline.
+inline bool Node::hasID() const
+{
+    return isElementNode() && toElement(this)->hasID();
+}
+
+inline bool Node::hasClass() const
+{
+    return isElementNode() && toElement(this)->hasClass();
+}
+
+inline Node::InsertionNotificationRequest Node::insertedInto(ContainerNode* insertionPoint)
+{
+    ASSERT(insertionPoint->inDocument() || isContainerNode());
+    if (insertionPoint->inDocument())
+        setFlag(InDocumentFlag);
+    if (parentOrShadowHostNode()->isInShadowTree())
+        setFlag(IsInShadowTreeFlag);
+    return InsertionDone;
+}
+
+inline void Node::removedFrom(ContainerNode* insertionPoint)
+{
+    ASSERT(insertionPoint->inDocument() || isContainerNode());
+    if (insertionPoint->inDocument())
+        clearFlag(InDocumentFlag);
+    if (isInShadowTree() && !treeScope()->rootNode()->isShadowRoot())
+        clearFlag(IsInShadowTreeFlag);
+}
+
+inline bool isShadowHost(const Node* node)
+{
+    return node && node->isElementNode() && toElement(node)->shadow();
+}
+
+inline size_t ElementData::length() const
+{
+    if (isUnique())
+        return static_cast<const UniqueElementData*>(this)->m_attributeVector.size();
+    return m_arraySize;
+}
+
+inline const StylePropertySet* ElementData::presentationAttributeStyle() const
+{
+    if (!m_isUnique)
+        return 0;
+    return static_cast<const UniqueElementData*>(this)->m_presentationAttributeStyle.get();
+}
+
+inline const Attribute* ElementData::getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const
+{
+    size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase);
+    if (index != notFound)
+        return attributeItem(index);
+    return 0;
+}
+
+inline const Attribute* ElementData::attributeBase() const
+{
+    if (m_isUnique)
+        return static_cast<const UniqueElementData*>(this)->m_attributeVector.begin();
+    return static_cast<const ShareableElementData*>(this)->m_attributeArray;
+}
+
+inline size_t ElementData::getAttributeItemIndex(const QualifiedName& name) const
+{
+    const Attribute* begin = attributeBase();
+    for (unsigned i = 0; i < length(); ++i) {
+        const Attribute& attribute = begin[i];
+        if (attribute.name().matches(name))
+            return i;
+    }
+    return notFound;
+}
+
+// We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller
+// can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not).
+inline size_t ElementData::getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const
+{
+    unsigned len = length();
+    bool doSlowCheck = shouldIgnoreAttributeCase;
+
+    // Optimize for the case where the attribute exists and its name exactly matches.
+    const Attribute* begin = attributeBase();
+    for (unsigned i = 0; i < len; ++i) {
+        const Attribute& attribute = begin[i];
+        if (!attribute.name().hasPrefix()) {
+            if (name == attribute.localName())
+                return i;
+        } else
+            doSlowCheck = true;
+    }
+
+    if (doSlowCheck)
+        return getAttributeItemIndexSlowCase(name, shouldIgnoreAttributeCase);
+    return notFound;
+}
+
+inline const Attribute* ElementData::getAttributeItem(const QualifiedName& name) const
+{
+    const Attribute* begin = attributeBase();
+    for (unsigned i = 0; i < length(); ++i) {
+        const Attribute& attribute = begin[i];
+        if (attribute.name().matches(name))
+            return &attribute;
+    }
+    return 0;
+}
+
+inline const Attribute* ElementData::attributeItem(unsigned index) const
+{
+    RELEASE_ASSERT(index < length());
+    return attributeBase() + index;
+}
+
+} // namespace
+
+#endif
diff --git a/Source/core/dom/Element.idl b/Source/core/dom/Element.idl
new file mode 100644
index 0000000..76136bc
--- /dev/null
+++ b/Source/core/dom/Element.idl
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+[
+    CustomToV8,
+    SkipVTableValidation
+] interface Element : Node {
+
+    // DOM Level 1 Core
+
+    [TreatReturnedNullStringAs=Null, PerWorldBindings] readonly attribute DOMString tagName;
+
+    [TreatReturnedNullStringAs=Null] DOMString getAttribute([Default=Undefined] optional DOMString name);
+     [RaisesException] void setAttribute([Default=Undefined] optional DOMString name,
+                                     [Default=Undefined] optional DOMString value);
+    void removeAttribute([Default=Undefined] optional DOMString name);
+    Attr getAttributeNode([Default=Undefined] optional DOMString name);
+    [RaisesException] Attr setAttributeNode([Default=Undefined] optional Attr newAttr);
+    [RaisesException] Attr removeAttributeNode([Default=Undefined] optional Attr oldAttr);
+    [PerWorldBindings] NodeList getElementsByTagName([Default=Undefined] optional DOMString name);
+
+    // For ObjC this is defined on Node for legacy support.
+    [PerWorldBindings] readonly attribute NamedNodeMap     attributes;
+    boolean            hasAttributes();
+
+    // DOM Level 2 Core
+
+     DOMString getAttributeNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
+                                            [Default=Undefined] optional DOMString localName);
+     [RaisesException] void setAttributeNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
+                                       [Default=Undefined] optional DOMString qualifiedName,
+                                       [Default=Undefined] optional DOMString value);
+     void removeAttributeNS([TreatNullAs=NullString] DOMString namespaceURI,
+                                          DOMString localName);
+     NodeList getElementsByTagNameNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
+                                                   [Default=Undefined] optional DOMString localName);
+     Attr getAttributeNodeNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
+                                           [Default=Undefined] optional DOMString localName);
+    [RaisesException] Attr setAttributeNodeNS([Default=Undefined] optional Attr newAttr);
+    boolean hasAttribute(DOMString name);
+     boolean hasAttributeNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
+                                          [Default=Undefined] optional DOMString localName);
+
+    [PerWorldBindings] readonly attribute CSSStyleDeclaration style;
+
+    // Common extensions
+
+    [PerWorldBindings] readonly attribute long offsetLeft;
+    [PerWorldBindings] readonly attribute long offsetTop;
+    [PerWorldBindings] readonly attribute long offsetWidth;
+    [PerWorldBindings] readonly attribute long offsetHeight;
+    [ImplementedAs=bindingsOffsetParent, PerWorldBindings] readonly attribute Element offsetParent;
+    [PerWorldBindings] readonly attribute long clientLeft;
+    [PerWorldBindings] readonly attribute long clientTop;
+    [PerWorldBindings] readonly attribute long clientWidth;
+    [PerWorldBindings] readonly attribute long clientHeight;
+             [PerWorldBindings] attribute long scrollLeft;
+             [PerWorldBindings] attribute long scrollTop;
+    [PerWorldBindings] readonly attribute long scrollWidth;
+    [PerWorldBindings] readonly attribute long scrollHeight;
+
+    void focus();
+    void blur();
+    void scrollIntoView(optional boolean alignWithTop);
+
+    // WebKit extensions
+
+    void scrollIntoViewIfNeeded(optional boolean centerIfNeeded);
+    void scrollByLines([Default=Undefined] optional long lines);
+    void scrollByPages([Default=Undefined] optional long pages);
+
+    // HTML 5
+    NodeList getElementsByClassName([Default=Undefined] optional DOMString name);
+
+    [Reflect=class, PerWorldBindings] attribute DOMString className;
+    [PerWorldBindings] readonly attribute DOMTokenList classList;
+
+    [PerWorldBindings] readonly attribute DOMStringMap dataset;
+
+    // NodeSelector - Selector API
+    [RaisesException] Element querySelector(DOMString selectors);
+    [RaisesException] NodeList querySelectorAll(DOMString selectors);
+
+    // WebKit extension, pending specification.
+    [RaisesException] boolean webkitMatchesSelector([Default=Undefined] optional DOMString selectors);
+
+    // ElementTraversal API
+    [PerWorldBindings] readonly attribute Element firstElementChild;
+    [PerWorldBindings] readonly attribute Element lastElementChild;
+    [PerWorldBindings] readonly attribute Element previousElementSibling;
+    [PerWorldBindings] readonly attribute Element nextElementSibling;
+    [PerWorldBindings] readonly attribute unsigned long childElementCount;
+
+    // ShadowAware API
+    [Reflect=pseudo, ImplementedAs=pseudo, PerWorldBindings] attribute DOMString webkitPseudo;
+    [ImplementedAs=createShadowRoot, RaisesException] ShadowRoot webkitCreateShadowRoot();
+    [ImplementedAs=shadowRoot, PerWorldBindings] readonly attribute ShadowRoot webkitShadowRoot;
+    [ImplementedAs=insertionParentForBinding, PerWorldBindings] readonly attribute Node webkitInsertionParent;
+
+    // DOM 4
+    [RaisesException] void remove();
+
+    // CSSOM View Module API
+    ClientRectList getClientRects();
+    ClientRect getBoundingClientRect();
+
+    // Mozilla version
+    const unsigned short ALLOW_KEYBOARD_INPUT = 1;
+    [EnabledAtRuntime=fullscreen] void webkitRequestFullScreen([Default=Undefined] optional unsigned short flags);
+
+    // W3C version
+    [EnabledAtRuntime=fullscreen] void webkitRequestFullscreen();
+
+    void webkitRequestPointerLock();
+
+    // CSS Regions API
+    [EnabledAtRuntime=cssRegions, PerWorldBindings] readonly attribute DOMString webkitRegionOverset;
+    [EnabledAtRuntime=cssRegions] sequence<Range> webkitGetRegionFlowRanges();
+
+    // Event handler DOM attributes
+    [NotEnumerable, PerWorldBindings] attribute EventListener onabort;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onblur;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onchange;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onclick;
+    [NotEnumerable, PerWorldBindings] attribute EventListener oncontextmenu;
+    [NotEnumerable, PerWorldBindings] attribute EventListener ondblclick;
+    [NotEnumerable, PerWorldBindings] attribute EventListener ondrag;
+    [NotEnumerable, PerWorldBindings] attribute EventListener ondragend;
+    [NotEnumerable, PerWorldBindings] attribute EventListener ondragenter;
+    [NotEnumerable, PerWorldBindings] attribute EventListener ondragleave;
+    [NotEnumerable, PerWorldBindings] attribute EventListener ondragover;
+    [NotEnumerable, PerWorldBindings] attribute EventListener ondragstart;
+    [NotEnumerable, PerWorldBindings] attribute EventListener ondrop;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onerror;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onfocus;
+    [NotEnumerable, PerWorldBindings] attribute EventListener oninput;
+    [NotEnumerable, PerWorldBindings] attribute EventListener oninvalid;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onkeydown;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onkeypress;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onkeyup;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onload;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onmousedown;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onmousemove;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onmouseout;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onmouseover;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onmouseup;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onmousewheel;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onscroll;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onselect;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onsubmit;
+
+    // attribute [NotEnumerable] EventListener oncanplay;
+    // attribute [NotEnumerable] EventListener oncanplaythrough;
+    // attribute [NotEnumerable] EventListener ondurationchange;
+    // attribute [NotEnumerable] EventListener onemptied;
+    // attribute [NotEnumerable] EventListener onended;
+    // attribute [NotEnumerable] EventListener onloadeddata;
+    // attribute [NotEnumerable] EventListener onloadedmetadata;
+    // attribute [NotEnumerable] EventListener onloadstart;
+    // attribute [NotEnumerable] EventListener onpause;
+    // attribute [NotEnumerable] EventListener onplay;
+    // attribute [NotEnumerable] EventListener onplaying;
+    // attribute [NotEnumerable] EventListener onprogress;
+    // attribute [NotEnumerable] EventListener onratechange;
+    // attribute [NotEnumerable] EventListener onreadystatechange;
+    // attribute [NotEnumerable] EventListener onseeked;
+    // attribute [NotEnumerable] EventListener onseeking;
+    // attribute [NotEnumerable] EventListener onshow;
+    // attribute [NotEnumerable] EventListener onstalled;
+    // attribute [NotEnumerable] EventListener onsuspend;
+    // attribute [NotEnumerable] EventListener ontimeupdate;
+    // attribute [NotEnumerable] EventListener onvolumechange;
+    // attribute [NotEnumerable] EventListener onwaiting;
+
+    // WebKit extensions
+    [NotEnumerable, PerWorldBindings] attribute EventListener onbeforecut;
+    [NotEnumerable, PerWorldBindings] attribute EventListener oncut;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onbeforecopy;
+    [NotEnumerable, PerWorldBindings] attribute EventListener oncopy;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onbeforepaste;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onpaste;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onreset;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onsearch;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onselectstart;
+    [NotEnumerable, EnabledAtRuntime=touch, PerWorldBindings] attribute EventListener ontouchstart;
+    [NotEnumerable, EnabledAtRuntime=touch, PerWorldBindings] attribute EventListener ontouchmove;
+    [NotEnumerable, EnabledAtRuntime=touch, PerWorldBindings] attribute EventListener ontouchend;
+    [NotEnumerable, EnabledAtRuntime=touch, PerWorldBindings] attribute EventListener ontouchcancel;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onwebkitfullscreenchange;
+    [NotEnumerable, PerWorldBindings] attribute EventListener onwebkitfullscreenerror;
+};
+
diff --git a/Source/core/dom/ElementRareData.cpp b/Source/core/dom/ElementRareData.cpp
new file mode 100644
index 0000000..72ce782
--- /dev/null
+++ b/Source/core/dom/ElementRareData.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/ElementRareData.h"
+
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/rendering/style/RenderStyle.h"
+
+namespace WebCore {
+
+struct SameSizeAsElementRareData : NodeRareData {
+    short indices[2];
+    unsigned bitfields;
+    LayoutSize sizeForResizing;
+    IntSize scrollOffset;
+    void* pointers[7];
+};
+
+COMPILE_ASSERT(sizeof(ElementRareData) == sizeof(SameSizeAsElementRareData), ElementRareDataShouldStaySmall);
+
+void ElementRareData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    NodeRareData::reportMemoryUsage(memoryObjectInfo);
+
+    info.addMember(m_computedStyle, "computedStyle");
+    info.addMember(m_dataset, "dataset");
+    info.addMember(m_classList, "classList");
+    info.addMember(m_shadow, "shadow");
+    info.addMember(m_attributeMap, "attributeMap");
+    info.addMember(m_generatedBefore, "generatedBefore");
+    info.addMember(m_generatedAfter, "generatedAfter");
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/ElementRareData.h b/Source/core/dom/ElementRareData.h
new file mode 100644
index 0000000..effc75d
--- /dev/null
+++ b/Source/core/dom/ElementRareData.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 David Smith <catfish.man@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ElementRareData_h
+#define ElementRareData_h
+
+#include "core/dom/DatasetDOMStringMap.h"
+#include "core/dom/ElementShadow.h"
+#include "core/dom/NamedNodeMap.h"
+#include "core/dom/NodeRareData.h"
+#include "core/dom/PseudoElement.h"
+#include "core/html/ClassList.h"
+#include "core/rendering/style/StyleInheritedData.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class ElementRareData : public NodeRareData {
+public:
+    static PassOwnPtr<ElementRareData> create(RenderObject* renderer) { return adoptPtr(new ElementRareData(renderer)); }
+
+    ~ElementRareData();
+
+    void setPseudoElement(PseudoId, PassRefPtr<PseudoElement>);
+    PseudoElement* pseudoElement(PseudoId) const;
+    bool hasPseudoElements() const { return m_generatedBefore || m_generatedAfter; }
+
+    void resetComputedStyle();
+    void resetDynamicRestyleObservations();
+    
+    short tabIndex() const { return m_tabIndex; }
+    void setTabIndexExplicitly(short index) { m_tabIndex = index; m_tabIndexWasSetExplicitly = true; }
+    bool tabIndexSetExplicitly() const { return m_tabIndexWasSetExplicitly; }
+    void clearTabIndexExplicitly() { m_tabIndex = 0; m_tabIndexWasSetExplicitly = false; }
+
+    bool needsFocusAppearanceUpdateSoonAfterAttach() const { return m_needsFocusAppearanceUpdateSoonAfterAttach; }
+    void setNeedsFocusAppearanceUpdateSoonAfterAttach(bool needs) { m_needsFocusAppearanceUpdateSoonAfterAttach = needs; }
+
+    bool styleAffectedByEmpty() const { return m_styleAffectedByEmpty; }
+    void setStyleAffectedByEmpty(bool value) { m_styleAffectedByEmpty = value; }
+
+    bool isInCanvasSubtree() const { return m_isInCanvasSubtree; }
+    void setIsInCanvasSubtree(bool value) { m_isInCanvasSubtree = value; }
+
+    bool containsFullScreenElement() { return m_containsFullScreenElement; }
+    void setContainsFullScreenElement(bool value) { m_containsFullScreenElement = value; }
+
+    bool isInTopLayer() const { return m_isInTopLayer; }
+    void setIsInTopLayer(bool value) { m_isInTopLayer = value; }
+
+    bool childrenAffectedByHover() const { return m_childrenAffectedByHover; }
+    void setChildrenAffectedByHover(bool value) { m_childrenAffectedByHover = value; }
+    bool childrenAffectedByActive() const { return m_childrenAffectedByActive; }
+    void setChildrenAffectedByActive(bool value) { m_childrenAffectedByActive = value; }
+    bool childrenAffectedByDrag() const { return m_childrenAffectedByDrag; }
+    void setChildrenAffectedByDrag(bool value) { m_childrenAffectedByDrag = value; }
+
+    bool childrenAffectedByFirstChildRules() const { return m_childrenAffectedByFirstChildRules; }
+    void setChildrenAffectedByFirstChildRules(bool value) { m_childrenAffectedByFirstChildRules = value; }
+    bool childrenAffectedByLastChildRules() const { return m_childrenAffectedByLastChildRules; }
+    void setChildrenAffectedByLastChildRules(bool value) { m_childrenAffectedByLastChildRules = value; }
+    bool childrenAffectedByDirectAdjacentRules() const { return m_childrenAffectedByDirectAdjacentRules; }
+    void setChildrenAffectedByDirectAdjacentRules(bool value) { m_childrenAffectedByDirectAdjacentRules = value; }
+    bool childrenAffectedByForwardPositionalRules() const { return m_childrenAffectedByForwardPositionalRules; }
+    void setChildrenAffectedByForwardPositionalRules(bool value) { m_childrenAffectedByForwardPositionalRules = value; }
+    bool childrenAffectedByBackwardPositionalRules() const { return m_childrenAffectedByBackwardPositionalRules; }
+    void setChildrenAffectedByBackwardPositionalRules(bool value) { m_childrenAffectedByBackwardPositionalRules = value; }
+    unsigned childIndex() const { return m_childIndex; }
+    void setChildIndex(unsigned index) { m_childIndex = index; }
+
+    // Manually called by Node::reportMemoryUsage.
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+    void clearShadow() { m_shadow = nullptr; }
+    ElementShadow* shadow() const { return m_shadow.get(); }
+    ElementShadow* ensureShadow()
+    {
+        if (!m_shadow)
+            m_shadow = ElementShadow::create();
+        return m_shadow.get();
+    }
+
+    NamedNodeMap* attributeMap() const { return m_attributeMap.get(); }
+    void setAttributeMap(PassOwnPtr<NamedNodeMap> attributeMap) { m_attributeMap = attributeMap; }
+
+    RenderStyle* computedStyle() const { return m_computedStyle.get(); }
+    void setComputedStyle(PassRefPtr<RenderStyle> computedStyle) { m_computedStyle = computedStyle; }
+
+    ClassList* classList() const { return m_classList.get(); }
+    void setClassList(PassOwnPtr<ClassList> classList) { m_classList = classList; }
+    void clearClassListValueForQuirksMode()
+    {
+        if (!m_classList)
+            return;
+        m_classList->clearValueForQuirksMode();
+    }
+
+    DatasetDOMStringMap* dataset() const { return m_dataset.get(); }
+    void setDataset(PassOwnPtr<DatasetDOMStringMap> dataset) { m_dataset = dataset; }
+
+    LayoutSize minimumSizeForResizing() const { return m_minimumSizeForResizing; }
+    void setMinimumSizeForResizing(LayoutSize size) { m_minimumSizeForResizing = size; }
+
+    IntSize savedLayerScrollOffset() const { return m_savedLayerScrollOffset; }
+    void setSavedLayerScrollOffset(IntSize size) { m_savedLayerScrollOffset = size; }
+
+#if ENABLE(SVG)
+    bool hasPendingResources() const { return m_hasPendingResources; }
+    void setHasPendingResources(bool has) { m_hasPendingResources = has; }
+#endif
+
+private:
+    short m_tabIndex;
+    unsigned short m_childIndex;
+    unsigned m_tabIndexWasSetExplicitly : 1;
+    unsigned m_needsFocusAppearanceUpdateSoonAfterAttach : 1;
+    unsigned m_styleAffectedByEmpty : 1;
+    unsigned m_isInCanvasSubtree : 1;
+    unsigned m_containsFullScreenElement : 1;
+    unsigned m_isInTopLayer : 1;
+#if ENABLE(SVG)
+    unsigned m_hasPendingResources : 1;
+#endif
+    unsigned m_childrenAffectedByHover : 1;
+    unsigned m_childrenAffectedByActive : 1;
+    unsigned m_childrenAffectedByDrag : 1;
+    // Bits for dynamic child matching.
+    // We optimize for :first-child and :last-child. The other positional child selectors like nth-child or
+    // *-child-of-type, we will just give up and re-evaluate whenever children change at all.
+    unsigned m_childrenAffectedByFirstChildRules : 1;
+    unsigned m_childrenAffectedByLastChildRules : 1;
+    unsigned m_childrenAffectedByDirectAdjacentRules : 1;
+    unsigned m_childrenAffectedByForwardPositionalRules : 1;
+    unsigned m_childrenAffectedByBackwardPositionalRules : 1;
+
+    LayoutSize m_minimumSizeForResizing;
+    IntSize m_savedLayerScrollOffset;
+    RefPtr<RenderStyle> m_computedStyle;
+
+    OwnPtr<DatasetDOMStringMap> m_dataset;
+    OwnPtr<ClassList> m_classList;
+    OwnPtr<ElementShadow> m_shadow;
+    OwnPtr<NamedNodeMap> m_attributeMap;
+
+    RefPtr<PseudoElement> m_generatedBefore;
+    RefPtr<PseudoElement> m_generatedAfter;
+
+    ElementRareData(RenderObject*);
+    void releasePseudoElement(PseudoElement*);
+};
+
+inline IntSize defaultMinimumSizeForResizing()
+{
+    return IntSize(LayoutUnit::max(), LayoutUnit::max());
+}
+
+inline ElementRareData::ElementRareData(RenderObject* renderer)
+    : NodeRareData(renderer)
+    , m_tabIndex(0)
+    , m_childIndex(0)
+    , m_tabIndexWasSetExplicitly(false)
+    , m_needsFocusAppearanceUpdateSoonAfterAttach(false)
+    , m_styleAffectedByEmpty(false)
+    , m_isInCanvasSubtree(false)
+    , m_containsFullScreenElement(false)
+    , m_isInTopLayer(false)
+#if ENABLE(SVG)
+    , m_hasPendingResources(false)
+#endif
+    , m_childrenAffectedByHover(false)
+    , m_childrenAffectedByActive(false)
+    , m_childrenAffectedByDrag(false)
+    , m_childrenAffectedByFirstChildRules(false)
+    , m_childrenAffectedByLastChildRules(false)
+    , m_childrenAffectedByDirectAdjacentRules(false)
+    , m_childrenAffectedByForwardPositionalRules(false)
+    , m_childrenAffectedByBackwardPositionalRules(false)
+    , m_minimumSizeForResizing(defaultMinimumSizeForResizing())
+{
+}
+
+inline ElementRareData::~ElementRareData()
+{
+    ASSERT(!m_shadow);
+    ASSERT(!m_generatedBefore);
+    ASSERT(!m_generatedAfter);
+}
+
+inline void ElementRareData::setPseudoElement(PseudoId pseudoId, PassRefPtr<PseudoElement> element)
+{
+    switch (pseudoId) {
+    case BEFORE:
+        releasePseudoElement(m_generatedBefore.get());
+        m_generatedBefore = element;
+        break;
+    case AFTER:
+        releasePseudoElement(m_generatedAfter.get());
+        m_generatedAfter = element;
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+}
+
+inline PseudoElement* ElementRareData::pseudoElement(PseudoId pseudoId) const
+{
+    switch (pseudoId) {
+    case BEFORE:
+        return m_generatedBefore.get();
+    case AFTER:
+        return m_generatedAfter.get();
+    default:
+        return 0;
+    }
+}
+
+inline void ElementRareData::releasePseudoElement(PseudoElement* element)
+{
+    if (!element)
+        return;
+
+    if (element->attached())
+        element->detach();
+
+    ASSERT(!element->nextSibling());
+    ASSERT(!element->previousSibling());
+
+    element->setParentOrShadowHostNode(0);
+}
+
+inline void ElementRareData::resetComputedStyle()
+{
+    setComputedStyle(0);
+    setStyleAffectedByEmpty(false);
+    setChildIndex(0);
+}
+
+inline void ElementRareData::resetDynamicRestyleObservations()
+{
+    setChildrenAffectedByHover(false);
+    setChildrenAffectedByActive(false);
+    setChildrenAffectedByDrag(false);
+    setChildrenAffectedByFirstChildRules(false);
+    setChildrenAffectedByLastChildRules(false);
+    setChildrenAffectedByDirectAdjacentRules(false);
+    setChildrenAffectedByForwardPositionalRules(false);
+    setChildrenAffectedByBackwardPositionalRules(false);
+}
+
+} // namespace
+
+#endif // ElementRareData_h
diff --git a/Source/core/dom/ElementShadow.cpp b/Source/core/dom/ElementShadow.cpp
new file mode 100644
index 0000000..9fe6b93
--- /dev/null
+++ b/Source/core/dom/ElementShadow.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2012 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 "core/dom/ElementShadow.h"
+
+#include "core/dom/ContainerNodeAlgorithms.h"
+#include "core/inspector/InspectorInstrumentation.h"
+
+namespace WebCore {
+
+ShadowRoot* ElementShadow::addShadowRoot(Element* shadowHost, ShadowRoot::ShadowRootType type)
+{
+    RefPtr<ShadowRoot> shadowRoot = ShadowRoot::create(shadowHost->document(), type);
+
+    shadowRoot->setParentOrShadowHostNode(shadowHost);
+    shadowRoot->setParentTreeScope(shadowHost->treeScope());
+    m_shadowRoots.push(shadowRoot.get());
+    m_distributor.didShadowBoundaryChange(shadowHost);
+    ChildNodeInsertionNotifier(shadowHost).notify(shadowRoot.get());
+
+    // Existence of shadow roots requires the host and its children to do traversal using ComposedShadowTreeWalker.
+    shadowHost->setNeedsShadowTreeWalker();
+
+    // FIXME(94905): ShadowHost should be reattached during recalcStyle.
+    // Set some flag here and recreate shadow hosts' renderer in
+    // Element::recalcStyle.
+    if (shadowHost->attached())
+        shadowHost->lazyReattach();
+
+    InspectorInstrumentation::didPushShadowRoot(shadowHost, shadowRoot.get());
+
+    return shadowRoot.get();
+}
+
+void ElementShadow::removeAllShadowRoots()
+{
+    // Dont protect this ref count.
+    Element* shadowHost = host();
+
+    while (RefPtr<ShadowRoot> oldRoot = m_shadowRoots.head()) {
+        InspectorInstrumentation::willPopShadowRoot(shadowHost, oldRoot.get());
+        shadowHost->document()->removeFocusedNodeOfSubtree(oldRoot.get());
+
+        if (oldRoot->attached())
+            oldRoot->detach();
+
+        m_shadowRoots.removeHead();
+        oldRoot->setParentOrShadowHostNode(0);
+        oldRoot->setParentTreeScope(shadowHost->document());
+        oldRoot->setPrev(0);
+        oldRoot->setNext(0);
+        ChildNodeRemovalNotifier(shadowHost).notify(oldRoot.get());
+    }
+
+    m_distributor.invalidateDistribution(shadowHost);
+}
+
+void ElementShadow::attach()
+{
+    ContentDistributor::ensureDistribution(youngestShadowRoot());
+
+    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
+        if (!root->attached())
+            root->attach();
+    }
+}
+
+void ElementShadow::detach()
+{
+    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
+        if (root->attached())
+            root->detach();
+    }
+}
+
+bool ElementShadow::childNeedsStyleRecalc() const
+{
+    ASSERT(youngestShadowRoot());
+    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot())
+        if (root->childNeedsStyleRecalc())
+            return true;
+
+    return false;
+}
+
+bool ElementShadow::needsStyleRecalc() const
+{
+    ASSERT(youngestShadowRoot());
+    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot())
+        if (root->needsStyleRecalc())
+            return true;
+
+    return false;
+}
+
+void ElementShadow::recalcStyle(Node::StyleChange change)
+{
+    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot())
+        root->recalcStyle(change);
+}
+
+void ElementShadow::removeAllEventListeners()
+{
+    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
+        for (Node* node = root; node; node = NodeTraversal::next(node))
+            node->removeAllEventListeners();
+    }
+}
+
+void ElementShadow::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    info.addMember(m_shadowRoots, "shadowRoots");
+    ShadowRoot* shadowRoot = m_shadowRoots.head();
+    while (shadowRoot) {
+        info.addMember(shadowRoot, "shadowRoot");
+        shadowRoot = shadowRoot->next();
+    }
+    info.addMember(m_distributor, "distributor");
+}
+
+} // namespace
diff --git a/Source/core/dom/ElementShadow.h b/Source/core/dom/ElementShadow.h
new file mode 100644
index 0000000..3276f65
--- /dev/null
+++ b/Source/core/dom/ElementShadow.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2012 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 ElementShadow_h
+#define ElementShadow_h
+
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/html/shadow/ContentDistributor.h"
+#include <wtf/DoublyLinkedList.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class ElementShadow {
+   WTF_MAKE_NONCOPYABLE(ElementShadow); WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<ElementShadow> create()
+    {
+        return adoptPtr(new ElementShadow());
+    }
+
+    ~ElementShadow()
+    {
+        removeAllShadowRoots();
+    }
+
+    Element* host() const;
+    ShadowRoot* youngestShadowRoot() const { return m_shadowRoots.head(); }
+    ShadowRoot* oldestShadowRoot() const { return m_shadowRoots.tail(); }
+    ElementShadow* containingShadow() const;
+
+    ShadowRoot* addShadowRoot(Element* shadowHost, ShadowRoot::ShadowRootType);
+
+    void attach();
+    void detach();
+
+    bool childNeedsStyleRecalc() const;
+    bool needsStyleRecalc() const;
+    void recalcStyle(Node::StyleChange);
+    void removeAllEventListeners();
+
+    void invalidateDistribution() { m_distributor.invalidateDistribution(host()); }
+    void didAffectSelector(AffectedSelectorMask mask) { m_distributor.didAffectSelector(host(), mask); }
+    void willAffectSelector() { m_distributor.willAffectSelector(host()); }
+
+    ContentDistributor& distributor() { return m_distributor; }
+    const ContentDistributor& distributor() const { return m_distributor; }
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+private:
+    ElementShadow() { }
+
+    void removeAllShadowRoots();
+
+    DoublyLinkedList<ShadowRoot> m_shadowRoots;
+    ContentDistributor m_distributor;
+};
+
+inline Element* ElementShadow::host() const
+{
+    ASSERT(!m_shadowRoots.isEmpty());
+    return youngestShadowRoot()->host();
+}
+
+inline ShadowRoot* Node::youngestShadowRoot() const
+{
+    if (!this->isElementNode())
+        return 0;
+    if (ElementShadow* shadow = toElement(this)->shadow())
+        return shadow->youngestShadowRoot();
+    return 0;
+}
+
+inline ElementShadow* ElementShadow::containingShadow() const
+{
+    if (ShadowRoot* parentRoot = host()->containingShadowRoot())
+        return parentRoot->owner();
+    return 0;
+}
+
+class ShadowRootVector : public Vector<RefPtr<ShadowRoot> > {
+public:
+    explicit ShadowRootVector(ElementShadow* tree)
+    {
+        for (ShadowRoot* root = tree->youngestShadowRoot(); root; root = root->olderShadowRoot())
+            append(root);
+    }
+};
+
+inline ElementShadow* shadowOfParent(const Node* node)
+{
+    if (!node)
+        return 0;
+    if (Node* parent = node->parentNode())
+        if (parent->isElementNode())
+            return toElement(parent)->shadow();
+    return 0;
+}
+
+
+} // namespace
+
+#endif
diff --git a/Source/core/dom/Entity.h b/Source/core/dom/Entity.h
new file mode 100644
index 0000000..f49d26a
--- /dev/null
+++ b/Source/core/dom/Entity.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2000 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Entity_h
+#define Entity_h
+
+#include "core/dom/ContainerNode.h"
+
+namespace WebCore {
+
+// FIXME: This abstract class is only here so that the JavaScript and bindings can continue to be compiled.
+class Entity : public ContainerNode {
+public:
+    String publicId() const { ASSERT_NOT_REACHED(); return String(); }
+    String systemId() const { ASSERT_NOT_REACHED(); return String(); }
+    String notationName() const { ASSERT_NOT_REACHED(); return String(); }
+
+private:
+    Entity() : ContainerNode(0)
+    {
+        ScriptWrappable::init(this);
+    }
+};
+
+} //namespace
+
+#endif
diff --git a/Source/core/dom/Entity.idl b/Source/core/dom/Entity.idl
new file mode 100644
index 0000000..7f5bf4b
--- /dev/null
+++ b/Source/core/dom/Entity.idl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+[
+    ImplementationLacksVTable
+] interface Entity : Node {
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString publicId;
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString systemId;
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString notationName;
+};
+
diff --git a/Source/core/dom/EntityReference.cpp b/Source/core/dom/EntityReference.cpp
new file mode 100644
index 0000000..f461e28
--- /dev/null
+++ b/Source/core/dom/EntityReference.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2000 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/EntityReference.h"
+
+#include "core/dom/Document.h"
+
+namespace WebCore {
+
+inline EntityReference::EntityReference(Document* document, const String& entityName)
+    : ContainerNode(document)
+    , m_entityName(entityName)
+{
+    ScriptWrappable::init(this);
+}
+
+PassRefPtr<EntityReference> EntityReference::create(Document* document, const String& entityName)
+{
+    return adoptRef(new EntityReference(document, entityName));
+}
+
+String EntityReference::nodeName() const
+{
+    return m_entityName;
+}
+
+Node::NodeType EntityReference::nodeType() const
+{
+    return ENTITY_REFERENCE_NODE;
+}
+
+PassRefPtr<Node> EntityReference::cloneNode(bool)
+{
+    return create(document(), m_entityName);
+}
+
+} // namespace
diff --git a/Source/core/dom/EntityReference.h b/Source/core/dom/EntityReference.h
new file mode 100644
index 0000000..31320a7
--- /dev/null
+++ b/Source/core/dom/EntityReference.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2000 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef EntityReference_h
+#define EntityReference_h
+
+#include "core/dom/ContainerNode.h"
+
+namespace WebCore {
+
+class EntityReference FINAL : public ContainerNode {
+public:
+    static PassRefPtr<EntityReference> create(Document*, const String& entityName);
+
+private:
+    EntityReference(Document*, const String& entityName);
+
+    virtual String nodeName() const;
+    virtual NodeType nodeType() const;
+    virtual PassRefPtr<Node> cloneNode(bool deep);
+
+    String m_entityName;
+};
+
+} //namespace
+
+#endif
diff --git a/Source/core/dom/EntityReference.idl b/Source/core/dom/EntityReference.idl
new file mode 100644
index 0000000..363554a
--- /dev/null
+++ b/Source/core/dom/EntityReference.idl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+interface EntityReference : Node {
+};
+
diff --git a/Source/core/dom/ErrorEvent.cpp b/Source/core/dom/ErrorEvent.cpp
new file mode 100644
index 0000000..f9f4638
--- /dev/null
+++ b/Source/core/dom/ErrorEvent.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/ErrorEvent.h"
+
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+ErrorEventInit::ErrorEventInit()
+    : message()
+    , filename()
+    , lineno(0)
+{
+}
+
+ErrorEvent::ErrorEvent()
+{
+    ScriptWrappable::init(this);
+}
+
+ErrorEvent::ErrorEvent(const AtomicString& type, const ErrorEventInit& initializer)
+    : Event(type, initializer)
+    , m_message(initializer.message)
+    , m_fileName(initializer.filename)
+    , m_lineNumber(initializer.lineno)
+{
+    ScriptWrappable::init(this);
+}
+
+ErrorEvent::ErrorEvent(const String& message, const String& fileName, unsigned lineNumber)
+    : Event(eventNames().errorEvent, false, true)
+    , m_message(message)
+    , m_fileName(fileName)
+    , m_lineNumber(lineNumber)
+{
+    ScriptWrappable::init(this);
+}
+
+ErrorEvent::~ErrorEvent()
+{
+}
+
+const AtomicString& ErrorEvent::interfaceName() const
+{
+    return eventNames().interfaceForErrorEvent;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/ErrorEvent.h b/Source/core/dom/ErrorEvent.h
new file mode 100644
index 0000000..7992ec3
--- /dev/null
+++ b/Source/core/dom/ErrorEvent.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ErrorEvent_h
+#define ErrorEvent_h
+
+#include "core/dom/Event.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+struct ErrorEventInit : public EventInit {
+    ErrorEventInit();
+
+    String message;
+    String filename;
+    unsigned lineno;
+};
+
+class ErrorEvent : public Event {
+public:
+    static PassRefPtr<ErrorEvent> create()
+    {
+        return adoptRef(new ErrorEvent);
+    }
+    static PassRefPtr<ErrorEvent> create(const String& message, const String& fileName, unsigned lineNumber)
+    {
+        return adoptRef(new ErrorEvent(message, fileName, lineNumber));
+    }
+    static PassRefPtr<ErrorEvent> create(const AtomicString& type, const ErrorEventInit& initializer)
+    {
+        return adoptRef(new ErrorEvent(type, initializer));
+    }
+    virtual ~ErrorEvent();
+
+    const String& message() const { return m_message; }
+    const String& filename() const { return m_fileName; }
+    unsigned lineno() const { return m_lineNumber; }
+
+    virtual const AtomicString& interfaceName() const;
+
+private:
+    ErrorEvent();
+    ErrorEvent(const String& message, const String& fileName, unsigned lineNumber);
+    ErrorEvent(const AtomicString&, const ErrorEventInit&);
+
+    String m_message;
+    String m_fileName;
+    unsigned m_lineNumber;
+};
+
+} // namespace WebCore
+
+#endif // ErrorEvent_h
diff --git a/Source/core/dom/ErrorEvent.idl b/Source/core/dom/ErrorEvent.idl
new file mode 100644
index 0000000..612a970
--- /dev/null
+++ b/Source/core/dom/ErrorEvent.idl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    ConstructorTemplate=Event
+] interface ErrorEvent : Event {
+    [InitializedByEventConstructor] readonly attribute DOMString message;
+    [InitializedByEventConstructor] readonly attribute DOMString filename;
+    [InitializedByEventConstructor] readonly attribute unsigned long lineno;
+};
+
diff --git a/Source/core/dom/Event.cpp b/Source/core/dom/Event.cpp
new file mode 100644
index 0000000..637ca94
--- /dev/null
+++ b/Source/core/dom/Event.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/Event.h"
+
+#include "core/dom/EventDispatcher.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/EventTarget.h"
+#include "core/dom/UserGestureIndicator.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+EventInit::EventInit()
+    : bubbles(false)
+    , cancelable(false)
+{
+}
+
+
+Event::Event()
+    : m_canBubble(false)
+    , m_cancelable(false)
+    , m_propagationStopped(false)
+    , m_immediatePropagationStopped(false)
+    , m_defaultPrevented(false)
+    , m_defaultHandled(false)
+    , m_cancelBubble(false)
+    , m_eventPhase(0)
+    , m_currentTarget(0)
+    , m_createTime(convertSecondsToDOMTimeStamp(currentTime()))
+{
+    ScriptWrappable::init(this);
+}
+
+Event::Event(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg)
+    : m_type(eventType)
+    , m_canBubble(canBubbleArg)
+    , m_cancelable(cancelableArg)
+    , m_propagationStopped(false)
+    , m_immediatePropagationStopped(false)
+    , m_defaultPrevented(false)
+    , m_defaultHandled(false)
+    , m_cancelBubble(false)
+    , m_eventPhase(0)
+    , m_currentTarget(0)
+    , m_createTime(convertSecondsToDOMTimeStamp(currentTime()))
+{
+    ScriptWrappable::init(this);
+}
+
+Event::Event(const AtomicString& eventType, const EventInit& initializer)
+    : m_type(eventType)
+    , m_canBubble(initializer.bubbles)
+    , m_cancelable(initializer.cancelable)
+    , m_propagationStopped(false)
+    , m_immediatePropagationStopped(false)
+    , m_defaultPrevented(false)
+    , m_defaultHandled(false)
+    , m_cancelBubble(false)
+    , m_eventPhase(0)
+    , m_currentTarget(0)
+    , m_createTime(convertSecondsToDOMTimeStamp(currentTime()))
+{
+    ScriptWrappable::init(this);
+}
+
+Event::~Event()
+{
+}
+
+void Event::initEvent(const AtomicString& eventTypeArg, bool canBubbleArg, bool cancelableArg)
+{
+    if (dispatched())
+        return;
+
+    m_propagationStopped = false;
+    m_immediatePropagationStopped = false;
+    m_defaultPrevented = false;
+
+    m_type = eventTypeArg;
+    m_canBubble = canBubbleArg;
+    m_cancelable = cancelableArg;
+}
+
+const AtomicString& Event::interfaceName() const
+{
+    return eventNames().interfaceForEvent;
+}
+
+bool Event::hasInterface(const AtomicString& name) const
+{
+    return interfaceName() == name;
+}
+
+bool Event::isUIEvent() const
+{
+    return false;
+}
+
+bool Event::isMouseEvent() const
+{
+    return false;
+}
+
+bool Event::isFocusEvent() const
+{
+    return false;
+}
+
+bool Event::isKeyboardEvent() const
+{
+    return false;
+}
+
+bool Event::isTouchEvent() const
+{
+    return false;
+}
+
+bool Event::isDragEvent() const
+{
+    return false;
+}
+
+bool Event::isClipboardEvent() const
+{
+    return false;
+}
+
+bool Event::storesResultAsString() const
+{
+    return false;
+}
+
+bool Event::isBeforeTextInsertedEvent() const
+{
+    return false;
+}
+
+void Event::storeResult(const String&)
+{
+}
+
+void Event::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    info.addMember(m_type, "type");
+    info.addMember(m_currentTarget, "currentTarget");
+    info.addMember(m_target, "target");
+    info.addMember(m_underlyingEvent, "underlyingEvent");
+}
+
+PassRefPtr<Event> Event::cloneFor(HTMLIFrameElement*) const
+{
+    return Event::create(type(), bubbles(), cancelable());
+}
+
+void Event::setTarget(PassRefPtr<EventTarget> target)
+{
+    if (m_target == target)
+        return;
+
+    m_target = target;
+    if (m_target)
+        receivedTarget();
+}
+
+void Event::receivedTarget()
+{
+}
+
+void Event::setUnderlyingEvent(PassRefPtr<Event> ue)
+{
+    // Prohibit creation of a cycle -- just do nothing in that case.
+    for (Event* e = ue.get(); e; e = e->underlyingEvent())
+        if (e == this)
+            return;
+    m_underlyingEvent = ue;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/Event.h b/Source/core/dom/Event.h
new file mode 100644
index 0000000..1a2942e
--- /dev/null
+++ b/Source/core/dom/Event.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Event_h
+#define Event_h
+
+#include "bindings/v8/ScriptWrappable.h"
+#include "core/dom/DOMTimeStamp.h"
+#include "core/dom/EventContext.h"
+#include "core/dom/EventNames.h"
+#include <wtf/HashMap.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class Clipboard;
+class EventTarget;
+class EventDispatcher;
+class HTMLIFrameElement;
+
+struct EventInit {
+    EventInit();
+     
+    bool bubbles;
+    bool cancelable;
+};
+
+class Event : public ScriptWrappable, public RefCounted<Event> {
+public:
+    enum PhaseType { 
+        NONE                = 0,
+        CAPTURING_PHASE     = 1, 
+        AT_TARGET           = 2,
+        BUBBLING_PHASE      = 3 
+    };
+
+    enum EventType {
+        MOUSEDOWN           = 1,
+        MOUSEUP             = 2,
+        MOUSEOVER           = 4,
+        MOUSEOUT            = 8,
+        MOUSEMOVE           = 16,
+        MOUSEDRAG           = 32,
+        CLICK               = 64,
+        DBLCLICK            = 128,
+        KEYDOWN             = 256,
+        KEYUP               = 512,
+        KEYPRESS            = 1024,
+        DRAGDROP            = 2048,
+        FOCUS               = 4096,
+        BLUR                = 8192,
+        SELECT              = 16384,
+        CHANGE              = 32768
+    };
+
+    static PassRefPtr<Event> create()
+    {
+        return adoptRef(new Event);
+    }
+    static PassRefPtr<Event> create(const AtomicString& type, bool canBubble, bool cancelable)
+    {
+        return adoptRef(new Event(type, canBubble, cancelable));
+    }
+
+    static PassRefPtr<Event> create(const AtomicString& type, const EventInit& initializer)
+    {
+        return adoptRef(new Event(type, initializer));
+    }
+
+    virtual ~Event();
+
+    void initEvent(const AtomicString& type, bool canBubble, bool cancelable);
+
+    const AtomicString& type() const { return m_type; }
+    
+    EventTarget* target() const { return m_target.get(); }
+    void setTarget(PassRefPtr<EventTarget>);
+
+    EventTarget* currentTarget() const { return m_currentTarget; }
+    void setCurrentTarget(EventTarget* currentTarget) { m_currentTarget = currentTarget; }
+
+    unsigned short eventPhase() const { return m_eventPhase; }
+    void setEventPhase(unsigned short eventPhase) { m_eventPhase = eventPhase; }
+
+    bool bubbles() const { return m_canBubble; }
+    bool cancelable() const { return m_cancelable; }
+    DOMTimeStamp timeStamp() const { return m_createTime; }
+
+    void stopPropagation() { m_propagationStopped = true; }
+    void stopImmediatePropagation() { m_immediatePropagationStopped = true; }
+    
+    // IE Extensions
+    EventTarget* srcElement() const { return target(); } // MSIE extension - "the object that fired the event"
+
+    bool returnValue() const { return !defaultPrevented(); }
+    void setReturnValue(bool returnValue) { setDefaultPrevented(!returnValue); }
+
+    Clipboard* clipboardData() const { return isClipboardEvent() ? clipboard() : 0; }
+
+    virtual const AtomicString& interfaceName() const;
+    bool hasInterface(const AtomicString&) const;
+
+    // These events are general classes of events.
+    virtual bool isUIEvent() const;
+    virtual bool isMouseEvent() const;
+    virtual bool isFocusEvent() const;
+    virtual bool isKeyboardEvent() const;
+    virtual bool isTouchEvent() const;
+
+    // Drag events are a subset of mouse events.
+    virtual bool isDragEvent() const;
+
+    // These events lack a DOM interface.
+    virtual bool isClipboardEvent() const;
+    virtual bool isBeforeTextInsertedEvent() const;
+
+    bool propagationStopped() const { return m_propagationStopped || m_immediatePropagationStopped; }
+    bool immediatePropagationStopped() const { return m_immediatePropagationStopped; }
+
+    bool defaultPrevented() const { return m_defaultPrevented; }
+    void preventDefault()
+    {
+        if (m_cancelable)
+            m_defaultPrevented = true;
+    }
+    void setDefaultPrevented(bool defaultPrevented) { m_defaultPrevented = defaultPrevented; }
+
+    bool defaultHandled() const { return m_defaultHandled; }
+    void setDefaultHandled() { m_defaultHandled = true; }
+
+    bool cancelBubble() const { return m_cancelBubble; }
+    void setCancelBubble(bool cancel) { m_cancelBubble = cancel; }
+
+    Event* underlyingEvent() const { return m_underlyingEvent.get(); }
+    void setUnderlyingEvent(PassRefPtr<Event>);
+
+    EventPath& eventPath() { return m_eventPath; }
+
+    virtual bool storesResultAsString() const;
+    virtual void storeResult(const String&);
+
+    virtual Clipboard* clipboard() const { return 0; }
+
+    bool isBeingDispatched() const { return eventPhase(); }
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+
+    virtual PassRefPtr<Event> cloneFor(HTMLIFrameElement*) const;
+
+protected:
+    Event();
+    Event(const AtomicString& type, bool canBubble, bool cancelable);
+    Event(const AtomicString& type, const EventInit&);
+
+    virtual void receivedTarget();
+    bool dispatched() const { return m_target; }
+
+private:
+    AtomicString m_type;
+    bool m_canBubble;
+    bool m_cancelable;
+
+    bool m_propagationStopped;
+    bool m_immediatePropagationStopped;
+    bool m_defaultPrevented;
+    bool m_defaultHandled;
+    bool m_cancelBubble;
+
+    unsigned short m_eventPhase;
+    EventTarget* m_currentTarget;
+    RefPtr<EventTarget> m_target;
+    DOMTimeStamp m_createTime;
+    RefPtr<Event> m_underlyingEvent;
+    EventPath m_eventPath;
+};
+
+} // namespace WebCore
+
+#endif // Event_h
diff --git a/Source/core/dom/Event.idl b/Source/core/dom/Event.idl
new file mode 100644
index 0000000..82b8e28
--- /dev/null
+++ b/Source/core/dom/Event.idl
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2006, 2007, 2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+// Introduced in DOM Level 2:
+[
+    CustomToV8,
+    ConstructorTemplate=Event,
+    
+    SkipVTableValidation
+] interface Event {
+
+    // DOM PhaseType
+    const unsigned short NONE                = 0;
+    const unsigned short CAPTURING_PHASE     = 1;
+    const unsigned short AT_TARGET           = 2;
+    const unsigned short BUBBLING_PHASE      = 3;
+
+    // Reverse-engineered from Netscape
+    const unsigned short MOUSEDOWN           = 1;
+    const unsigned short MOUSEUP             = 2;
+    const unsigned short MOUSEOVER           = 4;
+    const unsigned short MOUSEOUT            = 8;
+    const unsigned short MOUSEMOVE           = 16;
+    const unsigned short MOUSEDRAG           = 32;
+    const unsigned short CLICK               = 64;
+    const unsigned short DBLCLICK            = 128;
+    const unsigned short KEYDOWN             = 256;
+    const unsigned short KEYUP               = 512;
+    const unsigned short KEYPRESS            = 1024;
+    const unsigned short DRAGDROP            = 2048;
+    const unsigned short FOCUS               = 4096;
+    const unsigned short BLUR                = 8192;
+    const unsigned short SELECT              = 16384;
+    const unsigned short CHANGE              = 32768;
+
+    readonly attribute DOMString        type;
+    readonly attribute EventTarget      target;
+    readonly attribute EventTarget      currentTarget;
+    readonly attribute unsigned short   eventPhase;
+    [InitializedByEventConstructor] readonly attribute boolean bubbles;
+    [InitializedByEventConstructor] readonly attribute boolean cancelable;
+    readonly attribute DOMTimeStamp     timeStamp;
+
+    void               stopPropagation();
+    void               preventDefault();
+     void initEvent([Default=Undefined] optional DOMString eventTypeArg, 
+                                  [Default=Undefined] optional boolean canBubbleArg, 
+                                  [Default=Undefined] optional boolean cancelableArg);
+
+    // DOM Level 3 Additions.
+    readonly attribute boolean defaultPrevented;
+    void stopImmediatePropagation();
+
+    // IE Extensions
+    readonly attribute EventTarget      srcElement;
+             attribute boolean          returnValue;
+             attribute boolean          cancelBubble;
+
+    [Custom] readonly attribute Clipboard        clipboardData;
+};
+
diff --git a/Source/core/dom/EventContext.cpp b/Source/core/dom/EventContext.cpp
new file mode 100644
index 0000000..5161783
--- /dev/null
+++ b/Source/core/dom/EventContext.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "core/dom/EventContext.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/Event.h"
+#include "core/dom/FocusEvent.h"
+#include "core/dom/MouseEvent.h"
+#include "core/dom/Node.h"
+#include "core/dom/TouchEvent.h"
+#include "core/dom/TouchList.h"
+#include "core/page/DOMWindow.h"
+
+namespace WebCore {
+
+EventContext::EventContext(PassRefPtr<Node> node, PassRefPtr<EventTarget> currentTarget, PassRefPtr<EventTarget> target)
+    : m_node(node)
+    , m_currentTarget(currentTarget)
+    , m_target(target)
+{
+    ASSERT(m_node);
+    ASSERT(!isUnreachableNode(m_target.get()));
+}
+
+EventContext::~EventContext()
+{
+}
+
+void EventContext::handleLocalEvents(Event* event) const
+{
+    event->setTarget(m_target.get());
+    event->setCurrentTarget(m_currentTarget.get());
+    m_node->handleLocalEvents(event);
+}
+
+bool EventContext::isMouseOrFocusEventContext() const
+{
+    return false;
+}
+
+bool EventContext::isTouchEventContext() const
+{
+    return false;
+}
+
+MouseOrFocusEventContext::MouseOrFocusEventContext(PassRefPtr<Node> node, PassRefPtr<EventTarget> currentTarget, PassRefPtr<EventTarget> target)
+    : EventContext(node, currentTarget, target)
+    , m_relatedTarget(0)
+{
+}
+
+MouseOrFocusEventContext::~MouseOrFocusEventContext()
+{
+}
+
+void MouseOrFocusEventContext::handleLocalEvents(Event* event) const
+{
+    ASSERT(event->isMouseEvent() || event->isFocusEvent());
+    if (m_relatedTarget.get() && event->isMouseEvent())
+        toMouseEvent(event)->setRelatedTarget(m_relatedTarget.get());
+    else if (m_relatedTarget.get() && event->isFocusEvent())
+        toFocusEvent(event)->setRelatedTarget(m_relatedTarget.get());
+    EventContext::handleLocalEvents(event);
+}
+
+bool MouseOrFocusEventContext::isMouseOrFocusEventContext() const
+{
+    return true;
+}
+
+TouchEventContext::TouchEventContext(PassRefPtr<Node> node, PassRefPtr<EventTarget> currentTarget, PassRefPtr<EventTarget> target)
+    : EventContext(node, currentTarget, target)
+    , m_touches(TouchList::create())
+    , m_targetTouches(TouchList::create())
+    , m_changedTouches(TouchList::create())
+{
+}
+
+TouchEventContext::~TouchEventContext()
+{
+}
+
+void TouchEventContext::handleLocalEvents(Event* event) const
+{
+#ifndef NDEBUG
+    checkReachability(m_touches.get());
+    checkReachability(m_targetTouches.get());
+    checkReachability(m_changedTouches.get());
+#endif
+    ASSERT(event->isTouchEvent());
+    TouchEvent* touchEvent = toTouchEvent(event);
+    touchEvent->setTouches(m_touches);
+    touchEvent->setTargetTouches(m_targetTouches);
+    touchEvent->setChangedTouches(m_changedTouches);
+    EventContext::handleLocalEvents(event);
+}
+
+bool TouchEventContext::isTouchEventContext() const
+{
+    return true;
+}
+
+#ifndef NDEBUG
+void TouchEventContext::checkReachability(TouchList* touchList) const
+{
+    for (size_t i = 0; i < touchList->length(); ++i)
+        ASSERT(isReachable(touchList->item(i)->target()->toNode()));
+}
+#endif
+
+}
diff --git a/Source/core/dom/EventContext.h b/Source/core/dom/EventContext.h
new file mode 100644
index 0000000..0a21f59
--- /dev/null
+++ b/Source/core/dom/EventContext.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef EventContext_h
+#define EventContext_h
+
+#include "core/dom/EventTarget.h"
+#include "core/dom/Node.h"
+#include "core/dom/TreeScope.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Event;
+class TouchList;
+
+class EventContext {
+public:
+    // FIXME: Use ContainerNode instead of Node.
+    EventContext(PassRefPtr<Node>, PassRefPtr<EventTarget> currentTarget, PassRefPtr<EventTarget> target);
+    virtual ~EventContext();
+
+    Node* node() const { return m_node.get(); }
+    EventTarget* target() const { return m_target.get(); }
+    bool currentTargetSameAsTarget() const { return m_currentTarget.get() == m_target.get(); }
+    virtual void handleLocalEvents(Event*) const;
+    virtual bool isMouseOrFocusEventContext() const;
+    virtual bool isTouchEventContext() const;
+
+protected:
+#ifndef NDEBUG
+    bool isUnreachableNode(EventTarget*);
+    bool isReachable(Node*) const;
+#endif
+    RefPtr<Node> m_node;
+    RefPtr<EventTarget> m_currentTarget;
+    RefPtr<EventTarget> m_target;
+};
+
+typedef Vector<OwnPtr<EventContext>, 32> EventPath;
+
+class MouseOrFocusEventContext : public EventContext {
+public:
+    MouseOrFocusEventContext(PassRefPtr<Node>, PassRefPtr<EventTarget> currentTarget, PassRefPtr<EventTarget> target);
+    virtual ~MouseOrFocusEventContext();
+    EventTarget* relatedTarget() const { return m_relatedTarget.get(); }
+    void setRelatedTarget(PassRefPtr<EventTarget>);
+    virtual void handleLocalEvents(Event*) const OVERRIDE;
+    virtual bool isMouseOrFocusEventContext() const OVERRIDE;
+
+private:
+    RefPtr<EventTarget> m_relatedTarget;
+};
+
+
+class TouchEventContext : public EventContext {
+public:
+    TouchEventContext(PassRefPtr<Node>, PassRefPtr<EventTarget> currentTarget, PassRefPtr<EventTarget> target);
+    virtual ~TouchEventContext();
+
+    virtual void handleLocalEvents(Event*) const OVERRIDE;
+    virtual bool isTouchEventContext() const OVERRIDE;
+
+    TouchList* touches() { return m_touches.get(); }
+    TouchList* targetTouches() { return m_targetTouches.get(); }
+    TouchList* changedTouches() { return m_changedTouches.get(); }
+
+private:
+    RefPtr<TouchList> m_touches;
+    RefPtr<TouchList> m_targetTouches;
+    RefPtr<TouchList> m_changedTouches;
+#ifndef NDEBUG
+    void checkReachability(TouchList*) const;
+#endif
+};
+
+inline TouchEventContext* toTouchEventContext(EventContext* eventContext)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!eventContext || eventContext->isTouchEventContext());
+    return static_cast<TouchEventContext*>(eventContext);
+}
+
+#ifndef NDEBUG
+inline bool EventContext::isUnreachableNode(EventTarget* target)
+{
+    // FIXME: Checks also for SVG elements.
+    return target && target->toNode() && !target->toNode()->isSVGElement() && !isReachable(target->toNode());
+}
+
+inline bool EventContext::isReachable(Node* target) const
+{
+    ASSERT(target);
+    TreeScope* targetScope = target->treeScope();
+    for (TreeScope* scope = m_node->treeScope(); scope; scope = scope->parentTreeScope()) {
+        if (scope == targetScope)
+            return true;
+    }
+    return false;
+}
+#endif
+
+inline void MouseOrFocusEventContext::setRelatedTarget(PassRefPtr<EventTarget> relatedTarget)
+{
+    ASSERT(!isUnreachableNode(relatedTarget.get()));
+    m_relatedTarget = relatedTarget;
+}
+
+}
+
+#endif // EventContext_h
diff --git a/Source/core/dom/EventDispatchMediator.cpp b/Source/core/dom/EventDispatchMediator.cpp
new file mode 100644
index 0000000..895b402
--- /dev/null
+++ b/Source/core/dom/EventDispatchMediator.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/EventDispatchMediator.h"
+
+#include "core/dom/Event.h"
+#include "core/dom/EventDispatcher.h"
+#include "core/dom/EventRetargeter.h"
+#include "core/dom/Node.h"
+
+namespace WebCore {
+
+PassRefPtr<EventDispatchMediator> EventDispatchMediator::create(PassRefPtr<Event> event)
+{
+    return adoptRef(new EventDispatchMediator(event));
+}
+
+EventDispatchMediator::EventDispatchMediator(PassRefPtr<Event> event)
+    : m_event(event)
+{
+}
+
+bool EventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
+{
+    ASSERT(m_event.get() == dispatcher->event());
+    return dispatcher->dispatch();
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/EventDispatchMediator.h b/Source/core/dom/EventDispatchMediator.h
new file mode 100644
index 0000000..c334348
--- /dev/null
+++ b/Source/core/dom/EventDispatchMediator.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef EventDispatchMediator_h
+#define EventDispatchMediator_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Event;
+class EventDispatcher;
+class Node;
+
+class EventDispatchMediator : public RefCounted<EventDispatchMediator> {
+public:
+    static PassRefPtr<EventDispatchMediator> create(PassRefPtr<Event>);
+    virtual ~EventDispatchMediator() { };
+    virtual bool dispatchEvent(EventDispatcher*) const;
+    Event* event() const { return m_event.get(); };
+
+protected:
+    explicit EventDispatchMediator(PassRefPtr<Event>);
+    EventDispatchMediator() { };
+    void setEvent(PassRefPtr<Event> event) { m_event = event; };
+
+private:
+    RefPtr<Event> m_event;
+};
+
+} // namespace WebCore
+
+#endif // EventDispatchMediator_h
diff --git a/Source/core/dom/EventDispatcher.cpp b/Source/core/dom/EventDispatcher.cpp
new file mode 100644
index 0000000..9465946
--- /dev/null
+++ b/Source/core/dom/EventDispatcher.cpp
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/EventDispatcher.h"
+
+#include "core/dom/ContainerNode.h"
+#include "core/dom/ElementShadow.h"
+#include "core/dom/EventContext.h"
+#include "core/dom/EventDispatchMediator.h"
+#include "core/dom/EventPathWalker.h"
+#include "core/dom/EventRetargeter.h"
+#include "core/dom/MouseEvent.h"
+#include "core/dom/ScopedEventQueue.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/dom/WindowEventContext.h"
+#include "core/html/HTMLMediaElement.h"
+#include "core/html/shadow/InsertionPoint.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/page/FrameView.h"
+#include <wtf/RefPtr.h>
+#include <wtf/UnusedParam.h>
+
+namespace WebCore {
+
+static HashSet<Node*>* gNodesDispatchingSimulatedClicks = 0;
+
+bool EventDispatcher::dispatchEvent(Node* node, PassRefPtr<EventDispatchMediator> mediator)
+{
+    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
+    if (!mediator->event())
+        return true;
+    EventDispatcher dispatcher(node, mediator->event());
+    return mediator->dispatchEvent(&dispatcher);
+}
+
+EventDispatcher::EventDispatcher(Node* node, PassRefPtr<Event> event)
+    : m_node(node)
+    , m_event(event)
+#ifndef NDEBUG
+    , m_eventDispatched(false)
+#endif
+{
+    ASSERT(node);
+    ASSERT(m_event.get());
+    ASSERT(!m_event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.
+    m_view = node->document()->view();
+    EventRetargeter::calculateEventPath(m_node.get(), m_event.get());
+}
+
+void EventDispatcher::dispatchScopedEvent(Node* node, PassRefPtr<EventDispatchMediator> mediator)
+{
+    // We need to set the target here because it can go away by the time we actually fire the event.
+    mediator->event()->setTarget(EventRetargeter::eventTargetRespectingTargetRules(node));
+    ScopedEventQueue::instance()->enqueueEventDispatchMediator(mediator);
+}
+
+void EventDispatcher::dispatchSimulatedClick(Node* node, Event* underlyingEvent, SimulatedClickMouseEventOptions mouseEventOptions, SimulatedClickVisualOptions visualOptions)
+{
+    if (isDisabledFormControl(node))
+        return;
+
+    if (!gNodesDispatchingSimulatedClicks)
+        gNodesDispatchingSimulatedClicks = new HashSet<Node*>;
+    else if (gNodesDispatchingSimulatedClicks->contains(node))
+        return;
+
+    gNodesDispatchingSimulatedClicks->add(node);
+
+    if (mouseEventOptions == SendMouseOverUpDownEvents)
+        EventDispatcher(node, SimulatedMouseEvent::create(eventNames().mouseoverEvent, node->document()->defaultView(), underlyingEvent)).dispatch();
+
+    if (mouseEventOptions != SendNoEvents)
+        EventDispatcher(node, SimulatedMouseEvent::create(eventNames().mousedownEvent, node->document()->defaultView(), underlyingEvent)).dispatch();
+    node->setActive(true, visualOptions == ShowPressedLook);
+    if (mouseEventOptions != SendNoEvents)
+        EventDispatcher(node, SimulatedMouseEvent::create(eventNames().mouseupEvent, node->document()->defaultView(), underlyingEvent)).dispatch();
+    node->setActive(false);
+
+    // always send click
+    EventDispatcher(node, SimulatedMouseEvent::create(eventNames().clickEvent, node->document()->defaultView(), underlyingEvent)).dispatch();
+
+    gNodesDispatchingSimulatedClicks->remove(node);
+}
+
+bool EventDispatcher::dispatch()
+{
+#ifndef NDEBUG
+    ASSERT(!m_eventDispatched);
+    m_eventDispatched = true;
+#endif
+    ChildNodesLazySnapshot::takeChildNodesLazySnapshot();
+
+    m_event->setTarget(EventRetargeter::eventTargetRespectingTargetRules(m_node.get()));
+    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
+    ASSERT(m_event->target());
+    WindowEventContext windowEventContext(m_event.get(), m_node.get(), topEventContext());
+    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *m_event, windowEventContext.window(), m_node.get(), m_event->eventPath());
+
+    void* preDispatchEventHandlerResult;
+    if (dispatchEventPreProcess(preDispatchEventHandlerResult) == ContinueDispatching)
+        if (dispatchEventAtCapturing(windowEventContext) == ContinueDispatching)
+            if (dispatchEventAtTarget() == ContinueDispatching)
+                dispatchEventAtBubbling(windowEventContext);
+    dispatchEventPostProcess(preDispatchEventHandlerResult);
+
+    // Ensure that after event dispatch, the event's target object is the
+    // outermost shadow DOM boundary.
+    m_event->setTarget(windowEventContext.target());
+    m_event->setCurrentTarget(0);
+    InspectorInstrumentation::didDispatchEvent(cookie);
+
+    return !m_event->defaultPrevented();
+}
+
+inline EventDispatchContinuation EventDispatcher::dispatchEventPreProcess(void*& preDispatchEventHandlerResult)
+{
+    // Give the target node a chance to do some work before DOM event handlers get a crack.
+    preDispatchEventHandlerResult = m_node->preDispatchEventHandler(m_event.get());
+    return (m_event->eventPath().isEmpty() || m_event->propagationStopped()) ? DoneDispatching : ContinueDispatching;
+}
+
+inline EventDispatchContinuation EventDispatcher::dispatchEventAtCapturing(WindowEventContext& windowEventContext)
+{
+    // Trigger capturing event handlers, starting at the top and working our way down.
+    m_event->setEventPhase(Event::CAPTURING_PHASE);
+
+    if (windowEventContext.handleLocalEvents(m_event.get()) && m_event->propagationStopped())
+        return DoneDispatching;
+
+    for (size_t i = m_event->eventPath().size() - 1; i > 0; --i) {
+        const EventContext& eventContext = *m_event->eventPath()[i];
+        if (eventContext.currentTargetSameAsTarget())
+            continue;
+        eventContext.handleLocalEvents(m_event.get());
+        if (m_event->propagationStopped())
+            return DoneDispatching;
+    }
+
+    return ContinueDispatching;
+}
+
+inline EventDispatchContinuation EventDispatcher::dispatchEventAtTarget()
+{
+    m_event->setEventPhase(Event::AT_TARGET);
+    m_event->eventPath()[0]->handleLocalEvents(m_event.get());
+    return m_event->propagationStopped() ? DoneDispatching : ContinueDispatching;
+}
+
+inline void EventDispatcher::dispatchEventAtBubbling(WindowEventContext& windowContext)
+{
+    // Trigger bubbling event handlers, starting at the bottom and working our way up.
+    size_t size = m_event->eventPath().size();
+    for (size_t i = 1; i < size; ++i) {
+        const EventContext& eventContext = *m_event->eventPath()[i];
+        if (eventContext.currentTargetSameAsTarget())
+            m_event->setEventPhase(Event::AT_TARGET);
+        else if (m_event->bubbles() && !m_event->cancelBubble())
+            m_event->setEventPhase(Event::BUBBLING_PHASE);
+        else
+            continue;
+        eventContext.handleLocalEvents(m_event.get());
+        if (m_event->propagationStopped())
+            return;
+    }
+    if (m_event->bubbles() && !m_event->cancelBubble()) {
+        m_event->setEventPhase(Event::BUBBLING_PHASE);
+        windowContext.handleLocalEvents(m_event.get());
+    }
+}
+
+inline void EventDispatcher::dispatchEventPostProcess(void* preDispatchEventHandlerResult)
+{
+    m_event->setTarget(EventRetargeter::eventTargetRespectingTargetRules(m_node.get()));
+    m_event->setCurrentTarget(0);
+    m_event->setEventPhase(0);
+
+    // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
+    m_node->postDispatchEventHandler(m_event.get(), preDispatchEventHandlerResult);
+
+    // Call default event handlers. While the DOM does have a concept of preventing
+    // default handling, the detail of which handlers are called is an internal
+    // implementation detail and not part of the DOM.
+    if (!m_event->defaultPrevented() && !m_event->defaultHandled()) {
+        // Non-bubbling events call only one default event handler, the one for the target.
+        m_node->defaultEventHandler(m_event.get());
+        ASSERT(!m_event->defaultPrevented());
+        if (m_event->defaultHandled())
+            return;
+        // For bubbling events, call default event handlers on the same targets in the
+        // same order as the bubbling phase.
+        if (m_event->bubbles()) {
+            size_t size = m_event->eventPath().size();
+            for (size_t i = 1; i < size; ++i) {
+                m_event->eventPath()[i]->node()->defaultEventHandler(m_event.get());
+                ASSERT(!m_event->defaultPrevented());
+                if (m_event->defaultHandled())
+                    return;
+            }
+        }
+    }
+}
+
+const EventContext* EventDispatcher::topEventContext()
+{
+    return m_event->eventPath().isEmpty() ? 0 : m_event->eventPath().last().get();
+}
+
+}
diff --git a/Source/core/dom/EventDispatcher.h b/Source/core/dom/EventDispatcher.h
new file mode 100644
index 0000000..b4a439e
--- /dev/null
+++ b/Source/core/dom/EventDispatcher.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef EventDispatcher_h
+#define EventDispatcher_h
+
+#include "core/dom/EventContext.h"
+#include "core/dom/SimulatedClickOptions.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Event;
+class EventDispatchMediator;
+class EventTarget;
+class FrameView;
+class Node;
+class PlatformKeyboardEvent;
+class PlatformMouseEvent;
+class ShadowRoot;
+class TreeScope;
+class WindowEventContext;
+
+enum EventDispatchContinuation {
+    ContinueDispatching,
+    DoneDispatching
+};
+
+class EventDispatcher {
+public:
+    static bool dispatchEvent(Node*, PassRefPtr<EventDispatchMediator>);
+    static void dispatchScopedEvent(Node*, PassRefPtr<EventDispatchMediator>);
+
+    static void dispatchSimulatedClick(Node*, Event* underlyingEvent, SimulatedClickMouseEventOptions, SimulatedClickVisualOptions);
+
+    bool dispatch();
+    Node* node() const { return m_node.get(); }
+    Event* event() const { return m_event.get(); }
+
+private:
+    EventDispatcher(Node*, PassRefPtr<Event>);
+    const EventContext* topEventContext();
+
+    EventDispatchContinuation dispatchEventPreProcess(void*& preDispatchEventHandlerResult);
+    EventDispatchContinuation dispatchEventAtCapturing(WindowEventContext&);
+    EventDispatchContinuation dispatchEventAtTarget();
+    void dispatchEventAtBubbling(WindowEventContext&);
+    void dispatchEventPostProcess(void* preDispatchEventHandlerResult);
+
+    RefPtr<Node> m_node;
+    RefPtr<Event> m_event;
+    RefPtr<FrameView> m_view;
+#ifndef NDEBUG
+    bool m_eventDispatched;
+#endif
+};
+
+}
+
+#endif
diff --git a/Source/core/dom/EventException.cpp b/Source/core/dom/EventException.cpp
new file mode 100644
index 0000000..6e9241b
--- /dev/null
+++ b/Source/core/dom/EventException.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 GOOGLE AND ITS 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 APPLE OR ITS 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 "core/dom/EventException.h"
+
+namespace WebCore {
+
+static struct EventExceptionNameDescription {
+    const char* const name;
+    const char* const description;
+} eventExceptions[] = {
+    { "UNSPECIFIED_EVENT_TYPE_ERR", "The Event's type was not specified by initializing the event before the method was called." },
+    { "DISPATCH_REQUEST_ERR", "The Event object is already being dispatched." }
+};
+
+bool EventException::initializeDescription(ExceptionCode ec, ExceptionCodeDescription* description)
+{
+    if (ec < EventExceptionOffset || ec > EventExceptionMax)
+        return false;
+
+    description->typeName = "DOM Events";
+    description->code = ec - EventExceptionOffset;
+    description->type = EventExceptionType;
+
+    size_t tableSize = WTF_ARRAY_LENGTH(eventExceptions);
+    size_t tableIndex = ec - UNSPECIFIED_EVENT_TYPE_ERR;
+
+    description->name = tableIndex < tableSize ? eventExceptions[tableIndex].name : 0;
+    description->description = tableIndex < tableSize ? eventExceptions[tableIndex].description : 0;
+
+    return true;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/EventException.h b/Source/core/dom/EventException.h
new file mode 100644
index 0000000..77bde1c
--- /dev/null
+++ b/Source/core/dom/EventException.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 EventException_h
+#define EventException_h
+
+#include "core/dom/ExceptionBase.h"
+
+namespace WebCore {
+
+class EventException : public ExceptionBase {
+public:
+    static PassRefPtr<EventException> create(const ExceptionCodeDescription& description)
+    {
+        return adoptRef(new EventException(description));
+    }
+
+    static const int EventExceptionOffset = 100;
+    static const int EventExceptionMax = 199;
+
+    enum EventExceptionCode {
+        UNSPECIFIED_EVENT_TYPE_ERR = EventExceptionOffset,
+        DISPATCH_REQUEST_ERR
+    };
+
+    static bool initializeDescription(ExceptionCode, ExceptionCodeDescription*);
+
+private:
+    explicit EventException(const ExceptionCodeDescription& description)
+        : ExceptionBase(description)
+    {
+    }
+};
+
+} // namespace WebCore
+
+#endif // EventException_h
diff --git a/Source/core/dom/EventException.idl b/Source/core/dom/EventException.idl
new file mode 100644
index 0000000..cde7100
--- /dev/null
+++ b/Source/core/dom/EventException.idl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+// Introduced in DOM Level 2:
+[
+    DoNotCheckConstants,
+    ImplementationLacksVTable,
+] exception EventException {
+
+    readonly attribute unsigned short   code;
+    readonly attribute DOMString        name;
+    readonly attribute DOMString        message;
+
+    // Override in a Mozilla compatible format
+    [NotEnumerable] DOMString toString();
+
+    // EventExceptionCode
+    const unsigned short UNSPECIFIED_EVENT_TYPE_ERR = 0;
+    const unsigned short DISPATCH_REQUEST_ERR = 1;
+};
+
diff --git a/Source/core/dom/EventFactory.h b/Source/core/dom/EventFactory.h
new file mode 100644
index 0000000..adfcfb5
--- /dev/null
+++ b/Source/core/dom/EventFactory.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 EventFactory_h
+#define EventFactory_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class Event;
+
+class EventFactory {
+public:
+    static PassRefPtr<Event> create(const String& eventType);
+};
+
+}
+
+#endif
diff --git a/Source/core/dom/EventListener.h b/Source/core/dom/EventListener.h
new file mode 100644
index 0000000..1708a73
--- /dev/null
+++ b/Source/core/dom/EventListener.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef EventListener_h
+#define EventListener_h
+
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+    class ScriptExecutionContext;
+    class Event;
+
+    class EventListener : public RefCounted<EventListener> {
+    public:
+        enum Type {
+            JSEventListenerType, 
+            ImageEventListenerType, 
+            ObjCEventListenerType,
+            CPPEventListenerType,
+            ConditionEventListenerType,
+            GObjectEventListenerType,
+            NativeEventListenerType,
+            SVGTRefTargetEventListenerType
+        };
+
+        virtual ~EventListener() { }
+        virtual bool operator==(const EventListener&) = 0;
+        virtual void handleEvent(ScriptExecutionContext*, Event*) = 0;
+        virtual bool wasCreatedFromMarkup() const { return false; }
+
+        bool isAttribute() const { return virtualisAttribute(); }
+        Type type() const { return m_type; }
+
+    protected:
+        explicit EventListener(Type type)
+            : m_type(type)
+        {
+        }
+
+    private:
+        virtual bool virtualisAttribute() const { return false; }
+        
+        Type m_type;
+    };
+
+}
+
+#endif
diff --git a/Source/core/dom/EventListener.idl b/Source/core/dom/EventListener.idl
new file mode 100644
index 0000000..9d17453
--- /dev/null
+++ b/Source/core/dom/EventListener.idl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+[
+] interface EventListener {
+    void               handleEvent(Event evt);
+};
+
diff --git a/Source/core/dom/EventListenerMap.cpp b/Source/core/dom/EventListenerMap.cpp
new file mode 100644
index 0000000..00d2506
--- /dev/null
+++ b/Source/core/dom/EventListenerMap.cpp
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ *           (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2011 Andreas Kling (kling@webkit.org)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/EventListenerMap.h"
+
+#include "core/dom/Event.h"
+#include "core/dom/EventException.h"
+#include "core/dom/EventTarget.h"
+#include <wtf/MainThread.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+#ifndef NDEBUG
+#include <wtf/Threading.h>
+#endif
+
+using namespace WTF;
+
+namespace WebCore {
+
+#ifndef NDEBUG
+static Mutex& activeIteratorCountMutex()
+{
+    DEFINE_STATIC_LOCAL(Mutex, mutex, ());
+    return mutex;
+}
+
+void EventListenerMap::assertNoActiveIterators()
+{
+    MutexLocker locker(activeIteratorCountMutex());
+    ASSERT(!m_activeIteratorCount);
+}
+#endif
+
+EventListenerMap::EventListenerMap()
+#ifndef NDEBUG
+    : m_activeIteratorCount(0)
+#endif
+{
+}
+
+bool EventListenerMap::contains(const AtomicString& eventType) const
+{
+    for (unsigned i = 0; i < m_entries.size(); ++i) {
+        if (m_entries[i].first == eventType)
+            return true;
+    }
+    return false;
+}
+
+void EventListenerMap::clear()
+{
+    assertNoActiveIterators();
+
+    m_entries.clear();
+}
+
+Vector<AtomicString> EventListenerMap::eventTypes() const
+{
+    Vector<AtomicString> types;
+    types.reserveInitialCapacity(m_entries.size());
+
+    for (unsigned i = 0; i < m_entries.size(); ++i)
+        types.uncheckedAppend(m_entries[i].first);
+
+    return types;
+}
+
+static bool addListenerToVector(EventListenerVector* vector, PassRefPtr<EventListener> listener, bool useCapture)
+{
+    RegisteredEventListener registeredListener(listener, useCapture);
+
+    if (vector->find(registeredListener) != notFound)
+        return false; // Duplicate listener.
+
+    vector->append(registeredListener);
+    return true;
+}
+
+bool EventListenerMap::add(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
+{
+    assertNoActiveIterators();
+
+    for (unsigned i = 0; i < m_entries.size(); ++i) {
+        if (m_entries[i].first == eventType)
+            return addListenerToVector(m_entries[i].second.get(), listener, useCapture);
+    }
+
+    m_entries.append(std::make_pair(eventType, adoptPtr(new EventListenerVector)));
+    return addListenerToVector(m_entries.last().second.get(), listener, useCapture);
+}
+
+static bool removeListenerFromVector(EventListenerVector* listenerVector, EventListener* listener, bool useCapture, size_t& indexOfRemovedListener)
+{
+    RegisteredEventListener registeredListener(listener, useCapture);
+    indexOfRemovedListener = listenerVector->find(registeredListener);
+    if (indexOfRemovedListener == notFound)
+        return false;
+    listenerVector->remove(indexOfRemovedListener);
+    return true;
+}
+
+bool EventListenerMap::remove(const AtomicString& eventType, EventListener* listener, bool useCapture, size_t& indexOfRemovedListener)
+{
+    assertNoActiveIterators();
+
+    for (unsigned i = 0; i < m_entries.size(); ++i) {
+        if (m_entries[i].first == eventType) {
+            bool wasRemoved = removeListenerFromVector(m_entries[i].second.get(), listener, useCapture, indexOfRemovedListener);
+            if (m_entries[i].second->isEmpty())
+                m_entries.remove(i);
+            return wasRemoved;
+        }
+    }
+
+    return false;
+}
+
+EventListenerVector* EventListenerMap::find(const AtomicString& eventType)
+{
+    assertNoActiveIterators();
+
+    for (unsigned i = 0; i < m_entries.size(); ++i) {
+        if (m_entries[i].first == eventType)
+            return m_entries[i].second.get();
+    }
+
+    return 0;
+}
+
+#if ENABLE(SVG)
+
+static void removeFirstListenerCreatedFromMarkup(EventListenerVector* listenerVector)
+{
+    bool foundListener = false;
+
+    for (size_t i = 0; i < listenerVector->size(); ++i) {
+        if (!listenerVector->at(i).listener->wasCreatedFromMarkup())
+            continue;
+        foundListener = true;
+        listenerVector->remove(i);
+        break;
+    }
+
+    ASSERT_UNUSED(foundListener, foundListener);
+}
+
+void EventListenerMap::removeFirstEventListenerCreatedFromMarkup(const AtomicString& eventType)
+{
+    assertNoActiveIterators();
+
+    for (unsigned i = 0; i < m_entries.size(); ++i) {
+        if (m_entries[i].first == eventType) {
+            removeFirstListenerCreatedFromMarkup(m_entries[i].second.get());
+            if (m_entries[i].second->isEmpty())
+                m_entries.remove(i);
+            return;
+        }
+    }
+}
+
+static void copyListenersNotCreatedFromMarkupToTarget(const AtomicString& eventType, EventListenerVector* listenerVector, EventTarget* target)
+{
+    for (size_t i = 0; i < listenerVector->size(); ++i) {
+        // Event listeners created from markup have already been transfered to the shadow tree during cloning.
+        if ((*listenerVector)[i].listener->wasCreatedFromMarkup())
+            continue;
+        target->addEventListener(eventType, (*listenerVector)[i].listener, (*listenerVector)[i].useCapture);
+    }
+}
+
+void EventListenerMap::copyEventListenersNotCreatedFromMarkupToTarget(EventTarget* target)
+{
+    assertNoActiveIterators();
+
+    for (unsigned i = 0; i < m_entries.size(); ++i)
+        copyListenersNotCreatedFromMarkupToTarget(m_entries[i].first, m_entries[i].second.get(), target);
+}
+
+#endif // ENABLE(SVG)
+
+EventListenerIterator::EventListenerIterator()
+    : m_map(0)
+    , m_entryIndex(0)
+    , m_index(0)
+{
+}
+
+EventListenerIterator::EventListenerIterator(EventTarget* target)
+    : m_map(0)
+    , m_entryIndex(0)
+    , m_index(0)
+{
+    ASSERT(target);
+    EventTargetData* data = target->eventTargetData();
+
+    if (!data)
+        return;
+
+    m_map = &data->eventListenerMap;
+
+#ifndef NDEBUG
+    {
+        MutexLocker locker(activeIteratorCountMutex());
+        m_map->m_activeIteratorCount++;
+    }
+#endif
+}
+
+#ifndef NDEBUG
+EventListenerIterator::~EventListenerIterator()
+{
+    if (m_map) {
+        MutexLocker locker(activeIteratorCountMutex());
+        m_map->m_activeIteratorCount--;
+    }
+}
+#endif
+
+EventListener* EventListenerIterator::nextListener()
+{
+    if (!m_map)
+        return 0;
+
+    for (; m_entryIndex < m_map->m_entries.size(); ++m_entryIndex) {
+        EventListenerVector& listeners = *m_map->m_entries[m_entryIndex].second;
+        if (m_index < listeners.size())
+            return listeners[m_index++].listener.get();
+        m_index = 0;
+    }
+
+    return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/EventListenerMap.h b/Source/core/dom/EventListenerMap.h
new file mode 100644
index 0000000..c73364e
--- /dev/null
+++ b/Source/core/dom/EventListenerMap.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ *           (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2011 Andreas Kling (kling@webkit.org)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef EventListenerMap_h
+#define EventListenerMap_h
+
+#include "core/dom/RegisteredEventListener.h"
+#include <wtf/Forward.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/AtomicStringHash.h>
+
+namespace WebCore {
+
+class EventTarget;
+
+typedef Vector<RegisteredEventListener, 1> EventListenerVector;
+
+class EventListenerMap {
+public:
+    EventListenerMap();
+
+    bool isEmpty() const { return m_entries.isEmpty(); }
+    bool contains(const AtomicString& eventType) const;
+
+    void clear();
+    bool add(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
+    bool remove(const AtomicString& eventType, EventListener*, bool useCapture, size_t& indexOfRemovedListener);
+    EventListenerVector* find(const AtomicString& eventType);
+    Vector<AtomicString> eventTypes() const;
+
+#if ENABLE(SVG)
+    void removeFirstEventListenerCreatedFromMarkup(const AtomicString& eventType);
+    void copyEventListenersNotCreatedFromMarkupToTarget(EventTarget*);
+#endif
+
+private:
+    friend class EventListenerIterator;
+
+    void assertNoActiveIterators();
+
+    Vector<std::pair<AtomicString, OwnPtr<EventListenerVector> >, 2> m_entries;
+
+#ifndef NDEBUG
+    int m_activeIteratorCount;
+#endif
+};
+
+class EventListenerIterator {
+    WTF_MAKE_NONCOPYABLE(EventListenerIterator);
+public:
+    EventListenerIterator();
+    EventListenerIterator(EventTarget*);
+#ifndef NDEBUG
+    ~EventListenerIterator();
+#endif
+
+    EventListener* nextListener();
+
+private:
+    EventListenerMap* m_map;
+    unsigned m_entryIndex;
+    unsigned m_index;
+};
+
+#ifdef NDEBUG
+inline void EventListenerMap::assertNoActiveIterators() { }
+#endif
+
+} // namespace WebCore
+
+#endif // EventListenerMap_h
diff --git a/Source/core/dom/EventNames.cpp b/Source/core/dom/EventNames.cpp
new file mode 100644
index 0000000..3d68964
--- /dev/null
+++ b/Source/core/dom/EventNames.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2005 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+#define INITIALIZE_EVENT_NAME(name) \
+    , name##Event(#name, AtomicString::ConstructFromLiteral)
+
+#define INITIALIZE_EVENT_INTERFACE(name) \
+    , interfaceFor##name(#name, AtomicString::ConstructFromLiteral)
+
+EventNames::EventNames()
+    : dummy(0)
+DOM_EVENT_NAMES_FOR_EACH(INITIALIZE_EVENT_NAME)
+DOM_EVENT_INTERFACES_FOR_EACH(INITIALIZE_EVENT_INTERFACE)
+DOM_EVENT_TARGET_INTERFACES_FOR_EACH(INITIALIZE_EVENT_INTERFACE)
+{
+}
+
+}
diff --git a/Source/core/dom/EventNames.h b/Source/core/dom/EventNames.h
new file mode 100644
index 0000000..12db1a6
--- /dev/null
+++ b/Source/core/dom/EventNames.h
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2005, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Jon Shier (jshier@iastate.edu)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef EventNames_h
+#define EventNames_h
+
+#include "EventInterfaces.h"
+#include "EventTargetInterfaces.h"
+#include "core/platform/ThreadGlobalData.h"
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+#define DOM_EVENT_NAMES_FOR_EACH(macro) \
+    \
+    macro(abort) \
+    macro(beforecopy) \
+    macro(beforecut) \
+    macro(beforeload) \
+    macro(beforepaste) \
+    macro(beforeunload) \
+    macro(blocked) \
+    macro(blur) \
+    macro(cached) \
+    macro(change) \
+    macro(chargingchange) \
+    macro(chargingtimechange) \
+    macro(checking) \
+    macro(click) \
+    macro(close) \
+    macro(complete) \
+    macro(compositionend) \
+    macro(compositionstart) \
+    macro(compositionupdate) \
+    macro(connect) \
+    macro(contextmenu) \
+    macro(copy) \
+    macro(cut) \
+    macro(dblclick) \
+    macro(devicemotion) \
+    macro(deviceorientation) \
+    macro(dischargingtimechange) \
+    macro(disconnect) \
+    macro(display) \
+    macro(downloading) \
+    macro(drag) \
+    macro(dragend) \
+    macro(dragenter) \
+    macro(dragleave) \
+    macro(dragover) \
+    macro(dragstart) \
+    macro(drop) \
+    macro(error) \
+    macro(focus) \
+    macro(focusin) \
+    macro(focusout) \
+    macro(gesturetap) \
+    macro(gesturetapdown) \
+    macro(gesturescrollstart) \
+    macro(gesturescrollend) \
+    macro(gesturescrollupdate) \
+    macro(hashchange) \
+    macro(input) \
+    macro(invalid) \
+    macro(keydown) \
+    macro(keypress) \
+    macro(keyup) \
+    macro(levelchange) \
+    macro(load) \
+    macro(loading) \
+    macro(loadingdone) \
+    macro(loadstart) \
+    macro(message) \
+    macro(midimessage) \
+    macro(mousedown) \
+    macro(mousemove) \
+    macro(mouseout) \
+    macro(mouseover) \
+    macro(mouseup) \
+    macro(mousewheel) \
+    macro(noupdate) \
+    macro(obsolete) \
+    macro(offline) \
+    macro(online) \
+    macro(open) \
+    macro(overflowchanged) \
+    macro(pagehide) \
+    macro(pageshow) \
+    macro(paste) \
+    macro(popstate) \
+    macro(readystatechange) \
+    macro(reset) \
+    macro(resize) \
+    macro(scroll) \
+    macro(search) \
+    macro(select) \
+    macro(selectstart) \
+    macro(selectionchange) \
+    macro(storage) \
+    macro(submit) \
+    macro(textInput) \
+    macro(unload) \
+    macro(updateready) \
+    macro(upgradeneeded) \
+    macro(versionchange) \
+    macro(webkitvisibilitychange) \
+    macro(write) \
+    macro(writeend) \
+    macro(writestart) \
+    macro(zoom) \
+    \
+    macro(DOMActivate) \
+    macro(DOMFocusIn) \
+    macro(DOMFocusOut) \
+    macro(DOMCharacterDataModified) \
+    macro(DOMNodeInserted) \
+    macro(DOMNodeInsertedIntoDocument) \
+    macro(DOMNodeRemoved) \
+    macro(DOMNodeRemovedFromDocument) \
+    macro(DOMSubtreeModified) \
+    macro(DOMContentLoaded) \
+    \
+    macro(webkitBeforeTextInserted) \
+    macro(webkitEditableContentChanged) \
+    \
+    macro(canplay) \
+    macro(canplaythrough) \
+    macro(durationchange) \
+    macro(emptied) \
+    macro(ended) \
+    macro(loadeddata) \
+    macro(loadedmetadata) \
+    macro(pause) \
+    macro(play) \
+    macro(playing) \
+    macro(ratechange) \
+    macro(seeked) \
+    macro(seeking) \
+    macro(timeupdate) \
+    macro(volumechange) \
+    macro(waiting) \
+    \
+    macro(addtrack) \
+    macro(cuechange) \
+    macro(enter) \
+    macro(exit) \
+    \
+    macro(webkitaddsourcebuffer) \
+    macro(webkitremovesourcebuffer) \
+    macro(webkitsourceopen) \
+    macro(webkitsourceended) \
+    macro(webkitsourceclose) \
+    \
+    macro(webkitkeyadded) \
+    macro(webkitkeyerror) \
+    macro(webkitkeymessage) \
+    macro(webkitneedkey) \
+    \
+    macro(progress) \
+    macro(stalled) \
+    macro(suspend) \
+    \
+    macro(webkitAnimationEnd) \
+    macro(webkitAnimationStart) \
+    macro(webkitAnimationIteration) \
+    \
+    macro(webkitTransitionEnd) \
+    macro(transitionend) \
+    \
+    macro(orientationchange) \
+    \
+    macro(timeout) \
+    \
+    macro(touchstart) \
+    macro(touchmove) \
+    macro(touchend) \
+    macro(touchcancel) \
+    \
+    macro(success) \
+    \
+    macro(loadend) \
+    \
+    macro(webkitfullscreenchange) \
+    macro(webkitfullscreenerror) \
+    \
+    macro(webkitspeechchange) \
+    \
+    macro(audiostart) \
+    macro(soundstart) \
+    macro(speechstart) \
+    macro(speechend) \
+    macro(soundend) \
+    macro(audioend) \
+    macro(result) \
+    macro(nomatch) \
+    macro(start) \
+    macro(end) \
+    macro(mark) \
+    macro(boundary) \
+    macro(resume) \
+    \
+    macro(webglcontextlost) \
+    macro(webglcontextrestored) \
+    macro(webglcontextcreationerror) \
+    \
+    macro(audioprocess) \
+    \
+    macro(connecting) \
+    macro(addstream) \
+    macro(removestream) \
+    macro(signalingstatechange) \
+    macro(removetrack) \
+    macro(mute) \
+    macro(unmute) \
+    macro(iceconnectionstatechange) \
+    macro(icecandidate) \
+    macro(negotiationneeded) \
+    macro(datachannel) \
+    macro(tonechange) \
+    \
+    macro(show) \
+    \
+    macro(webkitpointerlockchange) \
+    macro(webkitpointerlockerror) \
+    \
+    macro(webkitregionlayoutupdate) \
+    \
+    macro(webkitnetworkinfochange) \
+    \
+    macro(webkitresourcetimingbufferfull) \
+    \
+    macro(webkitdeviceproximity) \
+    \
+    macro(autocomplete) \
+    macro(autocompleteerror) \
+    \
+    macro(webkitprerenderstart) \
+    macro(webkitprerenderstop) \
+    macro(webkitprerenderload) \
+    macro(webkitprerenderdomcontentloaded) \
+    \
+    macro(securitypolicyviolation) \
+    \
+
+// end of DOM_EVENT_NAMES_FOR_EACH
+
+    class EventNames {
+        WTF_MAKE_NONCOPYABLE(EventNames); WTF_MAKE_FAST_ALLOCATED;
+        int dummy; // Needed to make initialization macro work.
+        // Private to prevent accidental call to EventNames() instead of eventNames()
+        EventNames();
+        friend class ThreadGlobalData;
+
+    public:
+        #define DOM_EVENT_NAMES_DECLARE(name) AtomicString name##Event;
+        DOM_EVENT_NAMES_FOR_EACH(DOM_EVENT_NAMES_DECLARE)
+        #undef DOM_EVENT_NAMES_DECLARE
+
+        #define DOM_EVENT_INTERFACE_DECLARE(name) AtomicString interfaceFor##name;
+        DOM_EVENT_INTERFACES_FOR_EACH(DOM_EVENT_INTERFACE_DECLARE)
+        DOM_EVENT_TARGET_INTERFACES_FOR_EACH(DOM_EVENT_INTERFACE_DECLARE)
+        #undef DOM_EVENT_INTERFACE_DECLARE
+
+        inline bool isTouchEventType(const AtomicString& eventType) const
+        {
+            return eventType == touchstartEvent
+                || eventType == touchmoveEvent
+                || eventType == touchendEvent
+                || eventType == touchcancelEvent;
+        }
+
+        inline bool isGestureEventType(const AtomicString& eventType) const
+        {
+            return eventType == gesturetapEvent
+                || eventType == gesturetapdownEvent
+                || eventType == gesturescrollstartEvent
+                || eventType == gesturescrollendEvent
+                || eventType == gesturescrollupdateEvent;
+        }
+
+        Vector<AtomicString> touchEventNames() const
+        {
+            Vector<AtomicString> names;
+            names.reserveCapacity(4);
+            names.append(touchstartEvent);
+            names.append(touchmoveEvent);
+            names.append(touchendEvent);
+            names.append(touchcancelEvent);
+            return names;
+        }
+    };
+
+    inline EventNames& eventNames()
+    {
+        return threadGlobalData().eventNames();
+    }
+
+}
+
+#endif
diff --git a/Source/core/dom/EventNames.in b/Source/core/dom/EventNames.in
new file mode 100644
index 0000000..5ede665
--- /dev/null
+++ b/Source/core/dom/EventNames.in
@@ -0,0 +1,61 @@
+namespace="Event"
+
+Event
+Events interfaceName=Event
+HTMLEvents interfaceName=Event
+core/dom/BeforeLoadEvent
+modules/websockets/CloseEvent
+CompositionEvent
+CustomEvent
+ErrorEvent
+FocusEvent
+HashChangeEvent
+KeyboardEvent
+KeyboardEvents interfaceName=KeyboardEvent
+MessageEvent
+MouseEvent
+MouseEvents interfaceName=MouseEvent
+MutationEvent
+MutationEvents interfaceName=MutationEvent
+OverflowEvent
+PageTransitionEvent
+PopStateEvent
+ProgressEvent
+TextEvent
+TransitionEvent
+UIEvent
+UIEvents interfaceName=UIEvent
+WebKitAnimationEvent interfaceName=AnimationEvent
+WebKitTransitionEvent interfaceName=TransitionEvent
+WheelEvent
+core/xml/XMLHttpRequestProgressEvent
+modules/webaudio/AudioProcessingEvent conditional=WEB_AUDIO
+modules/webaudio/OfflineAudioCompletionEvent conditional=WEB_AUDIO
+modules/mediastream/MediaStreamEvent
+modules/mediastream/MediaStreamTrackEvent
+modules/mediastream/RTCIceCandidateEvent
+modules/mediastream/RTCDataChannelEvent
+modules/mediastream/RTCDTMFToneChangeEvent
+core/page/SpeechInputEvent conditional=INPUT_SPEECH
+modules/speech/SpeechRecognitionError
+modules/speech/SpeechRecognitionEvent
+modules/speech/SpeechSynthesisEvent
+core/html/canvas/WebGLContextEvent conditional=WEBGL
+core/storage/StorageEvent
+core/svg/SVGEvents interfaceName=Event, conditional=SVG
+core/svg/SVGZoomEvent conditional=SVG
+core/svg/SVGZoomEvents interfaceName=SVGZoomEvent, conditional=SVG
+modules/indexeddb/IDBVersionChangeEvent
+TouchEvent runtimeConditional=touchEnabled
+modules/device_orientation/DeviceMotionEvent
+core/dom/DeviceOrientationEvent
+OrientationEvent interfaceName=Event, conditional=ORIENTATION_EVENTS
+core/html/MediaKeyEvent conditional=ENCRYPTED_MEDIA
+MediaKeyMessageEvent conditional=ENCRYPTED_MEDIA_V2
+MediaKeyNeededEvent conditional=ENCRYPTED_MEDIA_V2
+core/html/track/TrackEvent
+core/dom/AutocompleteErrorEvent
+core/css/CSSFontFaceLoadEvent
+SecurityPolicyViolationEvent
+modules/webmidi/MIDIConnectionEvent
+modules/webmidi/MIDIMessageEvent
diff --git a/Source/core/dom/EventPathWalker.cpp b/Source/core/dom/EventPathWalker.cpp
new file mode 100644
index 0000000..2adac7b
--- /dev/null
+++ b/Source/core/dom/EventPathWalker.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2013 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 "core/dom/EventPathWalker.h"
+
+#include "core/dom/ShadowRoot.h"
+#include "core/html/shadow/ContentDistributor.h"
+#include "core/html/shadow/InsertionPoint.h"
+
+namespace WebCore {
+
+EventPathWalker::EventPathWalker(const Node* node)
+    : m_node(node)
+    , m_distributedNode(node)
+    , m_isVisitingInsertionPointInReprojection(false)
+{
+    ASSERT(node);
+}
+
+Node* EventPathWalker::parent(const Node* node)
+{
+    EventPathWalker walker(node);
+    walker.moveToParent();
+    return walker.node();
+}
+
+void EventPathWalker::moveToParent()
+{
+    ASSERT(m_node);
+    ASSERT(m_distributedNode);
+    if (ElementShadow* shadow = shadowOfParent(m_node)) {
+        ContentDistributor::ensureDistribution(shadow->youngestShadowRoot());
+        if (InsertionPoint* insertionPoint = shadow->distributor().findInsertionPointFor(m_distributedNode)) {
+            m_node = insertionPoint;
+            m_isVisitingInsertionPointInReprojection = true;
+            return;
+        }
+    }
+    if (!m_node->isShadowRoot()) {
+        m_node = m_node->parentNode();
+        if (!(m_node && m_node->isShadowRoot() && ScopeContentDistribution::assignedTo(toShadowRoot(m_node))))
+            m_distributedNode = m_node;
+        m_isVisitingInsertionPointInReprojection = false;
+        return;
+    }
+
+    const ShadowRoot* shadowRoot = toShadowRoot(m_node);
+    if (InsertionPoint* insertionPoint = ScopeContentDistribution::assignedTo(shadowRoot)) {
+        m_node = insertionPoint;
+        m_isVisitingInsertionPointInReprojection = true;
+        return;
+    }
+    m_node = shadowRoot->host();
+    m_distributedNode = m_node;
+    m_isVisitingInsertionPointInReprojection = false;
+}
+
+} // namespace
diff --git a/Source/core/dom/EventPathWalker.h b/Source/core/dom/EventPathWalker.h
new file mode 100644
index 0000000..9006e9b
--- /dev/null
+++ b/Source/core/dom/EventPathWalker.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 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 EventPathWalker_h
+#define EventPathWalker_h
+
+namespace WebCore {
+
+class Node;
+
+class EventPathWalker {
+public:
+    explicit EventPathWalker(const Node*);
+    static Node* parent(const Node*);
+    void moveToParent();
+    Node* node() const { return const_cast<Node*>(m_node); }
+    bool isVisitingInsertionPointInReprojection() { return m_isVisitingInsertionPointInReprojection; }
+
+private:
+    const Node* m_node;
+    const Node* m_distributedNode;
+    bool m_isVisitingInsertionPointInReprojection;
+};
+
+} // namespace
+
+#endif
diff --git a/Source/core/dom/EventQueue.h b/Source/core/dom/EventQueue.h
new file mode 100644
index 0000000..56ce153
--- /dev/null
+++ b/Source/core/dom/EventQueue.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef EventQueue_h
+#define EventQueue_h
+
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class Event;
+
+class EventQueue {
+public:
+    virtual ~EventQueue() { }
+    virtual bool enqueueEvent(PassRefPtr<Event>) = 0;
+    virtual bool cancelEvent(Event*) = 0;
+    // The accumulated and all the future events will be discarded, no events will be dispatched anymore.
+    virtual void close() = 0;
+};
+
+}
+
+#endif // EventQueue_h
diff --git a/Source/core/dom/EventRetargeter.cpp b/Source/core/dom/EventRetargeter.cpp
new file mode 100644
index 0000000..297fa6c
--- /dev/null
+++ b/Source/core/dom/EventRetargeter.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/EventRetargeter.h"
+
+#include "core/dom/ContainerNode.h"
+#include "core/dom/EventContext.h"
+#include "core/dom/EventPathWalker.h"
+#include "core/dom/FocusEvent.h"
+#include "core/dom/MouseEvent.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/dom/Touch.h"
+#include "core/dom/TouchEvent.h"
+#include "core/dom/TouchList.h"
+#include "core/dom/TreeScope.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+static inline bool inTheSameScope(ShadowRoot* shadowRoot, EventTarget* target)
+{
+    return target->toNode() && target->toNode()->treeScope()->rootNode() == shadowRoot;
+}
+
+static inline EventDispatchBehavior determineDispatchBehavior(Event* event, ShadowRoot* shadowRoot, EventTarget* target)
+{
+    // Video-only full screen is a mode where we use the shadow DOM as an implementation
+    // detail that should not be detectable by the web content.
+    if (Element* element = target->toNode()->document()->webkitCurrentFullScreenElement()) {
+        // FIXME: We assume that if the full screen element is a media element that it's
+        // the video-only full screen. Both here and elsewhere. But that is probably wrong.
+        if (element->isMediaElement() && shadowRoot && shadowRoot->host() == element)
+            return StayInsideShadowDOM;
+    }
+
+    // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
+    // Changing this breaks existing sites.
+    // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
+    const AtomicString eventType = event->type();
+    if (inTheSameScope(shadowRoot, target)
+        && (eventType == eventNames().abortEvent
+            || eventType == eventNames().changeEvent
+            || eventType == eventNames().errorEvent
+            || eventType == eventNames().loadEvent
+            || eventType == eventNames().resetEvent
+            || eventType == eventNames().resizeEvent
+            || eventType == eventNames().scrollEvent
+            || eventType == eventNames().selectEvent
+            || eventType == eventNames().selectstartEvent))
+        return StayInsideShadowDOM;
+
+    return RetargetEvent;
+}
+
+void EventRetargeter::calculateEventPath(Node* node, Event* event)
+{
+    EventPath& eventPath = event->eventPath();
+    eventPath.clear();
+    bool inDocument = node->inDocument();
+    bool isSVGElement = node->isSVGElement();
+    bool isMouseOrFocusEvent = event->isMouseEvent() || event->isFocusEvent();
+    bool isTouchEvent = event->isTouchEvent();
+    Vector<EventTarget*, 32> targetStack;
+    for (EventPathWalker walker(node); walker.node(); walker.moveToParent()) {
+        Node* node = walker.node();
+        if (targetStack.isEmpty())
+            targetStack.append(eventTargetRespectingTargetRules(node));
+        else if (walker.isVisitingInsertionPointInReprojection())
+            targetStack.append(targetStack.last());
+        if (isMouseOrFocusEvent)
+            eventPath.append(adoptPtr(new MouseOrFocusEventContext(node, eventTargetRespectingTargetRules(node), targetStack.last())));
+        else if (isTouchEvent)
+            eventPath.append(adoptPtr(new TouchEventContext(node, eventTargetRespectingTargetRules(node), targetStack.last())));
+        else
+            eventPath.append(adoptPtr(new EventContext(node, eventTargetRespectingTargetRules(node), targetStack.last())));
+        if (!inDocument)
+            return;
+        if (!node->isShadowRoot())
+            continue;
+        if (determineDispatchBehavior(event, toShadowRoot(node), targetStack.last()) == StayInsideShadowDOM)
+            return;
+        if (!isSVGElement) {
+            ASSERT(!targetStack.isEmpty());
+            targetStack.removeLast();
+        }
+    }
+}
+
+void EventRetargeter::adjustForMouseEvent(Node* node, MouseEvent& mouseEvent)
+{
+    adjustForRelatedTarget(node, mouseEvent.relatedTarget(), mouseEvent.eventPath());
+}
+
+void EventRetargeter::adjustForFocusEvent(Node* node, FocusEvent& focusEvent)
+{
+    adjustForRelatedTarget(node, focusEvent.relatedTarget(), focusEvent.eventPath());
+}
+
+void EventRetargeter::adjustForTouchEvent(Node* node, TouchEvent& touchEvent)
+{
+    EventPath& eventPath = touchEvent.eventPath();
+    size_t eventPathSize = eventPath.size();
+
+    EventPathTouchLists eventPathTouches(eventPathSize);
+    EventPathTouchLists eventPathTargetTouches(eventPathSize);
+    EventPathTouchLists eventPathChangedTouches(eventPathSize);
+
+    for (size_t i = 0; i < eventPathSize; ++i) {
+        ASSERT(eventPath[i]->isTouchEventContext());
+        TouchEventContext* touchEventContext = toTouchEventContext(eventPath[i].get());
+        eventPathTouches[i] = touchEventContext->touches();
+        eventPathTargetTouches[i] = touchEventContext->targetTouches();
+        eventPathChangedTouches[i] = touchEventContext->changedTouches();
+    }
+
+    adjustTouchList(node, touchEvent.touches(), eventPath, eventPathTouches);
+    adjustTouchList(node, touchEvent.targetTouches(), eventPath, eventPathTargetTouches);
+    adjustTouchList(node, touchEvent.changedTouches(), eventPath, eventPathChangedTouches);
+}
+
+void EventRetargeter::adjustTouchList(const Node* node, const TouchList* touchList, const EventPath& eventPath, EventPathTouchLists& eventPathTouchLists)
+{
+    if (!touchList)
+        return;
+    size_t eventPathSize = eventPath.size();
+    ASSERT(eventPathTouchLists.size() == eventPathSize);
+    for (size_t i = 0; i < touchList->length(); ++i) {
+        const Touch& touch = *touchList->item(i);
+        AdjustedNodes adjustedNodes;
+        calculateAdjustedNodes(node, touch.target()->toNode(), DoesNotStopAtBoundary, const_cast<EventPath&>(eventPath), adjustedNodes);
+        ASSERT(adjustedNodes.size() == eventPathSize);
+        for (size_t j = 0; j < eventPathSize; ++j)
+            eventPathTouchLists[j]->append(touch.cloneWithNewTarget(adjustedNodes[j].get()));
+    }
+}
+
+void EventRetargeter::adjustForRelatedTarget(const Node* node, EventTarget* relatedTarget, EventPath& eventPath)
+{
+    if (!node)
+        return;
+    if (!relatedTarget)
+        return;
+    Node* relatedNode = relatedTarget->toNode();
+    if (!relatedNode)
+        return;
+    AdjustedNodes adjustedNodes;
+    calculateAdjustedNodes(node, relatedNode, StopAtBoundaryIfNeeded, eventPath, adjustedNodes);
+    ASSERT(adjustedNodes.size() <= eventPath.size());
+    for (size_t i = 0; i < adjustedNodes.size(); ++i) {
+        ASSERT(eventPath[i]->isMouseOrFocusEventContext());
+        MouseOrFocusEventContext* mouseOrFocusEventContext = static_cast<MouseOrFocusEventContext*>(eventPath[i].get());
+        mouseOrFocusEventContext->setRelatedTarget(adjustedNodes[i]);
+    }
+}
+
+void EventRetargeter::calculateAdjustedNodes(const Node* node, const Node* relatedNode, EventWithRelatedTargetDispatchBehavior eventWithRelatedTargetDispatchBehavior, EventPath& eventPath, AdjustedNodes& adjustedNodes)
+{
+    RelatedNodeMap relatedNodeMap;
+    buildRelatedNodeMap(relatedNode, relatedNodeMap);
+
+    // Synthetic mouse events can have a relatedTarget which is identical to the target.
+    bool targetIsIdenticalToToRelatedTarget = (node == relatedNode);
+
+    TreeScope* lastTreeScope = 0;
+    Node* adjustedNode = 0;
+    for (EventPath::const_iterator iter = eventPath.begin(); iter < eventPath.end(); ++iter) {
+        TreeScope* scope = (*iter)->node()->treeScope();
+        if (scope == lastTreeScope) {
+            // Re-use the previous adjustedRelatedTarget if treeScope does not change. Just for the performance optimization.
+            adjustedNodes.append(adjustedNode);
+        } else {
+            adjustedNode = findRelatedNode(scope, relatedNodeMap);
+            adjustedNodes.append(adjustedNode);
+        }
+        lastTreeScope = scope;
+        if (eventWithRelatedTargetDispatchBehavior == DoesNotStopAtBoundary)
+            continue;
+        if (targetIsIdenticalToToRelatedTarget) {
+            if (node->treeScope()->rootNode() == (*iter)->node()) {
+                eventPath.shrink(iter + 1 - eventPath.begin());
+                break;
+            }
+        } else if ((*iter)->target() == adjustedNode) {
+            // Event dispatching should be stopped here.
+            eventPath.shrink(iter - eventPath.begin());
+            adjustedNodes.shrink(adjustedNodes.size() - 1);
+            break;
+        }
+    }
+}
+
+void EventRetargeter::buildRelatedNodeMap(const Node* relatedNode, RelatedNodeMap& relatedNodeMap)
+{
+    Vector<Node*, 32> relatedNodeStack;
+    TreeScope* lastTreeScope = 0;
+    for (EventPathWalker walker(relatedNode); walker.node(); walker.moveToParent()) {
+        Node* node = walker.node();
+        if (relatedNodeStack.isEmpty())
+            relatedNodeStack.append(node);
+        else if (walker.isVisitingInsertionPointInReprojection())
+            relatedNodeStack.append(relatedNodeStack.last());
+        TreeScope* scope = node->treeScope();
+        // Skips adding a node to the map if treeScope does not change. Just for the performance optimization.
+        if (scope != lastTreeScope)
+            relatedNodeMap.add(scope, relatedNodeStack.last());
+        lastTreeScope = scope;
+        if (node->isShadowRoot()) {
+            ASSERT(!relatedNodeStack.isEmpty());
+            relatedNodeStack.removeLast();
+        }
+    }
+}
+
+Node* EventRetargeter::findRelatedNode(TreeScope* scope, RelatedNodeMap& relatedNodeMap)
+{
+    Vector<TreeScope*, 32> parentTreeScopes;
+    Node* relatedNode = 0;
+    while (scope) {
+        parentTreeScopes.append(scope);
+        RelatedNodeMap::const_iterator found = relatedNodeMap.find(scope);
+        if (found != relatedNodeMap.end()) {
+            relatedNode = found->value;
+            break;
+        }
+        scope = scope->parentTreeScope();
+    }
+    for (Vector<TreeScope*, 32>::iterator iter = parentTreeScopes.begin(); iter < parentTreeScopes.end(); ++iter)
+        relatedNodeMap.add(*iter, relatedNode);
+    return relatedNode;
+}
+
+}
diff --git a/Source/core/dom/EventRetargeter.h b/Source/core/dom/EventRetargeter.h
new file mode 100644
index 0000000..d88e674
--- /dev/null
+++ b/Source/core/dom/EventRetargeter.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef EventRetargeter_h
+#define EventRetargeter_h
+
+#include "core/dom/ContainerNode.h"
+#include "core/dom/EventContext.h"
+#include "core/dom/ShadowRoot.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#include "core/svg/SVGElementInstance.h"
+#include "core/svg/SVGUseElement.h"
+#endif
+
+namespace WebCore {
+
+class EventTarget;
+class FocusEvent;
+class MouseEvent;
+class Node;
+class TouchEvent;
+class TreeScope;
+
+enum EventDispatchBehavior {
+    RetargetEvent,
+    StayInsideShadowDOM
+};
+
+class EventRetargeter {
+public:
+    static void calculateEventPath(Node*, Event*);
+    static void adjustForMouseEvent(Node*, MouseEvent&);
+    static void adjustForFocusEvent(Node*, FocusEvent&);
+    typedef Vector<RefPtr<TouchList> > EventPathTouchLists;
+    static void adjustForTouchEvent(Node*, TouchEvent&);
+    static EventTarget* eventTargetRespectingTargetRules(Node* referenceNode);
+
+private:
+    typedef Vector<RefPtr<Node> > AdjustedNodes;
+    typedef HashMap<TreeScope*, Node*> RelatedNodeMap;
+    enum EventWithRelatedTargetDispatchBehavior {
+        StopAtBoundaryIfNeeded,
+        DoesNotStopAtBoundary
+    };
+    static void adjustForRelatedTarget(const Node*, EventTarget* relatedTarget, EventPath&);
+    static void calculateAdjustedNodes(const Node*, const Node* relatedNode, EventWithRelatedTargetDispatchBehavior, EventPath&, AdjustedNodes&);
+    static void buildRelatedNodeMap(const Node*, RelatedNodeMap&);
+    static Node* findRelatedNode(TreeScope*, RelatedNodeMap&);
+    static void adjustTouchList(const Node*, const TouchList*, const EventPath&, EventPathTouchLists&);
+};
+
+inline EventTarget* EventRetargeter::eventTargetRespectingTargetRules(Node* referenceNode)
+{
+    ASSERT(referenceNode);
+
+    if (referenceNode->isPseudoElement())
+        return referenceNode->parentNode();
+
+#if ENABLE(SVG)
+    if (!referenceNode->isSVGElement() || !referenceNode->isInShadowTree())
+        return referenceNode;
+
+    // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
+    // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
+    Element* shadowHostElement = toShadowRoot(referenceNode->treeScope()->rootNode())->host();
+    // At this time, SVG nodes are not supported in non-<use> shadow trees.
+    if (!shadowHostElement || !shadowHostElement->hasTagName(SVGNames::useTag))
+        return referenceNode;
+    SVGUseElement* useElement = static_cast<SVGUseElement*>(shadowHostElement);
+    if (SVGElementInstance* instance = useElement->instanceForShadowTreeElement(referenceNode))
+        return instance;
+#endif
+
+    return referenceNode;
+}
+
+}
+
+#endif // EventRetargeter_h
diff --git a/Source/core/dom/EventSender.h b/Source/core/dom/EventSender.h
new file mode 100644
index 0000000..c0ee7c5
--- /dev/null
+++ b/Source/core/dom/EventSender.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 EventSender_h
+#define EventSender_h
+
+#include "core/platform/Timer.h"
+#include <wtf/text/AtomicString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+template<typename T> class EventSender {
+    WTF_MAKE_NONCOPYABLE(EventSender); WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit EventSender(const AtomicString& eventType);
+
+    const AtomicString& eventType() const { return m_eventType; }
+    void dispatchEventSoon(T*);
+    void cancelEvent(T*);
+    void dispatchPendingEvents();
+
+#ifndef NDEBUG
+    bool hasPendingEvents(T* sender) const
+    {
+        return m_dispatchSoonList.find(sender) != notFound || m_dispatchingList.find(sender) != notFound;
+    }
+#endif
+
+private:
+    void timerFired(Timer<EventSender<T> >*) { dispatchPendingEvents(); }
+
+    AtomicString m_eventType;
+    Timer<EventSender<T> > m_timer;
+    Vector<T*> m_dispatchSoonList;
+    Vector<T*> m_dispatchingList;
+};
+
+template<typename T> EventSender<T>::EventSender(const AtomicString& eventType)
+    : m_eventType(eventType)
+    , m_timer(this, &EventSender::timerFired)
+{
+}
+
+template<typename T> void EventSender<T>::dispatchEventSoon(T* sender)
+{
+    m_dispatchSoonList.append(sender);
+    if (!m_timer.isActive())
+        m_timer.startOneShot(0);
+}
+
+template<typename T> void EventSender<T>::cancelEvent(T* sender)
+{
+    // Remove instances of this sender from both lists.
+    // Use loops because we allow multiple instances to get into the lists.
+    size_t size = m_dispatchSoonList.size();
+    for (size_t i = 0; i < size; ++i) {
+        if (m_dispatchSoonList[i] == sender)
+            m_dispatchSoonList[i] = 0;
+    }
+    size = m_dispatchingList.size();
+    for (size_t i = 0; i < size; ++i) {
+        if (m_dispatchingList[i] == sender)
+            m_dispatchingList[i] = 0;
+    }
+}
+
+template<typename T> void EventSender<T>::dispatchPendingEvents()
+{
+    // Need to avoid re-entering this function; if new dispatches are
+    // scheduled before the parent finishes processing the list, they
+    // will set a timer and eventually be processed.
+    if (!m_dispatchingList.isEmpty())
+        return;
+
+    m_timer.stop();
+
+    m_dispatchSoonList.checkConsistency();
+
+    m_dispatchingList.swap(m_dispatchSoonList);
+    size_t size = m_dispatchingList.size();
+    for (size_t i = 0; i < size; ++i) {
+        if (T* sender = m_dispatchingList[i]) {
+            m_dispatchingList[i] = 0;
+            sender->dispatchPendingEvent(this);
+        }
+    }
+    m_dispatchingList.clear();
+}
+
+} // namespace WebCore
+
+#endif // EventSender_h
diff --git a/Source/core/dom/EventTarget.cpp b/Source/core/dom/EventTarget.cpp
new file mode 100644
index 0000000..0625587
--- /dev/null
+++ b/Source/core/dom/EventTarget.cpp
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ *           (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "core/dom/EventTarget.h"
+
+#include "bindings/v8/ScriptController.h"
+#include "core/dom/Event.h"
+#include "core/dom/EventException.h"
+#include "core/dom/TransitionEvent.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include <wtf/MainThread.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+using namespace WTF;
+
+namespace WebCore {
+
+EventTargetData::EventTargetData()
+{
+}
+
+EventTargetData::~EventTargetData()
+{
+}
+
+EventTarget::~EventTarget()
+{
+}
+
+Node* EventTarget::toNode()
+{
+    return 0;
+}
+
+DOMWindow* EventTarget::toDOMWindow()
+{
+    return 0;
+}
+
+bool EventTarget::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
+{
+    EventTargetData* d = ensureEventTargetData();
+    return d->eventListenerMap.add(eventType, listener, useCapture);
+}
+
+bool EventTarget::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
+{
+    EventTargetData* d = eventTargetData();
+    if (!d)
+        return false;
+
+    size_t indexOfRemovedListener;
+
+    if (!d->eventListenerMap.remove(eventType, listener, useCapture, indexOfRemovedListener))
+        return false;
+
+    // Notify firing events planning to invoke the listener at 'index' that
+    // they have one less listener to invoke.
+    if (!d->firingEventIterators)
+        return true;
+    for (size_t i = 0; i < d->firingEventIterators->size(); ++i) {
+        FiringEventIterator& firingIterator = d->firingEventIterators->at(i);
+        if (eventType != firingIterator.eventType)
+            continue;
+
+        if (indexOfRemovedListener >= firingIterator.end)
+            continue;
+
+        --firingIterator.end;
+        if (indexOfRemovedListener <= firingIterator.iterator)
+            --firingIterator.iterator;
+    }
+
+    return true;
+}
+
+bool EventTarget::setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener)
+{
+    clearAttributeEventListener(eventType);
+    if (!listener)
+        return false;
+    return addEventListener(eventType, listener, false);
+}
+
+EventListener* EventTarget::getAttributeEventListener(const AtomicString& eventType)
+{
+    const EventListenerVector& entry = getEventListeners(eventType);
+    for (size_t i = 0; i < entry.size(); ++i) {
+        if (entry[i].listener->isAttribute())
+            return entry[i].listener.get();
+    }
+    return 0;
+}
+
+bool EventTarget::clearAttributeEventListener(const AtomicString& eventType)
+{
+    EventListener* listener = getAttributeEventListener(eventType);
+    if (!listener)
+        return false;
+    return removeEventListener(eventType, listener, false);
+}
+
+bool EventTarget::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec)
+{
+    if (!event || event->type().isEmpty()) {
+        ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
+        return false;
+    }
+
+    if (event->isBeingDispatched()) {
+        ec = EventException::DISPATCH_REQUEST_ERR;
+        return false;
+    }
+
+    if (!scriptExecutionContext())
+        return false;
+
+    return dispatchEvent(event);
+}
+
+bool EventTarget::dispatchEvent(PassRefPtr<Event> event)
+{
+    event->setTarget(this);
+    event->setCurrentTarget(this);
+    event->setEventPhase(Event::AT_TARGET);
+    bool defaultPrevented = fireEventListeners(event.get());
+    event->setEventPhase(0);
+    return defaultPrevented;
+}
+
+void EventTarget::uncaughtExceptionInEventHandler()
+{
+}
+
+static PassRefPtr<Event> createMatchingPrefixedEvent(const Event* event)
+{
+    if (event->type() == eventNames().transitionendEvent) {
+        const TransitionEvent* transitionEvent = static_cast<const TransitionEvent*>(event);
+        RefPtr<Event> prefixedEvent = TransitionEvent::create(eventNames().webkitTransitionEndEvent, transitionEvent->propertyName(), transitionEvent->elapsedTime(), transitionEvent->pseudoElement());
+        prefixedEvent->setTarget(event->target());
+        prefixedEvent->setCurrentTarget(event->currentTarget());
+        prefixedEvent->setEventPhase(event->eventPhase());
+        return prefixedEvent.release();
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+static AtomicString prefixedType(const Event* event)
+{
+    if (event->type() == eventNames().transitionendEvent)
+        return eventNames().webkitTransitionEndEvent;
+
+    return emptyString();
+}
+
+bool EventTarget::fireEventListeners(Event* event)
+{
+    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
+    ASSERT(event && !event->type().isEmpty());
+
+    EventTargetData* d = eventTargetData();
+    if (!d)
+        return true;
+
+    EventListenerVector* listenerPrefixedVector = 0;
+    AtomicString prefixedTypeName = prefixedType(event);
+    if (!prefixedTypeName.isEmpty())
+        listenerPrefixedVector = d->eventListenerMap.find(prefixedTypeName);
+
+    EventListenerVector* listenerUnprefixedVector = d->eventListenerMap.find(event->type());
+
+    if (listenerUnprefixedVector)
+        fireEventListeners(event, d, *listenerUnprefixedVector);
+    else if (listenerPrefixedVector)
+        fireEventListeners(createMatchingPrefixedEvent(event).get(), d, *listenerPrefixedVector);
+
+    if (!prefixedTypeName.isEmpty()) {
+        ScriptExecutionContext* context = scriptExecutionContext();
+        if (context && context->isDocument()) {
+            Document* document = toDocument(context);
+            if (document->domWindow()) {
+                if (listenerPrefixedVector)
+                    if (listenerUnprefixedVector)
+                        UseCounter::count(document->domWindow(), UseCounter::PrefixedAndUnprefixedTransitionEndEvent);
+                    else
+                        UseCounter::count(document->domWindow(), UseCounter::PrefixedTransitionEndEvent);
+                else if (listenerUnprefixedVector)
+                    UseCounter::count(document->domWindow(), UseCounter::UnprefixedTransitionEndEvent);
+            }
+        }
+    }
+
+    return !event->defaultPrevented();
+}
+        
+void EventTarget::fireEventListeners(Event* event, EventTargetData* d, EventListenerVector& entry)
+{
+    RefPtr<EventTarget> protect = this;
+
+    // Fire all listeners registered for this event. Don't fire listeners removed
+    // during event dispatch. Also, don't fire event listeners added during event
+    // dispatch. Conveniently, all new event listeners will be added after 'end',
+    // so iterating to 'end' naturally excludes new event listeners.
+
+    bool userEventWasHandled = false;
+    size_t i = 0;
+    size_t end = entry.size();
+    if (!d->firingEventIterators)
+        d->firingEventIterators = adoptPtr(new FiringEventIteratorVector);
+    d->firingEventIterators->append(FiringEventIterator(event->type(), i, end));
+    for ( ; i < end; ++i) {
+        RegisteredEventListener& registeredListener = entry[i];
+        if (event->eventPhase() == Event::CAPTURING_PHASE && !registeredListener.useCapture)
+            continue;
+        if (event->eventPhase() == Event::BUBBLING_PHASE && registeredListener.useCapture)
+            continue;
+
+        // If stopImmediatePropagation has been called, we just break out immediately, without
+        // handling any more events on this target.
+        if (event->immediatePropagationStopped())
+            break;
+
+        ScriptExecutionContext* context = scriptExecutionContext();
+        InspectorInstrumentationCookie cookie = InspectorInstrumentation::willHandleEvent(context, event);
+        // To match Mozilla, the AT_TARGET phase fires both capturing and bubbling
+        // event listeners, even though that violates some versions of the DOM spec.
+        registeredListener.listener->handleEvent(context, event);
+        if (!userEventWasHandled && ScriptController::processingUserGesture())
+            userEventWasHandled = true;
+        InspectorInstrumentation::didHandleEvent(cookie);
+    }
+    d->firingEventIterators->removeLast();
+    if (userEventWasHandled) {
+        ScriptExecutionContext* context = scriptExecutionContext();
+        if (context && context->isDocument()) {
+            Document* document = toDocument(context);
+            document->resetLastHandledUserGestureTimestamp();
+        }
+    }
+}
+
+const EventListenerVector& EventTarget::getEventListeners(const AtomicString& eventType)
+{
+    DEFINE_STATIC_LOCAL(EventListenerVector, emptyVector, ());
+
+    EventTargetData* d = eventTargetData();
+    if (!d)
+        return emptyVector;
+
+    EventListenerVector* listenerVector = d->eventListenerMap.find(eventType);
+    if (!listenerVector)
+        return emptyVector;
+
+    return *listenerVector;
+}
+
+void EventTarget::removeAllEventListeners()
+{
+    EventTargetData* d = eventTargetData();
+    if (!d)
+        return;
+    d->eventListenerMap.clear();
+
+    // Notify firing events planning to invoke the listener at 'index' that
+    // they have one less listener to invoke.
+    if (d->firingEventIterators) {
+        for (size_t i = 0; i < d->firingEventIterators->size(); ++i) {
+            d->firingEventIterators->at(i).iterator = 0;
+            d->firingEventIterators->at(i).end = 0;
+        }
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/EventTarget.h b/Source/core/dom/EventTarget.h
new file mode 100644
index 0000000..7bf80c9
--- /dev/null
+++ b/Source/core/dom/EventTarget.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ *           (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef EventTarget_h
+#define EventTarget_h
+
+#include "core/dom/EventListenerMap.h"
+#include "core/dom/EventNames.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/text/AtomicStringHash.h>
+
+namespace WebCore {
+
+    class AudioContext;
+    class DedicatedWorkerContext;
+    class DOMApplicationCache;
+    class DOMWindow;
+    class Event;
+    class EventListener;
+    class EventSource;
+    class FileReader;
+    class FileWriter;
+    class IDBDatabase;
+    class IDBRequest;
+    class IDBTransaction;
+    class MIDIInput;
+    class MIDIPort;
+    class MediaController;
+    class MediaSource;
+    class MediaStream;
+    class MessagePort;
+    class NamedFlow;
+    class Node;
+    class Notification;
+    class SVGElementInstance;
+    class ScriptExecutionContext;
+    class ScriptProcessorNode;
+    class SharedWorker;
+    class SharedWorkerContext;
+    class SourceBufferList;
+    class TextTrack;
+    class TextTrackCue;
+    class WebSocket;
+    class Worker;
+    class XMLHttpRequest;
+    class XMLHttpRequestUpload;
+
+    typedef int ExceptionCode;
+
+    struct FiringEventIterator {
+        FiringEventIterator(const AtomicString& eventType, size_t& iterator, size_t& end)
+            : eventType(eventType)
+            , iterator(iterator)
+            , end(end)
+        {
+        }
+
+        const AtomicString& eventType;
+        size_t& iterator;
+        size_t& end;
+    };
+    typedef Vector<FiringEventIterator, 1> FiringEventIteratorVector;
+
+    struct EventTargetData {
+        WTF_MAKE_NONCOPYABLE(EventTargetData); WTF_MAKE_FAST_ALLOCATED;
+    public:
+        EventTargetData();
+        ~EventTargetData();
+
+        EventListenerMap eventListenerMap;
+        OwnPtr<FiringEventIteratorVector> firingEventIterators;
+    };
+
+    class EventTarget {
+    public:
+        void ref() { refEventTarget(); }
+        void deref() { derefEventTarget(); }
+
+        virtual const AtomicString& interfaceName() const = 0;
+        virtual ScriptExecutionContext* scriptExecutionContext() const = 0;
+
+        virtual Node* toNode();
+        virtual DOMWindow* toDOMWindow();
+
+        virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
+        virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
+        virtual void removeAllEventListeners();
+        virtual bool dispatchEvent(PassRefPtr<Event>);
+        bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&); // DOM API
+        virtual void uncaughtExceptionInEventHandler();
+
+        // Used for legacy "onEvent" attribute APIs.
+        bool setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener>);
+        bool clearAttributeEventListener(const AtomicString& eventType);
+        EventListener* getAttributeEventListener(const AtomicString& eventType);
+
+        bool hasEventListeners();
+        bool hasEventListeners(const AtomicString& eventType);
+        const EventListenerVector& getEventListeners(const AtomicString& eventType);
+
+        bool fireEventListeners(Event*);
+        bool isFiringEventListeners();
+
+    protected:
+        virtual ~EventTarget();
+        
+        virtual EventTargetData* eventTargetData() = 0;
+        virtual EventTargetData* ensureEventTargetData() = 0;
+
+    private:
+        virtual void refEventTarget() = 0;
+        virtual void derefEventTarget() = 0;
+        
+        void fireEventListeners(Event*, EventTargetData*, EventListenerVector&);
+
+        friend class EventListenerIterator;
+    };
+
+    // FIXME: These macros should be split into separate DEFINE and DECLARE
+    // macros to avoid causing so many header includes.
+    #define DEFINE_ATTRIBUTE_EVENT_LISTENER(attribute) \
+        EventListener* on##attribute() { return getAttributeEventListener(eventNames().attribute##Event); } \
+        void setOn##attribute(PassRefPtr<EventListener> listener) { setAttributeEventListener(eventNames().attribute##Event, listener); } \
+
+    #define DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(attribute) \
+        virtual EventListener* on##attribute(); \
+        virtual void setOn##attribute(PassRefPtr<EventListener> listener); \
+
+    #define DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(type, attribute) \
+        EventListener* type::on##attribute() { return getAttributeEventListener(eventNames().attribute##Event); } \
+        void type::setOn##attribute(PassRefPtr<EventListener> listener) { setAttributeEventListener(eventNames().attribute##Event, listener); } \
+
+    #define DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(attribute) \
+        EventListener* on##attribute() { return document()->getWindowAttributeEventListener(eventNames().attribute##Event); } \
+        void setOn##attribute(PassRefPtr<EventListener> listener) { document()->setWindowAttributeEventListener(eventNames().attribute##Event, listener); } \
+
+    #define DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(attribute, eventName) \
+        EventListener* on##attribute() { return getAttributeEventListener(eventNames().eventName##Event); } \
+        void setOn##attribute(PassRefPtr<EventListener> listener) { setAttributeEventListener(eventNames().eventName##Event, listener); } \
+
+    #define DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(recipient, attribute) \
+        EventListener* on##attribute() { return recipient ? recipient->getAttributeEventListener(eventNames().attribute##Event) : 0; } \
+        void setOn##attribute(PassRefPtr<EventListener> listener) { if (recipient) recipient->setAttributeEventListener(eventNames().attribute##Event, listener); } \
+
+    inline bool EventTarget::isFiringEventListeners()
+    {
+        EventTargetData* d = eventTargetData();
+        if (!d)
+            return false;
+        return d->firingEventIterators && !d->firingEventIterators->isEmpty();
+    }
+
+    inline bool EventTarget::hasEventListeners()
+    {
+        EventTargetData* d = eventTargetData();
+        if (!d)
+            return false;
+        return !d->eventListenerMap.isEmpty();
+    }
+
+    inline bool EventTarget::hasEventListeners(const AtomicString& eventType)
+    {
+        EventTargetData* d = eventTargetData();
+        if (!d)
+            return false;
+        return d->eventListenerMap.contains(eventType);
+    }
+
+} // namespace WebCore
+
+#endif // EventTarget_h
diff --git a/Source/core/dom/EventTarget.idl b/Source/core/dom/EventTarget.idl
new file mode 100644
index 0000000..8647c27
--- /dev/null
+++ b/Source/core/dom/EventTarget.idl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+[
+    CustomToV8,
+    DoNotGenerateWrap,
+    EventTarget
+] interface EventTarget {
+    void addEventListener(DOMString type, 
+                                         EventListener listener, 
+                                         optional boolean useCapture);
+    void removeEventListener(DOMString type, 
+                                         EventListener listener, 
+                                         optional boolean useCapture);
+    [RaisesException] boolean dispatchEvent(Event event);
+};
+
diff --git a/Source/core/dom/EventTargetFactory.in b/Source/core/dom/EventTargetFactory.in
new file mode 100644
index 0000000..d5e4f56
--- /dev/null
+++ b/Source/core/dom/EventTargetFactory.in
@@ -0,0 +1,44 @@
+namespace="EventTarget"
+
+core/css/FontLoader
+core/dom/MessagePort
+core/dom/Node
+core/fileapi/FileReader
+core/html/MediaController
+core/html/track/TextTrack
+core/html/track/TextTrackCue
+core/html/track/TextTrackList
+core/loader/appcache/DOMApplicationCache
+core/page/DOMWindow
+core/page/EventSource
+core/page/Performance
+core/svg/SVGElementInstance conditional=SVG
+core/workers/DedicatedWorkerContext
+core/workers/SharedWorker
+core/workers/SharedWorkerContext
+core/workers/Worker
+core/xml/XMLHttpRequest
+core/xml/XMLHttpRequestUpload
+modules/battery/BatteryManager conditional=BATTERY_STATUS
+modules/encryptedmedia/MediaKeySession conditional=ENCRYPTED_MEDIA_V2
+modules/filesystem/FileWriter
+modules/indexeddb/IDBDatabase
+modules/indexeddb/IDBOpenDBRequest
+modules/indexeddb/IDBRequest
+modules/indexeddb/IDBTransaction
+modules/mediasource/MediaSource
+modules/mediasource/SourceBufferList
+modules/mediastream/MediaStream
+modules/mediastream/MediaStreamTrack
+modules/mediastream/RTCDataChannel
+modules/mediastream/RTCDTMFSender
+modules/mediastream/RTCPeerConnection
+modules/notifications/Notification conditional=NOTIFICATIONS|LEGACY_NOTIFICATIONS
+modules/speech/SpeechRecognition
+modules/speech/SpeechSynthesisUtterance
+modules/webaudio/AudioContext conditional=WEB_AUDIO
+modules/webaudio/ScriptProcessorNode conditional=WEB_AUDIO
+modules/webmidi/MIDIInput
+modules/webmidi/MIDIPort
+modules/websockets/WebSocket
+WebKitNamedFlow interfaceName=NamedFlow
diff --git a/Source/core/dom/ExceptionBase.cpp b/Source/core/dom/ExceptionBase.cpp
new file mode 100644
index 0000000..d6567c7
--- /dev/null
+++ b/Source/core/dom/ExceptionBase.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "core/dom/ExceptionBase.h"
+#include "core/dom/ExceptionCode.h"
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+ExceptionBase::ExceptionBase(const ExceptionCodeDescription& description)
+    : m_code(description.code)
+    , m_name(description.name)
+    , m_description(description.description)
+{
+    if (description.name)
+        m_message = m_name + ": " + description.typeName + " Exception " + String::number(description.code);
+    else
+        m_message = makeString(description.typeName, " Exception ", String::number(description.code));
+}
+
+String ExceptionBase::toString() const
+{
+    return "Error: " + m_message;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/ExceptionBase.h b/Source/core/dom/ExceptionBase.h
new file mode 100644
index 0000000..d8850ae
--- /dev/null
+++ b/Source/core/dom/ExceptionBase.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 ExceptionBase_h
+#define ExceptionBase_h
+
+#include "core/dom/ExceptionCode.h"
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+struct ExceptionCodeDescription;
+
+class ExceptionBase : public RefCounted<ExceptionBase> {
+public:
+    unsigned short code() const { return m_code; }
+    String name() const { return m_name; }
+    String message() const { return m_message; }
+    String description() const { return m_description; }
+
+    String toString() const;
+
+protected:
+    explicit ExceptionBase(const ExceptionCodeDescription&);
+
+private:
+    unsigned short m_code;
+    String m_name;
+    String m_message;
+    String m_description;
+};
+
+} // namespace WebCore
+
+#endif // ExceptionBase_h
diff --git a/Source/core/dom/ExceptionCode.h b/Source/core/dom/ExceptionCode.h
new file mode 100644
index 0000000..88f5f10
--- /dev/null
+++ b/Source/core/dom/ExceptionCode.h
@@ -0,0 +1,75 @@
+/*
+ *  Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef ExceptionCode_h
+#define ExceptionCode_h
+
+// FIXME: Move this header into the files that actually need it.
+#include "ExceptionCodeDescription.h"
+
+namespace WebCore {
+
+    // The DOM standards use unsigned short for exception codes.
+    // In our DOM implementation we use int instead, and use different
+    // numerical ranges for different types of DOM exception, so that
+    // an exception of any type can be expressed with a single integer.
+    typedef int ExceptionCode;
+
+
+    // Some of these are considered historical since they have been
+    // changed or removed from the specifications.
+    enum {
+        INDEX_SIZE_ERR = 1,
+        HIERARCHY_REQUEST_ERR = 3,
+        WRONG_DOCUMENT_ERR = 4,
+        INVALID_CHARACTER_ERR = 5,
+        NO_MODIFICATION_ALLOWED_ERR = 7,
+        NOT_FOUND_ERR = 8,
+        NOT_SUPPORTED_ERR = 9,
+        INUSE_ATTRIBUTE_ERR = 10, // Historical. Only used in setAttributeNode etc which have been removed from the DOM specs.
+
+        // Introduced in DOM Level 2:
+        INVALID_STATE_ERR = 11,
+        SYNTAX_ERR = 12,
+        INVALID_MODIFICATION_ERR = 13,
+        NAMESPACE_ERR = 14,
+        INVALID_ACCESS_ERR = 15,
+
+        // Introduced in DOM Level 3:
+        TYPE_MISMATCH_ERR = 17, // Historical; use TypeError instead
+
+        // XMLHttpRequest extension:
+        SECURITY_ERR = 18,
+
+        // Others introduced in HTML5:
+        NETWORK_ERR = 19,
+        ABORT_ERR = 20,
+        URL_MISMATCH_ERR = 21,
+        QUOTA_EXCEEDED_ERR = 22,
+        TIMEOUT_ERR = 23,
+        INVALID_NODE_TYPE_ERR = 24,
+        DATA_CLONE_ERR = 25,
+
+        // WebIDL exception types, handled by the binding layer.
+        // FIXME: Add GeneralError, EvalError, etc. when implemented in the bindings.
+        TypeError = 105,
+    };
+
+} // namespace WebCore
+
+#endif // ExceptionCode_h
diff --git a/Source/core/dom/ExceptionCodePlaceholder.cpp b/Source/core/dom/ExceptionCodePlaceholder.cpp
new file mode 100644
index 0000000..9eb8ffd
--- /dev/null
+++ b/Source/core/dom/ExceptionCodePlaceholder.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.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/ExceptionCodePlaceholder.h"
+
+namespace WebCore {
+
+#if !ASSERT_DISABLED
+
+NoExceptionAssertionChecker::NoExceptionAssertionChecker(const char* file, int line)
+    : ExceptionCodePlaceholder(defaultExceptionCode)
+    , m_file(file)
+    , m_line(line)
+{
+}
+
+NoExceptionAssertionChecker::~NoExceptionAssertionChecker()
+{
+    ASSERT_AT(!m_code || m_code == defaultExceptionCode, m_file, m_line, "");
+}
+
+#endif
+
+}
diff --git a/Source/core/dom/ExceptionCodePlaceholder.h b/Source/core/dom/ExceptionCodePlaceholder.h
new file mode 100644
index 0000000..aadd527
--- /dev/null
+++ b/Source/core/dom/ExceptionCodePlaceholder.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ExceptionCodePlaceholder_h
+#define ExceptionCodePlaceholder_h
+
+#include <wtf/Assertions.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+typedef int ExceptionCode;
+
+class ExceptionCodePlaceholder {
+    WTF_MAKE_NONCOPYABLE(ExceptionCodePlaceholder);
+public:
+    ExceptionCodePlaceholder() { }
+    explicit ExceptionCodePlaceholder(ExceptionCode);
+
+    operator ExceptionCode& () const { return m_code; }
+
+protected:
+    mutable ExceptionCode m_code;
+};
+
+inline ExceptionCodePlaceholder::ExceptionCodePlaceholder(ExceptionCode code)
+    : m_code(code)
+{
+}
+
+class IgnorableExceptionCode : public ExceptionCodePlaceholder {
+};
+
+#define IGNORE_EXCEPTION ::WebCore::IgnorableExceptionCode()
+
+#if ASSERT_DISABLED
+
+#define ASSERT_NO_EXCEPTION ::WebCore::IgnorableExceptionCode()
+
+#else
+
+class NoExceptionAssertionChecker : public ExceptionCodePlaceholder {
+public:
+    NoExceptionAssertionChecker(const char* file, int line);
+    ~NoExceptionAssertionChecker();
+
+private:
+    static const ExceptionCode defaultExceptionCode = 0xaaaaaaaa;
+    const char* m_file;
+    int m_line;
+};
+
+#define ASSERT_NO_EXCEPTION ::WebCore::NoExceptionAssertionChecker(__FILE__, __LINE__)
+
+#endif
+
+}
+
+#endif
diff --git a/Source/core/dom/FocusEvent.cpp b/Source/core/dom/FocusEvent.cpp
new file mode 100644
index 0000000..80eebe0
--- /dev/null
+++ b/Source/core/dom/FocusEvent.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2013 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. AND ITS 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 APPLE INC. OR ITS 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 "core/dom/FocusEvent.h"
+
+#include "core/dom/Event.h"
+#include "core/dom/EventDispatcher.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/EventRetargeter.h"
+#include "core/dom/Node.h"
+
+namespace WebCore {
+
+FocusEventInit::FocusEventInit()
+    : relatedTarget(0)
+{
+}
+
+const AtomicString& FocusEvent::interfaceName() const
+{
+    return eventNames().interfaceForFocusEvent;
+}
+
+bool FocusEvent::isFocusEvent() const
+{
+    return true;
+}
+
+FocusEvent::FocusEvent()
+{
+    ScriptWrappable::init(this);
+}
+
+FocusEvent::FocusEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView> view, int detail, PassRefPtr<EventTarget> relatedTarget)
+    : UIEvent(type, canBubble, cancelable, view, detail)
+    , m_relatedTarget(relatedTarget)
+{
+    ScriptWrappable::init(this);
+}
+
+FocusEvent::FocusEvent(const AtomicString& type, const FocusEventInit& initializer)
+    : UIEvent(type, initializer)
+    , m_relatedTarget(initializer.relatedTarget)
+{
+    ScriptWrappable::init(this);
+}
+
+PassRefPtr<FocusEventDispatchMediator> FocusEventDispatchMediator::create(PassRefPtr<FocusEvent> focusEvent)
+{
+    return adoptRef(new FocusEventDispatchMediator(focusEvent));
+}
+
+FocusEventDispatchMediator::FocusEventDispatchMediator(PassRefPtr<FocusEvent> focusEvent)
+    : EventDispatchMediator(focusEvent)
+{
+}
+
+bool FocusEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
+{
+    EventRetargeter::adjustForFocusEvent(dispatcher->node(), *event());
+    return EventDispatchMediator::dispatchEvent(dispatcher);
+}
+
+PassRefPtr<BlurEventDispatchMediator> BlurEventDispatchMediator::create(PassRefPtr<FocusEvent> focusEvent)
+{
+    return adoptRef(new BlurEventDispatchMediator(focusEvent));
+}
+
+BlurEventDispatchMediator::BlurEventDispatchMediator(PassRefPtr<FocusEvent> focusEvent)
+    : EventDispatchMediator(focusEvent)
+{
+}
+
+bool BlurEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
+{
+    EventRetargeter::adjustForFocusEvent(dispatcher->node(), *event());
+    return EventDispatchMediator::dispatchEvent(dispatcher);
+}
+
+PassRefPtr<FocusInEventDispatchMediator> FocusInEventDispatchMediator::create(PassRefPtr<FocusEvent> focusEvent)
+{
+    return adoptRef(new FocusInEventDispatchMediator(focusEvent));
+}
+
+FocusInEventDispatchMediator::FocusInEventDispatchMediator(PassRefPtr<FocusEvent> focusEvent)
+    : EventDispatchMediator(focusEvent)
+{
+}
+
+bool FocusInEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
+{
+    EventRetargeter::adjustForFocusEvent(dispatcher->node(), *event());
+    return EventDispatchMediator::dispatchEvent(dispatcher);
+}
+
+PassRefPtr<FocusOutEventDispatchMediator> FocusOutEventDispatchMediator::create(PassRefPtr<FocusEvent> focusEvent)
+{
+    return adoptRef(new FocusOutEventDispatchMediator(focusEvent));
+}
+
+FocusOutEventDispatchMediator::FocusOutEventDispatchMediator(PassRefPtr<FocusEvent> focusEvent)
+    : EventDispatchMediator(focusEvent)
+{
+}
+
+bool FocusOutEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
+{
+    EventRetargeter::adjustForFocusEvent(dispatcher->node(), *event());
+    return EventDispatchMediator::dispatchEvent(dispatcher);
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/FocusEvent.h b/Source/core/dom/FocusEvent.h
new file mode 100644
index 0000000..65dbfd5
--- /dev/null
+++ b/Source/core/dom/FocusEvent.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2013 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. AND ITS 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 APPLE INC. OR ITS 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 FocusEvent_h
+#define FocusEvent_h
+
+#include "core/dom/EventTarget.h"
+#include "core/dom/UIEvent.h"
+
+namespace WebCore {
+
+class Node;
+
+struct FocusEventInit : public UIEventInit {
+    FocusEventInit();
+
+    RefPtr<EventTarget> relatedTarget;
+};
+
+class FocusEvent : public UIEvent {
+public:
+    static PassRefPtr<FocusEvent> create()
+    {
+        return adoptRef(new FocusEvent);
+    }
+
+    static PassRefPtr<FocusEvent> create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView> view, int detail, PassRefPtr<EventTarget> relatedTarget)
+    {
+        return adoptRef(new FocusEvent(type, canBubble, cancelable, view, detail, relatedTarget));
+    }
+
+    static PassRefPtr<FocusEvent> create(const AtomicString& type, const FocusEventInit& initializer)
+    {
+        return adoptRef(new FocusEvent(type, initializer));
+    }
+
+    EventTarget* relatedTarget() const { return m_relatedTarget.get(); }
+    void setRelatedTarget(PassRefPtr<EventTarget> relatedTarget) { m_relatedTarget = relatedTarget; }
+
+    virtual const AtomicString& interfaceName() const;
+    virtual bool isFocusEvent() const;
+
+private:
+    FocusEvent();
+    FocusEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>, int, PassRefPtr<EventTarget>);
+    FocusEvent(const AtomicString& type, const FocusEventInit&);
+
+    RefPtr<EventTarget> m_relatedTarget;
+};
+
+inline FocusEvent* toFocusEvent(Event* event)
+{
+    ASSERT(event && event->isFocusEvent());
+    return static_cast<FocusEvent*>(event);
+}
+
+class FocusEventDispatchMediator : public EventDispatchMediator {
+public:
+    static PassRefPtr<FocusEventDispatchMediator> create(PassRefPtr<FocusEvent>);
+private:
+    explicit FocusEventDispatchMediator(PassRefPtr<FocusEvent>);
+    FocusEvent* event() const { return static_cast<FocusEvent*>(EventDispatchMediator::event()); }
+    virtual bool dispatchEvent(EventDispatcher*) const OVERRIDE;
+};
+
+class BlurEventDispatchMediator : public EventDispatchMediator {
+public:
+    static PassRefPtr<BlurEventDispatchMediator> create(PassRefPtr<FocusEvent>);
+private:
+    explicit BlurEventDispatchMediator(PassRefPtr<FocusEvent>);
+    FocusEvent* event() const { return static_cast<FocusEvent*>(EventDispatchMediator::event()); }
+    virtual bool dispatchEvent(EventDispatcher*) const OVERRIDE;
+};
+
+class FocusInEventDispatchMediator : public EventDispatchMediator {
+public:
+    static PassRefPtr<FocusInEventDispatchMediator> create(PassRefPtr<FocusEvent>);
+private:
+    explicit FocusInEventDispatchMediator(PassRefPtr<FocusEvent>);
+    FocusEvent* event() const { return static_cast<FocusEvent*>(EventDispatchMediator::event()); }
+    virtual bool dispatchEvent(EventDispatcher*) const OVERRIDE;
+};
+
+class FocusOutEventDispatchMediator : public EventDispatchMediator {
+public:
+    static PassRefPtr<FocusOutEventDispatchMediator> create(PassRefPtr<FocusEvent>);
+private:
+    explicit FocusOutEventDispatchMediator(PassRefPtr<FocusEvent>);
+    FocusEvent* event() const { return static_cast<FocusEvent*>(EventDispatchMediator::event()); }
+    virtual bool dispatchEvent(EventDispatcher*) const OVERRIDE;
+};
+
+} // namespace WebCore
+
+#endif // FocusEvent_h
diff --git a/Source/core/dom/FocusEvent.idl b/Source/core/dom/FocusEvent.idl
new file mode 100644
index 0000000..659e576
--- /dev/null
+++ b/Source/core/dom/FocusEvent.idl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013 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. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+[
+    ConstructorTemplate=Event
+] interface FocusEvent : UIEvent {
+    [InitializedByEventConstructor] readonly attribute EventTarget relatedTarget;
+};
diff --git a/Source/core/dom/FragmentScriptingPermission.h b/Source/core/dom/FragmentScriptingPermission.h
new file mode 100644
index 0000000..21b3552
--- /dev/null
+++ b/Source/core/dom/FragmentScriptingPermission.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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.
+ */
+
+// FIXME: Move this file to ParserContentPolicy.h.
+
+#ifndef ParserContentPolicy_h
+#define ParserContentPolicy_h
+
+namespace WebCore {
+
+enum ParserContentPolicy {
+    DisallowScriptingAndPluginContent,
+    DisallowScriptingContent,
+    AllowScriptingContent,
+    AllowScriptingContentAndDoNotMarkAlreadyStarted,
+};
+
+static inline bool scriptingContentIsAllowed(ParserContentPolicy parserContentPolicy) 
+{
+    return parserContentPolicy == AllowScriptingContent || parserContentPolicy == AllowScriptingContentAndDoNotMarkAlreadyStarted;
+}
+
+static inline ParserContentPolicy disallowScriptingContent(ParserContentPolicy parserContentPolicy)
+{
+    if (!scriptingContentIsAllowed(parserContentPolicy))
+        return parserContentPolicy;
+    return DisallowScriptingContent;
+}
+
+static inline bool pluginContentIsAllowed(ParserContentPolicy parserContentPolicy)
+{
+    return parserContentPolicy != DisallowScriptingAndPluginContent;
+}
+
+static inline ParserContentPolicy allowPluginContent(ParserContentPolicy parserContentPolicy)
+{
+    if (pluginContentIsAllowed(parserContentPolicy))
+        return parserContentPolicy;
+    return DisallowScriptingContent;
+}
+
+} // namespace WebCore
+
+#endif // ParserContentPolicy_h
diff --git a/Source/core/dom/GenericEventQueue.cpp b/Source/core/dom/GenericEventQueue.cpp
new file mode 100644
index 0000000..172074f
--- /dev/null
+++ b/Source/core/dom/GenericEventQueue.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2012 Victor Carbune (victor@rosedu.org)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+
+#include "core/dom/GenericEventQueue.h"
+
+#include "core/dom/Event.h"
+
+namespace WebCore {
+
+PassOwnPtr<GenericEventQueue> GenericEventQueue::create(EventTarget* owner)
+{
+    return adoptPtr(new GenericEventQueue(owner));
+}
+
+GenericEventQueue::GenericEventQueue(EventTarget* owner)
+    : m_owner(owner)
+    , m_timer(this, &GenericEventQueue::timerFired)
+    , m_isClosed(false)
+{
+}
+
+GenericEventQueue::~GenericEventQueue()
+{
+}
+
+bool GenericEventQueue::enqueueEvent(PassRefPtr<Event> event)
+{
+    if (m_isClosed)
+        return false;
+
+    ASSERT(event->target());
+    if (event->target() == m_owner)
+        event->setTarget(0);
+
+    m_pendingEvents.append(event);
+
+    if (!m_timer.isActive())
+        m_timer.startOneShot(0);
+
+    return true;
+}
+
+bool GenericEventQueue::cancelEvent(Event* event)
+{
+    bool found = m_pendingEvents.contains(event);
+
+    if (found)
+        m_pendingEvents.remove(m_pendingEvents.find(event));
+
+    if (m_pendingEvents.isEmpty())
+        m_timer.stop();
+
+    return found;
+}
+
+void GenericEventQueue::timerFired(Timer<GenericEventQueue>*)
+{
+    ASSERT(!m_timer.isActive());
+    ASSERT(!m_pendingEvents.isEmpty());
+
+    Vector<RefPtr<Event> > pendingEvents;
+    m_pendingEvents.swap(pendingEvents);
+
+    RefPtr<EventTarget> protect(m_owner);
+    for (unsigned i = 0; i < pendingEvents.size(); ++i) {
+        EventTarget* target = pendingEvents[i]->target() ? pendingEvents[i]->target() : m_owner;
+        target->dispatchEvent(pendingEvents[i].release());
+    }
+}
+
+void GenericEventQueue::close()
+{
+    m_isClosed = true;
+
+    m_timer.stop();
+    m_pendingEvents.clear();
+}
+
+void GenericEventQueue::cancelAllEvents()
+{
+    m_timer.stop();
+    m_pendingEvents.clear();
+}
+
+bool GenericEventQueue::hasPendingEvents() const
+{
+    return m_pendingEvents.size();
+}
+
+}
diff --git a/Source/core/dom/GenericEventQueue.h b/Source/core/dom/GenericEventQueue.h
new file mode 100644
index 0000000..5900a72
--- /dev/null
+++ b/Source/core/dom/GenericEventQueue.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 Victor Carbune (victor@rosedu.org)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef GenericEventQueue_h
+#define GenericEventQueue_h
+
+#include "core/dom/EventQueue.h"
+#include "core/dom/EventTarget.h"
+#include "core/platform/Timer.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class GenericEventQueue : public EventQueue {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit GenericEventQueue(EventTarget*);
+    static PassOwnPtr<GenericEventQueue> create(EventTarget*);
+    virtual ~GenericEventQueue();
+
+    // EventQueue
+    virtual bool enqueueEvent(PassRefPtr<Event>) OVERRIDE;
+    virtual bool cancelEvent(Event*) OVERRIDE;
+    virtual void close() OVERRIDE;
+
+    void cancelAllEvents();
+    bool hasPendingEvents() const;
+
+private:
+    void timerFired(Timer<GenericEventQueue>*);
+
+    EventTarget* m_owner;
+    Vector<RefPtr<Event> > m_pendingEvents;
+    Timer<GenericEventQueue> m_timer;
+
+    bool m_isClosed;
+};
+
+}
+
+#endif
diff --git a/Source/core/dom/GestureEvent.cpp b/Source/core/dom/GestureEvent.cpp
new file mode 100644
index 0000000..7a60317
--- /dev/null
+++ b/Source/core/dom/GestureEvent.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/Element.h"
+#include "core/dom/GestureEvent.h"
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+PassRefPtr<GestureEvent> GestureEvent::create()
+{
+    return adoptRef(new GestureEvent);
+}
+
+PassRefPtr<GestureEvent> GestureEvent::create(PassRefPtr<AbstractView> view, const PlatformGestureEvent& event)
+{
+    AtomicString eventType;
+    switch (event.type()) {
+    case PlatformEvent::GestureScrollBegin:
+        eventType = eventNames().gesturescrollstartEvent; break;
+    case PlatformEvent::GestureScrollEnd:
+        eventType = eventNames().gesturescrollendEvent; break;
+    case PlatformEvent::GestureScrollUpdate:
+    case PlatformEvent::GestureScrollUpdateWithoutPropagation:
+        eventType = eventNames().gesturescrollupdateEvent; break;
+    case PlatformEvent::GestureTap:
+        eventType = eventNames().gesturetapEvent; break;
+    case PlatformEvent::GestureTapDown:
+        eventType = eventNames().gesturetapdownEvent; break;
+    case PlatformEvent::GestureTwoFingerTap:
+    case PlatformEvent::GestureLongPress:
+    case PlatformEvent::GesturePinchBegin:
+    case PlatformEvent::GesturePinchEnd:
+    case PlatformEvent::GesturePinchUpdate:
+    case PlatformEvent::GestureTapDownCancel:
+    default:
+        return 0;
+    }
+    return adoptRef(new GestureEvent(eventType, view, event.globalPosition().x(), event.globalPosition().y(), event.position().x(), event.position().y(), event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), event.deltaX(), event.deltaY()));
+}
+
+void GestureEvent::initGestureEvent(const AtomicString& type, PassRefPtr<AbstractView> view, int screenX, int screenY, int clientX, int clientY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, float deltaX, float deltaY)
+{
+    if (dispatched())
+        return;
+
+    initUIEvent(type, true, true, view, 0);
+    m_screenLocation = IntPoint(screenX, screenY);
+    m_ctrlKey = ctrlKey;
+    m_altKey = altKey;
+    m_shiftKey = shiftKey;
+    m_metaKey = metaKey;
+
+    m_deltaX = deltaX;
+    m_deltaY = deltaY;
+
+    initCoordinates(IntPoint(clientX, clientY));
+}
+
+const AtomicString& GestureEvent::interfaceName() const
+{
+    DEFINE_STATIC_LOCAL(AtomicString, name, ("TBDInterface"));
+    return name;
+}
+
+GestureEvent::GestureEvent()
+    : m_deltaX(0)
+    , m_deltaY(0)
+{
+}
+
+GestureEvent::GestureEvent(const AtomicString& type, PassRefPtr<AbstractView> view, int screenX, int screenY, int clientX, int clientY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, float deltaX, float deltaY)
+    : MouseRelatedEvent(type, true, true, view, 0, IntPoint(screenX, screenY), IntPoint(clientX, clientY), IntPoint(0, 0), ctrlKey, altKey, shiftKey, metaKey)
+    , m_deltaX(deltaX)
+    , m_deltaY(deltaY)
+{
+}
+
+GestureEventDispatchMediator::GestureEventDispatchMediator(PassRefPtr<GestureEvent> gestureEvent)
+    : EventDispatchMediator(gestureEvent)
+{
+}
+
+GestureEvent* GestureEventDispatchMediator::event() const
+{
+    return static_cast<GestureEvent*>(EventDispatchMediator::event());
+}
+
+bool GestureEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
+{
+    if (isDisabledFormControl(dispatcher->node()))
+        return true;
+
+    dispatcher->dispatch();
+    ASSERT(!event()->defaultPrevented());
+    return event()->defaultHandled() || event()->defaultPrevented();
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/GestureEvent.h b/Source/core/dom/GestureEvent.h
new file mode 100644
index 0000000..f0809b8
--- /dev/null
+++ b/Source/core/dom/GestureEvent.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GestureEvent_h
+#define GestureEvent_h
+
+#include "core/dom/EventDispatcher.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/MouseRelatedEvent.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/platform/PlatformEvent.h"
+#include "core/platform/PlatformGestureEvent.h"
+
+namespace WebCore {
+
+class GestureEvent : public MouseRelatedEvent {
+public:
+    virtual ~GestureEvent() { }
+
+    static PassRefPtr<GestureEvent> create();
+    static PassRefPtr<GestureEvent> create(PassRefPtr<AbstractView>, const PlatformGestureEvent&);
+
+    void initGestureEvent(const AtomicString& type, PassRefPtr<AbstractView>, int screenX, int screenY, int clientX, int clientY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, float deltaX, float deltaY);
+
+    virtual const AtomicString& interfaceName() const;
+
+    float deltaX() const { return m_deltaX; }
+    float deltaY() const { return m_deltaY; }
+
+private:
+    GestureEvent();
+    GestureEvent(const AtomicString& type, PassRefPtr<AbstractView>, int screenX, int screenY, int clientX, int clientY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, float deltaX, float deltaY);
+
+    float m_deltaX;
+    float m_deltaY;
+};
+
+class GestureEventDispatchMediator : public EventDispatchMediator {
+public:
+    static PassRefPtr<GestureEventDispatchMediator> create(PassRefPtr<GestureEvent> gestureEvent)
+    {
+        return adoptRef(new GestureEventDispatchMediator(gestureEvent));
+    }
+
+private:
+    explicit GestureEventDispatchMediator(PassRefPtr<GestureEvent>);
+
+    GestureEvent* event() const;
+
+    virtual bool dispatchEvent(EventDispatcher*) const OVERRIDE;
+};
+
+} // namespace WebCore
+
+#endif // GestureEvent_h
diff --git a/Source/core/dom/HashChangeEvent.h b/Source/core/dom/HashChangeEvent.h
new file mode 100644
index 0000000..dee8c10
--- /dev/null
+++ b/Source/core/dom/HashChangeEvent.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef HashChangeEvent_h
+#define HashChangeEvent_h
+
+#include "core/dom/Event.h"
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+struct HashChangeEventInit : public EventInit {
+    HashChangeEventInit()
+    {
+    };
+
+    String oldURL;
+    String newURL;
+};
+
+class HashChangeEvent : public Event {
+public:
+    static PassRefPtr<HashChangeEvent> create()
+    {
+        return adoptRef(new HashChangeEvent);
+    }
+
+    static PassRefPtr<HashChangeEvent> create(const String& oldURL, const String& newURL)
+    {
+        return adoptRef(new HashChangeEvent(oldURL, newURL));
+    }
+
+    static PassRefPtr<HashChangeEvent> create(const AtomicString& type, const HashChangeEventInit& initializer)
+    {
+        return adoptRef(new HashChangeEvent(type, initializer));
+    }
+
+    void initHashChangeEvent(const AtomicString& eventType, bool canBubble, bool cancelable, const String& oldURL, const String& newURL)
+    {
+        if (dispatched())
+            return;
+
+        initEvent(eventType, canBubble, cancelable);
+
+        m_oldURL = oldURL;
+        m_newURL = newURL;
+    }
+
+    const String& oldURL() const { return m_oldURL; }
+    const String& newURL() const { return m_newURL; }
+
+    virtual const AtomicString& interfaceName() const { return eventNames().interfaceForHashChangeEvent; }
+
+private:
+    HashChangeEvent()
+    {
+        ScriptWrappable::init(this);
+    }
+
+    HashChangeEvent(const String& oldURL, const String& newURL)
+        : Event(eventNames().hashchangeEvent, false, false)
+        , m_oldURL(oldURL)
+        , m_newURL(newURL)
+    {
+        ScriptWrappable::init(this);
+    }
+
+    HashChangeEvent(const AtomicString& type, const HashChangeEventInit& initializer)
+        : Event(type, initializer)
+        , m_oldURL(initializer.oldURL)
+        , m_newURL(initializer.newURL)
+    {
+        ScriptWrappable::init(this);
+    }
+
+    String m_oldURL;
+    String m_newURL;
+};
+
+} // namespace WebCore
+
+#endif // HashChangeEvent_h
diff --git a/Source/core/dom/HashChangeEvent.idl b/Source/core/dom/HashChangeEvent.idl
new file mode 100644
index 0000000..2408afe
--- /dev/null
+++ b/Source/core/dom/HashChangeEvent.idl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+// Introduced in http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#event-hashchange
+[
+    ConstructorTemplate=Event
+] interface HashChangeEvent : Event {
+    void initHashChangeEvent([Default=Undefined] optional DOMString type, 
+                             [Default=Undefined] optional boolean canBubble, 
+                             [Default=Undefined] optional boolean cancelable, 
+                             [Default=Undefined] optional DOMString oldURL, 
+                             [Default=Undefined] optional DOMString newURL); 
+    [InitializedByEventConstructor] readonly attribute DOMString oldURL;
+    [InitializedByEventConstructor] readonly attribute DOMString newURL;
+};
+
diff --git a/Source/core/dom/IconURL.cpp b/Source/core/dom/IconURL.cpp
new file mode 100644
index 0000000..97575a2
--- /dev/null
+++ b/Source/core/dom/IconURL.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/IconURL.h"
+
+namespace WebCore {
+
+IconURL IconURL::defaultIconURL(const KURL& url, IconType type)
+{
+    IconURL result(url, emptyString(), emptyString(), type);
+    result.m_isDefaultIcon = true;
+    return result;
+}
+
+bool operator==(const IconURL& lhs, const IconURL& rhs)
+{
+    return lhs.m_iconType == rhs.m_iconType
+           && lhs.m_isDefaultIcon == rhs.m_isDefaultIcon
+           && lhs.m_iconURL == rhs.m_iconURL
+           && lhs.m_sizes == rhs.m_sizes
+           && lhs.m_mimeType == rhs.m_mimeType;
+}
+
+}
+
diff --git a/Source/core/dom/IconURL.h b/Source/core/dom/IconURL.h
new file mode 100644
index 0000000..d4109b2
--- /dev/null
+++ b/Source/core/dom/IconURL.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef IconURL_h
+#define IconURL_h
+
+#include "core/platform/KURL.h"
+
+namespace WebCore {
+
+#if ENABLE(TOUCH_ICON_LOADING)
+#define ICON_COUNT 3
+#else
+#define ICON_COUNT 1
+#endif
+
+enum IconType {
+    InvalidIcon = 0,
+    Favicon = 1,
+    TouchIcon = 1 << 1,
+    TouchPrecomposedIcon = 1 << 2,
+};
+
+struct IconURL {
+    IconType m_iconType;
+    String m_sizes;
+    String m_mimeType;
+    KURL m_iconURL;
+    bool m_isDefaultIcon;
+
+    IconURL()
+        : m_iconType(InvalidIcon)
+        , m_isDefaultIcon(false)
+    {
+    }
+
+    IconURL(const KURL& url, const String& sizes, const String& mimeType, IconType type)
+        : m_iconType(type)
+        , m_sizes(sizes)
+        , m_mimeType(mimeType)
+        , m_iconURL(url)
+        , m_isDefaultIcon(false)
+    {
+    }
+    
+    static IconURL defaultIconURL(const KURL&, IconType);
+};
+
+bool operator==(const IconURL&, const IconURL&);
+
+typedef Vector<IconURL, ICON_COUNT> IconURLs;
+
+}
+
+#endif // IconURL_h
diff --git a/Source/core/dom/IdTargetObserver.cpp b/Source/core/dom/IdTargetObserver.cpp
new file mode 100644
index 0000000..6957995
--- /dev/null
+++ b/Source/core/dom/IdTargetObserver.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 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 "core/dom/IdTargetObserver.h"
+
+#include "core/dom/IdTargetObserverRegistry.h"
+
+namespace WebCore {
+
+IdTargetObserver::IdTargetObserver(IdTargetObserverRegistry& registry, const AtomicString& id)
+    : m_registry(&registry)
+    , m_id(id)
+{
+    m_registry->addObserver(m_id, this);
+}
+
+IdTargetObserver::~IdTargetObserver()
+{
+    if (m_registry)
+        m_registry->removeObserver(m_id, this);
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/IdTargetObserver.h b/Source/core/dom/IdTargetObserver.h
new file mode 100644
index 0000000..f9007c4
--- /dev/null
+++ b/Source/core/dom/IdTargetObserver.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 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 IdTargetObserver_h
+#define IdTargetObserver_h
+
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class IdTargetObserverRegistry;
+
+class IdTargetObserver {
+public:
+    virtual ~IdTargetObserver();
+    virtual void idTargetChanged() = 0;
+
+protected:
+    IdTargetObserver(IdTargetObserverRegistry&, const AtomicString& id);
+
+private:
+    IdTargetObserverRegistry* m_registry;
+    AtomicString m_id;
+};
+
+} // namespace WebCore
+
+#endif // IdTargetObserver_h
diff --git a/Source/core/dom/IdTargetObserverRegistry.cpp b/Source/core/dom/IdTargetObserverRegistry.cpp
new file mode 100644
index 0000000..2efc7fd
--- /dev/null
+++ b/Source/core/dom/IdTargetObserverRegistry.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 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 "core/dom/IdTargetObserverRegistry.h"
+
+#include "core/dom/IdTargetObserver.h"
+
+namespace WebCore {
+
+PassOwnPtr<IdTargetObserverRegistry> IdTargetObserverRegistry::create()
+{
+    return adoptPtr(new IdTargetObserverRegistry());
+}
+
+void IdTargetObserverRegistry::addObserver(const AtomicString& id, IdTargetObserver* observer)
+{
+    if (id.isEmpty())
+        return;
+    
+    IdToObserverSetMap::AddResult result = m_registry.add(id.impl(), nullptr);
+    if (result.isNewEntry)
+        result.iterator->value = adoptPtr(new ObserverSet());
+
+    result.iterator->value->add(observer);
+}
+
+void IdTargetObserverRegistry::removeObserver(const AtomicString& id, IdTargetObserver* observer)
+{
+    if (id.isEmpty() || m_registry.isEmpty())
+        return;
+
+    IdToObserverSetMap::iterator iter = m_registry.find(id.impl());
+
+    ObserverSet* set = iter->value.get();
+    set->remove(observer);
+    if (set->isEmpty() && set != m_notifyingObserversInSet)
+        m_registry.remove(iter);
+}
+
+void IdTargetObserverRegistry::notifyObserversInternal(const AtomicString& id)
+{
+    ASSERT(!id.isEmpty());
+    ASSERT(!m_registry.isEmpty());
+
+    m_notifyingObserversInSet = m_registry.get(id.impl());
+    if (!m_notifyingObserversInSet)
+        return;
+
+    Vector<IdTargetObserver*> copy;
+    copyToVector(*m_notifyingObserversInSet, copy);
+    for (Vector<IdTargetObserver*>::const_iterator it = copy.begin(); it != copy.end(); ++it) {
+        if (m_notifyingObserversInSet->contains(*it))
+            (*it)->idTargetChanged();
+    }
+
+    if (m_notifyingObserversInSet->isEmpty())
+        m_registry.remove(id.impl());
+
+    m_notifyingObserversInSet = 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/IdTargetObserverRegistry.h b/Source/core/dom/IdTargetObserverRegistry.h
new file mode 100644
index 0000000..ef5d662
--- /dev/null
+++ b/Source/core/dom/IdTargetObserverRegistry.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2012 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 IdTargetObserverRegistry_h
+#define IdTargetObserverRegistry_h
+
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class IdTargetObserver;
+
+class IdTargetObserverRegistry {
+    WTF_MAKE_FAST_ALLOCATED;
+    friend class IdTargetObserver;
+public:
+    static PassOwnPtr<IdTargetObserverRegistry> create();
+    void notifyObservers(const AtomicString& id);
+
+private:
+    IdTargetObserverRegistry() : m_notifyingObserversInSet(0) { }
+    void addObserver(const AtomicString& id, IdTargetObserver*);
+    void removeObserver(const AtomicString& id, IdTargetObserver*);
+    void notifyObserversInternal(const AtomicString& id);
+
+    typedef HashSet<IdTargetObserver*> ObserverSet;
+    typedef HashMap<AtomicStringImpl*, OwnPtr<ObserverSet> > IdToObserverSetMap;
+    IdToObserverSetMap m_registry;
+    ObserverSet* m_notifyingObserversInSet;
+};
+
+inline void IdTargetObserverRegistry::notifyObservers(const AtomicString& id)
+{
+    ASSERT(!m_notifyingObserversInSet);
+    if (id.isEmpty() || m_registry.isEmpty())
+        return;
+    IdTargetObserverRegistry::notifyObserversInternal(id);
+}
+
+} // namespace WebCore
+
+#endif // IdTargetObserverRegistry_h
diff --git a/Source/core/dom/IgnoreDestructiveWriteCountIncrementer.h b/Source/core/dom/IgnoreDestructiveWriteCountIncrementer.h
new file mode 100644
index 0000000..05218a4
--- /dev/null
+++ b/Source/core/dom/IgnoreDestructiveWriteCountIncrementer.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 GOOGLE 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 GOOGLE 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 IgnoreDestructiveWriteCountIncrementer_h
+#define IgnoreDestructiveWriteCountIncrementer_h
+
+#include "core/dom/Document.h"
+
+namespace WebCore {
+
+class IgnoreDestructiveWriteCountIncrementer {
+    WTF_MAKE_NONCOPYABLE(IgnoreDestructiveWriteCountIncrementer);
+public:
+    explicit IgnoreDestructiveWriteCountIncrementer(Document* document)
+        : m_count(document ? &document->m_ignoreDestructiveWriteCount : 0)
+    {
+        if (!m_count)
+            return;
+        ++(*m_count);
+    }
+
+    ~IgnoreDestructiveWriteCountIncrementer()
+    {
+        if (!m_count)
+            return;
+        --(*m_count);
+    }
+
+private:
+    unsigned* m_count;
+};
+
+}
+
+#endif
diff --git a/Source/core/dom/KeyboardEvent.cpp b/Source/core/dom/KeyboardEvent.cpp
new file mode 100644
index 0000000..33e0a7c
--- /dev/null
+++ b/Source/core/dom/KeyboardEvent.cpp
@@ -0,0 +1,243 @@
+/**
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/KeyboardEvent.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/EventDispatcher.h"
+#include "core/dom/EventNames.h"
+#include "core/page/DOMWindow.h"
+#include "core/page/EventHandler.h"
+#include "core/page/Frame.h"
+#include "core/page/Settings.h"
+#include "core/platform/PlatformKeyboardEvent.h"
+#include "core/platform/WindowsKeyboardCodes.h"
+
+namespace WebCore {
+
+static inline const AtomicString& eventTypeForKeyboardEventType(PlatformEvent::Type type)
+{
+    switch (type) {
+        case PlatformEvent::KeyUp:
+            return eventNames().keyupEvent;
+        case PlatformEvent::RawKeyDown:
+            return eventNames().keydownEvent;
+        case PlatformEvent::Char:
+            return eventNames().keypressEvent;
+        case PlatformEvent::KeyDown:
+            // The caller should disambiguate the combined event into RawKeyDown or Char events.
+            break;
+        default:
+            break;
+    }
+    ASSERT_NOT_REACHED();
+    return eventNames().keydownEvent;
+}
+
+static inline int windowsVirtualKeyCodeWithoutLocation(int keycode)
+{
+    switch (keycode) {
+    case VK_LCONTROL:
+    case VK_RCONTROL:
+        return VK_CONTROL;
+    case VK_LSHIFT:
+    case VK_RSHIFT:
+        return VK_SHIFT;
+    case VK_LMENU:
+    case VK_RMENU:
+        return VK_MENU;
+    default:
+        return keycode;
+    }
+}
+
+static inline KeyboardEvent::KeyLocationCode keyLocationCode(const PlatformKeyboardEvent& key)
+{
+    if (key.isKeypad())
+        return KeyboardEvent::DOMKeyLocationNumpad;
+
+    switch (key.windowsVirtualKeyCode()) {
+    case VK_LCONTROL:
+    case VK_LSHIFT:
+    case VK_LMENU:
+    case VK_LWIN:
+        return KeyboardEvent::DOMKeyLocationLeft;
+    case VK_RCONTROL:
+    case VK_RSHIFT:
+    case VK_RMENU:
+    case VK_RWIN:
+        return KeyboardEvent::DOMKeyLocationRight;
+    default:
+        return KeyboardEvent::DOMKeyLocationStandard;
+    }
+}
+
+KeyboardEventInit::KeyboardEventInit()
+    : keyLocation(0)
+    , ctrlKey(false)
+    , altKey(false)
+    , shiftKey(false)
+    , metaKey(false)
+{
+}
+
+KeyboardEvent::KeyboardEvent()
+    : m_keyLocation(DOMKeyLocationStandard)
+    , m_altGraphKey(false)
+{
+    ScriptWrappable::init(this);
+}
+
+KeyboardEvent::KeyboardEvent(const PlatformKeyboardEvent& key, AbstractView* view)
+    : UIEventWithKeyState(eventTypeForKeyboardEventType(key.type()),
+                          true, true, view, 0, key.ctrlKey(), key.altKey(), key.shiftKey(), key.metaKey())
+    , m_keyEvent(adoptPtr(new PlatformKeyboardEvent(key)))
+    , m_keyIdentifier(key.keyIdentifier())
+    , m_keyLocation(keyLocationCode(key))
+    , m_altGraphKey(false)
+{
+    ScriptWrappable::init(this);
+}
+
+KeyboardEvent::KeyboardEvent(const AtomicString& eventType, const KeyboardEventInit& initializer)
+    : UIEventWithKeyState(eventType, initializer.bubbles, initializer.cancelable, initializer.view, initializer.detail, initializer.ctrlKey, initializer.altKey, initializer.shiftKey, initializer.metaKey)
+    , m_keyIdentifier(initializer.keyIdentifier)
+    , m_keyLocation(initializer.keyLocation)
+    , m_altGraphKey(false)
+{
+    ScriptWrappable::init(this);
+}
+
+KeyboardEvent::KeyboardEvent(const AtomicString& eventType, bool canBubble, bool cancelable, AbstractView *view,
+                             const String &keyIdentifier,  unsigned keyLocation,
+                             bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool altGraphKey)
+    : UIEventWithKeyState(eventType, canBubble, cancelable, view, 0, ctrlKey, altKey, shiftKey, metaKey)
+    , m_keyIdentifier(keyIdentifier)
+    , m_keyLocation(keyLocation)
+    , m_altGraphKey(altGraphKey)
+{
+    ScriptWrappable::init(this);
+}
+
+KeyboardEvent::~KeyboardEvent()
+{
+}
+
+void KeyboardEvent::initKeyboardEvent(const AtomicString& type, bool canBubble, bool cancelable, AbstractView* view,
+                                      const String &keyIdentifier, unsigned keyLocation,
+                                      bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool altGraphKey)
+{
+    if (dispatched())
+        return;
+
+    initUIEvent(type, canBubble, cancelable, view, 0);
+
+    m_keyIdentifier = keyIdentifier;
+    m_keyLocation = keyLocation;
+    m_ctrlKey = ctrlKey;
+    m_shiftKey = shiftKey;
+    m_altKey = altKey;
+    m_metaKey = metaKey;
+    m_altGraphKey = altGraphKey;
+}
+
+bool KeyboardEvent::getModifierState(const String& keyIdentifier) const
+{
+    if (keyIdentifier == "Control")
+        return ctrlKey();
+    if (keyIdentifier == "Shift")
+        return shiftKey();
+    if (keyIdentifier == "Alt")
+        return altKey();
+    if (keyIdentifier == "Meta")
+        return metaKey();
+    return false;
+}
+
+int KeyboardEvent::keyCode() const
+{
+    // IE: virtual key code for keyup/keydown, character code for keypress
+    // Firefox: virtual key code for keyup/keydown, zero for keypress
+    // We match IE.
+    if (!m_keyEvent)
+        return 0;
+    if (type() == eventNames().keydownEvent || type() == eventNames().keyupEvent)
+        return windowsVirtualKeyCodeWithoutLocation(m_keyEvent->windowsVirtualKeyCode());
+
+    return charCode();
+}
+
+int KeyboardEvent::charCode() const
+{
+    // IE: not supported
+    // Firefox: 0 for keydown/keyup events, character code for keypress
+    // We match Firefox
+
+    if (!m_keyEvent || (type() != eventNames().keypressEvent))
+        return 0;
+    String text = m_keyEvent->text();
+    return static_cast<int>(text.characterStartingAt(0));
+}
+
+const AtomicString& KeyboardEvent::interfaceName() const
+{
+    return eventNames().interfaceForKeyboardEvent;
+}
+
+bool KeyboardEvent::isKeyboardEvent() const
+{
+    return true;
+}
+
+int KeyboardEvent::which() const
+{
+    // Netscape's "which" returns a virtual key code for keydown and keyup, and a character code for keypress.
+    // That's exactly what IE's "keyCode" returns. So they are the same for keyboard events.
+    return keyCode();
+}
+
+KeyboardEvent* findKeyboardEvent(Event* event)
+{
+    for (Event* e = event; e; e = e->underlyingEvent())
+        if (e->isKeyboardEvent())
+            return static_cast<KeyboardEvent*>(e);
+    return 0;
+}
+
+PassRefPtr<KeyboardEventDispatchMediator> KeyboardEventDispatchMediator::create(PassRefPtr<KeyboardEvent> event)
+{
+    return adoptRef(new KeyboardEventDispatchMediator(event));
+}
+
+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 EventDispatchMediator::dispatchEvent(dispatcher) && !event()->defaultHandled();
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/KeyboardEvent.h b/Source/core/dom/KeyboardEvent.h
new file mode 100644
index 0000000..1900174
--- /dev/null
+++ b/Source/core/dom/KeyboardEvent.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef KeyboardEvent_h
+#define KeyboardEvent_h
+
+#include "core/dom/EventDispatchMediator.h"
+#include "core/dom/UIEventWithKeyState.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class EventDispatcher;
+class Node;
+class PlatformKeyboardEvent;
+
+struct KeyboardEventInit : public UIEventInit {
+    KeyboardEventInit();
+
+    String keyIdentifier;
+    unsigned keyLocation;
+    bool ctrlKey;
+    bool altKey;
+    bool shiftKey;
+    bool metaKey;
+};
+
+class KeyboardEvent : public UIEventWithKeyState {
+public:
+    enum KeyLocationCode {
+        DOMKeyLocationStandard      = 0x00,
+        DOMKeyLocationLeft          = 0x01,
+        DOMKeyLocationRight         = 0x02,
+        DOMKeyLocationNumpad        = 0x03
+    };
+        
+    static PassRefPtr<KeyboardEvent> create()
+    {
+        return adoptRef(new KeyboardEvent);
+    }
+
+    static PassRefPtr<KeyboardEvent> create(const PlatformKeyboardEvent& platformEvent, AbstractView* view)
+    {
+        return adoptRef(new KeyboardEvent(platformEvent, view));
+    }
+
+    static PassRefPtr<KeyboardEvent> create(const AtomicString& type, const KeyboardEventInit& initializer)
+    {
+        return adoptRef(new KeyboardEvent(type, initializer));
+    }
+
+    static PassRefPtr<KeyboardEvent> create(const AtomicString& type, bool canBubble, bool cancelable, AbstractView* view,
+        const String& keyIdentifier, unsigned keyLocation,
+        bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool altGraphKey)
+    {
+        return adoptRef(new KeyboardEvent(type, canBubble, cancelable, view, keyIdentifier, keyLocation,
+        ctrlKey, altKey, shiftKey, metaKey, altGraphKey));
+    }
+
+    virtual ~KeyboardEvent();
+    
+    void initKeyboardEvent(const AtomicString& type, bool canBubble, bool cancelable, AbstractView*,
+        const String& keyIdentifier, unsigned keyLocation,
+        bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool altGraphKey = false);
+    
+    const String& keyIdentifier() const { return m_keyIdentifier; }
+    unsigned keyLocation() const { return m_keyLocation; }
+
+    bool getModifierState(const String& keyIdentifier) const;
+
+    bool altGraphKey() const { return m_altGraphKey; }
+    
+    const PlatformKeyboardEvent* keyEvent() const { return m_keyEvent.get(); }
+
+    int keyCode() const; // key code for keydown and keyup, character for keypress
+    int charCode() const; // character code for keypress, 0 for keydown and keyup
+
+    virtual const AtomicString& interfaceName() const;
+    virtual bool isKeyboardEvent() const;
+    virtual int which() const;
+
+private:
+    KeyboardEvent();
+    KeyboardEvent(const PlatformKeyboardEvent&, AbstractView*);
+    KeyboardEvent(const AtomicString&, const KeyboardEventInit&);
+    KeyboardEvent(const AtomicString& type, bool canBubble, bool cancelable, AbstractView*,
+        const String& keyIdentifier, unsigned keyLocation,
+        bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool altGraphKey);
+
+    OwnPtr<PlatformKeyboardEvent> m_keyEvent;
+    String m_keyIdentifier;
+    unsigned m_keyLocation;
+    bool m_altGraphKey : 1;
+};
+
+KeyboardEvent* findKeyboardEvent(Event*);
+
+class KeyboardEventDispatchMediator : public EventDispatchMediator {
+public:
+    static PassRefPtr<KeyboardEventDispatchMediator> create(PassRefPtr<KeyboardEvent>);
+private:
+    explicit KeyboardEventDispatchMediator(PassRefPtr<KeyboardEvent>);
+    virtual bool dispatchEvent(EventDispatcher*) const OVERRIDE;
+};
+
+} // namespace WebCore
+
+#endif // KeyboardEvent_h
diff --git a/Source/core/dom/KeyboardEvent.idl b/Source/core/dom/KeyboardEvent.idl
new file mode 100644
index 0000000..6eefd3a
--- /dev/null
+++ b/Source/core/dom/KeyboardEvent.idl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+[
+    ConstructorTemplate=Event
+] interface KeyboardEvent : UIEvent {
+
+    [InitializedByEventConstructor] readonly attribute DOMString        keyIdentifier;
+    [InitializedByEventConstructor] readonly attribute unsigned long    keyLocation;
+    [InitializedByEventConstructor] readonly attribute boolean          ctrlKey;
+    [InitializedByEventConstructor] readonly attribute boolean          shiftKey;
+    [InitializedByEventConstructor] readonly attribute boolean          altKey;
+    [InitializedByEventConstructor] readonly attribute boolean          metaKey;
+    readonly attribute boolean          altGraphKey;
+
+    // FIXME: this does not match the version in the DOM spec.
+    void initKeyboardEvent([Default=Undefined] optional DOMString type, 
+                           [Default=Undefined] optional boolean canBubble, 
+                           [Default=Undefined] optional boolean cancelable, 
+                           [Default=Undefined] optional DOMWindow view, 
+                           [Default=Undefined] optional DOMString keyIdentifier,
+                           [Default=Undefined] optional unsigned long keyLocation,
+                           [Default=Undefined] optional boolean ctrlKey,
+                           [Default=Undefined] optional boolean altKey,
+                           [Default=Undefined] optional boolean shiftKey,
+                           [Default=Undefined] optional boolean metaKey,
+                           [Default=Undefined] optional boolean altGraphKey);
+};
+
diff --git a/Source/core/dom/LiveNodeList.cpp b/Source/core/dom/LiveNodeList.cpp
new file mode 100644
index 0000000..8344556
--- /dev/null
+++ b/Source/core/dom/LiveNodeList.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/LiveNodeList.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/html/HTMLCollection.h"
+
+namespace WebCore {
+
+Node* LiveNodeListBase::rootNode() const
+{
+    if (isRootedAtDocument() && m_ownerNode->inDocument())
+        return m_ownerNode->document();
+    return m_ownerNode.get();
+}
+
+ContainerNode* LiveNodeListBase::rootContainerNode() const
+{
+    Node* rootNode = this->rootNode();
+    if (!rootNode->isContainerNode())
+        return 0;
+    return toContainerNode(rootNode);
+}
+
+void LiveNodeListBase::invalidateCache() const
+{
+    m_cachedItem = 0;
+    m_isLengthCacheValid = false;
+    m_isItemCacheValid = false;
+    m_isNameCacheValid = false;
+    m_isItemRefElementsCacheValid = false;
+    if (isNodeList(type()))
+        return;
+
+    const HTMLCollection* cacheBase = static_cast<const HTMLCollection*>(this);
+    cacheBase->m_idCache.clear();
+    cacheBase->m_nameCache.clear();
+    cacheBase->m_cachedElementsArrayOffset = 0;
+}
+
+void LiveNodeListBase::invalidateIdNameCacheMaps() const
+{
+    ASSERT(hasIdNameCache());
+    const HTMLCollection* cacheBase = static_cast<const HTMLCollection*>(this);
+    cacheBase->m_idCache.clear();
+    cacheBase->m_nameCache.clear();
+}
+
+void LiveNodeListBase::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    NodeList::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_ownerNode, "ownerNode");
+    info.addWeakPointer(m_cachedItem);
+}
+
+Node* LiveNodeList::namedItem(const AtomicString& elementId) const
+{
+    Node* rootNode = this->rootNode();
+
+    if (rootNode->inDocument()) {
+        Element* element = rootNode->treeScope()->getElementById(elementId);
+        if (element && nodeMatches(element) && element->isDescendantOf(rootNode))
+            return element;
+        if (!element)
+            return 0;
+        // In the case of multiple nodes with the same name, just fall through.
+    }
+
+    unsigned length = this->length();
+    for (unsigned i = 0; i < length; i++) {
+        Node* node = item(i);
+        // FIXME: This should probably be using getIdAttribute instead of idForStyleResolution.
+        if (node->hasID() && toElement(node)->idForStyleResolution() == elementId)
+            return node;
+    }
+
+    return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/LiveNodeList.h b/Source/core/dom/LiveNodeList.h
new file mode 100644
index 0000000..7ed7300
--- /dev/null
+++ b/Source/core/dom/LiveNodeList.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef LiveNodeList_h
+#define LiveNodeList_h
+
+#include "HTMLNames.h"
+#include "core/dom/Document.h"
+#include "core/dom/NodeList.h"
+#include "core/html/CollectionType.h"
+#include <wtf/Forward.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Element;
+
+enum NodeListRootType {
+    NodeListIsRootedAtNode,
+    NodeListIsRootedAtDocument,
+    NodeListIsRootedAtDocumentIfOwnerHasItemrefAttr,
+};
+
+class LiveNodeListBase : public NodeList {
+public:
+    enum ItemAfterOverrideType {
+        OverridesItemAfter,
+        DoesNotOverrideItemAfter,
+    };
+
+    LiveNodeListBase(Node* ownerNode, NodeListRootType rootType, NodeListInvalidationType invalidationType,
+        bool shouldOnlyIncludeDirectChildren, CollectionType collectionType, ItemAfterOverrideType itemAfterOverrideType)
+        : m_ownerNode(ownerNode)
+        , m_cachedItem(0)
+        , m_isLengthCacheValid(false)
+        , m_isItemCacheValid(false)
+        , m_rootType(rootType)
+        , m_invalidationType(invalidationType)
+        , m_shouldOnlyIncludeDirectChildren(shouldOnlyIncludeDirectChildren)
+        , m_isNameCacheValid(false)
+        , m_collectionType(collectionType)
+        , m_overridesItemAfter(itemAfterOverrideType == OverridesItemAfter)
+        , m_isItemRefElementsCacheValid(false)
+    {
+        ASSERT(m_rootType == static_cast<unsigned>(rootType));
+        ASSERT(m_invalidationType == static_cast<unsigned>(invalidationType));
+        ASSERT(m_collectionType == static_cast<unsigned>(collectionType));
+        ASSERT(!m_overridesItemAfter || !isNodeList(collectionType));
+
+        if (collectionType != ChildNodeListType)
+            document()->registerNodeList(this);
+    }
+
+    virtual ~LiveNodeListBase()
+    {
+        if (type() != ChildNodeListType)
+            document()->unregisterNodeList(this);
+    }
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+
+    // DOM API
+    virtual unsigned length() const OVERRIDE;
+    virtual Node* item(unsigned offset) const OVERRIDE;
+
+    ALWAYS_INLINE bool hasIdNameCache() const { return !isNodeList(type()); }
+    ALWAYS_INLINE bool isRootedAtDocument() const { return m_rootType == NodeListIsRootedAtDocument || m_rootType == NodeListIsRootedAtDocumentIfOwnerHasItemrefAttr; }
+    ALWAYS_INLINE NodeListInvalidationType invalidationType() const { return static_cast<NodeListInvalidationType>(m_invalidationType); }
+    ALWAYS_INLINE CollectionType type() const { return static_cast<CollectionType>(m_collectionType); }
+    Node* ownerNode() const { return m_ownerNode.get(); }
+    ALWAYS_INLINE void invalidateCache(const QualifiedName* attrName) const
+    {
+        if (!attrName || shouldInvalidateTypeOnAttributeChange(invalidationType(), *attrName))
+            invalidateCache();
+        else if (hasIdNameCache() && (*attrName == HTMLNames::idAttr || *attrName == HTMLNames::nameAttr))
+            invalidateIdNameCacheMaps();
+    }
+    void invalidateCache() const;
+    void invalidateIdNameCacheMaps() const;
+
+    static bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType, const QualifiedName&);
+
+protected:
+    Document* document() const { return m_ownerNode->document(); }
+    Node* rootNode() const;
+    ContainerNode* rootContainerNode() const;
+    bool overridesItemAfter() const { return m_overridesItemAfter; }
+
+    ALWAYS_INLINE bool isItemCacheValid() const { return m_isItemCacheValid; }
+    ALWAYS_INLINE Node* cachedItem() const { return m_cachedItem; }
+    ALWAYS_INLINE unsigned cachedItemOffset() const { return m_cachedItemOffset; }
+
+    ALWAYS_INLINE bool isLengthCacheValid() const { return m_isLengthCacheValid; }
+    ALWAYS_INLINE unsigned cachedLength() const { return m_cachedLength; }
+    ALWAYS_INLINE void setLengthCache(unsigned length) const
+    {
+        m_cachedLength = length;
+        m_isLengthCacheValid = true;
+    }
+    ALWAYS_INLINE void setItemCache(Node* item, unsigned offset) const
+    {
+        ASSERT(item);
+        m_cachedItem = item;
+        m_cachedItemOffset = offset;
+        m_isItemCacheValid = true;
+    }
+    void setItemCache(Node* item, unsigned offset, unsigned elementsArrayOffset) const;
+
+    ALWAYS_INLINE bool isItemRefElementsCacheValid() const { return m_isItemRefElementsCacheValid; }
+    ALWAYS_INLINE void setItemRefElementsCacheValid() const { m_isItemRefElementsCacheValid = true; }
+
+    ALWAYS_INLINE NodeListRootType rootType() const { return static_cast<NodeListRootType>(m_rootType); }
+
+    bool hasNameCache() const { return m_isNameCacheValid; }
+    void setHasNameCache() const { m_isNameCacheValid = true; }
+
+    bool shouldOnlyIncludeDirectChildren() const { return m_shouldOnlyIncludeDirectChildren; }
+
+private:
+    Node* itemBeforeOrAfterCachedItem(unsigned offset, ContainerNode* root) const;
+    Node* traverseChildNodeListForwardToOffset(unsigned offset, Node* currentNode, unsigned& currentOffset) const;
+    Element* traverseLiveNodeListFirstElement(ContainerNode* root) const;
+    Element* traverseLiveNodeListForwardToOffset(unsigned offset, Element* currentElement, unsigned& currentOffset, ContainerNode* root) const;
+    bool isLastItemCloserThanLastOrCachedItem(unsigned offset) const;
+    bool isFirstItemCloserThanCachedItem(unsigned offset) const;
+    Node* iterateForPreviousNode(Node* current) const;
+    Node* itemBefore(Node* previousItem) const;
+
+    RefPtr<Node> m_ownerNode;
+    mutable Node* m_cachedItem;
+    mutable unsigned m_cachedLength;
+    mutable unsigned m_cachedItemOffset;
+    mutable unsigned m_isLengthCacheValid : 1;
+    mutable unsigned m_isItemCacheValid : 1;
+    const unsigned m_rootType : 2;
+    const unsigned m_invalidationType : 4;
+    const unsigned m_shouldOnlyIncludeDirectChildren : 1;
+
+    // From HTMLCollection
+    mutable unsigned m_isNameCacheValid : 1;
+    const unsigned m_collectionType : 5;
+    const unsigned m_overridesItemAfter : 1;
+    mutable unsigned m_isItemRefElementsCacheValid : 1;
+};
+
+ALWAYS_INLINE bool LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType type, const QualifiedName& attrName)
+{
+    switch (type) {
+    case InvalidateOnClassAttrChange:
+        return attrName == HTMLNames::classAttr;
+    case InvalidateOnNameAttrChange:
+        return attrName == HTMLNames::nameAttr;
+    case InvalidateOnIdNameAttrChange:
+        return attrName == HTMLNames::idAttr || attrName == HTMLNames::nameAttr;
+    case InvalidateOnForAttrChange:
+        return attrName == HTMLNames::forAttr;
+    case InvalidateForFormControls:
+        return attrName == HTMLNames::nameAttr || attrName == HTMLNames::idAttr || attrName == HTMLNames::forAttr
+            || attrName == HTMLNames::formAttr || attrName == HTMLNames::typeAttr;
+    case InvalidateOnHRefAttrChange:
+        return attrName == HTMLNames::hrefAttr;
+    case InvalidateOnItemAttrChange:
+    case DoNotInvalidateOnAttributeChanges:
+        return false;
+    case InvalidateOnAnyAttrChange:
+        return true;
+    }
+    return false;
+}
+
+class LiveNodeList : public LiveNodeListBase {
+public:
+    LiveNodeList(PassRefPtr<Node> ownerNode, CollectionType collectionType, NodeListInvalidationType invalidationType, NodeListRootType rootType = NodeListIsRootedAtNode)
+        : LiveNodeListBase(ownerNode.get(), rootType, invalidationType, collectionType == ChildNodeListType,
+        collectionType, DoesNotOverrideItemAfter)
+    { }
+
+    virtual Node* namedItem(const AtomicString&) const OVERRIDE;
+    virtual bool nodeMatches(Element*) const = 0;
+
+private:
+    virtual bool isLiveNodeList() const OVERRIDE { return true; }
+};
+
+} // namespace WebCore
+
+#endif // LiveNodeList_h
diff --git a/Source/core/dom/MessageChannel.cpp b/Source/core/dom/MessageChannel.cpp
new file mode 100644
index 0000000..a27ac9e
--- /dev/null
+++ b/Source/core/dom/MessageChannel.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "core/dom/MessageChannel.h"
+
+#include "core/dom/MessagePort.h"
+#include "core/dom/MessagePortChannel.h"
+
+namespace WebCore {
+
+MessageChannel::MessageChannel(ScriptExecutionContext* context)
+    : m_port1(MessagePort::create(*context))
+    , m_port2(MessagePort::create(*context))
+{
+    MessagePortChannel::createChannel(m_port1.get(), m_port2.get());
+}
+
+MessageChannel::~MessageChannel()
+{
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/MessageChannel.h b/Source/core/dom/MessageChannel.h
new file mode 100644
index 0000000..3d6579b
--- /dev/null
+++ b/Source/core/dom/MessageChannel.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef MessageChannel_h
+#define MessageChannel_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+    class MessagePort;
+    class ScriptExecutionContext;
+
+    class MessageChannel : public RefCounted<MessageChannel> {
+    public:
+        static PassRefPtr<MessageChannel> create(ScriptExecutionContext* context) { return adoptRef(new MessageChannel(context)); }
+        ~MessageChannel();
+
+        MessagePort* port1() const { return m_port1.get(); }
+        MessagePort* port2() const { return m_port2.get(); }
+
+    private:
+        explicit MessageChannel(ScriptExecutionContext*);
+
+        RefPtr<MessagePort> m_port1;
+        RefPtr<MessagePort> m_port2;
+    };
+
+} // namespace WebCore
+
+#endif // MessageChannel_h
diff --git a/Source/core/dom/MessageChannel.idl b/Source/core/dom/MessageChannel.idl
new file mode 100644
index 0000000..c81bd4c
--- /dev/null
+++ b/Source/core/dom/MessageChannel.idl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008, 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+[
+    Constructor,
+    CallWith=ScriptExecutionContext,
+    CustomConstructor,
+    ImplementationLacksVTable
+] interface MessageChannel {
+
+    readonly attribute MessagePort port1;
+    readonly attribute MessagePort port2;
+
+};
+
diff --git a/Source/core/dom/MessageEvent.cpp b/Source/core/dom/MessageEvent.cpp
new file mode 100644
index 0000000..0e269d7
--- /dev/null
+++ b/Source/core/dom/MessageEvent.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2007 Henry Mason (hmason@mac.com)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "core/dom/MessageEvent.h"
+
+#include "core/dom/EventNames.h"
+#include "core/page/DOMWindow.h"
+
+namespace WebCore {
+
+MessageEventInit::MessageEventInit()
+{
+}
+
+MessageEvent::MessageEvent()
+    : m_dataType(DataTypeScriptValue)
+{
+    ScriptWrappable::init(this);
+}
+
+MessageEvent::MessageEvent(const AtomicString& type, const MessageEventInit& initializer)
+    : Event(type, initializer)
+    , m_dataType(DataTypeScriptValue)
+    , m_dataAsScriptValue(initializer.data)
+    , m_origin(initializer.origin)
+    , m_lastEventId(initializer.lastEventId)
+    , m_source(initializer.source)
+    , m_ports(adoptPtr(new MessagePortArray(initializer.ports)))
+{
+    ScriptWrappable::init(this);
+}
+
+MessageEvent::MessageEvent(const ScriptValue& data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortArray> ports)
+    : Event(eventNames().messageEvent, false, false)
+    , m_dataType(DataTypeScriptValue)
+    , m_dataAsScriptValue(data)
+    , m_origin(origin)
+    , m_lastEventId(lastEventId)
+    , m_source(source)
+    , m_ports(ports)
+{
+    ScriptWrappable::init(this);
+}
+
+MessageEvent::MessageEvent(PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortArray> ports)
+    : Event(eventNames().messageEvent, false, false)
+    , m_dataType(DataTypeSerializedScriptValue)
+    , m_dataAsSerializedScriptValue(data)
+    , m_origin(origin)
+    , m_lastEventId(lastEventId)
+    , m_source(source)
+    , m_ports(ports)
+{
+    ScriptWrappable::init(this);
+    if (m_dataAsSerializedScriptValue)
+        m_dataAsSerializedScriptValue->registerMemoryAllocatedWithCurrentScriptContext();
+}
+
+MessageEvent::MessageEvent(const String& data, const String& origin)
+    : Event(eventNames().messageEvent, false, false)
+    , m_dataType(DataTypeString)
+    , m_dataAsString(data)
+    , m_origin(origin)
+    , m_lastEventId("")
+{
+    ScriptWrappable::init(this);
+}
+
+MessageEvent::MessageEvent(PassRefPtr<Blob> data, const String& origin)
+    : Event(eventNames().messageEvent, false, false)
+    , m_dataType(DataTypeBlob)
+    , m_dataAsBlob(data)
+    , m_origin(origin)
+    , m_lastEventId("")
+{
+    ScriptWrappable::init(this);
+}
+
+MessageEvent::MessageEvent(PassRefPtr<ArrayBuffer> data, const String& origin)
+    : Event(eventNames().messageEvent, false, false)
+    , m_dataType(DataTypeArrayBuffer)
+    , m_dataAsArrayBuffer(data)
+    , m_origin(origin)
+    , m_lastEventId("")
+{
+    ScriptWrappable::init(this);
+}
+
+MessageEvent::~MessageEvent()
+{
+}
+
+void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, const ScriptValue& data, const String& origin, const String& lastEventId, DOMWindow* source, PassOwnPtr<MessagePortArray> ports)
+{
+    if (dispatched())
+        return;
+
+    initEvent(type, canBubble, cancelable);
+
+    m_dataType = DataTypeScriptValue;
+    m_dataAsScriptValue = data;
+    m_origin = origin;
+    m_lastEventId = lastEventId;
+    m_source = source;
+    m_ports = ports;
+}
+
+void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, PassOwnPtr<MessagePortArray> ports)
+{
+    if (dispatched())
+        return;
+
+    initEvent(type, canBubble, cancelable);
+
+    m_dataType = DataTypeSerializedScriptValue;
+    m_dataAsSerializedScriptValue = data;
+    m_origin = origin;
+    m_lastEventId = lastEventId;
+    m_source = source;
+    m_ports = ports;
+
+    if (m_dataAsSerializedScriptValue)
+        m_dataAsSerializedScriptValue->registerMemoryAllocatedWithCurrentScriptContext();
+}
+
+const AtomicString& MessageEvent::interfaceName() const
+{
+    return eventNames().interfaceForMessageEvent;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/MessageEvent.h b/Source/core/dom/MessageEvent.h
new file mode 100644
index 0000000..297a788
--- /dev/null
+++ b/Source/core/dom/MessageEvent.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2007 Henry Mason (hmason@mac.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef MessageEvent_h
+#define MessageEvent_h
+
+#include "bindings/v8/ScriptValue.h"
+#include "bindings/v8/SerializedScriptValue.h"
+#include "core/dom/Event.h"
+#include "core/dom/MessagePort.h"
+#include "core/fileapi/Blob.h"
+#include "core/page/DOMWindow.h"
+#include <wtf/ArrayBuffer.h>
+
+namespace WebCore {
+
+class DOMWindow;
+
+struct MessageEventInit : public EventInit {
+    MessageEventInit();
+
+    ScriptValue data;
+    String origin;
+    String lastEventId;
+    RefPtr<DOMWindow> source;
+    MessagePortArray ports;
+};
+
+class MessageEvent : public Event {
+public:
+    static PassRefPtr<MessageEvent> create()
+    {
+        return adoptRef(new MessageEvent);
+    }
+    static PassRefPtr<MessageEvent> create(PassOwnPtr<MessagePortArray> ports, const ScriptValue& data = ScriptValue(), const String& origin = "", const String& lastEventId = "", PassRefPtr<DOMWindow> source = 0)
+    {
+        return adoptRef(new MessageEvent(data, origin, lastEventId, source, ports));
+    }
+    static PassRefPtr<MessageEvent> create(PassOwnPtr<MessagePortArray> ports, PassRefPtr<SerializedScriptValue> data, const String& origin = "", const String& lastEventId = "", PassRefPtr<DOMWindow> source = 0)
+    {
+        return adoptRef(new MessageEvent(data, origin, lastEventId, source, ports));
+    }
+    static PassRefPtr<MessageEvent> create(const String& data, const String& origin = "")
+    {
+        return adoptRef(new MessageEvent(data, origin));
+    }
+    static PassRefPtr<MessageEvent> create(PassRefPtr<Blob> data, const String& origin = "")
+    {
+        return adoptRef(new MessageEvent(data, origin));
+    }
+    static PassRefPtr<MessageEvent> create(PassRefPtr<ArrayBuffer> data, const String& origin = "")
+    {
+        return adoptRef(new MessageEvent(data, origin));
+    }
+    static PassRefPtr<MessageEvent> create(const AtomicString& type, const MessageEventInit& initializer)
+    {
+        return adoptRef(new MessageEvent(type, initializer));
+    }
+    virtual ~MessageEvent();
+
+    void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, const ScriptValue& data, const String& origin, const String& lastEventId, DOMWindow* source, PassOwnPtr<MessagePortArray>);
+    void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, PassOwnPtr<MessagePortArray>);
+
+    const String& origin() const { return m_origin; }
+    const String& lastEventId() const { return m_lastEventId; }
+    DOMWindow* source() const { return m_source.get(); }
+    MessagePortArray* ports() const { return m_ports.get(); }
+
+    virtual const AtomicString& interfaceName() const;
+
+    enum DataType {
+        DataTypeScriptValue,
+        DataTypeSerializedScriptValue,
+        DataTypeString,
+        DataTypeBlob,
+        DataTypeArrayBuffer
+    };
+    DataType dataType() const { return m_dataType; }
+    const ScriptValue& dataAsScriptValue() const { ASSERT(m_dataType == DataTypeScriptValue); return m_dataAsScriptValue; }
+    PassRefPtr<SerializedScriptValue> dataAsSerializedScriptValue() const { ASSERT(m_dataType == DataTypeSerializedScriptValue); return m_dataAsSerializedScriptValue; }
+    String dataAsString() const { ASSERT(m_dataType == DataTypeString); return m_dataAsString; }
+    Blob* dataAsBlob() const { ASSERT(m_dataType == DataTypeBlob); return m_dataAsBlob.get(); }
+    ArrayBuffer* dataAsArrayBuffer() const { ASSERT(m_dataType == DataTypeArrayBuffer); return m_dataAsArrayBuffer.get(); }
+
+private:
+    MessageEvent();
+    MessageEvent(const AtomicString&, const MessageEventInit&);
+    MessageEvent(const ScriptValue& data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortArray>);
+    MessageEvent(PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortArray>);
+
+    explicit MessageEvent(const String& data, const String& origin);
+    explicit MessageEvent(PassRefPtr<Blob> data, const String& origin);
+    explicit MessageEvent(PassRefPtr<ArrayBuffer> data, const String& origin);
+
+    DataType m_dataType;
+    ScriptValue m_dataAsScriptValue;
+    RefPtr<SerializedScriptValue> m_dataAsSerializedScriptValue;
+    String m_dataAsString;
+    RefPtr<Blob> m_dataAsBlob;
+    RefPtr<ArrayBuffer> m_dataAsArrayBuffer;
+    String m_origin;
+    String m_lastEventId;
+    RefPtr<DOMWindow> m_source;
+    OwnPtr<MessagePortArray> m_ports;
+};
+
+} // namespace WebCore
+
+#endif // MessageEvent_h
diff --git a/Source/core/dom/MessageEvent.idl b/Source/core/dom/MessageEvent.idl
new file mode 100644
index 0000000..928f2d7
--- /dev/null
+++ b/Source/core/dom/MessageEvent.idl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 Henry Mason <hmason@mac.com>
+ * 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 COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+[
+    ConstructorTemplate=Event
+] interface MessageEvent : Event {
+    [InitializedByEventConstructor] readonly attribute DOMString origin;
+    [InitializedByEventConstructor] readonly attribute DOMString lastEventId;
+    [InitializedByEventConstructor] readonly attribute DOMWindow source;
+    [InitializedByEventConstructor, CachedAttribute, CustomGetter] readonly attribute any data;
+    [InitializedByEventConstructor, CustomGetter] readonly attribute Array ports;
+
+    [Custom] void initMessageEvent([Default=Undefined] optional DOMString typeArg, 
+                                   [Default=Undefined] optional boolean canBubbleArg, 
+                                   [Default=Undefined] optional boolean cancelableArg, 
+                                   [Default=Undefined] optional any dataArg, 
+                                   [Default=Undefined] optional DOMString originArg, 
+                                   [Default=Undefined] optional DOMString lastEventIdArg, 
+                                   [Default=Undefined] optional DOMWindow sourceArg, 
+                                   [Default=Undefined] optional Array messagePorts);
+
+    [Custom] void webkitInitMessageEvent([Default=Undefined] optional DOMString typeArg,
+                                         [Default=Undefined] optional boolean canBubbleArg,
+                                         [Default=Undefined] optional boolean cancelableArg,
+                                         [Default=Undefined] optional any dataArg,
+                                         [Default=Undefined] optional DOMString originArg,
+                                         [Default=Undefined] optional DOMString lastEventIdArg,
+                                         [Default=Undefined] optional DOMWindow sourceArg,
+                                         [Default=Undefined] optional Array transferables);
+};
+
diff --git a/Source/core/dom/MessagePort.cpp b/Source/core/dom/MessagePort.cpp
new file mode 100644
index 0000000..c18b0cc
--- /dev/null
+++ b/Source/core/dom/MessagePort.cpp
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/MessagePort.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/EventException.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/MessageEvent.h"
+#include "core/page/DOMWindow.h"
+#include "core/page/SecurityOrigin.h"
+#include "core/platform/Timer.h"
+#include "core/workers/WorkerContext.h"
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext)
+    : m_started(false)
+    , m_closed(false)
+    , m_scriptExecutionContext(&scriptExecutionContext)
+{
+    m_scriptExecutionContext->createdMessagePort(this);
+
+    // Don't need to call processMessagePortMessagesSoon() here, because the port will not be opened until start() is invoked.
+}
+
+MessagePort::~MessagePort()
+{
+    close();
+    if (m_scriptExecutionContext)
+        m_scriptExecutionContext->destroyedMessagePort(this);
+}
+
+void MessagePort::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionCode& ec)
+{
+    if (!isEntangled())
+        return;
+    ASSERT(m_scriptExecutionContext);
+
+    OwnPtr<MessagePortChannelArray> channels;
+    // Make sure we aren't connected to any of the passed-in ports.
+    if (ports) {
+        for (unsigned int i = 0; i < ports->size(); ++i) {
+            MessagePort* dataPort = (*ports)[i].get();
+            if (dataPort == this || m_entangledChannel->isConnectedTo(dataPort)) {
+                ec = INVALID_STATE_ERR;
+                return;
+            }
+        }
+        channels = MessagePort::disentanglePorts(ports, ec);
+        if (ec)
+            return;
+    }
+    m_entangledChannel->postMessageToRemote(message, channels.release());
+}
+
+PassOwnPtr<MessagePortChannel> MessagePort::disentangle()
+{
+    ASSERT(m_entangledChannel);
+
+    m_entangledChannel->disentangle();
+
+    // We can't receive any messages or generate any events, so remove ourselves from the list of active ports.
+    ASSERT(m_scriptExecutionContext);
+    m_scriptExecutionContext->destroyedMessagePort(this);
+    m_scriptExecutionContext = 0;
+
+    return m_entangledChannel.release();
+}
+
+// Invoked to notify us that there are messages available for this port.
+// This code may be called from another thread, and so should not call any non-threadsafe APIs (i.e. should not call into the entangled channel or access mutable variables).
+void MessagePort::messageAvailable()
+{
+    ASSERT(m_scriptExecutionContext);
+    m_scriptExecutionContext->processMessagePortMessagesSoon();
+}
+
+void MessagePort::start()
+{
+    // Do nothing if we've been cloned or closed.
+    if (!isEntangled())
+        return;
+
+    ASSERT(m_scriptExecutionContext);
+    if (m_started)
+        return;
+
+    m_started = true;
+    m_scriptExecutionContext->processMessagePortMessagesSoon();
+}
+
+void MessagePort::close()
+{
+    if (isEntangled())
+        m_entangledChannel->close();
+    m_closed = true;
+}
+
+void MessagePort::entangle(PassOwnPtr<MessagePortChannel> remote)
+{
+    // Only invoked to set our initial entanglement.
+    ASSERT(!m_entangledChannel);
+    ASSERT(m_scriptExecutionContext);
+
+    // Don't entangle the ports if the channel is closed.
+    if (remote->entangleIfOpen(this))
+        m_entangledChannel = remote;
+}
+
+void MessagePort::contextDestroyed()
+{
+    ASSERT(m_scriptExecutionContext);
+    // Must be closed before blowing away the cached context, to ensure that we get no more calls to messageAvailable().
+    // ScriptExecutionContext::closeMessagePorts() takes care of that.
+    ASSERT(m_closed);
+    m_scriptExecutionContext = 0;
+}
+
+const AtomicString& MessagePort::interfaceName() const
+{
+    return eventNames().interfaceForMessagePort;
+}
+
+ScriptExecutionContext* MessagePort::scriptExecutionContext() const
+{
+    return m_scriptExecutionContext;
+}
+
+void MessagePort::dispatchMessages()
+{
+    // Messages for contexts that are not fully active get dispatched too, but JSAbstractEventListener::handleEvent() doesn't call handlers for these.
+    // The HTML5 spec specifies that any messages sent to a document that is not fully active should be dropped, so this behavior is OK.
+    ASSERT(started());
+
+    RefPtr<SerializedScriptValue> message;
+    OwnPtr<MessagePortChannelArray> channels;
+    while (m_entangledChannel && m_entangledChannel->tryGetMessageFromRemote(message, channels)) {
+
+        // close() in Worker onmessage handler should prevent next message from dispatching.
+        if (m_scriptExecutionContext->isWorkerContext() && static_cast<WorkerContext*>(m_scriptExecutionContext)->isClosing())
+            return;
+
+        OwnPtr<MessagePortArray> ports = MessagePort::entanglePorts(*m_scriptExecutionContext, channels.release());
+        RefPtr<Event> evt = MessageEvent::create(ports.release(), message.release());
+
+        dispatchEvent(evt.release(), ASSERT_NO_EXCEPTION);
+    }
+}
+
+bool MessagePort::hasPendingActivity()
+{
+    // The spec says that entangled message ports should always be treated as if they have a strong reference.
+    // We'll also stipulate that the queue needs to be open (if the app drops its reference to the port before start()-ing it, then it's not really entangled as it's unreachable).
+    if (m_started && m_entangledChannel && m_entangledChannel->hasPendingActivity())
+        return true;
+    if (isEntangled() && !locallyEntangledPort())
+        return true;
+    return false;
+}
+
+MessagePort* MessagePort::locallyEntangledPort()
+{
+    return m_entangledChannel ? m_entangledChannel->locallyEntangledPort(m_scriptExecutionContext) : 0;
+}
+
+PassOwnPtr<MessagePortChannelArray> MessagePort::disentanglePorts(const MessagePortArray* ports, ExceptionCode& ec)
+{
+    if (!ports || !ports->size())
+        return nullptr;
+
+    // HashSet used to efficiently check for duplicates in the passed-in array.
+    HashSet<MessagePort*> portSet;
+
+    // Walk the incoming array - if there are any duplicate ports, or null ports or cloned ports, throw an error (per section 8.3.3 of the HTML5 spec).
+    for (unsigned int i = 0; i < ports->size(); ++i) {
+        MessagePort* port = (*ports)[i].get();
+        if (!port || port->isNeutered() || portSet.contains(port)) {
+            ec = DATA_CLONE_ERR;
+            return nullptr;
+        }
+        portSet.add(port);
+    }
+
+    // Passed-in ports passed validity checks, so we can disentangle them.
+    OwnPtr<MessagePortChannelArray> portArray = adoptPtr(new MessagePortChannelArray(ports->size()));
+    for (unsigned int i = 0 ; i < ports->size() ; ++i) {
+        OwnPtr<MessagePortChannel> channel = (*ports)[i]->disentangle();
+        (*portArray)[i] = channel.release();
+    }
+    return portArray.release();
+}
+
+PassOwnPtr<MessagePortArray> MessagePort::entanglePorts(ScriptExecutionContext& context, PassOwnPtr<MessagePortChannelArray> channels)
+{
+    if (!channels || !channels->size())
+        return nullptr;
+
+    OwnPtr<MessagePortArray> portArray = adoptPtr(new MessagePortArray(channels->size()));
+    for (unsigned int i = 0; i < channels->size(); ++i) {
+        RefPtr<MessagePort> port = MessagePort::create(context);
+        port->entangle((*channels)[i].release());
+        (*portArray)[i] = port.release();
+    }
+    return portArray.release();
+}
+
+EventTargetData* MessagePort::eventTargetData()
+{
+    return &m_eventTargetData;
+}
+
+EventTargetData* MessagePort::ensureEventTargetData()
+{
+    return &m_eventTargetData;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/MessagePort.h b/Source/core/dom/MessagePort.h
new file mode 100644
index 0000000..294df46
--- /dev/null
+++ b/Source/core/dom/MessagePort.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef MessagePort_h
+#define MessagePort_h
+
+#include "core/dom/EventListener.h"
+#include "core/dom/EventTarget.h"
+#include "core/dom/MessagePortChannel.h"
+#include <wtf/Forward.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+    class Event;
+    class Frame;
+    class MessagePort;
+    class ScriptExecutionContext;
+
+    // The overwhelmingly common case is sending a single port, so handle that efficiently with an inline buffer of size 1.
+    typedef Vector<RefPtr<MessagePort>, 1> MessagePortArray;
+
+    class MessagePort : public RefCounted<MessagePort>, public EventTarget {
+    public:
+        static PassRefPtr<MessagePort> create(ScriptExecutionContext& scriptExecutionContext) { return adoptRef(new MessagePort(scriptExecutionContext)); }
+        virtual ~MessagePort();
+
+        void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, ExceptionCode&);
+
+        void start();
+        void close();
+
+        void entangle(PassOwnPtr<MessagePortChannel>);
+        PassOwnPtr<MessagePortChannel> disentangle();
+
+        // Returns 0 if there is an exception, or if the passed-in array is 0/empty.
+        static PassOwnPtr<MessagePortChannelArray> disentanglePorts(const MessagePortArray*, ExceptionCode&);
+
+        // Returns 0 if the passed array is 0/empty.
+        static PassOwnPtr<MessagePortArray> entanglePorts(ScriptExecutionContext&, PassOwnPtr<MessagePortChannelArray>);
+
+        void messageAvailable();
+        bool started() const { return m_started; }
+
+        void contextDestroyed();
+
+        virtual const AtomicString& interfaceName() const OVERRIDE;
+        virtual ScriptExecutionContext* scriptExecutionContext() const OVERRIDE;
+
+        void dispatchMessages();
+
+        using RefCounted<MessagePort>::ref;
+        using RefCounted<MessagePort>::deref;
+
+        bool hasPendingActivity();
+
+        void setOnmessage(PassRefPtr<EventListener> listener)
+        {
+            setAttributeEventListener(eventNames().messageEvent, listener);
+            start();
+        }
+        EventListener* onmessage() { return getAttributeEventListener(eventNames().messageEvent); }
+
+        // Returns null if there is no entangled port, or if the entangled port is run by a different thread.
+        // This is used solely to enable a GC optimization. Some platforms may not be able to determine ownership
+        // of the remote port (since it may live cross-process) - those platforms may always return null.
+        MessagePort* locallyEntangledPort();
+
+        // A port starts out its life entangled, and remains entangled until it is closed or is cloned.
+        bool isEntangled() { return !m_closed && !isNeutered(); }
+
+        // A port gets neutered when it is transferred to a new owner via postMessage().
+        bool isNeutered() { return !m_entangledChannel; }
+
+    private:
+        explicit MessagePort(ScriptExecutionContext&);
+
+        virtual void refEventTarget() OVERRIDE { ref(); }
+        virtual void derefEventTarget() OVERRIDE { deref(); }
+        virtual EventTargetData* eventTargetData() OVERRIDE;
+        virtual EventTargetData* ensureEventTargetData() OVERRIDE;
+
+        OwnPtr<MessagePortChannel> m_entangledChannel;
+
+        bool m_started;
+        bool m_closed;
+
+        ScriptExecutionContext* m_scriptExecutionContext;
+        EventTargetData m_eventTargetData;
+    };
+
+} // namespace WebCore
+
+#endif // MessagePort_h
diff --git a/Source/core/dom/MessagePort.idl b/Source/core/dom/MessagePort.idl
new file mode 100644
index 0000000..85514c2
--- /dev/null
+++ b/Source/core/dom/MessagePort.idl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * 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 COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+[
+    ActiveDOMObject,
+    EventTarget
+] interface MessagePort {
+// We need to have something as an ObjC binding, because MessagePort is used in MessageEvent, which already has one,
+// but we don't want to actually expose the API while it is in flux.
+    [Custom, RaisesException] void postMessage(any message, optional Array messagePorts);
+
+    void start();
+    void close();
+
+    // event handler attributes
+    attribute EventListener onmessage;
+
+    // EventTarget interface
+    void addEventListener(DOMString type, 
+                          EventListener listener, 
+                          optional boolean useCapture);
+    void removeEventListener(DOMString type, 
+                             EventListener listener, 
+                             optional boolean useCapture);
+    [RaisesException] boolean dispatchEvent(Event evt);
+};
+
diff --git a/Source/core/dom/MessagePortChannel.cpp b/Source/core/dom/MessagePortChannel.cpp
new file mode 100644
index 0000000..be07120
--- /dev/null
+++ b/Source/core/dom/MessagePortChannel.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "config.h"
+#include "core/dom/MessagePortChannel.h"
+
+namespace WebCore {
+
+} // namespace WebCore
diff --git a/Source/core/dom/MessagePortChannel.h b/Source/core/dom/MessagePortChannel.h
new file mode 100644
index 0000000..c11c363
--- /dev/null
+++ b/Source/core/dom/MessagePortChannel.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MessagePortChannel_h
+#define MessagePortChannel_h
+
+#include "bindings/v8/SerializedScriptValue.h"
+#include <wtf/Forward.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+    class MessagePort;
+    class MessagePortChannel;
+    class PlatformMessagePortChannel;
+    class ScriptExecutionContext;
+    class SerializedScriptValue;
+
+    // The overwhelmingly common case is sending a single port, so handle that efficiently with an inline buffer of size 1.
+    typedef Vector<OwnPtr<MessagePortChannel>, 1> MessagePortChannelArray;
+
+    // MessagePortChannel is a platform-independent interface to the remote side of a message channel.
+    // It acts as a wrapper around the platform-dependent PlatformMessagePortChannel implementation which ensures that the platform-dependent close() method is invoked before destruction.
+    class MessagePortChannel {
+        WTF_MAKE_NONCOPYABLE(MessagePortChannel); WTF_MAKE_FAST_ALLOCATED;
+    public:
+        static void createChannel(PassRefPtr<MessagePort>, PassRefPtr<MessagePort>);
+
+        // Entangles the channel with a port (called when a port has been cloned, after the clone has been marshaled to its new owning thread and is ready to receive messages).
+        // Returns false if the entanglement failed because the port was closed.
+        bool entangleIfOpen(MessagePort*);
+
+        // Disentangles the channel from a given port so it no longer forwards messages to the port. Called when the port is being cloned and no new owning thread has yet been established.
+        void disentangle();
+
+        // Closes the port (ensures that no further messages can be added to either queue).
+        void close();
+
+        // Used by MessagePort.postMessage() to prevent callers from passing a port's own entangled port.
+        bool isConnectedTo(MessagePort*);
+
+        // Returns true if the proxy currently contains messages for this port.
+        bool hasPendingActivity();
+
+        // Sends a message and optional cloned port to the remote port.
+        void postMessageToRemote(PassRefPtr<SerializedScriptValue>, PassOwnPtr<MessagePortChannelArray>);
+
+        // Extracts a message from the message queue for this port.
+        bool tryGetMessageFromRemote(RefPtr<SerializedScriptValue>&, OwnPtr<MessagePortChannelArray>&);
+
+        // Returns the entangled port if run by the same thread (see MessagePort::locallyEntangledPort() for more details).
+        MessagePort* locallyEntangledPort(const ScriptExecutionContext*);
+
+        ~MessagePortChannel();
+
+        // Creates a new wrapper for the passed channel.
+        static PassOwnPtr<MessagePortChannel> create(PassRefPtr<PlatformMessagePortChannel>);
+
+        // FIXME: PlatformMessagePortChannel is an implementation detail, and should not be exposed via a public function.
+        PlatformMessagePortChannel* channel() const { return m_channel.get(); }
+
+    private:
+        explicit MessagePortChannel(PassRefPtr<PlatformMessagePortChannel>);
+        RefPtr<PlatformMessagePortChannel> m_channel;
+    };
+
+} // namespace WebCore
+
+#endif // MessagePortChannel_h
diff --git a/Source/core/dom/MouseEvent.cpp b/Source/core/dom/MouseEvent.cpp
new file mode 100644
index 0000000..c1a8f6c
--- /dev/null
+++ b/Source/core/dom/MouseEvent.cpp
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/MouseEvent.h"
+
+#include "core/dom/Clipboard.h"
+#include "core/dom/EventDispatcher.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/EventRetargeter.h"
+#include "core/html/HTMLIFrameElement.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/platform/PlatformMouseEvent.h"
+
+namespace WebCore {
+
+MouseEventInit::MouseEventInit()
+    : screenX(0)
+    , screenY(0)
+    , clientX(0)
+    , clientY(0)
+    , ctrlKey(false)
+    , altKey(false)
+    , shiftKey(false)
+    , metaKey(false)
+    , button(0)
+    , relatedTarget(0)
+{
+}
+
+PassRefPtr<MouseEvent> MouseEvent::create(const AtomicString& type, const MouseEventInit& initializer)
+{
+    return adoptRef(new MouseEvent(type, initializer));
+}
+
+PassRefPtr<MouseEvent> MouseEvent::create(const AtomicString& eventType, PassRefPtr<AbstractView> view, const PlatformMouseEvent& event, int detail, PassRefPtr<Node> relatedTarget)
+{
+    ASSERT(event.type() == PlatformEvent::MouseMoved || event.button() != NoButton);
+
+    bool isCancelable = eventType != eventNames().mousemoveEvent;
+
+    return MouseEvent::create(eventType, true, isCancelable, view,
+        detail, event.globalPosition().x(), event.globalPosition().y(), event.position().x(), event.position().y(),
+        event.movementDelta().x(), event.movementDelta().y(),
+        event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), event.button(),
+        relatedTarget, 0, false);
+}
+
+PassRefPtr<MouseEvent> MouseEvent::create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView> view,
+    int detail, int screenX, int screenY, int pageX, int pageY,
+    int movementX, int movementY,
+    bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, unsigned short button,
+    PassRefPtr<EventTarget> relatedTarget)
+
+{
+    return MouseEvent::create(type, canBubble, cancelable, view,
+        detail, screenX, screenY, pageX, pageY,
+        movementX, movementY,
+        ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget, 0, false);
+}
+
+PassRefPtr<MouseEvent> MouseEvent::create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView> view,
+    int detail, int screenX, int screenY, int pageX, int pageY,
+    int movementX, int movementY,
+    bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, unsigned short button,
+    PassRefPtr<EventTarget> relatedTarget, PassRefPtr<Clipboard> clipboard, bool isSimulated)
+{
+    return adoptRef(new MouseEvent(type, canBubble, cancelable, view,
+        detail, screenX, screenY, pageX, pageY,
+        movementX, movementY,
+        ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget, clipboard, isSimulated));
+}
+
+MouseEvent::MouseEvent()
+    : m_button(0)
+    , m_buttonDown(false)
+{
+    ScriptWrappable::init(this);
+}
+
+MouseEvent::MouseEvent(const AtomicString& eventType, bool canBubble, bool cancelable, PassRefPtr<AbstractView> view,
+                       int detail, int screenX, int screenY, int pageX, int pageY,
+                       int movementX, int movementY,
+                       bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
+                       unsigned short button, PassRefPtr<EventTarget> relatedTarget,
+                       PassRefPtr<Clipboard> clipboard, bool isSimulated)
+    : MouseRelatedEvent(eventType, canBubble, cancelable, view, detail, IntPoint(screenX, screenY),
+                        IntPoint(pageX, pageY),
+                        IntPoint(movementX, movementY),
+                        ctrlKey, altKey, shiftKey, metaKey, isSimulated)
+    , m_button(button == (unsigned short)-1 ? 0 : button)
+    , m_buttonDown(button != (unsigned short)-1)
+    , m_relatedTarget(relatedTarget)
+    , m_clipboard(clipboard)
+{
+    ScriptWrappable::init(this);
+}
+
+MouseEvent::MouseEvent(const AtomicString& eventType, const MouseEventInit& initializer)
+    : MouseRelatedEvent(eventType, initializer.bubbles, initializer.cancelable, initializer.view, initializer.detail, IntPoint(initializer.screenX, initializer.screenY),
+        IntPoint(0 /* pageX */, 0 /* pageY */),
+        IntPoint(0 /* movementX */, 0 /* movementY */),
+        initializer.ctrlKey, initializer.altKey, initializer.shiftKey, initializer.metaKey, false /* isSimulated */)
+    , m_button(initializer.button == (unsigned short)-1 ? 0 : initializer.button)
+    , m_buttonDown(initializer.button != (unsigned short)-1)
+    , m_relatedTarget(initializer.relatedTarget)
+    , m_clipboard(0 /* clipboard */)
+{
+    ScriptWrappable::init(this);
+    initCoordinates(IntPoint(initializer.clientX, initializer.clientY));
+}
+
+MouseEvent::~MouseEvent()
+{
+}
+
+void MouseEvent::initMouseEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView> view,
+                                int detail, int screenX, int screenY, int clientX, int clientY,
+                                bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
+                                unsigned short button, PassRefPtr<EventTarget> relatedTarget)
+{
+    if (dispatched())
+        return;
+
+    initUIEvent(type, canBubble, cancelable, view, detail);
+
+    m_screenLocation = IntPoint(screenX, screenY);
+    m_ctrlKey = ctrlKey;
+    m_altKey = altKey;
+    m_shiftKey = shiftKey;
+    m_metaKey = metaKey;
+    m_button = button == (unsigned short)-1 ? 0 : button;
+    m_buttonDown = button != (unsigned short)-1;
+    m_relatedTarget = relatedTarget;
+
+    initCoordinates(IntPoint(clientX, clientY));
+
+    // FIXME: m_isSimulated is not set to false here.
+    // FIXME: m_clipboard is not set to 0 here.
+}
+
+const AtomicString& MouseEvent::interfaceName() const
+{
+    return eventNames().interfaceForMouseEvent;
+}
+
+bool MouseEvent::isMouseEvent() const
+{
+    return true;
+}
+
+bool MouseEvent::isDragEvent() const
+{
+    const AtomicString& t = type();
+    return t == eventNames().dragenterEvent || t == eventNames().dragoverEvent || t == eventNames().dragleaveEvent || t == eventNames().dropEvent
+               || t == eventNames().dragstartEvent|| t == eventNames().dragEvent || t == eventNames().dragendEvent;
+}
+
+int MouseEvent::which() const
+{
+    // For the DOM, the return values for left, middle and right mouse buttons are 0, 1, 2, respectively.
+    // For the Netscape "which" property, the return values for left, middle and right mouse buttons are 1, 2, 3, respectively. 
+    // So we must add 1.
+    if (!m_buttonDown)
+        return 0;
+    return m_button + 1;
+}
+
+Node* MouseEvent::toElement() const
+{
+    // MSIE extension - "the object toward which the user is moving the mouse pointer"
+    if (type() == eventNames().mouseoutEvent) 
+        return relatedTarget() ? relatedTarget()->toNode() : 0;
+    
+    return target() ? target()->toNode() : 0;
+}
+
+Node* MouseEvent::fromElement() const
+{
+    // MSIE extension - "object from which activation or the mouse pointer is exiting during the event" (huh?)
+    if (type() != eventNames().mouseoutEvent)
+        return relatedTarget() ? relatedTarget()->toNode() : 0;
+    
+    return target() ? target()->toNode() : 0;
+}
+
+// FIXME: Fix positioning. e.g. We need to consider border/padding.
+// https://bugs.webkit.org/show_bug.cgi?id=93696
+inline static int adjustedClientX(int innerClientX, HTMLIFrameElement* iframe, FrameView* frameView)
+{
+    return iframe->offsetLeft() - frameView->scrollX() + innerClientX;
+}
+
+inline static int adjustedClientY(int innerClientY, HTMLIFrameElement* iframe, FrameView* frameView)
+{
+    return iframe->offsetTop() - frameView->scrollY() + innerClientY;
+}
+
+PassRefPtr<Event> MouseEvent::cloneFor(HTMLIFrameElement* iframe) const
+{
+    ASSERT(iframe);
+    RefPtr<MouseEvent> clonedMouseEvent = MouseEvent::create();
+    Frame* frame = iframe->document()->frame();
+    FrameView* frameView = frame ? frame->view() : 0;
+    clonedMouseEvent->initMouseEvent(type(), bubbles(), cancelable(),
+            iframe->document()->defaultView(),
+            detail(), screenX(), screenY(),
+            frameView ? adjustedClientX(clientX(), iframe, frameView) : 0,
+            frameView ? adjustedClientY(clientY(), iframe, frameView) : 0,
+            ctrlKey(), altKey(), shiftKey(), metaKey(),
+            button(),
+            // Nullifies relatedTarget.
+            0);
+    return clonedMouseEvent.release();
+}
+
+PassRefPtr<SimulatedMouseEvent> SimulatedMouseEvent::create(const AtomicString& eventType, PassRefPtr<AbstractView> view, PassRefPtr<Event> underlyingEvent)
+{
+    return adoptRef(new SimulatedMouseEvent(eventType, view, underlyingEvent));
+}
+
+SimulatedMouseEvent::~SimulatedMouseEvent()
+{
+}
+
+SimulatedMouseEvent::SimulatedMouseEvent(const AtomicString& eventType, PassRefPtr<AbstractView> view, PassRefPtr<Event> underlyingEvent)
+    : MouseEvent(eventType, true, true, view, 0, 0, 0, 0, 0,
+                 0, 0,
+                 false, false, false, false, 0, 0, 0, true)
+{
+    if (UIEventWithKeyState* keyStateEvent = findEventWithKeyState(underlyingEvent.get())) {
+        m_ctrlKey = keyStateEvent->ctrlKey();
+        m_altKey = keyStateEvent->altKey();
+        m_shiftKey = keyStateEvent->shiftKey();
+        m_metaKey = keyStateEvent->metaKey();
+    }
+    setUnderlyingEvent(underlyingEvent);
+
+    if (this->underlyingEvent() && this->underlyingEvent()->isMouseEvent()) {
+        MouseEvent* mouseEvent = static_cast<MouseEvent*>(this->underlyingEvent());
+        m_screenLocation = mouseEvent->screenLocation();
+        initCoordinates(mouseEvent->clientLocation());
+    }
+}
+
+PassRefPtr<MouseEventDispatchMediator> MouseEventDispatchMediator::create(PassRefPtr<MouseEvent> mouseEvent, MouseEventType mouseEventType)
+{
+    return adoptRef(new MouseEventDispatchMediator(mouseEvent, mouseEventType));
+}
+
+MouseEventDispatchMediator::MouseEventDispatchMediator(PassRefPtr<MouseEvent> mouseEvent, MouseEventType mouseEventType)
+    : EventDispatchMediator(mouseEvent), m_mouseEventType(mouseEventType)
+{
+}
+
+MouseEvent* MouseEventDispatchMediator::event() const
+{
+    return static_cast<MouseEvent*>(EventDispatchMediator::event());
+}
+
+bool MouseEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
+{
+    if (isSyntheticMouseEvent()) {
+        EventRetargeter::adjustForMouseEvent(dispatcher->node(), *event());
+        return dispatcher->dispatch();
+    }
+
+    if (isDisabledFormControl(dispatcher->node()))
+        return false;
+
+    if (event()->type().isEmpty())
+        return true; // Shouldn't happen.
+
+    ASSERT(!event()->target() || event()->target() != event()->relatedTarget());
+
+    EventTarget* relatedTarget = event()->relatedTarget();
+    EventRetargeter::adjustForMouseEvent(dispatcher->node(), *event());
+
+    dispatcher->dispatch();
+    bool swallowEvent = event()->defaultHandled() || event()->defaultPrevented();
+
+    if (event()->type() != eventNames().clickEvent || event()->detail() != 2)
+        return !swallowEvent;
+
+    // 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.
+    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();
+    EventDispatcher::dispatchEvent(dispatcher->node(), MouseEventDispatchMediator::create(doubleClickEvent));
+    if (doubleClickEvent->defaultHandled() || doubleClickEvent->defaultPrevented())
+        return false;
+    return !swallowEvent;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/MouseEvent.h b/Source/core/dom/MouseEvent.h
new file mode 100644
index 0000000..d91daff
--- /dev/null
+++ b/Source/core/dom/MouseEvent.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MouseEvent_h
+#define MouseEvent_h
+
+#include "core/dom/EventDispatchMediator.h"
+#include "core/dom/MouseRelatedEvent.h"
+
+namespace WebCore {
+
+class Clipboard;
+class EventDispatcher;
+class PlatformMouseEvent;
+
+struct MouseEventInit : public UIEventInit {
+    MouseEventInit();
+
+    int screenX;
+    int screenY;
+    int clientX;
+    int clientY;
+    bool ctrlKey;
+    bool altKey;
+    bool shiftKey;
+    bool metaKey;
+    unsigned short button;
+    RefPtr<EventTarget> relatedTarget;
+};
+
+class MouseEvent : public MouseRelatedEvent {
+public:
+    static PassRefPtr<MouseEvent> create()
+    {
+        return adoptRef(new MouseEvent);
+    }
+
+    static PassRefPtr<MouseEvent> create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>,
+        int detail, int screenX, int screenY, int pageX, int pageY,
+        int movementX, int movementY,
+        bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, unsigned short button,
+        PassRefPtr<EventTarget> relatedTarget);
+
+    static PassRefPtr<MouseEvent> create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>,
+        int detail, int screenX, int screenY, int pageX, int pageY,
+        int movementX, int movementY,
+        bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, unsigned short button,
+        PassRefPtr<EventTarget> relatedTarget, PassRefPtr<Clipboard>, bool isSimulated = false);
+
+    static PassRefPtr<MouseEvent> create(const AtomicString& eventType, PassRefPtr<AbstractView>, const PlatformMouseEvent&, int detail, PassRefPtr<Node> relatedTarget);
+
+    static PassRefPtr<MouseEvent> create(const AtomicString& eventType, const MouseEventInit&);
+
+    virtual ~MouseEvent();
+
+    void initMouseEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>,
+        int detail, int screenX, int screenY, int clientX, int clientY,
+        bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
+        unsigned short button, PassRefPtr<EventTarget> relatedTarget);
+
+    // WinIE uses 1,4,2 for left/middle/right but not for click (just for mousedown/up, maybe others),
+    // but we will match the standard DOM.
+    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(); }
+
+    Node* toElement() const;
+    Node* fromElement() const;
+
+    Clipboard* dataTransfer() const { return isDragEvent() ? m_clipboard.get() : 0; }
+
+    virtual const AtomicString& interfaceName() const;
+
+    virtual bool isMouseEvent() const;
+    virtual bool isDragEvent() const;
+    virtual int which() const;
+
+    virtual PassRefPtr<Event> cloneFor(HTMLIFrameElement*) const OVERRIDE;
+
+protected:
+    MouseEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>,
+        int detail, int screenX, int screenY, int pageX, int pageY,
+        int movementX, int movementY,
+        bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, unsigned short button,
+        PassRefPtr<EventTarget> relatedTarget, PassRefPtr<Clipboard>, bool isSimulated);
+
+    MouseEvent(const AtomicString& type, const MouseEventInit&);
+
+    MouseEvent();
+
+private:
+    unsigned short m_button;
+    bool m_buttonDown;
+    RefPtr<EventTarget> m_relatedTarget;
+    RefPtr<Clipboard> m_clipboard;
+};
+
+class SimulatedMouseEvent : public MouseEvent {
+public:
+    static PassRefPtr<SimulatedMouseEvent> create(const AtomicString& eventType, PassRefPtr<AbstractView>, PassRefPtr<Event> underlyingEvent);
+    virtual ~SimulatedMouseEvent();
+
+private:
+    SimulatedMouseEvent(const AtomicString& eventType, PassRefPtr<AbstractView>, PassRefPtr<Event> underlyingEvent);
+};
+
+class MouseEventDispatchMediator : public EventDispatchMediator {
+public:
+    enum MouseEventType { SyntheticMouseEvent, NonSyntheticMouseEvent};
+    static PassRefPtr<MouseEventDispatchMediator> create(PassRefPtr<MouseEvent>, MouseEventType = NonSyntheticMouseEvent);
+
+private:
+    explicit MouseEventDispatchMediator(PassRefPtr<MouseEvent>, MouseEventType);
+    MouseEvent* event() const;
+
+    virtual bool dispatchEvent(EventDispatcher*) const OVERRIDE;
+    bool isSyntheticMouseEvent() const { return m_mouseEventType == SyntheticMouseEvent; }
+    MouseEventType m_mouseEventType;
+};
+
+inline MouseEvent* toMouseEvent(Event* event)
+{
+    ASSERT(event && event->isMouseEvent());
+    return static_cast<MouseEvent*>(event);
+}
+
+} // namespace WebCore
+
+#endif // MouseEvent_h
diff --git a/Source/core/dom/MouseEvent.idl b/Source/core/dom/MouseEvent.idl
new file mode 100644
index 0000000..888ac71
--- /dev/null
+++ b/Source/core/dom/MouseEvent.idl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+[
+    ConstructorTemplate=Event,
+    SkipVTableValidation
+] interface MouseEvent : UIEvent {
+    [InitializedByEventConstructor] readonly attribute long             screenX;
+    [InitializedByEventConstructor] readonly attribute long             screenY;
+    [InitializedByEventConstructor] readonly attribute long             clientX;
+    [InitializedByEventConstructor] readonly attribute long             clientY;
+    [InitializedByEventConstructor] readonly attribute boolean          ctrlKey;
+    [InitializedByEventConstructor] readonly attribute boolean          shiftKey;
+    [InitializedByEventConstructor] readonly attribute boolean          altKey;
+    [InitializedByEventConstructor] readonly attribute boolean          metaKey;
+    [InitializedByEventConstructor] readonly attribute unsigned short   button;
+    [InitializedByEventConstructor] readonly attribute EventTarget      relatedTarget;
+                                    readonly attribute long             webkitMovementX;
+                                    readonly attribute long             webkitMovementY;
+    
+     void initMouseEvent([Default=Undefined] optional DOMString type, 
+                                       [Default=Undefined] optional boolean canBubble, 
+                                       [Default=Undefined] optional boolean cancelable, 
+                                       [Default=Undefined] optional DOMWindow view, 
+                                       [Default=Undefined] optional long detail, 
+                                       [Default=Undefined] optional long screenX, 
+                                       [Default=Undefined] optional long screenY, 
+                                       [Default=Undefined] optional long clientX, 
+                                       [Default=Undefined] optional long clientY, 
+                                       [Default=Undefined] optional boolean ctrlKey, 
+                                       [Default=Undefined] optional boolean altKey, 
+                                       [Default=Undefined] optional boolean shiftKey, 
+                                       [Default=Undefined] optional boolean metaKey, 
+                                       [Default=Undefined] optional unsigned short button, 
+                                       [Default=Undefined] optional EventTarget relatedTarget);
+
+    // extensions
+    readonly attribute long             offsetX;
+    readonly attribute long             offsetY;
+    readonly attribute long             x;
+    readonly attribute long             y;
+    readonly attribute Node             fromElement;
+    readonly attribute Node             toElement;
+
+    readonly attribute Clipboard        dataTransfer;
+};
+
diff --git a/Source/core/dom/MouseRelatedEvent.cpp b/Source/core/dom/MouseRelatedEvent.cpp
new file mode 100644
index 0000000..14a40aa
--- /dev/null
+++ b/Source/core/dom/MouseRelatedEvent.cpp
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/MouseRelatedEvent.h"
+
+#include "core/dom/Document.h"
+#include "core/page/DOMWindow.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderObject.h"
+
+namespace WebCore {
+
+MouseRelatedEvent::MouseRelatedEvent()
+    : m_isSimulated(false)
+    , m_hasCachedRelativePosition(false)
+{
+}
+
+static LayoutSize contentsScrollOffset(AbstractView* abstractView)
+{
+    if (!abstractView)
+        return LayoutSize();
+    Frame* frame = abstractView->frame();
+    if (!frame)
+        return LayoutSize();
+    FrameView* frameView = frame->view();
+    if (!frameView)
+        return LayoutSize();
+    float scaleFactor = frame->pageZoomFactor();
+    return LayoutSize(frameView->scrollX() / scaleFactor, frameView->scrollY() / scaleFactor);
+}
+
+MouseRelatedEvent::MouseRelatedEvent(const AtomicString& eventType, bool canBubble, bool cancelable, PassRefPtr<AbstractView> abstractView,
+                                     int detail, const IntPoint& screenLocation, const IntPoint& windowLocation,
+                                     const IntPoint& movementDelta,
+                                     bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool isSimulated)
+    : UIEventWithKeyState(eventType, canBubble, cancelable, abstractView, detail, ctrlKey, altKey, shiftKey, metaKey)
+    , m_screenLocation(screenLocation)
+    , m_movementDelta(movementDelta)
+    , m_isSimulated(isSimulated)
+{
+    LayoutPoint adjustedPageLocation;
+    LayoutPoint scrollPosition;
+
+    Frame* frame = view() ? view()->frame() : 0;
+    if (frame && !isSimulated) {
+        if (FrameView* frameView = frame->view()) {
+            scrollPosition = frameView->scrollPosition();
+            adjustedPageLocation = frameView->windowToContents(windowLocation);
+            float scaleFactor = 1 / frame->pageZoomFactor();
+            if (scaleFactor != 1.0f) {
+                adjustedPageLocation.scale(scaleFactor, scaleFactor);
+                scrollPosition.scale(scaleFactor, scaleFactor);
+            }
+        }
+    }
+
+    m_clientLocation = adjustedPageLocation - toLayoutSize(scrollPosition);
+    m_pageLocation = adjustedPageLocation;
+
+    initCoordinates();
+}
+
+void MouseRelatedEvent::initCoordinates()
+{
+    // Set up initial values for coordinates.
+    // Correct values are computed lazily, see computeRelativePosition.
+    m_layerLocation = m_pageLocation;
+    m_offsetLocation = m_pageLocation;
+
+    computePageLocation();
+    m_hasCachedRelativePosition = false;
+}
+
+void MouseRelatedEvent::initCoordinates(const LayoutPoint& clientLocation)
+{
+    // Set up initial values for coordinates.
+    // Correct values are computed lazily, see computeRelativePosition.
+    m_clientLocation = clientLocation;
+    m_pageLocation = clientLocation + contentsScrollOffset(view());
+
+    m_layerLocation = m_pageLocation;
+    m_offsetLocation = m_pageLocation;
+
+    computePageLocation();
+    m_hasCachedRelativePosition = false;
+}
+
+static float pageZoomFactor(const UIEvent* event)
+{
+    DOMWindow* window = event->view();
+    if (!window)
+        return 1;
+    Frame* frame = window->frame();
+    if (!frame)
+        return 1;
+    return frame->pageZoomFactor();
+}
+
+void MouseRelatedEvent::computePageLocation()
+{
+    float scaleFactor = pageZoomFactor(this);
+    setAbsoluteLocation(roundedLayoutPoint(FloatPoint(pageX() * scaleFactor, pageY() * scaleFactor)));
+}
+
+void MouseRelatedEvent::receivedTarget()
+{
+    m_hasCachedRelativePosition = false;
+}
+
+void MouseRelatedEvent::computeRelativePosition()
+{
+    Node* targetNode = target() ? target()->toNode() : 0;
+    if (!targetNode)
+        return;
+
+    // Compute coordinates that are based on the target.
+    m_layerLocation = m_pageLocation;
+    m_offsetLocation = m_pageLocation;
+
+    // Must have an updated render tree for this math to work correctly.
+    targetNode->document()->updateLayoutIgnorePendingStylesheets();
+
+    // Adjust offsetLocation to be relative to the target's position.
+    if (RenderObject* r = targetNode->renderer()) {
+        FloatPoint localPos = r->absoluteToLocal(absoluteLocation(), UseTransforms);
+        m_offsetLocation = roundedLayoutPoint(localPos);
+        float scaleFactor = 1 / pageZoomFactor(this);
+        if (scaleFactor != 1.0f)
+            m_offsetLocation.scale(scaleFactor, scaleFactor);
+    }
+
+    // Adjust layerLocation to be relative to the layer.
+    // FIXME: event.layerX and event.layerY are poorly defined,
+    // and probably don't always correspond to RenderLayer offsets.
+    // https://bugs.webkit.org/show_bug.cgi?id=21868
+    Node* n = targetNode;
+    while (n && !n->renderer())
+        n = n->parentNode();
+
+    RenderLayer* layer;
+    if (n && (layer = n->renderer()->enclosingLayer())) {
+        for (; layer; layer = layer->parent()) {
+            m_layerLocation -= toLayoutSize(layer->location());
+        }
+    }
+
+    m_hasCachedRelativePosition = true;
+}
+
+int MouseRelatedEvent::layerX()
+{
+    if (!m_hasCachedRelativePosition)
+        computeRelativePosition();
+    return m_layerLocation.x();
+}
+
+int MouseRelatedEvent::layerY()
+{
+    if (!m_hasCachedRelativePosition)
+        computeRelativePosition();
+    return m_layerLocation.y();
+}
+
+int MouseRelatedEvent::offsetX()
+{
+    if (!m_hasCachedRelativePosition)
+        computeRelativePosition();
+    return roundToInt(m_offsetLocation.x());
+}
+
+int MouseRelatedEvent::offsetY()
+{
+    if (!m_hasCachedRelativePosition)
+        computeRelativePosition();
+    return roundToInt(m_offsetLocation.y());
+}
+
+int MouseRelatedEvent::pageX() const
+{
+    return m_pageLocation.x();
+}
+
+int MouseRelatedEvent::pageY() const
+{
+    return m_pageLocation.y();
+}
+
+const LayoutPoint& MouseRelatedEvent::pageLocation() const
+{
+    return m_pageLocation;
+}
+
+int MouseRelatedEvent::x() const
+{
+    // FIXME: This is not correct.
+    // See Microsoft documentation and <http://www.quirksmode.org/dom/w3c_events.html>.
+    return m_clientLocation.x();
+}
+
+int MouseRelatedEvent::y() const
+{
+    // FIXME: This is not correct.
+    // See Microsoft documentation and <http://www.quirksmode.org/dom/w3c_events.html>.
+    return m_clientLocation.y();
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/MouseRelatedEvent.h b/Source/core/dom/MouseRelatedEvent.h
new file mode 100644
index 0000000..a33ddf8
--- /dev/null
+++ b/Source/core/dom/MouseRelatedEvent.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MouseRelatedEvent_h
+#define MouseRelatedEvent_h
+
+#include "core/dom/UIEventWithKeyState.h"
+#include "core/platform/graphics/LayoutPoint.h"
+
+namespace WebCore {
+
+    // Internal only: Helper class for what's common between mouse and wheel events.
+    class MouseRelatedEvent : public UIEventWithKeyState {
+    public:
+        // Note that these values are adjusted to counter the effects of zoom, so that values
+        // exposed via DOM APIs are invariant under zooming.
+        int screenX() const { return m_screenLocation.x(); }
+        int screenY() const { return m_screenLocation.y(); }
+        const IntPoint& screenLocation() const { return m_screenLocation; }
+        int clientX() const { return m_clientLocation.x(); }
+        int clientY() const { return m_clientLocation.y(); }
+        int webkitMovementX() const { return m_movementDelta.x(); }
+        int webkitMovementY() const { return m_movementDelta.y(); }
+        const LayoutPoint& clientLocation() const { return m_clientLocation; }
+        int layerX();
+        int layerY();
+        int offsetX();
+        int offsetY();
+        bool isSimulated() const { return m_isSimulated; }
+        virtual int pageX() const;
+        virtual int pageY() const;
+        virtual const LayoutPoint& pageLocation() const;
+        int x() const;
+        int y() const;
+
+        // Page point in "absolute" coordinates (i.e. post-zoomed, page-relative coords,
+        // usable with RenderObject::absoluteToLocal).
+        const LayoutPoint& absoluteLocation() const { return m_absoluteLocation; }
+        void setAbsoluteLocation(const LayoutPoint& p) { m_absoluteLocation = p; }
+
+    protected:
+        MouseRelatedEvent();
+        MouseRelatedEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>,
+                          int detail, const IntPoint& screenLocation, const IntPoint& windowLocation,
+                          const IntPoint& movementDelta,
+                          bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool isSimulated = false);
+
+        void initCoordinates();
+        void initCoordinates(const LayoutPoint& clientLocation);
+        virtual void receivedTarget();
+
+        void computePageLocation();
+        void computeRelativePosition();
+
+        // Expose these so MouseEvent::initMouseEvent can set them.
+        IntPoint m_screenLocation;
+        LayoutPoint m_clientLocation;
+        LayoutPoint m_movementDelta;
+
+    private:
+        LayoutPoint m_pageLocation;
+        LayoutPoint m_layerLocation;
+        LayoutPoint m_offsetLocation;
+        LayoutPoint m_absoluteLocation;
+        bool m_isSimulated;
+        bool m_hasCachedRelativePosition;
+    };
+
+} // namespace WebCore
+
+#endif // MouseRelatedEvent_h
diff --git a/Source/core/dom/MutationCallback.h b/Source/core/dom/MutationCallback.h
new file mode 100644
index 0000000..a60ce8b
--- /dev/null
+++ b/Source/core/dom/MutationCallback.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MutationCallback_h
+#define MutationCallback_h
+
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class MutationRecord;
+class MutationObserver;
+
+class MutationCallback : public RefCounted<MutationCallback> {
+public:
+    virtual ~MutationCallback() { }
+
+    virtual void call(const Vector<RefPtr<MutationRecord> >&, MutationObserver*) = 0;
+    virtual ScriptExecutionContext* scriptExecutionContext() const = 0;
+};
+
+}
+
+#endif // MutationCallback_h
diff --git a/Source/core/dom/MutationEvent.cpp b/Source/core/dom/MutationEvent.cpp
new file mode 100644
index 0000000..fcb19b9
--- /dev/null
+++ b/Source/core/dom/MutationEvent.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/MutationEvent.h"
+
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+MutationEvent::MutationEvent()
+    : m_attrChange(0)
+{
+    ScriptWrappable::init(this);
+}
+
+MutationEvent::MutationEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<Node> relatedNode,
+                             const String& prevValue, const String& newValue,
+                             const String& attrName, unsigned short attrChange)
+    : Event(type, canBubble, cancelable)
+    , m_relatedNode(relatedNode)
+    , m_prevValue(prevValue)
+    , m_newValue(newValue)
+    , m_attrName(attrName)
+    , m_attrChange(attrChange)
+{
+    ScriptWrappable::init(this);
+}
+
+MutationEvent::~MutationEvent()
+{
+}
+
+void MutationEvent::initMutationEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<Node> relatedNode,
+                                      const String& prevValue, const String& newValue,
+                                      const String& attrName, unsigned short attrChange)
+{
+    if (dispatched())
+        return;
+
+    initEvent(type, canBubble, cancelable);
+
+    m_relatedNode = relatedNode;
+    m_prevValue = prevValue;
+    m_newValue = newValue;
+    m_attrName = attrName;
+    m_attrChange = attrChange;
+}
+
+const AtomicString& MutationEvent::interfaceName() const
+{
+    return eventNames().interfaceForMutationEvent;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/MutationEvent.h b/Source/core/dom/MutationEvent.h
new file mode 100644
index 0000000..15e3da1
--- /dev/null
+++ b/Source/core/dom/MutationEvent.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MutationEvent_h
+#define MutationEvent_h
+
+#include "core/dom/Event.h"
+#include "core/dom/Node.h"
+
+namespace WebCore {
+
+    class MutationEvent : public Event {
+    public:
+        virtual ~MutationEvent();
+
+        enum attrChangeType {
+            MODIFICATION    = 1,
+            ADDITION        = 2,
+            REMOVAL         = 3
+        };
+
+        static PassRefPtr<MutationEvent> create()
+        {
+            return adoptRef(new MutationEvent);
+        }
+
+        static PassRefPtr<MutationEvent> create(const AtomicString& type, bool canBubble, PassRefPtr<Node> relatedNode = 0,
+            const String& prevValue = String(), const String& newValue = String(), const String& attrName = String(), unsigned short attrChange = 0)
+        {
+            return adoptRef(new MutationEvent(type, canBubble, false, relatedNode, prevValue, newValue, attrName, attrChange));
+        }
+
+        void initMutationEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<Node> relatedNode,
+                               const String& prevValue, const String& newValue,
+                               const String& attrName, unsigned short attrChange);
+
+        Node* relatedNode() const { return m_relatedNode.get(); }
+        String prevValue() const { return m_prevValue; }
+        String newValue() const { return m_newValue; }
+        String attrName() const { return m_attrName; }
+        unsigned short attrChange() const { return m_attrChange; }
+
+        virtual const AtomicString& interfaceName() const;
+
+    private:
+        MutationEvent();
+        MutationEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<Node> relatedNode,
+                      const String& prevValue, const String& newValue,
+                      const String& attrName, unsigned short attrChange);
+
+        RefPtr<Node> m_relatedNode;
+        String m_prevValue;
+        String m_newValue;
+        String m_attrName;
+        unsigned short m_attrChange;
+    };
+
+} // namespace WebCore
+
+#endif // MutationEvent_h
diff --git a/Source/core/dom/MutationEvent.idl b/Source/core/dom/MutationEvent.idl
new file mode 100644
index 0000000..16c183e
--- /dev/null
+++ b/Source/core/dom/MutationEvent.idl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+// Introduced in DOM Level 2:
+interface MutationEvent : Event {
+
+    // attrChangeType
+    const unsigned short MODIFICATION = 1;
+    const unsigned short ADDITION     = 2;
+    const unsigned short REMOVAL      = 3;
+
+    readonly attribute Node           relatedNode;
+    readonly attribute DOMString      prevValue;
+    readonly attribute DOMString      newValue;
+    readonly attribute DOMString      attrName;
+    readonly attribute unsigned short attrChange;
+
+     void initMutationEvent([Default=Undefined] optional DOMString type, 
+                                          [Default=Undefined] optional boolean canBubble, 
+                                          [Default=Undefined] optional boolean cancelable, 
+                                          [Default=Undefined] optional Node relatedNode, 
+                                          [Default=Undefined] optional DOMString prevValue, 
+                                          [Default=Undefined] optional DOMString newValue, 
+                                          [Default=Undefined] optional DOMString attrName, 
+                                          [Default=Undefined] optional unsigned short attrChange);
+
+};
+
diff --git a/Source/core/dom/MutationObserver.cpp b/Source/core/dom/MutationObserver.cpp
new file mode 100644
index 0000000..c1a3a07
--- /dev/null
+++ b/Source/core/dom/MutationObserver.cpp
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "core/dom/MutationObserver.h"
+
+#include <algorithm>
+#include "bindings/v8/Dictionary.h"
+#include "core/dom/Document.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/MutationCallback.h"
+#include "core/dom/MutationObserverRegistration.h"
+#include "core/dom/MutationRecord.h"
+#include "core/dom/Node.h"
+#include <wtf/HashSet.h>
+#include <wtf/MainThread.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+static unsigned s_observerPriority = 0;
+
+struct MutationObserver::ObserverLessThan {
+    bool operator()(const RefPtr<MutationObserver>& lhs, const RefPtr<MutationObserver>& rhs)
+    {
+        return lhs->m_priority < rhs->m_priority;
+    }
+};
+
+PassRefPtr<MutationObserver> MutationObserver::create(PassRefPtr<MutationCallback> callback)
+{
+    ASSERT(isMainThread());
+    return adoptRef(new MutationObserver(callback));
+}
+
+MutationObserver::MutationObserver(PassRefPtr<MutationCallback> callback)
+    : m_callback(callback)
+    , m_priority(s_observerPriority++)
+{
+}
+
+MutationObserver::~MutationObserver()
+{
+    ASSERT(m_registrations.isEmpty());
+}
+
+bool MutationObserver::validateOptions(MutationObserverOptions options)
+{
+    return (options & (Attributes | CharacterData | ChildList))
+        && ((options & Attributes) || !(options & AttributeOldValue))
+        && ((options & Attributes) || !(options & AttributeFilter))
+        && ((options & CharacterData) || !(options & CharacterDataOldValue));
+}
+
+void MutationObserver::observe(Node* node, const Dictionary& optionsDictionary, ExceptionCode& ec)
+{
+    if (!node) {
+        ec = NOT_FOUND_ERR;
+        return;
+    }
+
+    static const struct {
+        const char* name;
+        MutationObserverOptions value;
+    } booleanOptions[] = {
+        { "childList", ChildList },
+        { "attributes", Attributes },
+        { "characterData", CharacterData },
+        { "subtree", Subtree },
+        { "attributeOldValue", AttributeOldValue },
+        { "characterDataOldValue", CharacterDataOldValue }
+    };
+    MutationObserverOptions options = 0;
+    for (unsigned i = 0; i < sizeof(booleanOptions) / sizeof(booleanOptions[0]); ++i) {
+        bool value = false;
+        if (optionsDictionary.get(booleanOptions[i].name, value) && value)
+            options |= booleanOptions[i].value;
+    }
+
+    HashSet<AtomicString> attributeFilter;
+    if (optionsDictionary.get("attributeFilter", attributeFilter))
+        options |= AttributeFilter;
+
+    if (!validateOptions(options)) {
+        ec = SYNTAX_ERR;
+        return;
+    }
+
+    node->registerMutationObserver(this, options, attributeFilter);
+}
+
+Vector<RefPtr<MutationRecord> > MutationObserver::takeRecords()
+{
+    Vector<RefPtr<MutationRecord> > records;
+    records.swap(m_records);
+    return records;
+}
+
+void MutationObserver::disconnect()
+{
+    m_records.clear();
+    HashSet<MutationObserverRegistration*> registrations(m_registrations);
+    for (HashSet<MutationObserverRegistration*>::iterator iter = registrations.begin(); iter != registrations.end(); ++iter)
+        (*iter)->unregister();
+}
+
+void MutationObserver::observationStarted(MutationObserverRegistration* registration)
+{
+    ASSERT(!m_registrations.contains(registration));
+    m_registrations.add(registration);
+}
+
+void MutationObserver::observationEnded(MutationObserverRegistration* registration)
+{
+    ASSERT(m_registrations.contains(registration));
+    m_registrations.remove(registration);
+}
+
+typedef HashSet<RefPtr<MutationObserver> > MutationObserverSet;
+
+static MutationObserverSet& activeMutationObservers()
+{
+    DEFINE_STATIC_LOCAL(MutationObserverSet, activeObservers, ());
+    return activeObservers;
+}
+
+static MutationObserverSet& suspendedMutationObservers()
+{
+    DEFINE_STATIC_LOCAL(MutationObserverSet, suspendedObservers, ());
+    return suspendedObservers;
+}
+
+void MutationObserver::enqueueMutationRecord(PassRefPtr<MutationRecord> mutation)
+{
+    ASSERT(isMainThread());
+    m_records.append(mutation);
+    activeMutationObservers().add(this);
+}
+
+void MutationObserver::setHasTransientRegistration()
+{
+    ASSERT(isMainThread());
+    activeMutationObservers().add(this);
+}
+
+HashSet<Node*> MutationObserver::getObservedNodes() const
+{
+    HashSet<Node*> observedNodes;
+    for (HashSet<MutationObserverRegistration*>::const_iterator iter = m_registrations.begin(); iter != m_registrations.end(); ++iter)
+        (*iter)->addRegistrationNodesToSet(observedNodes);
+    return observedNodes;
+}
+
+bool MutationObserver::canDeliver()
+{
+    return !m_callback->scriptExecutionContext()->activeDOMObjectsAreSuspended();
+}
+
+void MutationObserver::deliver()
+{
+    ASSERT(canDeliver());
+
+    // Calling clearTransientRegistrations() can modify m_registrations, so it's necessary
+    // to make a copy of the transient registrations before operating on them.
+    Vector<MutationObserverRegistration*, 1> transientRegistrations;
+    for (HashSet<MutationObserverRegistration*>::iterator iter = m_registrations.begin(); iter != m_registrations.end(); ++iter) {
+        if ((*iter)->hasTransientRegistrations())
+            transientRegistrations.append(*iter);
+    }
+    for (size_t i = 0; i < transientRegistrations.size(); ++i)
+        transientRegistrations[i]->clearTransientRegistrations();
+
+    if (m_records.isEmpty())
+        return;
+
+    Vector<RefPtr<MutationRecord> > records;
+    records.swap(m_records);
+
+    m_callback->call(records, this);
+}
+
+void MutationObserver::deliverAllMutations()
+{
+    ASSERT(isMainThread());
+    static bool deliveryInProgress = false;
+    if (deliveryInProgress)
+        return;
+    deliveryInProgress = true;
+
+    if (!suspendedMutationObservers().isEmpty()) {
+        Vector<RefPtr<MutationObserver> > suspended;
+        copyToVector(suspendedMutationObservers(), suspended);
+        for (size_t i = 0; i < suspended.size(); ++i) {
+            if (!suspended[i]->canDeliver())
+                continue;
+
+            suspendedMutationObservers().remove(suspended[i]);
+            activeMutationObservers().add(suspended[i]);
+        }
+    }
+
+    while (!activeMutationObservers().isEmpty()) {
+        Vector<RefPtr<MutationObserver> > observers;
+        copyToVector(activeMutationObservers(), observers);
+        activeMutationObservers().clear();
+        std::sort(observers.begin(), observers.end(), ObserverLessThan());
+        for (size_t i = 0; i < observers.size(); ++i) {
+            if (observers[i]->canDeliver())
+                observers[i]->deliver();
+            else
+                suspendedMutationObservers().add(observers[i]);
+        }
+    }
+
+    deliveryInProgress = false;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/MutationObserver.h b/Source/core/dom/MutationObserver.h
new file mode 100644
index 0000000..6d31277
--- /dev/null
+++ b/Source/core/dom/MutationObserver.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MutationObserver_h
+#define MutationObserver_h
+
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/AtomicStringHash.h>
+
+namespace WebCore {
+
+class Dictionary;
+class MutationCallback;
+class MutationObserverRegistration;
+class MutationRecord;
+class Node;
+
+typedef int ExceptionCode;
+
+typedef unsigned char MutationObserverOptions;
+typedef unsigned char MutationRecordDeliveryOptions;
+
+class MutationObserver : public RefCounted<MutationObserver> {
+public:
+    enum MutationType {
+        ChildList = 1 << 0,
+        Attributes = 1 << 1,
+        CharacterData = 1 << 2,
+
+        AllMutationTypes = ChildList | Attributes | CharacterData
+    };
+
+    enum ObservationFlags  {
+        Subtree = 1 << 3,
+        AttributeFilter = 1 << 4
+    };
+
+    enum DeliveryFlags {
+        AttributeOldValue = 1 << 5,
+        CharacterDataOldValue = 1 << 6,
+    };
+
+    static PassRefPtr<MutationObserver> create(PassRefPtr<MutationCallback>);
+    static void deliverAllMutations();
+
+    ~MutationObserver();
+
+    void observe(Node*, const Dictionary&, ExceptionCode&);
+    Vector<RefPtr<MutationRecord> > takeRecords();
+    void disconnect();
+    void observationStarted(MutationObserverRegistration*);
+    void observationEnded(MutationObserverRegistration*);
+    void enqueueMutationRecord(PassRefPtr<MutationRecord>);
+    void setHasTransientRegistration();
+    bool canDeliver();
+
+    HashSet<Node*> getObservedNodes() const;
+
+private:
+    struct ObserverLessThan;
+
+    explicit MutationObserver(PassRefPtr<MutationCallback>);
+    void deliver();
+
+    static bool validateOptions(MutationObserverOptions);
+
+    RefPtr<MutationCallback> m_callback;
+    Vector<RefPtr<MutationRecord> > m_records;
+    HashSet<MutationObserverRegistration*> m_registrations;
+    unsigned m_priority;
+};
+
+}
+
+#endif // MutationObserver_h
diff --git a/Source/core/dom/MutationObserver.idl b/Source/core/dom/MutationObserver.idl
new file mode 100644
index 0000000..6df62b7
--- /dev/null
+++ b/Source/core/dom/MutationObserver.idl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    CustomConstructor(MutationCallback callback),
+    ImplementationLacksVTable
+] interface MutationObserver {
+    [RaisesException] void observe(Node target, Dictionary options);
+    sequence<MutationRecord> takeRecords();
+    void disconnect();
+};
diff --git a/Source/core/dom/MutationObserverInterestGroup.cpp b/Source/core/dom/MutationObserverInterestGroup.cpp
new file mode 100644
index 0000000..e018157
--- /dev/null
+++ b/Source/core/dom/MutationObserverInterestGroup.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "core/dom/MutationObserverInterestGroup.h"
+
+#include "core/dom/MutationObserverRegistration.h"
+#include "core/dom/MutationRecord.h"
+#include "core/dom/Node.h"
+#include "core/dom/QualifiedName.h"
+
+namespace WebCore {
+
+PassOwnPtr<MutationObserverInterestGroup> MutationObserverInterestGroup::createIfNeeded(Node* target, MutationObserver::MutationType type, MutationRecordDeliveryOptions oldValueFlag, const QualifiedName* attributeName)
+{
+    ASSERT((type == MutationObserver::Attributes && attributeName) || !attributeName);
+    HashMap<MutationObserver*, MutationRecordDeliveryOptions> observers;
+    target->getRegisteredMutationObserversOfType(observers, type, attributeName);
+    if (observers.isEmpty())
+        return nullptr;
+
+    return adoptPtr(new MutationObserverInterestGroup(observers, oldValueFlag));
+}
+
+MutationObserverInterestGroup::MutationObserverInterestGroup(HashMap<MutationObserver*, MutationRecordDeliveryOptions>& observers, MutationRecordDeliveryOptions oldValueFlag)
+    : m_oldValueFlag(oldValueFlag)
+{
+    ASSERT(!observers.isEmpty());
+    m_observers.swap(observers);
+}
+
+bool MutationObserverInterestGroup::isOldValueRequested()
+{
+    for (HashMap<MutationObserver*, MutationRecordDeliveryOptions>::iterator iter = m_observers.begin(); iter != m_observers.end(); ++iter) {
+        if (hasOldValue(iter->value))
+            return true;
+    }
+    return false;
+}
+
+void MutationObserverInterestGroup::enqueueMutationRecord(PassRefPtr<MutationRecord> prpMutation)
+{
+    RefPtr<MutationRecord> mutation = prpMutation;
+    RefPtr<MutationRecord> mutationWithNullOldValue;
+    for (HashMap<MutationObserver*, MutationRecordDeliveryOptions>::iterator iter = m_observers.begin(); iter != m_observers.end(); ++iter) {
+        MutationObserver* observer = iter->key;
+        if (hasOldValue(iter->value)) {
+            observer->enqueueMutationRecord(mutation);
+            continue;
+        }
+        if (!mutationWithNullOldValue) {
+            if (mutation->oldValue().isNull())
+                mutationWithNullOldValue = mutation;
+            else
+                mutationWithNullOldValue = MutationRecord::createWithNullOldValue(mutation).get();
+        }
+        observer->enqueueMutationRecord(mutationWithNullOldValue);
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/MutationObserverInterestGroup.h b/Source/core/dom/MutationObserverInterestGroup.h
new file mode 100644
index 0000000..981c6e1
--- /dev/null
+++ b/Source/core/dom/MutationObserverInterestGroup.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MutationObserverInterestGroup_h
+#define MutationObserverInterestGroup_h
+
+#include "core/dom/Document.h"
+#include "core/dom/MutationObserver.h"
+#include "core/dom/Node.h"
+#include "core/dom/QualifiedName.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class MutationObserverInterestGroup {
+public:
+    static PassOwnPtr<MutationObserverInterestGroup> createForChildListMutation(Node* target)
+    {
+        if (!target->document()->hasMutationObserversOfType(MutationObserver::ChildList))
+            return nullptr;
+
+        MutationRecordDeliveryOptions oldValueFlag = 0;
+        return createIfNeeded(target, MutationObserver::ChildList, oldValueFlag);
+    }
+
+    static PassOwnPtr<MutationObserverInterestGroup> createForCharacterDataMutation(Node* target)
+    {
+        if (!target->document()->hasMutationObserversOfType(MutationObserver::CharacterData))
+            return nullptr;
+
+        return createIfNeeded(target, MutationObserver::CharacterData, MutationObserver::CharacterDataOldValue);
+    }
+
+    static PassOwnPtr<MutationObserverInterestGroup> createForAttributesMutation(Node* target, const QualifiedName& attributeName)
+    {
+        if (!target->document()->hasMutationObserversOfType(MutationObserver::Attributes))
+            return nullptr;
+
+        return createIfNeeded(target, MutationObserver::Attributes, MutationObserver::AttributeOldValue, &attributeName);
+    }
+
+    bool isOldValueRequested();
+    void enqueueMutationRecord(PassRefPtr<MutationRecord>);
+
+private:
+    static PassOwnPtr<MutationObserverInterestGroup> createIfNeeded(Node* target, MutationObserver::MutationType, MutationRecordDeliveryOptions oldValueFlag, const QualifiedName* attributeName = 0);
+    MutationObserverInterestGroup(HashMap<MutationObserver*, MutationRecordDeliveryOptions>& observers, MutationRecordDeliveryOptions oldValueFlag);
+
+    bool hasOldValue(MutationRecordDeliveryOptions options) { return options & m_oldValueFlag; }
+
+    HashMap<MutationObserver*, MutationRecordDeliveryOptions> m_observers;
+    MutationRecordDeliveryOptions m_oldValueFlag;
+};
+
+}
+
+#endif // MutationObserverInterestGroup_h
diff --git a/Source/core/dom/MutationObserverRegistration.cpp b/Source/core/dom/MutationObserverRegistration.cpp
new file mode 100644
index 0000000..f2b85a0
--- /dev/null
+++ b/Source/core/dom/MutationObserverRegistration.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "core/dom/MutationObserverRegistration.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/Node.h"
+#include "core/dom/QualifiedName.h"
+
+namespace WebCore {
+
+PassOwnPtr<MutationObserverRegistration> MutationObserverRegistration::create(PassRefPtr<MutationObserver> observer, Node* registrationNode, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter)
+{
+    return adoptPtr(new MutationObserverRegistration(observer, registrationNode, options, attributeFilter));
+}
+
+MutationObserverRegistration::MutationObserverRegistration(PassRefPtr<MutationObserver> observer, Node* registrationNode, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter)
+    : m_observer(observer)
+    , m_registrationNode(registrationNode)
+    , m_options(options)
+    , m_attributeFilter(attributeFilter)
+{
+    m_observer->observationStarted(this);
+}
+
+MutationObserverRegistration::~MutationObserverRegistration()
+{
+    clearTransientRegistrations();
+    m_observer->observationEnded(this);
+}
+
+void MutationObserverRegistration::resetObservation(MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter)
+{
+    clearTransientRegistrations();
+    m_options = options;
+    m_attributeFilter = attributeFilter;
+}
+
+void MutationObserverRegistration::observedSubtreeNodeWillDetach(Node* node)
+{
+    if (!isSubtree())
+        return;
+
+    node->registerTransientMutationObserver(this);
+    m_observer->setHasTransientRegistration();
+
+    if (!m_transientRegistrationNodes) {
+        m_transientRegistrationNodes = adoptPtr(new NodeHashSet);
+
+        ASSERT(!m_registrationNodeKeepAlive);
+        m_registrationNodeKeepAlive = m_registrationNode; // Balanced in clearTransientRegistrations.
+    }
+    m_transientRegistrationNodes->add(node);
+}
+
+void MutationObserverRegistration::clearTransientRegistrations()
+{
+    if (!m_transientRegistrationNodes) {
+        ASSERT(!m_registrationNodeKeepAlive);
+        return;
+    }
+
+    for (NodeHashSet::iterator iter = m_transientRegistrationNodes->begin(); iter != m_transientRegistrationNodes->end(); ++iter)
+        (*iter)->unregisterTransientMutationObserver(this);
+
+    m_transientRegistrationNodes.clear();
+
+    ASSERT(m_registrationNodeKeepAlive);
+    m_registrationNodeKeepAlive = 0; // Balanced in observeSubtreeNodeWillDetach.
+}
+
+void MutationObserverRegistration::unregister()
+{
+    m_registrationNode->unregisterMutationObserver(this);
+    // The above line will cause this object to be deleted, so don't do any more in this function.
+}
+
+bool MutationObserverRegistration::shouldReceiveMutationFrom(Node* node, MutationObserver::MutationType type, const QualifiedName* attributeName) const
+{
+    ASSERT((type == MutationObserver::Attributes && attributeName) || !attributeName);
+    if (!(m_options & type))
+        return false;
+
+    if (m_registrationNode != node && !isSubtree())
+        return false;
+
+    if (type != MutationObserver::Attributes || !(m_options & MutationObserver::AttributeFilter))
+        return true;
+
+    if (!attributeName->namespaceURI().isNull())
+        return false;
+
+    return m_attributeFilter.contains(attributeName->localName());
+}
+
+void MutationObserverRegistration::addRegistrationNodesToSet(HashSet<Node*>& nodes) const
+{
+    nodes.add(m_registrationNode);
+    if (!m_transientRegistrationNodes)
+        return;
+    for (NodeHashSet::const_iterator iter = m_transientRegistrationNodes->begin(); iter != m_transientRegistrationNodes->end(); ++iter)
+        nodes.add(iter->get());
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/MutationObserverRegistration.h b/Source/core/dom/MutationObserverRegistration.h
new file mode 100644
index 0000000..b17d95a
--- /dev/null
+++ b/Source/core/dom/MutationObserverRegistration.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MutationObserverRegistration_h
+#define MutationObserverRegistration_h
+
+#include "core/dom/MutationObserver.h"
+#include <wtf/HashSet.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/AtomicStringHash.h>
+
+namespace WebCore {
+
+class QualifiedName;
+
+class MutationObserverRegistration {
+public:
+    static PassOwnPtr<MutationObserverRegistration> create(PassRefPtr<MutationObserver>, Node*, MutationObserverOptions, const HashSet<AtomicString>& attributeFilter);
+    ~MutationObserverRegistration();
+
+    void resetObservation(MutationObserverOptions, const HashSet<AtomicString>& attributeFilter);
+    void observedSubtreeNodeWillDetach(Node*);
+    void clearTransientRegistrations();
+    bool hasTransientRegistrations() const { return m_transientRegistrationNodes && !m_transientRegistrationNodes->isEmpty(); }
+    void unregister();
+
+    bool shouldReceiveMutationFrom(Node*, MutationObserver::MutationType, const QualifiedName* attributeName) const;
+    bool isSubtree() const { return m_options & MutationObserver::Subtree; }
+
+    MutationObserver* observer() const { return m_observer.get(); }
+    MutationRecordDeliveryOptions deliveryOptions() const { return m_options & (MutationObserver::AttributeOldValue | MutationObserver::CharacterDataOldValue); }
+    MutationObserverOptions mutationTypes() const { return m_options & MutationObserver::AllMutationTypes; }
+
+    void addRegistrationNodesToSet(HashSet<Node*>&) const;
+
+private:
+    MutationObserverRegistration(PassRefPtr<MutationObserver>, Node*, MutationObserverOptions, const HashSet<AtomicString>& attributeFilter);
+
+    RefPtr<MutationObserver> m_observer;
+    Node* m_registrationNode;
+    RefPtr<Node> m_registrationNodeKeepAlive;
+    typedef HashSet<RefPtr<Node> > NodeHashSet;
+    OwnPtr<NodeHashSet> m_transientRegistrationNodes;
+
+    MutationObserverOptions m_options;
+    HashSet<AtomicString> m_attributeFilter;
+};
+
+} // namespace WebCore
+
+#endif // MutationObserverRegistration_h
diff --git a/Source/core/dom/MutationRecord.cpp b/Source/core/dom/MutationRecord.cpp
new file mode 100644
index 0000000..cc3b05a
--- /dev/null
+++ b/Source/core/dom/MutationRecord.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "core/dom/MutationRecord.h"
+
+#include "core/dom/Node.h"
+#include "core/dom/NodeList.h"
+#include "core/dom/QualifiedName.h"
+#include "core/dom/StaticNodeList.h"
+#include <wtf/Assertions.h>
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+namespace {
+
+class ChildListRecord : public MutationRecord {
+public:
+    ChildListRecord(PassRefPtr<Node> target, PassRefPtr<NodeList> added, PassRefPtr<NodeList> removed, PassRefPtr<Node> previousSibling, PassRefPtr<Node> nextSibling)
+        : m_target(target)
+        , m_addedNodes(added)
+        , m_removedNodes(removed)
+        , m_previousSibling(previousSibling)
+        , m_nextSibling(nextSibling)
+    {
+    }
+
+private:
+    virtual const AtomicString& type() OVERRIDE;
+    virtual Node* target() OVERRIDE { return m_target.get(); }
+    virtual NodeList* addedNodes() OVERRIDE { return m_addedNodes.get(); }
+    virtual NodeList* removedNodes() OVERRIDE { return m_removedNodes.get(); }
+    virtual Node* previousSibling() OVERRIDE { return m_previousSibling.get(); }
+    virtual Node* nextSibling() OVERRIDE { return m_nextSibling.get(); }
+
+    RefPtr<Node> m_target;
+    RefPtr<NodeList> m_addedNodes;
+    RefPtr<NodeList> m_removedNodes;
+    RefPtr<Node> m_previousSibling;
+    RefPtr<Node> m_nextSibling;
+};
+
+class RecordWithEmptyNodeLists : public MutationRecord {
+public:
+    RecordWithEmptyNodeLists(PassRefPtr<Node> target, const String& oldValue)
+        : m_target(target)
+        , m_oldValue(oldValue)
+    {
+    }
+
+private:
+    virtual Node* target() OVERRIDE { return m_target.get(); }
+    virtual String oldValue() OVERRIDE { return m_oldValue; }
+    virtual NodeList* addedNodes() OVERRIDE { return lazilyInitializeEmptyNodeList(m_addedNodes); }
+    virtual NodeList* removedNodes() OVERRIDE { return lazilyInitializeEmptyNodeList(m_removedNodes); }
+
+    static NodeList* lazilyInitializeEmptyNodeList(RefPtr<NodeList>& nodeList)
+    {
+        if (!nodeList)
+            nodeList = StaticNodeList::createEmpty();
+        return nodeList.get();
+    }
+
+    RefPtr<Node> m_target;
+    String m_oldValue;
+    RefPtr<NodeList> m_addedNodes;
+    RefPtr<NodeList> m_removedNodes;
+};
+
+class AttributesRecord : public RecordWithEmptyNodeLists {
+public:
+    AttributesRecord(PassRefPtr<Node> target, const QualifiedName& name, const AtomicString& oldValue)
+        : RecordWithEmptyNodeLists(target, oldValue)
+        , m_attributeName(name.localName())
+        , m_attributeNamespace(name.namespaceURI())
+    {
+    }
+
+private:
+    virtual const AtomicString& type() OVERRIDE;
+    virtual const AtomicString& attributeName() OVERRIDE { return m_attributeName; }
+    virtual const AtomicString& attributeNamespace() OVERRIDE { return m_attributeNamespace; }
+
+    AtomicString m_attributeName;
+    AtomicString m_attributeNamespace;
+};
+
+class CharacterDataRecord : public RecordWithEmptyNodeLists {
+public:
+    CharacterDataRecord(PassRefPtr<Node> target, const String& oldValue)
+        : RecordWithEmptyNodeLists(target, oldValue)
+    {
+    }
+
+private:
+    virtual const AtomicString& type() OVERRIDE;
+};
+
+class MutationRecordWithNullOldValue : public MutationRecord {
+public:
+    MutationRecordWithNullOldValue(PassRefPtr<MutationRecord> record)
+        : m_record(record)
+    {
+    }
+
+private:
+    virtual const AtomicString& type() OVERRIDE { return m_record->type(); }
+    virtual Node* target() OVERRIDE { return m_record->target(); }
+    virtual NodeList* addedNodes() OVERRIDE { return m_record->addedNodes(); }
+    virtual NodeList* removedNodes() OVERRIDE { return m_record->removedNodes(); }
+    virtual Node* previousSibling() OVERRIDE { return m_record->previousSibling(); }
+    virtual Node* nextSibling() OVERRIDE { return m_record->nextSibling(); }
+    virtual const AtomicString& attributeName() OVERRIDE { return m_record->attributeName(); }
+    virtual const AtomicString& attributeNamespace() OVERRIDE { return m_record->attributeNamespace(); }
+
+    virtual String oldValue() OVERRIDE { return String(); }
+
+    RefPtr<MutationRecord> m_record;
+};
+
+const AtomicString& ChildListRecord::type()
+{
+    DEFINE_STATIC_LOCAL(AtomicString, childList, ("childList", AtomicString::ConstructFromLiteral));
+    return childList;
+}
+
+const AtomicString& AttributesRecord::type()
+{
+    DEFINE_STATIC_LOCAL(AtomicString, attributes, ("attributes", AtomicString::ConstructFromLiteral));
+    return attributes;
+}
+
+const AtomicString& CharacterDataRecord::type()
+{
+    DEFINE_STATIC_LOCAL(AtomicString, characterData, ("characterData", AtomicString::ConstructFromLiteral));
+    return characterData;
+}
+
+} // namespace
+
+PassRefPtr<MutationRecord> MutationRecord::createChildList(PassRefPtr<Node> target, PassRefPtr<NodeList> added, PassRefPtr<NodeList> removed, PassRefPtr<Node> previousSibling, PassRefPtr<Node> nextSibling)
+{
+    return adoptRef(static_cast<MutationRecord*>(new ChildListRecord(target, added, removed, previousSibling, nextSibling)));
+}
+
+PassRefPtr<MutationRecord> MutationRecord::createAttributes(PassRefPtr<Node> target, const QualifiedName& name, const AtomicString& oldValue)
+{
+    return adoptRef(static_cast<MutationRecord*>(new AttributesRecord(target, name, oldValue)));
+}
+
+PassRefPtr<MutationRecord> MutationRecord::createCharacterData(PassRefPtr<Node> target, const String& oldValue)
+{
+    return adoptRef(static_cast<MutationRecord*>(new CharacterDataRecord(target, oldValue)));
+}
+
+PassRefPtr<MutationRecord> MutationRecord::createWithNullOldValue(PassRefPtr<MutationRecord> record)
+{
+    return adoptRef(static_cast<MutationRecord*>(new MutationRecordWithNullOldValue(record)));
+}
+
+MutationRecord::~MutationRecord()
+{
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/MutationRecord.h b/Source/core/dom/MutationRecord.h
new file mode 100644
index 0000000..4606df0
--- /dev/null
+++ b/Source/core/dom/MutationRecord.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MutationRecord_h
+#define MutationRecord_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class Node;
+class NodeList;
+class QualifiedName;
+
+class MutationRecord : public RefCounted<MutationRecord> {
+public:
+    static PassRefPtr<MutationRecord> createChildList(PassRefPtr<Node> target, PassRefPtr<NodeList> added, PassRefPtr<NodeList> removed, PassRefPtr<Node> previousSibling, PassRefPtr<Node> nextSibling);
+    static PassRefPtr<MutationRecord> createAttributes(PassRefPtr<Node> target, const QualifiedName&, const AtomicString& oldValue);
+    static PassRefPtr<MutationRecord> createCharacterData(PassRefPtr<Node> target, const String& oldValue);
+
+    static PassRefPtr<MutationRecord> createWithNullOldValue(PassRefPtr<MutationRecord>);
+
+    virtual ~MutationRecord();
+
+    virtual const AtomicString& type() = 0;
+    virtual Node* target() = 0;
+
+    virtual NodeList* addedNodes() = 0;
+    virtual NodeList* removedNodes() = 0;
+    virtual Node* previousSibling() { return 0; }
+    virtual Node* nextSibling() { return 0; }
+
+    virtual const AtomicString& attributeName() { return nullAtom; }
+    virtual const AtomicString& attributeNamespace() { return nullAtom; }
+
+    virtual String oldValue() { return String(); }
+};
+
+} // namespace WebCore
+
+#endif // MutationRecord_h
diff --git a/Source/core/dom/MutationRecord.idl b/Source/core/dom/MutationRecord.idl
new file mode 100644
index 0000000..2002d1d
--- /dev/null
+++ b/Source/core/dom/MutationRecord.idl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    SkipVTableValidation
+] interface MutationRecord {
+    readonly attribute DOMString type;
+    readonly attribute Node target;
+
+    readonly attribute NodeList addedNodes;
+    readonly attribute NodeList removedNodes;
+    readonly attribute Node previousSibling;
+    readonly attribute Node nextSibling;
+
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString attributeName;
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString attributeNamespace;
+
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString oldValue;
+};
diff --git a/Source/core/dom/NameNodeList.cpp b/Source/core/dom/NameNodeList.cpp
new file mode 100644
index 0000000..2323d75
--- /dev/null
+++ b/Source/core/dom/NameNodeList.cpp
@@ -0,0 +1,51 @@
+/**
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2007 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/NameNodeList.h"
+
+#include "HTMLNames.h"
+#include "core/dom/Element.h"
+#include "core/dom/NodeRareData.h"
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+NameNodeList::NameNodeList(PassRefPtr<Node> rootNode, const AtomicString& name)
+    : LiveNodeList(rootNode, NameNodeListType, InvalidateOnNameAttrChange)
+    , m_name(name)
+{
+}
+
+NameNodeList::~NameNodeList()
+{
+    ownerNode()->nodeLists()->removeCacheWithAtomicName(this, NameNodeListType, m_name);
+} 
+
+bool NameNodeList::nodeMatches(Element* testNode) const
+{
+    return testNode->getNameAttribute() == m_name;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/NameNodeList.h b/Source/core/dom/NameNodeList.h
new file mode 100644
index 0000000..32c1eff
--- /dev/null
+++ b/Source/core/dom/NameNodeList.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2007m 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NameNodeList_h
+#define NameNodeList_h
+
+#include "core/dom/LiveNodeList.h"
+#include <wtf/Forward.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+// NodeList which lists all Nodes in a Element with a given "name" attribute
+class NameNodeList : public LiveNodeList {
+public:
+    static PassRefPtr<NameNodeList> create(PassRefPtr<Node> rootNode, CollectionType type, const AtomicString& name)
+    {
+        ASSERT_UNUSED(type, type == NameNodeListType);
+        return adoptRef(new NameNodeList(rootNode, name));
+    }
+
+    virtual ~NameNodeList();
+
+private:
+    NameNodeList(PassRefPtr<Node> rootNode, const AtomicString& name);
+
+    virtual bool nodeMatches(Element*) const;
+
+    AtomicString m_name;
+};
+
+} // namespace WebCore
+
+#endif // NameNodeList_h
diff --git a/Source/core/dom/NamedFlow.cpp b/Source/core/dom/NamedFlow.cpp
new file mode 100644
index 0000000..871c633
--- /dev/null
+++ b/Source/core/dom/NamedFlow.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2011 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 HOLDER 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 "core/dom/NamedFlow.h"
+
+#include "RuntimeEnabledFeatures.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/NamedFlowCollection.h"
+#include "core/dom/ScriptExecutionContext.h"
+#include "core/dom/StaticNodeList.h"
+#include "core/dom/UIEvent.h"
+#include "core/rendering/RenderNamedFlowThread.h"
+#include "core/rendering/RenderRegion.h"
+
+namespace WebCore {
+
+NamedFlow::NamedFlow(PassRefPtr<NamedFlowCollection> manager, const AtomicString& flowThreadName)
+    : m_flowThreadName(flowThreadName)
+    , m_flowManager(manager)
+    , m_parentFlowThread(0)
+{
+    ASSERT(RuntimeEnabledFeatures::cssRegionsEnabled());
+}
+
+NamedFlow::~NamedFlow()
+{
+    // The named flow is not "strong" referenced from anywhere at this time so it shouldn't be reused if the named flow is recreated.
+    m_flowManager->discardNamedFlow(this);
+}
+
+PassRefPtr<NamedFlow> NamedFlow::create(PassRefPtr<NamedFlowCollection> manager, const AtomicString& flowThreadName)
+{
+    return adoptRef(new NamedFlow(manager, flowThreadName));
+}
+
+const AtomicString& NamedFlow::name() const
+{
+    return m_flowThreadName;
+}
+
+bool NamedFlow::overset() const
+{
+    if (m_flowManager->document())
+        m_flowManager->document()->updateLayoutIgnorePendingStylesheets();
+
+    // The renderer may be destroyed or created after the style update.
+    // Because this is called from JS, where the wrapper keeps a reference to the NamedFlow, no guard is necessary.
+    return m_parentFlowThread ? m_parentFlowThread->overset() : true;
+}
+
+static inline bool inFlowThread(RenderObject* renderer, RenderNamedFlowThread* flowThread)
+{
+    if (!renderer)
+        return false;
+    RenderFlowThread* currentFlowThread = renderer->flowThreadContainingBlock();
+    if (flowThread == currentFlowThread)
+        return true;
+    if (renderer->flowThreadState() != RenderObject::InsideInFlowThread)
+        return false;
+
+    // An in-flow flow thread can be nested inside an out-of-flow one, so we have to recur up to check.
+    return inFlowThread(currentFlowThread->containingBlock(), flowThread);
+}
+
+int NamedFlow::firstEmptyRegionIndex() const
+{
+    if (m_flowManager->document())
+        m_flowManager->document()->updateLayoutIgnorePendingStylesheets();
+
+    if (!m_parentFlowThread)
+        return -1;
+
+    const RenderRegionList& regionList = m_parentFlowThread->renderRegionList();
+    if (regionList.isEmpty())
+        return -1;
+    RenderRegionList::const_iterator iter = regionList.begin();
+    for (int index = 0; iter != regionList.end(); ++index, ++iter) {
+        const RenderRegion* renderRegion = *iter;
+        if (renderRegion->regionState() == RenderRegion::RegionEmpty)
+            return index;
+    }
+    return -1;
+}
+
+PassRefPtr<NodeList> NamedFlow::getRegionsByContent(Node* contentNode)
+{
+    Vector<RefPtr<Node> > regionNodes;
+
+    if (!contentNode)
+        return StaticNodeList::adopt(regionNodes);
+
+    if (m_flowManager->document())
+        m_flowManager->document()->updateLayoutIgnorePendingStylesheets();
+
+    // The renderer may be destroyed or created after the style update.
+    // Because this is called from JS, where the wrapper keeps a reference to the NamedFlow, no guard is necessary.
+    if (!m_parentFlowThread)
+        return StaticNodeList::adopt(regionNodes);
+
+    if (inFlowThread(contentNode->renderer(), m_parentFlowThread)) {
+        const RenderRegionList& regionList = m_parentFlowThread->renderRegionList();
+        for (RenderRegionList::const_iterator iter = regionList.begin(); iter != regionList.end(); ++iter) {
+            const RenderRegion* renderRegion = *iter;
+            // FIXME: Pseudo-elements are not included in the list.
+            if (!renderRegion->node())
+                continue;
+            if (m_parentFlowThread->objectInFlowRegion(contentNode->renderer(), renderRegion))
+                regionNodes.append(renderRegion->node());
+        }
+    }
+
+    return StaticNodeList::adopt(regionNodes);
+}
+
+PassRefPtr<NodeList> NamedFlow::getRegions()
+{
+    Vector<RefPtr<Node> > regionNodes;
+
+    if (m_flowManager->document())
+        m_flowManager->document()->updateLayoutIgnorePendingStylesheets();
+
+    // The renderer may be destroyed or created after the style update.
+    // Because this is called from JS, where the wrapper keeps a reference to the NamedFlow, no guard is necessary.
+    if (!m_parentFlowThread)
+        return StaticNodeList::adopt(regionNodes);
+
+    const RenderRegionList& regionList = m_parentFlowThread->renderRegionList();
+    for (RenderRegionList::const_iterator iter = regionList.begin(); iter != regionList.end(); ++iter) {
+        const RenderRegion* renderRegion = *iter;
+        // FIXME: Pseudo-elements are not included in the list.
+        if (!renderRegion->node())
+            continue;
+        regionNodes.append(renderRegion->node());
+    }
+
+    return StaticNodeList::adopt(regionNodes);
+}
+
+PassRefPtr<NodeList> NamedFlow::getContent()
+{
+    Vector<RefPtr<Node> > contentNodes;
+
+    if (m_flowManager->document())
+        m_flowManager->document()->updateLayoutIgnorePendingStylesheets();
+
+    // The renderer may be destroyed or created after the style update.
+    // Because this is called from JS, where the wrapper keeps a reference to the NamedFlow, no guard is necessary.
+    if (!m_parentFlowThread)
+        return StaticNodeList::adopt(contentNodes);
+
+    const NamedFlowContentNodes& contentNodesList = m_parentFlowThread->contentNodes();
+    for (NamedFlowContentNodes::const_iterator it = contentNodesList.begin(); it != contentNodesList.end(); ++it) {
+        Node* node = *it;
+        ASSERT(node->computedStyle()->flowThread() == m_parentFlowThread->flowThreadName());
+        contentNodes.append(node);
+    }
+
+    return StaticNodeList::adopt(contentNodes);
+}
+
+void NamedFlow::setRenderer(RenderNamedFlowThread* parentFlowThread)
+{
+    // The named flow can either go from a no_renderer->renderer or renderer->no_renderer state; anything else could indicate a bug.
+    ASSERT((!m_parentFlowThread && parentFlowThread) || (m_parentFlowThread && !parentFlowThread));
+
+    // If parentFlowThread is 0, the flow thread will move in the "NULL" state.
+    m_parentFlowThread = parentFlowThread;
+}
+
+EventTargetData* NamedFlow::eventTargetData()
+{
+    return &m_eventTargetData;
+}
+
+EventTargetData* NamedFlow::ensureEventTargetData()
+{
+    return &m_eventTargetData;
+}
+
+void NamedFlow::dispatchRegionLayoutUpdateEvent()
+{
+    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
+
+    // If the flow is in the "NULL" state the event should not be dispatched any more.
+    if (flowState() == FlowStateNull)
+        return;
+
+    RefPtr<Event> event = UIEvent::create(eventNames().webkitregionlayoutupdateEvent, false, false, m_flowManager->document()->defaultView(), 0);
+
+    dispatchEvent(event);
+}
+
+const AtomicString& NamedFlow::interfaceName() const
+{
+    return eventNames().interfaceForNamedFlow;
+}
+
+ScriptExecutionContext* NamedFlow::scriptExecutionContext() const
+{
+    return m_flowManager->document();
+}
+
+Node* NamedFlow::ownerNode() const
+{
+    return m_flowManager->document();
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/dom/NamedFlow.h b/Source/core/dom/NamedFlow.h
new file mode 100644
index 0000000..8cf206e
--- /dev/null
+++ b/Source/core/dom/NamedFlow.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2011 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 HOLDER 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 NamedFlow_h
+#define NamedFlow_h
+
+#include "core/dom/EventTarget.h"
+
+#include <wtf/ListHashSet.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class Document;
+class NamedFlowCollection;
+class Node;
+class NodeList;
+class RenderNamedFlowThread;
+class ScriptExecutionContext;
+
+class NamedFlow : public RefCounted<NamedFlow>, public EventTarget {
+public:
+    static PassRefPtr<NamedFlow> create(PassRefPtr<NamedFlowCollection> manager, const AtomicString& flowThreadName);
+
+    ~NamedFlow();
+
+    const AtomicString& name() const;
+    bool overset() const;
+    int firstEmptyRegionIndex() const;
+    PassRefPtr<NodeList> getRegionsByContent(Node*);
+    PassRefPtr<NodeList> getRegions();
+    PassRefPtr<NodeList> getContent();
+
+    using RefCounted<NamedFlow>::ref;
+    using RefCounted<NamedFlow>::deref;
+
+    virtual const AtomicString& interfaceName() const;
+    virtual ScriptExecutionContext* scriptExecutionContext() const;
+
+    // This function is called from the JS binding code to determine if the NamedFlow object is reachable or not.
+    // If the object has listeners, the object should only be discarded if the parent Document is not reachable.
+    Node* ownerNode() const;
+
+    void setRenderer(RenderNamedFlowThread* parentFlowThread);
+
+    enum FlowState {
+        FlowStateCreated,
+        FlowStateNull
+    };
+
+    FlowState flowState() const { return m_parentFlowThread ? FlowStateCreated : FlowStateNull; }
+
+    void dispatchRegionLayoutUpdateEvent();
+
+private:
+    NamedFlow(PassRefPtr<NamedFlowCollection>, const AtomicString&);
+
+    // EventTarget implementation.
+    virtual void refEventTarget() { ref(); }
+    virtual void derefEventTarget() { deref(); }
+
+    virtual EventTargetData* eventTargetData() OVERRIDE;
+    virtual EventTargetData* ensureEventTargetData() OVERRIDE;
+
+    // The name of the flow thread as specified in CSS.
+    AtomicString m_flowThreadName;
+
+    RefPtr<NamedFlowCollection> m_flowManager;
+    RenderNamedFlowThread* m_parentFlowThread;
+
+    EventTargetData m_eventTargetData;
+};
+
+}
+
+#endif
diff --git a/Source/core/dom/NamedFlow.idl b/Source/core/dom/NamedFlow.idl
new file mode 100644
index 0000000..b7e09e5
--- /dev/null
+++ b/Source/core/dom/NamedFlow.idl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 HOLDER 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.
+ */
+
+[
+    EnabledAtRuntime=cssRegions,
+    EventTarget,
+    InterfaceName=WebKitNamedFlow,
+    GenerateIsReachable=ImplOwnerNodeRoot
+] interface NamedFlow {
+    readonly attribute DOMString name;
+    readonly attribute boolean overset;
+    readonly attribute long firstEmptyRegionIndex;
+    NodeList getRegionsByContent(Node contentNode);
+    NodeList getRegions();
+    NodeList getContent();
+
+    // EventTarget interface
+    void addEventListener(DOMString type, 
+                          EventListener listener, 
+                          optional boolean useCapture);
+    void removeEventListener(DOMString type, 
+                             EventListener listener, 
+                             optional boolean useCapture);
+    [RaisesException] boolean dispatchEvent(Event event);
+};
diff --git a/Source/core/dom/NamedFlowCollection.cpp b/Source/core/dom/NamedFlowCollection.cpp
new file mode 100644
index 0000000..ea88831
--- /dev/null
+++ b/Source/core/dom/NamedFlowCollection.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 HOLDER 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 "core/dom/NamedFlowCollection.h"
+
+#include "RuntimeEnabledFeatures.h"
+#include "core/dom/DOMNamedFlowCollection.h"
+#include "core/dom/Document.h"
+#include "core/dom/NamedFlow.h"
+#include "core/inspector/InspectorInstrumentation.h"
+
+#include <wtf/text/StringHash.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+NamedFlowCollection::NamedFlowCollection(Document* document)
+    : ContextDestructionObserver(document)
+{
+    ASSERT(RuntimeEnabledFeatures::cssRegionsEnabled());
+}
+
+Vector<RefPtr<NamedFlow> > NamedFlowCollection::namedFlows()
+{
+    Vector<RefPtr<NamedFlow> > namedFlows;
+
+    for (NamedFlowSet::iterator it = m_namedFlows.begin(); it != m_namedFlows.end(); ++it) {
+        if ((*it)->flowState() == NamedFlow::FlowStateNull)
+            continue;
+
+        namedFlows.append(RefPtr<NamedFlow>(*it));
+    }
+
+    return namedFlows;
+}
+
+NamedFlow* NamedFlowCollection::flowByName(const String& flowName)
+{
+    NamedFlowSet::iterator it = m_namedFlows.find<String, NamedFlowHashTranslator>(flowName);
+    if (it == m_namedFlows.end() || (*it)->flowState() == NamedFlow::FlowStateNull)
+        return 0;
+
+    return *it;
+}
+
+PassRefPtr<NamedFlow> NamedFlowCollection::ensureFlowWithName(const String& flowName)
+{
+    NamedFlowSet::iterator it = m_namedFlows.find<String, NamedFlowHashTranslator>(flowName);
+    if (it != m_namedFlows.end()) {
+        NamedFlow* namedFlow = *it;
+        ASSERT(namedFlow->flowState() == NamedFlow::FlowStateNull);
+
+        return namedFlow;
+    }
+
+    RefPtr<NamedFlow> newFlow = NamedFlow::create(this, flowName);
+    m_namedFlows.add(newFlow.get());
+
+    InspectorInstrumentation::didCreateNamedFlow(document(), newFlow.get());
+
+    return newFlow.release();
+}
+
+void NamedFlowCollection::discardNamedFlow(NamedFlow* namedFlow)
+{
+    // The document is not valid anymore so the collection will be destroyed anyway.
+    if (!document())
+        return;
+
+    ASSERT(namedFlow->flowState() == NamedFlow::FlowStateNull);
+    ASSERT(m_namedFlows.contains(namedFlow));
+
+    InspectorInstrumentation::willRemoveNamedFlow(document(), namedFlow);
+
+    m_namedFlows.remove(namedFlow);
+}
+
+Document* NamedFlowCollection::document() const
+{
+    ScriptExecutionContext* context = ContextDestructionObserver::scriptExecutionContext();
+    return toDocument(context);
+}
+
+PassRefPtr<DOMNamedFlowCollection> NamedFlowCollection::createCSSOMSnapshot()
+{
+    Vector<NamedFlow*> createdFlows;
+    for (NamedFlowSet::iterator it = m_namedFlows.begin(); it != m_namedFlows.end(); ++it)
+        if ((*it)->flowState() == NamedFlow::FlowStateCreated)
+            createdFlows.append(*it);
+    return DOMNamedFlowCollection::create(createdFlows);
+}
+
+// The HashFunctions object used by the HashSet to compare between NamedFlows.
+// It is safe to set safeToCompareToEmptyOrDeleted because the HashSet will never contain null pointers or deleted values.
+struct NamedFlowCollection::NamedFlowHashFunctions {
+    static unsigned hash(NamedFlow* key) { return DefaultHash<String>::Hash::hash(key->name()); }
+    static bool equal(NamedFlow* a, NamedFlow* b) { return a->name() == b->name(); }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+// The HashTranslator is used to lookup a NamedFlow in the set using a name.
+struct NamedFlowCollection::NamedFlowHashTranslator {
+    static unsigned hash(const String& key) { return DefaultHash<String>::Hash::hash(key); }
+    static bool equal(NamedFlow* a, const String& b) { return a->name() == b; }
+};
+
+} // namespace WebCore
diff --git a/Source/core/dom/NamedFlowCollection.h b/Source/core/dom/NamedFlowCollection.h
new file mode 100644
index 0000000..ef163b8
--- /dev/null
+++ b/Source/core/dom/NamedFlowCollection.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 HOLDER 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 NamedFlowCollection_h
+#define NamedFlowCollection_h
+
+#include "core/dom/ContextDestructionObserver.h"
+#include "core/dom/NamedFlow.h"
+#include <wtf/Forward.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Document;
+class DOMNamedFlowCollection;
+
+class NamedFlowCollection : public RefCounted<NamedFlowCollection>, public ContextDestructionObserver {
+public:
+    static PassRefPtr<NamedFlowCollection> create(Document* doc) { return adoptRef(new NamedFlowCollection(doc)); }
+
+    Vector<RefPtr<NamedFlow> > namedFlows();
+    NamedFlow* flowByName(const String&);
+    PassRefPtr<NamedFlow> ensureFlowWithName(const String&);
+
+    void discardNamedFlow(NamedFlow*);
+
+    Document* document() const;
+
+    virtual ~NamedFlowCollection() { }
+
+    PassRefPtr<DOMNamedFlowCollection> createCSSOMSnapshot();
+
+private:
+    struct NamedFlowHashFunctions;
+    struct NamedFlowHashTranslator;
+
+    typedef ListHashSet<NamedFlow*, 1, NamedFlowHashFunctions> NamedFlowSet;
+
+    explicit NamedFlowCollection(Document*);
+
+    NamedFlowSet m_namedFlows;
+};
+
+} // namespace WebCore
+
+#endif // NamedFlowCollection_h
diff --git a/Source/core/dom/NamedNodeMap.cpp b/Source/core/dom/NamedNodeMap.cpp
new file mode 100644
index 0000000..98bddb5
--- /dev/null
+++ b/Source/core/dom/NamedNodeMap.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Peter Kelly (pmk@post.com)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
+ *           (C) 2007 Eric Seidel (eric@webkit.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/NamedNodeMap.h"
+
+#include "HTMLNames.h"
+#include "core/dom/Attr.h"
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/ExceptionCode.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+static inline bool shouldIgnoreAttributeCase(const Element* e)
+{
+    return e && e->document()->isHTMLDocument() && e->isHTMLElement();
+}
+
+void NamedNodeMap::ref()
+{
+    m_element->ref();
+}
+
+void NamedNodeMap::deref()
+{
+    m_element->deref();
+}
+
+PassRefPtr<Node> NamedNodeMap::getNamedItem(const AtomicString& name) const
+{
+    return m_element->getAttributeNode(name);
+}
+
+PassRefPtr<Node> NamedNodeMap::getNamedItemNS(const AtomicString& namespaceURI, const AtomicString& localName) const
+{
+    return m_element->getAttributeNodeNS(namespaceURI, localName);
+}
+
+PassRefPtr<Node> NamedNodeMap::removeNamedItem(const AtomicString& name, ExceptionCode& ec)
+{
+    size_t index = m_element->hasAttributes() ? m_element->getAttributeItemIndex(name, shouldIgnoreAttributeCase(m_element)) : notFound;
+    if (index == notFound) {
+        ec = NOT_FOUND_ERR;
+        return 0;
+    }
+    return m_element->detachAttribute(index);
+}
+
+PassRefPtr<Node> NamedNodeMap::removeNamedItemNS(const AtomicString& namespaceURI, const AtomicString& localName, ExceptionCode& ec)
+{
+    size_t index = m_element->hasAttributes() ? m_element->getAttributeItemIndex(QualifiedName(nullAtom, localName, namespaceURI)) : notFound;
+    if (index == notFound) {
+        ec = NOT_FOUND_ERR;
+        return 0;
+    }
+    return m_element->detachAttribute(index);
+}
+
+PassRefPtr<Node> NamedNodeMap::setNamedItem(Node* node, ExceptionCode& ec)
+{
+    if (!node) {
+        ec = NOT_FOUND_ERR;
+        return 0;
+    }
+
+    // Not mentioned in spec: throw a HIERARCHY_REQUEST_ERROR if the user passes in a non-attribute node
+    if (!node->isAttributeNode()) {
+        ec = HIERARCHY_REQUEST_ERR;
+        return 0;
+    }
+
+    return m_element->setAttributeNode(static_cast<Attr*>(node), ec);
+}
+
+PassRefPtr<Node> NamedNodeMap::setNamedItemNS(Node* node, ExceptionCode& ec)
+{
+    return setNamedItem(node, ec);
+}
+
+PassRefPtr<Node> NamedNodeMap::item(unsigned index) const
+{
+    if (index >= length())
+        return 0;
+    return m_element->ensureAttr(m_element->attributeItem(index)->name());
+}
+
+size_t NamedNodeMap::length() const
+{
+    if (!m_element->hasAttributes())
+        return 0;
+    return m_element->attributeCount();
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/NamedNodeMap.h b/Source/core/dom/NamedNodeMap.h
new file mode 100644
index 0000000..609b3b5
--- /dev/null
+++ b/Source/core/dom/NamedNodeMap.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Peter Kelly (pmk@post.com)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2010, 2013 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NamedNodeMap_h
+#define NamedNodeMap_h
+
+#include "bindings/v8/ScriptWrappable.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class Node;
+class Element;
+
+typedef int ExceptionCode;
+
+class NamedNodeMap : public ScriptWrappable {
+    WTF_MAKE_FAST_ALLOCATED;
+    friend class Element;
+public:
+    static PassOwnPtr<NamedNodeMap> create(Element* element)
+    {
+        return adoptPtr(new NamedNodeMap(element));
+    }
+
+    void ref();
+    void deref();
+
+    // Public DOM interface.
+
+    PassRefPtr<Node> getNamedItem(const AtomicString&) const;
+    PassRefPtr<Node> removeNamedItem(const AtomicString& name, ExceptionCode&);
+
+    PassRefPtr<Node> getNamedItemNS(const AtomicString& namespaceURI, const AtomicString& localName) const;
+    PassRefPtr<Node> removeNamedItemNS(const AtomicString& namespaceURI, const AtomicString& localName, ExceptionCode&);
+
+    PassRefPtr<Node> setNamedItem(Node*, ExceptionCode&);
+    PassRefPtr<Node> setNamedItemNS(Node*, ExceptionCode&);
+
+    PassRefPtr<Node> item(unsigned index) const;
+    size_t length() const;
+
+    Element* element() const { return m_element; }
+
+private:
+    explicit NamedNodeMap(Element* element)
+        : m_element(element)
+    {
+        // Only supports NamedNodeMaps with Element associated, DocumentType.entities and DocumentType.notations are not supported yet.
+        ASSERT(m_element);
+        ScriptWrappable::init(this);
+    }
+
+    Element* m_element;
+};
+
+} // namespace WebCore
+
+#endif // NamedNodeMap_h
diff --git a/Source/core/dom/NamedNodeMap.idl b/Source/core/dom/NamedNodeMap.idl
new file mode 100644
index 0000000..17e7736
--- /dev/null
+++ b/Source/core/dom/NamedNodeMap.idl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+[
+    GenerateIsReachable=ImplElementRoot,
+    CustomNamedGetter,
+    ImplementationLacksVTable
+] interface NamedNodeMap {
+
+    Node getNamedItem([Default=Undefined] optional DOMString name);
+
+    [RaisesException] Node setNamedItem([Default=Undefined] optional Node node);
+
+    [RaisesException] Node removeNamedItem([Default=Undefined] optional DOMString name);
+
+    getter Node item([Default=Undefined] optional unsigned long index);
+    
+    readonly attribute unsigned long length;
+
+
+    // Introduced in DOM Level 2:
+
+    // FIXME: the implementation does take an exceptioncode parameter.
+    /*[RaisesException]*/ Node getNamedItemNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI, 
+                                              [Default=Undefined] optional DOMString localName);
+
+    [RaisesException] Node setNamedItemNS([Default=Undefined] optional Node node);
+
+     [RaisesException] Node removeNamedItemNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI, 
+                                          [Default=Undefined] optional DOMString localName);
+
+};
+
diff --git a/Source/core/dom/Node.cpp b/Source/core/dom/Node.cpp
new file mode 100644
index 0000000..4b0e256
--- /dev/null
+++ b/Source/core/dom/Node.cpp
@@ -0,0 +1,2804 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/Node.h"
+
+#include "HTMLNames.h"
+#include "XMLNames.h"
+#include "core/accessibility/AXObjectCache.h"
+#include "core/css/CSSParser.h"
+#include "core/css/CSSRule.h"
+#include "core/css/CSSSelector.h"
+#include "core/css/CSSSelectorList.h"
+#include "core/css/CSSStyleRule.h"
+#include "core/css/CSSStyleSheet.h"
+#include "core/css/StyleResolver.h"
+#include "core/dom/Attr.h"
+#include "core/dom/Attribute.h"
+#include "core/dom/BeforeLoadEvent.h"
+#include "core/dom/ChildListMutationScope.h"
+#include "core/dom/ChildNodeList.h"
+#include "core/dom/ClassNodeList.h"
+#include "core/dom/ContainerNodeAlgorithms.h"
+#include "core/dom/DOMImplementation.h"
+#include "core/dom/Document.h"
+#include "core/dom/DocumentFragment.h"
+#include "core/dom/DocumentType.h"
+#include "core/dom/Element.h"
+#include "core/dom/ElementRareData.h"
+#include "core/dom/ElementShadow.h"
+#include "core/dom/Event.h"
+#include "core/dom/EventContext.h"
+#include "core/dom/EventDispatchMediator.h"
+#include "core/dom/EventDispatcher.h"
+#include "core/dom/EventException.h"
+#include "core/dom/EventListener.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/ExceptionCodePlaceholder.h"
+#include "core/dom/FocusEvent.h"
+#include "core/dom/GestureEvent.h"
+#include "core/dom/KeyboardEvent.h"
+#include "core/dom/LiveNodeList.h"
+#include "core/dom/MouseEvent.h"
+#include "core/dom/MutationEvent.h"
+#include "core/dom/NameNodeList.h"
+#include "core/dom/NamedNodeMap.h"
+#include "core/dom/NodeRareData.h"
+#include "core/dom/NodeRenderingContext.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/dom/ProcessingInstruction.h"
+#include "core/dom/ProgressEvent.h"
+#include "core/dom/RegisteredEventListener.h"
+#include "core/dom/ScopedEventQueue.h"
+#include "core/dom/SelectorQuery.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/dom/StaticNodeList.h"
+#include "core/dom/TagNodeList.h"
+#include "core/dom/TemplateContentDocumentFragment.h"
+#include "core/dom/Text.h"
+#include "core/dom/TextEvent.h"
+#include "core/dom/TouchEvent.h"
+#include "core/dom/TreeScopeAdopter.h"
+#include "core/dom/UIEvent.h"
+#include "core/dom/UIEventWithKeyState.h"
+#include "core/dom/UserActionElementSet.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/dom/WheelEvent.h"
+#include "core/dom/WindowEventContext.h"
+#include "core/editing/htmlediting.h"
+#include "core/html/DOMSettableTokenList.h"
+#include "core/html/HTMLElement.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/html/HTMLStyleElement.h"
+#include "core/html/LabelsNodeList.h"
+#include "core/html/RadioNodeList.h"
+#include "core/html/shadow/InsertionPoint.h"
+#include "core/inspector/InspectorCounters.h"
+#include "core/page/Chrome.h"
+#include "core/page/ChromeClient.h"
+#include "core/page/ContextMenuController.h"
+#include "core/page/EventHandler.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/platform/Logging.h"
+#include "core/platform/PlatformMouseEvent.h"
+#include "core/platform/PlatformWheelEvent.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderBox.h"
+#include "core/rendering/RenderTextControl.h"
+#include "core/rendering/RenderView.h"
+#include "core/storage/StorageEvent.h"
+#include <wtf/HashSet.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefCountedLeakCounter.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/UnusedParam.h>
+#include <wtf/Vector.h>
+
+#ifndef NDEBUG
+#include "core/rendering/RenderLayer.h"
+#endif
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+bool Node::isSupported(const String& feature, const String& version)
+{
+    return DOMImplementation::hasFeature(feature, version);
+}
+
+#if DUMP_NODE_STATISTICS
+static HashSet<Node*> liveNodeSet;
+#endif
+
+void Node::dumpStatistics()
+{
+#if DUMP_NODE_STATISTICS
+    size_t nodesWithRareData = 0;
+
+    size_t elementNodes = 0;
+    size_t attrNodes = 0;
+    size_t textNodes = 0;
+    size_t cdataNodes = 0;
+    size_t commentNodes = 0;
+    size_t entityReferenceNodes = 0;
+    size_t entityNodes = 0;
+    size_t piNodes = 0;
+    size_t documentNodes = 0;
+    size_t docTypeNodes = 0;
+    size_t fragmentNodes = 0;
+    size_t notationNodes = 0;
+    size_t xpathNSNodes = 0;
+    size_t shadowRootNodes = 0;
+
+    HashMap<String, size_t> perTagCount;
+
+    size_t attributes = 0;
+    size_t attributesWithAttr = 0;
+    size_t elementsWithAttributeStorage = 0;
+    size_t elementsWithRareData = 0;
+    size_t elementsWithNamedNodeMap = 0;
+
+    for (HashSet<Node*>::iterator it = liveNodeSet.begin(); it != liveNodeSet.end(); ++it) {
+        Node* node = *it;
+
+        if (node->hasRareData()) {
+            ++nodesWithRareData;
+            if (node->isElementNode()) {
+                ++elementsWithRareData;
+                if (toElement(node)->hasNamedNodeMap())
+                    ++elementsWithNamedNodeMap;
+            }
+        }
+
+        switch (node->nodeType()) {
+            case ELEMENT_NODE: {
+                ++elementNodes;
+
+                // Tag stats
+                Element* element = toElement(node);
+                HashMap<String, size_t>::AddResult result = perTagCount.add(element->tagName(), 1);
+                if (!result.isNewEntry)
+                    result.iterator->value++;
+
+                if (ElementData* elementData = element->elementData()) {
+                    attributes += elementData->length();
+                    ++elementsWithAttributeStorage;
+                    for (unsigned i = 0; i < elementData->length(); ++i) {
+                        Attribute* attr = elementData->attributeItem(i);
+                        if (attr->attr())
+                            ++attributesWithAttr;
+                    }
+                }
+                break;
+            }
+            case ATTRIBUTE_NODE: {
+                ++attrNodes;
+                break;
+            }
+            case TEXT_NODE: {
+                ++textNodes;
+                break;
+            }
+            case CDATA_SECTION_NODE: {
+                ++cdataNodes;
+                break;
+            }
+            case COMMENT_NODE: {
+                ++commentNodes;
+                break;
+            }
+            case ENTITY_REFERENCE_NODE: {
+                ++entityReferenceNodes;
+                break;
+            }
+            case ENTITY_NODE: {
+                ++entityNodes;
+                break;
+            }
+            case PROCESSING_INSTRUCTION_NODE: {
+                ++piNodes;
+                break;
+            }
+            case DOCUMENT_NODE: {
+                ++documentNodes;
+                break;
+            }
+            case DOCUMENT_TYPE_NODE: {
+                ++docTypeNodes;
+                break;
+            }
+            case DOCUMENT_FRAGMENT_NODE: {
+                if (node->isShadowRoot())
+                    ++shadowRootNodes;
+                else
+                    ++fragmentNodes;
+                break;
+            }
+            case NOTATION_NODE: {
+                ++notationNodes;
+                break;
+            }
+            case XPATH_NAMESPACE_NODE: {
+                ++xpathNSNodes;
+                break;
+            }
+        }
+    }
+
+    printf("Number of Nodes: %d\n\n", liveNodeSet.size());
+    printf("Number of Nodes with RareData: %zu\n\n", nodesWithRareData);
+
+    printf("NodeType distribution:\n");
+    printf("  Number of Element nodes: %zu\n", elementNodes);
+    printf("  Number of Attribute nodes: %zu\n", attrNodes);
+    printf("  Number of Text nodes: %zu\n", textNodes);
+    printf("  Number of CDATASection nodes: %zu\n", cdataNodes);
+    printf("  Number of Comment nodes: %zu\n", commentNodes);
+    printf("  Number of EntityReference nodes: %zu\n", entityReferenceNodes);
+    printf("  Number of Entity nodes: %zu\n", entityNodes);
+    printf("  Number of ProcessingInstruction nodes: %zu\n", piNodes);
+    printf("  Number of Document nodes: %zu\n", documentNodes);
+    printf("  Number of DocumentType nodes: %zu\n", docTypeNodes);
+    printf("  Number of DocumentFragment nodes: %zu\n", fragmentNodes);
+    printf("  Number of Notation nodes: %zu\n", notationNodes);
+    printf("  Number of XPathNS nodes: %zu\n", xpathNSNodes);
+    printf("  Number of ShadowRoot nodes: %zu\n", shadowRootNodes);
+
+    printf("Element tag name distibution:\n");
+    for (HashMap<String, size_t>::iterator it = perTagCount.begin(); it != perTagCount.end(); ++it)
+        printf("  Number of <%s> tags: %zu\n", it->key.utf8().data(), it->value);
+
+    printf("Attributes:\n");
+    printf("  Number of Attributes (non-Node and Node): %zu [%zu]\n", attributes, sizeof(Attribute));
+    printf("  Number of Attributes with an Attr: %zu\n", attributesWithAttr);
+    printf("  Number of Elements with attribute storage: %zu [%zu]\n", elementsWithAttributeStorage, sizeof(ElementData));
+    printf("  Number of Elements with RareData: %zu\n", elementsWithRareData);
+    printf("  Number of Elements with NamedNodeMap: %zu [%zu]\n", elementsWithNamedNodeMap, sizeof(NamedNodeMap));
+#endif
+}
+
+DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, nodeCounter, ("WebCoreNode"));
+DEFINE_DEBUG_ONLY_GLOBAL(HashSet<Node*>, ignoreSet, );
+
+#ifndef NDEBUG
+static bool shouldIgnoreLeaks = false;
+#endif
+
+void Node::startIgnoringLeaks()
+{
+#ifndef NDEBUG
+    shouldIgnoreLeaks = true;
+#endif
+}
+
+void Node::stopIgnoringLeaks()
+{
+#ifndef NDEBUG
+    shouldIgnoreLeaks = false;
+#endif
+}
+
+Node::StyleChange Node::diff(const RenderStyle* s1, const RenderStyle* s2, Document* doc)
+{
+    StyleChange ch = NoInherit;
+    EDisplay display1 = s1 ? s1->display() : NONE;
+    bool fl1 = s1 && s1->hasPseudoStyle(FIRST_LETTER);
+    EDisplay display2 = s2 ? s2->display() : NONE;
+    bool fl2 = s2 && s2->hasPseudoStyle(FIRST_LETTER);
+    
+    // We just detach if a renderer acquires or loses a column-span, since spanning elements
+    // typically won't contain much content.
+    bool colSpan1 = s1 && s1->columnSpan();
+    bool colSpan2 = s2 && s2->columnSpan();
+    
+    bool specifiesColumns1 = s1 && (!s1->hasAutoColumnCount() || !s1->hasAutoColumnWidth());
+    bool specifiesColumns2 = s2 && (!s2->hasAutoColumnCount() || !s2->hasAutoColumnWidth());
+
+    if (display1 != display2 || fl1 != fl2 || colSpan1 != colSpan2 
+        || (specifiesColumns1 != specifiesColumns2 && doc->settings()->regionBasedColumnsEnabled())
+        || (s1 && s2 && !s1->contentDataEquivalent(s2)))
+        ch = Detach;
+    else if (!s1 || !s2)
+        ch = Inherit;
+    else if (*s1 == *s2)
+        ch = NoChange;
+    else if (s1->inheritedNotEqual(s2))
+        ch = Inherit;
+    else if (s1->hasExplicitlyInheritedProperties() || s2->hasExplicitlyInheritedProperties())
+        ch = Inherit;
+
+    // If the pseudoStyles have changed, we want any StyleChange that is not NoChange
+    // because setStyle will do the right thing with anything else.
+    if (ch == NoChange && s1->hasAnyPublicPseudoStyles()) {
+        for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; ch == NoChange && pseudoId < FIRST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
+            if (s1->hasPseudoStyle(pseudoId)) {
+                RenderStyle* ps2 = s2->getCachedPseudoStyle(pseudoId);
+                if (!ps2)
+                    ch = NoInherit;
+                else {
+                    RenderStyle* ps1 = s1->getCachedPseudoStyle(pseudoId);
+                    ch = ps1 && *ps1 == *ps2 ? NoChange : NoInherit;
+                }
+            }
+        }
+    }
+
+    // When text-combine property has been changed, we need to prepare a separate renderer object.
+    // When text-combine is on, we use RenderCombineText, otherwise RenderText.
+    // https://bugs.webkit.org/show_bug.cgi?id=55069
+    if ((s1 && s2) && (s1->hasTextCombine() != s2->hasTextCombine()))
+        ch = Detach;
+
+    // We need to reattach the node, so that it is moved to the correct RenderFlowThread.
+    if ((s1 && s2) && (s1->flowThread() != s2->flowThread()))
+        ch = Detach;
+
+    // When the region thread has changed, we need to prepare a separate render region object.
+    if ((s1 && s2) && (s1->regionThread() != s2->regionThread()))
+        ch = Detach;
+
+    return ch;
+}
+
+void Node::trackForDebugging()
+{
+#ifndef NDEBUG
+    if (shouldIgnoreLeaks)
+        ignoreSet.add(this);
+    else
+        nodeCounter.increment();
+#endif
+
+#if DUMP_NODE_STATISTICS
+    liveNodeSet.add(this);
+#endif
+}
+
+Node::~Node()
+{
+#ifndef NDEBUG
+    HashSet<Node*>::iterator it = ignoreSet.find(this);
+    if (it != ignoreSet.end())
+        ignoreSet.remove(it);
+    else
+        nodeCounter.decrement();
+#endif
+
+#if DUMP_NODE_STATISTICS
+    liveNodeSet.remove(this);
+#endif
+
+    if (hasRareData())
+        clearRareData();
+
+    if (renderer())
+        detach();
+
+    if (!isContainerNode()) {
+        if (Document* document = documentInternal())
+            willBeDeletedFrom(document);
+    }
+
+    if (m_previous)
+        m_previous->setNextSibling(0);
+    if (m_next)
+        m_next->setPreviousSibling(0);
+
+    m_treeScope->guardDeref();
+
+    InspectorCounters::decrementCounter(InspectorCounters::NodeCounter);
+}
+
+void Node::willBeDeletedFrom(Document* document)
+{
+    if (hasEventTargetData()) {
+        if (document)
+            document->didRemoveEventTargetNode(this);
+        clearEventTargetData();
+    }
+
+    if (document) {
+        if (AXObjectCache* cache = document->existingAXObjectCache())
+            cache->remove(this);
+    }
+}
+
+NodeRareData* Node::rareData() const
+{
+    ASSERT(hasRareData());
+    return static_cast<NodeRareData*>(m_data.m_rareData);
+}
+
+NodeRareData* Node::ensureRareData()
+{
+    if (hasRareData())
+        return rareData();
+
+    NodeRareData* data;
+    if (isElementNode())
+        data = ElementRareData::create(m_data.m_renderer).leakPtr();
+    else
+        data = NodeRareData::create(m_data.m_renderer).leakPtr();
+    ASSERT(data);
+
+    m_data.m_rareData = data;
+    setFlag(HasRareDataFlag);
+    return data;
+}
+
+void Node::clearRareData()
+{
+    ASSERT(hasRareData());
+    ASSERT(!transientMutationObserverRegistry() || transientMutationObserverRegistry()->isEmpty());
+
+    RenderObject* renderer = m_data.m_rareData->renderer();
+    if (isElementNode())
+        delete static_cast<ElementRareData*>(m_data.m_rareData);
+    else
+        delete static_cast<NodeRareData*>(m_data.m_rareData);
+    m_data.m_renderer = renderer;
+    clearFlag(HasRareDataFlag);
+}
+
+Node* Node::toNode()
+{
+    return this;
+}
+
+HTMLInputElement* Node::toInputElement()
+{
+    // If one of the below ASSERTs trigger, you are calling this function
+    // directly or indirectly from a constructor or destructor of this object.
+    // Don't do this!
+    ASSERT(!(isHTMLElement() && hasTagName(inputTag)));
+    return 0;
+}
+
+short Node::tabIndex() const
+{
+    return 0;
+}
+
+String Node::nodeValue() const
+{
+    return String();
+}
+
+void Node::setNodeValue(const String& /*nodeValue*/, ExceptionCode& ec)
+{
+    // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
+    if (isReadOnlyNode()) {
+        ec = NO_MODIFICATION_ALLOWED_ERR;
+        return;
+    }
+
+    // By default, setting nodeValue has no effect.
+}
+
+PassRefPtr<NodeList> Node::childNodes()
+{
+    return ensureRareData()->ensureNodeLists()->ensureChildNodeList(this);
+}
+
+Node *Node::lastDescendant() const
+{
+    Node *n = const_cast<Node *>(this);
+    while (n && n->lastChild())
+        n = n->lastChild();
+    return n;
+}
+
+Node* Node::firstDescendant() const
+{
+    Node *n = const_cast<Node *>(this);
+    while (n && n->firstChild())
+        n = n->firstChild();
+    return n;
+}
+
+Node* Node::pseudoAwarePreviousSibling() const
+{
+    if (parentElement() && !previousSibling()) {
+        Element* parent = parentElement();
+        if (isAfterPseudoElement() && parent->lastChild())
+            return parent->lastChild();
+        if (!isBeforePseudoElement())
+            return parent->pseudoElement(BEFORE);
+    }
+    return previousSibling();
+}
+
+Node* Node::pseudoAwareNextSibling() const
+{
+    if (parentElement() && !nextSibling()) {
+        Element* parent = parentElement();
+        if (isBeforePseudoElement() && parent->firstChild())
+            return parent->firstChild();
+        if (!isAfterPseudoElement())
+            return parent->pseudoElement(AFTER);
+    }
+    return nextSibling();
+}
+
+Node* Node::pseudoAwareFirstChild() const
+{
+    if (isElementNode()) {
+        const Element* currentElement = toElement(this);
+        Node* first = currentElement->pseudoElement(BEFORE);
+        if (first)
+            return first;
+        first = currentElement->firstChild();
+        if (!first)
+            first = currentElement->pseudoElement(AFTER);
+        return first;
+    }
+
+    return firstChild();
+}
+
+Node* Node::pseudoAwareLastChild() const
+{
+    if (isElementNode()) {
+        const Element* currentElement = toElement(this);
+        Node* last = currentElement->pseudoElement(AFTER);
+        if (last)
+            return last;
+        last = currentElement->lastChild();
+        if (!last)
+            last = currentElement->pseudoElement(BEFORE);
+        return last;
+    }
+
+    return lastChild();
+}
+
+bool Node::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, AttachBehavior attachBehavior)
+{
+    if (!isContainerNode()) {
+        ec = HIERARCHY_REQUEST_ERR;
+        return false;
+    }
+    return toContainerNode(this)->insertBefore(newChild, refChild, ec, attachBehavior);
+}
+
+bool Node::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, AttachBehavior attachBehavior)
+{
+    if (!isContainerNode()) {
+        ec = HIERARCHY_REQUEST_ERR;
+        return false;
+    }
+    return toContainerNode(this)->replaceChild(newChild, oldChild, ec, attachBehavior);
+}
+
+bool Node::removeChild(Node* oldChild, ExceptionCode& ec)
+{
+    if (!isContainerNode()) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+    return toContainerNode(this)->removeChild(oldChild, ec);
+}
+
+bool Node::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, AttachBehavior attachBehavior)
+{
+    if (!isContainerNode()) {
+        ec = HIERARCHY_REQUEST_ERR;
+        return false;
+    }
+    return toContainerNode(this)->appendChild(newChild, ec, attachBehavior);
+}
+
+void Node::remove(ExceptionCode& ec)
+{
+    if (ContainerNode* parent = parentNode())
+        parent->removeChild(this, ec);
+}
+
+void Node::normalize()
+{
+    // Go through the subtree beneath us, normalizing all nodes. This means that
+    // any two adjacent text nodes are merged and any empty text nodes are removed.
+
+    RefPtr<Node> node = this;
+    while (Node* firstChild = node->firstChild())
+        node = firstChild;
+    while (node) {
+        NodeType type = node->nodeType();
+        if (type == ELEMENT_NODE)
+            toElement(node.get())->normalizeAttributes();
+
+        if (node == this)
+            break;
+
+        if (type != TEXT_NODE) {
+            node = NodeTraversal::nextPostOrder(node.get());
+            continue;
+        }
+
+        RefPtr<Text> text = toText(node.get());
+
+        // Remove empty text nodes.
+        if (!text->length()) {
+            // Care must be taken to get the next node before removing the current node.
+            node = NodeTraversal::nextPostOrder(node.get());
+            text->remove(IGNORE_EXCEPTION);
+            continue;
+        }
+
+        // Merge text nodes.
+        while (Node* nextSibling = node->nextSibling()) {
+            if (nextSibling->nodeType() != TEXT_NODE)
+                break;
+            RefPtr<Text> nextText = toText(nextSibling);
+
+            // Remove empty text nodes.
+            if (!nextText->length()) {
+                nextText->remove(IGNORE_EXCEPTION);
+                continue;
+            }
+
+            // Both non-empty text nodes. Merge them.
+            unsigned offset = text->length();
+            text->appendData(nextText->data(), IGNORE_EXCEPTION);
+            document()->textNodesMerged(nextText.get(), offset);
+            nextText->remove(IGNORE_EXCEPTION);
+        }
+
+        node = NodeTraversal::nextPostOrder(node.get());
+    }
+}
+
+const AtomicString& Node::virtualPrefix() const
+{
+    // For nodes other than elements and attributes, the prefix is always null
+    return nullAtom;
+}
+
+void Node::setPrefix(const AtomicString& /*prefix*/, ExceptionCode& ec)
+{
+    // The spec says that for nodes other than elements and attributes, prefix is always null.
+    // It does not say what to do when the user tries to set the prefix on another type of
+    // node, however Mozilla throws a NAMESPACE_ERR exception.
+    ec = NAMESPACE_ERR;
+}
+
+const AtomicString& Node::virtualLocalName() const
+{
+    return nullAtom;
+}
+
+const AtomicString& Node::virtualNamespaceURI() const
+{
+    return nullAtom;
+}
+
+bool Node::isContentEditable(UserSelectAllTreatment treatment)
+{
+    document()->updateStyleIfNeeded();
+    return rendererIsEditable(Editable, treatment);
+}
+
+bool Node::isContentRichlyEditable()
+{
+    document()->updateStyleIfNeeded();
+    return rendererIsEditable(RichlyEditable, UserSelectAllIsAlwaysNonEditable);
+}
+
+bool Node::rendererIsEditable(EditableLevel editableLevel, UserSelectAllTreatment treatment) const
+{
+    if (isPseudoElement())
+        return false;
+
+    // Ideally we'd call ASSERT(!needsStyleRecalc()) here, but
+    // ContainerNode::setFocus() calls setNeedsStyleRecalc(), so the assertion
+    // would fire in the middle of Document::setFocusedNode().
+
+    for (const Node* node = this; node; node = node->parentNode()) {
+        if ((node->isHTMLElement() || node->isDocumentNode()) && node->renderer()) {
+#if ENABLE(USERSELECT_ALL)
+            // Elements with user-select: all style are considered atomic
+            // therefore non editable.
+            if (node->renderer()->style()->userSelect() == SELECT_ALL && treatment == UserSelectAllIsAlwaysNonEditable)
+                return false;
+#else
+            UNUSED_PARAM(treatment);
+#endif
+            switch (node->renderer()->style()->userModify()) {
+            case READ_ONLY:
+                return false;
+            case READ_WRITE:
+                return true;
+            case READ_WRITE_PLAINTEXT_ONLY:
+                return editableLevel != RichlyEditable;
+            }
+            ASSERT_NOT_REACHED();
+            return false;
+        }
+    }
+
+    return false;
+}
+
+bool Node::isEditableToAccessibility(EditableLevel editableLevel) const
+{
+    if (rendererIsEditable(editableLevel))
+        return true;
+
+    // FIXME: Respect editableLevel for ARIA editable elements.
+    if (editableLevel == RichlyEditable)
+        return false;
+
+    ASSERT(document());
+    ASSERT(AXObjectCache::accessibilityEnabled());
+    ASSERT(document()->existingAXObjectCache());
+
+    if (document()) {
+        if (AXObjectCache* cache = document()->existingAXObjectCache())
+            return cache->rootAXEditableElement(this);
+    }
+
+    return false;
+}
+
+bool Node::shouldUseInputMethod()
+{
+    return isContentEditable(UserSelectAllIsAlwaysNonEditable);
+}
+
+RenderBox* Node::renderBox() const
+{
+    RenderObject* renderer = this->renderer();
+    return renderer && renderer->isBox() ? toRenderBox(renderer) : 0;
+}
+
+RenderBoxModelObject* Node::renderBoxModelObject() const
+{
+    RenderObject* renderer = this->renderer();
+    return renderer && renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
+}
+
+LayoutRect Node::boundingBox() const
+{
+    if (renderer())
+        return renderer()->absoluteBoundingBoxRect();
+    return LayoutRect();
+}
+    
+LayoutRect Node::renderRect(bool* isReplaced)
+{    
+    RenderObject* hitRenderer = this->renderer();
+    ASSERT(hitRenderer);
+    RenderObject* renderer = hitRenderer;
+    while (renderer && !renderer->isBody() && !renderer->isRoot()) {
+        if (renderer->isRenderBlock() || renderer->isInlineBlockOrInlineTable() || renderer->isReplaced()) {
+            *isReplaced = renderer->isReplaced();
+            return renderer->absoluteBoundingBoxRect();
+        }
+        renderer = renderer->parent();
+    }
+    return LayoutRect();    
+}
+
+bool Node::hasNonEmptyBoundingBox() const
+{
+    // Before calling absoluteRects, check for the common case where the renderer
+    // is non-empty, since this is a faster check and almost always returns true.
+    RenderBoxModelObject* box = renderBoxModelObject();
+    if (!box)
+        return false;
+    if (!box->borderBoundingBox().isEmpty())
+        return true;
+
+    Vector<IntRect> rects;
+    FloatPoint absPos = renderer()->localToAbsolute();
+    renderer()->absoluteRects(rects, flooredLayoutPoint(absPos));
+    size_t n = rects.size();
+    for (size_t i = 0; i < n; ++i)
+        if (!rects[i].isEmpty())
+            return true;
+
+    return false;
+}
+
+inline static ShadowRoot* oldestShadowRootFor(const Node* node)
+{
+    if (!node->isElementNode())
+        return 0;
+    if (ElementShadow* shadow = toElement(node)->shadow())
+        return shadow->oldestShadowRoot();
+    return 0;
+}
+
+inline void Node::setStyleChange(StyleChangeType changeType)
+{
+    m_nodeFlags = (m_nodeFlags & ~StyleChangeMask) | changeType;
+}
+
+inline void Node::markAncestorsWithChildNeedsStyleRecalc()
+{
+    for (ContainerNode* p = parentOrShadowHostNode(); p && !p->childNeedsStyleRecalc(); p = p->parentOrShadowHostNode())
+        p->setChildNeedsStyleRecalc();
+
+    if (document()->childNeedsStyleRecalc())
+        document()->scheduleStyleRecalc();
+}
+
+void Node::refEventTarget()
+{
+    ref();
+}
+
+void Node::derefEventTarget()
+{
+    deref();
+}
+
+void Node::setNeedsStyleRecalc(StyleChangeType changeType)
+{
+    ASSERT(changeType != NoStyleChange);
+    if (!attached()) // changed compared to what?
+        return;
+
+    StyleChangeType existingChangeType = styleChangeType();
+    if (changeType > existingChangeType)
+        setStyleChange(changeType);
+
+    if (existingChangeType == NoStyleChange)
+        markAncestorsWithChildNeedsStyleRecalc();
+}
+
+void Node::lazyAttach(ShouldSetAttached shouldSetAttached)
+{
+    for (Node* n = this; n; n = NodeTraversal::next(n, this)) {
+        if (n->hasChildNodes())
+            n->setChildNeedsStyleRecalc();
+        n->setStyleChange(FullStyleChange);
+        if (shouldSetAttached == SetAttached)
+            n->setAttached();
+    }
+    markAncestorsWithChildNeedsStyleRecalc();
+}
+
+bool Node::supportsFocus() const
+{
+    return false;
+}
+    
+bool Node::isFocusable() const
+{
+    if (!inDocument() || !supportsFocus())
+        return false;
+    
+    // Elements in canvas fallback content are not rendered, but they are allowed to be
+    // focusable as long as their canvas is displayed and visible.
+    if (isElementNode() && toElement(this)->isInCanvasSubtree()) {
+        const Element* e = toElement(this);
+        while (e && !e->hasLocalName(canvasTag))
+            e = e->parentElement();
+        ASSERT(e);
+        return e->renderer() && e->renderer()->style()->visibility() == VISIBLE;
+    }
+
+    if (renderer())
+        ASSERT(!renderer()->needsLayout());
+    else
+        // If the node is in a display:none tree it might say it needs style recalc but
+        // the whole document is actually up to date.
+        ASSERT(!document()->childNeedsStyleRecalc());
+
+    // FIXME: Even if we are not visible, we might have a child that is visible.
+    // Hyatt wants to fix that some day with a "has visible content" flag or the like.
+    if (!renderer() || renderer()->style()->visibility() != VISIBLE)
+        return false;
+
+    return true;
+}
+
+bool Node::isKeyboardFocusable(KeyboardEvent*) const
+{
+    return isFocusable() && tabIndex() >= 0;
+}
+
+bool Node::isMouseFocusable() const
+{
+    return isFocusable();
+}
+
+Node* Node::focusDelegate()
+{
+    return this;
+}
+
+unsigned Node::nodeIndex() const
+{
+    Node *_tempNode = previousSibling();
+    unsigned count=0;
+    for ( count=0; _tempNode; count++ )
+        _tempNode = _tempNode->previousSibling();
+    return count;
+}
+
+template<unsigned type>
+bool shouldInvalidateNodeListCachesForAttr(const unsigned nodeListCounts[], const QualifiedName& attrName)
+{
+    if (nodeListCounts[type] && LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(static_cast<NodeListInvalidationType>(type), attrName))
+        return true;
+    return shouldInvalidateNodeListCachesForAttr<type + 1>(nodeListCounts, attrName);
+}
+
+template<>
+bool shouldInvalidateNodeListCachesForAttr<numNodeListInvalidationTypes>(const unsigned[], const QualifiedName&)
+{
+    return false;
+}
+
+bool Document::shouldInvalidateNodeListCaches(const QualifiedName* attrName) const
+{
+    if (attrName)
+        return shouldInvalidateNodeListCachesForAttr<DoNotInvalidateOnAttributeChanges + 1>(m_nodeListCounts, *attrName);
+
+    for (int type = 0; type < numNodeListInvalidationTypes; type++) {
+        if (m_nodeListCounts[type])
+            return true;
+    }
+
+    return false;
+}
+
+void Document::invalidateNodeListCaches(const QualifiedName* attrName)
+{
+    HashSet<LiveNodeListBase*>::iterator end = m_listsInvalidatedAtDocument.end();
+    for (HashSet<LiveNodeListBase*>::iterator it = m_listsInvalidatedAtDocument.begin(); it != end; ++it)
+        (*it)->invalidateCache(attrName);
+}
+
+void Node::invalidateNodeListCachesInAncestors(const QualifiedName* attrName, Element* attributeOwnerElement)
+{
+    if (hasRareData() && (!attrName || isAttributeNode())) {
+        if (NodeListsNodeData* lists = rareData()->nodeLists())
+            lists->clearChildNodeListCache();
+    }
+
+    // Modifications to attributes that are not associated with an Element can't invalidate NodeList caches.
+    if (attrName && !attributeOwnerElement)
+        return;
+
+    if (!document()->shouldInvalidateNodeListCaches(attrName))
+        return;
+
+    document()->invalidateNodeListCaches(attrName);
+
+    for (Node* node = this; node; node = node->parentNode()) {
+        if (!node->hasRareData())
+            continue;
+        NodeRareData* data = node->rareData();
+        if (data->nodeLists())
+            data->nodeLists()->invalidateCaches(attrName);
+    }
+}
+
+NodeListsNodeData* Node::nodeLists()
+{
+    return hasRareData() ? rareData()->nodeLists() : 0;
+}
+
+void Node::clearNodeLists()
+{
+    rareData()->clearNodeLists();
+}
+
+void Node::checkSetPrefix(const AtomicString& prefix, ExceptionCode& ec)
+{
+    // Perform error checking as required by spec for setting Node.prefix. Used by
+    // Element::setPrefix() and Attr::setPrefix()
+
+    if (!prefix.isEmpty() && !Document::isValidName(prefix)) {
+        ec = INVALID_CHARACTER_ERR;
+        return;
+    }
+
+    if (isReadOnlyNode()) {
+        ec = NO_MODIFICATION_ALLOWED_ERR;
+        return;
+    }
+
+    // FIXME: Raise NAMESPACE_ERR if prefix is malformed per the Namespaces in XML specification.
+
+    const AtomicString& nodeNamespaceURI = namespaceURI();
+    if ((nodeNamespaceURI.isEmpty() && !prefix.isEmpty())
+        || (prefix == xmlAtom && nodeNamespaceURI != XMLNames::xmlNamespaceURI)) {
+        ec = NAMESPACE_ERR;
+        return;
+    }
+    // Attribute-specific checks are in Attr::setPrefix().
+}
+
+bool Node::isDescendantOf(const Node *other) const
+{
+    // Return true if other is an ancestor of this, otherwise false
+    if (!other || !other->hasChildNodes() || inDocument() != other->inDocument())
+        return false;
+    if (other->isDocumentNode())
+        return document() == other && !isDocumentNode() && inDocument();
+    for (const ContainerNode* n = parentNode(); n; n = n->parentNode()) {
+        if (n == other)
+            return true;
+    }
+    return false;
+}
+
+bool Node::contains(const Node* node) const
+{
+    if (!node)
+        return false;
+    return this == node || node->isDescendantOf(this);
+}
+
+bool Node::containsIncludingShadowDOM(const Node* node) const
+{
+    for (; node; node = node->parentOrShadowHostNode()) {
+        if (node == this)
+            return true;
+    }
+    return false;
+}
+
+bool Node::containsIncludingHostElements(const Node* node) const
+{
+    while (node) {
+        if (node == this)
+            return true;
+        if (node->isDocumentFragment() && static_cast<const DocumentFragment*>(node)->isTemplateContent())
+            node = static_cast<const TemplateContentDocumentFragment*>(node)->host();
+        else
+            node = node->parentOrShadowHostNode();
+    }
+    return false;
+}
+
+void Node::attach()
+{
+    ASSERT(!attached());
+    ASSERT(!renderer() || (renderer()->style() && renderer()->parent()));
+
+    // If this node got a renderer it may be the previousRenderer() of sibling text nodes and thus affect the
+    // result of Text::textRendererIsNeeded() for those nodes.
+    if (renderer()) {
+        for (Node* next = nextSibling(); next; next = next->nextSibling()) {
+            if (next->renderer())
+                break;
+            if (!next->attached())
+                break; // Assume this means none of the following siblings are attached.
+            if (!next->isTextNode())
+                continue;
+            ASSERT(!next->renderer());
+            toText(next)->createTextRendererIfNeeded();
+            // If we again decided not to create a renderer for next, we can bail out the loop,
+            // because it won't affect the result of Text::textRendererIsNeeded() for the rest
+            // of sibling nodes.
+            if (!next->renderer())
+                break;
+        }
+    }
+
+    setAttached();
+    clearNeedsStyleRecalc();
+
+    if (Document* doc = documentInternal()) {
+        if (AXObjectCache* cache = doc->axObjectCache())
+            cache->updateCacheAfterNodeIsAttached(this);
+    }
+}
+
+#ifndef NDEBUG
+static Node* detachingNode;
+
+bool Node::inDetach() const
+{
+    return detachingNode == this;
+}
+#endif
+
+void Node::detach()
+{
+#ifndef NDEBUG
+    ASSERT(!detachingNode);
+    detachingNode = this;
+#endif
+
+    if (renderer())
+        renderer()->destroyAndCleanupAnonymousWrappers();
+    setRenderer(0);
+
+    Document* doc = document();
+    if (isUserActionElement()) {
+        if (hovered())
+            doc->hoveredNodeDetached(this);
+        if (inActiveChain())
+            doc->activeChainNodeDetached(this);
+        doc->userActionElements().didDetach(this);
+    }
+
+    clearFlag(IsAttachedFlag);
+
+#ifndef NDEBUG
+    detachingNode = 0;
+#endif
+}
+
+// FIXME: This code is used by editing.  Seems like it could move over there and not pollute Node.
+Node *Node::previousNodeConsideringAtomicNodes() const
+{
+    if (previousSibling()) {
+        Node *n = previousSibling();
+        while (!isAtomicNode(n) && n->lastChild())
+            n = n->lastChild();
+        return n;
+    }
+    else if (parentNode()) {
+        return parentNode();
+    }
+    else {
+        return 0;
+    }
+}
+
+Node *Node::nextNodeConsideringAtomicNodes() const
+{
+    if (!isAtomicNode(this) && firstChild())
+        return firstChild();
+    if (nextSibling())
+        return nextSibling();
+    const Node *n = this;
+    while (n && !n->nextSibling())
+        n = n->parentNode();
+    if (n)
+        return n->nextSibling();
+    return 0;
+}
+
+Node *Node::previousLeafNode() const
+{
+    Node *node = previousNodeConsideringAtomicNodes();
+    while (node) {
+        if (isAtomicNode(node))
+            return node;
+        node = node->previousNodeConsideringAtomicNodes();
+    }
+    return 0;
+}
+
+Node *Node::nextLeafNode() const
+{
+    Node *node = nextNodeConsideringAtomicNodes();
+    while (node) {
+        if (isAtomicNode(node))
+            return node;
+        node = node->nextNodeConsideringAtomicNodes();
+    }
+    return 0;
+}
+
+ContainerNode* Node::parentNodeForRenderingAndStyle()
+{
+    return NodeRenderingContext(this).parentNodeForRenderingAndStyle();
+}
+
+RenderStyle* Node::virtualComputedStyle(PseudoId pseudoElementSpecifier)
+{
+    return parentOrShadowHostNode() ? parentOrShadowHostNode()->computedStyle(pseudoElementSpecifier) : 0;
+}
+
+int Node::maxCharacterOffset() const
+{
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+// FIXME: Shouldn't these functions be in the editing code?  Code that asks questions about HTML in the core DOM class
+// is obviously misplaced.
+bool Node::canStartSelection() const
+{
+    if (rendererIsEditable())
+        return true;
+
+    if (renderer()) {
+        RenderStyle* style = renderer()->style();
+        // We allow selections to begin within an element that has -webkit-user-select: none set,
+        // but if the element is draggable then dragging should take priority over selection.
+        if (style->userDrag() == DRAG_ELEMENT && style->userSelect() == SELECT_NONE)
+            return false;
+    }
+    return parentOrShadowHostNode() ? parentOrShadowHostNode()->canStartSelection() : true;
+}
+
+Element* Node::shadowHost() const
+{
+    if (ShadowRoot* root = containingShadowRoot())
+        return root->host();
+    return 0;
+}
+
+Node* Node::deprecatedShadowAncestorNode() const
+{
+    if (ShadowRoot* root = containingShadowRoot())
+        return root->host();
+
+    return const_cast<Node*>(this);
+}
+
+ShadowRoot* Node::containingShadowRoot() const
+{
+    Node* root = treeScope()->rootNode();
+    return root && root->isShadowRoot() ? toShadowRoot(root) : 0;
+}
+
+Node* Node::nonBoundaryShadowTreeRootNode()
+{
+    ASSERT(!isShadowRoot());
+    Node* root = this;
+    while (root) {
+        if (root->isShadowRoot())
+            return root;
+        Node* parent = root->parentNodeGuaranteedHostFree();
+        if (parent && parent->isShadowRoot())
+            return root;
+        root = parent;
+    }
+    return 0;
+}
+
+ContainerNode* Node::nonShadowBoundaryParentNode() const
+{
+    ContainerNode* parent = parentNode();
+    return parent && !parent->isShadowRoot() ? parent : 0;
+}
+
+Element* Node::parentOrShadowHostElement() const
+{
+    ContainerNode* parent = parentOrShadowHostNode();
+    if (!parent)
+        return 0;
+
+    if (parent->isShadowRoot())
+        return toShadowRoot(parent)->host();
+
+    if (!parent->isElementNode())
+        return 0;
+
+    return toElement(parent);
+}
+
+Node* Node::insertionParentForBinding() const
+{
+    return resolveReprojection(this);
+}
+
+bool Node::needsShadowTreeWalkerSlow() const
+{
+    return (isShadowRoot() || (isElementNode() && (isInsertionPoint() || isPseudoElement() || toElement(this)->hasPseudoElements() || toElement(this)->shadow())));
+}
+
+bool Node::isBlockFlowElement() const
+{
+    return isElementNode() && renderer() && renderer()->isBlockFlow();
+}
+
+Element *Node::enclosingBlockFlowElement() const
+{
+    Node *n = const_cast<Node *>(this);
+    if (isBlockFlowElement())
+        return toElement(n);
+
+    while (1) {
+        n = n->parentNode();
+        if (!n)
+            break;
+        if (n->isBlockFlowElement() || n->hasTagName(bodyTag))
+            return toElement(n);
+    }
+    return 0;
+}
+
+bool Node::isRootEditableElement() const
+{
+    return rendererIsEditable() && isElementNode() && (!parentNode() || !parentNode()->rendererIsEditable()
+        || !parentNode()->isElementNode() || hasTagName(bodyTag));
+}
+
+Element* Node::rootEditableElement(EditableType editableType) const
+{
+    if (editableType == HasEditableAXRole) {
+        if (AXObjectCache* cache = document()->existingAXObjectCache())
+            return const_cast<Element*>(cache->rootAXEditableElement(this));
+    }
+    
+    return rootEditableElement();
+}
+
+Element* Node::rootEditableElement() const
+{
+    Element* result = 0;
+    for (Node* n = const_cast<Node*>(this); n && n->rendererIsEditable(); n = n->parentNode()) {
+        if (n->isElementNode())
+            result = toElement(n);
+        if (n->hasTagName(bodyTag))
+            break;
+    }
+    return result;
+}
+
+bool Node::inSameContainingBlockFlowElement(Node *n)
+{
+    return n ? enclosingBlockFlowElement() == n->enclosingBlockFlowElement() : false;
+}
+
+// FIXME: End of obviously misplaced HTML editing functions.  Try to move these out of Node.
+
+PassRefPtr<NodeList> Node::getElementsByTagName(const AtomicString& localName)
+{
+    if (localName.isNull())
+        return 0;
+
+    if (document()->isHTMLDocument())
+        return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLTagNodeList>(this, HTMLTagNodeListType, localName);
+    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<TagNodeList>(this, TagNodeListType, localName);
+}
+
+PassRefPtr<NodeList> Node::getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName)
+{
+    if (localName.isNull())
+        return 0;
+
+    if (namespaceURI == starAtom)
+        return getElementsByTagName(localName);
+
+    return ensureRareData()->ensureNodeLists()->addCacheWithQualifiedName(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localName);
+}
+
+PassRefPtr<NodeList> Node::getElementsByName(const String& elementName)
+{
+    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<NameNodeList>(this, NameNodeListType, elementName);
+}
+
+PassRefPtr<NodeList> Node::getElementsByClassName(const String& classNames)
+{
+    return ensureRareData()->ensureNodeLists()->addCacheWithName<ClassNodeList>(this, ClassNodeListType, classNames);
+}
+
+PassRefPtr<RadioNodeList> Node::radioNodeList(const AtomicString& name)
+{
+    ASSERT(hasTagName(formTag) || hasTagName(fieldsetTag));
+    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<RadioNodeList>(this, RadioNodeListType, name);
+}
+
+PassRefPtr<Element> Node::querySelector(const AtomicString& selectors, ExceptionCode& ec)
+{
+    if (selectors.isEmpty()) {
+        ec = SYNTAX_ERR;
+        return 0;
+    }
+
+    SelectorQuery* selectorQuery = document()->selectorQueryCache()->add(selectors, document(), ec);
+    if (!selectorQuery)
+        return 0;
+    return selectorQuery->queryFirst(this);
+}
+
+PassRefPtr<NodeList> Node::querySelectorAll(const AtomicString& selectors, ExceptionCode& ec)
+{
+    if (selectors.isEmpty()) {
+        ec = SYNTAX_ERR;
+        return 0;
+    }
+
+    SelectorQuery* selectorQuery = document()->selectorQueryCache()->add(selectors, document(), ec);
+    if (!selectorQuery)
+        return 0;
+    return selectorQuery->queryAll(this);
+}
+
+Document *Node::ownerDocument() const
+{
+    Document *doc = document();
+    return doc == this ? 0 : doc;
+}
+
+KURL Node::baseURI() const
+{
+    return parentNode() ? parentNode()->baseURI() : KURL();
+}
+
+bool Node::isEqualNode(Node* other) const
+{
+    if (!other)
+        return false;
+    
+    NodeType nodeType = this->nodeType();
+    if (nodeType != other->nodeType())
+        return false;
+    
+    if (nodeName() != other->nodeName())
+        return false;
+    
+    if (localName() != other->localName())
+        return false;
+    
+    if (namespaceURI() != other->namespaceURI())
+        return false;
+    
+    if (prefix() != other->prefix())
+        return false;
+    
+    if (nodeValue() != other->nodeValue())
+        return false;
+    
+    if (isElementNode() && !toElement(this)->hasEquivalentAttributes(toElement(other)))
+        return false;
+    
+    Node* child = firstChild();
+    Node* otherChild = other->firstChild();
+    
+    while (child) {
+        if (!child->isEqualNode(otherChild))
+            return false;
+        
+        child = child->nextSibling();
+        otherChild = otherChild->nextSibling();
+    }
+    
+    if (otherChild)
+        return false;
+    
+    if (nodeType == DOCUMENT_TYPE_NODE) {
+        const DocumentType* documentTypeThis = static_cast<const DocumentType*>(this);
+        const DocumentType* documentTypeOther = static_cast<const DocumentType*>(other);
+        
+        if (documentTypeThis->publicId() != documentTypeOther->publicId())
+            return false;
+
+        if (documentTypeThis->systemId() != documentTypeOther->systemId())
+            return false;
+
+        if (documentTypeThis->internalSubset() != documentTypeOther->internalSubset())
+            return false;
+
+        // FIXME: We don't compare entities or notations because currently both are always empty.
+    }
+    
+    return true;
+}
+
+bool Node::isDefaultNamespace(const AtomicString& namespaceURIMaybeEmpty) const
+{
+    const AtomicString& namespaceURI = namespaceURIMaybeEmpty.isEmpty() ? nullAtom : namespaceURIMaybeEmpty;
+
+    switch (nodeType()) {
+        case ELEMENT_NODE: {
+            const Element* elem = toElement(this);
+            
+            if (elem->prefix().isNull())
+                return elem->namespaceURI() == namespaceURI;
+
+            if (elem->hasAttributes()) {
+                for (unsigned i = 0; i < elem->attributeCount(); i++) {
+                    const Attribute* attr = elem->attributeItem(i);
+                    
+                    if (attr->localName() == xmlnsAtom)
+                        return attr->value() == namespaceURI;
+                }
+            }
+
+            if (Element* ancestor = ancestorElement())
+                return ancestor->isDefaultNamespace(namespaceURI);
+
+            return false;
+        }
+        case DOCUMENT_NODE:
+            if (Element* de = toDocument(this)->documentElement())
+                return de->isDefaultNamespace(namespaceURI);
+            return false;
+        case ENTITY_NODE:
+        case NOTATION_NODE:
+        case DOCUMENT_TYPE_NODE:
+        case DOCUMENT_FRAGMENT_NODE:
+            return false;
+        case ATTRIBUTE_NODE: {
+            const Attr* attr = static_cast<const Attr*>(this);
+            if (attr->ownerElement())
+                return attr->ownerElement()->isDefaultNamespace(namespaceURI);
+            return false;
+        }
+        default:
+            if (Element* ancestor = ancestorElement())
+                return ancestor->isDefaultNamespace(namespaceURI);
+            return false;
+    }
+}
+
+String Node::lookupPrefix(const AtomicString &namespaceURI) const
+{
+    // Implemented according to
+    // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespacePrefixAlgo
+    
+    if (namespaceURI.isEmpty())
+        return String();
+    
+    switch (nodeType()) {
+        case ELEMENT_NODE:
+            return lookupNamespacePrefix(namespaceURI, static_cast<const Element *>(this));
+        case DOCUMENT_NODE:
+            if (Element* de = toDocument(this)->documentElement())
+                return de->lookupPrefix(namespaceURI);
+            return String();
+        case ENTITY_NODE:
+        case NOTATION_NODE:
+        case DOCUMENT_FRAGMENT_NODE:
+        case DOCUMENT_TYPE_NODE:
+            return String();
+        case ATTRIBUTE_NODE: {
+            const Attr *attr = static_cast<const Attr *>(this);
+            if (attr->ownerElement())
+                return attr->ownerElement()->lookupPrefix(namespaceURI);
+            return String();
+        }
+        default:
+            if (Element* ancestor = ancestorElement())
+                return ancestor->lookupPrefix(namespaceURI);
+            return String();
+    }
+}
+
+String Node::lookupNamespaceURI(const String &prefix) const
+{
+    // Implemented according to
+    // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespaceURIAlgo
+    
+    if (!prefix.isNull() && prefix.isEmpty())
+        return String();
+    
+    switch (nodeType()) {
+        case ELEMENT_NODE: {
+            const Element *elem = static_cast<const Element *>(this);
+            
+            if (!elem->namespaceURI().isNull() && elem->prefix() == prefix)
+                return elem->namespaceURI();
+            
+            if (elem->hasAttributes()) {
+                for (unsigned i = 0; i < elem->attributeCount(); i++) {
+                    const Attribute* attr = elem->attributeItem(i);
+                    
+                    if (attr->prefix() == xmlnsAtom && attr->localName() == prefix) {
+                        if (!attr->value().isEmpty())
+                            return attr->value();
+                        
+                        return String();
+                    } else if (attr->localName() == xmlnsAtom && prefix.isNull()) {
+                        if (!attr->value().isEmpty())
+                            return attr->value();
+                        
+                        return String();
+                    }
+                }
+            }
+            if (Element* ancestor = ancestorElement())
+                return ancestor->lookupNamespaceURI(prefix);
+            return String();
+        }
+        case DOCUMENT_NODE:
+            if (Element* de = toDocument(this)->documentElement())
+                return de->lookupNamespaceURI(prefix);
+            return String();
+        case ENTITY_NODE:
+        case NOTATION_NODE:
+        case DOCUMENT_TYPE_NODE:
+        case DOCUMENT_FRAGMENT_NODE:
+            return String();
+        case ATTRIBUTE_NODE: {
+            const Attr *attr = static_cast<const Attr *>(this);
+            
+            if (attr->ownerElement())
+                return attr->ownerElement()->lookupNamespaceURI(prefix);
+            else
+                return String();
+        }
+        default:
+            if (Element* ancestor = ancestorElement())
+                return ancestor->lookupNamespaceURI(prefix);
+            return String();
+    }
+}
+
+String Node::lookupNamespacePrefix(const AtomicString &_namespaceURI, const Element *originalElement) const
+{
+    if (_namespaceURI.isNull())
+        return String();
+            
+    if (originalElement->lookupNamespaceURI(prefix()) == _namespaceURI)
+        return prefix();
+    
+    ASSERT(isElementNode());
+    const Element* thisElement = toElement(this);
+    if (thisElement->hasAttributes()) {
+        for (unsigned i = 0; i < thisElement->attributeCount(); i++) {
+            const Attribute* attr = thisElement->attributeItem(i);
+            
+            if (attr->prefix() == xmlnsAtom && attr->value() == _namespaceURI
+                    && originalElement->lookupNamespaceURI(attr->localName()) == _namespaceURI)
+                return attr->localName();
+        }
+    }
+    
+    if (Element* ancestor = ancestorElement())
+        return ancestor->lookupNamespacePrefix(_namespaceURI, originalElement);
+    return String();
+}
+
+static void appendTextContent(const Node* node, bool convertBRsToNewlines, bool& isNullString, StringBuilder& content)
+{
+    switch (node->nodeType()) {
+    case Node::TEXT_NODE:
+    case Node::CDATA_SECTION_NODE:
+    case Node::COMMENT_NODE:
+        isNullString = false;
+        content.append(static_cast<const CharacterData*>(node)->data());
+        break;
+
+    case Node::PROCESSING_INSTRUCTION_NODE:
+        isNullString = false;
+        content.append(static_cast<const ProcessingInstruction*>(node)->data());
+        break;
+    
+    case Node::ELEMENT_NODE:
+        if (node->hasTagName(brTag) && convertBRsToNewlines) {
+            isNullString = false;
+            content.append('\n');
+            break;
+        }
+    // Fall through.
+    case Node::ATTRIBUTE_NODE:
+    case Node::ENTITY_NODE:
+    case Node::ENTITY_REFERENCE_NODE:
+    case Node::DOCUMENT_FRAGMENT_NODE:
+        isNullString = false;
+        for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
+            if (child->nodeType() == Node::COMMENT_NODE || child->nodeType() == Node::PROCESSING_INSTRUCTION_NODE)
+                continue;
+            appendTextContent(child, convertBRsToNewlines, isNullString, content);
+        }
+        break;
+
+    case Node::DOCUMENT_NODE:
+    case Node::DOCUMENT_TYPE_NODE:
+    case Node::NOTATION_NODE:
+    case Node::XPATH_NAMESPACE_NODE:
+        break;
+    }
+}
+
+String Node::textContent(bool convertBRsToNewlines) const
+{
+    StringBuilder content;
+    bool isNullString = true;
+    appendTextContent(this, convertBRsToNewlines, isNullString, content);
+    return isNullString ? String() : content.toString();
+}
+
+void Node::setTextContent(const String& text, ExceptionCode& ec)
+{           
+    switch (nodeType()) {
+        case TEXT_NODE:
+        case CDATA_SECTION_NODE:
+        case COMMENT_NODE:
+        case PROCESSING_INSTRUCTION_NODE:
+            setNodeValue(text, ec);
+            return;
+        case ELEMENT_NODE:
+        case ATTRIBUTE_NODE:
+        case ENTITY_NODE:
+        case ENTITY_REFERENCE_NODE:
+        case DOCUMENT_FRAGMENT_NODE: {
+            RefPtr<ContainerNode> container = toContainerNode(this);
+            ChildListMutationScope mutation(this);
+            container->removeChildren();
+            if (!text.isEmpty())
+                container->appendChild(document()->createTextNode(text), ec);
+            return;
+        }
+        case DOCUMENT_NODE:
+        case DOCUMENT_TYPE_NODE:
+        case NOTATION_NODE:
+        case XPATH_NAMESPACE_NODE:
+            // Do nothing.
+            return;
+    }
+    ASSERT_NOT_REACHED();
+}
+
+Element* Node::ancestorElement() const
+{
+    // In theory, there can be EntityReference nodes between elements, but this is currently not supported.
+    for (ContainerNode* n = parentNode(); n; n = n->parentNode()) {
+        if (n->isElementNode())
+            return toElement(n);
+    }
+    return 0;
+}
+
+bool Node::offsetInCharacters() const
+{
+    return false;
+}
+
+unsigned short Node::compareDocumentPosition(Node* otherNode)
+{
+    return compareDocumentPositionInternal(otherNode, TreatShadowTreesAsDisconnected);
+}
+
+unsigned short Node::compareDocumentPositionInternal(Node* otherNode, ShadowTreesTreatment treatment)
+{
+    // It is not clear what should be done if |otherNode| is 0.
+    if (!otherNode)
+        return DOCUMENT_POSITION_DISCONNECTED;
+
+    if (otherNode == this)
+        return DOCUMENT_POSITION_EQUIVALENT;
+    
+    Attr* attr1 = nodeType() == ATTRIBUTE_NODE ? static_cast<Attr*>(this) : 0;
+    Attr* attr2 = otherNode->nodeType() == ATTRIBUTE_NODE ? static_cast<Attr*>(otherNode) : 0;
+    
+    Node* start1 = attr1 ? attr1->ownerElement() : this;
+    Node* start2 = attr2 ? attr2->ownerElement() : otherNode;
+    
+    // If either of start1 or start2 is null, then we are disconnected, since one of the nodes is
+    // an orphaned attribute node.
+    if (!start1 || !start2)
+        return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
+
+    Vector<Node*, 16> chain1;
+    Vector<Node*, 16> chain2;
+    if (attr1)
+        chain1.append(attr1);
+    if (attr2)
+        chain2.append(attr2);
+    
+    if (attr1 && attr2 && start1 == start2 && start1) {
+        // We are comparing two attributes on the same node. Crawl our attribute map and see which one we hit first.
+        Element* owner1 = attr1->ownerElement();
+        owner1->synchronizeAllAttributes();
+        unsigned length = owner1->attributeCount();
+        for (unsigned i = 0; i < length; ++i) {
+            // If neither of the two determining nodes is a child node and nodeType is the same for both determining nodes, then an 
+            // implementation-dependent order between the determining nodes is returned. This order is stable as long as no nodes of
+            // the same nodeType are inserted into or removed from the direct container. This would be the case, for example, 
+            // when comparing two attributes of the same element, and inserting or removing additional attributes might change 
+            // the order between existing attributes.
+            const Attribute* attribute = owner1->attributeItem(i);
+            if (attr1->qualifiedName() == attribute->name())
+                return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_FOLLOWING;
+            if (attr2->qualifiedName() == attribute->name())
+                return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_PRECEDING;
+        }
+        
+        ASSERT_NOT_REACHED();
+        return DOCUMENT_POSITION_DISCONNECTED;
+    }
+
+    // If one node is in the document and the other is not, we must be disconnected.
+    // If the nodes have different owning documents, they must be disconnected.  Note that we avoid
+    // comparing Attr nodes here, since they return false from inDocument() all the time (which seems like a bug).
+    if (start1->inDocument() != start2->inDocument())
+        return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
+    if (treatment == TreatShadowTreesAsDisconnected && start1->treeScope() != start2->treeScope())
+        return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
+
+    // We need to find a common ancestor container, and then compare the indices of the two immediate children.
+    Node* current;
+    for (current = start1; current; current = current->parentOrShadowHostNode())
+        chain1.append(current);
+    for (current = start2; current; current = current->parentOrShadowHostNode())
+        chain2.append(current);
+
+    unsigned index1 = chain1.size();
+    unsigned index2 = chain2.size();
+
+    // If the two elements don't have a common root, they're not in the same tree.
+    if (chain1[index1 - 1] != chain2[index2 - 1]) {
+        unsigned short direction = (start1 > start2) ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING;
+        return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction;
+    }
+
+    unsigned connection = start1->treeScope() != start2->treeScope() ? DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 0;
+
+    // Walk the two chains backwards and look for the first difference.
+    for (unsigned i = min(index1, index2); i; --i) {
+        Node* child1 = chain1[--index1];
+        Node* child2 = chain2[--index2];
+        if (child1 != child2) {
+            // If one of the children is an attribute, it wins.
+            if (child1->nodeType() == ATTRIBUTE_NODE)
+                return DOCUMENT_POSITION_FOLLOWING | connection;
+            if (child2->nodeType() == ATTRIBUTE_NODE)
+                return DOCUMENT_POSITION_PRECEDING | connection;
+
+            // If one of the children is a shadow root,
+            if (child1->isShadowRoot() || child2->isShadowRoot()) {
+                if (!child2->isShadowRoot())
+                    return Node::DOCUMENT_POSITION_FOLLOWING | connection;
+                if (!child1->isShadowRoot())
+                    return Node::DOCUMENT_POSITION_PRECEDING | connection;
+
+                for (ShadowRoot* child = toShadowRoot(child2)->olderShadowRoot(); child; child = child->olderShadowRoot())
+                    if (child == child1)
+                        return Node::DOCUMENT_POSITION_FOLLOWING | connection;
+
+                return Node::DOCUMENT_POSITION_PRECEDING | connection;
+            }
+
+            if (!child2->nextSibling())
+                return DOCUMENT_POSITION_FOLLOWING | connection;
+            if (!child1->nextSibling())
+                return DOCUMENT_POSITION_PRECEDING | connection;
+
+            // Otherwise we need to see which node occurs first.  Crawl backwards from child2 looking for child1.
+            for (Node* child = child2->previousSibling(); child; child = child->previousSibling()) {
+                if (child == child1)
+                    return DOCUMENT_POSITION_FOLLOWING | connection;
+            }
+            return DOCUMENT_POSITION_PRECEDING | connection;
+        }
+    }
+    
+    // There was no difference between the two parent chains, i.e., one was a subset of the other.  The shorter
+    // chain is the ancestor.
+    return index1 < index2 ? 
+               DOCUMENT_POSITION_FOLLOWING | DOCUMENT_POSITION_CONTAINED_BY | connection :
+               DOCUMENT_POSITION_PRECEDING | DOCUMENT_POSITION_CONTAINS | connection;
+}
+
+FloatPoint Node::convertToPage(const FloatPoint& p) const
+{
+    // If there is a renderer, just ask it to do the conversion
+    if (renderer())
+        return renderer()->localToAbsolute(p, UseTransforms);
+    
+    // Otherwise go up the tree looking for a renderer
+    Element *parent = ancestorElement();
+    if (parent)
+        return parent->convertToPage(p);
+
+    // No parent - no conversion needed
+    return p;
+}
+
+FloatPoint Node::convertFromPage(const FloatPoint& p) const
+{
+    // If there is a renderer, just ask it to do the conversion
+    if (renderer())
+        return renderer()->absoluteToLocal(p, UseTransforms);
+
+    // Otherwise go up the tree looking for a renderer
+    Element *parent = ancestorElement();
+    if (parent)
+        return parent->convertFromPage(p);
+
+    // No parent - no conversion needed
+    return p;
+}
+
+#ifndef NDEBUG
+
+String Node::debugName() const
+{
+    StringBuilder name;
+    name.append(nodeName());
+
+    if (hasID()) {
+        name.appendLiteral(" id=\'");
+        name.append(toElement(this)->getIdAttribute());
+        name.append('\'');
+    }
+
+    if (hasClass()) {
+        name.appendLiteral(" class=\'");
+        const StyledElement* styledElement = static_cast<const StyledElement*>(this);
+        for (size_t i = 0; i < styledElement->classNames().size(); ++i) {
+            if (i > 0)
+                name.append(' ');
+            name.append(styledElement->classNames()[i]);
+        }
+        name.append('\'');
+    }
+
+    return name.toString();
+}
+
+static void appendAttributeDesc(const Node* node, StringBuilder& stringBuilder, const QualifiedName& name, const char* attrDesc)
+{
+    if (!node->isElementNode())
+        return;
+
+    String attr = toElement(node)->getAttribute(name);
+    if (attr.isEmpty())
+        return;
+
+    stringBuilder.append(attrDesc);
+    stringBuilder.append(attr);
+}
+
+void Node::showNode(const char* prefix) const
+{
+    if (!prefix)
+        prefix = "";
+    if (isTextNode()) {
+        String value = nodeValue();
+        value.replaceWithLiteral('\\', "\\\\");
+        value.replaceWithLiteral('\n', "\\n");
+        fprintf(stderr, "%s%s\t%p \"%s\"\n", prefix, nodeName().utf8().data(), this, value.utf8().data());
+    } else {
+        StringBuilder attrs;
+        appendAttributeDesc(this, attrs, classAttr, " CLASS=");
+        appendAttributeDesc(this, attrs, styleAttr, " STYLE=");
+        fprintf(stderr, "%s%s\t%p%s\n", prefix, nodeName().utf8().data(), this, attrs.toString().utf8().data());
+    }
+}
+
+void Node::showTreeForThis() const
+{
+    showTreeAndMark(this, "*");
+}
+
+void Node::showNodePathForThis() const
+{
+    Vector<const Node*, 16> chain;
+    const Node* node = this;
+    while (node->parentOrShadowHostNode()) {
+        chain.append(node);
+        node = node->parentOrShadowHostNode();
+    }
+    for (unsigned index = chain.size(); index > 0; --index) {
+        const Node* node = chain[index - 1];
+        if (node->isShadowRoot()) {
+            int count = 0;
+            for (ShadowRoot* shadowRoot = oldestShadowRootFor(toShadowRoot(node)->host()); shadowRoot && shadowRoot != node; shadowRoot = shadowRoot->youngerShadowRoot())
+                ++count;
+            fprintf(stderr, "/#shadow-root[%d]", count);
+            continue;
+        }
+
+        switch (node->nodeType()) {
+        case ELEMENT_NODE: {
+            fprintf(stderr, "/%s", node->nodeName().utf8().data());
+
+            const Element* element = toElement(node);
+            const AtomicString& idattr = element->getIdAttribute();
+            bool hasIdAttr = !idattr.isNull() && !idattr.isEmpty();
+            if (node->previousSibling() || node->nextSibling()) {
+                int count = 0;
+                for (Node* previous = node->previousSibling(); previous; previous = previous->previousSibling())
+                    if (previous->nodeName() == node->nodeName())
+                        ++count;
+                if (hasIdAttr)
+                    fprintf(stderr, "[@id=\"%s\" and position()=%d]", idattr.string().utf8().data(), count);
+                else
+                    fprintf(stderr, "[%d]", count);
+            } else if (hasIdAttr)
+                fprintf(stderr, "[@id=\"%s\"]", idattr.string().utf8().data());
+            break;
+        }
+        case TEXT_NODE:
+            fprintf(stderr, "/text()");
+            break;
+        case ATTRIBUTE_NODE:
+            fprintf(stderr, "/@%s", node->nodeName().utf8().data());
+            break;
+        default:
+            break;
+        }
+    }
+    fprintf(stderr, "\n");
+}
+
+static void traverseTreeAndMark(const String& baseIndent, const Node* rootNode, const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2)
+{
+    for (const Node* node = rootNode; node; node = NodeTraversal::next(node)) {
+        if (node == markedNode1)
+            fprintf(stderr, "%s", markedLabel1);
+        if (node == markedNode2)
+            fprintf(stderr, "%s", markedLabel2);
+
+        StringBuilder indent;
+        indent.append(baseIndent);
+        for (const Node* tmpNode = node; tmpNode && tmpNode != rootNode; tmpNode = tmpNode->parentOrShadowHostNode())
+            indent.append('\t');
+        fprintf(stderr, "%s", indent.toString().utf8().data());
+        node->showNode();
+        indent.append('\t');
+        if (node->isShadowRoot()) {
+            if (ShadowRoot* youngerShadowRoot = toShadowRoot(node)->youngerShadowRoot())
+                traverseTreeAndMark(indent.toString(), youngerShadowRoot, markedNode1, markedLabel1, markedNode2, markedLabel2);
+        } else if (ShadowRoot* oldestShadowRoot = oldestShadowRootFor(node))
+            traverseTreeAndMark(indent.toString(), oldestShadowRoot, markedNode1, markedLabel1, markedNode2, markedLabel2);
+    }
+}
+
+void Node::showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2) const
+{
+    const Node* rootNode;
+    const Node* node = this;
+    while (node->parentOrShadowHostNode() && !node->hasTagName(bodyTag))
+        node = node->parentOrShadowHostNode();
+    rootNode = node;
+
+    String startingIndent;
+    traverseTreeAndMark(startingIndent, rootNode, markedNode1, markedLabel1, markedNode2, markedLabel2);
+}
+
+void Node::formatForDebugger(char* buffer, unsigned length) const
+{
+    String result;
+    String s;
+
+    s = nodeName();
+    if (s.isEmpty())
+        result = "<none>";
+    else
+        result = s;
+
+    strncpy(buffer, result.utf8().data(), length - 1);
+}
+
+static ContainerNode* parentOrShadowHostOrFrameOwner(const Node* node)
+{
+    ContainerNode* parent = node->parentOrShadowHostNode();
+    if (!parent && node->document() && node->document()->frame())
+        parent = node->document()->frame()->ownerElement();
+    return parent;
+}
+
+static void showSubTreeAcrossFrame(const Node* node, const Node* markedNode, const String& indent)
+{
+    if (node == markedNode)
+        fputs("*", stderr);
+    fputs(indent.utf8().data(), stderr);
+    node->showNode();
+     if (node->isShadowRoot()) {
+         if (ShadowRoot* youngerShadowRoot = toShadowRoot(node)->youngerShadowRoot())
+             showSubTreeAcrossFrame(youngerShadowRoot, markedNode, indent + "\t");
+     } else {
+         if (node->isFrameOwnerElement())
+             showSubTreeAcrossFrame(static_cast<const HTMLFrameOwnerElement*>(node)->contentDocument(), markedNode, indent + "\t");
+         if (ShadowRoot* oldestShadowRoot = oldestShadowRootFor(node))
+             showSubTreeAcrossFrame(oldestShadowRoot, markedNode, indent + "\t");
+     }
+    for (Node* child = node->firstChild(); child; child = child->nextSibling())
+        showSubTreeAcrossFrame(child, markedNode, indent + "\t");
+}
+
+void Node::showTreeForThisAcrossFrame() const
+{
+    Node* rootNode = const_cast<Node*>(this);
+    while (parentOrShadowHostOrFrameOwner(rootNode))
+        rootNode = parentOrShadowHostOrFrameOwner(rootNode);
+    showSubTreeAcrossFrame(rootNode, this, "");
+}
+
+#endif
+
+// --------
+
+void NodeListsNodeData::invalidateCaches(const QualifiedName* attrName)
+{
+    NodeListAtomicNameCacheMap::const_iterator atomicNameCacheEnd = m_atomicNameCaches.end();
+    for (NodeListAtomicNameCacheMap::const_iterator it = m_atomicNameCaches.begin(); it != atomicNameCacheEnd; ++it)
+        it->value->invalidateCache(attrName);
+
+    NodeListNameCacheMap::const_iterator nameCacheEnd = m_nameCaches.end();
+    for (NodeListNameCacheMap::const_iterator it = m_nameCaches.begin(); it != nameCacheEnd; ++it)
+        it->value->invalidateCache(attrName);
+
+    if (attrName)
+        return;
+
+    TagNodeListCacheNS::iterator tagCacheEnd = m_tagNodeListCacheNS.end();
+    for (TagNodeListCacheNS::iterator it = m_tagNodeListCacheNS.begin(); it != tagCacheEnd; ++it)
+        it->value->invalidateCache();
+}
+
+void Node::getSubresourceURLs(ListHashSet<KURL>& urls) const
+{
+    addSubresourceAttributeURLs(urls);
+}
+
+Node* Node::enclosingLinkEventParentOrSelf()
+{
+    for (Node* node = this; node; node = node->parentOrShadowHostNode()) {
+        // For imagemaps, the enclosing link node is the associated area element not the image itself.
+        // So we don't let images be the enclosingLinkNode, even though isLink sometimes returns true
+        // for them.
+        if (node->isLink() && !node->hasTagName(imgTag))
+            return node;
+    }
+
+    return 0;
+}
+
+const AtomicString& Node::interfaceName() const
+{
+    return eventNames().interfaceForNode;
+}
+
+ScriptExecutionContext* Node::scriptExecutionContext() const
+{
+    return document();
+}
+
+void Node::didMoveToNewDocument(Document* oldDocument)
+{
+    TreeScopeAdopter::ensureDidMoveToNewDocumentWasCalled(oldDocument);
+
+    if (const EventTargetData* eventTargetData = this->eventTargetData()) {
+        const EventListenerMap& listenerMap = eventTargetData->eventListenerMap;
+        if (!listenerMap.isEmpty()) {
+            Vector<AtomicString> types = listenerMap.eventTypes();
+            for (unsigned i = 0; i < types.size(); ++i)
+                document()->addListenerTypeIfNeeded(types[i]);
+        }
+    }
+
+    if (AXObjectCache::accessibilityEnabled() && oldDocument)
+        if (AXObjectCache* cache = oldDocument->existingAXObjectCache())
+            cache->remove(this);
+
+    const EventListenerVector& wheelListeners = getEventListeners(eventNames().mousewheelEvent);
+    for (size_t i = 0; i < wheelListeners.size(); ++i) {
+        oldDocument->didRemoveWheelEventHandler();
+        document()->didAddWheelEventHandler();
+    }
+
+    Vector<AtomicString> touchEventNames = eventNames().touchEventNames();
+    for (size_t i = 0; i < touchEventNames.size(); ++i) {
+        const EventListenerVector& listeners = getEventListeners(touchEventNames[i]);
+        for (size_t j = 0; j < listeners.size(); ++j) {
+            oldDocument->didRemoveTouchEventHandler(this);
+            document()->didAddTouchEventHandler(this);
+        }
+    }
+
+    if (Vector<OwnPtr<MutationObserverRegistration> >* registry = mutationObserverRegistry()) {
+        for (size_t i = 0; i < registry->size(); ++i) {
+            document()->addMutationObserverTypes(registry->at(i)->mutationTypes());
+        }
+    }
+
+    if (HashSet<MutationObserverRegistration*>* transientRegistry = transientMutationObserverRegistry()) {
+        for (HashSet<MutationObserverRegistration*>::iterator iter = transientRegistry->begin(); iter != transientRegistry->end(); ++iter) {
+            document()->addMutationObserverTypes((*iter)->mutationTypes());
+        }
+    }
+}
+
+static inline bool tryAddEventListener(Node* targetNode, const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
+{
+    if (!targetNode->EventTarget::addEventListener(eventType, listener, useCapture))
+        return false;
+
+    if (Document* document = targetNode->document()) {
+        document->addListenerTypeIfNeeded(eventType);
+        if (eventType == eventNames().mousewheelEvent)
+            document->didAddWheelEventHandler();
+        else if (eventNames().isTouchEventType(eventType))
+            document->didAddTouchEventHandler(targetNode);
+    }
+
+    return true;
+}
+
+bool Node::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
+{
+    return tryAddEventListener(this, eventType, listener, useCapture);
+}
+
+static inline bool tryRemoveEventListener(Node* targetNode, const AtomicString& eventType, EventListener* listener, bool useCapture)
+{
+    if (!targetNode->EventTarget::removeEventListener(eventType, listener, useCapture))
+        return false;
+
+    // FIXME: Notify Document that the listener has vanished. We need to keep track of a number of
+    // listeners for each type, not just a bool - see https://bugs.webkit.org/show_bug.cgi?id=33861
+    if (Document* document = targetNode->document()) {
+        if (eventType == eventNames().mousewheelEvent)
+            document->didRemoveWheelEventHandler();
+        else if (eventNames().isTouchEventType(eventType))
+            document->didRemoveTouchEventHandler(targetNode);
+    }
+
+    return true;
+}
+
+bool Node::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
+{
+    return tryRemoveEventListener(this, eventType, listener, useCapture);
+}
+
+typedef HashMap<Node*, OwnPtr<EventTargetData> > EventTargetDataMap;
+
+static EventTargetDataMap& eventTargetDataMap()
+{
+    DEFINE_STATIC_LOCAL(EventTargetDataMap, map, ());
+    return map;
+}
+
+EventTargetData* Node::eventTargetData()
+{
+    return hasEventTargetData() ? eventTargetDataMap().get(this) : 0;
+}
+
+EventTargetData* Node::ensureEventTargetData()
+{
+    if (hasEventTargetData())
+        return eventTargetDataMap().get(this);
+    setHasEventTargetData(true);
+    EventTargetData* data = new EventTargetData;
+    eventTargetDataMap().set(this, adoptPtr(data));
+    return data;
+}
+
+void Node::clearEventTargetData()
+{
+    eventTargetDataMap().remove(this);
+}
+
+Vector<OwnPtr<MutationObserverRegistration> >* Node::mutationObserverRegistry()
+{
+    if (!hasRareData())
+        return 0;
+    NodeMutationObserverData* data = rareData()->mutationObserverData();
+    if (!data)
+        return 0;
+    return &data->registry;
+}
+
+HashSet<MutationObserverRegistration*>* Node::transientMutationObserverRegistry()
+{
+    if (!hasRareData())
+        return 0;
+    NodeMutationObserverData* data = rareData()->mutationObserverData();
+    if (!data)
+        return 0;
+    return &data->transientRegistry;
+}
+
+template<typename Registry>
+static inline void collectMatchingObserversForMutation(HashMap<MutationObserver*, MutationRecordDeliveryOptions>& observers, Registry* registry, Node* target, MutationObserver::MutationType type, const QualifiedName* attributeName)
+{
+    if (!registry)
+        return;
+    for (typename Registry::iterator iter = registry->begin(); iter != registry->end(); ++iter) {
+        const MutationObserverRegistration& registration = **iter;
+        if (registration.shouldReceiveMutationFrom(target, type, attributeName)) {
+            MutationRecordDeliveryOptions deliveryOptions = registration.deliveryOptions();
+            HashMap<MutationObserver*, MutationRecordDeliveryOptions>::AddResult result = observers.add(registration.observer(), deliveryOptions);
+            if (!result.isNewEntry)
+                result.iterator->value |= deliveryOptions;
+        }
+    }
+}
+
+void Node::getRegisteredMutationObserversOfType(HashMap<MutationObserver*, MutationRecordDeliveryOptions>& observers, MutationObserver::MutationType type, const QualifiedName* attributeName)
+{
+    ASSERT((type == MutationObserver::Attributes && attributeName) || !attributeName);
+    collectMatchingObserversForMutation(observers, mutationObserverRegistry(), this, type, attributeName);
+    collectMatchingObserversForMutation(observers, transientMutationObserverRegistry(), this, type, attributeName);
+    for (Node* node = parentNode(); node; node = node->parentNode()) {
+        collectMatchingObserversForMutation(observers, node->mutationObserverRegistry(), this, type, attributeName);
+        collectMatchingObserversForMutation(observers, node->transientMutationObserverRegistry(), this, type, attributeName);
+    }
+}
+
+void Node::registerMutationObserver(MutationObserver* observer, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter)
+{
+    MutationObserverRegistration* registration = 0;
+    Vector<OwnPtr<MutationObserverRegistration> >& registry = ensureRareData()->ensureMutationObserverData()->registry;
+    for (size_t i = 0; i < registry.size(); ++i) {
+        if (registry[i]->observer() == observer) {
+            registration = registry[i].get();
+            registration->resetObservation(options, attributeFilter);
+        }
+    }
+
+    if (!registration) {
+        registry.append(MutationObserverRegistration::create(observer, this, options, attributeFilter));
+        registration = registry.last().get();
+    }
+
+    document()->addMutationObserverTypes(registration->mutationTypes());
+}
+
+void Node::unregisterMutationObserver(MutationObserverRegistration* registration)
+{
+    Vector<OwnPtr<MutationObserverRegistration> >* registry = mutationObserverRegistry();
+    ASSERT(registry);
+    if (!registry)
+        return;
+
+    size_t index = registry->find(registration);
+    ASSERT(index != notFound);
+    if (index == notFound)
+        return;
+
+    registry->remove(index);
+}
+
+void Node::registerTransientMutationObserver(MutationObserverRegistration* registration)
+{
+    ensureRareData()->ensureMutationObserverData()->transientRegistry.add(registration);
+}
+
+void Node::unregisterTransientMutationObserver(MutationObserverRegistration* registration)
+{
+    HashSet<MutationObserverRegistration*>* transientRegistry = transientMutationObserverRegistry();
+    ASSERT(transientRegistry);
+    if (!transientRegistry)
+        return;
+
+    ASSERT(transientRegistry->contains(registration));
+    transientRegistry->remove(registration);
+}
+
+void Node::notifyMutationObserversNodeWillDetach()
+{
+    if (!document()->hasMutationObservers())
+        return;
+
+    for (Node* node = parentNode(); node; node = node->parentNode()) {
+        if (Vector<OwnPtr<MutationObserverRegistration> >* registry = node->mutationObserverRegistry()) {
+            const size_t size = registry->size();
+            for (size_t i = 0; i < size; ++i)
+                registry->at(i)->observedSubtreeNodeWillDetach(this);
+        }
+
+        if (HashSet<MutationObserverRegistration*>* transientRegistry = node->transientMutationObserverRegistry()) {
+            for (HashSet<MutationObserverRegistration*>::iterator iter = transientRegistry->begin(); iter != transientRegistry->end(); ++iter)
+                (*iter)->observedSubtreeNodeWillDetach(this);
+        }
+    }
+}
+
+void Node::handleLocalEvents(Event* event)
+{
+    if (!hasEventTargetData())
+        return;
+
+    if (isDisabledFormControl(this) && event->isMouseEvent())
+        return;
+
+    fireEventListeners(event);
+}
+
+void Node::dispatchScopedEvent(PassRefPtr<Event> event)
+{
+    dispatchScopedEventDispatchMediator(EventDispatchMediator::create(event));
+}
+
+void Node::dispatchScopedEventDispatchMediator(PassRefPtr<EventDispatchMediator> eventDispatchMediator)
+{
+    EventDispatcher::dispatchScopedEvent(this, eventDispatchMediator);
+}
+
+bool Node::dispatchEvent(PassRefPtr<Event> event)
+{
+    if (event->isMouseEvent())
+        return EventDispatcher::dispatchEvent(this, MouseEventDispatchMediator::create(adoptRef(toMouseEvent(event.leakRef())), MouseEventDispatchMediator::SyntheticMouseEvent));
+    if (event->isTouchEvent())
+        return dispatchTouchEvent(adoptRef(toTouchEvent(event.leakRef())));
+    return EventDispatcher::dispatchEvent(this, EventDispatchMediator::create(event));
+}
+
+void Node::dispatchSubtreeModifiedEvent()
+{
+    if (isInShadowTree())
+        return;
+
+    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
+
+    if (!document()->hasListenerType(Document::DOMSUBTREEMODIFIED_LISTENER))
+        return;
+
+    dispatchScopedEvent(MutationEvent::create(eventNames().DOMSubtreeModifiedEvent, true));
+}
+
+void Node::dispatchFocusInEvent(const AtomicString& eventType, PassRefPtr<Node> oldFocusedNode)
+{
+    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
+    ASSERT(eventType == eventNames().focusinEvent || eventType == eventNames().DOMFocusInEvent);
+    dispatchScopedEventDispatchMediator(FocusInEventDispatchMediator::create(FocusEvent::create(eventType, true, false, document()->defaultView(), 0, oldFocusedNode)));
+}
+
+void Node::dispatchFocusOutEvent(const AtomicString& eventType, PassRefPtr<Node> newFocusedNode)
+{
+    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
+    ASSERT(eventType == eventNames().focusoutEvent || eventType == eventNames().DOMFocusOutEvent);
+    dispatchScopedEventDispatchMediator(FocusOutEventDispatchMediator::create(FocusEvent::create(eventType, true, false, document()->defaultView(), 0, newFocusedNode)));
+}
+
+bool Node::dispatchDOMActivateEvent(int detail, PassRefPtr<Event> underlyingEvent)
+{
+    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
+    RefPtr<UIEvent> event = UIEvent::create(eventNames().DOMActivateEvent, true, true, document()->defaultView(), detail);
+    event->setUnderlyingEvent(underlyingEvent);
+    dispatchScopedEvent(event);
+    return event->defaultHandled();
+}
+
+bool Node::dispatchKeyEvent(const PlatformKeyboardEvent& event)
+{
+    return EventDispatcher::dispatchEvent(this, KeyboardEventDispatchMediator::create(KeyboardEvent::create(event, document()->defaultView())));
+}
+
+bool Node::dispatchMouseEvent(const PlatformMouseEvent& event, const AtomicString& eventType,
+    int detail, Node* relatedTarget)
+{
+    return EventDispatcher::dispatchEvent(this, MouseEventDispatchMediator::create(MouseEvent::create(eventType, document()->defaultView(), event, detail, relatedTarget)));
+}
+
+bool Node::dispatchGestureEvent(const PlatformGestureEvent& event)
+{
+    RefPtr<GestureEvent> gestureEvent = GestureEvent::create(document()->defaultView(), event);
+    if (!gestureEvent.get())
+        return false;
+    return EventDispatcher::dispatchEvent(this, GestureEventDispatchMediator::create(gestureEvent));
+}
+
+bool Node::dispatchTouchEvent(PassRefPtr<TouchEvent> event)
+{
+    return EventDispatcher::dispatchEvent(this, TouchEventDispatchMediator::create(event));
+}
+
+void Node::dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions eventOptions, SimulatedClickVisualOptions visualOptions)
+{
+    EventDispatcher::dispatchSimulatedClick(this, underlyingEvent, eventOptions, visualOptions);
+}
+
+bool Node::dispatchBeforeLoadEvent(const String& sourceURL)
+{
+    if (!document()->hasListenerType(Document::BEFORELOAD_LISTENER))
+        return true;
+
+    RefPtr<Node> protector(this);
+    RefPtr<BeforeLoadEvent> beforeLoadEvent = BeforeLoadEvent::create(sourceURL);
+    dispatchEvent(beforeLoadEvent.get());
+    return !beforeLoadEvent->defaultPrevented();
+}
+
+bool Node::dispatchWheelEvent(const PlatformWheelEvent& event)
+{
+    return EventDispatcher::dispatchEvent(this, WheelEventDispatchMediator::create(event, document()->defaultView()));
+}
+
+void Node::dispatchFocusEvent(PassRefPtr<Node> oldFocusedNode, FocusDirection)
+{
+    if (document()->page())
+        document()->page()->chrome()->client()->elementDidFocus(this);
+
+    RefPtr<FocusEvent> event = FocusEvent::create(eventNames().focusEvent, false, false, document()->defaultView(), 0, oldFocusedNode);
+    EventDispatcher::dispatchEvent(this, FocusEventDispatchMediator::create(event.release()));
+}
+
+void Node::dispatchBlurEvent(PassRefPtr<Node> newFocusedNode)
+{
+    if (document()->page())
+        document()->page()->chrome()->client()->elementDidBlur(this);
+
+    RefPtr<FocusEvent> event = FocusEvent::create(eventNames().blurEvent, false, false, document()->defaultView(), 0, newFocusedNode);
+    EventDispatcher::dispatchEvent(this, BlurEventDispatchMediator::create(event.release()));
+}
+
+void Node::dispatchChangeEvent()
+{
+    dispatchScopedEvent(Event::create(eventNames().changeEvent, true, false));
+}
+
+void Node::dispatchInputEvent()
+{
+    dispatchScopedEvent(Event::create(eventNames().inputEvent, true, false));
+}
+
+void Node::defaultEventHandler(Event* event)
+{
+    if (event->target() != this)
+        return;
+    const AtomicString& eventType = event->type();
+    if (eventType == eventNames().keydownEvent || eventType == eventNames().keypressEvent) {
+        if (event->isKeyboardEvent())
+            if (Frame* frame = document()->frame())
+                frame->eventHandler()->defaultKeyboardEventHandler(static_cast<KeyboardEvent*>(event));
+    } else if (eventType == eventNames().clickEvent) {
+        int detail = event->isUIEvent() ? static_cast<UIEvent*>(event)->detail() : 0;
+        if (dispatchDOMActivateEvent(detail, event))
+            event->setDefaultHandled();
+    } else if (eventType == eventNames().contextmenuEvent) {
+        if (Frame* frame = document()->frame())
+            if (Page* page = frame->page())
+                page->contextMenuController()->handleContextMenuEvent(event);
+    } else if (eventType == eventNames().textInputEvent) {
+        if (event->hasInterface(eventNames().interfaceForTextEvent))
+            if (Frame* frame = document()->frame())
+                frame->eventHandler()->defaultTextInputEventHandler(static_cast<TextEvent*>(event));
+#if ENABLE(PAN_SCROLLING)
+    } else if (eventType == eventNames().mousedownEvent && event->isMouseEvent()) {
+        MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
+        if (mouseEvent->button() == MiddleButton) {
+            if (enclosingLinkEventParentOrSelf())
+                return;
+
+            RenderObject* renderer = this->renderer();
+            while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()))
+                renderer = renderer->parent();
+
+            if (renderer) {
+                if (Frame* frame = document()->frame())
+                    frame->eventHandler()->startPanScrolling(renderer);
+            }
+        }
+#endif
+    } else if (eventType == eventNames().mousewheelEvent && event->hasInterface(eventNames().interfaceForWheelEvent)) {
+        WheelEvent* wheelEvent = static_cast<WheelEvent*>(event);
+
+        // If we don't have a renderer, send the wheel event to the first node we find with a renderer.
+        // This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll.
+        Node* startNode = this;
+        while (startNode && !startNode->renderer())
+            startNode = startNode->parentOrShadowHostNode();
+        
+        if (startNode && startNode->renderer())
+            if (Frame* frame = document()->frame())
+                frame->eventHandler()->defaultWheelEventHandler(startNode, wheelEvent);
+    } else if (event->type() == eventNames().webkitEditableContentChangedEvent) {
+        dispatchInputEvent();
+    }
+}
+
+bool Node::willRespondToMouseMoveEvents()
+{
+    if (isDisabledFormControl(this))
+        return false;
+    return hasEventListeners(eventNames().mousemoveEvent) || hasEventListeners(eventNames().mouseoverEvent) || hasEventListeners(eventNames().mouseoutEvent);
+}
+
+bool Node::willRespondToMouseClickEvents()
+{
+    if (isDisabledFormControl(this))
+        return false;
+    return isContentEditable(UserSelectAllIsAlwaysNonEditable) || hasEventListeners(eventNames().mouseupEvent) || hasEventListeners(eventNames().mousedownEvent) || hasEventListeners(eventNames().clickEvent) || hasEventListeners(eventNames().DOMActivateEvent);
+}
+
+bool Node::willRespondToTouchEvents()
+{
+    if (isDisabledFormControl(this))
+        return false;
+    return hasEventListeners(eventNames().touchstartEvent) || hasEventListeners(eventNames().touchmoveEvent) || hasEventListeners(eventNames().touchcancelEvent) || hasEventListeners(eventNames().touchendEvent);
+}
+
+// This is here for inlining
+inline void TreeScope::removedLastRefToScope()
+{
+    ASSERT(!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
+        // removeDetachedChildren returns, so we guard ourselves with an
+        // extra self-only ref.
+        guardRef();
+        dispose();
+#ifndef NDEBUG
+        // We need to do this right now since guardDeref() can delete this.
+        rootNode()->m_inRemovedLastRefFunction = false;
+#endif
+        guardDeref();
+    } else {
+#ifndef NDEBUG
+        rootNode()->m_inRemovedLastRefFunction = false;
+        beginDeletion();
+#endif
+        delete this;
+    }
+}
+
+// It's important not to inline removedLastRef, because we don't want to inline the code to
+// delete a Node at each deref call site.
+void Node::removedLastRef()
+{
+    // An explicit check for Document here is better than a virtual function since it is
+    // faster for non-Document nodes, and because the call to removedLastRef that is inlined
+    // at all deref call sites is smaller if it's a non-virtual function.
+    if (isTreeScope()) {
+        treeScope()->removedLastRefToScope();
+        return;
+    }
+
+#ifndef NDEBUG
+    m_deletionHasBegun = true;
+#endif
+    delete this;
+}
+
+void Node::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    ScriptWrappable::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_parentOrShadowHostNode, "parentOrShadowHostNode");
+    info.addMember(m_treeScope, "treeScope");
+    info.ignoreMember(m_next);
+    info.ignoreMember(m_previous);
+    info.addMember(this->renderer(), "renderer");
+    if (hasRareData()) {
+        if (isElementNode())
+            info.addMember(static_cast<ElementRareData*>(rareData()), "elementRareData");
+        else
+            info.addMember(rareData(), "rareData");
+    }
+}
+
+void Node::textRects(Vector<IntRect>& rects) const
+{
+    RefPtr<Range> range = Range::create(document());
+    range->selectNodeContents(const_cast<Node*>(this), IGNORE_EXCEPTION);
+    range->textRects(rects);
+}
+
+unsigned Node::connectedSubframeCount() const
+{
+    return hasRareData() ? rareData()->connectedSubframeCount() : 0;
+}
+
+void Node::incrementConnectedSubframeCount(unsigned amount)
+{
+    ASSERT(isContainerNode());
+    ensureRareData()->incrementConnectedSubframeCount(amount);
+}
+
+void Node::decrementConnectedSubframeCount(unsigned amount)
+{
+    rareData()->decrementConnectedSubframeCount(amount);
+}
+
+void Node::updateAncestorConnectedSubframeCountForRemoval() const
+{
+    unsigned count = connectedSubframeCount();
+
+    if (!count)
+        return;
+
+    for (Node* node = parentOrShadowHostNode(); node; node = node->parentOrShadowHostNode())
+        node->decrementConnectedSubframeCount(count);
+}
+
+void Node::updateAncestorConnectedSubframeCountForInsertion() const
+{
+    unsigned count = connectedSubframeCount();
+
+    if (!count)
+        return;
+
+    for (Node* node = parentOrShadowHostNode(); node; node = node->parentOrShadowHostNode())
+        node->incrementConnectedSubframeCount(count);
+}
+
+void Node::registerScopedHTMLStyleChild()
+{
+    setHasScopedHTMLStyleChild(true);
+}
+
+void Node::unregisterScopedHTMLStyleChild()
+{
+    ASSERT(hasScopedHTMLStyleChild());
+    setHasScopedHTMLStyleChild(numberOfScopedHTMLStyleChildren());
+}
+
+size_t Node::numberOfScopedHTMLStyleChildren() const
+{
+    size_t count = 0;
+    for (Node* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->hasTagName(HTMLNames::styleTag) && static_cast<HTMLStyleElement*>(child)->isRegisteredAsScoped())
+            count++;
+    }
+
+    return count;
+}
+
+void Node::setFocus(bool flag)
+{
+    if (Document* document = this->document())
+        document->userActionElements().setFocused(this, flag);
+}
+
+void Node::setActive(bool flag, bool)
+{
+    if (Document* document = this->document())
+        document->userActionElements().setActive(this, flag);
+}
+
+void Node::setHovered(bool flag)
+{
+    if (Document* document = this->document())
+        document->userActionElements().setHovered(this, flag);
+}
+
+bool Node::isUserActionElementActive() const
+{
+    ASSERT(isUserActionElement());
+    return document()->userActionElements().isActive(this);
+}
+
+bool Node::isUserActionElementInActiveChain() const
+{
+    ASSERT(isUserActionElement());
+    return document()->userActionElements().isInActiveChain(this);
+}
+
+bool Node::isUserActionElementHovered() const
+{
+    ASSERT(isUserActionElement());
+    return document()->userActionElements().isHovered(this);
+}
+
+bool Node::isUserActionElementFocused() const
+{
+    ASSERT(isUserActionElement());
+    return document()->userActionElements().isFocused(this);
+}
+
+void Node::setIsCustomElement()
+{
+    ASSERT(isHTMLElement() || isSVGElement());
+    setFlag(IsCustomElement);
+}
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+
+void showTree(const WebCore::Node* node)
+{
+    if (node)
+        node->showTreeForThis();
+}
+
+void showNodePath(const WebCore::Node* node)
+{
+    if (node)
+        node->showNodePathForThis();
+}
+
+#endif
diff --git a/Source/core/dom/Node.h b/Source/core/dom/Node.h
new file mode 100644
index 0000000..0b74968
--- /dev/null
+++ b/Source/core/dom/Node.h
@@ -0,0 +1,890 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Node_h
+#define Node_h
+
+#include "bindings/v8/ScriptWrappable.h"
+#include "core/dom/EventTarget.h"
+#include "core/dom/MutationObserver.h"
+#include "core/dom/SimulatedClickOptions.h"
+#include "core/dom/TreeScope.h"
+#include "core/editing/EditingBoundary.h"
+#include "core/page/FocusDirection.h"
+#include "core/platform/KURLHash.h"
+#include "core/platform/TreeShared.h"
+#include "core/platform/graphics/LayoutRect.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+#include <wtf/Forward.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/text/AtomicString.h>
+
+// This needs to be here because Document.h also depends on it.
+#define DUMP_NODE_STATISTICS 0
+
+namespace WebCore {
+
+class Attribute;
+class ClassNodeList;
+class ContainerNode;
+class DOMSettableTokenList;
+class Document;
+class Element;
+class Event;
+class EventContext;
+class EventDispatchMediator;
+class EventListener;
+class FloatPoint;
+class Frame;
+class HTMLInputElement;
+class IntRect;
+class KeyboardEvent;
+class NSResolver;
+class NamedNodeMap;
+class NameNodeList;
+class NodeList;
+class NodeListsNodeData;
+class NodeRareData;
+class NodeRenderingContext;
+class PlatformGestureEvent;
+class PlatformKeyboardEvent;
+class PlatformMouseEvent;
+class PlatformWheelEvent;
+class QualifiedName;
+class RadioNodeList;
+class RegisteredEventListener;
+class RenderArena;
+class RenderBox;
+class RenderBoxModelObject;
+class RenderObject;
+class RenderStyle;
+class ShadowRoot;
+class TagNodeList;
+class TouchEvent;
+
+typedef int ExceptionCode;
+
+const int nodeStyleChangeShift = 15;
+
+// SyntheticStyleChange means that we need to go through the entire style change logic even though
+// no style property has actually changed. It is used to restructure the tree when, for instance,
+// RenderLayers are created or destroyed due to animation changes.
+enum StyleChangeType { 
+    NoStyleChange = 0, 
+    InlineStyleChange = 1 << nodeStyleChangeShift, 
+    FullStyleChange = 2 << nodeStyleChangeShift, 
+    SyntheticStyleChange = 3 << nodeStyleChangeShift
+};
+
+class NodeRareDataBase {
+public:
+    RenderObject* renderer() const { return m_renderer; }
+    void setRenderer(RenderObject* renderer) { m_renderer = renderer; }
+
+protected:
+    NodeRareDataBase(RenderObject* renderer)
+        : m_renderer(renderer)
+    { }
+
+private:
+    RenderObject* m_renderer;
+};
+
+enum AttachBehavior {
+    AttachNow,
+    AttachLazily,
+};
+
+class Node : public EventTarget, public ScriptWrappable, public TreeShared<Node> {
+    friend class Document;
+    friend class TreeScope;
+    friend class TreeScopeAdopter;
+
+public:
+    enum NodeType {
+        ELEMENT_NODE = 1,
+        ATTRIBUTE_NODE = 2,
+        TEXT_NODE = 3,
+        CDATA_SECTION_NODE = 4,
+        ENTITY_REFERENCE_NODE = 5,
+        ENTITY_NODE = 6,
+        PROCESSING_INSTRUCTION_NODE = 7,
+        COMMENT_NODE = 8,
+        DOCUMENT_NODE = 9,
+        DOCUMENT_TYPE_NODE = 10,
+        DOCUMENT_FRAGMENT_NODE = 11,
+        NOTATION_NODE = 12,
+        XPATH_NAMESPACE_NODE = 13,
+    };
+    enum DocumentPosition {
+        DOCUMENT_POSITION_EQUIVALENT = 0x00,
+        DOCUMENT_POSITION_DISCONNECTED = 0x01,
+        DOCUMENT_POSITION_PRECEDING = 0x02,
+        DOCUMENT_POSITION_FOLLOWING = 0x04,
+        DOCUMENT_POSITION_CONTAINS = 0x08,
+        DOCUMENT_POSITION_CONTAINED_BY = 0x10,
+        DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20,
+    };
+
+    static bool isSupported(const String& feature, const String& version);
+
+    static void startIgnoringLeaks();
+    static void stopIgnoringLeaks();
+
+    static void dumpStatistics();
+
+    enum StyleChange { NoChange, NoInherit, Inherit, Detach, Force };    
+    static StyleChange diff(const RenderStyle*, const RenderStyle*, Document*);
+
+    virtual ~Node();
+    void willBeDeletedFrom(Document*);
+
+    // DOM methods & attributes for Node
+
+    bool hasTagName(const QualifiedName&) const;
+    bool hasLocalName(const AtomicString&) const;
+    virtual String nodeName() const = 0;
+    virtual String nodeValue() const;
+    virtual void setNodeValue(const String&, ExceptionCode&);
+    virtual NodeType nodeType() const = 0;
+    ContainerNode* parentNode() const;
+    Element* parentElement() const;
+    Node* previousSibling() const { return m_previous; }
+    Node* nextSibling() const { return m_next; }
+    PassRefPtr<NodeList> childNodes();
+    Node* firstChild() const;
+    Node* lastChild() const;
+    bool hasAttributes() const;
+    NamedNodeMap* attributes() const;
+
+    Node* pseudoAwareNextSibling() const;
+    Node* pseudoAwarePreviousSibling() const;
+    Node* pseudoAwareFirstChild() const;
+    Node* pseudoAwareLastChild() const;
+
+    virtual KURL baseURI() const;
+    
+    void getSubresourceURLs(ListHashSet<KURL>&) const;
+
+    // These should all actually return a node, but this is only important for language bindings,
+    // which will already know and hold a ref on the right node to return. Returning bool allows
+    // these methods to be more efficient since they don't need to return a ref
+    bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode&, AttachBehavior = AttachNow);
+    bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode&, AttachBehavior = AttachNow);
+    bool removeChild(Node* child, ExceptionCode&);
+    bool appendChild(PassRefPtr<Node> newChild, ExceptionCode&, AttachBehavior = AttachNow);
+
+    void remove(ExceptionCode&);
+    bool hasChildNodes() const { return firstChild(); }
+    virtual PassRefPtr<Node> cloneNode(bool deep) = 0;
+    const AtomicString& localName() const { return virtualLocalName(); }
+    const AtomicString& namespaceURI() const { return virtualNamespaceURI(); }
+    const AtomicString& prefix() const { return virtualPrefix(); }
+    virtual void setPrefix(const AtomicString&, ExceptionCode&);
+    void normalize();
+
+    bool isSameNode(Node* other) const { return this == other; }
+    bool isEqualNode(Node*) const;
+    bool isDefaultNamespace(const AtomicString& namespaceURI) const;
+    String lookupPrefix(const AtomicString& namespaceURI) const;
+    String lookupNamespaceURI(const String& prefix) const;
+    String lookupNamespacePrefix(const AtomicString& namespaceURI, const Element* originalElement) const;
+    
+    String textContent(bool convertBRsToNewlines = false) const;
+    void setTextContent(const String&, ExceptionCode&);
+    
+    Node* lastDescendant() const;
+    Node* firstDescendant() const;
+
+    // Other methods (not part of DOM)
+
+    bool isElementNode() const { return getFlag(IsElementFlag); }
+    bool isContainerNode() const { return getFlag(IsContainerFlag); }
+    bool isTextNode() const { return getFlag(IsTextFlag); }
+    bool isHTMLElement() const { return getFlag(IsHTMLFlag); }
+    bool isSVGElement() const { return getFlag(IsSVGFlag); }
+
+    bool isPseudoElement() const { return pseudoId() != NOPSEUDO; }
+    bool isBeforePseudoElement() const { return pseudoId() == BEFORE; }
+    bool isAfterPseudoElement() const { return pseudoId() == AFTER; }
+    PseudoId pseudoId() const { return (isElementNode() && hasCustomStyleCallbacks()) ? customPseudoId() : NOPSEUDO; }
+
+    bool isCustomElement() const { return getFlag(IsCustomElement); }
+    void setIsCustomElement();
+
+    virtual bool isMediaControlElement() const { return false; }
+    virtual bool isMediaControls() const { return false; }
+    virtual bool isWebVTTElement() const { return false; }
+    bool isStyledElement() const { return getFlag(IsStyledElementFlag); }
+    virtual bool isAttributeNode() const { return false; }
+    virtual bool isCharacterDataNode() const { return false; }
+    virtual bool isFrameOwnerElement() const { return false; }
+    virtual bool isPluginElement() const { return false; }
+    virtual bool isInsertionPointNode() const { return false; }
+
+    bool isDocumentNode() const;
+    bool isTreeScope() const { return treeScope()->rootNode() == this; }
+    bool isDocumentFragment() const { return getFlag(IsDocumentFragmentFlag); }
+    bool isShadowRoot() const { return isDocumentFragment() && isTreeScope(); }
+    bool isInsertionPoint() const { return getFlag(NeedsShadowTreeWalkerFlag) && isInsertionPointNode(); }
+    // Returns Node rather than InsertionPoint. Should be used only for language bindings.
+    Node* insertionParentForBinding() const;
+
+    bool needsShadowTreeWalker() const;
+    bool needsShadowTreeWalkerSlow() const;
+    void setNeedsShadowTreeWalker() { setFlag(NeedsShadowTreeWalkerFlag); }
+    void resetNeedsShadowTreeWalker() { setFlag(needsShadowTreeWalkerSlow(), NeedsShadowTreeWalkerFlag); }
+
+    bool inNamedFlow() const { return getFlag(InNamedFlowFlag); }
+    bool hasCustomStyleCallbacks() const { return getFlag(HasCustomStyleCallbacksFlag); }
+
+    bool hasSyntheticAttrChildNodes() const { return getFlag(HasSyntheticAttrChildNodesFlag); }
+    void setHasSyntheticAttrChildNodes(bool flag) { setFlag(flag, HasSyntheticAttrChildNodesFlag); }
+
+    // If this node is in a shadow tree, returns its shadow host. Otherwise, returns 0.
+    Element* shadowHost() const;
+    // If this node is in a shadow tree, returns its shadow host. Otherwise, returns this.
+    // Deprecated. Should use shadowHost() and check the return value.
+    Node* deprecatedShadowAncestorNode() const;
+    ShadowRoot* containingShadowRoot() const;
+    ShadowRoot* youngestShadowRoot() const;
+
+    // Returns 0, a child of ShadowRoot, or a legacy shadow root.
+    Node* nonBoundaryShadowTreeRootNode();
+
+    // Node's parent, shadow tree host.
+    ContainerNode* parentOrShadowHostNode() const;
+    Element* parentOrShadowHostElement() const;
+    void setParentOrShadowHostNode(ContainerNode*);
+    Node* highestAncestor() const;
+
+    // Use when it's guaranteed to that shadowHost is 0.
+    ContainerNode* parentNodeGuaranteedHostFree() const;
+    // Returns the parent node, but 0 if the parent node is a ShadowRoot.
+    ContainerNode* nonShadowBoundaryParentNode() const;
+
+    bool selfOrAncestorHasDirAutoAttribute() const { return getFlag(SelfOrAncestorHasDirAutoFlag); }
+    void setSelfOrAncestorHasDirAutoAttribute(bool flag) { setFlag(flag, SelfOrAncestorHasDirAutoFlag); }
+
+    // Returns the enclosing event parent node (or self) that, when clicked, would trigger a navigation.
+    Node* enclosingLinkEventParentOrSelf();
+
+    bool isBlockFlowElement() const;
+
+    // These low-level calls give the caller responsibility for maintaining the integrity of the tree.
+    void setPreviousSibling(Node* previous) { m_previous = previous; }
+    void setNextSibling(Node* next) { m_next = next; }
+
+    virtual bool canContainRangeEndPoint() const { return false; }
+
+    // FIXME: These two functions belong in editing -- "atomic node" is an editing concept.
+    Node* previousNodeConsideringAtomicNodes() const;
+    Node* nextNodeConsideringAtomicNodes() const;
+    
+    // Returns the next leaf node or 0 if there are no more.
+    // Delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes.
+    // Uses an editing-specific concept of what a leaf node is, and should probably be moved
+    // out of the Node class into an editing-specific source file.
+    Node* nextLeafNode() const;
+
+    // Returns the previous leaf node or 0 if there are no more.
+    // Delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes.
+    // Uses an editing-specific concept of what a leaf node is, and should probably be moved
+    // out of the Node class into an editing-specific source file.
+    Node* previousLeafNode() const;
+
+    // enclosingBlockFlowElement() is deprecated. Use enclosingBlock instead.
+    Element* enclosingBlockFlowElement() const;
+
+    bool isRootEditableElement() const;
+    Element* rootEditableElement() const;
+    Element* rootEditableElement(EditableType) const;
+
+    bool inSameContainingBlockFlowElement(Node*);
+
+    // Called by the parser when this element's close tag is reached,
+    // signaling that all child tags have been parsed and added.
+    // This is needed for <applet> and <object> elements, which can't lay themselves out
+    // until they know all of their nested <param>s. [Radar 3603191, 4040848].
+    // Also used for script elements and some SVG elements for similar purposes,
+    // but making parsing a special case in this respect should be avoided if possible.
+    virtual void finishParsingChildren() { }
+    virtual void beginParsingChildren() { }
+
+    // For <link> and <style> elements.
+    virtual bool sheetLoaded() { return true; }
+    virtual void notifyLoadedSheetAndAllCriticalSubresources(bool /* error loading subresource */) { }
+    virtual void startLoadingDynamicSheet() { ASSERT_NOT_REACHED(); }
+
+    bool hasName() const { return !isTextNode() && getFlag(HasNameOrIsEditingTextFlag); }
+    bool hasID() const;
+    bool hasClass() const;
+
+    bool isUserActionElement() const { return getFlag(IsUserActionElement); }
+    void setUserActionElement(bool flag) { setFlag(flag, IsUserActionElement); }
+
+    bool active() const { return isUserActionElement() && isUserActionElementActive(); }
+    bool inActiveChain() const { return isUserActionElement() && isUserActionElementInActiveChain(); }
+    bool hovered() const { return isUserActionElement() && isUserActionElementHovered(); }
+    bool focused() const { return isUserActionElement() && isUserActionElementFocused(); }
+
+    bool attached() const { return getFlag(IsAttachedFlag); }
+    void setAttached() { setFlag(IsAttachedFlag); }
+    bool needsStyleRecalc() const { return styleChangeType() != NoStyleChange; }
+    StyleChangeType styleChangeType() const { return static_cast<StyleChangeType>(m_nodeFlags & StyleChangeMask); }
+    bool childNeedsStyleRecalc() const { return getFlag(ChildNeedsStyleRecalcFlag); }
+    bool isLink() const { return getFlag(IsLinkFlag); }
+    bool isEditingText() const { return isTextNode() && getFlag(HasNameOrIsEditingTextFlag); }
+
+    void setHasName(bool f) { ASSERT(!isTextNode()); setFlag(f, HasNameOrIsEditingTextFlag); }
+    void setChildNeedsStyleRecalc() { setFlag(ChildNeedsStyleRecalcFlag); }
+    void clearChildNeedsStyleRecalc() { clearFlag(ChildNeedsStyleRecalcFlag); }
+
+    void setNeedsStyleRecalc(StyleChangeType changeType = FullStyleChange);
+    void clearNeedsStyleRecalc() { m_nodeFlags &= ~StyleChangeMask; }
+    virtual void scheduleSetNeedsStyleRecalc(StyleChangeType changeType = FullStyleChange) { setNeedsStyleRecalc(changeType); }
+
+    void setIsLink(bool f) { setFlag(f, IsLinkFlag); }
+    void setIsLink() { setFlag(IsLinkFlag); }
+    void clearIsLink() { clearFlag(IsLinkFlag); }
+
+    void setInNamedFlow() { setFlag(InNamedFlowFlag); }
+    void clearInNamedFlow() { clearFlag(InNamedFlowFlag); }
+
+    bool hasScopedHTMLStyleChild() const { return getFlag(HasScopedHTMLStyleChildFlag); }
+    void setHasScopedHTMLStyleChild(bool flag) { setFlag(flag, HasScopedHTMLStyleChildFlag); }
+
+    bool hasEventTargetData() const { return getFlag(HasEventTargetDataFlag); }
+    void setHasEventTargetData(bool flag) { setFlag(flag, HasEventTargetDataFlag); }
+
+    bool isV8CollectableDuringMinorGC() const { return getFlag(V8CollectableDuringMinorGCFlag); }
+    void setV8CollectableDuringMinorGC(bool flag) { setFlag(flag, V8CollectableDuringMinorGCFlag); }
+
+    enum ShouldSetAttached {
+        SetAttached,
+        DoNotSetAttached
+    };
+    void lazyAttach(ShouldSetAttached = SetAttached);
+    void lazyReattach(ShouldSetAttached = SetAttached);
+
+    virtual void setFocus(bool flag);
+    virtual void setActive(bool flag = true, bool pause = false);
+    virtual void setHovered(bool flag = true);
+
+    virtual short tabIndex() const;
+
+    // Whether this kind of node can receive focus by default. Most nodes are
+    // not focusable but some elements, such as form controls and links, are.
+    virtual bool supportsFocus() const;
+    // Whether the node can actually be focused.
+    virtual bool isFocusable() const;
+    virtual bool isKeyboardFocusable(KeyboardEvent*) const;
+    virtual bool isMouseFocusable() const;
+    virtual Node* focusDelegate();
+
+    enum UserSelectAllTreatment {
+        UserSelectAllDoesNotAffectEditability,
+        UserSelectAllIsAlwaysNonEditable
+    };
+    bool isContentEditable(UserSelectAllTreatment = UserSelectAllDoesNotAffectEditability);
+    bool isContentRichlyEditable();
+
+    bool rendererIsEditable(EditableType editableType = ContentIsEditable, UserSelectAllTreatment treatment = UserSelectAllIsAlwaysNonEditable) const
+    {
+        switch (editableType) {
+        case ContentIsEditable:
+            return rendererIsEditable(Editable, treatment);
+        case HasEditableAXRole:
+            return isEditableToAccessibility(Editable);
+        }
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+
+    bool rendererIsRichlyEditable(EditableType editableType = ContentIsEditable) const
+    {
+        switch (editableType) {
+        case ContentIsEditable:
+            return rendererIsEditable(RichlyEditable, UserSelectAllIsAlwaysNonEditable);
+        case HasEditableAXRole:
+            return isEditableToAccessibility(RichlyEditable);
+        }
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+
+    virtual bool shouldUseInputMethod();
+    virtual LayoutRect boundingBox() const;
+    IntRect pixelSnappedBoundingBox() const { return pixelSnappedIntRect(boundingBox()); }
+    LayoutRect renderRect(bool* isReplaced);
+    IntRect pixelSnappedRenderRect(bool* isReplaced) { return pixelSnappedIntRect(renderRect(isReplaced)); }
+
+    // Returns true if the node has a non-empty bounding box in layout.
+    // This does not 100% guarantee the user can see it, but is pretty close.
+    // Note: This method only works properly after layout has occurred.
+    bool hasNonEmptyBoundingBox() const;
+
+    unsigned nodeIndex() const;
+
+    // Returns the DOM ownerDocument attribute. This method never returns NULL, except in the case 
+    // of (1) a Document node or (2) a DocumentType node that is not used with any Document yet. 
+    Document* ownerDocument() const;
+
+    // Returns the document associated with this node. This method never returns NULL, except in the case 
+    // of a DocumentType node that is not used with any Document yet. A Document node returns itself.
+    Document* document() const
+    {
+        ASSERT(this);
+        // FIXME: below ASSERT is useful, but prevents the use of document() in the constructor or destructor
+        // due to the virtual function call to nodeType().
+        ASSERT(documentInternal() || (nodeType() == DOCUMENT_TYPE_NODE && !inDocument()));
+        return documentInternal();
+    }
+
+    TreeScope* treeScope() const { return m_treeScope; }
+
+    // Returns true if this node is associated with a document and is in its associated document's
+    // node tree, false otherwise.
+    bool inDocument() const 
+    { 
+        ASSERT(documentInternal() || !getFlag(InDocumentFlag));
+        return getFlag(InDocumentFlag);
+    }
+    bool isInShadowTree() const { return getFlag(IsInShadowTreeFlag); }
+    bool isInTreeScope() const { return getFlag(static_cast<NodeFlags>(InDocumentFlag | IsInShadowTreeFlag)); }
+
+    bool isReadOnlyNode() const { return nodeType() == ENTITY_REFERENCE_NODE; }
+    bool isDocumentTypeNode() const { return nodeType() == DOCUMENT_TYPE_NODE; }
+    virtual bool childTypeAllowed(NodeType) const { return false; }
+    unsigned childNodeCount() const;
+    Node* childNode(unsigned index) const;
+
+    void checkSetPrefix(const AtomicString& prefix, ExceptionCode&);
+    bool isDescendantOf(const Node*) const;
+    bool contains(const Node*) const;
+    bool containsIncludingShadowDOM(const Node*) const;
+    bool containsIncludingHostElements(const Node*) const;
+
+    // Used to determine whether range offsets use characters or node indices.
+    virtual bool offsetInCharacters() const;
+    // Number of DOM 16-bit units contained in node. Note that rendered text length can be different - e.g. because of
+    // css-transform:capitalize breaking up precomposed characters and ligatures.
+    virtual int maxCharacterOffset() const;
+
+    // Whether or not a selection can be started in this object
+    virtual bool canStartSelection() const;
+
+    // Getting points into and out of screen space
+    FloatPoint convertToPage(const FloatPoint&) const;
+    FloatPoint convertFromPage(const FloatPoint&) const;
+
+    // -----------------------------------------------------------------------------
+    // Integration with rendering tree
+
+    // As renderer() includes a branch you should avoid calling it repeatedly in hot code paths.
+    RenderObject* renderer() const { return hasRareData() ? m_data.m_rareData->renderer() : m_data.m_renderer; };
+    void setRenderer(RenderObject* renderer)
+    {
+        if (hasRareData())
+            m_data.m_rareData->setRenderer(renderer);
+        else
+            m_data.m_renderer = renderer;
+    }
+
+    // Use these two methods with caution.
+    RenderBox* renderBox() const;
+    RenderBoxModelObject* renderBoxModelObject() const;
+
+    // Attaches this node to the rendering tree. This calculates the style to be applied to the node and creates an
+    // appropriate RenderObject which will be inserted into the tree (except when the style has display: none). This
+    // makes the node visible in the FrameView.
+    virtual void attach();
+
+    // Detaches the node from the rendering tree, making it invisible in the rendered view. This method will remove
+    // the node's rendering object from the rendering tree and delete it.
+    virtual void detach();
+
+#ifndef NDEBUG
+    bool inDetach() const;
+#endif
+
+    void reattach();
+    void reattachIfAttached();
+    ContainerNode* parentNodeForRenderingAndStyle();
+    
+    // Wrapper for nodes that don't have a renderer, but still cache the style (like HTMLOptionElement).
+    RenderStyle* renderStyle() const;
+
+    RenderStyle* computedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return virtualComputedStyle(pseudoElementSpecifier); }
+
+    // -----------------------------------------------------------------------------
+    // Notification of document structure changes (see ContainerNode.h for more notification methods)
+    //
+    // At first, WebKit notifies the node that it has been inserted into the document. This is called during document parsing, and also
+    // when a node is added through the DOM methods insertBefore(), appendChild() or replaceChild(). The call happens _after_ the node has been added to the tree.
+    // This is similar to the DOMNodeInsertedIntoDocument DOM event, but does not require the overhead of event
+    // dispatching.
+    //
+    // WebKit notifies this callback regardless if the subtree of the node is a document tree or a floating subtree.
+    // Implementation can determine the type of subtree by seeing insertionPoint->inDocument().
+    // For a performance reason, notifications are delivered only to ContainerNode subclasses if the insertionPoint is out of document.
+    //
+    // There are another callback named didNotifyDescendantInsertions(), which is called after all the descendant is notified.
+    // Only a few subclasses actually need this. To utilize this, the node should return InsertionShouldCallDidNotifyDescendantInsertions
+    // from insrtedInto().
+    //
+    enum InsertionNotificationRequest {
+        InsertionDone,
+        InsertionShouldCallDidNotifySubtreeInsertions
+    };
+
+    virtual InsertionNotificationRequest insertedInto(ContainerNode* insertionPoint);
+    virtual void didNotifySubtreeInsertions(ContainerNode*) { }
+
+    // Notifies the node that it is no longer part of the tree.
+    //
+    // This is a dual of insertedInto(), and is similar to the DOMNodeRemovedFromDocument DOM event, but does not require the overhead of event
+    // dispatching, and is called _after_ the node is removed from the tree.
+    //
+    virtual void removedFrom(ContainerNode* insertionPoint);
+
+#ifndef NDEBUG
+    String debugName() const;
+
+    virtual void formatForDebugger(char* buffer, unsigned length) const;
+
+    void showNode(const char* prefix = "") const;
+    void showTreeForThis() const;
+    void showNodePathForThis() const;
+    void showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2 = 0, const char* markedLabel2 = 0) const;
+    void showTreeForThisAcrossFrame() const;
+#endif
+
+    void invalidateNodeListCachesInAncestors(const QualifiedName* attrName = 0, Element* attributeOwnerElement = 0);
+    NodeListsNodeData* nodeLists();
+    void clearNodeLists();
+
+    PassRefPtr<NodeList> getElementsByTagName(const AtomicString&);
+    PassRefPtr<NodeList> getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName);
+    PassRefPtr<NodeList> getElementsByName(const String& elementName);
+    PassRefPtr<NodeList> getElementsByClassName(const String& classNames);
+    PassRefPtr<RadioNodeList> radioNodeList(const AtomicString&);
+
+    virtual bool willRespondToMouseMoveEvents();
+    virtual bool willRespondToMouseClickEvents();
+    virtual bool willRespondToTouchEvents();
+
+    PassRefPtr<Element> querySelector(const AtomicString& selectors, ExceptionCode&);
+    PassRefPtr<NodeList> querySelectorAll(const AtomicString& selectors, ExceptionCode&);
+
+    unsigned short compareDocumentPosition(Node*);
+
+    enum ShadowTreesTreatment {
+        TreatShadowTreesAsDisconnected,
+        TreatShadowTreesAsComposed
+    };
+
+    unsigned short compareDocumentPositionInternal(Node*, ShadowTreesTreatment);
+
+    virtual Node* toNode();
+    virtual HTMLInputElement* toInputElement();
+
+    virtual const AtomicString& interfaceName() const;
+    virtual ScriptExecutionContext* scriptExecutionContext() const;
+
+    virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
+    virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
+
+    // Handlers to do/undo actions on the target node before an event is dispatched to it and after the event
+    // has been dispatched.  The data pointer is handed back by the preDispatch and passed to postDispatch.
+    virtual void* preDispatchEventHandler(Event*) { return 0; }
+    virtual void postDispatchEventHandler(Event*, void* /*dataFromPreDispatch*/) { }
+
+    using EventTarget::dispatchEvent;
+    virtual bool dispatchEvent(PassRefPtr<Event>) OVERRIDE;
+
+    void dispatchScopedEvent(PassRefPtr<Event>);
+    void dispatchScopedEventDispatchMediator(PassRefPtr<EventDispatchMediator>);
+
+    virtual void handleLocalEvents(Event*);
+
+    void dispatchSubtreeModifiedEvent();
+    bool dispatchDOMActivateEvent(int detail, PassRefPtr<Event> underlyingEvent);
+    void dispatchFocusInEvent(const AtomicString& eventType, PassRefPtr<Node> oldFocusedNode);
+    void dispatchFocusOutEvent(const AtomicString& eventType, PassRefPtr<Node> newFocusedNode);
+
+    bool dispatchKeyEvent(const PlatformKeyboardEvent&);
+    bool dispatchWheelEvent(const PlatformWheelEvent&);
+    bool dispatchMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType, int clickCount = 0, Node* relatedTarget = 0);
+    bool dispatchGestureEvent(const PlatformGestureEvent&);
+    bool dispatchTouchEvent(PassRefPtr<TouchEvent>);
+
+    void dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions = SendNoEvents, SimulatedClickVisualOptions = ShowPressedLook);
+
+    virtual bool dispatchBeforeLoadEvent(const String& sourceURL);
+    virtual void dispatchFocusEvent(PassRefPtr<Node> oldFocusedNode, FocusDirection);
+    virtual void dispatchBlurEvent(PassRefPtr<Node> newFocusedNode);
+    virtual void dispatchChangeEvent();
+    virtual void dispatchInputEvent();
+
+    // Perform the default action for an event.
+    virtual void defaultEventHandler(Event*);
+
+    using TreeShared<Node>::ref;
+    using TreeShared<Node>::deref;
+
+    virtual EventTargetData* eventTargetData();
+    virtual EventTargetData* ensureEventTargetData();
+
+    void getRegisteredMutationObserversOfType(HashMap<MutationObserver*, MutationRecordDeliveryOptions>&, MutationObserver::MutationType, const QualifiedName* attributeName);
+    void registerMutationObserver(MutationObserver*, MutationObserverOptions, const HashSet<AtomicString>& attributeFilter);
+    void unregisterMutationObserver(MutationObserverRegistration*);
+    void registerTransientMutationObserver(MutationObserverRegistration*);
+    void unregisterTransientMutationObserver(MutationObserverRegistration*);
+    void notifyMutationObserversNodeWillDetach();
+
+    virtual void registerScopedHTMLStyleChild();
+    virtual void unregisterScopedHTMLStyleChild();
+    size_t numberOfScopedHTMLStyleChildren() const;
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+
+    void textRects(Vector<IntRect>&) const;
+
+    unsigned connectedSubframeCount() const;
+    void incrementConnectedSubframeCount(unsigned amount = 1);
+    void decrementConnectedSubframeCount(unsigned amount = 1);
+    void updateAncestorConnectedSubframeCountForRemoval() const;
+    void updateAncestorConnectedSubframeCountForInsertion() const;
+
+private:
+    enum NodeFlags {
+        IsTextFlag = 1,
+        IsContainerFlag = 1 << 1,
+        IsElementFlag = 1 << 2,
+        IsStyledElementFlag = 1 << 3,
+        IsHTMLFlag = 1 << 4,
+        IsSVGFlag = 1 << 5,
+        IsAttachedFlag = 1 << 6,
+        ChildNeedsStyleRecalcFlag = 1 << 7,
+        InDocumentFlag = 1 << 8,
+        IsLinkFlag = 1 << 9,
+        IsUserActionElement = 1 << 10,
+        HasRareDataFlag = 1 << 11,
+        IsDocumentFragmentFlag = 1 << 12,
+
+        // These bits are used by derived classes, pulled up here so they can
+        // be stored in the same memory word as the Node bits above.
+        IsParsingChildrenFinishedFlag = 1 << 13, // Element
+#if ENABLE(SVG)
+        HasSVGRareDataFlag = 1 << 14, // SVGElement
+#endif
+
+        StyleChangeMask = 1 << nodeStyleChangeShift | 1 << (nodeStyleChangeShift + 1),
+
+        SelfOrAncestorHasDirAutoFlag = 1 << 17,
+
+        HasNameOrIsEditingTextFlag = 1 << 18,
+
+        InNamedFlowFlag = 1 << 19,
+        HasSyntheticAttrChildNodesFlag = 1 << 20,
+        HasCustomStyleCallbacksFlag = 1 << 21,
+        HasScopedHTMLStyleChildFlag = 1 << 22,
+        HasEventTargetDataFlag = 1 << 23,
+        V8CollectableDuringMinorGCFlag = 1 << 24,
+        NeedsShadowTreeWalkerFlag = 1 << 25,
+        IsInShadowTreeFlag = 1 << 26,
+        IsCustomElement = 1 << 27,
+
+        DefaultNodeFlags = IsParsingChildrenFinishedFlag
+    };
+
+    // 4 bits remaining
+
+    bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; }
+    void setFlag(bool f, NodeFlags mask) const { m_nodeFlags = (m_nodeFlags & ~mask) | (-(int32_t)f & mask); } 
+    void setFlag(NodeFlags mask) const { m_nodeFlags |= mask; } 
+    void clearFlag(NodeFlags mask) const { m_nodeFlags &= ~mask; } 
+
+protected:
+    enum ConstructionType { 
+        CreateOther = DefaultNodeFlags,
+        CreateText = DefaultNodeFlags | IsTextFlag,
+        CreateContainer = DefaultNodeFlags | IsContainerFlag, 
+        CreateElement = CreateContainer | IsElementFlag, 
+        CreatePseudoElement =  CreateElement | InDocumentFlag | NeedsShadowTreeWalkerFlag,
+        CreateShadowRoot = CreateContainer | IsDocumentFragmentFlag | NeedsShadowTreeWalkerFlag | IsInShadowTreeFlag,
+        CreateDocumentFragment = CreateContainer | IsDocumentFragmentFlag,
+        CreateStyledElement = CreateElement | IsStyledElementFlag, 
+        CreateHTMLElement = CreateStyledElement | IsHTMLFlag,
+        CreateSVGElement = CreateStyledElement | IsSVGFlag,
+        CreateDocument = CreateContainer | InDocumentFlag,
+        CreateInsertionPoint = CreateHTMLElement | NeedsShadowTreeWalkerFlag,
+        CreateEditingText = CreateText | HasNameOrIsEditingTextFlag,
+    };
+    Node(Document*, ConstructionType);
+
+    virtual void didMoveToNewDocument(Document* oldDocument);
+    
+    virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const { }
+
+    bool hasRareData() const { return getFlag(HasRareDataFlag); }
+
+    NodeRareData* rareData() const;
+    NodeRareData* ensureRareData();
+    void clearRareData();
+
+    void clearEventTargetData();
+
+    void setHasCustomStyleCallbacks() { setFlag(true, HasCustomStyleCallbacksFlag); }
+
+    Document* documentInternal() const { return treeScope()->documentScope(); }
+    void setTreeScope(TreeScope* scope) { m_treeScope = scope; }
+
+private:
+    friend class TreeShared<Node>;
+
+    virtual PseudoId customPseudoId() const
+    {
+        ASSERT(hasCustomStyleCallbacks());
+        return NOPSEUDO;
+    }
+
+    void removedLastRef();
+    bool hasTreeSharedParent() const { return !!parentOrShadowHostNode(); }
+
+    enum EditableLevel { Editable, RichlyEditable };
+    bool rendererIsEditable(EditableLevel, UserSelectAllTreatment = UserSelectAllIsAlwaysNonEditable) const;
+    bool isEditableToAccessibility(EditableLevel) const;
+
+    bool isUserActionElementActive() const;
+    bool isUserActionElementInActiveChain() const;
+    bool isUserActionElementHovered() const;
+    bool isUserActionElementFocused() const;
+
+    void setStyleChange(StyleChangeType);
+
+    // Used to share code between lazyAttach and setNeedsStyleRecalc.
+    void markAncestorsWithChildNeedsStyleRecalc();
+
+    virtual void refEventTarget();
+    virtual void derefEventTarget();
+
+    virtual RenderStyle* nonRendererStyle() const { return 0; }
+
+    virtual const AtomicString& virtualPrefix() const;
+    virtual const AtomicString& virtualLocalName() const;
+    virtual const AtomicString& virtualNamespaceURI() const;
+    virtual RenderStyle* virtualComputedStyle(PseudoId = NOPSEUDO);
+
+    Element* ancestorElement() const;
+
+    void trackForDebugging();
+
+    Vector<OwnPtr<MutationObserverRegistration> >* mutationObserverRegistry();
+    HashSet<MutationObserverRegistration*>* transientMutationObserverRegistry();
+
+    mutable uint32_t m_nodeFlags;
+    ContainerNode* m_parentOrShadowHostNode;
+    TreeScope* m_treeScope;
+    Node* m_previous;
+    Node* m_next;
+    // When a node has rare data we move the renderer into the rare data.
+    union DataUnion {
+        DataUnion() : m_renderer(0) { }
+        RenderObject* m_renderer;
+        NodeRareDataBase* m_rareData;
+    } m_data;
+
+protected:
+    bool isParsingChildrenFinished() const { return getFlag(IsParsingChildrenFinishedFlag); }
+    void setIsParsingChildrenFinished() { setFlag(IsParsingChildrenFinishedFlag); }
+    void clearIsParsingChildrenFinished() { clearFlag(IsParsingChildrenFinishedFlag); }
+
+#if ENABLE(SVG)
+    bool hasSVGRareData() const { return getFlag(HasSVGRareDataFlag); }
+    void setHasSVGRareData() { setFlag(HasSVGRareDataFlag); }
+    void clearHasSVGRareData() { clearFlag(HasSVGRareDataFlag); }
+#endif
+};
+
+// Used in Node::addSubresourceAttributeURLs() and in addSubresourceStyleURLs()
+inline void addSubresourceURL(ListHashSet<KURL>& urls, const KURL& url)
+{
+    if (!url.isNull())
+        urls.add(url);
+}
+
+inline void Node::setParentOrShadowHostNode(ContainerNode* parent)
+{
+    ASSERT(isMainThread());
+    m_parentOrShadowHostNode = parent;
+}
+
+inline ContainerNode* Node::parentOrShadowHostNode() const
+{
+    ASSERT(isMainThread());
+    return m_parentOrShadowHostNode;
+}
+
+inline ContainerNode* Node::parentNode() const
+{
+    return isShadowRoot() ? 0 : parentOrShadowHostNode();
+}
+
+inline ContainerNode* Node::parentNodeGuaranteedHostFree() const
+{
+    ASSERT(!isShadowRoot());
+    return parentOrShadowHostNode();
+}
+
+inline void Node::reattach()
+{
+    if (attached())
+        detach();
+    attach();
+}
+
+inline void Node::reattachIfAttached()
+{
+    if (attached())
+        reattach();
+}
+
+inline void Node::lazyReattach(ShouldSetAttached shouldSetAttached)
+{
+    if (attached())
+        detach();
+    lazyAttach(shouldSetAttached);
+}
+
+} //namespace
+
+#ifndef NDEBUG
+// Outside the WebCore namespace for ease of invocation from gdb.
+void showTree(const WebCore::Node*);
+void showNodePath(const WebCore::Node*);
+#endif
+
+#endif
diff --git a/Source/core/dom/Node.idl b/Source/core/dom/Node.idl
new file mode 100644
index 0000000..28d760e
--- /dev/null
+++ b/Source/core/dom/Node.idl
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+// FIXME: Node should inherit EventTarget.
+[
+    CustomToV8,
+    EventTarget,
+    DependentLifetime
+] interface Node {
+    // NodeType
+    const unsigned short      ELEMENT_NODE                   = 1;
+    const unsigned short      ATTRIBUTE_NODE                 = 2;
+    const unsigned short      TEXT_NODE                      = 3;
+    const unsigned short      CDATA_SECTION_NODE             = 4;
+    const unsigned short      ENTITY_REFERENCE_NODE          = 5;
+    const unsigned short      ENTITY_NODE                    = 6;
+    const unsigned short      PROCESSING_INSTRUCTION_NODE    = 7;
+    const unsigned short      COMMENT_NODE                   = 8;
+    const unsigned short      DOCUMENT_NODE                  = 9;
+    const unsigned short      DOCUMENT_TYPE_NODE             = 10;
+    const unsigned short      DOCUMENT_FRAGMENT_NODE         = 11;
+    const unsigned short      NOTATION_NODE                  = 12;
+
+    [TreatReturnedNullStringAs=Null, PerWorldBindings] readonly attribute DOMString        nodeName;
+
+             // FIXME: the spec says this can also raise on retrieval.
+             [TreatReturnedNullStringAs=Null, TreatNullAs=NullString, PerWorldBindings, SetterRaisesException] attribute DOMString        nodeValue;
+
+    [PerWorldBindings] readonly attribute unsigned short   nodeType;
+    [PerWorldBindings] readonly attribute Node             parentNode;
+    [PerWorldBindings] readonly attribute NodeList         childNodes;
+    [PerWorldBindings] readonly attribute Node             firstChild;
+    [PerWorldBindings] readonly attribute Node             lastChild;
+    [PerWorldBindings] readonly attribute Node             previousSibling;
+    [PerWorldBindings] readonly attribute Node             nextSibling;
+    [PerWorldBindings] readonly attribute Document         ownerDocument;
+
+    [Custom, PerWorldBindings, ActivityLog=AccessForIsolatedWorlds, RaisesException] Node insertBefore(Node newChild, Node refChild);
+    [Custom, PerWorldBindings, ActivityLog=AccessForIsolatedWorlds, RaisesException] Node replaceChild(Node newChild, Node oldChild);
+    [Custom, PerWorldBindings, RaisesException] Node removeChild(Node oldChild);
+    [Custom, PerWorldBindings, ActivityLog=AccessForIsolatedWorlds, RaisesException] Node appendChild(Node newChild);
+
+    boolean            hasChildNodes();
+    [DeliverCustomElementCallbacks, PerWorldBindings]
+    Node               cloneNode([Default=Undefined] optional boolean deep);
+    void               normalize();
+
+    // Introduced in DOM Level 2:
+     boolean isSupported([Default=Undefined] optional DOMString feature, 
+                                       [TreatNullAs=NullString,Default=Undefined] optional DOMString version);
+
+    [TreatReturnedNullStringAs=Null, PerWorldBindings] readonly attribute DOMString        namespaceURI;
+             [TreatReturnedNullStringAs=Null, TreatNullAs=NullString, PerWorldBindings, SetterRaisesException] attribute DOMString        prefix;
+    [TreatReturnedNullStringAs=Null, PerWorldBindings] readonly attribute DOMString        localName;
+
+    // Introduced in DOM Level 3:
+    [TreatReturnedNullStringAs=Null, PerWorldBindings] readonly attribute DOMString       baseURI;
+
+             // FIXME: the spec says this can also raise on retrieval.
+             [TreatReturnedNullStringAs=Null, TreatNullAs=NullString, PerWorldBindings, SetterRaisesException] attribute DOMString       textContent;
+
+    boolean            isSameNode([Default=Undefined] optional Node other);
+    boolean            isEqualNode([Default=Undefined] optional Node other);
+    [TreatReturnedNullStringAs=Null] DOMString          lookupPrefix([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI);
+    boolean            isDefaultNamespace([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI);
+    [TreatReturnedNullStringAs=Null] DOMString          lookupNamespaceURI([TreatNullAs=NullString,Default=Undefined] optional DOMString prefix);
+
+    // DocumentPosition
+    const unsigned short      DOCUMENT_POSITION_DISCONNECTED = 0x01;
+    const unsigned short      DOCUMENT_POSITION_PRECEDING    = 0x02;
+    const unsigned short      DOCUMENT_POSITION_FOLLOWING    = 0x04;
+    const unsigned short      DOCUMENT_POSITION_CONTAINS     = 0x08;
+    const unsigned short      DOCUMENT_POSITION_CONTAINED_BY = 0x10;
+    const unsigned short      DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
+
+    unsigned short     compareDocumentPosition([Default=Undefined] optional Node other);
+
+    // Introduced in DOM4
+    boolean contains([Default=Undefined] optional Node other);
+
+    // IE extensions
+    [PerWorldBindings] readonly attribute Element          parentElement;
+
+    void addEventListener(DOMString type, 
+                          EventListener listener, 
+                          optional boolean useCapture);
+    void removeEventListener(DOMString type, 
+                             EventListener listener, 
+                             optional boolean useCapture);
+    [RaisesException] boolean dispatchEvent(Event event);
+};
diff --git a/Source/core/dom/NodeFilter.cpp b/Source/core/dom/NodeFilter.cpp
new file mode 100644
index 0000000..5667ea4
--- /dev/null
+++ b/Source/core/dom/NodeFilter.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/NodeFilter.h"
+
+#include "core/dom/Node.h"
+
+namespace WebCore {
+
+short NodeFilter::acceptNode(ScriptState* state, Node* node) const
+{
+    // cast to short silences "enumeral and non-enumeral types in return" warning
+    return m_condition ? m_condition->acceptNode(state, node) : static_cast<short>(FILTER_ACCEPT);
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/NodeFilter.h b/Source/core/dom/NodeFilter.h
new file mode 100644
index 0000000..8866ba6
--- /dev/null
+++ b/Source/core/dom/NodeFilter.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NodeFilter_h
+#define NodeFilter_h
+
+#include "core/dom/NodeFilterCondition.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+    class NodeFilter : public RefCounted<NodeFilter> {
+    public:
+        /**
+         * The following constants are returned by the acceptNode()
+         * method:
+         */
+        enum {
+            FILTER_ACCEPT = 1,
+            FILTER_REJECT = 2,
+            FILTER_SKIP   = 3
+        };
+
+        /**
+         * These are the available values for the whatToShow parameter.
+         * They are the same as the set of possible types for Node, and
+         * their values are derived by using a bit position corresponding
+         * to the value of NodeType for the equivalent node type.
+         */
+        enum {
+            SHOW_ALL                       = 0xFFFFFFFF,
+            SHOW_ELEMENT                   = 0x00000001,
+            SHOW_ATTRIBUTE                 = 0x00000002,
+            SHOW_TEXT                      = 0x00000004,
+            SHOW_CDATA_SECTION             = 0x00000008,
+            SHOW_ENTITY_REFERENCE          = 0x00000010,
+            SHOW_ENTITY                    = 0x00000020,
+            SHOW_PROCESSING_INSTRUCTION    = 0x00000040,
+            SHOW_COMMENT                   = 0x00000080,
+            SHOW_DOCUMENT                  = 0x00000100,
+            SHOW_DOCUMENT_TYPE             = 0x00000200,
+            SHOW_DOCUMENT_FRAGMENT         = 0x00000400,
+            SHOW_NOTATION                  = 0x00000800
+        };
+
+        static PassRefPtr<NodeFilter> create(PassRefPtr<NodeFilterCondition> condition)
+        {
+            return adoptRef(new NodeFilter(condition));
+        }
+
+        static PassRefPtr<NodeFilter> create()
+        {
+            return adoptRef(new NodeFilter());
+        }
+
+        short acceptNode(ScriptState*, Node*) const;
+
+    private:
+        explicit NodeFilter(PassRefPtr<NodeFilterCondition> condition) : m_condition(condition) { }
+        NodeFilter() {}
+
+        RefPtr<NodeFilterCondition> m_condition;
+    };
+
+} // namespace WebCore
+
+#endif // NodeFilter_h
diff --git a/Source/core/dom/NodeFilter.idl b/Source/core/dom/NodeFilter.idl
new file mode 100644
index 0000000..b42757c
--- /dev/null
+++ b/Source/core/dom/NodeFilter.idl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+[
+    ImplementationLacksVTable
+] interface NodeFilter {
+    // Constants returned by acceptNode
+    const short               FILTER_ACCEPT                  = 1;
+    const short               FILTER_REJECT                  = 2;
+    const short               FILTER_SKIP                    = 3;
+
+    // Constants for whatToShow
+    const unsigned long       SHOW_ALL                       = 0xFFFFFFFF;
+    const unsigned long       SHOW_ELEMENT                   = 0x00000001;
+    const unsigned long       SHOW_ATTRIBUTE                 = 0x00000002;
+    const unsigned long       SHOW_TEXT                      = 0x00000004;
+    const unsigned long       SHOW_CDATA_SECTION             = 0x00000008;
+    const unsigned long       SHOW_ENTITY_REFERENCE          = 0x00000010;
+    const unsigned long       SHOW_ENTITY                    = 0x00000020;
+    const unsigned long       SHOW_PROCESSING_INSTRUCTION    = 0x00000040;
+    const unsigned long       SHOW_COMMENT                   = 0x00000080;
+    const unsigned long       SHOW_DOCUMENT                  = 0x00000100;
+    const unsigned long       SHOW_DOCUMENT_TYPE             = 0x00000200;
+    const unsigned long       SHOW_DOCUMENT_FRAGMENT         = 0x00000400;
+    const unsigned long       SHOW_NOTATION                  = 0x00000800;
+
+    [CallWith=ScriptState] short acceptNode([Default=Undefined] optional Node n);
+
+};
+
diff --git a/Source/core/dom/NodeFilterCondition.cpp b/Source/core/dom/NodeFilterCondition.cpp
new file mode 100644
index 0000000..aee9f80
--- /dev/null
+++ b/Source/core/dom/NodeFilterCondition.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/NodeFilterCondition.h"
+
+#include "core/dom/NodeFilter.h"
+
+namespace WebCore {
+
+short NodeFilterCondition::acceptNode(ScriptState*, Node*) const
+{
+    return NodeFilter::FILTER_ACCEPT;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/NodeFilterCondition.h b/Source/core/dom/NodeFilterCondition.h
new file mode 100644
index 0000000..9608fcb
--- /dev/null
+++ b/Source/core/dom/NodeFilterCondition.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NodeFilterCondition_h
+#define NodeFilterCondition_h
+
+#include "bindings/v8/ScriptState.h"
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+    class Node;
+
+    class NodeFilterCondition : public RefCounted<NodeFilterCondition> {
+    public:
+        virtual ~NodeFilterCondition() { }
+        virtual short acceptNode(ScriptState*, Node*) const = 0;
+    };
+
+} // namespace WebCore
+
+#endif // NodeFilterCondition_h
diff --git a/Source/core/dom/NodeIterator.cpp b/Source/core/dom/NodeIterator.cpp
new file mode 100644
index 0000000..a521b04
--- /dev/null
+++ b/Source/core/dom/NodeIterator.cpp
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/NodeIterator.h"
+
+#include "bindings/v8/ScriptState.h"
+#include "core/dom/Document.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/NodeFilter.h"
+#include "core/dom/NodeTraversal.h"
+
+namespace WebCore {
+
+NodeIterator::NodePointer::NodePointer()
+{
+}
+
+NodeIterator::NodePointer::NodePointer(PassRefPtr<Node> n, bool b)
+    : node(n)
+    , isPointerBeforeNode(b)
+{
+}
+
+void NodeIterator::NodePointer::clear()
+{
+    node.clear();
+}
+
+bool NodeIterator::NodePointer::moveToNext(Node* root)
+{
+    if (!node)
+        return false;
+    if (isPointerBeforeNode) {
+        isPointerBeforeNode = false;
+        return true;
+    }
+    node = NodeTraversal::next(node.get(), root);
+    return node;
+}
+
+bool NodeIterator::NodePointer::moveToPrevious(Node* root)
+{
+    if (!node)
+        return false;
+    if (!isPointerBeforeNode) {
+        isPointerBeforeNode = true;
+        return true;
+    }
+    node = NodeTraversal::previous(node.get(), root);
+    return node;
+}
+
+NodeIterator::NodeIterator(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter, bool expandEntityReferences)
+    : Traversal(rootNode, whatToShow, filter, expandEntityReferences)
+    , m_referenceNode(root(), true)
+    , m_detached(false)
+{
+    // Document type nodes may have a null document. But since they can't have children, there is no need to listen for modifications to these.
+    ASSERT(root()->document() || root()->nodeType() == Node::DOCUMENT_TYPE_NODE);
+    ScriptWrappable::init(this);
+    if (Document* ownerDocument = root()->document())
+        ownerDocument->attachNodeIterator(this);
+}
+
+NodeIterator::~NodeIterator()
+{
+    if (Document* ownerDocument = root()->document())
+        ownerDocument->detachNodeIterator(this);
+}
+
+PassRefPtr<Node> NodeIterator::nextNode(ScriptState* state, ExceptionCode& ec)
+{
+    if (m_detached) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    RefPtr<Node> result;
+
+    m_candidateNode = m_referenceNode;
+    while (m_candidateNode.moveToNext(root())) {
+        // NodeIterators treat the DOM tree as a flat list of nodes.
+        // In other words, FILTER_REJECT does not pass over descendants
+        // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
+        RefPtr<Node> provisionalResult = m_candidateNode.node;
+        bool nodeWasAccepted = acceptNode(state, provisionalResult.get()) == NodeFilter::FILTER_ACCEPT;
+        if (state && state->hadException())
+            break;
+        if (nodeWasAccepted) {
+            m_referenceNode = m_candidateNode;
+            result = provisionalResult.release();
+            break;
+        }
+    }
+
+    m_candidateNode.clear();
+    return result.release();
+}
+
+PassRefPtr<Node> NodeIterator::previousNode(ScriptState* state, ExceptionCode& ec)
+{
+    if (m_detached) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    RefPtr<Node> result;
+
+    m_candidateNode = m_referenceNode;
+    while (m_candidateNode.moveToPrevious(root())) {
+        // NodeIterators treat the DOM tree as a flat list of nodes.
+        // In other words, FILTER_REJECT does not pass over descendants
+        // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
+        RefPtr<Node> provisionalResult = m_candidateNode.node;
+        bool nodeWasAccepted = acceptNode(state, provisionalResult.get()) == NodeFilter::FILTER_ACCEPT;
+        if (state && state->hadException())
+            break;
+        if (nodeWasAccepted) {
+            m_referenceNode = m_candidateNode;
+            result = provisionalResult.release();
+            break;
+        }
+    }
+
+    m_candidateNode.clear();
+    return result.release();
+}
+
+void NodeIterator::detach()
+{
+    if (Document* ownerDocument = root()->document())
+        ownerDocument->detachNodeIterator(this);
+    m_detached = true;
+    m_referenceNode.node.clear();
+}
+
+void NodeIterator::nodeWillBeRemoved(Node* removedNode)
+{
+    updateForNodeRemoval(removedNode, m_candidateNode);
+    updateForNodeRemoval(removedNode, m_referenceNode);
+}
+
+void NodeIterator::updateForNodeRemoval(Node* removedNode, NodePointer& referenceNode) const
+{
+    ASSERT(!m_detached);
+    ASSERT(removedNode);
+    ASSERT(root()->document());
+    ASSERT(root()->document() == removedNode->document());
+
+    // Iterator is not affected if the removed node is the reference node and is the root.
+    // or if removed node is not the reference node, or the ancestor of the reference node.
+    if (!removedNode->isDescendantOf(root()))
+        return;
+    bool willRemoveReferenceNode = removedNode == referenceNode.node;
+    bool willRemoveReferenceNodeAncestor = referenceNode.node && referenceNode.node->isDescendantOf(removedNode);
+    if (!willRemoveReferenceNode && !willRemoveReferenceNodeAncestor)
+        return;
+
+    if (referenceNode.isPointerBeforeNode) {
+        Node* node = NodeTraversal::next(removedNode, root());
+        if (node) {
+            // Move out from under the node being removed if the new reference
+            // node is a descendant of the node being removed.
+            while (node && node->isDescendantOf(removedNode))
+                node = NodeTraversal::next(node, root());
+            if (node)
+                referenceNode.node = node;
+        } else {
+            node = NodeTraversal::previous(removedNode, root());
+            if (node) {
+                // Move out from under the node being removed if the reference node is
+                // a descendant of the node being removed.
+                if (willRemoveReferenceNodeAncestor) {
+                    while (node && node->isDescendantOf(removedNode))
+                        node = NodeTraversal::previous(node, root());
+                }
+                if (node) {
+                    // Removing last node.
+                    // Need to move the pointer after the node preceding the 
+                    // new reference node.
+                    referenceNode.node = node;
+                    referenceNode.isPointerBeforeNode = false;
+                }
+            }
+        }
+    } else {
+        Node* node = NodeTraversal::previous(removedNode, root());
+        if (node) {
+            // Move out from under the node being removed if the reference node is
+            // a descendant of the node being removed.
+            if (willRemoveReferenceNodeAncestor) {
+                while (node && node->isDescendantOf(removedNode))
+                    node = NodeTraversal::previous(node, root());
+            }
+            if (node)
+                referenceNode.node = node;
+        } else {
+            // FIXME: This branch doesn't appear to have any LayoutTests.
+            node = NodeTraversal::next(removedNode, root());
+            // Move out from under the node being removed if the reference node is
+            // a descendant of the node being removed.
+            if (willRemoveReferenceNodeAncestor) {
+                while (node && node->isDescendantOf(removedNode))
+                    node = NodeTraversal::previous(node, root());
+            }
+            if (node)
+                referenceNode.node = node;
+        }
+    }
+}
+
+
+} // namespace WebCore
diff --git a/Source/core/dom/NodeIterator.h b/Source/core/dom/NodeIterator.h
new file mode 100644
index 0000000..cb81a01
--- /dev/null
+++ b/Source/core/dom/NodeIterator.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NodeIterator_h
+#define NodeIterator_h
+
+#include "bindings/v8/ScriptWrappable.h"
+#include "core/dom/NodeFilter.h"
+#include "core/dom/Traversal.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+    typedef int ExceptionCode;
+
+    class NodeIterator : public ScriptWrappable, public RefCounted<NodeIterator>, public Traversal {
+    public:
+        static PassRefPtr<NodeIterator> create(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter, bool expandEntityReferences)
+        {
+            return adoptRef(new NodeIterator(rootNode, whatToShow, filter, expandEntityReferences));
+        }
+        ~NodeIterator();
+
+        PassRefPtr<Node> nextNode(ScriptState*, ExceptionCode&);
+        PassRefPtr<Node> previousNode(ScriptState*, ExceptionCode&);
+        void detach();
+
+        Node* referenceNode() const { return m_referenceNode.node.get(); }
+        bool pointerBeforeReferenceNode() const { return m_referenceNode.isPointerBeforeNode; }
+
+        // This function is called before any node is removed from the document tree.
+        void nodeWillBeRemoved(Node*);
+
+    private:
+        NodeIterator(PassRefPtr<Node>, unsigned whatToShow, PassRefPtr<NodeFilter>, bool expandEntityReferences);
+
+        struct NodePointer {
+            RefPtr<Node> node;
+            bool isPointerBeforeNode;
+            NodePointer();
+            NodePointer(PassRefPtr<Node>, bool);
+            void clear();
+            bool moveToNext(Node* root);
+            bool moveToPrevious(Node* root);
+        };
+
+        void updateForNodeRemoval(Node* nodeToBeRemoved, NodePointer&) const;
+
+        NodePointer m_referenceNode;
+        NodePointer m_candidateNode;
+        bool m_detached;
+    };
+
+} // namespace WebCore
+
+#endif // NodeIterator_h
diff --git a/Source/core/dom/NodeIterator.idl b/Source/core/dom/NodeIterator.idl
new file mode 100644
index 0000000..3101322
--- /dev/null
+++ b/Source/core/dom/NodeIterator.idl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+// Introduced in DOM Level 2:
+[
+    ImplementationLacksVTable
+] interface NodeIterator {
+    readonly attribute Node root;
+    readonly attribute unsigned long whatToShow;
+    readonly attribute NodeFilter filter;
+    readonly attribute boolean expandEntityReferences;
+    readonly attribute Node referenceNode;
+    readonly attribute boolean pointerBeforeReferenceNode;
+
+    [CallWith=ScriptState, RaisesException] Node nextNode();
+    [CallWith=ScriptState, RaisesException] Node previousNode();
+    void detach();
+};
+
diff --git a/Source/core/dom/NodeList.h b/Source/core/dom/NodeList.h
new file mode 100644
index 0000000..48cb063
--- /dev/null
+++ b/Source/core/dom/NodeList.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NodeList_h
+#define NodeList_h
+
+#include "bindings/v8/ScriptWrappable.h"
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+    class Node;
+
+    class NodeList : public ScriptWrappable, public RefCounted<NodeList> {
+    public:
+        virtual ~NodeList() { }
+
+        // DOM methods & attributes for NodeList
+        virtual unsigned length() const = 0;
+        virtual Node* item(unsigned index) const = 0;
+        virtual Node* namedItem(const AtomicString&) const = 0;
+
+        // Other methods (not part of DOM)
+        virtual bool isLiveNodeList() const { return false; }
+
+    protected:
+        NodeList()
+        {
+            ScriptWrappable::init(this);
+        }
+    };
+
+} // namespace WebCore
+
+#endif // NodeList_h
diff --git a/Source/core/dom/NodeList.idl b/Source/core/dom/NodeList.idl
new file mode 100644
index 0000000..02bf971
--- /dev/null
+++ b/Source/core/dom/NodeList.idl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+[
+    CustomIsReachable,
+    CustomNamedGetter,
+    DependentLifetime,
+    SkipVTableValidation
+] interface NodeList {
+
+    getter Node item([IsIndex,Default=Undefined] optional unsigned long index);
+
+    readonly attribute unsigned long length;
+
+};
+
diff --git a/Source/core/dom/NodeRareData.cpp b/Source/core/dom/NodeRareData.cpp
new file mode 100644
index 0000000..2aec8fa
--- /dev/null
+++ b/Source/core/dom/NodeRareData.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/NodeRareData.h"
+
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include <wtf/MemoryInstrumentationHashMap.h>
+#include <wtf/MemoryInstrumentationHashSet.h>
+#include <wtf/MemoryInstrumentationVector.h>
+
+namespace WebCore {
+
+struct SameSizeAsNodeRareData {
+    unsigned m_bitfields : 20;
+    void* m_pointer[3];
+};
+
+COMPILE_ASSERT(sizeof(NodeRareData) == sizeof(SameSizeAsNodeRareData), NodeRareDataShouldStaySmall);
+
+void NodeListsNodeData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    info.addMember(m_childNodeList, "childNodeList");
+    info.addMember(m_atomicNameCaches, "atomicNameCaches");
+    info.addMember(m_nameCaches, "nameCaches");
+    info.addMember(m_tagNodeListCacheNS, "tagNodeListCacheNS");
+}
+
+void NodeRareData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    info.addMember(m_nodeLists, "nodeLists");
+    info.addMember(m_mutationObserverData, "mutationObserverData");
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/NodeRareData.h b/Source/core/dom/NodeRareData.h
new file mode 100644
index 0000000..f20b19a
--- /dev/null
+++ b/Source/core/dom/NodeRareData.h
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 David Smith <catfish.man@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NodeRareData_h
+#define NodeRareData_h
+
+#include "HTMLNames.h"
+#include "core/dom/ChildNodeList.h"
+#include "core/dom/LiveNodeList.h"
+#include "core/dom/MutationObserver.h"
+#include "core/dom/MutationObserverRegistration.h"
+#include "core/dom/QualifiedName.h"
+#include "core/dom/TagNodeList.h"
+#include "core/html/DOMSettableTokenList.h"
+#include "core/html/track/TextTrack.h"
+#include "core/page/Page.h"
+#include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+class LabelsNodeList;
+class RadioNodeList;
+class TreeScope;
+
+class NodeListsNodeData {
+    WTF_MAKE_NONCOPYABLE(NodeListsNodeData); WTF_MAKE_FAST_ALLOCATED;
+public:
+    void clearChildNodeListCache()
+    {
+        if (m_childNodeList)
+            m_childNodeList->invalidateCache();
+    }
+
+    PassRefPtr<ChildNodeList> ensureChildNodeList(Node* node)
+    {
+        if (m_childNodeList)
+            return m_childNodeList;
+        RefPtr<ChildNodeList> list = ChildNodeList::create(node);
+        m_childNodeList = list.get();
+        return list.release();
+    }
+
+    void removeChildNodeList(ChildNodeList* list)
+    {
+        ASSERT(m_childNodeList = list);
+        if (deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(list->ownerNode()))
+            return;
+        m_childNodeList = 0;
+    }
+
+    template <typename StringType>
+    struct NodeListCacheMapEntryHash {
+        static unsigned hash(const std::pair<unsigned char, StringType>& entry)
+        {
+            return DefaultHash<StringType>::Hash::hash(entry.second) + entry.first;
+        }
+        static bool equal(const std::pair<unsigned char, StringType>& a, const std::pair<unsigned char, StringType>& b) { return a == b; }
+        static const bool safeToCompareToEmptyOrDeleted = DefaultHash<StringType>::Hash::safeToCompareToEmptyOrDeleted;
+    };
+
+    typedef HashMap<std::pair<unsigned char, AtomicString>, LiveNodeListBase*, NodeListCacheMapEntryHash<AtomicString> > NodeListAtomicNameCacheMap;
+    typedef HashMap<std::pair<unsigned char, String>, LiveNodeListBase*, NodeListCacheMapEntryHash<String> > NodeListNameCacheMap;
+    typedef HashMap<QualifiedName, TagNodeList*> TagNodeListCacheNS;
+
+    template<typename T>
+    PassRefPtr<T> addCacheWithAtomicName(Node* node, CollectionType collectionType, const AtomicString& name)
+    {
+        NodeListAtomicNameCacheMap::AddResult result = m_atomicNameCaches.add(namedNodeListKey(collectionType, name), 0);
+        if (!result.isNewEntry)
+            return static_cast<T*>(result.iterator->value);
+
+        RefPtr<T> list = T::create(node, collectionType, name);
+        result.iterator->value = list.get();
+        return list.release();
+    }
+
+    // FIXME: This function should be renamed since it doesn't have an atomic name.
+    template<typename T>
+    PassRefPtr<T> addCacheWithAtomicName(Node* node, CollectionType collectionType)
+    {
+        NodeListAtomicNameCacheMap::AddResult result = m_atomicNameCaches.add(namedNodeListKey(collectionType, starAtom), 0);
+        if (!result.isNewEntry)
+            return static_cast<T*>(result.iterator->value);
+
+        RefPtr<T> list = T::create(node, collectionType);
+        result.iterator->value = list.get();
+        return list.release();
+    }
+
+    template<typename T>
+    T* cacheWithAtomicName(CollectionType collectionType)
+    {
+        return static_cast<T*>(m_atomicNameCaches.get(namedNodeListKey(collectionType, starAtom)));
+    }
+
+    template<typename T>
+    PassRefPtr<T> addCacheWithName(Node* node, CollectionType collectionType, const String& name)
+    {
+        NodeListNameCacheMap::AddResult result = m_nameCaches.add(namedNodeListKey(collectionType, name), 0);
+        if (!result.isNewEntry)
+            return static_cast<T*>(result.iterator->value);
+
+        RefPtr<T> list = T::create(node, name);
+        result.iterator->value = list.get();
+        return list.release();
+    }
+
+    PassRefPtr<TagNodeList> addCacheWithQualifiedName(Node* node, const AtomicString& namespaceURI, const AtomicString& localName)
+    {
+        QualifiedName name(nullAtom, localName, namespaceURI);
+        TagNodeListCacheNS::AddResult result = m_tagNodeListCacheNS.add(name, 0);
+        if (!result.isNewEntry)
+            return result.iterator->value;
+
+        RefPtr<TagNodeList> list = TagNodeList::create(node, namespaceURI, localName);
+        result.iterator->value = list.get();
+        return list.release();
+    }
+
+    void removeCacheWithAtomicName(LiveNodeListBase* list, CollectionType collectionType, const AtomicString& name = starAtom)
+    {
+        ASSERT(list == m_atomicNameCaches.get(namedNodeListKey(collectionType, name)));
+        if (deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(list->ownerNode()))
+            return;
+        m_atomicNameCaches.remove(namedNodeListKey(collectionType, name));
+    }
+
+    void removeCacheWithName(LiveNodeListBase* list, CollectionType collectionType, const String& name)
+    {
+        ASSERT(list == m_nameCaches.get(namedNodeListKey(collectionType, name)));
+        if (deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(list->ownerNode()))
+            return;
+        m_nameCaches.remove(namedNodeListKey(collectionType, name));
+    }
+
+    void removeCacheWithQualifiedName(LiveNodeList* list, const AtomicString& namespaceURI, const AtomicString& localName)
+    {
+        QualifiedName name(nullAtom, localName, namespaceURI);
+        ASSERT(list == m_tagNodeListCacheNS.get(name));
+        if (deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(list->ownerNode()))
+            return;
+        m_tagNodeListCacheNS.remove(name);
+    }
+
+    static PassOwnPtr<NodeListsNodeData> create()
+    {
+        return adoptPtr(new NodeListsNodeData);
+    }
+
+    void invalidateCaches(const QualifiedName* attrName = 0);
+    bool isEmpty() const
+    {
+        return m_atomicNameCaches.isEmpty() && m_nameCaches.isEmpty() && m_tagNodeListCacheNS.isEmpty();
+    }
+
+    void adoptTreeScope()
+    {
+        invalidateCaches();
+    }
+
+    void adoptDocument(Document* oldDocument, Document* newDocument)
+    {
+        invalidateCaches();
+
+        if (oldDocument != newDocument) {
+            NodeListAtomicNameCacheMap::const_iterator atomicNameCacheEnd = m_atomicNameCaches.end();
+            for (NodeListAtomicNameCacheMap::const_iterator it = m_atomicNameCaches.begin(); it != atomicNameCacheEnd; ++it) {
+                LiveNodeListBase* list = it->value;
+                oldDocument->unregisterNodeList(list);
+                newDocument->registerNodeList(list);
+            }
+
+            NodeListNameCacheMap::const_iterator nameCacheEnd = m_nameCaches.end();
+            for (NodeListNameCacheMap::const_iterator it = m_nameCaches.begin(); it != nameCacheEnd; ++it) {
+                LiveNodeListBase* list = it->value;
+                oldDocument->unregisterNodeList(list);
+                newDocument->registerNodeList(list);
+            }
+
+            TagNodeListCacheNS::const_iterator tagEnd = m_tagNodeListCacheNS.end();
+            for (TagNodeListCacheNS::const_iterator it = m_tagNodeListCacheNS.begin(); it != tagEnd; ++it) {
+                LiveNodeListBase* list = it->value;
+                ASSERT(!list->isRootedAtDocument());
+                oldDocument->unregisterNodeList(list);
+                newDocument->registerNodeList(list);
+            }
+        }
+    }
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+private:
+    NodeListsNodeData()
+        : m_childNodeList(0)
+    { }
+
+    std::pair<unsigned char, AtomicString> namedNodeListKey(CollectionType type, const AtomicString& name)
+    {
+        return std::pair<unsigned char, AtomicString>(type, name);
+    }
+
+    std::pair<unsigned char, String> namedNodeListKey(CollectionType type, const String& name)
+    {
+        return std::pair<unsigned char, String>(type, name);
+    }
+
+    bool deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(Node*);
+
+    // FIXME: m_childNodeList should be merged into m_atomicNameCaches or at least be shared with HTMLCollection returned by Element::children
+    // but it's tricky because invalidateCaches shouldn't invalidate this cache and adoptTreeScope shouldn't call registerNodeList or unregisterNodeList.
+    ChildNodeList* m_childNodeList;
+    NodeListAtomicNameCacheMap m_atomicNameCaches;
+    NodeListNameCacheMap m_nameCaches;
+    TagNodeListCacheNS m_tagNodeListCacheNS;
+};
+
+class NodeMutationObserverData {
+    WTF_MAKE_NONCOPYABLE(NodeMutationObserverData); WTF_MAKE_FAST_ALLOCATED;
+public:
+    Vector<OwnPtr<MutationObserverRegistration> > registry;
+    HashSet<MutationObserverRegistration*> transientRegistry;
+
+    static PassOwnPtr<NodeMutationObserverData> create() { return adoptPtr(new NodeMutationObserverData); }
+
+private:
+    NodeMutationObserverData() { }
+};
+
+class NodeRareData : public NodeRareDataBase {
+    WTF_MAKE_NONCOPYABLE(NodeRareData); WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<NodeRareData> create(RenderObject* renderer) { return adoptPtr(new NodeRareData(renderer)); }
+
+    void clearNodeLists() { m_nodeLists.clear(); }
+    NodeListsNodeData* nodeLists() const { return m_nodeLists.get(); }
+    NodeListsNodeData* ensureNodeLists()
+    {
+        if (!m_nodeLists)
+            m_nodeLists = NodeListsNodeData::create();
+        return m_nodeLists.get();
+    }
+
+    NodeMutationObserverData* mutationObserverData() { return m_mutationObserverData.get(); }
+    NodeMutationObserverData* ensureMutationObserverData()
+    {
+        if (!m_mutationObserverData)
+            m_mutationObserverData = NodeMutationObserverData::create();
+        return m_mutationObserverData.get();
+    }
+
+    unsigned connectedSubframeCount() const { return m_connectedFrameCount; }
+    void incrementConnectedSubframeCount(unsigned amount)
+    {
+        m_connectedFrameCount += amount;
+    }
+    void decrementConnectedSubframeCount(unsigned amount)
+    {
+        ASSERT(m_connectedFrameCount);
+        ASSERT(amount <= m_connectedFrameCount);
+        m_connectedFrameCount -= amount;
+    }
+
+    // This member function is intentionally not virtual to avoid adding a vtable pointer.
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+protected:
+    NodeRareData(RenderObject* renderer)
+        : NodeRareDataBase(renderer)
+        , m_connectedFrameCount(0)
+    { }
+
+private:
+    unsigned m_connectedFrameCount : 10; // Must fit Page::maxNumberOfFrames.
+
+    OwnPtr<NodeListsNodeData> m_nodeLists;
+    OwnPtr<NodeMutationObserverData> m_mutationObserverData;
+};
+
+inline bool NodeListsNodeData::deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(Node* ownerNode)
+{
+    ASSERT(ownerNode);
+    ASSERT(ownerNode->nodeLists() == this);
+    if ((m_childNodeList ? 1 : 0) + m_atomicNameCaches.size() + m_nameCaches.size() + m_tagNodeListCacheNS.size() != 1)
+        return false;
+    ownerNode->clearNodeLists();
+    return true;
+}
+
+// Ensure the 10 bits reserved for the m_connectedFrameCount cannot overflow
+COMPILE_ASSERT(Page::maxNumberOfFrames < 1024, Frame_limit_should_fit_in_rare_data_count);
+
+} // namespace WebCore
+
+#endif // NodeRareData_h
diff --git a/Source/core/dom/NodeRenderStyle.h b/Source/core/dom/NodeRenderStyle.h
new file mode 100644
index 0000000..2ab78c3
--- /dev/null
+++ b/Source/core/dom/NodeRenderStyle.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ *           (C) 2008 David Smith (catfish.man@gmail.com)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NodeRenderStyle_h
+#define NodeRenderStyle_h
+
+#include "core/dom/Node.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/style/RenderStyle.h"
+
+namespace WebCore {
+
+inline RenderStyle* Node::renderStyle() const
+{
+    // 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 (RenderObject* renderer = this->renderer())
+        return renderer->style();
+    return nonRendererStyle();
+}
+
+}
+#endif
diff --git a/Source/core/dom/NodeRenderingContext.cpp b/Source/core/dom/NodeRenderingContext.cpp
new file mode 100644
index 0000000..aca7e5f
--- /dev/null
+++ b/Source/core/dom/NodeRenderingContext.cpp
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/NodeRenderingContext.h"
+
+#include "HTMLNames.h"
+#include "core/css/StyleResolver.h"
+#include "core/dom/ContainerNode.h"
+#include "core/dom/ElementShadow.h"
+#include "core/dom/Node.h"
+#include "core/dom/PseudoElement.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/dom/Text.h"
+#include "core/html/HTMLInputElement.h"
+#include "core/html/shadow/ContentDistributor.h"
+#include "core/html/shadow/HTMLContentElement.h"
+#include "core/html/shadow/HTMLShadowElement.h"
+#include "core/rendering/FlowThreadController.h"
+#include "core/rendering/RenderFullScreen.h"
+#include "core/rendering/RenderNamedFlowThread.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/RenderText.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#endif
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+NodeRenderingContext::NodeRenderingContext(Node* node)
+    : m_node(node)
+    , m_parentFlowRenderer(0)
+{
+    m_renderingParent = NodeRenderingTraversal::parent(node, &m_parentDetails);
+}
+
+NodeRenderingContext::NodeRenderingContext(Node* node, RenderStyle* style)
+    : m_node(node)
+    , m_renderingParent(0)
+    , m_style(style)
+    , m_parentFlowRenderer(0)
+{
+}
+
+NodeRenderingContext::~NodeRenderingContext()
+{
+}
+
+static bool isRendererReparented(const RenderObject* renderer)
+{
+    if (!renderer->node()->isElementNode())
+        return false;
+    if (renderer->style() && !renderer->style()->flowThread().isEmpty())
+        return true;
+    if (toElement(renderer->node())->isInTopLayer())
+        return true;
+    return false;
+}
+
+RenderObject* NodeRenderingContext::nextRenderer() const
+{
+    if (RenderObject* renderer = m_node->renderer())
+        return renderer->nextSibling();
+
+    Element* element = m_node->isElementNode() ? toElement(m_node) : 0;
+    if (element && element->isInTopLayer()) {
+        const Vector<RefPtr<Element> >& topLayerElements = element->document()->topLayerElements();
+        size_t position = topLayerElements.find(element);
+        ASSERT(position != notFound);
+        for (size_t i = position + 1; i < topLayerElements.size(); ++i) {
+            if (RenderObject* renderer = topLayerElements[i]->renderer())
+                return renderer;
+        }
+        return 0;
+    }
+
+    if (m_parentFlowRenderer)
+        return m_parentFlowRenderer->nextRendererForNode(m_node);
+
+    // Avoid an O(N^2) problem with this function by not checking for
+    // nextRenderer() when the parent element hasn't attached yet.
+    if (m_renderingParent && !m_renderingParent->attached())
+        return 0;
+
+    for (Node* sibling = NodeRenderingTraversal::nextSibling(m_node); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
+        RenderObject* renderer = sibling->renderer();
+        if (renderer && !isRendererReparented(renderer))
+            return renderer;
+    }
+
+    return 0;
+}
+
+RenderObject* NodeRenderingContext::previousRenderer() const
+{
+    if (RenderObject* renderer = m_node->renderer())
+        return renderer->previousSibling();
+
+    // FIXME: This doesn't work correctly for things in the top layer that are
+    // display: none. We'd need to duplicate the logic in nextRenderer, but since
+    // nothing needs that yet just assert.
+    ASSERT(!m_node->isElementNode() || !toElement(m_node)->isInTopLayer());
+
+    if (m_parentFlowRenderer)
+        return m_parentFlowRenderer->previousRendererForNode(m_node);
+
+    // FIXME: We should have the same O(N^2) avoidance as nextRenderer does
+    // however, when I tried adding it, several tests failed.
+    for (Node* sibling = NodeRenderingTraversal::previousSibling(m_node); sibling; sibling = NodeRenderingTraversal::previousSibling(sibling)) {
+        RenderObject* renderer = sibling->renderer();
+        if (renderer && !isRendererReparented(renderer))
+            return renderer;
+    }
+
+    return 0;
+}
+
+RenderObject* NodeRenderingContext::parentRenderer() const
+{
+    if (RenderObject* renderer = m_node->renderer())
+        return renderer->parent();
+
+    if (m_node->isElementNode() && toElement(m_node)->isInTopLayer()) {
+        // The parent renderer of top layer elements is the RenderView, but only
+        // if the normal parent would have had a renderer.
+        // FIXME: This behavior isn't quite right as the spec for top layer
+        // only talks about display: none ancestors so putting a <dialog> inside
+        // an <optgroup> seems like it should still work even though this check
+        // will prevent it.
+        if (!m_renderingParent || !m_renderingParent->renderer())
+            return 0;
+        return m_node->document()->renderView();
+    }
+
+    if (m_parentFlowRenderer)
+        return m_parentFlowRenderer;
+
+    return m_renderingParent ? m_renderingParent->renderer() : 0;
+}
+
+bool NodeRenderingContext::shouldCreateRenderer() const
+{
+    if (!m_node->document()->shouldCreateRenderers())
+        return false;
+    if (!m_renderingParent)
+        return false;
+    RenderObject* parentRenderer = this->parentRenderer();
+    if (!parentRenderer)
+        return false;
+    if (!parentRenderer->canHaveChildren())
+        return false;
+    if (!m_renderingParent->childShouldCreateRenderer(*this))
+        return false;
+    return true;
+}
+
+void NodeRenderingContext::moveToFlowThreadIfNeeded()
+{
+    ASSERT(m_node->isElementNode());
+    ASSERT(m_style);
+    if (!RuntimeEnabledFeatures::cssRegionsEnabled())
+        return;
+
+    if (m_style->flowThread().isEmpty())
+        return;
+
+    // As per http://dev.w3.org/csswg/css3-regions/#flow-into, pseudo-elements such as ::first-line, ::first-letter, ::before or ::after
+    // cannot be directly collected into a named flow.
+    if (m_node->isPseudoElement())
+        return;
+
+    // FIXME: Do not collect elements if they are in shadow tree.
+    if (m_node->isInShadowTree())
+        return;
+
+    Document* document = m_node->document();
+    if (document->webkitIsFullScreen() && document->webkitCurrentFullScreenElement() == m_node)
+        return;
+
+#if ENABLE(SVG)
+    // Allow only svg root elements to be directly collected by a render flow thread.
+    if (m_node->isSVGElement()
+        && (!(m_node->hasTagName(SVGNames::svgTag) && m_node->parentNode() && !m_node->parentNode()->isSVGElement())))
+        return;
+#endif
+
+    m_flowThread = m_style->flowThread();
+    ASSERT(m_node->document()->renderView());
+    FlowThreadController* flowThreadController = m_node->document()->renderView()->flowThreadController();
+    m_parentFlowRenderer = flowThreadController->ensureRenderFlowThreadWithName(m_flowThread);
+    flowThreadController->registerNamedFlowContentNode(m_node, m_parentFlowRenderer);
+}
+
+bool NodeRenderingContext::isOnEncapsulationBoundary() const
+{
+    return isOnUpperEncapsulationBoundary() || isLowerEncapsulationBoundary(m_parentDetails.insertionPoint()) || isLowerEncapsulationBoundary(m_node->parentNode());
+}
+
+bool NodeRenderingContext::isOnUpperEncapsulationBoundary() const
+{
+    return m_node->parentNode() && m_node->parentNode()->isShadowRoot();
+}
+
+void NodeRenderingContext::createRendererForElementIfNeeded()
+{
+    ASSERT(!m_node->renderer());
+
+    Element* element = toElement(m_node);
+
+    if (!shouldCreateRenderer())
+        return;
+    m_style = element->styleForRenderer();
+    ASSERT(m_style);
+
+    moveToFlowThreadIfNeeded();
+
+    if (!element->rendererIsNeeded(*this))
+        return;
+
+    RenderObject* parentRenderer = this->parentRenderer();
+    RenderObject* nextRenderer = this->nextRenderer();
+
+    Document* document = element->document();
+    RenderObject* newRenderer = element->createRenderer(document->renderArena(), m_style.get());
+    if (!newRenderer)
+        return;
+    if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) {
+        newRenderer->destroy();
+        return;
+    }
+
+    // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
+    // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
+    newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
+
+    element->setRenderer(newRenderer);
+    newRenderer->setAnimatableStyle(m_style.release()); // setAnimatableStyle() can depend on renderer() already being set.
+
+    if (document->webkitIsFullScreen() && document->webkitCurrentFullScreenElement() == element) {
+        newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer, document);
+        if (!newRenderer)
+            return;
+    }
+
+    // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
+    parentRenderer->addChild(newRenderer, nextRenderer);
+}
+
+void NodeRenderingContext::createRendererForTextIfNeeded()
+{
+    ASSERT(!m_node->renderer());
+
+    Text* textNode = toText(m_node);
+
+    if (!shouldCreateRenderer())
+        return;
+
+    RenderObject* parentRenderer = this->parentRenderer();
+    ASSERT(parentRenderer);
+    Document* document = textNode->document();
+
+    if (resetStyleInheritance())
+        m_style = document->styleResolver()->defaultStyleForElement();
+    else
+        m_style = parentRenderer->style();
+
+    if (!textNode->textRendererIsNeeded(*this))
+        return;
+    RenderText* newRenderer = textNode->createTextRenderer(document->renderArena(), m_style.get());
+    if (!newRenderer)
+        return;
+    if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) {
+        newRenderer->destroy();
+        return;
+    }
+
+    // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
+    // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
+    newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
+
+    RenderObject* nextRenderer = this->nextRenderer();
+    textNode->setRenderer(newRenderer);
+    // Parent takes care of the animations, no need to call setAnimatableStyle.
+    newRenderer->setStyle(m_style.release());
+    parentRenderer->addChild(newRenderer, nextRenderer);
+}
+
+}
diff --git a/Source/core/dom/NodeRenderingContext.h b/Source/core/dom/NodeRenderingContext.h
new file mode 100644
index 0000000..79038d3
--- /dev/null
+++ b/Source/core/dom/NodeRenderingContext.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NodeRenderingContext_h
+#define NodeRenderingContext_h
+
+#include "core/dom/NodeRenderingTraversal.h"
+
+#include <wtf/Noncopyable.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class ContainerNode;
+class Document;
+class InsertionPoint;
+class Node;
+class RenderNamedFlowThread;
+class RenderObject;
+class RenderStyle;
+class ElementShadow;
+
+class NodeRenderingContext {
+public:
+    explicit NodeRenderingContext(Node*);
+    NodeRenderingContext(Node*, RenderStyle*);
+    ~NodeRenderingContext();
+
+    void createRendererForTextIfNeeded();
+    void createRendererForElementIfNeeded();
+
+    Node* node() const;
+    ContainerNode* parentNodeForRenderingAndStyle() const;
+    bool resetStyleInheritance() const;
+    RenderObject* parentRenderer() const;
+    RenderObject* nextRenderer() const;
+    RenderObject* previousRenderer() const;
+    InsertionPoint* insertionPoint() const;
+
+    const RenderStyle* style() const;
+
+    bool isOnUpperEncapsulationBoundary() const;
+    bool isOnEncapsulationBoundary() const;
+
+private:
+    bool shouldCreateRenderer() const;
+    void moveToFlowThreadIfNeeded();
+
+    Node* m_node;
+    ContainerNode* m_renderingParent;
+    NodeRenderingTraversal::ParentDetails m_parentDetails;
+    RefPtr<RenderStyle> m_style;
+    RenderNamedFlowThread* m_parentFlowRenderer;
+    AtomicString m_flowThread;
+};
+
+inline Node* NodeRenderingContext::node() const
+{
+    return m_node;
+}
+
+inline ContainerNode* NodeRenderingContext::parentNodeForRenderingAndStyle() const
+{
+    return m_renderingParent;
+}
+
+inline bool NodeRenderingContext::resetStyleInheritance() const
+{
+    return m_parentDetails.resetStyleInheritance();
+}
+
+inline const RenderStyle* NodeRenderingContext::style() const
+{
+    return m_style.get();
+}
+
+inline InsertionPoint* NodeRenderingContext::insertionPoint() const
+{
+    return m_parentDetails.insertionPoint();
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/core/dom/NodeRenderingTraversal.cpp b/Source/core/dom/NodeRenderingTraversal.cpp
new file mode 100644
index 0000000..97a4878
--- /dev/null
+++ b/Source/core/dom/NodeRenderingTraversal.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2012 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 "core/dom/NodeRenderingTraversal.h"
+
+#include "core/dom/ComposedShadowTreeWalker.h"
+#include "core/dom/PseudoElement.h"
+
+namespace WebCore {
+
+namespace NodeRenderingTraversal {
+
+void ParentDetails::didTraverseInsertionPoint(InsertionPoint* insertionPoint)
+{
+    if (!m_insertionPoint) {
+        m_insertionPoint = insertionPoint;
+        m_resetStyleInheritance  = m_resetStyleInheritance || insertionPoint->resetStyleInheritance();
+    }
+}
+
+void ParentDetails::didTraverseShadowRoot(const ShadowRoot* root)
+{
+    m_resetStyleInheritance  = m_resetStyleInheritance || root->resetStyleInheritance();
+}
+
+ContainerNode* parentSlow(const Node* node, ParentDetails* details)
+{
+    ComposedShadowTreeWalker walker(node, ComposedShadowTreeWalker::CrossUpperBoundary, ComposedShadowTreeWalker::CanStartFromShadowBoundary);
+    ContainerNode* found = toContainerNode(walker.traverseParent(walker.get(), details));
+    return details->outOfComposition() ? 0 : found;
+}
+
+Node* nextSiblingSlow(const Node* node)
+{
+    ComposedShadowTreeWalker walker(node);
+    if (node->isBeforePseudoElement()) {
+        walker.parent();
+        walker.firstChild();
+    } else
+        walker.nextSibling();
+
+    if (walker.get() || node->isAfterPseudoElement())
+        return walker.get();
+
+    Node* parent = walker.traverseParent(node);
+    if (parent && parent->isElementNode())
+        return toElement(parent)->pseudoElement(AFTER);
+
+    return 0;
+}
+
+Node* previousSiblingSlow(const Node* node)
+{
+    ComposedShadowTreeWalker walker(node);
+    if (node->isAfterPseudoElement()) {
+        walker.parent();
+        walker.lastChild();
+    } else
+        walker.previousSibling();
+
+    if (walker.get() || node->isBeforePseudoElement())
+        return walker.get();
+
+    Node* parent = walker.traverseParent(node);
+    if (parent && parent->isElementNode())
+        return toElement(parent)->pseudoElement(BEFORE);
+
+    return 0;
+}
+
+Node* nextInScope(const Node* node)
+{
+    ComposedShadowTreeWalker walker = ComposedShadowTreeWalker(node, ComposedShadowTreeWalker::DoNotCrossUpperBoundary);
+    walker.next();
+    return walker.get();
+}
+
+Node* previousInScope(const Node* node)
+{
+    ComposedShadowTreeWalker walker = ComposedShadowTreeWalker(node, ComposedShadowTreeWalker::DoNotCrossUpperBoundary);
+    walker.previous();
+    return walker.get();
+}
+
+Node* parentInScope(const Node* node)
+{
+    ComposedShadowTreeWalker walker = ComposedShadowTreeWalker(node, ComposedShadowTreeWalker::DoNotCrossUpperBoundary);
+    walker.parent();
+    return walker.get();
+}
+
+Node* lastChildInScope(const Node* node)
+{
+    ComposedShadowTreeWalker walker = ComposedShadowTreeWalker(node, ComposedShadowTreeWalker::DoNotCrossUpperBoundary);
+    walker.lastChild();
+    return walker.get();
+}
+
+}
+
+} // namespace
diff --git a/Source/core/dom/NodeRenderingTraversal.h b/Source/core/dom/NodeRenderingTraversal.h
new file mode 100644
index 0000000..3d7fa11
--- /dev/null
+++ b/Source/core/dom/NodeRenderingTraversal.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2012 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 NodeRenderingTraversal_h
+#define NodeRenderingTraversal_h
+
+#include "core/dom/Element.h"
+
+namespace WebCore {
+
+class InsertionPoint;
+
+namespace NodeRenderingTraversal {
+
+class ParentDetails {
+public:
+    ParentDetails()
+        : m_insertionPoint(0)
+        , m_resetStyleInheritance(false)
+        , m_outOfComposition(false)
+    { }
+
+    InsertionPoint* insertionPoint() const { return m_insertionPoint; }
+    bool resetStyleInheritance() const { return m_resetStyleInheritance; }
+    bool outOfComposition() const { return m_outOfComposition; }
+
+    void didTraverseInsertionPoint(InsertionPoint*);
+    void didTraverseShadowRoot(const ShadowRoot*);
+    void childWasOutOfComposition() { m_outOfComposition = true; }
+
+    bool operator==(const ParentDetails& other)
+    {
+        return m_insertionPoint == other.m_insertionPoint
+            && m_resetStyleInheritance == other.m_resetStyleInheritance
+            && m_outOfComposition == other.m_outOfComposition;
+    }
+
+private:
+    InsertionPoint* m_insertionPoint;
+    bool m_resetStyleInheritance;
+    bool m_outOfComposition;
+};
+
+ContainerNode* parent(const Node*, ParentDetails*);
+ContainerNode* parentSlow(const Node*, ParentDetails*);
+Node* nextSibling(const Node*);
+Node* nextSiblingSlow(const Node*);
+Node* previousSibling(const Node*);
+Node* previousSiblingSlow(const Node*);
+
+Node* nextInScope(const Node*);
+Node* previousInScope(const Node*);
+Node* parentInScope(const Node*);
+Node* lastChildInScope(const Node*);
+
+inline ContainerNode* parent(const Node* node, ParentDetails* details)
+{
+    if (!node->needsShadowTreeWalker()) {
+#ifndef NDEBUG
+        ParentDetails slowDetails;
+        ASSERT(node->parentNode() == parentSlow(node, &slowDetails));
+        ASSERT(slowDetails == *details);
+#endif
+        return node->parentNodeGuaranteedHostFree();
+    }
+
+    return parentSlow(node, details);
+}
+
+inline Node* nextSibling(const Node* node)
+{
+    if (!node->needsShadowTreeWalker()) {
+        ASSERT(nextSiblingSlow(node) == node->nextSibling());
+        return node->nextSibling();
+    }
+
+    return nextSiblingSlow(node);
+}
+
+inline Node* previousSibling(const Node* node)
+{
+    if (!node->needsShadowTreeWalker()) {
+        ASSERT(previousSiblingSlow(node) == node->previousSibling());
+        return node->previousSibling();
+    }
+
+    return previousSiblingSlow(node);
+}
+
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/core/dom/NodeTraversal.cpp b/Source/core/dom/NodeTraversal.cpp
new file mode 100644
index 0000000..11a9661
--- /dev/null
+++ b/Source/core/dom/NodeTraversal.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/NodeTraversal.h"
+
+#include "core/dom/ContainerNode.h"
+
+namespace WebCore {
+namespace NodeTraversal {
+
+Node* previousIncludingPseudo(const Node* current, const Node* stayWithin)
+{
+    if (current == stayWithin)
+        return 0;
+    if (Node* previous = current->pseudoAwarePreviousSibling()) {
+        while (previous->pseudoAwareLastChild())
+            previous = previous->pseudoAwareLastChild();
+        return previous;
+    }
+    return current->parentNode();
+}
+
+Node* nextIncludingPseudo(const Node* current, const Node* stayWithin)
+{
+    if (Node* next = current->pseudoAwareFirstChild())
+        return next;
+    if (current == stayWithin)
+        return 0;
+    if (Node* next = current->pseudoAwareNextSibling())
+        return next;
+    for (current = current->parentNode(); current; current = current->parentNode()) {
+        if (current == stayWithin)
+            return 0;
+        if (Node* next = current->pseudoAwareNextSibling())
+            return next;
+    }
+    return 0;
+}
+
+Node* nextIncludingPseudoSkippingChildren(const Node* current, const Node* stayWithin)
+{
+    if (current == stayWithin)
+        return 0;
+    if (Node* next = current->pseudoAwareNextSibling())
+        return next;
+    for (current = current->parentNode(); current; current = current->parentNode()) {
+        if (current == stayWithin)
+            return 0;
+        if (Node* next = current->pseudoAwareNextSibling())
+            return next;
+    }
+    return 0;
+}
+
+Node* nextAncestorSibling(const Node* current)
+{
+    ASSERT(!current->nextSibling());
+    for (current = current->parentNode(); current; current = current->parentNode()) {
+        if (current->nextSibling())
+            return current->nextSibling();
+    }
+    return 0;
+}
+
+Node* nextAncestorSibling(const Node* current, const Node* stayWithin)
+{
+    ASSERT(!current->nextSibling());
+    ASSERT(current != stayWithin);
+    for (current = current->parentNode(); current; current = current->parentNode()) {
+        if (current == stayWithin)
+            return 0;
+        if (current->nextSibling())
+            return current->nextSibling();
+    }
+    return 0;
+}
+
+Node* previous(const Node* current, const Node* stayWithin)
+{
+    if (current == stayWithin)
+        return 0;
+    if (current->previousSibling()) {
+        Node* previous = current->previousSibling();
+        while (previous->lastChild())
+            previous = previous->lastChild();
+        return previous;
+    }
+    return current->parentNode();
+}
+
+Node* previousSkippingChildren(const Node* current, const Node* stayWithin)
+{
+    if (current == stayWithin)
+        return 0;
+    if (current->previousSibling())
+        return current->previousSibling();
+    for (current = current->parentNode(); current; current = current->parentNode()) {
+        if (current == stayWithin)
+            return 0;
+        if (current->previousSibling())
+            return current->previousSibling();
+    }
+    return 0;
+}
+
+Node* nextPostOrder(const Node* current, const Node* stayWithin)
+{
+    if (current == stayWithin)
+        return 0;
+    if (!current->nextSibling())
+        return current->parentNode();
+    Node* next = current->nextSibling();
+    while (next->firstChild())
+        next = next->firstChild();
+    return next;
+}
+
+static Node* previousAncestorSiblingPostOrder(const Node* current, const Node* stayWithin)
+{
+    ASSERT(!current->previousSibling());
+    for (current = current->parentNode(); current; current = current->parentNode()) {
+        if (current == stayWithin)
+            return 0;
+        if (current->previousSibling())
+            return current->previousSibling();
+    }
+    return 0;
+}
+
+Node* previousPostOrder(const Node* current, const Node* stayWithin)
+{
+    if (current->lastChild())
+        return current->lastChild();
+    if (current == stayWithin)
+        return 0;
+    if (current->previousSibling())
+        return current->previousSibling();
+    return previousAncestorSiblingPostOrder(current, stayWithin);
+}
+
+Node* previousSkippingChildrenPostOrder(const Node* current, const Node* stayWithin)
+{
+    if (current == stayWithin)
+        return 0;
+    if (current->previousSibling())
+        return current->previousSibling();
+    return previousAncestorSiblingPostOrder(current, stayWithin);
+}
+
+}
+}
diff --git a/Source/core/dom/NodeTraversal.h b/Source/core/dom/NodeTraversal.h
new file mode 100644
index 0000000..a0211c2
--- /dev/null
+++ b/Source/core/dom/NodeTraversal.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NodeTraversal_h
+#define NodeTraversal_h
+
+#include "core/dom/Element.h"
+
+namespace WebCore {
+
+namespace ElementTraversal {
+
+// First element child of the node.
+Element* firstWithin(const Node*);
+Element* firstWithin(const ContainerNode*);
+
+// Pre-order traversal skipping non-element nodes.
+Element* next(const Node*);
+Element* next(const Node*, const Node* stayWithin);
+Element* next(const ContainerNode*);
+Element* next(const ContainerNode*, const Node* stayWithin);
+
+// Like next, but skips children.
+Element* nextSkippingChildren(const Node*);
+Element* nextSkippingChildren(const Node*, const Node* stayWithin);
+Element* nextSkippingChildren(const ContainerNode*);
+Element* nextSkippingChildren(const ContainerNode*, const Node* stayWithin);
+
+// Pre-order traversal including the pseudo-elements.
+Element* previousIncludingPseudo(const Node*, const Node* stayWithin = 0);
+Element* nextIncludingPseudo(const Node*, const Node* stayWithin = 0);
+Element* nextIncludingPseudoSkippingChildren(const Node*, const Node* stayWithin = 0);
+
+// Utility function to traverse only the element and pseudo-element siblings of a node.
+Element* pseudoAwarePreviousSibling(const Node*);
+
+}
+
+namespace NodeTraversal {
+
+// Does a pre-order traversal of the tree to find the next node after this one.
+// This uses the same order that tags appear in the source file. If the stayWithin
+// argument is non-null, the traversal will stop once the specified node is reached.
+// This can be used to restrict traversal to a particular sub-tree.
+Node* next(const Node*);
+Node* next(const Node*, const Node* stayWithin);
+Node* next(const ContainerNode*);
+Node* next(const ContainerNode*, const Node* stayWithin);
+
+// Like next, but skips children and starts with the next sibling.
+Node* nextSkippingChildren(const Node*);
+Node* nextSkippingChildren(const Node*, const Node* stayWithin);
+Node* nextSkippingChildren(const ContainerNode*);
+Node* nextSkippingChildren(const ContainerNode*, const Node* stayWithin);
+
+// Does a reverse pre-order traversal to find the node that comes before the current one in document order
+Node* previous(const Node*, const Node* stayWithin = 0);
+
+// Like previous, but skips children and starts with the next sibling.
+Node* previousSkippingChildren(const Node*, const Node* stayWithin = 0);
+
+// Like next, but visits parents after their children.
+Node* nextPostOrder(const Node*, const Node* stayWithin = 0);
+
+// Like previous/previousSkippingChildren, but visits parents before their children.
+Node* previousPostOrder(const Node*, const Node* stayWithin = 0);
+Node* previousSkippingChildrenPostOrder(const Node*, const Node* stayWithin = 0);
+
+// Pre-order traversal including the pseudo-elements.
+Node* previousIncludingPseudo(const Node*, const Node* stayWithin = 0);
+Node* nextIncludingPseudo(const Node*, const Node* stayWithin = 0);
+Node* nextIncludingPseudoSkippingChildren(const Node*, const Node* stayWithin = 0);
+
+}
+
+namespace ElementTraversal {
+template <class NodeType>
+inline Element* firstElementWithinTemplate(NodeType* current)
+{
+    // Except for the root containers, only elements can have element children.
+    Node* node = current->firstChild();
+    while (node && !node->isElementNode())
+        node = node->nextSibling();
+    return toElement(node);
+}
+inline Element* firstWithin(const ContainerNode* current) { return firstElementWithinTemplate(current); }
+inline Element* firstWithin(const Node* current) { return firstElementWithinTemplate(current); }
+
+template <class NodeType>
+inline Element* traverseNextElementTemplate(NodeType* current)
+{
+    Node* node = NodeTraversal::next(current);
+    while (node && !node->isElementNode())
+        node = NodeTraversal::nextSkippingChildren(node);
+    return toElement(node);
+}
+inline Element* next(const ContainerNode* current) { return traverseNextElementTemplate(current); }
+inline Element* next(const Node* current) { return traverseNextElementTemplate(current); }
+
+template <class NodeType>
+inline Element* traverseNextElementTemplate(NodeType* current, const Node* stayWithin)
+{
+    Node* node = NodeTraversal::next(current, stayWithin);
+    while (node && !node->isElementNode())
+        node = NodeTraversal::nextSkippingChildren(node, stayWithin);
+    return toElement(node);
+}
+inline Element* next(const ContainerNode* current, const Node* stayWithin) { return traverseNextElementTemplate(current, stayWithin); }
+inline Element* next(const Node* current, const Node* stayWithin) { return traverseNextElementTemplate(current, stayWithin); }
+
+template <class NodeType>
+inline Element* traverseNextElementSkippingChildrenTemplate(NodeType* current)
+{
+    Node* node = NodeTraversal::nextSkippingChildren(current);
+    while (node && !node->isElementNode())
+        node = NodeTraversal::nextSkippingChildren(node);
+    return toElement(node);
+}
+inline Element* nextSkippingChildren(const ContainerNode* current) { return traverseNextElementSkippingChildrenTemplate(current); }
+inline Element* nextSkippingChildren(const Node* current) { return traverseNextElementSkippingChildrenTemplate(current); }
+
+template <class NodeType>
+inline Element* traverseNextElementSkippingChildrenTemplate(NodeType* current, const Node* stayWithin)
+{
+    Node* node = NodeTraversal::nextSkippingChildren(current, stayWithin);
+    while (node && !node->isElementNode())
+        node = NodeTraversal::nextSkippingChildren(node, stayWithin);
+    return toElement(node);
+}
+inline Element* nextSkippingChildren(const ContainerNode* current, const Node* stayWithin) { return traverseNextElementSkippingChildrenTemplate(current, stayWithin); }
+inline Element* nextSkippingChildren(const Node* current, const Node* stayWithin) { return traverseNextElementSkippingChildrenTemplate(current, stayWithin); }
+
+inline Element* previousIncludingPseudo(const Node* current, const Node* stayWithin)
+{
+    Node* node = NodeTraversal::previousIncludingPseudo(current, stayWithin);
+    while (node && !node->isElementNode())
+        node = NodeTraversal::previousIncludingPseudo(node, stayWithin);
+    return toElement(node);
+}
+
+inline Element* nextIncludingPseudo(const Node* current, const Node* stayWithin)
+{
+    Node* node = NodeTraversal::nextIncludingPseudo(current, stayWithin);
+    while (node && !node->isElementNode())
+        node = NodeTraversal::nextIncludingPseudo(node, stayWithin);
+    return toElement(node);
+}
+
+inline Element* nextIncludingPseudoSkippingChildren(const Node* current, const Node* stayWithin)
+{
+    Node* node = NodeTraversal::nextIncludingPseudoSkippingChildren(current, stayWithin);
+    while (node && !node->isElementNode())
+        node = NodeTraversal::nextIncludingPseudoSkippingChildren(node, stayWithin);
+    return toElement(node);
+}
+
+inline Element* pseudoAwarePreviousSibling(const Node* current)
+{
+    Node* node = current->pseudoAwarePreviousSibling();
+    while (node && !node->isElementNode())
+        node = node->pseudoAwarePreviousSibling();
+    return toElement(node);
+}
+
+}
+
+namespace NodeTraversal {
+
+Node* nextAncestorSibling(const Node*);
+Node* nextAncestorSibling(const Node*, const Node* stayWithin);
+
+template <class NodeType>
+inline Node* traverseNextTemplate(NodeType* current)
+{
+    if (current->firstChild())
+        return current->firstChild();
+    if (current->nextSibling())
+        return current->nextSibling();
+    return nextAncestorSibling(current);
+}
+inline Node* next(const Node* current) { return traverseNextTemplate(current); }
+inline Node* next(const ContainerNode* current) { return traverseNextTemplate(current); }
+    
+template <class NodeType>
+inline Node* traverseNextTemplate(NodeType* current, const Node* stayWithin)
+{
+    if (current->firstChild())
+        return current->firstChild();
+    if (current == stayWithin)
+        return 0;
+    if (current->nextSibling())
+        return current->nextSibling();
+    return nextAncestorSibling(current, stayWithin);
+}
+inline Node* next(const Node* current, const Node* stayWithin) { return traverseNextTemplate(current, stayWithin); }
+inline Node* next(const ContainerNode* current, const Node* stayWithin) { return traverseNextTemplate(current, stayWithin); }
+
+template <class NodeType>
+inline Node* traverseNextSkippingChildrenTemplate(NodeType* current)
+{
+    if (current->nextSibling())
+        return current->nextSibling();
+    return nextAncestorSibling(current);
+}
+inline Node* nextSkippingChildren(const Node* current) { return traverseNextSkippingChildrenTemplate(current); }
+inline Node* nextSkippingChildren(const ContainerNode* current) { return traverseNextSkippingChildrenTemplate(current); }
+
+template <class NodeType>
+inline Node* traverseNextSkippingChildrenTemplate(NodeType* current, const Node* stayWithin)
+{
+    if (current == stayWithin)
+        return 0;
+    if (current->nextSibling())
+        return current->nextSibling();
+    return nextAncestorSibling(current, stayWithin);
+}
+inline Node* nextSkippingChildren(const Node* current, const Node* stayWithin) { return traverseNextSkippingChildrenTemplate(current, stayWithin); }
+inline Node* nextSkippingChildren(const ContainerNode* current, const Node* stayWithin) { return traverseNextSkippingChildrenTemplate(current, stayWithin); }
+
+}
+
+}
+
+#endif
diff --git a/Source/core/dom/NodeWithIndex.h b/Source/core/dom/NodeWithIndex.h
new file mode 100644
index 0000000..9c93755
--- /dev/null
+++ b/Source/core/dom/NodeWithIndex.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef NodeWithIndex_h
+#define NodeWithIndex_h
+
+#include "core/dom/Node.h"
+
+namespace WebCore {
+
+// For use when you want to get the index for a node repeatedly and
+// only want to walk the child list to figure out the index once.
+class NodeWithIndex {
+public:
+    explicit NodeWithIndex(Node* node)
+        : m_node(node)
+        , m_haveIndex(false)
+    {
+        ASSERT(node);
+    }
+
+    Node* node() const { return m_node; }
+
+    int index() const
+    {
+        if (!m_haveIndex) {
+            m_index = m_node->nodeIndex();
+            m_haveIndex = true;
+        }
+        ASSERT(m_index == static_cast<int>(m_node->nodeIndex()));
+        return m_index;
+    }
+
+private:
+    Node* m_node;
+    mutable bool m_haveIndex;
+    mutable int m_index;
+};
+
+}
+
+#endif
diff --git a/Source/core/dom/Notation.cpp b/Source/core/dom/Notation.cpp
new file mode 100644
index 0000000..ee4befd
--- /dev/null
+++ b/Source/core/dom/Notation.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2000 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/Notation.h"
+
+#include "core/dom/Document.h"
+
+namespace WebCore {
+
+Notation::Notation(Document* document, const String& name, const String& publicId, const String& systemId)
+    : ContainerNode(document)
+    , m_name(name)
+    , m_publicId(publicId)
+    , m_systemId(systemId)
+{
+    ScriptWrappable::init(this);
+}
+
+String Notation::nodeName() const
+{
+    return m_name;
+}
+
+Node::NodeType Notation::nodeType() const
+{
+    return NOTATION_NODE;
+}
+
+PassRefPtr<Node> Notation::cloneNode(bool /*deep*/)
+{
+    // Spec says cloning Notation nodes is "implementation dependent". We do not support it.
+    return 0;
+}
+
+bool Notation::childTypeAllowed(NodeType) const
+{
+    return false;
+}
+
+} // namespace
diff --git a/Source/core/dom/Notation.h b/Source/core/dom/Notation.h
new file mode 100644
index 0000000..507e10f
--- /dev/null
+++ b/Source/core/dom/Notation.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2000 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Notation_h
+#define Notation_h
+
+#include "core/dom/ContainerNode.h"
+
+namespace WebCore {
+
+// FIXME: This class is never instantiated. Maybe it should be removed.
+
+class Notation FINAL : public ContainerNode {
+public:
+    const String& publicId() const { return m_publicId; }
+    const String& systemId() const { return m_systemId; }
+
+private:
+    Notation(Document*, const String& name, const String& publicId, const String& systemId);
+
+    virtual String nodeName() const;
+    virtual NodeType nodeType() const;
+    virtual PassRefPtr<Node> cloneNode(bool deep);
+    virtual bool childTypeAllowed(NodeType) const;
+
+    String m_name;
+    String m_publicId;
+    String m_systemId;
+};
+
+} //namespace
+
+#endif
diff --git a/Source/core/dom/Notation.idl b/Source/core/dom/Notation.idl
new file mode 100644
index 0000000..4ac628f
--- /dev/null
+++ b/Source/core/dom/Notation.idl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+interface Notation : Node {
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString publicId;
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString systemId;
+};
+
diff --git a/Source/core/dom/OverflowEvent.cpp b/Source/core/dom/OverflowEvent.cpp
new file mode 100644
index 0000000..a90ff6f
--- /dev/null
+++ b/Source/core/dom/OverflowEvent.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "core/dom/OverflowEvent.h"
+
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+OverflowEventInit::OverflowEventInit()
+    : orient(0)
+    , horizontalOverflow(false)
+    , verticalOverflow(false)
+{
+}
+
+OverflowEvent::OverflowEvent()
+    : Event(eventNames().overflowchangedEvent, false, false)
+    , m_orient(VERTICAL)
+    , m_horizontalOverflow(false)
+    , m_verticalOverflow(false)
+{
+    ScriptWrappable::init(this);
+}
+
+OverflowEvent::OverflowEvent(bool horizontalOverflowChanged, bool horizontalOverflow, bool verticalOverflowChanged, bool verticalOverflow)
+    : Event(eventNames().overflowchangedEvent, false, false)
+    , m_horizontalOverflow(horizontalOverflow)
+    , m_verticalOverflow(verticalOverflow)
+{
+    ASSERT(horizontalOverflowChanged || verticalOverflowChanged);
+    ScriptWrappable::init(this);
+
+    if (horizontalOverflowChanged && verticalOverflowChanged)
+        m_orient = BOTH;
+    else if (horizontalOverflowChanged)
+        m_orient = HORIZONTAL;
+    else
+        m_orient = VERTICAL;
+}
+
+OverflowEvent::OverflowEvent(const AtomicString& type, const OverflowEventInit& initializer)
+    : Event(type, initializer)
+    , m_orient(initializer.orient)
+    , m_horizontalOverflow(initializer.horizontalOverflow)
+    , m_verticalOverflow(initializer.verticalOverflow)
+{
+    ScriptWrappable::init(this);
+}
+
+const AtomicString& OverflowEvent::interfaceName() const
+{
+    return eventNames().interfaceForOverflowEvent;
+}
+
+void OverflowEvent::initOverflowEvent(unsigned short orient, bool horizontalOverflow, bool verticalOverflow)
+{
+    if (dispatched())
+        return;
+
+    m_orient = orient;
+    m_horizontalOverflow = horizontalOverflow;
+    m_verticalOverflow = verticalOverflow;
+}
+
+}
diff --git a/Source/core/dom/OverflowEvent.h b/Source/core/dom/OverflowEvent.h
new file mode 100644
index 0000000..38b940e
--- /dev/null
+++ b/Source/core/dom/OverflowEvent.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef OverflowEvent_h
+#define OverflowEvent_h
+
+#include "core/dom/Event.h"
+
+namespace WebCore {
+
+struct OverflowEventInit : public EventInit {
+    OverflowEventInit();
+
+    unsigned short orient;
+    bool horizontalOverflow;
+    bool verticalOverflow;
+};
+
+class OverflowEvent : public Event {
+public:
+    enum orientType {
+        HORIZONTAL = 0,
+        VERTICAL   = 1,
+        BOTH       = 2
+    };
+
+    static PassRefPtr<OverflowEvent> create()
+    {
+        return adoptRef(new OverflowEvent);
+    }
+    static PassRefPtr<OverflowEvent> create(bool horizontalOverflowChanged, bool horizontalOverflow, bool verticalOverflowChanged, bool verticalOverflow)
+    {
+        return adoptRef(new OverflowEvent(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow));
+    }
+    static PassRefPtr<OverflowEvent> create(const AtomicString& type, const OverflowEventInit& initializer)
+    {
+        return adoptRef(new OverflowEvent(type, initializer));
+    }
+
+    void initOverflowEvent(unsigned short orient, bool horizontalOverflow, bool verticalOverflow);
+
+    unsigned short orient() const { return m_orient; }
+    bool horizontalOverflow() const { return m_horizontalOverflow; }
+    bool verticalOverflow() const { return m_verticalOverflow; }
+
+    virtual const AtomicString& interfaceName() const;
+
+private:
+    OverflowEvent();
+    OverflowEvent(bool horizontalOverflowChanged, bool horizontalOverflow, bool verticalOverflowChanged, bool verticalOverflow);
+    OverflowEvent(const AtomicString&, const OverflowEventInit&);
+
+    unsigned short m_orient;
+    bool m_horizontalOverflow;
+    bool m_verticalOverflow;
+};
+
+}
+
+#endif // OverflowEvent_h
diff --git a/Source/core/dom/OverflowEvent.idl b/Source/core/dom/OverflowEvent.idl
new file mode 100644
index 0000000..04a86c8
--- /dev/null
+++ b/Source/core/dom/OverflowEvent.idl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+[
+    ConstructorTemplate=Event
+] interface OverflowEvent : Event {
+    const unsigned short HORIZONTAL = 0;
+    const unsigned short VERTICAL   = 1;
+    const unsigned short BOTH       = 2;
+    
+    [InitializedByEventConstructor] readonly attribute unsigned short orient;
+    [InitializedByEventConstructor] readonly attribute boolean horizontalOverflow;
+    [InitializedByEventConstructor] readonly attribute boolean verticalOverflow;
+};
+
diff --git a/Source/core/dom/PageTransitionEvent.cpp b/Source/core/dom/PageTransitionEvent.cpp
new file mode 100644
index 0000000..2c210d0
--- /dev/null
+++ b/Source/core/dom/PageTransitionEvent.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "core/dom/PageTransitionEvent.h"
+
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+PageTransitionEventInit::PageTransitionEventInit()
+    : persisted(false)
+{
+}
+
+PageTransitionEvent::PageTransitionEvent()
+    : m_persisted(false)
+{
+    ScriptWrappable::init(this);
+}
+
+PageTransitionEvent::PageTransitionEvent(const AtomicString& type, bool persisted)
+    : Event(type, true, true)
+    , m_persisted(persisted)
+{
+    ScriptWrappable::init(this);
+}
+
+PageTransitionEvent::PageTransitionEvent(const AtomicString& type, const PageTransitionEventInit& initializer)
+    : Event(type, initializer)
+    , m_persisted(initializer.persisted)
+{
+    ScriptWrappable::init(this);
+}
+
+PageTransitionEvent::~PageTransitionEvent()
+{
+}
+
+const AtomicString& PageTransitionEvent::interfaceName() const
+{
+    return eventNames().interfaceForPageTransitionEvent;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/PageTransitionEvent.h b/Source/core/dom/PageTransitionEvent.h
new file mode 100644
index 0000000..16d0115
--- /dev/null
+++ b/Source/core/dom/PageTransitionEvent.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef PageTransitionEvent_h
+#define PageTransitionEvent_h
+
+#include "core/dom/Event.h"
+
+namespace WebCore {
+
+struct PageTransitionEventInit : public EventInit {
+    PageTransitionEventInit();
+
+    bool persisted;
+};
+
+class PageTransitionEvent : public Event {
+public:
+    static PassRefPtr<PageTransitionEvent> create()
+    {
+        return adoptRef(new PageTransitionEvent);
+    }
+    static PassRefPtr<PageTransitionEvent> create(const AtomicString& type, bool persisted)
+    {
+        return adoptRef(new PageTransitionEvent(type, persisted));
+    }
+    static PassRefPtr<PageTransitionEvent> create(const AtomicString& type, const PageTransitionEventInit& initializer)
+    {
+        return adoptRef(new PageTransitionEvent(type, initializer));
+    }
+
+    virtual ~PageTransitionEvent();
+
+    virtual const AtomicString& interfaceName() const;
+
+    bool persisted() const { return m_persisted; }
+
+private:
+    PageTransitionEvent();
+    PageTransitionEvent(const AtomicString& type, bool persisted);
+    PageTransitionEvent(const AtomicString&, const PageTransitionEventInit&);
+
+    bool m_persisted;
+};
+
+} // namespace WebCore
+
+#endif // PageTransitionEvent_h
diff --git a/Source/core/dom/PageTransitionEvent.idl b/Source/core/dom/PageTransitionEvent.idl
new file mode 100644
index 0000000..c8cea7f
--- /dev/null
+++ b/Source/core/dom/PageTransitionEvent.idl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+[
+    ConstructorTemplate=Event
+] interface PageTransitionEvent : Event {
+    [InitializedByEventConstructor] readonly attribute boolean persisted;
+};
+
diff --git a/Source/core/dom/PendingScript.cpp b/Source/core/dom/PendingScript.cpp
new file mode 100644
index 0000000..e344593
--- /dev/null
+++ b/Source/core/dom/PendingScript.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 "core/dom/PendingScript.h"
+
+#include "core/dom/Element.h"
+#include "core/loader/cache/CachedScript.h"
+
+namespace WebCore {
+
+PendingScript::~PendingScript()
+{
+    if (m_cachedScript)
+        m_cachedScript->removeClient(this);
+}
+
+PassRefPtr<Element> PendingScript::releaseElementAndClear()
+{
+    setCachedScript(0);
+    m_watchingForLoad = false;
+    m_startingPosition = TextPosition::belowRangePosition();
+    return m_element.release();
+}
+
+void PendingScript::setCachedScript(CachedScript* cachedScript)
+{
+    if (m_cachedScript == cachedScript)
+        return;
+    if (m_cachedScript)
+        m_cachedScript->removeClient(this);
+    m_cachedScript = cachedScript;
+    if (m_cachedScript)
+        m_cachedScript->addClient(this);
+}
+
+CachedScript* PendingScript::cachedScript() const
+{
+    return m_cachedScript.get();
+}
+
+void PendingScript::notifyFinished(CachedResource*)
+{
+}
+
+}
diff --git a/Source/core/dom/PendingScript.h b/Source/core/dom/PendingScript.h
new file mode 100644
index 0000000..ee183a2
--- /dev/null
+++ b/Source/core/dom/PendingScript.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 PendingScript_h
+#define PendingScript_h
+
+#include "core/loader/cache/CachedResourceClient.h"
+#include "core/loader/cache/CachedResourceHandle.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/TextPosition.h>
+
+namespace WebCore {
+
+class CachedScript;
+class Element;
+
+// A container for an external script which may be loaded and executed.
+//
+// A CachedResourceHandle alone does not prevent the underlying CachedResource
+// from purging its data buffer. This class holds a dummy client open for its
+// lifetime in order to guarantee that the data buffer will not be purged.
+class PendingScript : public CachedResourceClient {
+public:
+    PendingScript()
+        : m_watchingForLoad(false)
+        , m_startingPosition(TextPosition::belowRangePosition())
+    {
+    }
+
+    PendingScript(Element* element, CachedScript* cachedScript)
+        : m_watchingForLoad(false)
+        , m_element(element)
+    {
+        setCachedScript(cachedScript);
+    }
+
+    PendingScript(const PendingScript& other)
+        : CachedResourceClient(other)
+        , m_watchingForLoad(other.m_watchingForLoad)
+        , m_element(other.m_element)
+        , m_startingPosition(other.m_startingPosition)
+    {
+        setCachedScript(other.cachedScript());
+    }
+
+    ~PendingScript();
+
+    PendingScript& operator=(const PendingScript& other)
+    {
+        if (this == &other)
+            return *this;
+
+        m_watchingForLoad = other.m_watchingForLoad;
+        m_element = other.m_element;
+        m_startingPosition = other.m_startingPosition;
+        setCachedScript(other.cachedScript());
+
+        return *this;
+    }
+
+    TextPosition startingPosition() const { return m_startingPosition; }
+    void setStartingPosition(const TextPosition& position) { m_startingPosition = position; }
+
+    bool watchingForLoad() const { return m_watchingForLoad; }
+    void setWatchingForLoad(bool b) { m_watchingForLoad = b; }
+
+    Element* element() const { return m_element.get(); }
+    void setElement(Element* element) { m_element = element; }
+    PassRefPtr<Element> releaseElementAndClear();
+
+    CachedScript* cachedScript() const;
+    void setCachedScript(CachedScript*);
+
+    virtual void notifyFinished(CachedResource*);
+
+private:
+    bool m_watchingForLoad;
+    RefPtr<Element> m_element;
+    TextPosition m_startingPosition; // Only used for inline script tags.
+    CachedResourceHandle<CachedScript> m_cachedScript; 
+};
+
+}
+
+#endif
diff --git a/Source/core/dom/PopStateEvent.cpp b/Source/core/dom/PopStateEvent.cpp
new file mode 100644
index 0000000..072d28b
--- /dev/null
+++ b/Source/core/dom/PopStateEvent.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "core/dom/PopStateEvent.h"
+
+#include "bindings/v8/SerializedScriptValue.h"
+#include "core/dom/EventNames.h"
+#include "core/page/History.h"
+
+namespace WebCore {
+
+PopStateEventInit::PopStateEventInit()
+{
+}
+
+PopStateEvent::PopStateEvent()
+    : Event(eventNames().popstateEvent, false, true)
+    , m_serializedState(0)
+    , m_history(0)
+{
+    ScriptWrappable::init(this);
+}
+
+PopStateEvent::PopStateEvent(const AtomicString& type, const PopStateEventInit& initializer)
+    : Event(type, initializer)
+    , m_state(initializer.state)
+    , m_serializedState(0)
+    , m_history(0)
+{
+    ScriptWrappable::init(this);
+}
+
+PopStateEvent::PopStateEvent(PassRefPtr<SerializedScriptValue> serializedState, PassRefPtr<History> history)
+    : Event(eventNames().popstateEvent, false, true)
+    , m_serializedState(serializedState)
+    , m_history(history)
+{
+    ScriptWrappable::init(this);
+}
+
+PopStateEvent::~PopStateEvent()
+{
+}
+
+PassRefPtr<PopStateEvent> PopStateEvent::create()
+{
+    return adoptRef(new PopStateEvent);
+}
+
+PassRefPtr<PopStateEvent> PopStateEvent::create(PassRefPtr<SerializedScriptValue> serializedState, PassRefPtr<History> history)
+{
+    return adoptRef(new PopStateEvent(serializedState, history));
+}
+
+PassRefPtr<PopStateEvent> PopStateEvent::create(const AtomicString& type, const PopStateEventInit& initializer)
+{
+    return adoptRef(new PopStateEvent(type, initializer));
+}
+
+const AtomicString& PopStateEvent::interfaceName() const
+{
+    return eventNames().interfaceForPopStateEvent;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/PopStateEvent.h b/Source/core/dom/PopStateEvent.h
new file mode 100644
index 0000000..1c59d0f
--- /dev/null
+++ b/Source/core/dom/PopStateEvent.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef PopStateEvent_h
+#define PopStateEvent_h
+
+#include "bindings/v8/ScriptValue.h"
+#include "core/dom/Event.h"
+
+namespace WebCore {
+
+struct PopStateEventInit : public EventInit {
+    PopStateEventInit();
+
+    ScriptValue state;
+};
+
+class History;
+class SerializedScriptValue;
+
+class PopStateEvent : public Event {
+public:
+    virtual ~PopStateEvent();
+    static PassRefPtr<PopStateEvent> create();
+    static PassRefPtr<PopStateEvent> create(PassRefPtr<SerializedScriptValue>, PassRefPtr<History>);
+    static PassRefPtr<PopStateEvent> create(const AtomicString&, const PopStateEventInit&);
+
+    PassRefPtr<SerializedScriptValue> serializedState() const { return m_serializedState; }
+    const ScriptValue& state() const { return m_state; }
+    History* history() const { return m_history.get(); }
+
+    virtual const AtomicString& interfaceName() const;
+
+private:
+    PopStateEvent();
+    PopStateEvent(const AtomicString&, const PopStateEventInit&);
+    explicit PopStateEvent(PassRefPtr<SerializedScriptValue>, PassRefPtr<History>);
+
+    ScriptValue m_state;
+    RefPtr<SerializedScriptValue> m_serializedState;
+    RefPtr<History> m_history;
+};
+
+} // namespace WebCore
+
+#endif // PopStateEvent_h
diff --git a/Source/core/dom/PopStateEvent.idl b/Source/core/dom/PopStateEvent.idl
new file mode 100644
index 0000000..c4153f6
--- /dev/null
+++ b/Source/core/dom/PopStateEvent.idl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+[
+    ConstructorTemplate=Event
+] interface PopStateEvent : Event {
+    [InitializedByEventConstructor, CachedAttribute, CustomGetter] readonly attribute any state;
+};
diff --git a/Source/core/dom/Position.cpp b/Source/core/dom/Position.cpp
new file mode 100644
index 0000000..21f5080
--- /dev/null
+++ b/Source/core/dom/Position.cpp
@@ -0,0 +1,1400 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/Position.h"
+
+#include <stdio.h>
+#include "HTMLNames.h"
+#include "core/css/CSSComputedStyleDeclaration.h"
+#include "core/dom/PositionIterator.h"
+#include "core/dom/Text.h"
+#include "core/editing/TextIterator.h"
+#include "core/editing/VisiblePosition.h"
+#include "core/editing/VisibleUnits.h"
+#include "core/editing/htmlediting.h"
+#include "RuntimeEnabledFeatures.h"
+#include "core/platform/Logging.h"
+#include "core/rendering/InlineIterator.h"
+#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderText.h"
+#include <wtf/text/CString.h>
+#include <wtf/unicode/CharacterNames.h>
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+static Node* nextRenderedEditable(Node* node)
+{
+    while ((node = node->nextLeafNode())) {
+        if (!node->rendererIsEditable())
+            continue;
+        RenderObject* renderer = node->renderer();
+        if (!renderer)
+            continue;
+        if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) || (renderer->isText() && toRenderText(renderer)->firstTextBox()))
+            return node;
+    }
+    return 0;
+}
+
+static Node* previousRenderedEditable(Node* node)
+{
+    while ((node = node->previousLeafNode())) {
+        if (!node->rendererIsEditable())
+            continue;
+        RenderObject* renderer = node->renderer();
+        if (!renderer)
+            continue;
+        if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) || (renderer->isText() && toRenderText(renderer)->firstTextBox()))
+            return node;
+    }
+    return 0;
+}
+
+Position::Position(PassRefPtr<Node> anchorNode, LegacyEditingOffset offset)
+    : m_anchorNode(anchorNode)
+    , m_offset(offset.value())
+    , m_anchorType(anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset))
+    , m_isLegacyEditingPosition(true)
+{
+    ASSERT(!m_anchorNode || !m_anchorNode->isPseudoElement());
+}
+
+Position::Position(PassRefPtr<Node> anchorNode, AnchorType anchorType)
+    : m_anchorNode(anchorNode)
+    , m_offset(0)
+    , m_anchorType(anchorType)
+    , m_isLegacyEditingPosition(false)
+{
+    ASSERT(!m_anchorNode || !m_anchorNode->isPseudoElement());
+
+    ASSERT(anchorType != PositionIsOffsetInAnchor);
+    ASSERT(!((anchorType == PositionIsBeforeChildren || anchorType == PositionIsAfterChildren)
+        && (m_anchorNode->isTextNode() || editingIgnoresContent(m_anchorNode.get()))));
+}
+
+Position::Position(PassRefPtr<Node> anchorNode, int offset, AnchorType anchorType)
+    : m_anchorNode(anchorNode)
+    , m_offset(offset)
+    , m_anchorType(anchorType)
+    , m_isLegacyEditingPosition(false)
+{
+    ASSERT(!m_anchorNode || !m_anchorNode->isPseudoElement());
+
+    ASSERT(anchorType == PositionIsOffsetInAnchor);
+}
+
+Position::Position(PassRefPtr<Text> textNode, unsigned offset)
+    : m_anchorNode(textNode)
+    , m_offset(static_cast<int>(offset))
+    , m_anchorType(PositionIsOffsetInAnchor)
+    , m_isLegacyEditingPosition(false)
+{
+    ASSERT(m_anchorNode);
+}
+
+void Position::moveToPosition(PassRefPtr<Node> node, int offset)
+{
+    ASSERT(!editingIgnoresContent(node.get()));
+    ASSERT(anchorType() == PositionIsOffsetInAnchor || m_isLegacyEditingPosition);
+    m_anchorNode = node;
+    m_offset = offset;
+    if (m_isLegacyEditingPosition)
+        m_anchorType = anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset);
+}
+void Position::moveToOffset(int offset)
+{
+    ASSERT(anchorType() == PositionIsOffsetInAnchor || m_isLegacyEditingPosition);
+    m_offset = offset;
+    if (m_isLegacyEditingPosition)
+        m_anchorType = anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset);
+}
+
+Node* Position::containerNode() const
+{
+    if (!m_anchorNode)
+        return 0;
+
+    switch (anchorType()) {
+    case PositionIsBeforeChildren:
+    case PositionIsAfterChildren:
+    case PositionIsOffsetInAnchor:
+        return m_anchorNode.get();
+    case PositionIsBeforeAnchor:
+    case PositionIsAfterAnchor:
+        return findParent(m_anchorNode.get());
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+Text* Position::containerText() const
+{
+    switch (anchorType()) {
+    case PositionIsOffsetInAnchor:
+        return m_anchorNode && m_anchorNode->isTextNode() ? toText(m_anchorNode.get()) : 0;
+    case PositionIsBeforeAnchor:
+    case PositionIsAfterAnchor:
+        return 0;
+    case PositionIsBeforeChildren:
+    case PositionIsAfterChildren:
+        ASSERT(!m_anchorNode || !m_anchorNode->isTextNode());
+        return 0;
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+int Position::computeOffsetInContainerNode() const
+{
+    if (!m_anchorNode)
+        return 0;
+
+    switch (anchorType()) {
+    case PositionIsBeforeChildren:
+        return 0;
+    case PositionIsAfterChildren:
+        return lastOffsetInNode(m_anchorNode.get());
+    case PositionIsOffsetInAnchor:
+        return minOffsetForNode(m_anchorNode.get(), m_offset);
+    case PositionIsBeforeAnchor:
+        return m_anchorNode->nodeIndex();
+    case PositionIsAfterAnchor:
+        return m_anchorNode->nodeIndex() + 1;
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+int Position::offsetForPositionAfterAnchor() const
+{
+    ASSERT(m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAfterChildren);
+    ASSERT(!m_isLegacyEditingPosition);
+    return lastOffsetForEditing(m_anchorNode.get());
+}
+
+// Neighbor-anchored positions are invalid DOM positions, so they need to be
+// fixed up before handing them off to the Range object.
+Position Position::parentAnchoredEquivalent() const
+{
+    if (!m_anchorNode)
+        return Position();
+
+    // FIXME: This should only be necessary for legacy positions, but is also needed for positions before and after Tables
+    if (m_offset <= 0 && (m_anchorType != PositionIsAfterAnchor && m_anchorType != PositionIsAfterChildren)) {
+        if (findParent(m_anchorNode.get()) && (editingIgnoresContent(m_anchorNode.get()) || isTableElement(m_anchorNode.get())))
+            return positionInParentBeforeNode(m_anchorNode.get());
+        return Position(m_anchorNode.get(), 0, PositionIsOffsetInAnchor);
+    }
+    if (!m_anchorNode->offsetInCharacters()
+        && (m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAfterChildren || static_cast<unsigned>(m_offset) == m_anchorNode->childNodeCount())
+        && (editingIgnoresContent(m_anchorNode.get()) || isTableElement(m_anchorNode.get()))
+        && containerNode()) {
+        return positionInParentAfterNode(m_anchorNode.get());
+    }
+
+    return Position(containerNode(), computeOffsetInContainerNode(), PositionIsOffsetInAnchor);
+}
+
+Node* Position::computeNodeBeforePosition() const
+{
+    if (!m_anchorNode)
+        return 0;
+
+    switch (anchorType()) {
+    case PositionIsBeforeChildren:
+        return 0;
+    case PositionIsAfterChildren:
+        return m_anchorNode->lastChild();
+    case PositionIsOffsetInAnchor:
+        return m_anchorNode->childNode(m_offset - 1); // -1 converts to childNode((unsigned)-1) and returns null.
+    case PositionIsBeforeAnchor:
+        return m_anchorNode->previousSibling();
+    case PositionIsAfterAnchor:
+        return m_anchorNode.get();
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+Node* Position::computeNodeAfterPosition() const
+{
+    if (!m_anchorNode)
+        return 0;
+
+    switch (anchorType()) {
+    case PositionIsBeforeChildren:
+        return m_anchorNode->firstChild();
+    case PositionIsAfterChildren:
+        return 0;
+    case PositionIsOffsetInAnchor:
+        return m_anchorNode->childNode(m_offset);
+    case PositionIsBeforeAnchor:
+        return m_anchorNode.get();
+    case PositionIsAfterAnchor:
+        return m_anchorNode->nextSibling();
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+Position::AnchorType Position::anchorTypeForLegacyEditingPosition(Node* anchorNode, int offset)
+{
+    if (anchorNode && editingIgnoresContent(anchorNode)) {
+        if (offset == 0)
+            return Position::PositionIsBeforeAnchor;
+        return Position::PositionIsAfterAnchor;
+    }
+    return Position::PositionIsOffsetInAnchor;
+}
+
+// FIXME: This method is confusing (does it return anchorNode() or containerNode()?) and should be renamed or removed
+Element* Position::element() const
+{
+    Node* n = anchorNode();
+    while (n && !n->isElementNode())
+        n = n->parentNode();
+    return toElement(n);
+}
+
+PassRefPtr<CSSComputedStyleDeclaration> Position::computedStyle() const
+{
+    Element* elem = element();
+    if (!elem)
+        return 0;
+    return CSSComputedStyleDeclaration::create(elem);
+}
+
+Position Position::previous(PositionMoveType moveType) const
+{
+    Node* n = deprecatedNode();
+    if (!n)
+        return *this;
+
+    int o = deprecatedEditingOffset();
+    // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.
+    ASSERT(o >= 0);
+
+    if (o > 0) {
+        Node* child = n->childNode(o - 1);
+        if (child)
+            return lastPositionInOrAfterNode(child);
+
+        // There are two reasons child might be 0:
+        //   1) The node is node like a text node that is not an element, and therefore has no children.
+        //      Going backward one character at a time is correct.
+        //   2) The old offset was a bogus offset like (<br>, 1), and there is no child.
+        //      Going from 1 to 0 is correct.
+        switch (moveType) {
+        case CodePoint:
+            return createLegacyEditingPosition(n, o - 1);
+        case Character:
+            return createLegacyEditingPosition(n, uncheckedPreviousOffset(n, o));
+        case BackwardDeletion:
+            return createLegacyEditingPosition(n, uncheckedPreviousOffsetForBackwardDeletion(n, o));
+        }
+    }
+
+    ContainerNode* parent = findParent(n);
+    if (!parent)
+        return *this;
+
+    return createLegacyEditingPosition(parent, n->nodeIndex());
+}
+
+Position Position::next(PositionMoveType moveType) const
+{
+    ASSERT(moveType != BackwardDeletion);
+
+    Node* n = deprecatedNode();
+    if (!n)
+        return *this;
+
+    int o = deprecatedEditingOffset();
+    // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.
+    ASSERT(o >= 0);
+
+    Node* child = n->childNode(o);
+    if (child || (!n->hasChildNodes() && o < lastOffsetForEditing(n))) {
+        if (child)
+            return firstPositionInOrBeforeNode(child);
+
+        // There are two reasons child might be 0:
+        //   1) The node is node like a text node that is not an element, and therefore has no children.
+        //      Going forward one character at a time is correct.
+        //   2) The new offset is a bogus offset like (<br>, 1), and there is no child.
+        //      Going from 0 to 1 is correct.
+        return createLegacyEditingPosition(n, (moveType == Character) ? uncheckedNextOffset(n, o) : o + 1);
+    }
+
+    ContainerNode* parent = findParent(n);
+    if (!parent)
+        return *this;
+
+    return createLegacyEditingPosition(parent, n->nodeIndex() + 1);
+}
+
+int Position::uncheckedPreviousOffset(const Node* n, int current)
+{
+    return n->renderer() ? n->renderer()->previousOffset(current) : current - 1;
+}
+
+int Position::uncheckedPreviousOffsetForBackwardDeletion(const Node* n, int current)
+{
+    return n->renderer() ? n->renderer()->previousOffsetForBackwardDeletion(current) : current - 1;
+}
+
+int Position::uncheckedNextOffset(const Node* n, int current)
+{
+    return n->renderer() ? n->renderer()->nextOffset(current) : current + 1;
+}
+
+bool Position::atFirstEditingPositionForNode() const
+{
+    if (isNull())
+        return true;
+    // FIXME: Position before anchor shouldn't be considered as at the first editing position for node
+    // since that position resides outside of the node.
+    switch (m_anchorType) {
+    case PositionIsOffsetInAnchor:
+        return m_offset <= 0;
+    case PositionIsBeforeChildren:
+    case PositionIsBeforeAnchor:
+        return true;
+    case PositionIsAfterChildren:
+    case PositionIsAfterAnchor:
+        return !lastOffsetForEditing(deprecatedNode());
+    }
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool Position::atLastEditingPositionForNode() const
+{
+    if (isNull())
+        return true;
+    // FIXME: Position after anchor shouldn't be considered as at the first editing position for node
+    // since that position resides outside of the node.
+    return m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAfterChildren || m_offset >= lastOffsetForEditing(deprecatedNode());
+}
+
+// A position is considered at editing boundary if one of the following is true:
+// 1. It is the first position in the node and the next visually equivalent position
+//    is non editable.
+// 2. It is the last position in the node and the previous visually equivalent position
+//    is non editable.
+// 3. It is an editable position and both the next and previous visually equivalent
+//    positions are both non editable.
+bool Position::atEditingBoundary() const
+{
+    Position nextPosition = downstream(CanCrossEditingBoundary);
+    if (atFirstEditingPositionForNode() && nextPosition.isNotNull() && !nextPosition.deprecatedNode()->rendererIsEditable())
+        return true;
+
+    Position prevPosition = upstream(CanCrossEditingBoundary);
+    if (atLastEditingPositionForNode() && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->rendererIsEditable())
+        return true;
+
+    return nextPosition.isNotNull() && !nextPosition.deprecatedNode()->rendererIsEditable()
+        && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->rendererIsEditable();
+}
+
+Node* Position::parentEditingBoundary() const
+{
+    if (!m_anchorNode || !m_anchorNode->document())
+        return 0;
+
+    Node* documentElement = m_anchorNode->document()->documentElement();
+    if (!documentElement)
+        return 0;
+
+    Node* boundary = m_anchorNode.get();
+    while (boundary != documentElement && boundary->nonShadowBoundaryParentNode() && m_anchorNode->rendererIsEditable() == boundary->parentNode()->rendererIsEditable())
+        boundary = boundary->nonShadowBoundaryParentNode();
+
+    return boundary;
+}
+
+
+bool Position::atStartOfTree() const
+{
+    if (isNull())
+        return true;
+    return !findParent(deprecatedNode()) && m_offset <= 0;
+}
+
+bool Position::atEndOfTree() const
+{
+    if (isNull())
+        return true;
+    return !findParent(deprecatedNode()) && m_offset >= lastOffsetForEditing(deprecatedNode());
+}
+
+int Position::renderedOffset() const
+{
+    if (!deprecatedNode()->isTextNode())
+        return m_offset;
+
+    if (!deprecatedNode()->renderer())
+        return m_offset;
+
+    int result = 0;
+    RenderText* textRenderer = toRenderText(deprecatedNode()->renderer());
+    for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
+        int start = box->start();
+        int end = box->start() + box->len();
+        if (m_offset < start)
+            return result;
+        if (m_offset <= end) {
+            result += m_offset - start;
+            return result;
+        }
+        result += box->len();
+    }
+    return result;
+}
+
+// return first preceding DOM position rendered at a different location, or "this"
+Position Position::previousCharacterPosition(EAffinity affinity) const
+{
+    if (isNull())
+        return Position();
+
+    Node* fromRootEditableElement = deprecatedNode()->rootEditableElement();
+
+    bool atStartOfLine = isStartOfLine(VisiblePosition(*this, affinity));
+    bool rendered = isCandidate();
+
+    Position currentPos = *this;
+    while (!currentPos.atStartOfTree()) {
+        currentPos = currentPos.previous();
+
+        if (currentPos.deprecatedNode()->rootEditableElement() != fromRootEditableElement)
+            return *this;
+
+        if (atStartOfLine || !rendered) {
+            if (currentPos.isCandidate())
+                return currentPos;
+        } else if (rendersInDifferentPosition(currentPos))
+            return currentPos;
+    }
+
+    return *this;
+}
+
+// return first following position rendered at a different location, or "this"
+Position Position::nextCharacterPosition(EAffinity affinity) const
+{
+    if (isNull())
+        return Position();
+
+    Node* fromRootEditableElement = deprecatedNode()->rootEditableElement();
+
+    bool atEndOfLine = isEndOfLine(VisiblePosition(*this, affinity));
+    bool rendered = isCandidate();
+
+    Position currentPos = *this;
+    while (!currentPos.atEndOfTree()) {
+        currentPos = currentPos.next();
+
+        if (currentPos.deprecatedNode()->rootEditableElement() != fromRootEditableElement)
+            return *this;
+
+        if (atEndOfLine || !rendered) {
+            if (currentPos.isCandidate())
+                return currentPos;
+        } else if (rendersInDifferentPosition(currentPos))
+            return currentPos;
+    }
+
+    return *this;
+}
+
+// Whether or not [node, 0] and [node, lastOffsetForEditing(node)] are their own VisiblePositions.
+// If true, adjacent candidates are visually distinct.
+// FIXME: Disregard nodes with renderers that have no height, as we do in isCandidate.
+// FIXME: Share code with isCandidate, if possible.
+static bool endsOfNodeAreVisuallyDistinctPositions(Node* node)
+{
+    if (!node || !node->renderer())
+        return false;
+
+    if (!node->renderer()->isInline())
+        return true;
+
+    // Don't include inline tables.
+    if (node->hasTagName(tableTag))
+        return false;
+
+    // There is a VisiblePosition inside an empty inline-block container.
+    return node->renderer()->isReplaced() && canHaveChildrenForEditing(node) && toRenderBox(node->renderer())->height() != 0 && !node->firstChild();
+}
+
+static Node* enclosingVisualBoundary(Node* node)
+{
+    while (node && !endsOfNodeAreVisuallyDistinctPositions(node))
+        node = node->parentNode();
+
+    return node;
+}
+
+// upstream() and downstream() want to return positions that are either in a
+// text node or at just before a non-text node.  This method checks for that.
+static bool isStreamer(const PositionIterator& pos)
+{
+    if (!pos.node())
+        return true;
+
+    if (isAtomicNode(pos.node()))
+        return true;
+
+    return pos.atStartOfNode();
+}
+
+// This function and downstream() are used for moving back and forth between visually equivalent candidates.
+// For example, for the text node "foo     bar" where whitespace is collapsible, there are two candidates
+// that map to the VisiblePosition between 'b' and the space.  This function will return the left candidate
+// and downstream() will return the right one.
+// Also, upstream() will return [boundary, 0] for any of the positions from [boundary, 0] to the first candidate
+// in boundary, where endsOfNodeAreVisuallyDistinctPositions(boundary) is true.
+Position Position::upstream(EditingBoundaryCrossingRule rule) const
+{
+    Node* startNode = deprecatedNode();
+    if (!startNode)
+        return Position();
+
+    // iterate backward from there, looking for a qualified position
+    Node* boundary = enclosingVisualBoundary(startNode);
+    // FIXME: PositionIterator should respect Before and After positions.
+    PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? createLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m_anchorNode.get())) : *this;
+    PositionIterator currentPos = lastVisible;
+    bool startEditable = startNode->rendererIsEditable();
+    Node* lastNode = startNode;
+    bool boundaryCrossed = false;
+    for (; !currentPos.atStart(); currentPos.decrement()) {
+        Node* currentNode = currentPos.node();
+
+        // Don't check for an editability change if we haven't moved to a different node,
+        // to avoid the expense of computing rendererIsEditable().
+        if (currentNode != lastNode) {
+            // Don't change editability.
+            bool currentEditable = currentNode->rendererIsEditable();
+            if (startEditable != currentEditable) {
+                if (rule == CannotCrossEditingBoundary)
+                    break;
+                boundaryCrossed = true;
+            }
+            lastNode = currentNode;
+        }
+
+        // If we've moved to a position that is visually distinct, return the last saved position. There
+        // is code below that terminates early if we're *about* to move to a visually distinct position.
+        if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)
+            return lastVisible;
+
+        // skip position in unrendered or invisible node
+        RenderObject* renderer = currentNode->renderer();
+        if (!renderer || renderer->style()->visibility() != VISIBLE)
+            continue;
+
+        if (rule == CanCrossEditingBoundary && boundaryCrossed) {
+            lastVisible = currentPos;
+            break;
+        }
+
+        // track last visible streamer position
+        if (isStreamer(currentPos))
+            lastVisible = currentPos;
+
+        // Don't move past a position that is visually distinct.  We could rely on code above to terminate and
+        // return lastVisible on the next iteration, but we terminate early to avoid doing a nodeIndex() call.
+        if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentPos.atStartOfNode())
+            return lastVisible;
+
+        // Return position after tables and nodes which have content that can be ignored.
+        if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) {
+            if (currentPos.atEndOfNode())
+                return positionAfterNode(currentNode);
+            continue;
+        }
+
+        // return current position if it is in rendered text
+        if (renderer->isText() && toRenderText(renderer)->firstTextBox()) {
+            if (currentNode != startNode) {
+                // This assertion fires in layout tests in the case-transform.html test because
+                // of a mix-up between offsets in the text in the DOM tree with text in the
+                // render tree which can have a different length due to case transformation.
+                // Until we resolve that, disable this so we can run the layout tests!
+                //ASSERT(currentOffset >= renderer->caretMaxOffset());
+                return createLegacyEditingPosition(currentNode, renderer->caretMaxOffset());
+            }
+
+            unsigned textOffset = currentPos.offsetInLeafNode();
+            RenderText* textRenderer = toRenderText(renderer);
+            InlineTextBox* lastTextBox = textRenderer->lastTextBox();
+            for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
+                if (textOffset <= box->start() + box->len()) {
+                    if (textOffset > box->start())
+                        return currentPos;
+                    continue;
+                }
+
+                if (box == lastTextBox || textOffset != box->start() + box->len() + 1)
+                    continue;
+
+                // The text continues on the next line only if the last text box is not on this line and
+                // none of the boxes on this line have a larger start offset.
+
+                bool continuesOnNextLine = true;
+                InlineBox* otherBox = box;
+                while (continuesOnNextLine) {
+                    otherBox = otherBox->nextLeafChild();
+                    if (!otherBox)
+                        break;
+                    if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() > textOffset))
+                        continuesOnNextLine = false;
+                }
+
+                otherBox = box;
+                while (continuesOnNextLine) {
+                    otherBox = otherBox->prevLeafChild();
+                    if (!otherBox)
+                        break;
+                    if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() > textOffset))
+                        continuesOnNextLine = false;
+                }
+
+                if (continuesOnNextLine)
+                    return currentPos;
+            }
+        }
+    }
+
+    return lastVisible;
+}
+
+// This function and upstream() are used for moving back and forth between visually equivalent candidates.
+// For example, for the text node "foo     bar" where whitespace is collapsible, there are two candidates
+// that map to the VisiblePosition between 'b' and the space.  This function will return the right candidate
+// and upstream() will return the left one.
+// Also, downstream() will return the last position in the last atomic node in boundary for all of the positions
+// in boundary after the last candidate, where endsOfNodeAreVisuallyDistinctPositions(boundary).
+// FIXME: This function should never be called when the line box tree is dirty. See https://bugs.webkit.org/show_bug.cgi?id=97264
+Position Position::downstream(EditingBoundaryCrossingRule rule) const
+{
+    Node* startNode = deprecatedNode();
+    if (!startNode)
+        return Position();
+
+    // iterate forward from there, looking for a qualified position
+    Node* boundary = enclosingVisualBoundary(startNode);
+    // FIXME: PositionIterator should respect Before and After positions.
+    PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? createLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m_anchorNode.get())) : *this;
+    PositionIterator currentPos = lastVisible;
+    bool startEditable = startNode->rendererIsEditable();
+    Node* lastNode = startNode;
+    bool boundaryCrossed = false;
+    for (; !currentPos.atEnd(); currentPos.increment()) {
+        Node* currentNode = currentPos.node();
+
+        // Don't check for an editability change if we haven't moved to a different node,
+        // to avoid the expense of computing rendererIsEditable().
+        if (currentNode != lastNode) {
+            // Don't change editability.
+            bool currentEditable = currentNode->rendererIsEditable();
+            if (startEditable != currentEditable) {
+                if (rule == CannotCrossEditingBoundary)
+                    break;
+                boundaryCrossed = true;
+            }
+
+            lastNode = currentNode;
+        }
+
+        // stop before going above the body, up into the head
+        // return the last visible streamer position
+        if (currentNode->hasTagName(bodyTag) && currentPos.atEndOfNode())
+            break;
+
+        // Do not move to a visually distinct position.
+        if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)
+            return lastVisible;
+        // Do not move past a visually disinct position.
+        // Note: The first position after the last in a node whose ends are visually distinct
+        // positions will be [boundary->parentNode(), originalBlock->nodeIndex() + 1].
+        if (boundary && boundary->parentNode() == currentNode)
+            return lastVisible;
+
+        // skip position in unrendered or invisible node
+        RenderObject* renderer = currentNode->renderer();
+        if (!renderer || renderer->style()->visibility() != VISIBLE)
+            continue;
+
+        if (rule == CanCrossEditingBoundary && boundaryCrossed) {
+            lastVisible = currentPos;
+            break;
+        }
+
+        // track last visible streamer position
+        if (isStreamer(currentPos))
+            lastVisible = currentPos;
+
+        // Return position before tables and nodes which have content that can be ignored.
+        if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) {
+            if (currentPos.offsetInLeafNode() <= renderer->caretMinOffset())
+                return createLegacyEditingPosition(currentNode, renderer->caretMinOffset());
+            continue;
+        }
+
+        // return current position if it is in rendered text
+        if (renderer->isText() && toRenderText(renderer)->firstTextBox()) {
+            if (currentNode != startNode) {
+                ASSERT(currentPos.atStartOfNode());
+                return createLegacyEditingPosition(currentNode, renderer->caretMinOffset());
+            }
+
+            unsigned textOffset = currentPos.offsetInLeafNode();
+            RenderText* textRenderer = toRenderText(renderer);
+            InlineTextBox* lastTextBox = textRenderer->lastTextBox();
+            for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
+                if (textOffset <= box->end()) {
+                    if (textOffset >= box->start())
+                        return currentPos;
+                    continue;
+                }
+
+                if (box == lastTextBox || textOffset != box->start() + box->len())
+                    continue;
+
+                // The text continues on the next line only if the last text box is not on this line and
+                // none of the boxes on this line have a larger start offset.
+
+                bool continuesOnNextLine = true;
+                InlineBox* otherBox = box;
+                while (continuesOnNextLine) {
+                    otherBox = otherBox->nextLeafChild();
+                    if (!otherBox)
+                        break;
+                    if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() >= textOffset))
+                        continuesOnNextLine = false;
+                }
+
+                otherBox = box;
+                while (continuesOnNextLine) {
+                    otherBox = otherBox->prevLeafChild();
+                    if (!otherBox)
+                        break;
+                    if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() >= textOffset))
+                        continuesOnNextLine = false;
+                }
+
+                if (continuesOnNextLine)
+                    return currentPos;
+            }
+        }
+    }
+
+    return lastVisible;
+}
+
+static int boundingBoxLogicalHeight(RenderObject *o, const IntRect &rect)
+{
+    return o->style()->isHorizontalWritingMode() ? rect.height() : rect.width();
+}
+
+bool Position::hasRenderedNonAnonymousDescendantsWithHeight(RenderObject* renderer)
+{
+    RenderObject* stop = renderer->nextInPreOrderAfterChildren();
+    for (RenderObject *o = renderer->firstChild(); o && o != stop; o = o->nextInPreOrder())
+        if (o->nonPseudoNode()) {
+            if ((o->isText() && boundingBoxLogicalHeight(o, toRenderText(o)->linesBoundingBox()))
+                || (o->isBox() && toRenderBox(o)->pixelSnappedLogicalHeight())
+                || (o->isRenderInline() && isEmptyInline(o) && boundingBoxLogicalHeight(o, toRenderInline(o)->linesBoundingBox())))
+                return true;
+        }
+    return false;
+}
+
+bool Position::nodeIsUserSelectNone(Node* node)
+{
+    return node && node->renderer() && node->renderer()->style()->userSelect() == SELECT_NONE;
+}
+
+ContainerNode* Position::findParent(const Node* node)
+{
+    return node->parentNode();
+}
+
+#if ENABLE(USERSELECT_ALL)
+bool Position::nodeIsUserSelectAll(const Node* node)
+{
+    return node && node->renderer() && node->renderer()->style()->userSelect() == SELECT_ALL;
+}
+
+Node* Position::rootUserSelectAllForNode(Node* node)
+{
+    if (!node || !nodeIsUserSelectAll(node))
+        return 0;
+    Node* parent = node->parentNode();
+    if (!parent)
+        return node;
+
+    Node* candidateRoot = node;
+    while (parent) {
+        if (!parent->renderer()) {
+            parent = parent->parentNode();
+            continue;
+        }
+        if (!nodeIsUserSelectAll(parent))
+            break;
+        candidateRoot = parent;
+        parent = candidateRoot->parentNode();
+    }
+    return candidateRoot;
+}
+#endif
+
+bool Position::isCandidate() const
+{
+    if (isNull())
+        return false;
+
+    RenderObject* renderer = deprecatedNode()->renderer();
+    if (!renderer)
+        return false;
+
+    if (renderer->style()->visibility() != VISIBLE)
+        return false;
+
+    if (renderer->isBR())
+        // FIXME: The condition should be m_anchorType == PositionIsBeforeAnchor, but for now we still need to support legacy positions.
+        return !m_offset && m_anchorType != PositionIsAfterAnchor && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
+
+    if (renderer->isText())
+        return !nodeIsUserSelectNone(deprecatedNode()) && inRenderedText();
+
+    if (isTableElement(deprecatedNode()) || editingIgnoresContent(deprecatedNode()))
+        return (atFirstEditingPositionForNode() || atLastEditingPositionForNode()) && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
+
+    if (m_anchorNode->hasTagName(htmlTag))
+        return false;
+
+    if (renderer->isBlockFlow()) {
+        if (toRenderBlock(renderer)->logicalHeight() || m_anchorNode->hasTagName(bodyTag)) {
+            if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer))
+                return atFirstEditingPositionForNode() && !Position::nodeIsUserSelectNone(deprecatedNode());
+            return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
+        }
+    } else
+        return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
+
+    return false;
+}
+
+bool Position::inRenderedText() const
+{
+    if (isNull() || !deprecatedNode()->isTextNode())
+        return false;
+
+    RenderObject* renderer = deprecatedNode()->renderer();
+    if (!renderer)
+        return false;
+
+    RenderText *textRenderer = toRenderText(renderer);
+    for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
+        if (m_offset < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) {
+            // The offset we're looking for is before this node
+            // this means the offset must be in content that is
+            // not rendered. Return false.
+            return false;
+        }
+        if (box->containsCaretOffset(m_offset))
+            // Return false for offsets inside composed characters.
+            return m_offset == 0 || m_offset == textRenderer->nextOffset(textRenderer->previousOffset(m_offset));
+    }
+
+    return false;
+}
+
+bool Position::isRenderedCharacter() const
+{
+    if (isNull() || !deprecatedNode()->isTextNode())
+        return false;
+
+    RenderObject* renderer = deprecatedNode()->renderer();
+    if (!renderer)
+        return false;
+
+    RenderText* textRenderer = toRenderText(renderer);
+    for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
+        if (m_offset < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) {
+            // The offset we're looking for is before this node
+            // this means the offset must be in content that is
+            // not rendered. Return false.
+            return false;
+        }
+        if (m_offset >= static_cast<int>(box->start()) && m_offset < static_cast<int>(box->start() + box->len()))
+            return true;
+    }
+
+    return false;
+}
+
+bool Position::rendersInDifferentPosition(const Position &pos) const
+{
+    if (isNull() || pos.isNull())
+        return false;
+
+    RenderObject* renderer = deprecatedNode()->renderer();
+    if (!renderer)
+        return false;
+
+    RenderObject* posRenderer = pos.deprecatedNode()->renderer();
+    if (!posRenderer)
+        return false;
+
+    if (renderer->style()->visibility() != VISIBLE ||
+        posRenderer->style()->visibility() != VISIBLE)
+        return false;
+
+    if (deprecatedNode() == pos.deprecatedNode()) {
+        if (deprecatedNode()->hasTagName(brTag))
+            return false;
+
+        if (m_offset == pos.deprecatedEditingOffset())
+            return false;
+
+        if (!deprecatedNode()->isTextNode() && !pos.deprecatedNode()->isTextNode()) {
+            if (m_offset != pos.deprecatedEditingOffset())
+                return true;
+        }
+    }
+
+    if (deprecatedNode()->hasTagName(brTag) && pos.isCandidate())
+        return true;
+
+    if (pos.deprecatedNode()->hasTagName(brTag) && isCandidate())
+        return true;
+
+    if (deprecatedNode()->enclosingBlockFlowElement() != pos.deprecatedNode()->enclosingBlockFlowElement())
+        return true;
+
+    if (deprecatedNode()->isTextNode() && !inRenderedText())
+        return false;
+
+    if (pos.deprecatedNode()->isTextNode() && !pos.inRenderedText())
+        return false;
+
+    int thisRenderedOffset = renderedOffset();
+    int posRenderedOffset = pos.renderedOffset();
+
+    if (renderer == posRenderer && thisRenderedOffset == posRenderedOffset)
+        return false;
+
+    int ignoredCaretOffset;
+    InlineBox* b1;
+    getInlineBoxAndOffset(DOWNSTREAM, b1, ignoredCaretOffset);
+    InlineBox* b2;
+    pos.getInlineBoxAndOffset(DOWNSTREAM, b2, ignoredCaretOffset);
+
+    LOG(Editing, "renderer:               %p [%p]\n", renderer, b1);
+    LOG(Editing, "thisRenderedOffset:         %d\n", thisRenderedOffset);
+    LOG(Editing, "posRenderer:            %p [%p]\n", posRenderer, b2);
+    LOG(Editing, "posRenderedOffset:      %d\n", posRenderedOffset);
+    LOG(Editing, "node min/max:           %d:%d\n", caretMinOffset(deprecatedNode()), caretMaxOffset(deprecatedNode()));
+    LOG(Editing, "pos node min/max:       %d:%d\n", caretMinOffset(pos.deprecatedNode()), caretMaxOffset(pos.deprecatedNode()));
+    LOG(Editing, "----------------------------------------------------------------------\n");
+
+    if (!b1 || !b2) {
+        return false;
+    }
+
+    if (b1->root() != b2->root()) {
+        return true;
+    }
+
+    if (nextRenderedEditable(deprecatedNode()) == pos.deprecatedNode()
+        && thisRenderedOffset == caretMaxOffset(deprecatedNode()) && !posRenderedOffset) {
+        return false;
+    }
+
+    if (previousRenderedEditable(deprecatedNode()) == pos.deprecatedNode()
+        && !thisRenderedOffset && posRenderedOffset == caretMaxOffset(pos.deprecatedNode())) {
+        return false;
+    }
+
+    return true;
+}
+
+// This assumes that it starts in editable content.
+Position Position::leadingWhitespacePosition(EAffinity affinity, bool considerNonCollapsibleWhitespace) const
+{
+    ASSERT(isEditablePosition(*this));
+    if (isNull())
+        return Position();
+
+    if (upstream().deprecatedNode()->hasTagName(brTag))
+        return Position();
+
+    Position prev = previousCharacterPosition(affinity);
+    if (prev != *this && prev.deprecatedNode()->inSameContainingBlockFlowElement(deprecatedNode()) && prev.deprecatedNode()->isTextNode()) {
+        String string = toText(prev.deprecatedNode())->data();
+        UChar c = string[prev.deprecatedEditingOffset()];
+        if (considerNonCollapsibleWhitespace ? (isSpaceOrNewline(c) || c == noBreakSpace) : isCollapsibleWhitespace(c))
+            if (isEditablePosition(prev))
+                return prev;
+    }
+
+    return Position();
+}
+
+// This assumes that it starts in editable content.
+Position Position::trailingWhitespacePosition(EAffinity, bool considerNonCollapsibleWhitespace) const
+{
+    ASSERT(isEditablePosition(*this));
+    if (isNull())
+        return Position();
+
+    VisiblePosition v(*this);
+    UChar c = v.characterAfter();
+    // The space must not be in another paragraph and it must be editable.
+    if (!isEndOfParagraph(v) && v.next(CannotCrossEditingBoundary).isNotNull())
+        if (considerNonCollapsibleWhitespace ? (isSpaceOrNewline(c) || c == noBreakSpace) : isCollapsibleWhitespace(c))
+            return *this;
+
+    return Position();
+}
+
+void Position::getInlineBoxAndOffset(EAffinity affinity, InlineBox*& inlineBox, int& caretOffset) const
+{
+    getInlineBoxAndOffset(affinity, primaryDirection(), inlineBox, caretOffset);
+}
+
+static bool isNonTextLeafChild(RenderObject* object)
+{
+    if (object->firstChild())
+        return false;
+    if (object->isText())
+        return false;
+    return true;
+}
+
+static InlineTextBox* searchAheadForBetterMatch(RenderObject* renderer)
+{
+    RenderBlock* container = renderer->containingBlock();
+    RenderObject* next = renderer;
+    while ((next = next->nextInPreOrder(container))) {
+        if (next->isRenderBlock())
+            return 0;
+        if (next->isBR())
+            return 0;
+        if (isNonTextLeafChild(next))
+            return 0;
+        if (next->isText()) {
+            InlineTextBox* match = 0;
+            int minOffset = INT_MAX;
+            for (InlineTextBox* box = toRenderText(next)->firstTextBox(); box; box = box->nextTextBox()) {
+                int caretMinOffset = box->caretMinOffset();
+                if (caretMinOffset < minOffset) {
+                    match = box;
+                    minOffset = caretMinOffset;
+                }
+            }
+            if (match)
+                return match;
+        }
+    }
+    return 0;
+}
+
+static Position downstreamIgnoringEditingBoundaries(Position position)
+{
+    Position lastPosition;
+    while (position != lastPosition) {
+        lastPosition = position;
+        position = position.downstream(CanCrossEditingBoundary);
+    }
+    return position;
+}
+
+static Position upstreamIgnoringEditingBoundaries(Position position)
+{
+    Position lastPosition;
+    while (position != lastPosition) {
+        lastPosition = position;
+        position = position.upstream(CanCrossEditingBoundary);
+    }
+    return position;
+}
+
+void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const
+{
+    caretOffset = deprecatedEditingOffset();
+    RenderObject* renderer = deprecatedNode()->renderer();
+
+    if (!renderer->isText()) {
+        inlineBox = 0;
+        if (canHaveChildrenForEditing(deprecatedNode()) && renderer->isBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) {
+            // Try a visually equivalent position with possibly opposite editability. This helps in case |this| is in
+            // an editable block but surrounded by non-editable positions. It acts to negate the logic at the beginning
+            // of RenderObject::createVisiblePosition().
+            Position equivalent = downstreamIgnoringEditingBoundaries(*this);
+            if (equivalent == *this) {
+                equivalent = upstreamIgnoringEditingBoundaries(*this);
+                if (equivalent == *this || downstreamIgnoringEditingBoundaries(equivalent) == *this)
+                    return;
+            }
+
+            equivalent.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineBox, caretOffset);
+            return;
+        }
+        if (renderer->isBox()) {
+            inlineBox = toRenderBox(renderer)->inlineBoxWrapper();
+            if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset()))
+                return;
+        }
+    } else {
+        RenderText* textRenderer = toRenderText(renderer);
+
+        InlineTextBox* box;
+        InlineTextBox* candidate = 0;
+
+        for (box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
+            int caretMinOffset = box->caretMinOffset();
+            int caretMaxOffset = box->caretMaxOffset();
+
+            if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || (caretOffset == caretMaxOffset && box->isLineBreak()))
+                continue;
+
+            if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset) {
+                inlineBox = box;
+                return;
+            }
+
+            if (((caretOffset == caretMaxOffset) ^ (affinity == DOWNSTREAM))
+                || ((caretOffset == caretMinOffset) ^ (affinity == UPSTREAM))
+                || (caretOffset == caretMaxOffset && box->nextLeafChild() && box->nextLeafChild()->isLineBreak()))
+                break;
+
+            candidate = box;
+        }
+        if (candidate && candidate == textRenderer->lastTextBox() && affinity == DOWNSTREAM) {
+            box = searchAheadForBetterMatch(textRenderer);
+            if (box)
+                caretOffset = box->caretMinOffset();
+        }
+        inlineBox = box ? box : candidate;
+    }
+
+    if (!inlineBox)
+        return;
+
+    unsigned char level = inlineBox->bidiLevel();
+
+    if (inlineBox->direction() == primaryDirection) {
+        if (caretOffset == inlineBox->caretRightmostOffset()) {
+            InlineBox* nextBox = inlineBox->nextLeafChild();
+            if (!nextBox || nextBox->bidiLevel() >= level)
+                return;
+
+            level = nextBox->bidiLevel();
+            InlineBox* prevBox = inlineBox;
+            do {
+                prevBox = prevBox->prevLeafChild();
+            } while (prevBox && prevBox->bidiLevel() > level);
+
+            if (prevBox && prevBox->bidiLevel() == level)   // For example, abc FED 123 ^ CBA
+                return;
+
+            // For example, abc 123 ^ CBA
+            while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
+                if (nextBox->bidiLevel() < level)
+                    break;
+                inlineBox = nextBox;
+            }
+            caretOffset = inlineBox->caretRightmostOffset();
+        } else {
+            InlineBox* prevBox = inlineBox->prevLeafChild();
+            if (!prevBox || prevBox->bidiLevel() >= level)
+                return;
+
+            level = prevBox->bidiLevel();
+            InlineBox* nextBox = inlineBox;
+            do {
+                nextBox = nextBox->nextLeafChild();
+            } while (nextBox && nextBox->bidiLevel() > level);
+
+            if (nextBox && nextBox->bidiLevel() == level)
+                return;
+
+            while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
+                if (prevBox->bidiLevel() < level)
+                    break;
+                inlineBox = prevBox;
+            }
+            caretOffset = inlineBox->caretLeftmostOffset();
+        }
+        return;
+    }
+
+    if (caretOffset == inlineBox->caretLeftmostOffset()) {
+        InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak();
+        if (!prevBox || prevBox->bidiLevel() < level) {
+            // Left edge of a secondary run. Set to the right edge of the entire run.
+            while (InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
+                if (nextBox->bidiLevel() < level)
+                    break;
+                inlineBox = nextBox;
+            }
+            caretOffset = inlineBox->caretRightmostOffset();
+        } else if (prevBox->bidiLevel() > level) {
+            // Right edge of a "tertiary" run. Set to the left edge of that run.
+            while (InlineBox* tertiaryBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
+                if (tertiaryBox->bidiLevel() <= level)
+                    break;
+                inlineBox = tertiaryBox;
+            }
+            caretOffset = inlineBox->caretLeftmostOffset();
+        }
+    } else {
+        InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak();
+        if (!nextBox || nextBox->bidiLevel() < level) {
+            // Right edge of a secondary run. Set to the left edge of the entire run.
+            while (InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
+                if (prevBox->bidiLevel() < level)
+                    break;
+                inlineBox = prevBox;
+            }
+            caretOffset = inlineBox->caretLeftmostOffset();
+        } else if (nextBox->bidiLevel() > level) {
+            // Left edge of a "tertiary" run. Set to the right edge of that run.
+            while (InlineBox* tertiaryBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
+                if (tertiaryBox->bidiLevel() <= level)
+                    break;
+                inlineBox = tertiaryBox;
+            }
+            caretOffset = inlineBox->caretRightmostOffset();
+        }
+    }
+}
+
+TextDirection Position::primaryDirection() const
+{
+    TextDirection primaryDirection = LTR;
+    for (const RenderObject* r = m_anchorNode->renderer(); r; r = r->parent()) {
+        if (r->isBlockFlow()) {
+            primaryDirection = r->style()->direction();
+            break;
+        }
+    }
+
+    return primaryDirection;
+}
+
+
+void Position::debugPosition(const char* msg) const
+{
+    if (isNull())
+        fprintf(stderr, "Position [%s]: null\n", msg);
+    else
+        fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, deprecatedNode()->nodeName().utf8().data(), deprecatedNode(), m_offset);
+}
+
+#ifndef NDEBUG
+
+void Position::formatForDebugger(char* buffer, unsigned length) const
+{
+    StringBuilder result;
+
+    if (isNull())
+        result.appendLiteral("<null>");
+    else {
+        char s[1024];
+        result.appendLiteral("offset ");
+        result.appendNumber(m_offset);
+        result.appendLiteral(" of ");
+        deprecatedNode()->formatForDebugger(s, sizeof(s));
+        result.append(s);
+    }
+
+    strncpy(buffer, result.toString().utf8().data(), length - 1);
+}
+
+void Position::showAnchorTypeAndOffset() const
+{
+    if (m_isLegacyEditingPosition)
+        fputs("legacy, ", stderr);
+    switch (anchorType()) {
+    case PositionIsOffsetInAnchor:
+        fputs("offset", stderr);
+        break;
+    case PositionIsBeforeChildren:
+        fputs("beforeChildren", stderr);
+        break;
+    case PositionIsAfterChildren:
+        fputs("afterChildren", stderr);
+        break;
+    case PositionIsBeforeAnchor:
+        fputs("before", stderr);
+        break;
+    case PositionIsAfterAnchor:
+        fputs("after", stderr);
+        break;
+    }
+    fprintf(stderr, ", offset:%d\n", m_offset);
+}
+
+void Position::showTreeForThis() const
+{
+    if (anchorNode()) {
+        anchorNode()->showTreeForThis();
+        showAnchorTypeAndOffset();
+    }
+}
+
+#endif
+
+
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+
+void showTree(const WebCore::Position& pos)
+{
+    pos.showTreeForThis();
+}
+
+void showTree(const WebCore::Position* pos)
+{
+    if (pos)
+        pos->showTreeForThis();
+}
+
+#endif
diff --git a/Source/core/dom/Position.h b/Source/core/dom/Position.h
new file mode 100644
index 0000000..9cb00f4
--- /dev/null
+++ b/Source/core/dom/Position.h
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef Position_h
+#define Position_h
+
+#include "core/dom/ContainerNode.h"
+#include "core/editing/EditingBoundary.h"
+#include "core/editing/TextAffinity.h"
+#include "core/platform/text/TextDirection.h"
+#include <wtf/Assertions.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CSSComputedStyleDeclaration;
+class Element;
+class InlineBox;
+class Node;
+class Range;
+class RenderObject;
+class Text;
+
+enum PositionMoveType {
+    CodePoint,       // Move by a single code point.
+    Character,       // Move to the next Unicode character break.
+    BackwardDeletion // Subject to platform conventions.
+};
+
+class Position {
+public:
+    enum AnchorType {
+        PositionIsOffsetInAnchor,
+        PositionIsBeforeAnchor,
+        PositionIsAfterAnchor,
+        PositionIsBeforeChildren,
+        PositionIsAfterChildren,
+    };
+
+    Position()
+        : m_offset(0)
+        , m_anchorType(PositionIsOffsetInAnchor)
+        , m_isLegacyEditingPosition(false)
+    {
+    }
+
+    // For creating legacy editing positions: (Anchor type will be determined from editingIgnoresContent(node))
+    class LegacyEditingOffset {
+    public:
+        int value() const { return m_offset; }
+
+    private:
+        explicit LegacyEditingOffset(int offset) : m_offset(offset) { }
+
+        friend Position createLegacyEditingPosition(PassRefPtr<Node>, int offset);
+
+        int m_offset;
+    };
+    Position(PassRefPtr<Node> anchorNode, LegacyEditingOffset);
+
+    // For creating before/after positions:
+    Position(PassRefPtr<Node> anchorNode, AnchorType);
+    Position(PassRefPtr<Text> textNode, unsigned offset);
+
+    // For creating offset positions:
+    // FIXME: This constructor should eventually go away. See bug 63040.
+    Position(PassRefPtr<Node> anchorNode, int offset, AnchorType);
+
+    AnchorType anchorType() const { return static_cast<AnchorType>(m_anchorType); }
+
+    void clear() { m_anchorNode.clear(); m_offset = 0; m_anchorType = PositionIsOffsetInAnchor; m_isLegacyEditingPosition = false; }
+
+    // These are always DOM compliant values.  Editing positions like [img, 0] (aka [img, before])
+    // will return img->parentNode() and img->nodeIndex() from these functions.
+    Node* containerNode() const; // NULL for a before/after position anchored to a node with no parent
+    Text* containerText() const;
+
+    int computeOffsetInContainerNode() const;  // O(n) for before/after-anchored positions, O(1) for parent-anchored positions
+    Position parentAnchoredEquivalent() const; // Convenience method for DOM positions that also fixes up some positions for editing
+
+    // Inline O(1) access for Positions which callers know to be parent-anchored
+    int offsetInContainerNode() const
+    {
+        ASSERT(anchorType() == PositionIsOffsetInAnchor);
+        return m_offset;
+    }
+
+    // New code should not use this function.
+    int deprecatedEditingOffset() const
+    {
+        if (m_isLegacyEditingPosition || (m_anchorType != PositionIsAfterAnchor && m_anchorType != PositionIsAfterChildren))
+            return m_offset;
+        return offsetForPositionAfterAnchor();
+    }
+
+    // These are convenience methods which are smart about whether the position is neighbor anchored or parent anchored
+    Node* computeNodeBeforePosition() const;
+    Node* computeNodeAfterPosition() const;
+
+    Node* anchorNode() const { return m_anchorNode.get(); }
+
+    // FIXME: Callers should be moved off of node(), node() is not always the container for this position.
+    // For nodes which editingIgnoresContent(node()) returns true, positions like [ignoredNode, 0]
+    // will be treated as before ignoredNode (thus node() is really after the position, not containing it).
+    Node* deprecatedNode() const { return m_anchorNode.get(); }
+
+    Document* document() const { return m_anchorNode ? m_anchorNode->document() : 0; }
+    Element* rootEditableElement() const
+    {
+        Node* container = containerNode();
+        return container ? container->rootEditableElement() : 0;
+    }
+
+    // These should only be used for PositionIsOffsetInAnchor positions, unless
+    // the position is a legacy editing position.
+    void moveToPosition(PassRefPtr<Node> anchorNode, int offset);
+    void moveToOffset(int offset);
+
+    bool isNull() const { return !m_anchorNode; }
+    bool isNotNull() const { return m_anchorNode; }
+    bool isOrphan() const { return m_anchorNode && !m_anchorNode->inDocument(); }
+
+    Element* element() const;
+    PassRefPtr<CSSComputedStyleDeclaration> computedStyle() const;
+
+    // Move up or down the DOM by one position.
+    // Offsets are computed using render text for nodes that have renderers - but note that even when
+    // using composed characters, the result may be inside a single user-visible character if a ligature is formed.
+    Position previous(PositionMoveType = CodePoint) const;
+    Position next(PositionMoveType = CodePoint) const;
+    static int uncheckedPreviousOffset(const Node*, int current);
+    static int uncheckedPreviousOffsetForBackwardDeletion(const Node*, int current);
+    static int uncheckedNextOffset(const Node*, int current);
+
+    // These can be either inside or just before/after the node, depending on
+    // if the node is ignored by editing or not.
+    // FIXME: These should go away. They only make sense for legacy positions.
+    bool atFirstEditingPositionForNode() const;
+    bool atLastEditingPositionForNode() const;
+
+    // Returns true if the visually equivalent positions around have different editability
+    bool atEditingBoundary() const;
+    Node* parentEditingBoundary() const;
+    
+    bool atStartOfTree() const;
+    bool atEndOfTree() const;
+
+    // FIXME: Make these non-member functions and put them somewhere in the editing directory.
+    // These aren't really basic "position" operations. More high level editing helper functions.
+    Position leadingWhitespacePosition(EAffinity, bool considerNonCollapsibleWhitespace = false) const;
+    Position trailingWhitespacePosition(EAffinity, bool considerNonCollapsibleWhitespace = false) const;
+    
+    // These return useful visually equivalent positions.
+    Position upstream(EditingBoundaryCrossingRule = CannotCrossEditingBoundary) const;
+    Position downstream(EditingBoundaryCrossingRule = CannotCrossEditingBoundary) const;
+    
+    bool isCandidate() const;
+    bool inRenderedText() const;
+    bool isRenderedCharacter() const;
+    bool rendersInDifferentPosition(const Position&) const;
+
+    void getInlineBoxAndOffset(EAffinity, InlineBox*&, int& caretOffset) const;
+    void getInlineBoxAndOffset(EAffinity, TextDirection primaryDirection, InlineBox*&, int& caretOffset) const;
+
+    TextDirection primaryDirection() const;
+
+    static bool hasRenderedNonAnonymousDescendantsWithHeight(RenderObject*);
+    static bool nodeIsUserSelectNone(Node*);
+#if ENABLE(USERSELECT_ALL)
+    static bool nodeIsUserSelectAll(const Node*);
+    static Node* rootUserSelectAllForNode(Node*);
+#endif
+    static ContainerNode* findParent(const Node*);
+    
+    void debugPosition(const char* msg = "") const;
+
+#ifndef NDEBUG
+    void formatForDebugger(char* buffer, unsigned length) const;
+    void showAnchorTypeAndOffset() const;
+    void showTreeForThis() const;
+#endif
+    
+private:
+    int offsetForPositionAfterAnchor() const;
+
+    int renderedOffset() const;
+
+    
+    Position previousCharacterPosition(EAffinity) const;
+    Position nextCharacterPosition(EAffinity) const;
+
+    static AnchorType anchorTypeForLegacyEditingPosition(Node* anchorNode, int offset);
+
+    RefPtr<Node> m_anchorNode;
+    // m_offset can be the offset inside m_anchorNode, or if editingIgnoresContent(m_anchorNode)
+    // returns true, then other places in editing will treat m_offset == 0 as "before the anchor"
+    // and m_offset > 0 as "after the anchor node".  See parentAnchoredEquivalent for more info.
+    int m_offset;
+    unsigned m_anchorType : 3;
+    bool m_isLegacyEditingPosition : 1;
+};
+
+inline Position createLegacyEditingPosition(PassRefPtr<Node> node, int offset)
+{
+    return Position(node, Position::LegacyEditingOffset(offset));
+}
+
+inline bool operator==(const Position& a, const Position& b)
+{
+    // FIXME: In <div><img></div> [div, 0] != [img, 0] even though most of the
+    // editing code will treat them as identical.
+    return a.anchorNode() == b.anchorNode() && a.deprecatedEditingOffset() == b.deprecatedEditingOffset() && a.anchorType() == b.anchorType();
+}
+
+inline bool operator!=(const Position& a, const Position& b)
+{
+    return !(a == b);
+}
+
+// We define position creation functions to make callsites more readable.
+// These are inline to prevent ref-churn when returning a Position object.
+// If we ever add a PassPosition we can make these non-inline.
+
+inline Position positionInParentBeforeNode(const Node* node)
+{
+    // FIXME: This should ASSERT(node->parentNode())
+    // At least one caller currently hits this ASSERT though, which indicates
+    // that the caller is trying to make a position relative to a disconnected node (which is likely an error)
+    // Specifically, editing/deleting/delete-ligature-001.html crashes with ASSERT(node->parentNode())
+    return Position(Position::findParent(node), node->nodeIndex(), Position::PositionIsOffsetInAnchor);
+}
+
+inline Position positionInParentAfterNode(const Node* node)
+{
+    ASSERT(Position::findParent(node));
+    return Position(Position::findParent(node), node->nodeIndex() + 1, Position::PositionIsOffsetInAnchor);
+}
+
+// positionBeforeNode and positionAfterNode return neighbor-anchored positions, construction is O(1)
+inline Position positionBeforeNode(Node* anchorNode)
+{
+    ASSERT(anchorNode);
+    return Position(anchorNode, Position::PositionIsBeforeAnchor);
+}
+
+inline Position positionAfterNode(Node* anchorNode)
+{
+    ASSERT(anchorNode);
+    return Position(anchorNode, Position::PositionIsAfterAnchor);
+}
+
+inline int lastOffsetInNode(Node* node)
+{
+    return node->offsetInCharacters() ? node->maxCharacterOffset() : static_cast<int>(node->childNodeCount());
+}
+
+// firstPositionInNode and lastPositionInNode return parent-anchored positions, lastPositionInNode construction is O(n) due to childNodeCount()
+inline Position firstPositionInNode(Node* anchorNode)
+{
+    if (anchorNode->isTextNode())
+        return Position(anchorNode, 0, Position::PositionIsOffsetInAnchor);
+    return Position(anchorNode, Position::PositionIsBeforeChildren);
+}
+
+inline Position lastPositionInNode(Node* anchorNode)
+{
+    if (anchorNode->isTextNode())
+        return Position(anchorNode, lastOffsetInNode(anchorNode), Position::PositionIsOffsetInAnchor);
+    return Position(anchorNode, Position::PositionIsAfterChildren);
+}
+
+inline int minOffsetForNode(Node* anchorNode, int offset)
+{
+    if (anchorNode->offsetInCharacters())
+        return std::min(offset, anchorNode->maxCharacterOffset());
+
+    int newOffset = 0;
+    for (Node* node = anchorNode->firstChild(); node && newOffset < offset; node = node->nextSibling())
+        newOffset++;
+    
+    return newOffset;
+}
+
+inline bool offsetIsBeforeLastNodeOffset(int offset, Node* anchorNode)
+{
+    if (anchorNode->offsetInCharacters())
+        return offset < anchorNode->maxCharacterOffset();
+
+    int currentOffset = 0;
+    for (Node* node = anchorNode->firstChild(); node && currentOffset < offset; node = node->nextSibling())
+        currentOffset++;
+    
+    
+    return offset < currentOffset;
+}
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+// Outside the WebCore namespace for ease of invocation from gdb.
+void showTree(const WebCore::Position&);
+void showTree(const WebCore::Position*);
+#endif
+
+#endif // Position_h
diff --git a/Source/core/dom/PositionIterator.cpp b/Source/core/dom/PositionIterator.cpp
new file mode 100644
index 0000000..c9b2ef0
--- /dev/null
+++ b/Source/core/dom/PositionIterator.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "core/dom/PositionIterator.h"
+
+#include "HTMLNames.h"
+#include "core/dom/Node.h"
+#include "core/editing/htmlediting.h"
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+PositionIterator::operator Position() const
+{
+    if (m_nodeAfterPositionInAnchor) {
+        ASSERT(m_nodeAfterPositionInAnchor->parentNode() == m_anchorNode);
+        // FIXME: This check is inadaquete because any ancestor could be ignored by editing
+        if (editingIgnoresContent(m_nodeAfterPositionInAnchor->parentNode()))
+            return positionBeforeNode(m_anchorNode);
+        return positionInParentBeforeNode(m_nodeAfterPositionInAnchor);
+    }
+    if (m_anchorNode->hasChildNodes())
+        return lastPositionInOrAfterNode(m_anchorNode);
+    return createLegacyEditingPosition(m_anchorNode, m_offsetInAnchor);
+}
+
+void PositionIterator::increment()
+{
+    if (!m_anchorNode)
+        return;
+
+    if (m_nodeAfterPositionInAnchor) {
+        m_anchorNode = m_nodeAfterPositionInAnchor;
+        m_nodeAfterPositionInAnchor = m_anchorNode->firstChild();
+        m_offsetInAnchor = 0;
+        return;
+    }
+
+    if (!m_anchorNode->hasChildNodes() && m_offsetInAnchor < lastOffsetForEditing(m_anchorNode))
+        m_offsetInAnchor = Position::uncheckedNextOffset(m_anchorNode, m_offsetInAnchor);
+    else {
+        m_nodeAfterPositionInAnchor = m_anchorNode;
+        m_anchorNode = m_nodeAfterPositionInAnchor->parentNode();
+        m_nodeAfterPositionInAnchor = m_nodeAfterPositionInAnchor->nextSibling();
+        m_offsetInAnchor = 0;
+    }
+}
+
+void PositionIterator::decrement()
+{
+    if (!m_anchorNode)
+        return;
+
+    if (m_nodeAfterPositionInAnchor) {
+        m_anchorNode = m_nodeAfterPositionInAnchor->previousSibling();
+        if (m_anchorNode) {
+            m_nodeAfterPositionInAnchor = 0;
+            m_offsetInAnchor = m_anchorNode->hasChildNodes() ? 0 : lastOffsetForEditing(m_anchorNode);
+        } else {
+            m_nodeAfterPositionInAnchor = m_nodeAfterPositionInAnchor->parentNode();
+            m_anchorNode = m_nodeAfterPositionInAnchor->parentNode();
+            m_offsetInAnchor = 0;
+        }
+        return;
+    }
+    
+    if (m_anchorNode->hasChildNodes()) {
+        m_anchorNode = m_anchorNode->lastChild();
+        m_offsetInAnchor = m_anchorNode->hasChildNodes()? 0: lastOffsetForEditing(m_anchorNode);
+    } else {
+        if (m_offsetInAnchor)
+            m_offsetInAnchor = Position::uncheckedPreviousOffset(m_anchorNode, m_offsetInAnchor);
+        else {
+            m_nodeAfterPositionInAnchor = m_anchorNode;
+            m_anchorNode = m_anchorNode->parentNode();
+        }
+    }
+}
+
+bool PositionIterator::atStart() const
+{
+    if (!m_anchorNode)
+        return true;
+    if (m_anchorNode->parentNode())
+        return false;
+    return (!m_anchorNode->hasChildNodes() && !m_offsetInAnchor) || (m_nodeAfterPositionInAnchor && !m_nodeAfterPositionInAnchor->previousSibling());
+}
+
+bool PositionIterator::atEnd() const
+{
+    if (!m_anchorNode)
+        return true;
+    if (m_nodeAfterPositionInAnchor)
+        return false;
+    return !m_anchorNode->parentNode() && (m_anchorNode->hasChildNodes() || m_offsetInAnchor >= lastOffsetForEditing(m_anchorNode));
+}
+
+bool PositionIterator::atStartOfNode() const
+{
+    if (!m_anchorNode)
+        return true;
+    if (!m_nodeAfterPositionInAnchor)
+        return !m_anchorNode->hasChildNodes() && !m_offsetInAnchor;
+    return !m_nodeAfterPositionInAnchor->previousSibling();
+}
+
+bool PositionIterator::atEndOfNode() const
+{
+    if (!m_anchorNode)
+        return true;
+    if (m_nodeAfterPositionInAnchor)
+        return false;
+    return m_anchorNode->hasChildNodes() || m_offsetInAnchor >= lastOffsetForEditing(m_anchorNode);
+}
+
+bool PositionIterator::isCandidate() const
+{
+    if (!m_anchorNode)
+        return false;
+
+    RenderObject* renderer = m_anchorNode->renderer();
+    if (!renderer)
+        return false;
+    
+    if (renderer->style()->visibility() != VISIBLE)
+        return false;
+
+    if (renderer->isBR())
+        return !m_offsetInAnchor && !Position::nodeIsUserSelectNone(m_anchorNode->parentNode());
+
+    if (renderer->isText())
+        return !Position::nodeIsUserSelectNone(m_anchorNode) && Position(*this).inRenderedText();
+
+    if (isTableElement(m_anchorNode) || editingIgnoresContent(m_anchorNode))
+        return (atStartOfNode() || atEndOfNode()) && !Position::nodeIsUserSelectNone(m_anchorNode->parentNode());
+
+    if (!m_anchorNode->hasTagName(htmlTag) && renderer->isBlockFlow()) {
+        if (toRenderBlock(renderer)->logicalHeight() || m_anchorNode->hasTagName(bodyTag)) {
+            if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer))
+                return atStartOfNode() && !Position::nodeIsUserSelectNone(m_anchorNode);
+            return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSelectNone(m_anchorNode) && Position(*this).atEditingBoundary();
+        }
+    }
+
+    return false;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/PositionIterator.h b/Source/core/dom/PositionIterator.h
new file mode 100644
index 0000000..2457aba
--- /dev/null
+++ b/Source/core/dom/PositionIterator.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef PositionIterator_h
+#define PositionIterator_h
+
+#include "core/dom/Node.h"
+#include "core/dom/Position.h"
+
+namespace WebCore {
+
+// A Position iterator with constant-time
+// increment, decrement, and several predicates on the Position it is at.
+// Conversion to/from Position is O(n) in the offset.
+class PositionIterator {
+public:
+    PositionIterator()
+        : m_anchorNode(0)
+        , m_nodeAfterPositionInAnchor(0)
+        , m_offsetInAnchor(0)
+    {
+    }
+
+    PositionIterator(const Position& pos)
+        : m_anchorNode(pos.anchorNode())
+        , m_nodeAfterPositionInAnchor(m_anchorNode->childNode(pos.deprecatedEditingOffset()))
+        , m_offsetInAnchor(m_nodeAfterPositionInAnchor ? 0 : pos.deprecatedEditingOffset())
+    {
+    }
+    operator Position() const;
+
+    void increment();
+    void decrement();
+
+    Node* node() const { return m_anchorNode; }
+    int offsetInLeafNode() const { return m_offsetInAnchor; }
+
+    bool atStart() const;
+    bool atEnd() const;
+    bool atStartOfNode() const;
+    bool atEndOfNode() const;
+    bool isCandidate() const;
+
+private:
+    Node* m_anchorNode;
+    Node* m_nodeAfterPositionInAnchor; // If this is non-null, m_nodeAfterPositionInAnchor->parentNode() == m_anchorNode;
+    int m_offsetInAnchor;
+};
+
+} // namespace WebCore
+
+#endif // PositionIterator_h
diff --git a/Source/core/dom/ProcessingInstruction.cpp b/Source/core/dom/ProcessingInstruction.cpp
new file mode 100644
index 0000000..49d9d93
--- /dev/null
+++ b/Source/core/dom/ProcessingInstruction.cpp
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2000 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/ProcessingInstruction.h"
+
+#include "core/css/CSSStyleSheet.h"
+#include "core/css/MediaList.h"
+#include "core/css/StyleSheetContents.h"
+#include "core/dom/Document.h"
+#include "core/dom/DocumentStyleSheetCollection.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/loader/FrameLoader.h"
+#include "core/loader/cache/CachedCSSStyleSheet.h"
+#include "core/loader/cache/CachedResourceLoader.h"
+#include "core/loader/cache/CachedResourceRequest.h"
+#include "core/loader/cache/CachedXSLStyleSheet.h"
+#include "core/page/Frame.h"
+#include "core/xml/XSLStyleSheet.h"
+#include "core/xml/parser/XMLDocumentParser.h" // for parseAttributes()
+
+namespace WebCore {
+
+inline ProcessingInstruction::ProcessingInstruction(Document* document, const String& target, const String& data)
+    : Node(document, CreateOther)
+    , m_target(target)
+    , m_data(data)
+    , m_cachedSheet(0)
+    , m_loading(false)
+    , m_alternate(false)
+    , m_createdByParser(false)
+    , m_isCSS(false)
+    , m_isXSL(false)
+{
+    ScriptWrappable::init(this);
+}
+
+PassRefPtr<ProcessingInstruction> ProcessingInstruction::create(Document* document, const String& target, const String& data)
+{
+    return adoptRef(new ProcessingInstruction(document, target, data));
+}
+
+ProcessingInstruction::~ProcessingInstruction()
+{
+    if (m_sheet)
+        m_sheet->clearOwnerNode();
+
+    if (m_cachedSheet)
+        m_cachedSheet->removeClient(this);
+
+    if (inDocument())
+        document()->styleSheetCollection()->removeStyleSheetCandidateNode(this);
+}
+
+void ProcessingInstruction::setData(const String& data, ExceptionCode&)
+{
+    int oldLength = m_data.length();
+    m_data = data;
+    document()->textRemoved(this, 0, oldLength);
+    checkStyleSheet();
+}
+
+String ProcessingInstruction::nodeName() const
+{
+    return m_target;
+}
+
+Node::NodeType ProcessingInstruction::nodeType() const
+{
+    return PROCESSING_INSTRUCTION_NODE;
+}
+
+String ProcessingInstruction::nodeValue() const
+{
+    return m_data;
+}
+
+void ProcessingInstruction::setNodeValue(const String& nodeValue, ExceptionCode& ec)
+{
+    // NO_MODIFICATION_ALLOWED_ERR: taken care of by setData()
+    setData(nodeValue, ec);
+}
+
+PassRefPtr<Node> ProcessingInstruction::cloneNode(bool /*deep*/)
+{
+    // FIXME: Is it a problem that this does not copy m_localHref?
+    // What about other data members?
+    return create(document(), m_target, m_data);
+}
+
+void ProcessingInstruction::checkStyleSheet()
+{
+    if (m_target == "xml-stylesheet" && document()->frame() && parentNode() == document()) {
+        // see http://www.w3.org/TR/xml-stylesheet/
+        // ### support stylesheet included in a fragment of this (or another) document
+        // ### make sure this gets called when adding from javascript
+        bool attrsOk;
+        const HashMap<String, String> attrs = parseAttributes(m_data, attrsOk);
+        if (!attrsOk)
+            return;
+        HashMap<String, String>::const_iterator i = attrs.find("type");
+        String type;
+        if (i != attrs.end())
+            type = i->value;
+
+        m_isCSS = type.isEmpty() || type == "text/css";
+        m_isXSL = (type == "text/xml" || type == "text/xsl" || type == "application/xml" ||
+                   type == "application/xhtml+xml" || type == "application/rss+xml" || type == "application/atom+xml");
+        if (!m_isCSS && !m_isXSL)
+            return;
+
+        String href = attrs.get("href");
+        String alternate = attrs.get("alternate");
+        m_alternate = alternate == "yes";
+        m_title = attrs.get("title");
+        m_media = attrs.get("media");
+
+        if (m_alternate && m_title.isEmpty())
+            return;
+
+        if (href.length() > 1 && href[0] == '#') {
+            m_localHref = href.substring(1);
+            // We need to make a synthetic XSLStyleSheet that is embedded.  It needs to be able
+            // to kick off import/include loads that can hang off some parent sheet.
+            if (m_isXSL) {
+                KURL finalURL(ParsedURLString, m_localHref);
+                m_sheet = XSLStyleSheet::createEmbedded(this, finalURL);
+                m_loading = false;
+            }
+        } else {
+            if (m_cachedSheet) {
+                m_cachedSheet->removeClient(this);
+                m_cachedSheet = 0;
+            }
+            
+            String url = document()->completeURL(href).string();
+            if (!dispatchBeforeLoadEvent(url))
+                return;
+            
+            m_loading = true;
+            document()->styleSheetCollection()->addPendingSheet();
+            
+            CachedResourceRequest request(ResourceRequest(document()->completeURL(href)));
+            if (m_isXSL)
+                m_cachedSheet = document()->cachedResourceLoader()->requestXSLStyleSheet(request);
+            else
+            {
+                String charset = attrs.get("charset");
+                if (charset.isEmpty())
+                    charset = document()->charset();
+                request.setCharset(charset);
+
+                m_cachedSheet = document()->cachedResourceLoader()->requestCSSStyleSheet(request);
+            }
+            if (m_cachedSheet)
+                m_cachedSheet->addClient(this);
+            else {
+                // The request may have been denied if (for example) the stylesheet is local and the document is remote.
+                m_loading = false;
+                document()->styleSheetCollection()->removePendingSheet();
+            }
+        }
+    }
+}
+
+bool ProcessingInstruction::isLoading() const
+{
+    if (m_loading)
+        return true;
+    if (!m_sheet)
+        return false;
+    return m_sheet->isLoading();
+}
+
+bool ProcessingInstruction::sheetLoaded()
+{
+    if (!isLoading()) {
+        document()->styleSheetCollection()->removePendingSheet();
+        return true;
+    }
+    return false;
+}
+
+void ProcessingInstruction::setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet* sheet)
+{
+    if (!inDocument()) {
+        ASSERT(!m_sheet);
+        return;
+    }
+
+    ASSERT(m_isCSS);
+    CSSParserContext parserContext(document(), baseURL, charset);
+
+    RefPtr<StyleSheetContents> newSheet = StyleSheetContents::create(href, parserContext);
+
+    RefPtr<CSSStyleSheet> cssSheet = CSSStyleSheet::create(newSheet, this);
+    cssSheet->setDisabled(m_alternate);
+    cssSheet->setTitle(m_title);
+    cssSheet->setMediaQueries(MediaQuerySet::create(m_media));
+
+    m_sheet = cssSheet.release();
+
+    // We don't need the cross-origin security check here because we are
+    // getting the sheet text in "strict" mode. This enforces a valid CSS MIME
+    // type.
+    parseStyleSheet(sheet->sheetText(true));
+}
+
+void ProcessingInstruction::setXSLStyleSheet(const String& href, const KURL& baseURL, const String& sheet)
+{
+    ASSERT(m_isXSL);
+    m_sheet = XSLStyleSheet::create(this, href, baseURL);
+    parseStyleSheet(sheet);
+}
+
+void ProcessingInstruction::parseStyleSheet(const String& sheet)
+{
+    if (m_isCSS)
+        static_cast<CSSStyleSheet*>(m_sheet.get())->contents()->parseString(sheet);
+    else if (m_isXSL)
+        static_cast<XSLStyleSheet*>(m_sheet.get())->parseString(sheet);
+
+    if (m_cachedSheet)
+        m_cachedSheet->removeClient(this);
+    m_cachedSheet = 0;
+
+    m_loading = false;
+
+    if (m_isCSS)
+        static_cast<CSSStyleSheet*>(m_sheet.get())->contents()->checkLoaded();
+    else if (m_isXSL)
+        static_cast<XSLStyleSheet*>(m_sheet.get())->checkLoaded();
+}
+
+void ProcessingInstruction::setCSSStyleSheet(PassRefPtr<CSSStyleSheet> sheet)
+{
+    ASSERT(!m_cachedSheet);
+    ASSERT(!m_loading);
+    m_sheet = sheet;
+    sheet->setTitle(m_title);
+    sheet->setDisabled(m_alternate);
+}
+
+bool ProcessingInstruction::offsetInCharacters() const
+{
+    return true;
+}
+
+int ProcessingInstruction::maxCharacterOffset() const 
+{
+    return static_cast<int>(m_data.length());
+}
+
+void ProcessingInstruction::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
+{
+    if (!sheet())
+        return;
+    
+    addSubresourceURL(urls, sheet()->baseURL());
+}
+
+Node::InsertionNotificationRequest ProcessingInstruction::insertedInto(ContainerNode* insertionPoint)
+{
+    Node::insertedInto(insertionPoint);
+    if (!insertionPoint->inDocument())
+        return InsertionDone;
+    document()->styleSheetCollection()->addStyleSheetCandidateNode(this, m_createdByParser);
+    checkStyleSheet();
+    return InsertionDone;
+}
+
+void ProcessingInstruction::removedFrom(ContainerNode* insertionPoint)
+{
+    Node::removedFrom(insertionPoint);
+    if (!insertionPoint->inDocument())
+        return;
+    
+    document()->styleSheetCollection()->removeStyleSheetCandidateNode(this);
+
+    if (m_sheet) {
+        ASSERT(m_sheet->ownerNode() == this);
+        m_sheet->clearOwnerNode();
+        m_sheet = 0;
+    }
+
+    // If we're in document teardown, then we don't need to do any notification of our sheet's removal.
+    if (document()->renderer())
+        document()->styleResolverChanged(DeferRecalcStyle);
+}
+
+void ProcessingInstruction::finishParsingChildren()
+{
+    m_createdByParser = false;
+    Node::finishParsingChildren();
+}
+
+} // namespace
diff --git a/Source/core/dom/ProcessingInstruction.h b/Source/core/dom/ProcessingInstruction.h
new file mode 100644
index 0000000..a63c1b7
--- /dev/null
+++ b/Source/core/dom/ProcessingInstruction.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2000 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ProcessingInstruction_h
+#define ProcessingInstruction_h
+
+#include "core/dom/Node.h"
+#include "core/loader/cache/CachedResourceHandle.h"
+#include "core/loader/cache/CachedStyleSheetClient.h"
+
+namespace WebCore {
+
+class StyleSheet;
+class CSSStyleSheet;
+
+class ProcessingInstruction FINAL : public Node, private CachedStyleSheetClient {
+public:
+    static PassRefPtr<ProcessingInstruction> create(Document*, const String& target, const String& data);
+    virtual ~ProcessingInstruction();
+
+    const String& target() const { return m_target; }
+    const String& data() const { return m_data; }
+    void setData(const String&, ExceptionCode&);
+
+    void setCreatedByParser(bool createdByParser) { m_createdByParser = createdByParser; }
+
+    virtual void finishParsingChildren();
+
+    const String& localHref() const { return m_localHref; }
+    StyleSheet* sheet() const { return m_sheet.get(); }
+    void setCSSStyleSheet(PassRefPtr<CSSStyleSheet>);
+
+    bool isCSS() const { return m_isCSS; }
+    bool isXSL() const { return m_isXSL; }
+
+private:
+    ProcessingInstruction(Document*, const String& target, const String& data);
+
+    virtual String nodeName() const;
+    virtual NodeType nodeType() const;
+    virtual String nodeValue() const;
+    virtual void setNodeValue(const String&, ExceptionCode&);
+    virtual PassRefPtr<Node> cloneNode(bool deep);
+    virtual bool offsetInCharacters() const;
+    virtual int maxCharacterOffset() const;
+
+    virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
+    virtual void removedFrom(ContainerNode*) OVERRIDE;
+
+    void checkStyleSheet();
+    virtual void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet*);
+    virtual void setXSLStyleSheet(const String& href, const KURL& baseURL, const String& sheet);
+
+    bool isLoading() const;
+    virtual bool sheetLoaded();
+
+    virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const;
+
+    void parseStyleSheet(const String& sheet);
+
+    String m_target;
+    String m_data;
+    String m_localHref;
+    String m_title;
+    String m_media;
+    CachedResourceHandle<CachedResource> m_cachedSheet;
+    RefPtr<StyleSheet> m_sheet;
+    bool m_loading;
+    bool m_alternate;
+    bool m_createdByParser;
+    bool m_isCSS;
+    bool m_isXSL;
+};
+
+} //namespace
+
+#endif
diff --git a/Source/core/dom/ProcessingInstruction.idl b/Source/core/dom/ProcessingInstruction.idl
new file mode 100644
index 0000000..03530e2
--- /dev/null
+++ b/Source/core/dom/ProcessingInstruction.idl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+interface ProcessingInstruction : Node {
+
+    // DOM Level 1
+
+    [TreatReturnedNullStringAs=Null] readonly attribute DOMString target;
+             [TreatReturnedNullStringAs=Null, TreatNullAs=NullString, SetterRaisesException] attribute DOMString data;
+
+    // interface LinkStyle from DOM Level 2 Style Sheets
+    readonly attribute StyleSheet sheet;
+};
+
diff --git a/Source/core/dom/ProgressEvent.cpp b/Source/core/dom/ProgressEvent.cpp
new file mode 100644
index 0000000..18d6980
--- /dev/null
+++ b/Source/core/dom/ProgressEvent.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "core/dom/ProgressEvent.h"
+
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+ProgressEventInit::ProgressEventInit()
+    : lengthComputable(false)
+    , loaded(0)
+    , total(0)
+{
+}
+
+ProgressEvent::ProgressEvent()
+    : m_lengthComputable(false)
+    , m_loaded(0)
+    , m_total(0)
+{
+    ScriptWrappable::init(this);
+}
+
+ProgressEvent::ProgressEvent(const AtomicString& type, const ProgressEventInit& initializer)
+    : Event(type, initializer)
+    , m_lengthComputable(initializer.lengthComputable)
+    , m_loaded(initializer.loaded)
+    , m_total(initializer.total)
+{
+    ScriptWrappable::init(this);
+}
+
+ProgressEvent::ProgressEvent(const AtomicString& type, bool lengthComputable, unsigned long long loaded, unsigned long long total)
+    : Event(type, false, true)
+    , m_lengthComputable(lengthComputable)
+    , m_loaded(loaded)
+    , m_total(total)
+{
+    ScriptWrappable::init(this);
+}
+    
+const AtomicString& ProgressEvent::interfaceName() const
+{
+    return eventNames().interfaceForProgressEvent;
+}
+
+}
diff --git a/Source/core/dom/ProgressEvent.h b/Source/core/dom/ProgressEvent.h
new file mode 100644
index 0000000..eb1ecd3
--- /dev/null
+++ b/Source/core/dom/ProgressEvent.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef ProgressEvent_h
+#define ProgressEvent_h
+
+#include "core/dom/Event.h"
+
+namespace WebCore {
+
+struct ProgressEventInit : public EventInit {
+    ProgressEventInit();
+
+    bool lengthComputable;
+    unsigned long long loaded;
+    unsigned long long total;
+};
+
+class ProgressEvent : public Event {
+public:
+    static PassRefPtr<ProgressEvent> create()
+    {
+        return adoptRef(new ProgressEvent);
+    }
+    static PassRefPtr<ProgressEvent> create(const AtomicString& type, bool lengthComputable, unsigned long long loaded, unsigned long long total)
+    {
+        return adoptRef(new ProgressEvent(type, lengthComputable, loaded, total));
+    }
+    static PassRefPtr<ProgressEvent> create(const AtomicString& type, const ProgressEventInit& initializer)
+    {
+        return adoptRef(new ProgressEvent(type, initializer));
+    }
+
+    bool lengthComputable() const { return m_lengthComputable; }
+    unsigned long long loaded() const { return m_loaded; }
+    unsigned long long total() const { return m_total; }
+
+    virtual const AtomicString& interfaceName() const;
+
+protected:
+    ProgressEvent();
+    ProgressEvent(const AtomicString& type, bool lengthComputable, unsigned long long loaded, unsigned long long total);
+    ProgressEvent(const AtomicString&, const ProgressEventInit&);
+
+private:
+    bool m_lengthComputable;
+    unsigned long long m_loaded;
+    unsigned long long m_total;
+};
+}
+
+#endif // ProgressEvent_h
diff --git a/Source/core/dom/ProgressEvent.idl b/Source/core/dom/ProgressEvent.idl
new file mode 100644
index 0000000..fd82129
--- /dev/null
+++ b/Source/core/dom/ProgressEvent.idl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+[
+    ConstructorTemplate=Event
+] interface ProgressEvent : Event {
+    [InitializedByEventConstructor] readonly attribute boolean lengthComputable;
+    [InitializedByEventConstructor] readonly attribute unsigned long long loaded;
+    [InitializedByEventConstructor] readonly attribute unsigned long long total;
+};
+
diff --git a/Source/core/dom/PseudoElement.cpp b/Source/core/dom/PseudoElement.cpp
new file mode 100644
index 0000000..269d884
--- /dev/null
+++ b/Source/core/dom/PseudoElement.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2012 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 "core/dom/PseudoElement.h"
+
+#include "core/dom/NodeRenderingContext.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/RenderQuote.h"
+#include "core/rendering/style/ContentData.h"
+
+namespace WebCore {
+
+const QualifiedName& pseudoElementTagName()
+{
+    DEFINE_STATIC_LOCAL(QualifiedName, name, (nullAtom, "<pseudo>", nullAtom));
+    return name;
+}
+
+String PseudoElement::pseudoElementNameForEvents(PseudoId pseudoId)
+{
+    DEFINE_STATIC_LOCAL(const String, after, (ASCIILiteral("::after")));
+    DEFINE_STATIC_LOCAL(const String, before, (ASCIILiteral("::before")));
+    switch (pseudoId) {
+    case AFTER:
+        return after;
+    case BEFORE:
+        return before;
+    default:
+        return emptyString();
+    }
+}
+
+PseudoElement::PseudoElement(Element* parent, PseudoId pseudoId)
+    : Element(pseudoElementTagName(), parent->document(), CreatePseudoElement)
+    , m_pseudoId(pseudoId)
+{
+    ASSERT(pseudoId != NOPSEUDO);
+    setParentOrShadowHostNode(parent);
+    setHasCustomStyleCallbacks();
+}
+
+PseudoElement::~PseudoElement()
+{
+    InspectorInstrumentation::pseudoElementDestroyed(document()->page(), this);
+}
+
+PassRefPtr<RenderStyle> PseudoElement::customStyleForRenderer()
+{
+    return parentOrShadowHostElement()->renderer()->getCachedPseudoStyle(m_pseudoId);
+}
+
+void PseudoElement::attach()
+{
+    ASSERT(!renderer());
+
+    Element::attach();
+
+    RenderObject* renderer = this->renderer();
+    if (!renderer || !renderer->style()->regionThread().isEmpty())
+        return;
+
+    RenderStyle* style = renderer->style();
+    ASSERT(style->contentData());
+
+    for (const ContentData* content = style->contentData(); content; content = content->next()) {
+        RenderObject* child = content->createRenderer(document(), style);
+        if (renderer->isChildAllowed(child, style)) {
+            renderer->addChild(child);
+            if (child->isQuote())
+                toRenderQuote(child)->attachQuote();
+        } else
+            child->destroy();
+    }
+}
+
+bool PseudoElement::rendererIsNeeded(const NodeRenderingContext& context)
+{
+    return pseudoElementRendererIsNeeded(context.style());
+}
+
+void PseudoElement::didRecalcStyle(StyleChange)
+{
+    if (!renderer())
+        return;
+
+    // The renderers inside pseudo elements are anonymous so they don't get notified of recalcStyle and must have
+    // the style propagated downward manually similar to RenderObject::propagateStyleToAnonymousChildren.
+    RenderObject* renderer = this->renderer();
+    for (RenderObject* child = renderer->nextInPreOrder(renderer); child; child = child->nextInPreOrder(renderer)) {
+        // We only manage the style for the generated content which must be images or text.
+        if (!child->isText() && !child->isImage())
+            continue;
+
+        // The style for the RenderTextFragment for first letter is managed by an enclosing block, not by us.
+        if (child->style()->styleType() == FIRST_LETTER)
+            continue;
+
+        child->setPseudoStyle(renderer->style());
+    }
+}
+
+} // namespace
diff --git a/Source/core/dom/PseudoElement.h b/Source/core/dom/PseudoElement.h
new file mode 100644
index 0000000..87c8064
--- /dev/null
+++ b/Source/core/dom/PseudoElement.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2012 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 PseudoElement_h
+#define PseudoElement_h
+
+#include "core/dom/Element.h"
+#include "core/dom/Event.h"
+#include "core/rendering/style/RenderStyle.h"
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class PseudoElement FINAL : public Element {
+public:
+    static PassRefPtr<PseudoElement> create(Element* parent, PseudoId pseudoId)
+    {
+        return adoptRef(new PseudoElement(parent, pseudoId));
+    }
+    ~PseudoElement();
+
+    virtual PassRefPtr<RenderStyle> customStyleForRenderer() OVERRIDE;
+    virtual void attach() OVERRIDE;
+    virtual bool rendererIsNeeded(const NodeRenderingContext&) OVERRIDE;
+
+    virtual bool canStartSelection() const OVERRIDE { return false; }
+    virtual bool canContainRangeEndPoint() const OVERRIDE { return false; }
+
+    static String pseudoElementNameForEvents(PseudoId);
+
+private:
+    PseudoElement(Element*, PseudoId);
+
+    virtual void didRecalcStyle(StyleChange) OVERRIDE;
+    virtual PseudoId customPseudoId() const OVERRIDE { return m_pseudoId; }
+
+    PseudoId m_pseudoId;
+};
+
+const QualifiedName& pseudoElementTagName();
+
+inline bool pseudoElementRendererIsNeeded(const RenderStyle* style)
+{
+    return style && style->display() != NONE && (style->contentData() || !style->regionThread().isEmpty());
+}
+
+} // namespace
+
+#endif
diff --git a/Source/core/dom/QualifiedName.cpp b/Source/core/dom/QualifiedName.cpp
new file mode 100644
index 0000000..d0228de
--- /dev/null
+++ b/Source/core/dom/QualifiedName.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2005, 2006, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC
+#define WEBCORE_QUALIFIEDNAME_HIDE_GLOBALS 1
+#else
+#define QNAME_DEFAULT_CONSTRUCTOR
+#endif
+
+#include "HTMLNames.h"
+#include "XLinkNames.h"
+#include "XMLNSNames.h"
+#include "XMLNames.h"
+#include "core/dom/QualifiedName.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include <wtf/Assertions.h>
+#include <wtf/HashSet.h>
+#include <wtf/StaticConstructors.h>
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#endif
+
+namespace WebCore {
+
+static const int staticQualifiedNamesCount = HTMLNames::HTMLTagsCount + HTMLNames::HTMLAttrsCount
+#if ENABLE(SVG)
+    + SVGNames::SVGTagsCount + SVGNames::SVGAttrsCount
+#endif
+    + XLinkNames::XLinkAttrsCount
+    + XMLNSNames::XMLNSAttrsCount
+    + XMLNames::XMLAttrsCount;
+
+struct QualifiedNameHashTraits : public HashTraits<QualifiedName::QualifiedNameImpl*> {
+    static const int minimumTableSize = WTF::HashTableCapacityForSize<staticQualifiedNamesCount>::value;
+};
+
+typedef HashSet<QualifiedName::QualifiedNameImpl*, QualifiedNameHash, QualifiedNameHashTraits> QNameSet;
+
+struct QNameComponentsTranslator {
+    static unsigned hash(const QualifiedNameComponents& components)
+    {
+        return hashComponents(components); 
+    }
+    static bool equal(QualifiedName::QualifiedNameImpl* name, const QualifiedNameComponents& c)
+    {
+        return c.m_prefix == name->m_prefix.impl() && c.m_localName == name->m_localName.impl() && c.m_namespace == name->m_namespace.impl();
+    }
+    static void translate(QualifiedName::QualifiedNameImpl*& location, const QualifiedNameComponents& components, unsigned)
+    {
+        location = QualifiedName::QualifiedNameImpl::create(components.m_prefix, components.m_localName, components.m_namespace).leakRef();
+    }
+};
+
+static QNameSet* gNameCache;
+
+QualifiedName::QualifiedName(const AtomicString& p, const AtomicString& l, const AtomicString& n)
+{
+    if (!gNameCache)
+        gNameCache = new QNameSet;
+    QualifiedNameComponents components = { p.impl(), l.impl(), n.isEmpty() ? nullAtom.impl() : n.impl() };
+    QNameSet::AddResult addResult = gNameCache->add<QualifiedNameComponents, QNameComponentsTranslator>(components);
+    m_impl = *addResult.iterator;
+    if (!addResult.isNewEntry)
+        m_impl->ref();
+}
+
+QualifiedName::~QualifiedName()
+{
+    deref();
+}
+
+void QualifiedName::deref()
+{
+#ifdef QNAME_DEFAULT_CONSTRUCTOR
+    if (!m_impl)
+        return;
+#endif
+    ASSERT(!isHashTableDeletedValue());
+    m_impl->deref();
+}
+
+QualifiedName::QualifiedNameImpl::~QualifiedNameImpl()
+{
+    gNameCache->remove(this);
+}
+
+String QualifiedName::toString() const
+{
+    String local = localName();
+    if (hasPrefix()) {
+        String result = prefix().string();
+        result.append(":");
+        result.append(local);
+        return result;
+    }
+    return local;
+}
+
+// Global init routines
+DEFINE_GLOBAL(QualifiedName, anyName, nullAtom, starAtom, starAtom)
+
+void QualifiedName::init()
+{
+    static bool initialized;
+    if (initialized)
+        return;
+    initialized = true;
+
+    ASSERT(starAtom.impl());
+    new ((void*)&anyName) QualifiedName(nullAtom, starAtom, starAtom);
+}
+
+const QualifiedName& nullQName()
+{
+    DEFINE_STATIC_LOCAL(QualifiedName, nullName, (nullAtom, nullAtom, nullAtom));
+    return nullName;
+}
+
+const AtomicString& QualifiedName::localNameUpper() const
+{
+    if (!m_impl->m_localNameUpper)
+        m_impl->m_localNameUpper = m_impl->m_localName.upper();
+    return m_impl->m_localNameUpper;
+}
+
+void QualifiedName::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    info.addMember(m_impl, "impl");
+}
+
+
+void QualifiedName::QualifiedNameImpl::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    info.addMember(m_prefix, "prefix");
+    info.addMember(m_localName, "localName");
+    info.addMember(m_namespace, "namespace");
+    info.addMember(m_localNameUpper, "localNameUpper");
+}
+
+unsigned QualifiedName::QualifiedNameImpl::computeHash() const
+{
+    QualifiedNameComponents components = { m_prefix.impl(), m_localName.impl(), m_namespace.impl() };
+    return hashComponents(components);
+}
+
+void createQualifiedName(void* targetAddress, StringImpl* name, const AtomicString& nameNamespace)
+{
+    new (reinterpret_cast<void*>(targetAddress)) QualifiedName(nullAtom, AtomicString(name), nameNamespace);
+}
+
+void createQualifiedName(void* targetAddress, StringImpl* name)
+{
+    new (reinterpret_cast<void*>(targetAddress)) QualifiedName(nullAtom, AtomicString(name), nullAtom);
+}
+
+}
diff --git a/Source/core/dom/QualifiedName.h b/Source/core/dom/QualifiedName.h
new file mode 100644
index 0000000..3867315
--- /dev/null
+++ b/Source/core/dom/QualifiedName.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2005, 2006, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef QualifiedName_h
+#define QualifiedName_h
+
+#include <wtf/Forward.h>
+#include <wtf/HashTraits.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+struct QualifiedNameComponents {
+    StringImpl* m_prefix;
+    StringImpl* m_localName;
+    StringImpl* m_namespace;
+};
+
+class QualifiedName {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    class QualifiedNameImpl : public RefCounted<QualifiedNameImpl> {
+    public:
+        static PassRefPtr<QualifiedNameImpl> create(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI)
+        {
+            return adoptRef(new QualifiedNameImpl(prefix, localName, namespaceURI));
+        }
+
+        ~QualifiedNameImpl();
+
+        unsigned computeHash() const;
+
+        mutable unsigned m_existingHash;
+        const AtomicString m_prefix;
+        const AtomicString m_localName;
+        const AtomicString m_namespace;
+        mutable AtomicString m_localNameUpper;
+
+        void reportMemoryUsage(MemoryObjectInfo*) const;
+
+    private:
+        QualifiedNameImpl(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI)
+            : m_existingHash(0)
+            , m_prefix(prefix)
+            , m_localName(localName)
+            , m_namespace(namespaceURI)
+        {
+            ASSERT(!namespaceURI.isEmpty() || namespaceURI.isNull());
+        }        
+    };
+
+    QualifiedName(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI);
+    QualifiedName(WTF::HashTableDeletedValueType) : m_impl(hashTableDeletedValue()) { }
+    bool isHashTableDeletedValue() const { return m_impl == hashTableDeletedValue(); }
+    ~QualifiedName();
+#ifdef QNAME_DEFAULT_CONSTRUCTOR
+    QualifiedName() : m_impl(0) { }
+#endif
+
+    QualifiedName(const QualifiedName& other) : m_impl(other.m_impl) { ref(); }
+    const QualifiedName& operator=(const QualifiedName& other) { other.ref(); deref(); m_impl = other.m_impl; return *this; }
+
+    bool operator==(const QualifiedName& other) const { return m_impl == other.m_impl; }
+    bool operator!=(const QualifiedName& other) const { return !(*this == other); }
+
+    bool matches(const QualifiedName& other) const { return m_impl == other.m_impl || (localName() == other.localName() && namespaceURI() == other.namespaceURI()); }
+
+    bool hasPrefix() const { return m_impl->m_prefix != nullAtom; }
+    void setPrefix(const AtomicString& prefix) { *this = QualifiedName(prefix, localName(), namespaceURI()); }
+
+    const AtomicString& prefix() const { return m_impl->m_prefix; }
+    const AtomicString& localName() const { return m_impl->m_localName; }
+    const AtomicString& namespaceURI() const { return m_impl->m_namespace; }
+
+    // Uppercased localName, cached for efficiency
+    const AtomicString& localNameUpper() const;
+
+    String toString() const;
+
+    QualifiedNameImpl* impl() const { return m_impl; }
+    
+    // Init routine for globals
+    static void init();
+    
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+private:
+    void ref() const { m_impl->ref(); }
+    void deref();
+
+    static QualifiedNameImpl* hashTableDeletedValue() { return RefPtr<QualifiedNameImpl>::hashTableDeletedValue(); }
+    
+    QualifiedNameImpl* m_impl;
+};
+
+#ifndef WEBCORE_QUALIFIEDNAME_HIDE_GLOBALS
+extern const QualifiedName anyName;
+inline const QualifiedName& anyQName() { return anyName; }
+#endif
+
+const QualifiedName& nullQName();
+
+inline bool operator==(const AtomicString& a, const QualifiedName& q) { return a == q.localName(); }
+inline bool operator!=(const AtomicString& a, const QualifiedName& q) { return a != q.localName(); }
+inline bool operator==(const QualifiedName& q, const AtomicString& a) { return a == q.localName(); }
+inline bool operator!=(const QualifiedName& q, const AtomicString& a) { return a != q.localName(); }
+
+inline unsigned hashComponents(const QualifiedNameComponents& buf)
+{
+    return StringHasher::hashMemory<sizeof(QualifiedNameComponents)>(&buf);
+}
+
+struct QualifiedNameHash {
+    static unsigned hash(const QualifiedName& name) { return hash(name.impl()); }
+
+    static unsigned hash(const QualifiedName::QualifiedNameImpl* name) 
+    {
+        if (!name->m_existingHash)
+            name->m_existingHash = name->computeHash();
+        return name->m_existingHash;
+    }
+
+    static bool equal(const QualifiedName& a, const QualifiedName& b) { return a == b; }
+    static bool equal(const QualifiedName::QualifiedNameImpl* a, const QualifiedName::QualifiedNameImpl* b) { return a == b; }
+
+    static const bool safeToCompareToEmptyOrDeleted = false;
+};
+
+void createQualifiedName(void* targetAddress, StringImpl* name);
+void createQualifiedName(void* targetAddress, StringImpl* name, const AtomicString& nameNamespace);
+
+}
+
+namespace WTF {
+    
+    template<typename T> struct DefaultHash;
+
+    template<> struct DefaultHash<WebCore::QualifiedName> {
+        typedef WebCore::QualifiedNameHash Hash;
+    };
+    
+    template<> struct HashTraits<WebCore::QualifiedName> : SimpleClassHashTraits<WebCore::QualifiedName> {
+        static const bool emptyValueIsZero = false;
+        static WebCore::QualifiedName emptyValue() { return WebCore::nullQName(); }
+    };
+}
+
+#endif
diff --git a/Source/core/dom/Range.cpp b/Source/core/dom/Range.cpp
new file mode 100644
index 0000000..87ccff1
--- /dev/null
+++ b/Source/core/dom/Range.cpp
@@ -0,0 +1,1975 @@
+/*
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Gunnstein Lye (gunnstein@netcom.no)
+ * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Motorola Mobility. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/Range.h"
+
+#include <stdio.h>
+#include "HTMLNames.h"
+#include "core/dom/ClientRect.h"
+#include "core/dom/ClientRectList.h"
+#include "core/dom/DocumentFragment.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/Node.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/dom/NodeWithIndex.h"
+#include "core/dom/ProcessingInstruction.h"
+#include "core/dom/Text.h"
+#include "core/editing/TextIterator.h"
+#include "core/editing/VisiblePosition.h"
+#include "core/editing/VisibleUnits.h"
+#include "core/editing/htmlediting.h"
+#include "core/editing/markup.h"
+#include "core/html/HTMLElement.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/rendering/RenderBoxModelObject.h"
+#include "core/rendering/RenderText.h"
+#include <wtf/RefCountedLeakCounter.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+using namespace std;
+using namespace HTMLNames;
+
+DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, rangeCounter, ("Range"));
+
+inline Range::Range(PassRefPtr<Document> ownerDocument)
+    : m_ownerDocument(ownerDocument)
+    , m_start(m_ownerDocument)
+    , m_end(m_ownerDocument)
+{
+#ifndef NDEBUG
+    rangeCounter.increment();
+#endif
+
+    m_ownerDocument->attachRange(this);
+}
+
+PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument)
+{
+    return adoptRef(new Range(ownerDocument));
+}
+
+inline Range::Range(PassRefPtr<Document> ownerDocument, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset)
+    : m_ownerDocument(ownerDocument)
+    , m_start(m_ownerDocument)
+    , m_end(m_ownerDocument)
+{
+#ifndef NDEBUG
+    rangeCounter.increment();
+#endif
+
+    m_ownerDocument->attachRange(this);
+
+    // Simply setting the containers and offsets directly would not do any of the checking
+    // that setStart and setEnd do, so we call those functions.
+    setStart(startContainer, startOffset);
+    setEnd(endContainer, endOffset);
+}
+
+PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset)
+{
+    return adoptRef(new Range(ownerDocument, startContainer, startOffset, endContainer, endOffset));
+}
+
+PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument, const Position& start, const Position& end)
+{
+    return adoptRef(new Range(ownerDocument, start.containerNode(), start.computeOffsetInContainerNode(), end.containerNode(), end.computeOffsetInContainerNode()));
+}
+
+Range::~Range()
+{
+    // Always detach (even if we've already detached) to fix https://bugs.webkit.org/show_bug.cgi?id=26044
+    m_ownerDocument->detachRange(this);
+
+#ifndef NDEBUG
+    rangeCounter.decrement();
+#endif
+}
+
+void Range::setDocument(Document* document)
+{
+    ASSERT(m_ownerDocument != document);
+    if (m_ownerDocument)
+        m_ownerDocument->detachRange(this);
+    m_ownerDocument = document;
+    m_start.setToStartOfNode(document);
+    m_end.setToStartOfNode(document);
+    m_ownerDocument->attachRange(this);
+}
+
+Node* Range::startContainer(ExceptionCode& ec) const
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    return m_start.container();
+}
+
+int Range::startOffset(ExceptionCode& ec) const
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    return m_start.offset();
+}
+
+Node* Range::endContainer(ExceptionCode& ec) const
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    return m_end.container();
+}
+
+int Range::endOffset(ExceptionCode& ec) const
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    return m_end.offset();
+}
+
+Node* Range::commonAncestorContainer(ExceptionCode& ec) const
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    return commonAncestorContainer(m_start.container(), m_end.container());
+}
+
+Node* Range::commonAncestorContainer(Node* containerA, Node* containerB)
+{
+    for (Node* parentA = containerA; parentA; parentA = parentA->parentNode()) {
+        for (Node* parentB = containerB; parentB; parentB = parentB->parentNode()) {
+            if (parentA == parentB)
+                return parentA;
+        }
+    }
+    return 0;
+}
+
+bool Range::collapsed(ExceptionCode& ec) const
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    return m_start == m_end;
+}
+
+static inline bool checkForDifferentRootContainer(const RangeBoundaryPoint& start, const RangeBoundaryPoint& end)
+{
+    Node* endRootContainer = end.container();
+    while (endRootContainer->parentNode())
+        endRootContainer = endRootContainer->parentNode();
+    Node* startRootContainer = start.container();
+    while (startRootContainer->parentNode())
+        startRootContainer = startRootContainer->parentNode();
+
+    return startRootContainer != endRootContainer || (Range::compareBoundaryPoints(start, end, ASSERT_NO_EXCEPTION) > 0);
+}
+
+void Range::setStart(PassRefPtr<Node> refNode, int offset, ExceptionCode& ec)
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    if (!refNode) {
+        ec = NOT_FOUND_ERR;
+        return;
+    }
+
+    bool didMoveDocument = false;
+    if (refNode->document() != m_ownerDocument) {
+        setDocument(refNode->document());
+        didMoveDocument = true;
+    }
+
+    ec = 0;
+    Node* childNode = checkNodeWOffset(refNode.get(), offset, ec);
+    if (ec)
+        return;
+
+    m_start.set(refNode, offset, childNode);
+
+    if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end))
+        collapse(true, ec);
+}
+
+void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionCode& ec)
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    if (!refNode) {
+        ec = NOT_FOUND_ERR;
+        return;
+    }
+
+    bool didMoveDocument = false;
+    if (refNode->document() != m_ownerDocument) {
+        setDocument(refNode->document());
+        didMoveDocument = true;
+    }
+
+    ec = 0;
+    Node* childNode = checkNodeWOffset(refNode.get(), offset, ec);
+    if (ec)
+        return;
+
+    m_end.set(refNode, offset, childNode);
+
+    if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end))
+        collapse(false, ec);
+}
+
+void Range::setStart(const Position& start, ExceptionCode& ec)
+{
+    Position parentAnchored = start.parentAnchoredEquivalent();
+    setStart(parentAnchored.containerNode(), parentAnchored.offsetInContainerNode(), ec);
+}
+
+void Range::setEnd(const Position& end, ExceptionCode& ec)
+{
+    Position parentAnchored = end.parentAnchoredEquivalent();
+    setEnd(parentAnchored.containerNode(), parentAnchored.offsetInContainerNode(), ec);
+}
+
+void Range::collapse(bool toStart, ExceptionCode& ec)
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    if (toStart)
+        m_end = m_start;
+    else
+        m_start = m_end;
+}
+
+bool Range::isPointInRange(Node* refNode, int offset, ExceptionCode& ec)
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return false;
+    }
+
+    if (!refNode) {
+        ec = HIERARCHY_REQUEST_ERR;
+        return false;
+    }
+
+    if (!refNode->attached() || refNode->document() != m_ownerDocument) {
+        return false;
+    }
+
+    ec = 0;
+    checkNodeWOffset(refNode, offset, ec);
+    if (ec)
+        return false;
+
+    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
+{
+    // http://developer.mozilla.org/en/docs/DOM:range.comparePoint
+    // This method returns -1, 0 or 1 depending on if the point described by the 
+    // refNode node and an offset within the node is before, same as, or after the range respectively.
+
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    if (!refNode) {
+        ec = HIERARCHY_REQUEST_ERR;
+        return 0;
+    }
+
+    if (!refNode->attached() || refNode->document() != m_ownerDocument) {
+        ec = WRONG_DOCUMENT_ERR;
+        return 0;
+    }
+
+    ec = 0;
+    checkNodeWOffset(refNode, offset, ec);
+    if (ec)
+        return 0;
+
+    // compare to start, and point comes before
+    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(), ec) > 0 && !ec)
+        return 1;
+
+    // point is in the middle of this range, or on the boundary points
+    return 0;
+}
+
+Range::CompareResults Range::compareNode(Node* refNode, ExceptionCode& ec) const
+{
+    // http://developer.mozilla.org/en/docs/DOM:range.compareNode
+    // This method returns 0, 1, 2, or 3 based on if the node is before, after,
+    // before and after(surrounds), or inside the range, respectively
+
+    if (!refNode) {
+        ec = NOT_FOUND_ERR;
+        return NODE_BEFORE;
+    }
+    
+    if (!m_start.container() && refNode->attached()) {
+        ec = INVALID_STATE_ERR;
+        return NODE_BEFORE;
+    }
+
+    if (m_start.container() && !refNode->attached()) {
+        // Firefox doesn't throw an exception for this case; it returns 0.
+        return NODE_BEFORE;
+    }
+
+    if (refNode->document() != m_ownerDocument) {
+        // Firefox doesn't throw an exception for this case; it returns 0.
+        return NODE_BEFORE;
+    }
+
+    ContainerNode* parentNode = refNode->parentNode();
+    int nodeIndex = refNode->nodeIndex();
+    
+    if (!parentNode) {
+        // if the node is the top document we should return NODE_BEFORE_AND_AFTER
+        // but we throw to match firefox behavior
+        ec = NOT_FOUND_ERR;
+        return NODE_BEFORE;
+    }
+
+    if (comparePoint(parentNode, nodeIndex, ec) < 0) { // starts before
+        if (comparePoint(parentNode, nodeIndex + 1, ec) > 0) // ends after the range
+            return NODE_BEFORE_AND_AFTER;
+        return NODE_BEFORE; // ends before or in the range
+    } else { // starts at or after the range start
+        if (comparePoint(parentNode, nodeIndex + 1, ec) > 0) // ends after the range
+            return NODE_AFTER;
+        return NODE_INSIDE; // ends inside the range
+    }
+}
+
+short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, ExceptionCode& ec) const
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    if (!sourceRange) {
+        ec = NOT_FOUND_ERR;
+        return 0;
+    }
+
+    ec = 0;
+    Node* thisCont = commonAncestorContainer(ec);
+    if (ec)
+        return 0;
+    Node* sourceCont = sourceRange->commonAncestorContainer(ec);
+    if (ec)
+        return 0;
+
+    if (thisCont->document() != sourceCont->document()) {
+        ec = WRONG_DOCUMENT_ERR;
+        return 0;
+    }
+
+    Node* thisTop = thisCont;
+    Node* sourceTop = sourceCont;
+    while (thisTop->parentNode())
+        thisTop = thisTop->parentNode();
+    while (sourceTop->parentNode())
+        sourceTop = sourceTop->parentNode();
+    if (thisTop != sourceTop) { // in different DocumentFragments
+        ec = WRONG_DOCUMENT_ERR;
+        return 0;
+    }
+
+    switch (how) {
+        case START_TO_START:
+            return compareBoundaryPoints(m_start, sourceRange->m_start, ec);
+        case START_TO_END:
+            return compareBoundaryPoints(m_end, sourceRange->m_start, ec);
+        case END_TO_END:
+            return compareBoundaryPoints(m_end, sourceRange->m_end, ec);
+        case END_TO_START:
+            return compareBoundaryPoints(m_start, sourceRange->m_end, ec);
+    }
+
+    ec = SYNTAX_ERR;
+    return 0;
+}
+
+short Range::compareBoundaryPoints(Node* containerA, int offsetA, Node* containerB, int offsetB, ExceptionCode& ec)
+{
+    ASSERT(containerA);
+    ASSERT(containerB);
+
+    if (!containerA)
+        return -1;
+    if (!containerB)
+        return 1;
+
+    // see DOM2 traversal & range section 2.5
+
+    // case 1: both points have the same container
+    if (containerA == containerB) {
+        if (offsetA == offsetB)
+            return 0;           // A is equal to B
+        if (offsetA < offsetB)
+            return -1;          // A is before B
+        else
+            return 1;           // A is after B
+    }
+
+    // case 2: node C (container B or an ancestor) is a child node of A
+    Node* c = containerB;
+    while (c && c->parentNode() != containerA)
+        c = c->parentNode();
+    if (c) {
+        int offsetC = 0;
+        Node* n = containerA->firstChild();
+        while (n != c && offsetC < offsetA) {
+            offsetC++;
+            n = n->nextSibling();
+        }
+
+        if (offsetA <= offsetC)
+            return -1;              // A is before B
+        else
+            return 1;               // A is after B
+    }
+
+    // case 3: node C (container A or an ancestor) is a child node of B
+    c = containerA;
+    while (c && c->parentNode() != containerB)
+        c = c->parentNode();
+    if (c) {
+        int offsetC = 0;
+        Node* n = containerB->firstChild();
+        while (n != c && offsetC < offsetB) {
+            offsetC++;
+            n = n->nextSibling();
+        }
+
+        if (offsetC < offsetB)
+            return -1;              // A is before B
+        else
+            return 1;               // A is after B
+    }
+
+    // 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) {
+        ec = WRONG_DOCUMENT_ERR;
+        return 0;
+    }
+    Node* childA = containerA;
+    while (childA && childA->parentNode() != commonAncestor)
+        childA = childA->parentNode();
+    if (!childA)
+        childA = commonAncestor;
+    Node* childB = containerB;
+    while (childB && childB->parentNode() != commonAncestor)
+        childB = childB->parentNode();
+    if (!childB)
+        childB = commonAncestor;
+
+    if (childA == childB)
+        return 0; // A is equal to B
+
+    Node* n = commonAncestor->firstChild();
+    while (n) {
+        if (n == childA)
+            return -1; // A is before B
+        if (n == childB)
+            return 1; // A is after B
+        n = n->nextSibling();
+    }
+
+    // Should never reach this point.
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const RangeBoundaryPoint& boundaryB, ExceptionCode& ec)
+{
+    return compareBoundaryPoints(boundaryA.container(), boundaryA.offset(), boundaryB.container(), boundaryB.offset(), ec);
+}
+
+bool Range::boundaryPointsValid() const
+{
+    ExceptionCode ec = 0;
+    return m_start.container() && compareBoundaryPoints(m_start, m_end, ec) <= 0 && !ec;
+}
+
+void Range::deleteContents(ExceptionCode& ec)
+{
+    checkDeleteExtract(ec);
+    if (ec)
+        return;
+
+    processContents(DELETE_CONTENTS, ec);
+}
+
+bool Range::intersectsNode(Node* refNode, ExceptionCode& ec)
+{
+    // http://developer.mozilla.org/en/docs/DOM:range.intersectsNode
+    // Returns a bool if the node intersects the range.
+
+    // Throw exception if the range is already detached.
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return false;
+    }
+    if (!refNode) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    if (!refNode->attached() || refNode->document() != m_ownerDocument) {
+        // Firefox doesn't throw an exception for these cases; it returns false.
+        return false;
+    }
+
+    ContainerNode* parentNode = refNode->parentNode();
+    int nodeIndex = refNode->nodeIndex();
+    
+    if (!parentNode) {
+        // if the node is the top document we should return NODE_BEFORE_AND_AFTER
+        // but we throw to match firefox behavior
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    if (comparePoint(parentNode, nodeIndex, ec) < 0 && // starts before start
+        comparePoint(parentNode, nodeIndex + 1, ec) < 0) { // ends before start
+        return false;
+    } else if (comparePoint(parentNode, nodeIndex, ec) > 0 && // starts after end
+               comparePoint(parentNode, nodeIndex + 1, ec) > 0) { // ends after end
+        return false;
+    }
+    
+    return true; // all other cases
+}
+
+static inline Node* highestAncestorUnderCommonRoot(Node* node, Node* commonRoot)
+{
+    if (node == commonRoot)
+        return 0;
+
+    ASSERT(commonRoot->contains(node));
+
+    while (node->parentNode() != commonRoot)
+        node = node->parentNode();
+
+    return node;
+}
+
+static inline Node* childOfCommonRootBeforeOffset(Node* container, unsigned offset, Node* commonRoot)
+{
+    ASSERT(container);
+    ASSERT(commonRoot);
+    
+    if (!commonRoot->contains(container))
+        return 0;
+
+    if (container == commonRoot) {
+        container = container->firstChild();
+        for (unsigned i = 0; container && i < offset; i++)
+            container = container->nextSibling();
+    } else {
+        while (container->parentNode() != commonRoot)
+            container = container->parentNode();
+    }
+
+    return container;
+}
+
+static inline unsigned lengthOfContentsInNode(Node* node)
+{
+    // This switch statement must be consistent with that of Range::processContentsBetweenOffsets.
+    switch (node->nodeType()) {
+    case Node::TEXT_NODE:
+    case Node::CDATA_SECTION_NODE:
+    case Node::COMMENT_NODE:
+        return static_cast<CharacterData*>(node)->length();
+    case Node::PROCESSING_INSTRUCTION_NODE:
+        return static_cast<ProcessingInstruction*>(node)->data().length();
+    case Node::ELEMENT_NODE:
+    case Node::ATTRIBUTE_NODE:
+    case Node::ENTITY_REFERENCE_NODE:
+    case Node::ENTITY_NODE:
+    case Node::DOCUMENT_NODE:
+    case Node::DOCUMENT_TYPE_NODE:
+    case Node::DOCUMENT_FRAGMENT_NODE:
+    case Node::NOTATION_NODE:
+    case Node::XPATH_NAMESPACE_NODE:
+        return node->childNodeCount();
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+PassRefPtr<DocumentFragment> Range::processContents(ActionType action, ExceptionCode& ec)
+{
+    typedef Vector<RefPtr<Node> > NodeVector;
+
+    RefPtr<DocumentFragment> fragment;
+    if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
+        fragment = DocumentFragment::create(m_ownerDocument.get());
+
+    ec = 0;
+    if (collapsed(ec))
+        return fragment.release();
+    if (ec)
+        return 0;
+
+    RefPtr<Node> commonRoot = commonAncestorContainer(ec);
+    if (ec)
+        return 0;
+    ASSERT(commonRoot);
+
+    if (m_start.container() == m_end.container()) {
+        processContentsBetweenOffsets(action, fragment, m_start.container(), m_start.offset(), m_end.offset(), ec);
+        return fragment;
+    }
+
+    // what is the highest node that partially selects the start / end of the range?
+    RefPtr<Node> partialStart = highestAncestorUnderCommonRoot(m_start.container(), commonRoot.get());
+    RefPtr<Node> partialEnd = highestAncestorUnderCommonRoot(m_end.container(), commonRoot.get());
+
+    // Start and end containers are different.
+    // There are three possibilities here:
+    // 1. Start container == commonRoot (End container must be a descendant)
+    // 2. End container == commonRoot (Start container must be a descendant)
+    // 3. Neither is commonRoot, they are both descendants
+    //
+    // In case 3, we grab everything after the start (up until a direct child
+    // of commonRoot) into leftContents, and everything before the end (up until
+    // a direct child of commonRoot) into rightContents. Then we process all
+    // commonRoot children between leftContents and rightContents
+    //
+    // In case 1 or 2, we skip either processing of leftContents or rightContents,
+    // in which case the last lot of nodes either goes from the first or last
+    // child of commonRoot.
+    //
+    // These are deleted, cloned, or extracted (i.e. both) depending on action.
+
+    // Note that we are verifying that our common root hierarchy is still intact
+    // after any DOM mutation event, at various stages below. See webkit bug 60350.
+
+    RefPtr<Node> leftContents;
+    if (m_start.container() != commonRoot && commonRoot->contains(m_start.container())) {
+        leftContents = processContentsBetweenOffsets(action, 0, m_start.container(), m_start.offset(), lengthOfContentsInNode(m_start.container()), ec);
+        leftContents = processAncestorsAndTheirSiblings(action, m_start.container(), ProcessContentsForward, leftContents, commonRoot.get(), ec);
+    }
+
+    RefPtr<Node> rightContents;
+    if (m_end.container() != commonRoot && commonRoot->contains(m_end.container())) {
+        rightContents = processContentsBetweenOffsets(action, 0, m_end.container(), 0, m_end.offset(), ec);
+        rightContents = processAncestorsAndTheirSiblings(action, m_end.container(), ProcessContentsBackward, rightContents, commonRoot.get(), ec);
+    }
+
+    // delete all children of commonRoot between the start and end container
+    RefPtr<Node> processStart = childOfCommonRootBeforeOffset(m_start.container(), m_start.offset(), commonRoot.get());
+    if (processStart && m_start.container() != commonRoot) // processStart contains nodes before m_start.
+        processStart = processStart->nextSibling();
+    RefPtr<Node> processEnd = childOfCommonRootBeforeOffset(m_end.container(), m_end.offset(), commonRoot.get());
+
+    // Collapse the range, making sure that the result is not within a node that was partially selected.
+    if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
+        if (partialStart && commonRoot->contains(partialStart.get()))
+            setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1, ec);
+        else if (partialEnd && commonRoot->contains(partialEnd.get()))
+            setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), ec);
+        if (ec)
+            return 0;
+        m_end = m_start;
+    }
+
+    // Now add leftContents, stuff in between, and rightContents to the fragment
+    // (or just delete the stuff in between)
+
+    if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents)
+        fragment->appendChild(leftContents, ec);
+
+    if (processStart) {
+        NodeVector nodes;
+        for (Node* n = processStart.get(); n && n != processEnd; n = n->nextSibling())
+            nodes.append(n);
+        processNodes(action, nodes, commonRoot, fragment, ec);
+    }
+
+    if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContents)
+        fragment->appendChild(rightContents, ec);
+
+    return fragment.release();
+}
+
+static inline void deleteCharacterData(PassRefPtr<CharacterData> data, unsigned startOffset, unsigned endOffset, ExceptionCode& ec)
+{
+    if (data->length() - endOffset)
+        data->deleteData(endOffset, data->length() - endOffset, ec);
+    if (startOffset)
+        data->deleteData(0, startOffset, ec);
+}
+
+PassRefPtr<Node> Range::processContentsBetweenOffsets(ActionType action, PassRefPtr<DocumentFragment> fragment,
+    Node* container, unsigned startOffset, unsigned endOffset, ExceptionCode& ec)
+{
+    ASSERT(container);
+    ASSERT(startOffset <= endOffset);
+
+    // This switch statement must be consistent with that of lengthOfContentsInNode.
+    RefPtr<Node> result;   
+    switch (container->nodeType()) {
+    case Node::TEXT_NODE:
+    case Node::CDATA_SECTION_NODE:
+    case Node::COMMENT_NODE:
+        ASSERT(endOffset <= static_cast<CharacterData*>(container)->length());
+        if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
+            RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(container->cloneNode(true));
+            deleteCharacterData(c, startOffset, endOffset, ec);
+            if (fragment) {
+                result = fragment;
+                result->appendChild(c.release(), ec);
+            } else
+                result = c.release();
+        }
+        if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
+            static_cast<CharacterData*>(container)->deleteData(startOffset, endOffset - startOffset, ec);
+        break;
+    case Node::PROCESSING_INSTRUCTION_NODE:
+        ASSERT(endOffset <= static_cast<ProcessingInstruction*>(container)->data().length());
+        if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
+            RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(container->cloneNode(true));
+            c->setData(c->data().substring(startOffset, endOffset - startOffset), ec);
+            if (fragment) {
+                result = fragment;
+                result->appendChild(c.release(), ec);
+            } else
+                result = c.release();
+        }
+        if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
+            ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(container);
+            String data(pi->data());
+            data.remove(startOffset, endOffset - startOffset);
+            pi->setData(data, ec);
+        }
+        break;
+    case Node::ELEMENT_NODE:
+    case Node::ATTRIBUTE_NODE:
+    case Node::ENTITY_REFERENCE_NODE:
+    case Node::ENTITY_NODE:
+    case Node::DOCUMENT_NODE:
+    case Node::DOCUMENT_TYPE_NODE:
+    case Node::DOCUMENT_FRAGMENT_NODE:
+    case Node::NOTATION_NODE:
+    case Node::XPATH_NAMESPACE_NODE:
+        // FIXME: Should we assert that some nodes never appear here?
+        if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
+            if (fragment)
+                result = fragment;
+            else
+                result = container->cloneNode(false);
+        }
+
+        Node* n = container->firstChild();
+        Vector<RefPtr<Node> > nodes;
+        for (unsigned i = startOffset; n && i; i--)
+            n = n->nextSibling();
+        for (unsigned i = startOffset; n && i < endOffset; i++, n = n->nextSibling())
+            nodes.append(n);
+
+        processNodes(action, nodes, container, result, ec);
+        break;
+    }
+
+    return result.release();
+}
+
+void Range::processNodes(ActionType action, Vector<RefPtr<Node> >& nodes, PassRefPtr<Node> oldContainer, PassRefPtr<Node> newContainer, ExceptionCode& ec)
+{
+    for (unsigned i = 0; i < nodes.size(); i++) {
+        switch (action) {
+        case DELETE_CONTENTS:
+            oldContainer->removeChild(nodes[i].get(), ec);
+            break;
+        case EXTRACT_CONTENTS:
+            newContainer->appendChild(nodes[i].release(), ec); // will remove n from its parent
+            break;
+        case CLONE_CONTENTS:
+            newContainer->appendChild(nodes[i]->cloneNode(true), ec);
+            break;
+        }
+    }
+}
+
+PassRefPtr<Node> Range::processAncestorsAndTheirSiblings(ActionType action, Node* container, ContentsProcessDirection direction, PassRefPtr<Node> passedClonedContainer, Node* commonRoot, ExceptionCode& ec)
+{
+    typedef Vector<RefPtr<Node> > NodeVector;
+
+    RefPtr<Node> clonedContainer = passedClonedContainer;
+    Vector<RefPtr<Node> > ancestors;
+    for (ContainerNode* n = container->parentNode(); n && n != commonRoot; n = n->parentNode())
+        ancestors.append(n);
+
+    RefPtr<Node> firstChildInAncestorToProcess = direction == ProcessContentsForward ? container->nextSibling() : container->previousSibling();
+    for (Vector<RefPtr<Node> >::const_iterator it = ancestors.begin(); it != ancestors.end(); it++) {
+        RefPtr<Node> ancestor = *it;
+        if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
+            if (RefPtr<Node> clonedAncestor = ancestor->cloneNode(false)) { // Might have been removed already during mutation event.
+                clonedAncestor->appendChild(clonedContainer, ec);
+                clonedContainer = clonedAncestor;
+            }
+        }
+
+        // Copy siblings of an ancestor of start/end containers
+        // FIXME: This assertion may fail if DOM is modified during mutation event
+        // FIXME: Share code with Range::processNodes
+        ASSERT(!firstChildInAncestorToProcess || firstChildInAncestorToProcess->parentNode() == ancestor);
+        
+        NodeVector nodes;
+        for (Node* child = firstChildInAncestorToProcess.get(); child;
+            child = (direction == ProcessContentsForward) ? child->nextSibling() : child->previousSibling())
+            nodes.append(child);
+
+        for (NodeVector::const_iterator it = nodes.begin(); it != nodes.end(); it++) {
+            Node* child = it->get();
+            switch (action) {
+            case DELETE_CONTENTS:
+                ancestor->removeChild(child, ec);
+                break;
+            case EXTRACT_CONTENTS: // will remove child from ancestor
+                if (direction == ProcessContentsForward)
+                    clonedContainer->appendChild(child, ec);
+                else
+                    clonedContainer->insertBefore(child, clonedContainer->firstChild(), ec);
+                break;
+            case CLONE_CONTENTS:
+                if (direction == ProcessContentsForward)
+                    clonedContainer->appendChild(child->cloneNode(true), ec);
+                else
+                    clonedContainer->insertBefore(child->cloneNode(true), clonedContainer->firstChild(), ec);
+                break;
+            }
+        }
+        firstChildInAncestorToProcess = direction == ProcessContentsForward ? ancestor->nextSibling() : ancestor->previousSibling();
+    }
+
+    return clonedContainer.release();
+}
+
+PassRefPtr<DocumentFragment> Range::extractContents(ExceptionCode& ec)
+{
+    checkDeleteExtract(ec);
+    if (ec)
+        return 0;
+
+    return processContents(EXTRACT_CONTENTS, ec);
+}
+
+PassRefPtr<DocumentFragment> Range::cloneContents(ExceptionCode& ec)
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    return processContents(CLONE_CONTENTS, ec);
+}
+
+void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionCode& ec)
+{
+    RefPtr<Node> newNode = prpNewNode;
+
+    ec = 0;
+
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    if (!newNode) {
+        ec = NOT_FOUND_ERR;
+        return;
+    }
+
+    // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
+    // the Range is read-only.
+    if (containedByReadOnly()) {
+        ec = NO_MODIFICATION_ALLOWED_ERR;
+        return;
+    }
+
+    // HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that
+    // does not allow children of the type of newNode or if newNode is an ancestor of the container.
+
+    // an extra one here - if a text node is going to split, it must have a parent to insert into
+    bool startIsText = m_start.container()->isTextNode();
+    if (startIsText && !m_start.container()->parentNode()) {
+        ec = HIERARCHY_REQUEST_ERR;
+        return;
+    }
+
+    // In the case where the container is a text node, we check against the container's parent, because
+    // text nodes get split up upon insertion.
+    Node* checkAgainst;
+    if (startIsText)
+        checkAgainst = m_start.container()->parentNode();
+    else
+        checkAgainst = m_start.container();
+
+    Node::NodeType newNodeType = newNode->nodeType();
+    int numNewChildren;
+    if (newNodeType == Node::DOCUMENT_FRAGMENT_NODE && !newNode->isShadowRoot()) {
+        // check each child node, not the DocumentFragment itself
+        numNewChildren = 0;
+        for (Node* c = newNode->firstChild(); c; c = c->nextSibling()) {
+            if (!checkAgainst->childTypeAllowed(c->nodeType())) {
+                ec = HIERARCHY_REQUEST_ERR;
+                return;
+            }
+            ++numNewChildren;
+        }
+    } else {
+        numNewChildren = 1;
+        if (!checkAgainst->childTypeAllowed(newNodeType)) {
+            ec = HIERARCHY_REQUEST_ERR;
+            return;
+        }
+    }
+
+    for (Node* n = m_start.container(); n; n = n->parentNode()) {
+        if (n == newNode) {
+            ec = HIERARCHY_REQUEST_ERR;
+            return;
+        }
+    }
+
+    // INVALID_NODE_TYPE_ERR: Raised if newNode is an Attr, Entity, Notation, ShadowRoot or Document node.
+    switch (newNodeType) {
+    case Node::ATTRIBUTE_NODE:
+    case Node::ENTITY_NODE:
+    case Node::NOTATION_NODE:
+    case Node::DOCUMENT_NODE:
+        ec = INVALID_NODE_TYPE_ERR;
+        return;
+    default:
+        if (newNode->isShadowRoot()) {
+            ec = INVALID_NODE_TYPE_ERR;
+            return;
+        }
+        break;
+    }
+
+    bool collapsed = m_start == m_end;
+    RefPtr<Node> container;
+    if (startIsText) {
+        container = m_start.container();
+        RefPtr<Text> newText = toText(container.get())->splitText(m_start.offset(), ec);
+        if (ec)
+            return;
+        
+        container = m_start.container();
+        container->parentNode()->insertBefore(newNode.release(), newText.get(), ec);
+        if (ec)
+            return;
+
+        // This special case doesn't seem to match the DOM specification, but it's currently required
+        // to pass Acid3. We might later decide to remove this.
+        if (collapsed)
+            m_end.setToBeforeChild(newText.get());
+    } else {
+        RefPtr<Node> lastChild;
+        if (collapsed)
+            lastChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ? newNode->lastChild() : newNode;
+
+        int startOffset = m_start.offset();
+        container = m_start.container();
+        container->insertBefore(newNode.release(), container->childNode(startOffset), ec);
+        if (ec)
+            return;
+
+        // This special case doesn't seem to match the DOM specification, but it's currently required
+        // to pass Acid3. We might later decide to remove this.
+        if (collapsed && numNewChildren)
+            m_end.set(m_start.container(), startOffset + numNewChildren, lastChild.get());
+    }
+}
+
+String Range::toString(ExceptionCode& ec) const
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return String();
+    }
+
+    StringBuilder builder;
+
+    Node* pastLast = pastLastNode();
+    for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(n)) {
+        if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SECTION_NODE) {
+            String data = static_cast<CharacterData*>(n)->data();
+            int length = data.length();
+            int start = (n == m_start.container()) ? min(max(0, m_start.offset()), length) : 0;
+            int end = (n == m_end.container()) ? min(max(start, m_end.offset()), length) : length;
+            builder.append(data.characters() + start, end - start);
+        }
+    }
+
+    return builder.toString();
+}
+
+String Range::toHTML() const
+{
+    return createMarkup(this);
+}
+
+String Range::text() const
+{
+    if (!m_start.container())
+        return String();
+
+    // We need to update layout, since plainText uses line boxes in the render tree.
+    // FIXME: As with innerText, we'd like this to work even if there are no render objects.
+    m_start.container()->document()->updateLayout();
+
+    return plainText(this);
+}
+
+PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& markup, ExceptionCode& ec)
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    Node* element = m_start.container()->isElementNode() ? m_start.container() : m_start.container()->parentNode();
+    if (!element || !element->isHTMLElement()) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+
+    RefPtr<DocumentFragment> fragment = WebCore::createContextualFragment(markup, toHTMLElement(element), AllowScriptingContentAndDoNotMarkAlreadyStarted, ec);
+    if (!fragment)
+        return 0;
+
+    return fragment.release();
+}
+
+
+void Range::detach(ExceptionCode& ec)
+{
+    // Check first to see if we've already detached:
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    m_ownerDocument->detachRange(this);
+
+    m_start.clear();
+    m_end.clear();
+}
+
+Node* Range::checkNodeWOffset(Node* n, int offset, ExceptionCode& ec) const
+{
+    switch (n->nodeType()) {
+        case Node::DOCUMENT_TYPE_NODE:
+        case Node::ENTITY_NODE:
+        case Node::NOTATION_NODE:
+            ec = INVALID_NODE_TYPE_ERR;
+            return 0;
+        case Node::CDATA_SECTION_NODE:
+        case Node::COMMENT_NODE:
+        case Node::TEXT_NODE:
+            if (static_cast<unsigned>(offset) > static_cast<CharacterData*>(n)->length())
+                ec = INDEX_SIZE_ERR;
+            return 0;
+        case Node::PROCESSING_INSTRUCTION_NODE:
+            if (static_cast<unsigned>(offset) > static_cast<ProcessingInstruction*>(n)->data().length())
+                ec = INDEX_SIZE_ERR;
+            return 0;
+        case Node::ATTRIBUTE_NODE:
+        case Node::DOCUMENT_FRAGMENT_NODE:
+        case Node::DOCUMENT_NODE:
+        case Node::ELEMENT_NODE:
+        case Node::ENTITY_REFERENCE_NODE:
+        case Node::XPATH_NAMESPACE_NODE: {
+            if (!offset)
+                return 0;
+            Node* childBefore = n->childNode(offset - 1);
+            if (!childBefore)
+                ec = INDEX_SIZE_ERR;
+            return childBefore;
+        }
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+void Range::checkNodeBA(Node* n, ExceptionCode& ec) const
+{
+    // INVALID_NODE_TYPE_ERR: Raised if the root container of refNode is not an
+    // Attr, Document, DocumentFragment or ShadowRoot node, or part of a SVG shadow DOM tree,
+    // or if refNode is a Document, DocumentFragment, ShadowRoot, Attr, Entity, or Notation node.
+
+    switch (n->nodeType()) {
+        case Node::ATTRIBUTE_NODE:
+        case Node::DOCUMENT_FRAGMENT_NODE:
+        case Node::DOCUMENT_NODE:
+        case Node::ENTITY_NODE:
+        case Node::NOTATION_NODE:
+            ec = INVALID_NODE_TYPE_ERR;
+            return;
+        case Node::CDATA_SECTION_NODE:
+        case Node::COMMENT_NODE:
+        case Node::DOCUMENT_TYPE_NODE:
+        case Node::ELEMENT_NODE:
+        case Node::ENTITY_REFERENCE_NODE:
+        case Node::PROCESSING_INSTRUCTION_NODE:
+        case Node::TEXT_NODE:
+        case Node::XPATH_NAMESPACE_NODE:
+            break;
+    }
+
+    Node* root = n;
+    while (ContainerNode* parent = root->parentNode())
+        root = parent;
+
+    switch (root->nodeType()) {
+        case Node::ATTRIBUTE_NODE:
+        case Node::DOCUMENT_NODE:
+        case Node::DOCUMENT_FRAGMENT_NODE:
+            break;
+        case Node::CDATA_SECTION_NODE:
+        case Node::COMMENT_NODE:
+        case Node::DOCUMENT_TYPE_NODE:
+        case Node::ELEMENT_NODE:
+        case Node::ENTITY_NODE:
+        case Node::ENTITY_REFERENCE_NODE:
+        case Node::NOTATION_NODE:
+        case Node::PROCESSING_INSTRUCTION_NODE:
+        case Node::TEXT_NODE:
+        case Node::XPATH_NAMESPACE_NODE:
+            ec = INVALID_NODE_TYPE_ERR;
+            return;
+    }
+}
+
+PassRefPtr<Range> Range::cloneRange(ExceptionCode& ec) const
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+
+    return Range::create(m_ownerDocument, m_start.container(), m_start.offset(), m_end.container(), m_end.offset());
+}
+
+void Range::setStartAfter(Node* refNode, ExceptionCode& ec)
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    if (!refNode) {
+        ec = NOT_FOUND_ERR;
+        return;
+    }
+
+    ec = 0;
+    checkNodeBA(refNode, ec);
+    if (ec)
+        return;
+
+    setStart(refNode->parentNode(), refNode->nodeIndex() + 1, ec);
+}
+
+void Range::setEndBefore(Node* refNode, ExceptionCode& ec)
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    if (!refNode) {
+        ec = NOT_FOUND_ERR;
+        return;
+    }
+
+    ec = 0;
+    checkNodeBA(refNode, ec);
+    if (ec)
+        return;
+
+    setEnd(refNode->parentNode(), refNode->nodeIndex(), ec);
+}
+
+void Range::setEndAfter(Node* refNode, ExceptionCode& ec)
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    if (!refNode) {
+        ec = NOT_FOUND_ERR;
+        return;
+    }
+
+    ec = 0;
+    checkNodeBA(refNode, ec);
+    if (ec)
+        return;
+
+    setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, ec);
+}
+
+void Range::selectNode(Node* refNode, ExceptionCode& ec)
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    if (!refNode) {
+        ec = NOT_FOUND_ERR;
+        return;
+    }
+
+    // INVALID_NODE_TYPE_ERR: Raised if an ancestor of refNode is an Entity, Notation or
+    // DocumentType node or if refNode is a Document, DocumentFragment, ShadowRoot, Attr, Entity, or Notation
+    // node.
+    for (ContainerNode* anc = refNode->parentNode(); anc; anc = anc->parentNode()) {
+        switch (anc->nodeType()) {
+            case Node::ATTRIBUTE_NODE:
+            case Node::CDATA_SECTION_NODE:
+            case Node::COMMENT_NODE:
+            case Node::DOCUMENT_FRAGMENT_NODE:
+            case Node::DOCUMENT_NODE:
+            case Node::ELEMENT_NODE:
+            case Node::ENTITY_REFERENCE_NODE:
+            case Node::PROCESSING_INSTRUCTION_NODE:
+            case Node::TEXT_NODE:
+            case Node::XPATH_NAMESPACE_NODE:
+                break;
+            case Node::DOCUMENT_TYPE_NODE:
+            case Node::ENTITY_NODE:
+            case Node::NOTATION_NODE:
+                ec = INVALID_NODE_TYPE_ERR;
+                return;
+        }
+    }
+
+    switch (refNode->nodeType()) {
+        case Node::CDATA_SECTION_NODE:
+        case Node::COMMENT_NODE:
+        case Node::DOCUMENT_TYPE_NODE:
+        case Node::ELEMENT_NODE:
+        case Node::ENTITY_REFERENCE_NODE:
+        case Node::PROCESSING_INSTRUCTION_NODE:
+        case Node::TEXT_NODE:
+        case Node::XPATH_NAMESPACE_NODE:
+            break;
+        case Node::ATTRIBUTE_NODE:
+        case Node::DOCUMENT_FRAGMENT_NODE:
+        case Node::DOCUMENT_NODE:
+        case Node::ENTITY_NODE:
+        case Node::NOTATION_NODE:
+            ec = INVALID_NODE_TYPE_ERR;
+            return;
+    }
+
+    if (m_ownerDocument != refNode->document())
+        setDocument(refNode->document());
+
+    ec = 0;
+    setStartBefore(refNode, ec);
+    if (ec)
+        return;
+    setEndAfter(refNode, ec);
+}
+
+void Range::selectNodeContents(Node* refNode, ExceptionCode& ec)
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    if (!refNode) {
+        ec = NOT_FOUND_ERR;
+        return;
+    }
+
+    // INVALID_NODE_TYPE_ERR: Raised if refNode or an ancestor of refNode is an Entity, Notation
+    // or DocumentType node.
+    for (Node* n = refNode; n; n = n->parentNode()) {
+        switch (n->nodeType()) {
+            case Node::ATTRIBUTE_NODE:
+            case Node::CDATA_SECTION_NODE:
+            case Node::COMMENT_NODE:
+            case Node::DOCUMENT_FRAGMENT_NODE:
+            case Node::DOCUMENT_NODE:
+            case Node::ELEMENT_NODE:
+            case Node::ENTITY_REFERENCE_NODE:
+            case Node::PROCESSING_INSTRUCTION_NODE:
+            case Node::TEXT_NODE:
+            case Node::XPATH_NAMESPACE_NODE:
+                break;
+            case Node::DOCUMENT_TYPE_NODE:
+            case Node::ENTITY_NODE:
+            case Node::NOTATION_NODE:
+                ec = INVALID_NODE_TYPE_ERR;
+                return;
+        }
+    }
+
+    if (m_ownerDocument != refNode->document())
+        setDocument(refNode->document());
+
+    m_start.setToStartOfNode(refNode);
+    m_end.setToEndOfNode(refNode);
+}
+
+void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionCode& ec)
+{
+    RefPtr<Node> newParent = passNewParent;
+
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    if (!newParent) {
+        ec = NOT_FOUND_ERR;
+        return;
+    }
+
+    // INVALID_NODE_TYPE_ERR: Raised if node is an Attr, Entity, DocumentType, Notation,
+    // Document, or DocumentFragment node.
+    switch (newParent->nodeType()) {
+        case Node::ATTRIBUTE_NODE:
+        case Node::DOCUMENT_FRAGMENT_NODE:
+        case Node::DOCUMENT_NODE:
+        case Node::DOCUMENT_TYPE_NODE:
+        case Node::ENTITY_NODE:
+        case Node::NOTATION_NODE:
+            ec = INVALID_NODE_TYPE_ERR;
+            return;
+        case Node::CDATA_SECTION_NODE:
+        case Node::COMMENT_NODE:
+        case Node::ELEMENT_NODE:
+        case Node::ENTITY_REFERENCE_NODE:
+        case Node::PROCESSING_INSTRUCTION_NODE:
+        case Node::TEXT_NODE:
+        case Node::XPATH_NAMESPACE_NODE:
+            break;
+    }
+
+    // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
+    // the Range is read-only.
+    if (containedByReadOnly()) {
+        ec = NO_MODIFICATION_ALLOWED_ERR;
+        return;
+    }
+
+    // Raise a HIERARCHY_REQUEST_ERR if m_start.container() doesn't accept children like newParent.
+    Node* parentOfNewParent = m_start.container();
+
+    // If m_start.container() is a character data node, it will be split and it will be its parent that will 
+    // need to accept newParent (or in the case of a comment, it logically "would" be inserted into the parent,
+    // although this will fail below for another reason).
+    if (parentOfNewParent->isCharacterDataNode())
+        parentOfNewParent = parentOfNewParent->parentNode();
+    if (!parentOfNewParent || !parentOfNewParent->childTypeAllowed(newParent->nodeType())) {
+        ec = HIERARCHY_REQUEST_ERR;
+        return;
+    }
+    
+    if (newParent->contains(m_start.container())) {
+        ec = HIERARCHY_REQUEST_ERR;
+        return;
+    }
+
+    // FIXME: Do we need a check if the node would end up with a child node of a type not
+    // allowed by the type of node?
+
+    // BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially selects a non-Text node.
+    Node* startNonTextContainer = m_start.container();
+    if (startNonTextContainer->nodeType() == Node::TEXT_NODE)
+        startNonTextContainer = startNonTextContainer->parentNode();
+    Node* endNonTextContainer = m_end.container();
+    if (endNonTextContainer->nodeType() == Node::TEXT_NODE)
+        endNonTextContainer = endNonTextContainer->parentNode();
+    if (startNonTextContainer != endNonTextContainer) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    ec = 0;
+    while (Node* n = newParent->firstChild()) {
+        toContainerNode(newParent.get())->removeChild(n, ec);
+        if (ec)
+            return;
+    }
+    RefPtr<DocumentFragment> fragment = extractContents(ec);
+    if (ec)
+        return;
+    insertNode(newParent, ec);
+    if (ec)
+        return;
+    newParent->appendChild(fragment.release(), ec);
+    if (ec)
+        return;
+    selectNode(newParent.get(), ec);
+}
+
+void Range::setStartBefore(Node* refNode, ExceptionCode& ec)
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    if (!refNode) {
+        ec = NOT_FOUND_ERR;
+        return;
+    }
+
+    ec = 0;
+    checkNodeBA(refNode, ec);
+    if (ec)
+        return;
+
+    setStart(refNode->parentNode(), refNode->nodeIndex(), ec);
+}
+
+void Range::checkDeleteExtract(ExceptionCode& ec)
+{
+    if (!m_start.container()) {
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    ec = 0;
+    if (!commonAncestorContainer(ec) || ec)
+        return;
+        
+    Node* pastLast = pastLastNode();
+    for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(n)) {
+        if (n->isReadOnlyNode()) {
+            ec = NO_MODIFICATION_ALLOWED_ERR;
+            return;
+        }
+        if (n->nodeType() == Node::DOCUMENT_TYPE_NODE) {
+            ec = HIERARCHY_REQUEST_ERR;
+            return;
+        }
+    }
+
+    if (containedByReadOnly()) {
+        ec = NO_MODIFICATION_ALLOWED_ERR;
+        return;
+    }
+}
+
+bool Range::containedByReadOnly() const
+{
+    for (Node* n = m_start.container(); n; n = n->parentNode()) {
+        if (n->isReadOnlyNode())
+            return true;
+    }
+    for (Node* n = m_end.container(); n; n = n->parentNode()) {
+        if (n->isReadOnlyNode())
+            return true;
+    }
+    return false;
+}
+
+Node* Range::firstNode() const
+{
+    if (!m_start.container())
+        return 0;
+    if (m_start.container()->offsetInCharacters())
+        return m_start.container();
+    if (Node* child = m_start.container()->childNode(m_start.offset()))
+        return child;
+    if (!m_start.offset())
+        return m_start.container();
+    return NodeTraversal::nextSkippingChildren(m_start.container());
+}
+
+ShadowRoot* Range::shadowRoot() const
+{
+    return startContainer() ? startContainer()->containingShadowRoot() : 0;
+}
+
+Node* Range::pastLastNode() const
+{
+    if (!m_start.container() || !m_end.container())
+        return 0;
+    if (m_end.container()->offsetInCharacters())
+        return NodeTraversal::nextSkippingChildren(m_end.container());
+    if (Node* child = m_end.container()->childNode(m_end.offset()))
+        return child;
+    return NodeTraversal::nextSkippingChildren(m_end.container());
+}
+
+IntRect Range::boundingBox() const
+{
+    IntRect result;
+    Vector<IntRect> rects;
+    textRects(rects);
+    const size_t n = rects.size();
+    for (size_t i = 0; i < n; ++i)
+        result.unite(rects[i]);
+    return result;
+}
+
+void Range::textRects(Vector<IntRect>& rects, bool useSelectionHeight, RangeInFixedPosition* inFixed) const
+{
+    Node* startContainer = m_start.container();
+    Node* endContainer = m_end.container();
+
+    if (!startContainer || !endContainer) {
+        if (inFixed)
+            *inFixed = NotFixedPosition;
+        return;
+    }
+
+    bool allFixed = true;
+    bool someFixed = false;
+
+    Node* stopNode = pastLastNode();
+    for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next(node)) {
+        RenderObject* r = node->renderer();
+        if (!r || !r->isText())
+            continue;
+        RenderText* renderText = toRenderText(r);
+        int startOffset = node == startContainer ? m_start.offset() : 0;
+        int endOffset = node == endContainer ? m_end.offset() : numeric_limits<int>::max();
+        bool isFixed = false;
+        renderText->absoluteRectsForRange(rects, startOffset, endOffset, useSelectionHeight, &isFixed);
+        allFixed &= isFixed;
+        someFixed |= isFixed;
+    }
+    
+    if (inFixed)
+        *inFixed = allFixed ? EntirelyFixedPosition : (someFixed ? PartiallyFixedPosition : NotFixedPosition);
+}
+
+void Range::textQuads(Vector<FloatQuad>& quads, bool useSelectionHeight, RangeInFixedPosition* inFixed) const
+{
+    Node* startContainer = m_start.container();
+    Node* endContainer = m_end.container();
+
+    if (!startContainer || !endContainer) {
+        if (inFixed)
+            *inFixed = NotFixedPosition;
+        return;
+    }
+
+    bool allFixed = true;
+    bool someFixed = false;
+
+    Node* stopNode = pastLastNode();
+    for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next(node)) {
+        RenderObject* r = node->renderer();
+        if (!r || !r->isText())
+            continue;
+        RenderText* renderText = toRenderText(r);
+        int startOffset = node == startContainer ? m_start.offset() : 0;
+        int endOffset = node == endContainer ? m_end.offset() : numeric_limits<int>::max();
+        bool isFixed = false;
+        renderText->absoluteQuadsForRange(quads, startOffset, endOffset, useSelectionHeight, &isFixed);
+        allFixed &= isFixed;
+        someFixed |= isFixed;
+    }
+
+    if (inFixed)
+        *inFixed = allFixed ? EntirelyFixedPosition : (someFixed ? PartiallyFixedPosition : NotFixedPosition);
+}
+
+#ifndef NDEBUG
+void Range::formatForDebugger(char* buffer, unsigned length) const
+{
+    StringBuilder result;
+    String s;
+
+    if (!m_start.container() || !m_end.container())
+        result.appendLiteral("<empty>");
+    else {
+        const int FormatBufferSize = 1024;
+        char s[FormatBufferSize];
+        result.appendLiteral("from offset ");
+        result.appendNumber(m_start.offset());
+        result.appendLiteral(" of ");
+        m_start.container()->formatForDebugger(s, FormatBufferSize);
+        result.append(s);
+        result.appendLiteral(" to offset ");
+        result.appendNumber(m_end.offset());
+        result.appendLiteral(" of ");
+        m_end.container()->formatForDebugger(s, FormatBufferSize);
+        result.append(s);
+    }
+
+    strncpy(buffer, result.toString().utf8().data(), length - 1);
+}
+#endif
+
+bool areRangesEqual(const Range* a, const Range* b)
+{
+    if (a == b)
+        return true;
+    if (!a || !b)
+        return false;
+    return a->startPosition() == b->startPosition() && a->endPosition() == b->endPosition();
+}
+
+PassRefPtr<Range> rangeOfContents(Node* node)
+{
+    ASSERT(node);
+    RefPtr<Range> range = Range::create(node->document());
+    int exception = 0;
+    range->selectNodeContents(node, exception);
+    return range.release();
+}
+
+int Range::maxStartOffset() const
+{
+    if (!m_start.container())
+        return 0;
+    if (!m_start.container()->offsetInCharacters())
+        return m_start.container()->childNodeCount();
+    return m_start.container()->maxCharacterOffset();
+}
+
+int Range::maxEndOffset() const
+{
+    if (!m_end.container())
+        return 0;
+    if (!m_end.container()->offsetInCharacters())
+        return m_end.container()->childNodeCount();
+    return m_end.container()->maxCharacterOffset();
+}
+
+static inline void boundaryNodeChildrenChanged(RangeBoundaryPoint& boundary, ContainerNode* container)
+{
+    if (!boundary.childBefore())
+        return;
+    if (boundary.container() != container)
+        return;
+    boundary.invalidateOffset();
+}
+
+void Range::nodeChildrenChanged(ContainerNode* container)
+{
+    ASSERT(container);
+    ASSERT(container->document() == m_ownerDocument);
+    boundaryNodeChildrenChanged(m_start, container);
+    boundaryNodeChildrenChanged(m_end, container);
+}
+
+static inline void boundaryNodeChildrenWillBeRemoved(RangeBoundaryPoint& boundary, ContainerNode* container)
+{
+    for (Node* nodeToBeRemoved = container->firstChild(); nodeToBeRemoved; nodeToBeRemoved = nodeToBeRemoved->nextSibling()) {
+        if (boundary.childBefore() == nodeToBeRemoved) {
+            boundary.setToStartOfNode(container);
+            return;
+        }
+
+        for (Node* n = boundary.container(); n; n = n->parentNode()) {
+            if (n == nodeToBeRemoved) {
+                boundary.setToStartOfNode(container);
+                return;
+            }
+        }
+    }
+}
+
+void Range::nodeChildrenWillBeRemoved(ContainerNode* container)
+{
+    ASSERT(container);
+    ASSERT(container->document() == m_ownerDocument);
+    boundaryNodeChildrenWillBeRemoved(m_start, container);
+    boundaryNodeChildrenWillBeRemoved(m_end, container);
+}
+
+static inline void boundaryNodeWillBeRemoved(RangeBoundaryPoint& boundary, Node* nodeToBeRemoved)
+{
+    if (boundary.childBefore() == nodeToBeRemoved) {
+        boundary.childBeforeWillBeRemoved();
+        return;
+    }
+
+    for (Node* n = boundary.container(); n; n = n->parentNode()) {
+        if (n == nodeToBeRemoved) {
+            boundary.setToBeforeChild(nodeToBeRemoved);
+            return;
+        }
+    }
+}
+
+void Range::nodeWillBeRemoved(Node* node)
+{
+    ASSERT(node);
+    ASSERT(node->document() == m_ownerDocument);
+    ASSERT(node != m_ownerDocument);
+    ASSERT(node->parentNode());
+    boundaryNodeWillBeRemoved(m_start, node);
+    boundaryNodeWillBeRemoved(m_end, node);
+}
+
+static inline void boundaryTextInserted(RangeBoundaryPoint& boundary, Node* text, unsigned offset, unsigned length)
+{
+    if (boundary.container() != text)
+        return;
+    unsigned boundaryOffset = boundary.offset();
+    if (offset >= boundaryOffset)
+        return;
+    boundary.setOffset(boundaryOffset + length);
+}
+
+void Range::textInserted(Node* text, unsigned offset, unsigned length)
+{
+    ASSERT(text);
+    ASSERT(text->document() == m_ownerDocument);
+    boundaryTextInserted(m_start, text, offset, length);
+    boundaryTextInserted(m_end, text, offset, length);
+}
+
+static inline void boundaryTextRemoved(RangeBoundaryPoint& boundary, Node* text, unsigned offset, unsigned length)
+{
+    if (boundary.container() != text)
+        return;
+    unsigned boundaryOffset = boundary.offset();
+    if (offset >= boundaryOffset)
+        return;
+    if (offset + length >= boundaryOffset)
+        boundary.setOffset(offset);
+    else
+        boundary.setOffset(boundaryOffset - length);
+}
+
+void Range::textRemoved(Node* text, unsigned offset, unsigned length)
+{
+    ASSERT(text);
+    ASSERT(text->document() == m_ownerDocument);
+    boundaryTextRemoved(m_start, text, offset, length);
+    boundaryTextRemoved(m_end, text, offset, length);
+}
+
+static inline void boundaryTextNodesMerged(RangeBoundaryPoint& boundary, NodeWithIndex& oldNode, unsigned offset)
+{
+    if (boundary.container() == oldNode.node())
+        boundary.set(oldNode.node()->previousSibling(), boundary.offset() + offset, 0);
+    else if (boundary.container() == oldNode.node()->parentNode() && boundary.offset() == oldNode.index())
+        boundary.set(oldNode.node()->previousSibling(), offset, 0);
+}
+
+void Range::textNodesMerged(NodeWithIndex& oldNode, unsigned offset)
+{
+    ASSERT(oldNode.node());
+    ASSERT(oldNode.node()->document() == m_ownerDocument);
+    ASSERT(oldNode.node()->parentNode());
+    ASSERT(oldNode.node()->isTextNode());
+    ASSERT(oldNode.node()->previousSibling());
+    ASSERT(oldNode.node()->previousSibling()->isTextNode());
+    boundaryTextNodesMerged(m_start, oldNode, offset);
+    boundaryTextNodesMerged(m_end, oldNode, offset);
+}
+
+static inline void boundaryTextNodesSplit(RangeBoundaryPoint& boundary, Text* oldNode)
+{
+    if (boundary.container() != oldNode)
+        return;
+    unsigned boundaryOffset = boundary.offset();
+    if (boundaryOffset <= oldNode->length())
+        return;
+    boundary.set(oldNode->nextSibling(), boundaryOffset - oldNode->length(), 0);
+}
+
+void Range::textNodeSplit(Text* oldNode)
+{
+    ASSERT(oldNode);
+    ASSERT(oldNode->document() == m_ownerDocument);
+    ASSERT(oldNode->parentNode());
+    ASSERT(oldNode->isTextNode());
+    ASSERT(oldNode->nextSibling());
+    ASSERT(oldNode->nextSibling()->isTextNode());
+    boundaryTextNodesSplit(m_start, oldNode);
+    boundaryTextNodesSplit(m_end, oldNode);
+}
+
+void Range::expand(const String& unit, ExceptionCode& ec)
+{
+    VisiblePosition start(startPosition());
+    VisiblePosition end(endPosition());
+    if (unit == "word") {
+        start = startOfWord(start);
+        end = endOfWord(end);
+    } else if (unit == "sentence") {
+        start = startOfSentence(start);
+        end = endOfSentence(end);
+    } else if (unit == "block") {
+        start = startOfParagraph(start);
+        end = endOfParagraph(end);
+    } else if (unit == "document") {
+        start = startOfDocument(start);
+        end = endOfDocument(end);
+    } else
+        return;
+    setStart(start.deepEquivalent().containerNode(), start.deepEquivalent().computeOffsetInContainerNode(), ec);
+    setEnd(end.deepEquivalent().containerNode(), end.deepEquivalent().computeOffsetInContainerNode(), ec);
+}
+
+PassRefPtr<ClientRectList> Range::getClientRects() const
+{
+    if (!m_start.container())
+        return ClientRectList::create();
+
+    m_ownerDocument->updateLayoutIgnorePendingStylesheets();
+
+    Vector<FloatQuad> quads;
+    getBorderAndTextQuads(quads);
+
+    return ClientRectList::create(quads);
+}
+
+PassRefPtr<ClientRect> Range::getBoundingClientRect() const
+{
+    return ClientRect::create(boundingRect());
+}
+
+void Range::getBorderAndTextQuads(Vector<FloatQuad>& quads) const
+{
+    Node* startContainer = m_start.container();
+    Node* endContainer = m_end.container();
+    Node* stopNode = pastLastNode();
+
+    HashSet<Node*> nodeSet;
+    for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next(node)) {
+        if (node->isElementNode())
+            nodeSet.add(node);
+    }
+
+    for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next(node)) {
+        if (node->isElementNode()) {
+            if (!nodeSet.contains(node->parentNode())) {
+                if (RenderBoxModelObject* renderBoxModelObject = toElement(node)->renderBoxModelObject()) {
+                    Vector<FloatQuad> elementQuads;
+                    renderBoxModelObject->absoluteQuads(elementQuads);
+                    m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoom(elementQuads, renderBoxModelObject);
+
+                    quads.append(elementQuads);
+                }
+            }
+        } else if (node->isTextNode()) {
+            if (RenderObject* renderer = toText(node)->renderer()) {
+                RenderText* renderText = toRenderText(renderer);
+                int startOffset = (node == startContainer) ? m_start.offset() : 0;
+                int endOffset = (node == endContainer) ? m_end.offset() : INT_MAX;
+                
+                Vector<FloatQuad> textQuads;
+                renderText->absoluteQuadsForRange(textQuads, startOffset, endOffset);
+                m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoom(textQuads, renderText);
+
+                quads.append(textQuads);
+            }
+        }
+    }
+}
+
+FloatRect Range::boundingRect() const
+{
+    if (!m_start.container())
+        return FloatRect();
+
+    m_ownerDocument->updateLayoutIgnorePendingStylesheets();
+
+    Vector<FloatQuad> quads;
+    getBorderAndTextQuads(quads);
+    if (quads.isEmpty())
+        return FloatRect();
+
+    FloatRect result;
+    for (size_t i = 0; i < quads.size(); ++i)
+        result.unite(quads[i].boundingBox());
+
+    return result;
+}
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+
+void showTree(const WebCore::Range* range)
+{
+    if (range && range->boundaryPointsValid()) {
+        range->startContainer()->showTreeAndMark(range->startContainer(), "S", range->endContainer(), "E");
+        fprintf(stderr, "start offset: %d, end offset: %d\n", range->startOffset(), range->endOffset());
+    }
+}
+
+#endif
diff --git a/Source/core/dom/Range.h b/Source/core/dom/Range.h
new file mode 100644
index 0000000..7e65656
--- /dev/null
+++ b/Source/core/dom/Range.h
@@ -0,0 +1,187 @@
+/*
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Gunnstein Lye (gunnstein@netcom.no)
+ * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Range_h
+#define Range_h
+
+#include "core/dom/ExceptionCodePlaceholder.h"
+#include "core/dom/FragmentScriptingPermission.h"
+#include "core/dom/RangeBoundaryPoint.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/IntRect.h"
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class ClientRect;
+class ClientRectList;
+class ContainerNode;
+class Document;
+class DocumentFragment;
+class FloatQuad;
+class Node;
+class NodeWithIndex;
+class Text;
+
+class Range : public RefCounted<Range> {
+public:
+    static PassRefPtr<Range> create(PassRefPtr<Document>);
+    static PassRefPtr<Range> create(PassRefPtr<Document>, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset);
+    static PassRefPtr<Range> create(PassRefPtr<Document>, const Position&, const Position&);
+    ~Range();
+
+    Document* ownerDocument() const { return m_ownerDocument.get(); }
+    Node* startContainer() const { return m_start.container(); }
+    int startOffset() const { return m_start.offset(); }
+    Node* endContainer() const { return m_end.container(); }
+    int endOffset() const { return m_end.offset(); }
+
+    Node* startContainer(ExceptionCode&) const;
+    int startOffset(ExceptionCode&) const;
+    Node* endContainer(ExceptionCode&) const;
+    int endOffset(ExceptionCode&) const;
+    bool collapsed(ExceptionCode&) const;
+
+    Node* commonAncestorContainer(ExceptionCode&) const;
+    static Node* commonAncestorContainer(Node* containerA, Node* containerB);
+    void setStart(PassRefPtr<Node> container, int offset, ExceptionCode& = ASSERT_NO_EXCEPTION);
+    void setEnd(PassRefPtr<Node> container, int offset, ExceptionCode& = ASSERT_NO_EXCEPTION);
+    void collapse(bool toStart, ExceptionCode&);
+    bool isPointInRange(Node* refNode, int offset, ExceptionCode&);
+    short comparePoint(Node* refNode, int offset, ExceptionCode&) const;
+    enum CompareResults { NODE_BEFORE, NODE_AFTER, NODE_BEFORE_AND_AFTER, NODE_INSIDE };
+    CompareResults compareNode(Node* refNode, ExceptionCode&) 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, ExceptionCode&);
+    static short compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const RangeBoundaryPoint& boundaryB, ExceptionCode&);
+    bool boundaryPointsValid() const;
+    bool intersectsNode(Node* refNode, ExceptionCode&);
+    void deleteContents(ExceptionCode&);
+    PassRefPtr<DocumentFragment> extractContents(ExceptionCode&);
+    PassRefPtr<DocumentFragment> cloneContents(ExceptionCode&);
+    void insertNode(PassRefPtr<Node>, ExceptionCode&);
+    String toString(ExceptionCode&) const;
+
+    String toHTML() const;
+    String text() const;
+
+    PassRefPtr<DocumentFragment> createContextualFragment(const String& html, ExceptionCode&);
+
+    void detach(ExceptionCode&);
+    PassRefPtr<Range> cloneRange(ExceptionCode&) const;
+
+    void setStartAfter(Node*, ExceptionCode& = ASSERT_NO_EXCEPTION);
+    void setEndBefore(Node*, ExceptionCode& = ASSERT_NO_EXCEPTION);
+    void setEndAfter(Node*, ExceptionCode& = ASSERT_NO_EXCEPTION);
+    void selectNode(Node*, ExceptionCode& = ASSERT_NO_EXCEPTION);
+    void selectNodeContents(Node*, ExceptionCode&);
+    void surroundContents(PassRefPtr<Node>, ExceptionCode&);
+    void setStartBefore(Node*, ExceptionCode&);
+
+    const Position startPosition() const { return m_start.toPosition(); }
+    const Position endPosition() const { return m_end.toPosition(); }
+    void setStart(const Position&, ExceptionCode& = ASSERT_NO_EXCEPTION);
+    void setEnd(const Position&, ExceptionCode& = ASSERT_NO_EXCEPTION);
+
+    Node* firstNode() const;
+    Node* pastLastNode() const;
+
+    ShadowRoot* shadowRoot() const;
+
+    enum RangeInFixedPosition {
+        NotFixedPosition,
+        PartiallyFixedPosition,
+        EntirelyFixedPosition
+    };
+
+    // Not transform-friendly
+    void textRects(Vector<IntRect>&, bool useSelectionHeight = false, RangeInFixedPosition* = 0) const;
+    IntRect boundingBox() const;
+
+    // Transform-friendly
+    void textQuads(Vector<FloatQuad>&, bool useSelectionHeight = false, RangeInFixedPosition* = 0) const;
+    void getBorderAndTextQuads(Vector<FloatQuad>&) const;
+    FloatRect boundingRect() const;
+
+    void nodeChildrenChanged(ContainerNode*);
+    void nodeChildrenWillBeRemoved(ContainerNode*);
+    void nodeWillBeRemoved(Node*);
+
+    void textInserted(Node*, unsigned offset, unsigned length);
+    void textRemoved(Node*, unsigned offset, unsigned length);
+    void textNodesMerged(NodeWithIndex& oldNode, unsigned offset);
+    void textNodeSplit(Text* oldNode);
+
+    // Expand range to a unit (word or sentence or block or document) boundary.
+    // Please refer to https://bugs.webkit.org/show_bug.cgi?id=27632 comment #5 
+    // for details.
+    void expand(const String&, ExceptionCode&);
+
+    PassRefPtr<ClientRectList> getClientRects() const;
+    PassRefPtr<ClientRect> getBoundingClientRect() const;
+
+#ifndef NDEBUG
+    void formatForDebugger(char* buffer, unsigned length) const;
+#endif
+
+private:
+    explicit Range(PassRefPtr<Document>);
+    Range(PassRefPtr<Document>, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset);
+
+    void setDocument(Document*);
+
+    Node* checkNodeWOffset(Node*, int offset, ExceptionCode&) const;
+    void checkNodeBA(Node*, ExceptionCode&) const;
+    void checkDeleteExtract(ExceptionCode&);
+    bool containedByReadOnly() const;
+    int maxStartOffset() const;
+    int maxEndOffset() const;
+
+    enum ActionType { DELETE_CONTENTS, EXTRACT_CONTENTS, CLONE_CONTENTS };
+    PassRefPtr<DocumentFragment> processContents(ActionType, ExceptionCode&);
+    static PassRefPtr<Node> processContentsBetweenOffsets(ActionType, PassRefPtr<DocumentFragment>, Node*, unsigned startOffset, unsigned endOffset, ExceptionCode&);
+    static void processNodes(ActionType, Vector<RefPtr<Node> >&, PassRefPtr<Node> oldContainer, PassRefPtr<Node> newContainer, ExceptionCode&);
+    enum ContentsProcessDirection { ProcessContentsForward, ProcessContentsBackward };
+    static PassRefPtr<Node> processAncestorsAndTheirSiblings(ActionType, Node* container, ContentsProcessDirection, PassRefPtr<Node> clonedContainer, Node* commonRoot, ExceptionCode&);
+
+    RefPtr<Document> m_ownerDocument;
+    RangeBoundaryPoint m_start;
+    RangeBoundaryPoint m_end;
+};
+
+PassRefPtr<Range> rangeOfContents(Node*);
+
+bool areRangesEqual(const Range*, const Range*);
+
+} // namespace
+
+#ifndef NDEBUG
+// Outside the WebCore namespace for ease of invocation from gdb.
+void showTree(const WebCore::Range*);
+#endif
+
+#endif
diff --git a/Source/core/dom/Range.idl b/Source/core/dom/Range.idl
new file mode 100644
index 0000000..3504bad
--- /dev/null
+++ b/Source/core/dom/Range.idl
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+// Introduced in DOM Level 2:
+[
+    ImplementationLacksVTable
+] interface Range {
+
+    [GetterRaisesException] readonly attribute Node startContainer;
+    [GetterRaisesException] readonly attribute long startOffset;
+    [GetterRaisesException] readonly attribute Node endContainer;
+    [GetterRaisesException] readonly attribute long endOffset;
+    [GetterRaisesException] readonly attribute boolean collapsed;
+    [GetterRaisesException] readonly attribute Node commonAncestorContainer;
+
+     [RaisesException] void setStart([Default=Undefined] optional Node refNode, 
+                                 [Default=Undefined] optional long offset);
+     [RaisesException] void setEnd([Default=Undefined] optional Node refNode, 
+                               [Default=Undefined] optional long offset);
+    [RaisesException] void setStartBefore([Default=Undefined] optional Node refNode);
+    [RaisesException] void setStartAfter([Default=Undefined] optional Node refNode);
+    [RaisesException] void setEndBefore([Default=Undefined] optional Node refNode);
+    [RaisesException] void setEndAfter([Default=Undefined] optional Node refNode);
+    [RaisesException] void collapse([Default=Undefined] optional boolean toStart);
+    [RaisesException] void selectNode([Default=Undefined] optional Node refNode);
+    [RaisesException] void selectNodeContents([Default=Undefined] optional Node refNode);
+
+    // CompareHow
+    const unsigned short START_TO_START = 0;
+    const unsigned short START_TO_END   = 1;
+    const unsigned short END_TO_END     = 2;
+    const unsigned short END_TO_START   = 3;
+
+     [RaisesException] short compareBoundaryPoints([Default=Undefined] optional CompareHow how,
+                                               [Default=Undefined] optional Range sourceRange);
+
+    [RaisesException] void deleteContents();
+    [RaisesException] DocumentFragment extractContents();
+    [RaisesException] DocumentFragment cloneContents();
+    [RaisesException] void insertNode([Default=Undefined] optional Node newNode);
+    [RaisesException] void surroundContents([Default=Undefined] optional Node newParent);
+    [RaisesException] Range cloneRange();
+    [RaisesException] DOMString toString();
+
+    [RaisesException] void detach();
+
+    // CSSOM View Module API extensions
+
+    ClientRectList getClientRects();
+    ClientRect getBoundingClientRect();
+
+    // extensions
+
+    [RaisesException] DocumentFragment createContextualFragment([Default=Undefined] optional DOMString html);
+
+    // WebKit extensions
+
+    [RaisesException] boolean intersectsNode([Default=Undefined] optional Node refNode);
+
+    [RaisesException] short compareNode([Default=Undefined] optional Node refNode);
+
+    // CompareResults
+    const unsigned short NODE_BEFORE           = 0;
+    const unsigned short NODE_AFTER            = 1;
+    const unsigned short NODE_BEFORE_AND_AFTER = 2;
+    const unsigned short NODE_INSIDE           = 3;
+
+    [RaisesException] short comparePoint([Default=Undefined] optional Node refNode, 
+                       [Default=Undefined] optional long offset);
+
+    [RaisesException] boolean isPointInRange([Default=Undefined] optional Node refNode, 
+                           [Default=Undefined] optional long offset);
+
+    [RaisesException] void expand([Default=Undefined] optional DOMString unit);
+};
+
diff --git a/Source/core/dom/RangeBoundaryPoint.h b/Source/core/dom/RangeBoundaryPoint.h
new file mode 100644
index 0000000..e868452
--- /dev/null
+++ b/Source/core/dom/RangeBoundaryPoint.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef RangeBoundaryPoint_h
+#define RangeBoundaryPoint_h
+
+#include "core/dom/Node.h"
+#include "core/dom/Position.h"
+
+namespace WebCore {
+
+class RangeBoundaryPoint {
+public:
+    explicit RangeBoundaryPoint(PassRefPtr<Node> container);
+
+    const Position toPosition() const;
+
+    Node* container() const;
+    int offset() const;
+    Node* childBefore() const;
+
+    void clear();
+
+    void set(PassRefPtr<Node> container, int offset, Node* childBefore);
+    void setOffset(int offset);
+
+    void setToBeforeChild(Node*);
+    void setToStartOfNode(PassRefPtr<Node>);
+    void setToEndOfNode(PassRefPtr<Node>);
+
+    void childBeforeWillBeRemoved();
+    void invalidateOffset() const;
+    void ensureOffsetIsValid() const;
+
+private:
+    static const int invalidOffset = -1;
+    
+    RefPtr<Node> m_containerNode;
+    mutable int m_offsetInContainer;
+    RefPtr<Node> m_childBeforeBoundary;
+};
+
+inline RangeBoundaryPoint::RangeBoundaryPoint(PassRefPtr<Node> container)
+    : m_containerNode(container)
+    , m_offsetInContainer(0)
+    , m_childBeforeBoundary(0)
+{
+    ASSERT(m_containerNode);
+}
+
+inline Node* RangeBoundaryPoint::container() const
+{
+    return m_containerNode.get();
+}
+
+inline Node* RangeBoundaryPoint::childBefore() const
+{
+    return m_childBeforeBoundary.get();
+}
+
+inline void RangeBoundaryPoint::ensureOffsetIsValid() const
+{
+    if (m_offsetInContainer >= 0)
+        return;
+
+    ASSERT(m_childBeforeBoundary);
+    m_offsetInContainer = m_childBeforeBoundary->nodeIndex() + 1;
+}
+
+inline const Position RangeBoundaryPoint::toPosition() const
+{
+    ensureOffsetIsValid();
+    return createLegacyEditingPosition(m_containerNode.get(), m_offsetInContainer);
+}
+
+inline int RangeBoundaryPoint::offset() const
+{
+    ensureOffsetIsValid();
+    return m_offsetInContainer;
+}
+
+inline void RangeBoundaryPoint::clear()
+{
+    m_containerNode.clear();
+    m_offsetInContainer = 0;
+    m_childBeforeBoundary = 0;
+}
+
+inline void RangeBoundaryPoint::set(PassRefPtr<Node> container, int offset, Node* childBefore)
+{
+    ASSERT(container);
+    ASSERT(offset >= 0);
+    ASSERT(childBefore == (offset ? container->childNode(offset - 1) : 0));
+    m_containerNode = container;
+    m_offsetInContainer = offset;
+    m_childBeforeBoundary = childBefore;
+}
+
+inline void RangeBoundaryPoint::setOffset(int offset)
+{
+    ASSERT(m_containerNode);
+    ASSERT(m_containerNode->offsetInCharacters());
+    ASSERT(m_offsetInContainer >= 0);
+    ASSERT(!m_childBeforeBoundary);
+    m_offsetInContainer = offset;
+}
+
+inline void RangeBoundaryPoint::setToBeforeChild(Node* child)
+{
+    ASSERT(child);
+    ASSERT(child->parentNode());
+    m_childBeforeBoundary = child->previousSibling();
+    m_containerNode = child->parentNode();
+    m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
+}
+
+inline void RangeBoundaryPoint::setToStartOfNode(PassRefPtr<Node> container)
+{
+    ASSERT(container);
+    m_containerNode = container;
+    m_offsetInContainer = 0;
+    m_childBeforeBoundary = 0;
+}
+
+inline void RangeBoundaryPoint::setToEndOfNode(PassRefPtr<Node> container)
+{
+    ASSERT(container);
+    m_containerNode = container;
+    if (m_containerNode->offsetInCharacters()) {
+        m_offsetInContainer = m_containerNode->maxCharacterOffset();
+        m_childBeforeBoundary = 0;
+    } else {
+        m_childBeforeBoundary = m_containerNode->lastChild();
+        m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
+    }
+}
+
+inline void RangeBoundaryPoint::childBeforeWillBeRemoved()
+{
+    ASSERT(m_offsetInContainer);
+    m_childBeforeBoundary = m_childBeforeBoundary->previousSibling();
+    if (!m_childBeforeBoundary)
+        m_offsetInContainer = 0;
+    else if (m_offsetInContainer > 0)
+        --m_offsetInContainer;
+}
+
+inline void RangeBoundaryPoint::invalidateOffset() const
+{
+    m_offsetInContainer = invalidOffset;
+}
+
+inline bool operator==(const RangeBoundaryPoint& a, const RangeBoundaryPoint& b)
+{
+    if (a.container() != b.container())
+        return false;
+    if (a.childBefore() || b.childBefore()) {
+        if (a.childBefore() != b.childBefore())
+            return false;
+    } else {
+        if (a.offset() != b.offset())
+            return false;
+    }
+    return true;
+}
+
+}
+
+#endif
diff --git a/Source/core/dom/RawDataDocumentParser.h b/Source/core/dom/RawDataDocumentParser.h
new file mode 100644
index 0000000..47d9952
--- /dev/null
+++ b/Source/core/dom/RawDataDocumentParser.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 RawDataDocumentParser_h
+#define RawDataDocumentParser_h
+
+#include "core/dom/DocumentParser.h"
+
+namespace WebCore {
+
+class RawDataDocumentParser : public DocumentParser {
+protected:
+    explicit RawDataDocumentParser(Document* document)
+        : DocumentParser(document)
+    {
+    }
+
+    virtual void finish()
+    {
+        if (!isStopped())
+            document()->finishedParsing();
+    }
+
+private:
+    virtual void flush(DocumentWriter* writer)
+    {
+        // Make sure appendBytes is called at least once.
+        appendBytes(writer, 0, 0);
+    }
+
+    virtual void insert(const SegmentedString&)
+    {
+        // <https://bugs.webkit.org/show_bug.cgi?id=25397>: JS code can always call document.write, we need to handle it.
+        ASSERT_NOT_REACHED();
+    }
+
+    virtual void append(PassRefPtr<StringImpl>)
+    {
+        ASSERT_NOT_REACHED();
+    }
+};
+
+};
+
+#endif // RawDataDocumentParser_h
diff --git a/Source/core/dom/RegisteredEventListener.cpp b/Source/core/dom/RegisteredEventListener.cpp
new file mode 100644
index 0000000..6153b5c
--- /dev/null
+++ b/Source/core/dom/RegisteredEventListener.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/RegisteredEventListener.h"
+
+#include "core/dom/EventListener.h"
+
+namespace WebCore {
+
+} // namespace WebCore
diff --git a/Source/core/dom/RegisteredEventListener.h b/Source/core/dom/RegisteredEventListener.h
new file mode 100644
index 0000000..1da01e6
--- /dev/null
+++ b/Source/core/dom/RegisteredEventListener.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RegisteredEventListener_h
+#define RegisteredEventListener_h
+
+#include "core/dom/EventListener.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+    class RegisteredEventListener {
+    public:
+        RegisteredEventListener(PassRefPtr<EventListener> listener, bool useCapture)
+            : listener(listener)
+            , useCapture(useCapture)
+        {
+        }
+
+        RefPtr<EventListener> listener;
+        bool useCapture;
+    };
+    
+    inline bool operator==(const RegisteredEventListener& a, const RegisteredEventListener& b)
+    {
+        return *a.listener == *b.listener && a.useCapture == b.useCapture;
+    }
+
+} // namespace WebCore
+
+#endif // RegisteredEventListener_h
diff --git a/Source/core/dom/RenderedDocumentMarker.h b/Source/core/dom/RenderedDocumentMarker.h
new file mode 100644
index 0000000..9e6966a
--- /dev/null
+++ b/Source/core/dom/RenderedDocumentMarker.h
@@ -0,0 +1,72 @@
+/*
+ * 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 RenderedDocumentMarker_h
+#define RenderedDocumentMarker_h
+
+#include "core/dom/DocumentMarker.h"
+
+namespace WebCore {
+
+class RenderedDocumentMarker : public DocumentMarker {
+public:
+
+    explicit RenderedDocumentMarker(const DocumentMarker& marker)
+        : DocumentMarker(marker), m_renderedRect(invalidMarkerRect())
+    {
+    }
+
+    bool isRendered() const { return invalidMarkerRect() != m_renderedRect; }
+    bool contains(const LayoutPoint& point) const { return isRendered() && m_renderedRect.contains(point); }
+    void setRenderedRect(const LayoutRect& r) { m_renderedRect = r; }
+    const LayoutRect& renderedRect() const { return m_renderedRect; }
+    void invalidate(const LayoutRect&);
+    void invalidate() { m_renderedRect = invalidMarkerRect(); }
+
+private:
+    static const LayoutRect& invalidMarkerRect()
+    {
+        static const LayoutRect rect = LayoutRect(-1, -1, -1, -1);
+        return rect;
+    }
+
+    LayoutRect m_renderedRect;
+};
+
+inline void RenderedDocumentMarker::invalidate(const LayoutRect& r)
+{
+    if (m_renderedRect.intersects(r))
+        invalidate();
+}
+
+inline RenderedDocumentMarker* toRenderedDocumentMarker(DocumentMarker* marker)
+{
+    return static_cast<RenderedDocumentMarker*>(marker);
+}
+
+} // namespace
+
+#endif
diff --git a/Source/core/dom/RequestAnimationFrameCallback.h b/Source/core/dom/RequestAnimationFrameCallback.h
new file mode 100644
index 0000000..52580dc
--- /dev/null
+++ b/Source/core/dom/RequestAnimationFrameCallback.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RequestAnimationFrameCallback_h
+#define RequestAnimationFrameCallback_h
+
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class RequestAnimationFrameCallback : public RefCounted<RequestAnimationFrameCallback> {
+public:
+    virtual ~RequestAnimationFrameCallback() { }
+    virtual bool handleEvent(double highResTimeMs) = 0;
+
+    int m_id;
+    bool m_firedOrCancelled;
+    bool m_useLegacyTimeBase;
+};
+
+}
+
+#endif // RequestAnimationFrameCallback_h
diff --git a/Source/core/dom/RequestAnimationFrameCallback.idl b/Source/core/dom/RequestAnimationFrameCallback.idl
new file mode 100644
index 0000000..d2f1d22
--- /dev/null
+++ b/Source/core/dom/RequestAnimationFrameCallback.idl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+callback interface RequestAnimationFrameCallback{
+    // highResTime is passed as high resolution timestamp, see
+    // http://www.w3.org/TR/hr-time/ for details.
+    boolean handleEvent(double highResTime);
+};
diff --git a/Source/core/dom/ScopedEventQueue.cpp b/Source/core/dom/ScopedEventQueue.cpp
new file mode 100644
index 0000000..3889936
--- /dev/null
+++ b/Source/core/dom/ScopedEventQueue.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/ScopedEventQueue.h"
+
+#include "core/dom/Event.h"
+#include "core/dom/EventDispatchMediator.h"
+#include "core/dom/EventDispatcher.h"
+#include "core/dom/EventTarget.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+ScopedEventQueue* ScopedEventQueue::s_instance = 0;
+
+ScopedEventQueue::ScopedEventQueue()
+    : m_scopingLevel(0)
+{
+}
+
+ScopedEventQueue::~ScopedEventQueue()
+{
+    ASSERT(!m_scopingLevel);
+    ASSERT(!m_queuedEventDispatchMediators.size());
+}
+
+void ScopedEventQueue::initialize()
+{
+    ASSERT(!s_instance);
+    OwnPtr<ScopedEventQueue> instance = adoptPtr(new ScopedEventQueue);
+    s_instance = instance.leakPtr();
+}
+
+void ScopedEventQueue::enqueueEventDispatchMediator(PassRefPtr<EventDispatchMediator> mediator)
+{
+    if (m_scopingLevel)
+        m_queuedEventDispatchMediators.append(mediator);
+    else
+        dispatchEvent(mediator);
+}
+
+void ScopedEventQueue::dispatchAllEvents()
+{
+    Vector<RefPtr<EventDispatchMediator> > queuedEventDispatchMediators;
+    queuedEventDispatchMediators.swap(m_queuedEventDispatchMediators);
+
+    for (size_t i = 0; i < queuedEventDispatchMediators.size(); i++)
+        dispatchEvent(queuedEventDispatchMediators[i].release());
+}
+
+void ScopedEventQueue::dispatchEvent(PassRefPtr<EventDispatchMediator> mediator) const
+{
+    ASSERT(mediator->event()->target());
+    Node* node = mediator->event()->target()->toNode();
+    EventDispatcher::dispatchEvent(node, mediator);
+}
+
+ScopedEventQueue* ScopedEventQueue::instance()
+{
+    if (!s_instance)
+        initialize();
+
+    return s_instance;
+}
+
+void ScopedEventQueue::incrementScopingLevel()
+{
+    m_scopingLevel++;
+}
+
+void ScopedEventQueue::decrementScopingLevel()
+{
+    ASSERT(m_scopingLevel);
+    m_scopingLevel--;
+    if (!m_scopingLevel)
+        dispatchAllEvents();
+}
+
+}
diff --git a/Source/core/dom/ScopedEventQueue.h b/Source/core/dom/ScopedEventQueue.h
new file mode 100644
index 0000000..262f6a9
--- /dev/null
+++ b/Source/core/dom/ScopedEventQueue.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ScopedEventQueue_h
+#define ScopedEventQueue_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class EventDispatchMediator;
+
+class ScopedEventQueue {
+    WTF_MAKE_NONCOPYABLE(ScopedEventQueue); WTF_MAKE_FAST_ALLOCATED;
+public:
+    ~ScopedEventQueue();
+
+    void enqueueEventDispatchMediator(PassRefPtr<EventDispatchMediator>);
+    void dispatchAllEvents();
+    static ScopedEventQueue* instance();
+
+    void incrementScopingLevel();
+    void decrementScopingLevel();
+
+private:
+    ScopedEventQueue();
+    static void initialize();
+    void dispatchEvent(PassRefPtr<EventDispatchMediator>) const;
+
+    Vector<RefPtr<EventDispatchMediator> > m_queuedEventDispatchMediators;
+    unsigned m_scopingLevel;
+
+    static ScopedEventQueue* s_instance;
+};
+
+class EventQueueScope {
+    WTF_MAKE_NONCOPYABLE(EventQueueScope);
+
+public:
+    EventQueueScope() { ScopedEventQueue::instance()->incrementScopingLevel(); }
+    ~EventQueueScope() { ScopedEventQueue::instance()->decrementScopingLevel(); }
+};
+
+}
+
+#endif // ScopedEventQueue_h
diff --git a/Source/core/dom/ScriptElement.cpp b/Source/core/dom/ScriptElement.cpp
new file mode 100644
index 0000000..b39ba0f
--- /dev/null
+++ b/Source/core/dom/ScriptElement.cpp
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/ScriptElement.h"
+
+#include "HTMLNames.h"
+#include "bindings/v8/ScriptController.h"
+#include "bindings/v8/ScriptSourceCode.h"
+#include "bindings/v8/ScriptValue.h"
+#include "core/dom/Document.h"
+#include "core/dom/DocumentParser.h"
+#include "core/dom/Event.h"
+#include "core/dom/IgnoreDestructiveWriteCountIncrementer.h"
+#include "core/dom/ScriptRunner.h"
+#include "core/dom/ScriptableDocumentParser.h"
+#include "core/dom/Text.h"
+#include "core/html/HTMLScriptElement.h"
+#include "core/html/parser/HTMLParserIdioms.h"
+#include "core/inspector/ScriptCallStack.h"
+#include "core/loader/CrossOriginAccessControl.h"
+#include "core/loader/FrameLoader.h"
+#include "core/loader/cache/CachedResourceLoader.h"
+#include "core/loader/cache/CachedResourceRequest.h"
+#include "core/loader/cache/CachedScript.h"
+#include "core/page/ContentSecurityPolicy.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/page/SecurityOrigin.h"
+#include "core/page/Settings.h"
+#include "core/platform/MIMETypeRegistry.h"
+#include <wtf/StdLibExtras.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/text/TextPosition.h>
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#include "core/svg/SVGScriptElement.h"
+#endif
+
+namespace WebCore {
+
+ScriptElement::ScriptElement(Element* element, bool parserInserted, bool alreadyStarted)
+    : m_element(element)
+    , m_cachedScript(0)
+    , m_startLineNumber(WTF::OrdinalNumber::beforeFirst())
+    , m_parserInserted(parserInserted)
+    , m_isExternalScript(false)
+    , m_alreadyStarted(alreadyStarted)
+    , m_haveFiredLoad(false)
+    , m_willBeParserExecuted(false)
+    , m_readyToBeParserExecuted(false)
+    , m_willExecuteWhenDocumentFinishedParsing(false)
+    , m_forceAsync(!parserInserted)
+    , m_willExecuteInOrder(false)
+    , m_requestUsesAccessControl(false)
+{
+    ASSERT(m_element);
+    if (parserInserted && m_element->document()->scriptableDocumentParser() && !m_element->document()->isInDocumentWrite())
+        m_startLineNumber = m_element->document()->scriptableDocumentParser()->lineNumber();
+}
+
+ScriptElement::~ScriptElement()
+{
+    stopLoadRequest();
+}
+
+void ScriptElement::insertedInto(ContainerNode* insertionPoint)
+{
+    if (insertionPoint->inDocument() && !m_parserInserted)
+        prepareScript(); // FIXME: Provide a real starting line number here.
+}
+
+void ScriptElement::childrenChanged()
+{
+    if (!m_parserInserted && m_element->inDocument())
+        prepareScript(); // FIXME: Provide a real starting line number here.
+}
+
+void ScriptElement::handleSourceAttribute(const String& sourceUrl)
+{
+    if (ignoresLoadRequest() || sourceUrl.isEmpty())
+        return;
+
+    prepareScript(); // FIXME: Provide a real starting line number here.
+}
+
+void ScriptElement::handleAsyncAttribute()
+{
+    m_forceAsync = false;
+}
+
+// Helper function
+static bool isLegacySupportedJavaScriptLanguage(const String& language)
+{
+    // Mozilla 1.8 accepts javascript1.0 - javascript1.7, but WinIE 7 accepts only javascript1.1 - javascript1.3.
+    // Mozilla 1.8 and WinIE 7 both accept javascript and livescript.
+    // WinIE 7 accepts ecmascript and jscript, but Mozilla 1.8 doesn't.
+    // Neither Mozilla 1.8 nor WinIE 7 accept leading or trailing whitespace.
+    // We want to accept all the values that either of these browsers accept, but not other values.
+
+    // FIXME: This function is not HTML5 compliant. These belong in the MIME registry as "text/javascript<version>" entries.
+    typedef HashSet<String, CaseFoldingHash> LanguageSet;
+    DEFINE_STATIC_LOCAL(LanguageSet, languages, ());
+    if (languages.isEmpty()) {
+        languages.add("javascript");
+        languages.add("javascript");
+        languages.add("javascript1.0");
+        languages.add("javascript1.1");
+        languages.add("javascript1.2");
+        languages.add("javascript1.3");
+        languages.add("javascript1.4");
+        languages.add("javascript1.5");
+        languages.add("javascript1.6");
+        languages.add("javascript1.7");
+        languages.add("livescript");
+        languages.add("ecmascript");
+        languages.add("jscript");
+    }
+
+    return languages.contains(language);
+}
+
+void ScriptElement::dispatchErrorEvent()
+{
+    m_element->dispatchEvent(Event::create(eventNames().errorEvent, false, false));
+}
+
+bool ScriptElement::isScriptTypeSupported(LegacyTypeSupport supportLegacyTypes) const
+{
+    // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is used here to maintain backwards compatibility with existing layout tests. The specific violations are:
+    // - Allowing type=javascript. type= should only support MIME types, such as text/javascript.
+    // - Allowing a different set of languages for language= and type=. language= supports Javascript 1.1 and 1.4-1.6, but type= does not.
+
+    String type = typeAttributeValue();
+    String language = languageAttributeValue();
+    if (type.isEmpty() && language.isEmpty())
+        return true; // Assume text/javascript.
+    if (type.isEmpty()) {
+        type = "text/" + language.lower();
+        if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type) || isLegacySupportedJavaScriptLanguage(language))
+            return true;
+    } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type.stripWhiteSpace().lower()) || (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && isLegacySupportedJavaScriptLanguage(type)))
+        return true;
+    return false;
+}
+
+// http://dev.w3.org/html5/spec/Overview.html#prepare-a-script
+bool ScriptElement::prepareScript(const TextPosition& scriptStartPosition, LegacyTypeSupport supportLegacyTypes)
+{
+    if (m_alreadyStarted)
+        return false;
+
+    bool wasParserInserted;
+    if (m_parserInserted) {
+        wasParserInserted = true;
+        m_parserInserted = false;
+    } else
+        wasParserInserted = false;
+
+    if (wasParserInserted && !asyncAttributeValue())
+        m_forceAsync = true;
+
+    // FIXME: HTML5 spec says we should check that all children are either comments or empty text nodes.
+    if (!hasSourceAttribute() && !m_element->firstChild())
+        return false;
+
+    if (!m_element->inDocument())
+        return false;
+
+    if (!isScriptTypeSupported(supportLegacyTypes))
+        return false;
+
+    if (wasParserInserted) {
+        m_parserInserted = true;
+        m_forceAsync = false;
+    }
+
+    m_alreadyStarted = true;
+
+    // FIXME: If script is parser inserted, verify it's still in the original document.
+    Document* document = m_element->document();
+
+    // FIXME: Eventually we'd like to evaluate scripts which are inserted into a
+    // viewless document but this'll do for now.
+    // See http://bugs.webkit.org/show_bug.cgi?id=5727
+    if (!document->frame())
+        return false;
+
+    if (!document->frame()->script()->canExecuteScripts(AboutToExecuteScript))
+        return false;
+
+    if (!isScriptForEventSupported())
+        return false;
+
+    if (!charsetAttributeValue().isEmpty())
+        m_characterEncoding = charsetAttributeValue();
+    else
+        m_characterEncoding = document->charset();
+
+    if (hasSourceAttribute())
+        if (!requestScript(sourceAttributeValue()))
+            return false;
+
+    if (hasSourceAttribute() && deferAttributeValue() && m_parserInserted && !asyncAttributeValue()) {
+        m_willExecuteWhenDocumentFinishedParsing = true;
+        m_willBeParserExecuted = true;
+    } else if (hasSourceAttribute() && m_parserInserted && !asyncAttributeValue())
+        m_willBeParserExecuted = true;
+    else if (!hasSourceAttribute() && m_parserInserted && !document->haveStylesheetsLoaded()) {
+        m_willBeParserExecuted = true;
+        m_readyToBeParserExecuted = true;
+    } else if (hasSourceAttribute() && !asyncAttributeValue() && !m_forceAsync) {
+        m_willExecuteInOrder = true;
+        document->scriptRunner()->queueScriptForExecution(this, m_cachedScript, ScriptRunner::IN_ORDER_EXECUTION);
+        m_cachedScript->addClient(this);
+    } else if (hasSourceAttribute()) {
+        m_element->document()->scriptRunner()->queueScriptForExecution(this, m_cachedScript, ScriptRunner::ASYNC_EXECUTION);
+        m_cachedScript->addClient(this);
+    } else {
+        // Reset line numbering for nested writes.
+        TextPosition position = document->isInDocumentWrite() ? TextPosition() : scriptStartPosition;
+        executeScript(ScriptSourceCode(scriptContent(), document->url(), position));
+    }
+
+    return true;
+}
+
+bool ScriptElement::requestScript(const String& sourceUrl)
+{
+    RefPtr<Document> originalDocument = m_element->document();
+    if (!m_element->dispatchBeforeLoadEvent(sourceUrl))
+        return false;
+    if (!m_element->inDocument() || m_element->document() != originalDocument)
+        return false;
+    if (!m_element->document()->contentSecurityPolicy()->allowScriptNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr), m_element->document()->url(), m_startLineNumber, m_element->document()->completeURL(sourceUrl)))
+        return false;
+
+    ASSERT(!m_cachedScript);
+    if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) {
+        CachedResourceRequest request(ResourceRequest(m_element->document()->completeURL(sourceUrl)));
+
+        String crossOriginMode = m_element->fastGetAttribute(HTMLNames::crossoriginAttr);
+        if (!crossOriginMode.isNull()) {
+            m_requestUsesAccessControl = true;
+            StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMode, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials;
+            updateRequestForAccessControl(request.mutableResourceRequest(), m_element->document()->securityOrigin(), allowCredentials);
+        }
+        request.setCharset(scriptCharset());
+        request.setInitiator(element());
+
+        m_cachedScript = m_element->document()->cachedResourceLoader()->requestScript(request);
+        m_isExternalScript = true;
+    }
+
+    if (m_cachedScript) {
+        return true;
+    }
+
+    dispatchErrorEvent();
+    return false;
+}
+
+void ScriptElement::executeScript(const ScriptSourceCode& sourceCode)
+{
+    ASSERT(m_alreadyStarted);
+
+    if (sourceCode.isEmpty())
+        return;
+
+    RefPtr<Document> document = m_element->document();
+    Frame* frame = document->frame();
+
+    bool shouldBypassMainWorldContentSecurityPolicy = (frame && frame->script()->shouldBypassMainWorldContentSecurityPolicy());
+    if (!shouldBypassMainWorldContentSecurityPolicy && !document->contentSecurityPolicy()->allowScriptNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr), document->url(), m_startLineNumber))
+        return;
+
+    if (!m_isExternalScript && (!shouldBypassMainWorldContentSecurityPolicy && !document->contentSecurityPolicy()->allowInlineScript(document->url(), m_startLineNumber)))
+        return;
+
+    if (m_isExternalScript && m_cachedScript && !m_cachedScript->mimeTypeAllowedByNosniff()) {
+        document->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Refused to execute script from '" + m_cachedScript->url().elidedString() + "' because its MIME type ('" + m_cachedScript->mimeType() + "') is not executable, and strict MIME type checking is enabled.");
+        return;
+    }
+
+    if (frame) {
+        {
+            IgnoreDestructiveWriteCountIncrementer ignoreDesctructiveWriteCountIncrementer(m_isExternalScript ? document.get() : 0);
+            // Create a script from the script element node, using the script
+            // block's source and the script block's type.
+            // Note: This is where the script is compiled and actually executed.
+            frame->script()->evaluate(sourceCode);
+        }
+    }
+}
+
+void ScriptElement::stopLoadRequest()
+{
+    if (m_cachedScript) {
+        if (!m_willBeParserExecuted)
+            m_cachedScript->removeClient(this);
+        m_cachedScript = 0;
+    }
+}
+
+void ScriptElement::execute(CachedScript* cachedScript)
+{
+    ASSERT(!m_willBeParserExecuted);
+    ASSERT(cachedScript);
+    if (cachedScript->errorOccurred())
+        dispatchErrorEvent();
+    else if (!cachedScript->wasCanceled()) {
+        executeScript(ScriptSourceCode(cachedScript));
+        dispatchLoadEvent();
+    }
+    cachedScript->removeClient(this);
+}
+
+void ScriptElement::notifyFinished(CachedResource* resource)
+{
+    ASSERT(!m_willBeParserExecuted);
+
+    // CachedResource possibly invokes this notifyFinished() more than
+    // once because ScriptElement doesn't unsubscribe itself from
+    // CachedResource here and does it in execute() instead.
+    // We use m_cachedScript to check if this function is already called.
+    ASSERT_UNUSED(resource, resource == m_cachedScript);
+    if (!m_cachedScript)
+        return;
+
+    String error;
+    if (m_requestUsesAccessControl
+        && !m_element->document()->securityOrigin()->canRequest(m_cachedScript->response().url())
+        && !m_cachedScript->passesAccessControlCheck(m_element->document()->securityOrigin(), error)) {
+
+        dispatchErrorEvent();
+        m_element->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Script from origin '" + SecurityOrigin::create(m_cachedScript->response().url())->toString() + "' has been blocked from loading by Cross-Origin Resource Sharing policy: " + error);
+        return;
+    }
+
+    if (m_willExecuteInOrder)
+        m_element->document()->scriptRunner()->notifyScriptReady(this, ScriptRunner::IN_ORDER_EXECUTION);
+    else
+        m_element->document()->scriptRunner()->notifyScriptReady(this, ScriptRunner::ASYNC_EXECUTION);
+
+    m_cachedScript = 0;
+}
+
+bool ScriptElement::ignoresLoadRequest() const
+{
+    return m_alreadyStarted || m_isExternalScript || m_parserInserted || !m_element->inDocument();
+}
+
+bool ScriptElement::isScriptForEventSupported() const
+{
+    String eventAttribute = eventAttributeValue();
+    String forAttribute = forAttributeValue();
+    if (!eventAttribute.isEmpty() && !forAttribute.isEmpty()) {
+        forAttribute = forAttribute.stripWhiteSpace();
+        if (!equalIgnoringCase(forAttribute, "window"))
+            return false;
+
+        eventAttribute = eventAttribute.stripWhiteSpace();
+        if (!equalIgnoringCase(eventAttribute, "onload") && !equalIgnoringCase(eventAttribute, "onload()"))
+            return false;
+    }
+    return true;
+}
+
+String ScriptElement::scriptContent() const
+{
+    StringBuilder content;
+    Text* firstTextNode = 0;
+    bool foundMultipleTextNodes = false;
+
+    for (Node* n = m_element->firstChild(); n; n = n->nextSibling()) {
+        if (!n->isTextNode())
+            continue;
+
+        Text* t = toText(n);
+        if (foundMultipleTextNodes)
+            content.append(t->data());
+        else if (firstTextNode) {
+            content.append(firstTextNode->data());
+            content.append(t->data());
+            foundMultipleTextNodes = true;
+        } else
+            firstTextNode = t;
+    }
+
+    if (firstTextNode && !foundMultipleTextNodes)
+        return firstTextNode->data();
+
+    return content.toString();
+}
+
+ScriptElement* toScriptElementIfPossible(Element* element)
+{
+    if (element->isHTMLElement() && element->hasTagName(HTMLNames::scriptTag))
+        return static_cast<HTMLScriptElement*>(element);
+
+#if ENABLE(SVG)
+    if (element->isSVGElement() && element->hasTagName(SVGNames::scriptTag))
+        return static_cast<SVGScriptElement*>(element);
+#endif
+
+    return 0;
+}
+
+}
diff --git a/Source/core/dom/ScriptElement.h b/Source/core/dom/ScriptElement.h
new file mode 100644
index 0000000..b6ec408
--- /dev/null
+++ b/Source/core/dom/ScriptElement.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ScriptElement_h
+#define ScriptElement_h
+
+#include "core/loader/cache/CachedResourceClient.h"
+#include "core/loader/cache/CachedResourceHandle.h"
+#include <wtf/text/TextPosition.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class CachedScript;
+class ContainerNode;
+class Element;
+class ScriptElement;
+class ScriptSourceCode;
+
+class ScriptElement : private CachedResourceClient {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ScriptElement(Element*, bool createdByParser, bool isEvaluated);
+    virtual ~ScriptElement();
+
+    Element* element() const { return m_element; }
+
+    enum LegacyTypeSupport { DisallowLegacyTypeInTypeAttribute, AllowLegacyTypeInTypeAttribute };
+    bool prepareScript(const TextPosition& scriptStartPosition = TextPosition::minimumPosition(), LegacyTypeSupport = DisallowLegacyTypeInTypeAttribute);
+
+    String scriptCharset() const { return m_characterEncoding; }
+    String scriptContent() const;
+    void executeScript(const ScriptSourceCode&);
+    void execute(CachedScript*);
+
+    // XML parser calls these
+    virtual void dispatchLoadEvent() = 0;
+    void dispatchErrorEvent();
+    bool isScriptTypeSupported(LegacyTypeSupport) const;
+
+    bool haveFiredLoadEvent() const { return m_haveFiredLoad; }
+    bool willBeParserExecuted() const { return m_willBeParserExecuted; }
+    bool readyToBeParserExecuted() const { return m_readyToBeParserExecuted; }
+    bool willExecuteWhenDocumentFinishedParsing() const { return m_willExecuteWhenDocumentFinishedParsing; }
+    CachedResourceHandle<CachedScript> cachedScript() { return m_cachedScript; }
+
+protected:
+    void setHaveFiredLoadEvent(bool haveFiredLoad) { m_haveFiredLoad = haveFiredLoad; }
+    bool isParserInserted() const { return m_parserInserted; }
+    bool alreadyStarted() const { return m_alreadyStarted; }
+    bool forceAsync() const { return m_forceAsync; }
+
+    // Helper functions used by our parent classes.
+    void insertedInto(ContainerNode*);
+    void childrenChanged();
+    void handleSourceAttribute(const String& sourceUrl);
+    void handleAsyncAttribute();
+
+private:
+    bool ignoresLoadRequest() const;
+    bool isScriptForEventSupported() const;
+
+    bool requestScript(const String& sourceUrl);
+    void stopLoadRequest();
+
+    virtual void notifyFinished(CachedResource*);
+
+    virtual String sourceAttributeValue() const = 0;
+    virtual String charsetAttributeValue() const = 0;
+    virtual String typeAttributeValue() const = 0;
+    virtual String languageAttributeValue() const = 0;
+    virtual String forAttributeValue() const = 0;
+    virtual String eventAttributeValue() const = 0;
+    virtual bool asyncAttributeValue() const = 0;
+    virtual bool deferAttributeValue() const = 0;
+    virtual bool hasSourceAttribute() const = 0;
+
+    Element* m_element;
+    CachedResourceHandle<CachedScript> m_cachedScript;
+    WTF::OrdinalNumber m_startLineNumber;
+    bool m_parserInserted : 1;
+    bool m_isExternalScript : 1;
+    bool m_alreadyStarted : 1;
+    bool m_haveFiredLoad : 1;
+    bool m_willBeParserExecuted : 1; // Same as "The parser will handle executing the script."
+    bool m_readyToBeParserExecuted : 1;
+    bool m_willExecuteWhenDocumentFinishedParsing : 1;
+    bool m_forceAsync : 1;
+    bool m_willExecuteInOrder : 1;
+    bool m_requestUsesAccessControl : 1;
+    String m_characterEncoding;
+    String m_fallbackCharacterEncoding;
+};
+
+ScriptElement* toScriptElementIfPossible(Element*);
+
+}
+
+#endif
diff --git a/Source/core/dom/ScriptExecutionContext.cpp b/Source/core/dom/ScriptExecutionContext.cpp
new file mode 100644
index 0000000..5ca4d36
--- /dev/null
+++ b/Source/core/dom/ScriptExecutionContext.cpp
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012 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 COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/ScriptExecutionContext.h"
+
+#include "core/dom/ErrorEvent.h"
+#include "core/dom/EventTarget.h"
+#include "core/dom/MessagePort.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/html/PublicURLManager.h"
+#include "core/inspector/ScriptCallStack.h"
+#include "core/loader/cache/CachedScript.h"
+#include "core/page/DOMTimer.h"
+#include "core/workers/WorkerContext.h"
+#include "core/workers/WorkerThread.h"
+#include "modules/webdatabase/DatabaseContext.h"
+#include <wtf/MainThread.h>
+#include <wtf/MemoryInstrumentationHashMap.h>
+#include <wtf/MemoryInstrumentationVector.h>
+
+namespace WTF {
+
+template<> struct SequenceMemoryInstrumentationTraits<WebCore::ContextDestructionObserver*> {
+    template <typename I> static void reportMemoryUsage(I, I, MemoryClassInfo&) { }
+};
+
+}
+namespace WebCore {
+
+class ProcessMessagesSoonTask : public ScriptExecutionContext::Task {
+public:
+    static PassOwnPtr<ProcessMessagesSoonTask> create()
+    {
+        return adoptPtr(new ProcessMessagesSoonTask);
+    }
+
+    virtual void performTask(ScriptExecutionContext* context)
+    {
+        context->dispatchMessagePortEvents();
+    }
+};
+
+class ScriptExecutionContext::PendingException {
+    WTF_MAKE_NONCOPYABLE(PendingException);
+public:
+    PendingException(const String& errorMessage, int lineNumber, const String& sourceURL, PassRefPtr<ScriptCallStack> callStack)
+        : m_errorMessage(errorMessage)
+        , m_lineNumber(lineNumber)
+        , m_sourceURL(sourceURL)
+        , m_callStack(callStack)
+    {
+    }
+    String m_errorMessage;
+    int m_lineNumber;
+    String m_sourceURL;
+    RefPtr<ScriptCallStack> m_callStack;
+};
+
+void ScriptExecutionContext::AddConsoleMessageTask::performTask(ScriptExecutionContext* context)
+{
+    context->addConsoleMessage(m_source, m_level, m_message);
+}
+
+ScriptExecutionContext::ScriptExecutionContext()
+    : m_iteratingActiveDOMObjects(false)
+    , m_inDestructor(false)
+    , m_circularSequentialID(0)
+    , m_inDispatchErrorEvent(false)
+    , m_activeDOMObjectsAreSuspended(false)
+    , m_reasonForSuspendingActiveDOMObjects(static_cast<ActiveDOMObject::ReasonForSuspension>(-1))
+    , m_activeDOMObjectsAreStopped(false)
+{
+}
+
+ScriptExecutionContext::~ScriptExecutionContext()
+{
+    m_inDestructor = true;
+    for (HashSet<ContextDestructionObserver*>::iterator iter = m_destructionObservers.begin(); iter != m_destructionObservers.end(); iter = m_destructionObservers.begin()) {
+        ContextDestructionObserver* observer = *iter;
+        m_destructionObservers.remove(observer);
+        ASSERT(observer->scriptExecutionContext() == this);
+        observer->contextDestroyed();
+    }
+
+    HashSet<MessagePort*>::iterator messagePortsEnd = m_messagePorts.end();
+    for (HashSet<MessagePort*>::iterator iter = m_messagePorts.begin(); iter != messagePortsEnd; ++iter) {
+        ASSERT((*iter)->scriptExecutionContext() == this);
+        (*iter)->contextDestroyed();
+    }
+    if (m_publicURLManager)
+        m_publicURLManager->contextDestroyed();
+}
+
+void ScriptExecutionContext::processMessagePortMessagesSoon()
+{
+    postTask(ProcessMessagesSoonTask::create());
+}
+
+void ScriptExecutionContext::dispatchMessagePortEvents()
+{
+    RefPtr<ScriptExecutionContext> protect(this);
+
+    // Make a frozen copy.
+    Vector<MessagePort*> ports;
+    copyToVector(m_messagePorts, ports);
+
+    unsigned portCount = ports.size();
+    for (unsigned i = 0; i < portCount; ++i) {
+        MessagePort* port = ports[i];
+        // The port may be destroyed, and another one created at the same address, but this is safe, as the worst that can happen
+        // as a result is that dispatchMessages() will be called needlessly.
+        if (m_messagePorts.contains(port) && port->started())
+            port->dispatchMessages();
+    }
+}
+
+void ScriptExecutionContext::createdMessagePort(MessagePort* port)
+{
+    ASSERT(port);
+    ASSERT((isDocument() && isMainThread())
+        || (isWorkerContext() && currentThread() == static_cast<WorkerContext*>(this)->thread()->threadID()));
+
+    m_messagePorts.add(port);
+}
+
+void ScriptExecutionContext::destroyedMessagePort(MessagePort* port)
+{
+    ASSERT(port);
+    ASSERT((isDocument() && isMainThread())
+        || (isWorkerContext() && currentThread() == static_cast<WorkerContext*>(this)->thread()->threadID()));
+
+    m_messagePorts.remove(port);
+}
+
+bool ScriptExecutionContext::canSuspendActiveDOMObjects()
+{
+    // No protection against m_activeDOMObjects changing during iteration: canSuspend() shouldn't execute arbitrary JS.
+    m_iteratingActiveDOMObjects = true;
+    ActiveDOMObjectsSet::iterator activeObjectsEnd = m_activeDOMObjects.end();
+    for (ActiveDOMObjectsSet::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
+        ASSERT((*iter)->scriptExecutionContext() == this);
+        ASSERT((*iter)->suspendIfNeededCalled());
+        if (!(*iter)->canSuspend()) {
+            m_iteratingActiveDOMObjects = false;
+            return false;
+        }
+    }
+    m_iteratingActiveDOMObjects = false;
+    return true;
+}
+
+void ScriptExecutionContext::suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension why)
+{
+    // No protection against m_activeDOMObjects changing during iteration: suspend() shouldn't execute arbitrary JS.
+    m_iteratingActiveDOMObjects = true;
+    ActiveDOMObjectsSet::iterator activeObjectsEnd = m_activeDOMObjects.end();
+    for (ActiveDOMObjectsSet::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
+        ASSERT((*iter)->scriptExecutionContext() == this);
+        ASSERT((*iter)->suspendIfNeededCalled());
+        (*iter)->suspend(why);
+    }
+    m_iteratingActiveDOMObjects = false;
+    m_activeDOMObjectsAreSuspended = true;
+    m_reasonForSuspendingActiveDOMObjects = why;
+}
+
+void ScriptExecutionContext::resumeActiveDOMObjects()
+{
+    m_activeDOMObjectsAreSuspended = false;
+    // No protection against m_activeDOMObjects changing during iteration: resume() shouldn't execute arbitrary JS.
+    m_iteratingActiveDOMObjects = true;
+    ActiveDOMObjectsSet::iterator activeObjectsEnd = m_activeDOMObjects.end();
+    for (ActiveDOMObjectsSet::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
+        ASSERT((*iter)->scriptExecutionContext() == this);
+        ASSERT((*iter)->suspendIfNeededCalled());
+        (*iter)->resume();
+    }
+    m_iteratingActiveDOMObjects = false;
+}
+
+void ScriptExecutionContext::stopActiveDOMObjects()
+{
+    m_activeDOMObjectsAreStopped = true;
+    // No protection against m_activeDOMObjects changing during iteration: stop() shouldn't execute arbitrary JS.
+    m_iteratingActiveDOMObjects = true;
+    ActiveDOMObjectsSet::iterator activeObjectsEnd = m_activeDOMObjects.end();
+    for (ActiveDOMObjectsSet::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
+        ASSERT((*iter)->scriptExecutionContext() == this);
+        ASSERT((*iter)->suspendIfNeededCalled());
+        (*iter)->stop();
+    }
+    m_iteratingActiveDOMObjects = false;
+
+    // Also close MessagePorts. If they were ActiveDOMObjects (they could be) then they could be stopped instead.
+    closeMessagePorts();
+}
+
+void ScriptExecutionContext::suspendActiveDOMObjectIfNeeded(ActiveDOMObject* object)
+{
+    ASSERT(m_activeDOMObjects.contains(object));
+    // Ensure all ActiveDOMObjects are suspended also newly created ones.
+    if (m_activeDOMObjectsAreSuspended)
+        object->suspend(m_reasonForSuspendingActiveDOMObjects);
+}
+
+void ScriptExecutionContext::didCreateActiveDOMObject(ActiveDOMObject* object)
+{
+    ASSERT(object);
+    ASSERT(!m_inDestructor);
+    if (m_iteratingActiveDOMObjects)
+        CRASH();
+    m_activeDOMObjects.add(object);
+}
+
+void ScriptExecutionContext::willDestroyActiveDOMObject(ActiveDOMObject* object)
+{
+    ASSERT(object);
+    if (m_iteratingActiveDOMObjects)
+        CRASH();
+    m_activeDOMObjects.remove(object);
+}
+
+void ScriptExecutionContext::didCreateDestructionObserver(ContextDestructionObserver* observer)
+{
+    ASSERT(observer);
+    ASSERT(!m_inDestructor);
+    m_destructionObservers.add(observer);
+}
+
+void ScriptExecutionContext::willDestroyDestructionObserver(ContextDestructionObserver* observer)
+{
+    ASSERT(observer);
+    m_destructionObservers.remove(observer);
+}
+
+void ScriptExecutionContext::closeMessagePorts() {
+    HashSet<MessagePort*>::iterator messagePortsEnd = m_messagePorts.end();
+    for (HashSet<MessagePort*>::iterator iter = m_messagePorts.begin(); iter != messagePortsEnd; ++iter) {
+        ASSERT((*iter)->scriptExecutionContext() == this);
+        (*iter)->close();
+    }
+}
+
+bool ScriptExecutionContext::sanitizeScriptError(String& errorMessage, int& lineNumber, String& sourceURL, CachedScript* cachedScript)
+{
+    KURL targetURL = completeURL(sourceURL);
+    if (securityOrigin()->canRequest(targetURL) || (cachedScript && cachedScript->passesAccessControlCheck(securityOrigin())))
+        return false;
+    errorMessage = "Script error.";
+    sourceURL = String();
+    lineNumber = 0;
+    return true;
+}
+
+void ScriptExecutionContext::reportException(const String& errorMessage, int lineNumber, const String& sourceURL, PassRefPtr<ScriptCallStack> callStack, CachedScript* cachedScript)
+{
+    if (m_inDispatchErrorEvent) {
+        if (!m_pendingExceptions)
+            m_pendingExceptions = adoptPtr(new Vector<OwnPtr<PendingException> >());
+        m_pendingExceptions->append(adoptPtr(new PendingException(errorMessage, lineNumber, sourceURL, callStack)));
+        return;
+    }
+
+    // First report the original exception and only then all the nested ones.
+    if (!dispatchErrorEvent(errorMessage, lineNumber, sourceURL, cachedScript))
+        logExceptionToConsole(errorMessage, sourceURL, lineNumber, callStack);
+
+    if (!m_pendingExceptions)
+        return;
+
+    for (size_t i = 0; i < m_pendingExceptions->size(); i++) {
+        PendingException* e = m_pendingExceptions->at(i).get();
+        logExceptionToConsole(e->m_errorMessage, e->m_sourceURL, e->m_lineNumber, e->m_callStack);
+    }
+    m_pendingExceptions.clear();
+}
+
+void ScriptExecutionContext::addConsoleMessage(MessageSource source, MessageLevel level, const String& message, const String& sourceURL, unsigned lineNumber, ScriptState* state, unsigned long requestIdentifier)
+{
+    addMessage(source, level, message, sourceURL, lineNumber, 0, state, requestIdentifier);
+}
+
+bool ScriptExecutionContext::dispatchErrorEvent(const String& errorMessage, int lineNumber, const String& sourceURL, CachedScript* cachedScript)
+{
+    EventTarget* target = errorEventTarget();
+    if (!target)
+        return false;
+
+    String message = errorMessage;
+    int line = lineNumber;
+    String sourceName = sourceURL;
+    sanitizeScriptError(message, line, sourceName, cachedScript);
+
+    ASSERT(!m_inDispatchErrorEvent);
+    m_inDispatchErrorEvent = true;
+    RefPtr<ErrorEvent> errorEvent = ErrorEvent::create(message, sourceName, line);
+    target->dispatchEvent(errorEvent);
+    m_inDispatchErrorEvent = false;
+    return errorEvent->defaultPrevented();
+}
+
+int ScriptExecutionContext::circularSequentialID()
+{
+    ++m_circularSequentialID;
+    if (m_circularSequentialID <= 0)
+        m_circularSequentialID = 1;
+    return m_circularSequentialID;
+}
+
+PublicURLManager& ScriptExecutionContext::publicURLManager()
+{
+    if (!m_publicURLManager)
+        m_publicURLManager = PublicURLManager::create();
+    return *m_publicURLManager;
+}
+
+void ScriptExecutionContext::didChangeTimerAlignmentInterval()
+{
+    for (TimeoutMap::iterator iter = m_timeouts.begin(); iter != m_timeouts.end(); ++iter) {
+        DOMTimer* timer = iter->value;
+        timer->didChangeAlignmentInterval();
+    }
+}
+
+double ScriptExecutionContext::timerAlignmentInterval() const
+{
+    return DOMTimer::visiblePageAlignmentInterval();
+}
+
+void ScriptExecutionContext::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    SecurityContext::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_messagePorts, "messagePorts");
+    info.addMember(m_destructionObservers, "destructionObservers");
+    info.addMember(m_activeDOMObjects, "activeDOMObjects");
+    info.addMember(m_timeouts, "timeouts");
+    info.addMember(m_pendingExceptions, "pendingExceptions");
+    info.addMember(m_publicURLManager, "publicURLManager");
+}
+
+ScriptExecutionContext::Task::~Task()
+{
+}
+
+void ScriptExecutionContext::setDatabaseContext(DatabaseContext* databaseContext)
+{
+    ASSERT(!m_databaseContext);
+    m_databaseContext = databaseContext;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/ScriptExecutionContext.h b/Source/core/dom/ScriptExecutionContext.h
new file mode 100644
index 0000000..1275d79
--- /dev/null
+++ b/Source/core/dom/ScriptExecutionContext.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012 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 COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef ScriptExecutionContext_h
+#define ScriptExecutionContext_h
+
+#include "core/dom/ActiveDOMObject.h"
+#include "core/dom/SecurityContext.h"
+#include "core/page/ConsoleTypes.h"
+#include "core/platform/KURL.h"
+#include "core/platform/Supplementable.h"
+#include <wtf/HashSet.h>
+
+namespace WebCore {
+
+class CachedScript;
+class DatabaseContext;
+class DOMTimer;
+class EventListener;
+class EventQueue;
+class EventTarget;
+class MessagePort;
+class PublicURLManager;
+class ScriptCallStack;
+class ScriptState;
+
+class ScriptExecutionContext : public SecurityContext, public Supplementable<ScriptExecutionContext> {
+public:
+    ScriptExecutionContext();
+    virtual ~ScriptExecutionContext();
+
+    virtual bool isDocument() const { return false; }
+    virtual bool isWorkerContext() const { return false; }
+
+    virtual bool isContextThread() const { return true; }
+    virtual bool isJSExecutionForbidden() const = 0;
+
+    const KURL& url() const { return virtualURL(); }
+    KURL completeURL(const String& url) const { return virtualCompleteURL(url); }
+
+    virtual String userAgent(const KURL&) const = 0;
+
+    virtual void disableEval(const String& errorMessage) = 0;
+
+    bool sanitizeScriptError(String& errorMessage, int& lineNumber, String& sourceURL, CachedScript* = 0);
+    void reportException(const String& errorMessage, int lineNumber, const String& sourceURL, PassRefPtr<ScriptCallStack>, CachedScript* = 0);
+
+    void addConsoleMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, ScriptState* = 0, unsigned long requestIdentifier = 0);
+    virtual void addConsoleMessage(MessageSource, MessageLevel, const String& message, unsigned long requestIdentifier = 0) = 0;
+
+    virtual const SecurityOrigin* topOrigin() const = 0;
+
+    PublicURLManager& publicURLManager();
+
+    // Active objects are not garbage collected even if inaccessible, e.g. because their activity may result in callbacks being invoked.
+    bool canSuspendActiveDOMObjects();
+    // Active objects can be asked to suspend even if canSuspendActiveDOMObjects() returns 'false' -
+    // step-by-step JS debugging is one example.
+    virtual void suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension);
+    virtual void resumeActiveDOMObjects();
+    virtual void stopActiveDOMObjects();
+
+    bool activeDOMObjectsAreSuspended() const { return m_activeDOMObjectsAreSuspended; }
+    bool activeDOMObjectsAreStopped() const { return m_activeDOMObjectsAreStopped; }
+
+    // Called from the constructor and destructors of ActiveDOMObject.
+    void didCreateActiveDOMObject(ActiveDOMObject*);
+    void willDestroyActiveDOMObject(ActiveDOMObject*);
+
+    // Called after the construction of an ActiveDOMObject to synchronize suspend state.
+    void suspendActiveDOMObjectIfNeeded(ActiveDOMObject*);
+
+    typedef HashSet<ActiveDOMObject*> ActiveDOMObjectsSet;
+    const ActiveDOMObjectsSet& activeDOMObjects() const { return m_activeDOMObjects; }
+
+    void didCreateDestructionObserver(ContextDestructionObserver*);
+    void willDestroyDestructionObserver(ContextDestructionObserver*);
+
+    virtual void suspendScriptedAnimationControllerCallbacks() { }
+    virtual void resumeScriptedAnimationControllerCallbacks() { }
+
+    // MessagePort is conceptually a kind of ActiveDOMObject, but it needs to be tracked separately for message dispatch.
+    void processMessagePortMessagesSoon();
+    void dispatchMessagePortEvents();
+    void createdMessagePort(MessagePort*);
+    void destroyedMessagePort(MessagePort*);
+    const HashSet<MessagePort*>& messagePorts() const { return m_messagePorts; }
+
+    void ref() { refScriptExecutionContext(); }
+    void deref() { derefScriptExecutionContext(); }
+
+    class Task {
+        WTF_MAKE_NONCOPYABLE(Task);
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        Task() { }
+        virtual ~Task();
+        virtual void performTask(ScriptExecutionContext*) = 0;
+        // Certain tasks get marked specially so that they aren't discarded, and are executed, when the context is shutting down its message queue.
+        virtual bool isCleanupTask() const { return false; }
+    };
+
+    virtual void postTask(PassOwnPtr<Task>) = 0; // Executes the task on context's thread asynchronously.
+
+    // Gets the next id in a circular sequence from 1 to 2^31-1.
+    int circularSequentialID();
+
+    bool addTimeout(int timeoutId, DOMTimer* timer) { return m_timeouts.add(timeoutId, timer).isNewEntry; }
+    void removeTimeout(int timeoutId) { m_timeouts.remove(timeoutId); }
+    DOMTimer* findTimeout(int timeoutId) { return m_timeouts.get(timeoutId); }
+
+    void didChangeTimerAlignmentInterval();
+    virtual double timerAlignmentInterval() const;
+
+    virtual EventQueue* eventQueue() const = 0;
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+    void setDatabaseContext(DatabaseContext*);
+
+protected:
+    class AddConsoleMessageTask : public Task {
+    public:
+        static PassOwnPtr<AddConsoleMessageTask> create(MessageSource source, MessageLevel level, const String& message)
+        {
+            return adoptPtr(new AddConsoleMessageTask(source, level, message));
+        }
+        virtual void performTask(ScriptExecutionContext*);
+    private:
+        AddConsoleMessageTask(MessageSource source, MessageLevel level, const String& message)
+            : m_source(source)
+            , m_level(level)
+            , m_message(message.isolatedCopy())
+        {
+        }
+        MessageSource m_source;
+        MessageLevel m_level;
+        String m_message;
+    };
+
+private:
+    virtual const KURL& virtualURL() const = 0;
+    virtual KURL virtualCompleteURL(const String&) const = 0;
+
+    virtual void addMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, PassRefPtr<ScriptCallStack>, ScriptState* = 0, unsigned long requestIdentifier = 0) = 0;
+    virtual EventTarget* errorEventTarget() = 0;
+    virtual void logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, PassRefPtr<ScriptCallStack>) = 0;
+    bool dispatchErrorEvent(const String& errorMessage, int lineNumber, const String& sourceURL, CachedScript*);
+
+    void closeMessagePorts();
+
+    virtual void refScriptExecutionContext() = 0;
+    virtual void derefScriptExecutionContext() = 0;
+
+    HashSet<MessagePort*> m_messagePorts;
+    HashSet<ContextDestructionObserver*> m_destructionObservers;
+    ActiveDOMObjectsSet m_activeDOMObjects;
+    bool m_iteratingActiveDOMObjects;
+    bool m_inDestructor;
+
+    int m_circularSequentialID;
+    typedef HashMap<int, DOMTimer*> TimeoutMap;
+    TimeoutMap m_timeouts;
+
+    bool m_inDispatchErrorEvent;
+    class PendingException;
+    OwnPtr<Vector<OwnPtr<PendingException> > > m_pendingExceptions;
+
+    bool m_activeDOMObjectsAreSuspended;
+    ActiveDOMObject::ReasonForSuspension m_reasonForSuspendingActiveDOMObjects;
+    bool m_activeDOMObjectsAreStopped;
+
+    OwnPtr<PublicURLManager> m_publicURLManager;
+
+    RefPtr<DatabaseContext> m_databaseContext;
+};
+
+} // namespace WebCore
+
+#endif // ScriptExecutionContext_h
diff --git a/Source/core/dom/ScriptRunner.cpp b/Source/core/dom/ScriptRunner.cpp
new file mode 100644
index 0000000..706a1d1
--- /dev/null
+++ b/Source/core/dom/ScriptRunner.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 "core/dom/ScriptRunner.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/PendingScript.h"
+#include "core/dom/ScriptElement.h"
+#include "core/loader/cache/CachedScript.h"
+
+namespace WebCore {
+
+ScriptRunner::ScriptRunner(Document* document)
+    : m_document(document)
+    , m_timer(this, &ScriptRunner::timerFired)
+{
+    ASSERT(document);
+}
+
+ScriptRunner::~ScriptRunner()
+{
+    for (size_t i = 0; i < m_scriptsToExecuteSoon.size(); ++i)
+        m_document->decrementLoadEventDelayCount();
+    for (size_t i = 0; i < m_scriptsToExecuteInOrder.size(); ++i)
+        m_document->decrementLoadEventDelayCount();
+    for (int i = 0; i < m_pendingAsyncScripts.size(); ++i)
+        m_document->decrementLoadEventDelayCount();
+}
+
+void ScriptRunner::queueScriptForExecution(ScriptElement* scriptElement, CachedResourceHandle<CachedScript> cachedScript, ExecutionType executionType)
+{
+    ASSERT(scriptElement);
+    ASSERT(cachedScript.get());
+
+    Element* element = scriptElement->element();
+    ASSERT(element);
+    ASSERT(element->inDocument());
+
+    m_document->incrementLoadEventDelayCount();
+
+    switch (executionType) {
+    case ASYNC_EXECUTION:
+        m_pendingAsyncScripts.add(scriptElement, PendingScript(element, cachedScript.get()));
+        break;
+
+    case IN_ORDER_EXECUTION:
+        m_scriptsToExecuteInOrder.append(PendingScript(element, cachedScript.get()));
+        break;
+    }
+}
+
+void ScriptRunner::suspend()
+{
+    m_timer.stop();
+}
+
+void ScriptRunner::resume()
+{
+    if (hasPendingScripts())
+        m_timer.startOneShot(0);
+}
+
+void ScriptRunner::notifyScriptReady(ScriptElement* scriptElement, ExecutionType executionType)
+{
+    switch (executionType) {
+    case ASYNC_EXECUTION:
+        ASSERT(m_pendingAsyncScripts.contains(scriptElement));
+        m_scriptsToExecuteSoon.append(m_pendingAsyncScripts.take(scriptElement));
+        break;
+
+    case IN_ORDER_EXECUTION:
+        ASSERT(!m_scriptsToExecuteInOrder.isEmpty());
+        break;
+    }
+    m_timer.startOneShot(0);
+}
+
+void ScriptRunner::timerFired(Timer<ScriptRunner>* timer)
+{
+    ASSERT_UNUSED(timer, timer == &m_timer);
+
+    RefPtr<Document> protect(m_document);
+
+    Vector<PendingScript> scripts;
+    scripts.swap(m_scriptsToExecuteSoon);
+
+    size_t numInOrderScriptsToExecute = 0;
+    for (; numInOrderScriptsToExecute < m_scriptsToExecuteInOrder.size() && m_scriptsToExecuteInOrder[numInOrderScriptsToExecute].cachedScript()->isLoaded(); ++numInOrderScriptsToExecute)
+        scripts.append(m_scriptsToExecuteInOrder[numInOrderScriptsToExecute]);
+    if (numInOrderScriptsToExecute)
+        m_scriptsToExecuteInOrder.remove(0, numInOrderScriptsToExecute);
+
+    size_t size = scripts.size();
+    for (size_t i = 0; i < size; ++i) {
+        CachedScript* cachedScript = scripts[i].cachedScript();
+        RefPtr<Element> element = scripts[i].releaseElementAndClear();
+        toScriptElementIfPossible(element.get())->execute(cachedScript);
+        m_document->decrementLoadEventDelayCount();
+    }
+}
+
+}
diff --git a/Source/core/dom/ScriptRunner.h b/Source/core/dom/ScriptRunner.h
new file mode 100644
index 0000000..c52bd89
--- /dev/null
+++ b/Source/core/dom/ScriptRunner.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 ScriptRunner_h
+#define ScriptRunner_h
+
+#include "core/loader/cache/CachedResourceHandle.h"
+#include "core/platform/Timer.h"
+#include <wtf/HashMap.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CachedScript;
+class Document;
+class PendingScript;
+class ScriptElement;
+
+class ScriptRunner {
+    WTF_MAKE_NONCOPYABLE(ScriptRunner); WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<ScriptRunner> create(Document* document) { return adoptPtr(new ScriptRunner(document)); }
+    ~ScriptRunner();
+
+    enum ExecutionType { ASYNC_EXECUTION, IN_ORDER_EXECUTION };
+    void queueScriptForExecution(ScriptElement*, CachedResourceHandle<CachedScript>, ExecutionType);
+    bool hasPendingScripts() const { return !m_scriptsToExecuteSoon.isEmpty() || !m_scriptsToExecuteInOrder.isEmpty() || !m_pendingAsyncScripts.isEmpty(); }
+    void suspend();
+    void resume();
+    void notifyScriptReady(ScriptElement*, ExecutionType);
+
+private:
+    explicit ScriptRunner(Document*);
+
+    void timerFired(Timer<ScriptRunner>*);
+
+    Document* m_document;
+    Vector<PendingScript> m_scriptsToExecuteInOrder;
+    Vector<PendingScript> m_scriptsToExecuteSoon; // http://www.whatwg.org/specs/web-apps/current-work/#set-of-scripts-that-will-execute-as-soon-as-possible
+    HashMap<ScriptElement*, PendingScript> m_pendingAsyncScripts;
+    Timer<ScriptRunner> m_timer;
+};
+
+}
+
+#endif
diff --git a/Source/core/dom/ScriptableDocumentParser.cpp b/Source/core/dom/ScriptableDocumentParser.cpp
new file mode 100644
index 0000000..42da5b5
--- /dev/null
+++ b/Source/core/dom/ScriptableDocumentParser.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 "core/dom/ScriptableDocumentParser.h"
+
+#include "bindings/v8/ScriptController.h"
+#include "core/dom/Document.h"
+#include "core/page/Frame.h"
+#include "core/page/Settings.h"
+
+namespace WebCore {
+
+ScriptableDocumentParser::ScriptableDocumentParser(Document* document, ParserContentPolicy parserContentPolicy)
+    : DecodedDataDocumentParser(document)
+    , m_wasCreatedByScript(false)
+    , m_parserContentPolicy(parserContentPolicy)
+{
+    if (!pluginContentIsAllowed(m_parserContentPolicy) && (!document->settings() || document->settings()->unsafePluginPastingEnabled()))
+        m_parserContentPolicy = allowPluginContent(m_parserContentPolicy);
+}
+
+};
diff --git a/Source/core/dom/ScriptableDocumentParser.h b/Source/core/dom/ScriptableDocumentParser.h
new file mode 100644
index 0000000..27dd726
--- /dev/null
+++ b/Source/core/dom/ScriptableDocumentParser.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 ScriptableDocumentParser_h
+#define ScriptableDocumentParser_h
+
+#include "core/dom/DecodedDataDocumentParser.h"
+#include "core/dom/FragmentScriptingPermission.h"
+#include <wtf/text/TextPosition.h>
+
+namespace WebCore {
+
+class ScriptableDocumentParser : public DecodedDataDocumentParser {
+public:
+    // Only used by Document::open for deciding if its safe to act on a
+    // JavaScript document.open() call right now, or it should be ignored.
+    virtual bool isExecutingScript() const { return false; }
+
+    // FIXME: Only the HTMLDocumentParser ever blocks script execution on
+    // stylesheet load, which is likely a bug in the XMLDocumentParser.
+    virtual void executeScriptsWaitingForStylesheets() { }
+
+    virtual bool isWaitingForScripts() const = 0;
+
+    // These are used to expose the current line/column to the scripting system.
+    virtual OrdinalNumber lineNumber() const = 0;
+    virtual TextPosition textPosition() const = 0;
+
+    void setWasCreatedByScript(bool wasCreatedByScript) { m_wasCreatedByScript = wasCreatedByScript; }
+    bool wasCreatedByScript() const { return m_wasCreatedByScript; }
+
+    ParserContentPolicy parserContentPolicy() { return m_parserContentPolicy; }
+
+protected:
+    explicit ScriptableDocumentParser(Document*, ParserContentPolicy = AllowScriptingContent);
+
+private:
+    virtual ScriptableDocumentParser* asScriptableDocumentParser() { return this; }
+
+    // http://www.whatwg.org/specs/web-apps/current-work/#script-created-parser
+    bool m_wasCreatedByScript;
+    ParserContentPolicy m_parserContentPolicy;
+};
+
+}
+
+#endif // ScriptableDocumentParser_h
diff --git a/Source/core/dom/ScriptedAnimationController.cpp b/Source/core/dom/ScriptedAnimationController.cpp
new file mode 100644
index 0000000..0a27612
--- /dev/null
+++ b/Source/core/dom/ScriptedAnimationController.cpp
@@ -0,0 +1,140 @@
+/*
+ * 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. AND ITS 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 APPLE INC. OR ITS 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 "core/dom/ScriptedAnimationController.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/RequestAnimationFrameCallback.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/loader/DocumentLoader.h"
+#include "core/page/FrameView.h"
+
+namespace WebCore {
+
+ScriptedAnimationController::ScriptedAnimationController(Document* document)
+    : m_document(document)
+    , m_nextCallbackId(0)
+    , m_suspendCount(0)
+{
+}
+
+ScriptedAnimationController::~ScriptedAnimationController()
+{
+}
+
+void ScriptedAnimationController::suspend()
+{
+    ++m_suspendCount;
+}
+
+void ScriptedAnimationController::resume()
+{
+    // It would be nice to put an ASSERT(m_suspendCount > 0) here, but in WK1 resume() can be called
+    // even when suspend hasn't (if a tab was created in the background).
+    if (m_suspendCount > 0)
+        --m_suspendCount;
+
+    if (!m_suspendCount && m_callbacks.size())
+        scheduleAnimation();
+}
+
+ScriptedAnimationController::CallbackId ScriptedAnimationController::registerCallback(PassRefPtr<RequestAnimationFrameCallback> callback)
+{
+    ScriptedAnimationController::CallbackId id = ++m_nextCallbackId;
+    callback->m_firedOrCancelled = false;
+    callback->m_id = id;
+    m_callbacks.append(callback);
+
+    InspectorInstrumentation::didRequestAnimationFrame(m_document, id);
+
+    if (!m_suspendCount)
+        scheduleAnimation();
+    return id;
+}
+
+void ScriptedAnimationController::cancelCallback(CallbackId id)
+{
+    for (size_t i = 0; i < m_callbacks.size(); ++i) {
+        if (m_callbacks[i]->m_id == id) {
+            m_callbacks[i]->m_firedOrCancelled = true;
+            InspectorInstrumentation::didCancelAnimationFrame(m_document, id);
+            m_callbacks.remove(i);
+            return;
+        }
+    }
+}
+
+void ScriptedAnimationController::serviceScriptedAnimations(double monotonicTimeNow)
+{
+    if (!m_callbacks.size() || m_suspendCount)
+        return;
+
+    double highResNowMs = 1000.0 * m_document->loader()->timing()->monotonicTimeToZeroBasedDocumentTime(monotonicTimeNow);
+    double legacyHighResNowMs = 1000.0 * m_document->loader()->timing()->monotonicTimeToPseudoWallTime(monotonicTimeNow);
+
+    // First, generate a list of callbacks to consider.  Callbacks registered from this point
+    // on are considered only for the "next" frame, not this one.
+    CallbackList callbacks(m_callbacks);
+
+    // Invoking callbacks may detach elements from our document, which clears the document's
+    // reference to us, so take a defensive reference.
+    RefPtr<ScriptedAnimationController> protector(this);
+
+    for (size_t i = 0; i < callbacks.size(); ++i) {
+        RequestAnimationFrameCallback* callback = callbacks[i].get();
+        if (!callback->m_firedOrCancelled) {
+            callback->m_firedOrCancelled = true;
+            InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireAnimationFrame(m_document, callback->m_id);
+            if (callback->m_useLegacyTimeBase)
+                callback->handleEvent(legacyHighResNowMs);
+            else
+                callback->handleEvent(highResNowMs);
+            InspectorInstrumentation::didFireAnimationFrame(cookie);
+        }
+    }
+
+    // Remove any callbacks we fired from the list of pending callbacks.
+    for (size_t i = 0; i < m_callbacks.size();) {
+        if (m_callbacks[i]->m_firedOrCancelled)
+            m_callbacks.remove(i);
+        else
+            ++i;
+    }
+
+    if (m_callbacks.size())
+        scheduleAnimation();
+}
+
+void ScriptedAnimationController::scheduleAnimation()
+{
+    if (!m_document)
+        return;
+
+    if (FrameView* frameView = m_document->view())
+        frameView->scheduleAnimation();
+}
+
+}
diff --git a/Source/core/dom/ScriptedAnimationController.h b/Source/core/dom/ScriptedAnimationController.h
new file mode 100644
index 0000000..9737c89
--- /dev/null
+++ b/Source/core/dom/ScriptedAnimationController.h
@@ -0,0 +1,73 @@
+/*
+ * 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. AND ITS 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 APPLE INC. OR ITS 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 ScriptedAnimationController_h
+#define ScriptedAnimationController_h
+
+#include "core/dom/DOMTimeStamp.h"
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Document;
+class RequestAnimationFrameCallback;
+
+class ScriptedAnimationController : public RefCounted<ScriptedAnimationController>
+{
+public:
+    static PassRefPtr<ScriptedAnimationController> create(Document* document)
+    {
+        return adoptRef(new ScriptedAnimationController(document));
+    }
+    ~ScriptedAnimationController();
+    void clearDocumentPointer() { m_document = 0; }
+
+    typedef int CallbackId;
+
+    CallbackId registerCallback(PassRefPtr<RequestAnimationFrameCallback>);
+    void cancelCallback(CallbackId);
+    void serviceScriptedAnimations(double monotonicTimeNow);
+
+    void suspend();
+    void resume();
+
+private:
+    explicit ScriptedAnimationController(Document*);
+
+    typedef Vector<RefPtr<RequestAnimationFrameCallback> > CallbackList;
+    CallbackList m_callbacks;
+
+    Document* m_document;
+    CallbackId m_nextCallbackId;
+    int m_suspendCount;
+
+    void scheduleAnimation();
+};
+
+}
+
+#endif // ScriptedAnimationController_h
diff --git a/Source/core/dom/SecurityContext.cpp b/Source/core/dom/SecurityContext.cpp
new file mode 100644
index 0000000..fbc460d
--- /dev/null
+++ b/Source/core/dom/SecurityContext.cpp
@@ -0,0 +1,153 @@
+/*
+ * 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 GOOGLE, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/SecurityContext.h"
+
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/html/parser/HTMLParserIdioms.h"
+#include "core/page/ContentSecurityPolicy.h"
+#include "core/page/SecurityOrigin.h"
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+SecurityContext::SecurityContext()
+    : m_mayDisplaySeamlesslyWithParent(false)
+    , m_haveInitializedSecurityOrigin(false)
+    , m_sandboxFlags(SandboxNone)
+{
+}
+
+SecurityContext::~SecurityContext()
+{
+}
+
+void SecurityContext::setSecurityOrigin(PassRefPtr<SecurityOrigin> securityOrigin)
+{
+    m_securityOrigin = securityOrigin;
+    m_haveInitializedSecurityOrigin = true;
+}
+
+void SecurityContext::setContentSecurityPolicy(PassOwnPtr<ContentSecurityPolicy> contentSecurityPolicy)
+{
+    m_contentSecurityPolicy = contentSecurityPolicy;
+}
+
+bool SecurityContext::isSecureTransitionTo(const KURL& url) const
+{
+    // If we haven't initialized our security origin by now, this is probably
+    // a new window created via the API (i.e., that lacks an origin and lacks
+    // a place to inherit the origin from).
+    if (!haveInitializedSecurityOrigin())
+        return true;
+
+    RefPtr<SecurityOrigin> other = SecurityOrigin::create(url);
+    return securityOrigin()->canAccess(other.get());
+}
+
+void SecurityContext::enforceSandboxFlags(SandboxFlags mask)
+{
+    m_sandboxFlags |= mask;
+
+    // The SandboxOrigin is stored redundantly in the security origin.
+    if (isSandboxed(SandboxOrigin) && securityOrigin() && !securityOrigin()->isUnique()) {
+        setSecurityOrigin(SecurityOrigin::createUnique());
+        didUpdateSecurityOrigin();
+    }
+}
+
+void SecurityContext::didUpdateSecurityOrigin()
+{
+    // Subclasses can override this function if the need to do extra work when the security origin changes.
+}
+
+SandboxFlags SecurityContext::parseSandboxPolicy(const String& policy, String& invalidTokensErrorMessage)
+{
+    // http://www.w3.org/TR/html5/the-iframe-element.html#attr-iframe-sandbox
+    // Parse the unordered set of unique space-separated tokens.
+    SandboxFlags flags = SandboxAll;
+    const UChar* characters = policy.characters();
+    unsigned length = policy.length();
+    unsigned start = 0;
+    unsigned numberOfTokenErrors = 0;
+    StringBuilder tokenErrors;
+    while (true) {
+        while (start < length && isHTMLSpace(characters[start]))
+            ++start;
+        if (start >= length)
+            break;
+        unsigned end = start + 1;
+        while (end < length && !isHTMLSpace(characters[end]))
+            ++end;
+
+        // Turn off the corresponding sandbox flag if it's set as "allowed".
+        String sandboxToken = policy.substring(start, end - start);
+        if (equalIgnoringCase(sandboxToken, "allow-same-origin"))
+            flags &= ~SandboxOrigin;
+        else if (equalIgnoringCase(sandboxToken, "allow-forms"))
+            flags &= ~SandboxForms;
+        else if (equalIgnoringCase(sandboxToken, "allow-scripts")) {
+            flags &= ~SandboxScripts;
+            flags &= ~SandboxAutomaticFeatures;
+        } else if (equalIgnoringCase(sandboxToken, "allow-top-navigation"))
+            flags &= ~SandboxTopNavigation;
+        else if (equalIgnoringCase(sandboxToken, "allow-popups"))
+            flags &= ~SandboxPopups;
+        else if (equalIgnoringCase(sandboxToken, "allow-pointer-lock"))
+            flags &= ~SandboxPointerLock;
+        else {
+            if (numberOfTokenErrors)
+                tokenErrors.appendLiteral(", '");
+            else
+                tokenErrors.append('\'');
+            tokenErrors.append(sandboxToken);
+            tokenErrors.append('\'');
+            numberOfTokenErrors++;
+        }
+
+        start = end + 1;
+    }
+
+    if (numberOfTokenErrors) {
+        if (numberOfTokenErrors > 1)
+            tokenErrors.appendLiteral(" are invalid sandbox flags.");
+        else
+            tokenErrors.appendLiteral(" is an invalid sandbox flag.");
+        invalidTokensErrorMessage = tokenErrors.toString();
+    }
+
+    return flags;
+}
+
+void SecurityContext::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    info.addMember(m_securityOrigin, "securityOrigin");
+    info.addMember(m_contentSecurityPolicy, "contentSecurityPolicy");
+}
+
+}
diff --git a/Source/core/dom/SecurityContext.h b/Source/core/dom/SecurityContext.h
new file mode 100644
index 0000000..61f0e6a
--- /dev/null
+++ b/Source/core/dom/SecurityContext.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 GOOGLE, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef SecurityContext_h
+#define SecurityContext_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class SecurityOrigin;
+class ContentSecurityPolicy;
+class KURL;
+
+enum SandboxFlag {
+    // See http://www.whatwg.org/specs/web-apps/current-work/#attr-iframe-sandbox for a list of the sandbox flags.
+    SandboxNone = 0,
+    SandboxNavigation = 1,
+    SandboxPlugins = 1 << 1,
+    SandboxOrigin = 1 << 2,
+    SandboxForms = 1 << 3,
+    SandboxScripts = 1 << 4,
+    SandboxTopNavigation = 1 << 5,
+    SandboxPopups = 1 << 6, // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=12393
+    SandboxAutomaticFeatures = 1 << 7,
+    SandboxSeamlessIframes = 1 << 8,
+    SandboxPointerLock = 1 << 9,
+    SandboxAll = -1 // Mask with all bits set to 1.
+};
+
+typedef int SandboxFlags;
+
+class SecurityContext {
+public:
+    SecurityOrigin* securityOrigin() const { return m_securityOrigin.get(); }
+    SandboxFlags sandboxFlags() const { return m_sandboxFlags; }
+    ContentSecurityPolicy* contentSecurityPolicy() { return m_contentSecurityPolicy.get(); }
+
+    bool isSecureTransitionTo(const KURL&) const;
+
+    void enforceSandboxFlags(SandboxFlags mask);
+    bool isSandboxed(SandboxFlags mask) const { return m_sandboxFlags & mask; }
+
+    // Explicitly override the security origin for this security context.
+    // Note: It is dangerous to change the security origin of a script context
+    //       that already contains content.
+    void setSecurityOrigin(PassRefPtr<SecurityOrigin>);
+
+    static SandboxFlags parseSandboxPolicy(const String& policy, String& invalidTokensErrorMessage);
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+
+protected:
+    SecurityContext();
+    virtual ~SecurityContext();
+
+    virtual void didUpdateSecurityOrigin();
+
+    void setContentSecurityPolicy(PassOwnPtr<ContentSecurityPolicy>);
+
+    void didFailToInitializeSecurityOrigin() { m_haveInitializedSecurityOrigin = false; }
+    bool haveInitializedSecurityOrigin() const { return m_haveInitializedSecurityOrigin; }
+
+    // Set in Document::initSecurityContext() at Document creation, per:
+    // http://www.whatwg.org/specs/web-apps/current-work/#attr-iframe-seamless
+    bool m_mayDisplaySeamlesslyWithParent;
+
+private:
+    bool m_haveInitializedSecurityOrigin;
+    SandboxFlags m_sandboxFlags;
+    RefPtr<SecurityOrigin> m_securityOrigin;
+    OwnPtr<ContentSecurityPolicy> m_contentSecurityPolicy;
+};
+
+} // namespace WebCore
+
+#endif // SecurityContext_h
diff --git a/Source/core/dom/SecurityPolicyViolationEvent.h b/Source/core/dom/SecurityPolicyViolationEvent.h
new file mode 100644
index 0000000..5915e43
--- /dev/null
+++ b/Source/core/dom/SecurityPolicyViolationEvent.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2013 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. AND ITS 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 APPLE INC. OR ITS 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 SecurityPolicyViolationEvent_h
+#define SecurityPolicyViolationEvent_h
+
+#include "core/dom/Event.h"
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+struct SecurityPolicyViolationEventInit : public EventInit {
+    SecurityPolicyViolationEventInit()
+    {
+    }
+
+    String documentURI;
+    String referrer;
+    String blockedURI;
+    String violatedDirective;
+    String effectiveDirective;
+    String originalPolicy;
+    String sourceFile;
+    int lineNumber;
+    int columnNumber;
+};
+
+class SecurityPolicyViolationEvent : public Event {
+public:
+    static PassRefPtr<SecurityPolicyViolationEvent> create()
+    {
+        return adoptRef(new SecurityPolicyViolationEvent());
+    }
+
+    static PassRefPtr<SecurityPolicyViolationEvent> create(const AtomicString& type, const SecurityPolicyViolationEventInit& initializer)
+    {
+        return adoptRef(new SecurityPolicyViolationEvent(type, initializer));
+    }
+
+    const String& documentURI() const { return m_documentURI; }
+    const String& referrer() const { return m_referrer; }
+    const String& blockedURI() const { return m_blockedURI; }
+    const String& violatedDirective() const { return m_violatedDirective; }
+    const String& effectiveDirective() const { return m_effectiveDirective; }
+    const String& originalPolicy() const { return m_originalPolicy; }
+    const String& sourceFile() const { return m_sourceFile; }
+    int lineNumber() const { return m_lineNumber; }
+    int columnNumber() const { return m_columnNumber; }
+
+    virtual const AtomicString& interfaceName() const { return eventNames().interfaceForSecurityPolicyViolationEvent; }
+
+private:
+    SecurityPolicyViolationEvent()
+    {
+        ScriptWrappable::init(this);
+    }
+
+    SecurityPolicyViolationEvent(const AtomicString& type, const SecurityPolicyViolationEventInit& initializer)
+        : Event(type, initializer)
+        , m_documentURI(initializer.documentURI)
+        , m_referrer(initializer.referrer)
+        , m_blockedURI(initializer.blockedURI)
+        , m_violatedDirective(initializer.violatedDirective)
+        , m_effectiveDirective(initializer.effectiveDirective)
+        , m_originalPolicy(initializer.originalPolicy)
+        , m_sourceFile(initializer.sourceFile)
+        , m_lineNumber(initializer.lineNumber)
+        , m_columnNumber(initializer.columnNumber)
+    {
+        ScriptWrappable::init(this);
+    }
+
+    String m_documentURI;
+    String m_referrer;
+    String m_blockedURI;
+    String m_violatedDirective;
+    String m_effectiveDirective;
+    String m_originalPolicy;
+    String m_sourceFile;
+    int m_lineNumber;
+    int m_columnNumber;
+};
+
+} // namespace WebCore
+
+#endif // SecurityPolicyViolationEvent_h
diff --git a/Source/core/dom/SecurityPolicyViolationEvent.idl b/Source/core/dom/SecurityPolicyViolationEvent.idl
new file mode 100644
index 0000000..590d8e6
--- /dev/null
+++ b/Source/core/dom/SecurityPolicyViolationEvent.idl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 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. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+[
+    ConstructorTemplate=Event,
+] interface SecurityPolicyViolationEvent : Event {
+    [InitializedByEventConstructor] readonly attribute DOMString documentURI;
+    [InitializedByEventConstructor] readonly attribute DOMString referrer;
+    [InitializedByEventConstructor] readonly attribute DOMString blockedURI;
+    [InitializedByEventConstructor] readonly attribute DOMString violatedDirective;
+    [InitializedByEventConstructor] readonly attribute DOMString effectiveDirective;
+    [InitializedByEventConstructor] readonly attribute DOMString originalPolicy;
+    [InitializedByEventConstructor] readonly attribute DOMString sourceFile;
+    [InitializedByEventConstructor] readonly attribute long      lineNumber;
+    [InitializedByEventConstructor] readonly attribute long      columnNumber;
+};
diff --git a/Source/core/dom/SelectorQuery.cpp b/Source/core/dom/SelectorQuery.cpp
new file mode 100644
index 0000000..589a0f2
--- /dev/null
+++ b/Source/core/dom/SelectorQuery.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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 "core/dom/SelectorQuery.h"
+
+#include "core/css/CSSParser.h"
+#include "core/css/CSSSelectorList.h"
+#include "core/css/SelectorChecker.h"
+#include "core/css/SelectorCheckerFastPath.h"
+#include "core/css/SiblingTraversalStrategies.h"
+#include "core/dom/Document.h"
+#include "core/dom/StaticNodeList.h"
+#include "core/dom/StyledElement.h"
+
+namespace WebCore {
+
+void SelectorDataList::initialize(const CSSSelectorList& selectorList)
+{
+    ASSERT(m_selectors.isEmpty());
+
+    unsigned selectorCount = 0;
+    for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector))
+        selectorCount++;
+
+    m_selectors.reserveInitialCapacity(selectorCount);
+    for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector))
+        m_selectors.uncheckedAppend(SelectorData(selector, SelectorCheckerFastPath::canUse(selector)));
+}
+
+inline bool SelectorDataList::selectorMatches(const SelectorData& selectorData, Element* element, const Node* rootNode) const
+{
+    if (selectorData.isFastCheckable && !element->isSVGElement()) {
+        SelectorCheckerFastPath selectorCheckerFastPath(selectorData.selector, element);
+        if (!selectorCheckerFastPath.matchesRightmostSelector(SelectorChecker::VisitedMatchDisabled))
+            return false;
+        return selectorCheckerFastPath.matches();
+    }
+
+    SelectorChecker selectorChecker(element->document(), SelectorChecker::QueryingRules);
+    SelectorChecker::SelectorCheckingContext selectorCheckingContext(selectorData.selector, element, SelectorChecker::VisitedMatchDisabled);
+    selectorCheckingContext.behaviorAtBoundary = SelectorChecker::StaysWithinTreeScope;
+    selectorCheckingContext.scope = !rootNode->isDocumentNode() && rootNode->isContainerNode() ? toContainerNode(rootNode) : 0;
+    PseudoId ignoreDynamicPseudo = NOPSEUDO;
+    return selectorChecker.match(selectorCheckingContext, ignoreDynamicPseudo, DOMSiblingTraversalStrategy()) == SelectorChecker::SelectorMatches;
+}
+
+bool SelectorDataList::matches(Element* targetElement) const
+{
+    ASSERT(targetElement);
+
+    unsigned selectorCount = m_selectors.size();
+    for (unsigned i = 0; i < selectorCount; ++i) {
+        if (selectorMatches(m_selectors[i], targetElement, targetElement))
+            return true;
+    }
+
+    return false;
+}
+
+PassRefPtr<NodeList> SelectorDataList::queryAll(Node* rootNode) const
+{
+    Vector<RefPtr<Node> > result;
+    execute<false>(rootNode, result);
+    return StaticNodeList::adopt(result);
+}
+
+PassRefPtr<Element> SelectorDataList::queryFirst(Node* rootNode) const
+{
+    Vector<RefPtr<Node> > result;
+    execute<true>(rootNode, result);
+    if (result.isEmpty())
+        return 0;
+    ASSERT(result.size() == 1);
+    ASSERT(result.first()->isElementNode());
+    return toElement(result.first().get());
+}
+
+bool SelectorDataList::canUseIdLookup(Node* rootNode) const
+{
+    // We need to return the matches in document order. To use id lookup while there is possiblity of multiple matches
+    // we would need to sort the results. For now, just traverse the document in that case.
+    if (m_selectors.size() != 1)
+        return false;
+    if (m_selectors[0].selector->m_match != CSSSelector::Id)
+        return false;
+    if (!rootNode->inDocument())
+        return false;
+    if (rootNode->document()->inQuirksMode())
+        return false;
+    if (rootNode->document()->containsMultipleElementsWithId(m_selectors[0].selector->value()))
+        return false;
+    return true;
+}
+
+static inline bool isTreeScopeRoot(Node* node)
+{
+    ASSERT(node);
+    return node->isDocumentNode() || node->isShadowRoot();
+}
+
+template <bool firstMatchOnly>
+void SelectorDataList::execute(Node* rootNode, Vector<RefPtr<Node> >& matchedElements) const
+{
+    if (canUseIdLookup(rootNode)) {
+        ASSERT(m_selectors.size() == 1);
+        const CSSSelector* selector = m_selectors[0].selector;
+        Element* element = rootNode->treeScope()->getElementById(selector->value());
+        if (!element || !(isTreeScopeRoot(rootNode) || element->isDescendantOf(rootNode)))
+            return;
+        if (selectorMatches(m_selectors[0], element, rootNode))
+            matchedElements.append(element);
+        return;
+    }
+
+    unsigned selectorCount = m_selectors.size();
+
+    Node* n = rootNode->firstChild();
+    while (n) {
+        if (n->isElementNode()) {
+            Element* element = toElement(n);
+            for (unsigned i = 0; i < selectorCount; ++i) {
+                if (selectorMatches(m_selectors[i], element, rootNode)) {
+                    matchedElements.append(element);
+                    if (firstMatchOnly)
+                        return;
+                    break;
+                }
+            }
+            if (element->firstChild()) {
+                n = element->firstChild();
+                continue;
+            }
+        }
+        while (!n->nextSibling()) {
+            n = n->parentNode();
+            if (n == rootNode)
+                return;
+        }
+        n = n->nextSibling();
+    }
+}
+
+SelectorQuery::SelectorQuery(const CSSSelectorList& selectorList)
+    : m_selectorList(selectorList)
+{
+    m_selectors.initialize(m_selectorList);
+}
+
+bool SelectorQuery::matches(Element* element) const
+{
+    return m_selectors.matches(element);
+}
+
+PassRefPtr<NodeList> SelectorQuery::queryAll(Node* rootNode) const
+{
+    return m_selectors.queryAll(rootNode);
+}
+
+PassRefPtr<Element> SelectorQuery::queryFirst(Node* rootNode) const
+{
+    return m_selectors.queryFirst(rootNode);
+}
+
+SelectorQuery* SelectorQueryCache::add(const AtomicString& selectors, Document* document, ExceptionCode& ec)
+{
+    HashMap<AtomicString, OwnPtr<SelectorQuery> >::iterator it = m_entries.find(selectors);
+    if (it != m_entries.end())
+        return it->value.get();
+
+    CSSParser parser(document);
+    CSSSelectorList selectorList;
+    parser.parseSelector(selectors, selectorList);
+
+    if (!selectorList.first() || selectorList.hasInvalidSelector()) {
+        ec = SYNTAX_ERR;
+        return 0;
+    }
+
+    // throw a NAMESPACE_ERR if the selector includes any namespace prefixes.
+    if (selectorList.selectorsNeedNamespaceResolution()) {
+        ec = NAMESPACE_ERR;
+        return 0;
+    }
+
+    const int maximumSelectorQueryCacheSize = 256;
+    if (m_entries.size() == maximumSelectorQueryCacheSize)
+        m_entries.remove(m_entries.begin());
+    
+    OwnPtr<SelectorQuery> selectorQuery = adoptPtr(new SelectorQuery(selectorList));
+    SelectorQuery* rawSelectorQuery = selectorQuery.get();
+    m_entries.add(selectors, selectorQuery.release());
+    return rawSelectorQuery;
+}
+
+void SelectorQueryCache::invalidate()
+{
+    m_entries.clear();
+}
+
+}
diff --git a/Source/core/dom/SelectorQuery.h b/Source/core/dom/SelectorQuery.h
new file mode 100644
index 0000000..779e782
--- /dev/null
+++ b/Source/core/dom/SelectorQuery.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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 SelectorQuery_h
+#define SelectorQuery_h
+
+#include "core/css/CSSSelectorList.h"
+#include <wtf/HashMap.h>
+#include <wtf/text/AtomicStringHash.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+typedef int ExceptionCode;
+    
+class CSSSelector;
+class Document;
+class Element;
+class Node;
+class NodeList;
+
+class SelectorDataList {
+public:
+    void initialize(const CSSSelectorList&);
+    bool matches(Element*) const;
+    PassRefPtr<NodeList> queryAll(Node* rootNode) const;
+    PassRefPtr<Element> queryFirst(Node* rootNode) const;
+
+private:
+    struct SelectorData {
+        SelectorData(const CSSSelector* selector, bool isFastCheckable) : selector(selector), isFastCheckable(isFastCheckable) { }
+        const CSSSelector* selector;
+        bool isFastCheckable;
+    };
+
+    bool selectorMatches(const SelectorData&, Element*, const Node*) const;
+    bool canUseIdLookup(Node* rootNode) const;
+    template <bool firstMatchOnly>
+    void execute(Node* rootNode, Vector<RefPtr<Node> >&) const;
+
+    Vector<SelectorData> m_selectors;
+};
+
+class SelectorQuery {
+    WTF_MAKE_NONCOPYABLE(SelectorQuery);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit SelectorQuery(const CSSSelectorList&);
+    bool matches(Element*) const;
+    PassRefPtr<NodeList> queryAll(Node* rootNode) const;
+    PassRefPtr<Element> queryFirst(Node* rootNode) const;
+private:
+    SelectorDataList m_selectors;
+    CSSSelectorList m_selectorList;
+};
+
+class SelectorQueryCache {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    SelectorQuery* add(const AtomicString&, Document*, ExceptionCode&);
+    void invalidate();
+
+private:
+    HashMap<AtomicString, OwnPtr<SelectorQuery> > m_entries;
+};
+
+}
+
+#endif
diff --git a/Source/core/dom/ShadowRoot.cpp b/Source/core/dom/ShadowRoot.cpp
new file mode 100644
index 0000000..48aa0ca
--- /dev/null
+++ b/Source/core/dom/ShadowRoot.cpp
@@ -0,0 +1,266 @@
+/*
+ * 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 "core/dom/ShadowRoot.h"
+
+#include "core/css/StyleResolver.h"
+#include "core/dom/ElementShadow.h"
+#include "core/dom/Text.h"
+#include "core/editing/markup.h"
+#include "core/html/shadow/ContentDistributor.h"
+#include "core/html/shadow/InsertionPoint.h"
+#include "RuntimeEnabledFeatures.h"
+#include "core/platform/HistogramSupport.h"
+
+namespace WebCore {
+
+struct SameSizeAsShadowRoot : public DocumentFragment, public TreeScope, public DoublyLinkedListNode<ShadowRoot> {
+    void* pointers[3];
+    unsigned countersAndFlags[1];
+};
+
+COMPILE_ASSERT(sizeof(ShadowRoot) == sizeof(SameSizeAsShadowRoot), shadowroot_should_stay_small);
+
+enum ShadowRootUsageOriginType {
+    ShadowRootUsageOriginWeb = 0,
+    ShadowRootUsageOriginNotWeb,
+    ShadowRootUsageOriginMax
+};
+
+ShadowRoot::ShadowRoot(Document* document, ShadowRootType type)
+    : DocumentFragment(0, CreateShadowRoot)
+    , TreeScope(this, document)
+    , m_prev(0)
+    , m_next(0)
+    , m_numberOfStyles(0)
+    , m_applyAuthorStyles(false)
+    , m_resetStyleInheritance(false)
+    , m_type(type)
+    , m_registeredWithParentShadowRoot(false)
+{
+    ASSERT(document);
+    ScriptWrappable::init(this);
+
+    if (type == ShadowRoot::AuthorShadowRoot) {
+        ShadowRootUsageOriginType usageType = document->url().protocolIsInHTTPFamily() ? ShadowRootUsageOriginWeb : ShadowRootUsageOriginNotWeb;
+        HistogramSupport::histogramEnumeration("WebCore.ShadowRoot.constructor", usageType, ShadowRootUsageOriginMax);
+    }
+}
+
+ShadowRoot::~ShadowRoot()
+{
+    ASSERT(!m_prev);
+    ASSERT(!m_next);
+
+    // We cannot let ContainerNode destructor call willBeDeletedFrom()
+    // for this ShadowRoot instance because TreeScope destructor
+    // clears Node::m_treeScope thus ContainerNode is no longer able
+    // to access it Document reference after that.
+    willBeDeletedFrom(documentInternal());
+
+    // We must remove all of our children first before the TreeScope destructor
+    // runs so we don't go through TreeScopeAdopter for each child with a
+    // destructed tree scope in each descendant.
+    removeDetachedChildren();
+
+    // We must call clearRareData() here since a ShadowRoot class inherits TreeScope
+    // as well as Node. See a comment on TreeScope.h for the reason.
+    if (hasRareData())
+        clearRareData();
+}
+
+void ShadowRoot::dispose()
+{
+    removeDetachedChildren();
+}
+
+PassRefPtr<Node> ShadowRoot::cloneNode(bool, ExceptionCode& ec)
+{
+    ec = DATA_CLONE_ERR;
+    return 0;
+}
+
+String ShadowRoot::innerHTML() const
+{
+    return createMarkup(this, ChildrenOnly);
+}
+
+void ShadowRoot::setInnerHTML(const String& markup, ExceptionCode& ec)
+{
+    if (isOrphan()) {
+        ec = INVALID_ACCESS_ERR;
+        return;
+    }
+
+    if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, host(), AllowScriptingContent, ec))
+        replaceChildrenWithFragment(this, fragment.release(), ec);
+}
+
+bool ShadowRoot::childTypeAllowed(NodeType type) const
+{
+    switch (type) {
+    case ELEMENT_NODE:
+    case PROCESSING_INSTRUCTION_NODE:
+    case COMMENT_NODE:
+    case TEXT_NODE:
+    case CDATA_SECTION_NODE:
+    case ENTITY_REFERENCE_NODE:
+        return true;
+    default:
+        return false;
+    }
+}
+
+void ShadowRoot::recalcStyle(StyleChange change)
+{
+    // ShadowRoot doesn't support custom callbacks.
+    ASSERT(!hasCustomStyleCallbacks());
+
+    StyleResolver* styleResolver = document()->styleResolver();
+    styleResolver->pushParentShadowRoot(this);
+
+    for (Node* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isElementNode())
+            toElement(child)->recalcStyle(change);
+        else if (child->isTextNode())
+            toText(child)->recalcTextStyle(change);
+    }
+
+    styleResolver->popParentShadowRoot(this);
+    clearNeedsStyleRecalc();
+    clearChildNeedsStyleRecalc();
+}
+
+void ShadowRoot::setApplyAuthorStyles(bool value)
+{
+    if (isOrphan())
+        return;
+
+    if (m_applyAuthorStyles != value) {
+        m_applyAuthorStyles = value;
+        host()->setNeedsStyleRecalc();
+    }
+}
+
+void ShadowRoot::setResetStyleInheritance(bool value)
+{
+    if (isOrphan())
+        return;
+
+    if (value != m_resetStyleInheritance) {
+        m_resetStyleInheritance = value;
+        if (attached() && owner())
+            owner()->recalcStyle(Force);
+    }
+}
+
+void ShadowRoot::attach()
+{
+    StyleResolver* styleResolver = document()->styleResolver();
+    styleResolver->pushParentShadowRoot(this);
+    DocumentFragment::attach();
+    styleResolver->popParentShadowRoot(this);
+}
+
+Node::InsertionNotificationRequest ShadowRoot::insertedInto(ContainerNode* insertionPoint)
+{
+    DocumentFragment::insertedInto(insertionPoint);
+
+    if (!insertionPoint->inDocument() || !isOldest())
+        return InsertionDone;
+
+    // FIXME: When parsing <video controls>, insertedInto() is called many times without invoking removedFrom.
+    // For now, we check m_registeredWithParentShadowroot. We would like to ASSERT(!m_registeredShadowRoot) here.
+    // https://bugs.webkit.org/show_bug.cig?id=101316
+    if (m_registeredWithParentShadowRoot)
+        return InsertionDone;
+
+    if (ShadowRoot* root = host()->containingShadowRoot()) {
+        root->ensureScopeDistribution()->registerElementShadow();
+        m_registeredWithParentShadowRoot = true;
+    }
+
+    return InsertionDone;
+}
+
+void ShadowRoot::removedFrom(ContainerNode* insertionPoint)
+{
+    if (insertionPoint->inDocument() && m_registeredWithParentShadowRoot) {
+        ShadowRoot* root = host()->containingShadowRoot();
+        if (!root)
+            root = insertionPoint->containingShadowRoot();
+
+        if (root && root->scopeDistribution())
+            root->scopeDistribution()->unregisterElementShadow();
+        m_registeredWithParentShadowRoot = false;
+    }
+
+    DocumentFragment::removedFrom(insertionPoint);
+}
+
+void ShadowRoot::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
+{
+    if (isOrphan())
+        return;
+
+    ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
+    owner()->invalidateDistribution();
+}
+
+void ShadowRoot::registerScopedHTMLStyleChild()
+{
+    ++m_numberOfStyles;
+    setHasScopedHTMLStyleChild(true);
+}
+
+void ShadowRoot::unregisterScopedHTMLStyleChild()
+{
+    ASSERT(hasScopedHTMLStyleChild() && m_numberOfStyles > 0);
+    --m_numberOfStyles;
+    setHasScopedHTMLStyleChild(m_numberOfStyles > 0);
+}
+
+ScopeContentDistribution* ShadowRoot::ensureScopeDistribution()
+{
+    if (m_scopeDistribution)
+        return m_scopeDistribution.get();
+
+    m_scopeDistribution = adoptPtr(new ScopeContentDistribution);
+    return m_scopeDistribution.get();
+}
+
+void ShadowRoot::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    DocumentFragment::reportMemoryUsage(memoryObjectInfo);
+    TreeScope::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_prev, "prev");
+    info.addMember(m_next, "next");
+    info.addMember(m_scopeDistribution, "scopeDistribution");
+}
+
+}
diff --git a/Source/core/dom/ShadowRoot.h b/Source/core/dom/ShadowRoot.h
new file mode 100644
index 0000000..ce1ce4c
--- /dev/null
+++ b/Source/core/dom/ShadowRoot.h
@@ -0,0 +1,143 @@
+/*
+ * 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 "core/dom/ContainerNode.h"
+#include "core/dom/Document.h"
+#include "core/dom/DocumentFragment.h"
+#include "core/dom/Element.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/TreeScope.h"
+#include <wtf/DoublyLinkedList.h>
+
+namespace WebCore {
+
+class ElementShadow;
+class ScopeContentDistribution;
+
+class ShadowRoot FINAL : public DocumentFragment, public TreeScope, public DoublyLinkedListNode<ShadowRoot> {
+    friend class WTF::DoublyLinkedListNode<ShadowRoot>;
+public:
+    // FIXME: We will support multiple shadow subtrees, however current implementation does not work well
+    // if a shadow root is dynamically created. So we prohibit multiple shadow subtrees
+    // in several elements for a while.
+    // See https://bugs.webkit.org/show_bug.cgi?id=77503 and related bugs.
+    enum ShadowRootType {
+        UserAgentShadowRoot = 0,
+        AuthorShadowRoot
+    };
+
+    static PassRefPtr<ShadowRoot> create(Document* document, ShadowRootType type)
+    {
+        return adoptRef(new ShadowRoot(document, type));
+    }
+
+    void recalcStyle(StyleChange);
+
+    virtual bool applyAuthorStyles() const OVERRIDE { return m_applyAuthorStyles; }
+    void setApplyAuthorStyles(bool);
+    virtual bool resetStyleInheritance() const OVERRIDE { return m_resetStyleInheritance; }
+    void setResetStyleInheritance(bool);
+
+    Element* host() const { return toElement(parentOrShadowHostNode()); }
+    ElementShadow* owner() const { return host() ? host()->shadow() : 0; }
+
+    String innerHTML() const;
+    void setInnerHTML(const String&, ExceptionCode&);
+
+    Element* activeElement() const;
+
+    ShadowRoot* youngerShadowRoot() const { return prev(); }
+    ShadowRoot* olderShadowRoot() const { return next(); }
+
+    bool isYoungest() const { return !youngerShadowRoot(); }
+    bool isOldest() const { return !olderShadowRoot(); }
+
+    virtual void attach();
+
+    virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
+    virtual void removedFrom(ContainerNode*) OVERRIDE;
+
+    virtual void registerScopedHTMLStyleChild() OVERRIDE;
+    virtual void unregisterScopedHTMLStyleChild() OVERRIDE;
+
+    ScopeContentDistribution* scopeDistribution() { return m_scopeDistribution.get(); }
+    const ScopeContentDistribution* scopeDistribution() const { return m_scopeDistribution.get(); }
+    ScopeContentDistribution* ensureScopeDistribution();
+
+    ShadowRootType type() const { return static_cast<ShadowRootType>(m_type); }
+
+    PassRefPtr<Node> cloneNode(bool, ExceptionCode&);
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+private:
+    ShadowRoot(Document*, ShadowRootType);
+    virtual ~ShadowRoot();
+
+    virtual void dispose() OVERRIDE;
+    virtual bool childTypeAllowed(NodeType) const OVERRIDE;
+    virtual void childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) OVERRIDE;
+
+    // ShadowRoots should never be cloned.
+    virtual PassRefPtr<Node> cloneNode(bool) OVERRIDE { return 0; }
+
+    // FIXME: This shouldn't happen. https://bugs.webkit.org/show_bug.cgi?id=88834
+    bool isOrphan() const { return !host(); }
+
+    ShadowRoot* m_prev;
+    ShadowRoot* m_next;
+    OwnPtr<ScopeContentDistribution> m_scopeDistribution;
+    unsigned m_numberOfStyles : 28;
+    unsigned m_applyAuthorStyles : 1;
+    unsigned m_resetStyleInheritance : 1;
+    unsigned m_type : 1;
+    unsigned m_registeredWithParentShadowRoot : 1;
+};
+
+inline Element* ShadowRoot::activeElement() const
+{
+    if (Node* node = treeScope()->focusedNode())
+        return node->isElementNode() ? toElement(node) : 0;
+    return 0;
+}
+
+inline const ShadowRoot* toShadowRoot(const Node* node)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isShadowRoot());
+    return static_cast<const ShadowRoot*>(node);
+}
+
+inline ShadowRoot* toShadowRoot(Node* node)
+{
+    return const_cast<ShadowRoot*>(toShadowRoot(static_cast<const Node*>(node)));
+}
+
+} // namespace
+
+#endif
diff --git a/Source/core/dom/ShadowRoot.idl b/Source/core/dom/ShadowRoot.idl
new file mode 100644
index 0000000..8d95548
--- /dev/null
+++ b/Source/core/dom/ShadowRoot.idl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+interface ShadowRoot : DocumentFragment {
+    readonly attribute Element activeElement;
+    attribute boolean applyAuthorStyles;
+    attribute boolean resetStyleInheritance;
+
+    [TreatNullAs=NullString, DeliverCustomElementCallbacks, PerWorldBindings, ActivityLog=SetterForIsolatedWorlds, SetterRaisesException] attribute DOMString innerHTML;
+
+    [RaisesException] Node cloneNode([Default=Undefined] optional boolean deep);
+    DOMSelection getSelection();
+    Element getElementById([Default=Undefined] optional DOMString elementId);
+    NodeList getElementsByClassName([Default=Undefined] optional DOMString className);
+    NodeList getElementsByTagName([Default=Undefined] optional DOMString tagName);
+    NodeList getElementsByTagNameNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
+                                    [Default=Undefined] optional DOMString localName);
+
+    Element elementFromPoint([Default=Undefined] optional long x, 
+                             [Default=Undefined] optional long y);
+};
diff --git a/Source/core/dom/SimulatedClickOptions.h b/Source/core/dom/SimulatedClickOptions.h
new file mode 100644
index 0000000..a49ed74
--- /dev/null
+++ b/Source/core/dom/SimulatedClickOptions.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SimulatedClickOptions_h
+#define SimulatedClickOptions_h
+
+namespace WebCore {
+
+enum SimulatedClickMouseEventOptions {
+    SendNoEvents,
+    SendMouseUpDownEvents,
+    SendMouseOverUpDownEvents
+};
+
+enum SimulatedClickVisualOptions {
+    DoNotShowPressedLook,
+    ShowPressedLook
+};
+
+} // namespace WebCore
+
+#endif // SimulatedClickOptions_h
diff --git a/Source/core/dom/SpaceSplitString.cpp b/Source/core/dom/SpaceSplitString.cpp
new file mode 100644
index 0000000..4af9a1c
--- /dev/null
+++ b/Source/core/dom/SpaceSplitString.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2007 David Smith (catfish.man@gmail.com)
+ * Copyright (C) 2007, 2008, 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "core/dom/SpaceSplitString.h"
+
+#include "core/html/parser/HTMLParserIdioms.h"
+#include <wtf/ASCIICType.h>
+#include <wtf/HashMap.h>
+#include <wtf/text/AtomicStringHash.h>
+#include <wtf/text/StringBuilder.h>
+
+using namespace WTF;
+
+namespace WebCore {
+
+template <typename CharacterType>
+static inline bool hasNonASCIIOrUpper(const CharacterType* characters, unsigned length)
+{
+    bool hasUpper = false;
+    CharacterType ored = 0;
+    for (unsigned i = 0; i < length; i++) {
+        CharacterType c = characters[i];
+        hasUpper |= isASCIIUpper(c);
+        ored |= c;
+    }
+    return hasUpper || (ored & ~0x7F);
+}
+
+static inline bool hasNonASCIIOrUpper(const String& string)
+{
+    unsigned length = string.length();
+
+    if (string.is8Bit())
+        return hasNonASCIIOrUpper(string.characters8(), length);
+    return hasNonASCIIOrUpper(string.characters16(), length);
+}
+
+template <typename CharacterType>
+inline void SpaceSplitStringData::createVector(const CharacterType* characters, unsigned length)
+{
+    unsigned start = 0;
+    while (true) {
+        while (start < length && isHTMLSpace(characters[start]))
+            ++start;
+        if (start >= length)
+            break;
+        unsigned end = start + 1;
+        while (end < length && isNotHTMLSpace(characters[end]))
+            ++end;
+
+        m_vector.append(AtomicString(characters + start, end - start));
+
+        start = end + 1;
+    }
+}
+
+void SpaceSplitStringData::createVector(const String& string)
+{
+    unsigned length = string.length();
+
+    if (string.is8Bit()) {
+        createVector(string.characters8(), length);
+        return;
+    }
+
+    createVector(string.characters16(), length);
+}
+
+bool SpaceSplitStringData::containsAll(SpaceSplitStringData& other)
+{
+    if (this == &other)
+        return true;
+
+    size_t thisSize = m_vector.size();
+    size_t otherSize = other.m_vector.size();
+    for (size_t i = 0; i < otherSize; ++i) {
+        const AtomicString& name = other.m_vector[i];
+        size_t j;
+        for (j = 0; j < thisSize; ++j) {
+            if (m_vector[j] == name)
+                break;
+        }
+        if (j == thisSize)
+            return false;
+    }
+    return true;
+}
+
+void SpaceSplitStringData::add(const AtomicString& string)
+{
+    ASSERT(hasOneRef());
+    ASSERT(!contains(string));
+    m_vector.append(string);
+}
+
+void SpaceSplitStringData::remove(unsigned index)
+{
+    ASSERT(hasOneRef());
+    m_vector.remove(index);
+}
+
+void SpaceSplitString::add(const AtomicString& string)
+{
+    // FIXME: add() does not allow duplicates but createVector() does.
+    if (contains(string))
+        return;
+    ensureUnique();
+    if (m_data)
+        m_data->add(string);
+}
+
+bool SpaceSplitString::remove(const AtomicString& string)
+{
+    if (!m_data)
+        return false;
+    unsigned i = 0;
+    bool changed = false;
+    while (i < m_data->size()) {
+        if ((*m_data)[i] == string) {
+            if (!changed)
+                ensureUnique();
+            m_data->remove(i);
+            changed = true;
+            continue;
+        }
+        ++i;
+    }
+    return changed;
+}
+
+typedef HashMap<AtomicString, SpaceSplitStringData*> SpaceSplitStringDataMap;
+
+static SpaceSplitStringDataMap& sharedDataMap()
+{
+    DEFINE_STATIC_LOCAL(SpaceSplitStringDataMap, map, ());
+    return map;
+}
+
+void SpaceSplitString::set(const AtomicString& inputString, bool shouldFoldCase)
+{
+    if (inputString.isNull()) {
+        clear();
+        return;
+    }
+
+    String string(inputString.string());
+    if (shouldFoldCase && hasNonASCIIOrUpper(string))
+        string = string.foldCase();
+
+    m_data = SpaceSplitStringData::create(string);
+}
+
+SpaceSplitStringData::~SpaceSplitStringData()
+{
+    if (!m_keyString.isNull())
+        sharedDataMap().remove(m_keyString);
+}
+
+PassRefPtr<SpaceSplitStringData> SpaceSplitStringData::create(const AtomicString& string)
+{
+    SpaceSplitStringData*& data = sharedDataMap().add(string, 0).iterator->value;
+    if (!data) {
+        data = new SpaceSplitStringData(string);
+        return adoptRef(data);
+    }
+    return data;
+}
+
+PassRefPtr<SpaceSplitStringData> SpaceSplitStringData::createUnique(const SpaceSplitStringData& other)
+{
+    return adoptRef(new SpaceSplitStringData(other));
+}
+
+SpaceSplitStringData::SpaceSplitStringData(const AtomicString& string)
+    : m_keyString(string)
+{
+    ASSERT(!string.isNull());
+    createVector(string);
+}
+
+SpaceSplitStringData::SpaceSplitStringData(const SpaceSplitStringData& other)
+    : RefCounted<SpaceSplitStringData>()
+    , m_vector(other.m_vector)
+{
+    // Note that we don't copy m_keyString to indicate to the destructor that there's nothing
+    // to be removed from the sharedDataMap().
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/SpaceSplitString.h b/Source/core/dom/SpaceSplitString.h
new file mode 100644
index 0000000..53b588f
--- /dev/null
+++ b/Source/core/dom/SpaceSplitString.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2007, 2008, 2010, 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef SpaceSplitString_h
+#define SpaceSplitString_h
+
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+    class SpaceSplitStringData : public RefCounted<SpaceSplitStringData> {
+    public:
+        static PassRefPtr<SpaceSplitStringData> create(const AtomicString&);
+        static PassRefPtr<SpaceSplitStringData> createUnique(const SpaceSplitStringData&);
+
+        ~SpaceSplitStringData();
+
+        bool contains(const AtomicString& string)
+        {
+            size_t size = m_vector.size();
+            for (size_t i = 0; i < size; ++i) {
+                if (m_vector[i] == string)
+                    return true;
+            }
+            return false;
+        }
+
+        bool containsAll(SpaceSplitStringData&);
+
+        void add(const AtomicString&);
+        void remove(unsigned index);
+
+        bool isUnique() const { return m_keyString.isNull(); } 
+        size_t size() const { return m_vector.size(); }
+        const AtomicString& operator[](size_t i) { ASSERT_WITH_SECURITY_IMPLICATION(i < size()); return m_vector[i]; }
+
+    private:
+        explicit SpaceSplitStringData(const AtomicString&);
+        explicit SpaceSplitStringData(const SpaceSplitStringData&);
+
+        void createVector(const String&);
+        template <typename CharacterType>
+        inline void createVector(const CharacterType*, unsigned);
+
+        AtomicString m_keyString;
+        Vector<AtomicString, 4> m_vector;
+    };
+
+    class SpaceSplitString {
+    public:
+        SpaceSplitString() { }
+        SpaceSplitString(const AtomicString& string, bool shouldFoldCase) { set(string, shouldFoldCase); }
+
+        bool operator!=(const SpaceSplitString& other) const { return m_data != other.m_data; }
+
+        void set(const AtomicString&, bool shouldFoldCase);
+        void clear() { m_data.clear(); }
+
+        bool contains(const AtomicString& string) const { return m_data && m_data->contains(string); }
+        bool containsAll(const SpaceSplitString& names) const { return !names.m_data || (m_data && m_data->containsAll(*names.m_data)); }
+        void add(const AtomicString&);
+        bool remove(const AtomicString&);
+
+        size_t size() const { return m_data ? m_data->size() : 0; }
+        bool isNull() const { return !m_data; }
+        const AtomicString& operator[](size_t i) const { ASSERT_WITH_SECURITY_IMPLICATION(i < size()); return (*m_data)[i]; }
+
+    private:
+        void ensureUnique()
+        {
+            if (m_data && !m_data->isUnique())
+                m_data = SpaceSplitStringData::createUnique(*m_data);
+        }
+
+        RefPtr<SpaceSplitStringData> m_data;
+    };
+
+} // namespace WebCore
+
+#endif // SpaceSplitString_h
diff --git a/Source/core/dom/StaticNodeList.cpp b/Source/core/dom/StaticNodeList.cpp
new file mode 100644
index 0000000..10f4b28
--- /dev/null
+++ b/Source/core/dom/StaticNodeList.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007, 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "core/dom/StaticNodeList.h"
+
+#include "core/dom/Element.h"
+
+namespace WebCore {
+
+unsigned StaticNodeList::length() const
+{
+    return m_nodes.size();
+}
+
+Node* StaticNodeList::item(unsigned index) const
+{
+    if (index < m_nodes.size())
+        return m_nodes[index].get();
+    return 0;
+}
+
+Node* StaticNodeList::namedItem(const AtomicString& elementId) const
+{
+    size_t length = m_nodes.size();
+    for (size_t i = 0; i < length; ++i) {
+        Node* node = m_nodes[i].get();
+        if (node->isElementNode() && toElement(node)->getIdAttribute() == elementId)
+            return node;
+    }
+
+    return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/StaticNodeList.h b/Source/core/dom/StaticNodeList.h
new file mode 100644
index 0000000..823f48f
--- /dev/null
+++ b/Source/core/dom/StaticNodeList.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 StaticNodeList_h
+#define StaticNodeList_h
+
+#include "core/dom/NodeList.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+    class Node;
+
+    class StaticNodeList : public NodeList {
+    public:
+        static PassRefPtr<StaticNodeList> adopt(Vector<RefPtr<Node> >& nodes)
+        {
+            RefPtr<StaticNodeList> nodeList = adoptRef(new StaticNodeList);
+            nodeList->m_nodes.swap(nodes);
+            return nodeList.release();
+        }
+
+        static PassRefPtr<StaticNodeList> createEmpty()
+        {
+            return adoptRef(new StaticNodeList);
+        }
+
+        virtual unsigned length() const OVERRIDE;
+        virtual Node* item(unsigned index) const OVERRIDE;
+        virtual Node* namedItem(const AtomicString&) const OVERRIDE;
+
+    private:
+        StaticNodeList() { }
+
+        Vector<RefPtr<Node> > m_nodes;
+    };
+
+} // namespace WebCore
+
+#endif // StaticNodeList_h
diff --git a/Source/core/dom/StringCallback.cpp b/Source/core/dom/StringCallback.cpp
new file mode 100644
index 0000000..687821e
--- /dev/null
+++ b/Source/core/dom/StringCallback.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/StringCallback.h"
+
+#include "core/dom/ScriptExecutionContext.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+namespace {
+
+class DispatchCallbackTask : public ScriptExecutionContext::Task {
+public:
+    static PassOwnPtr<DispatchCallbackTask> create(PassRefPtr<StringCallback> callback, const String& data)
+    {
+        return adoptPtr(new DispatchCallbackTask(callback, data));
+    }
+
+    virtual void performTask(ScriptExecutionContext*)
+    {
+        m_callback->handleEvent(m_data);
+    }
+
+private:
+    DispatchCallbackTask(PassRefPtr<StringCallback> callback, const String& data)
+        : m_callback(callback)
+        , m_data(data)
+    {
+    }
+
+    RefPtr<StringCallback> m_callback;
+    const String m_data;
+};
+
+} // namespace
+
+void StringCallback::scheduleCallback(ScriptExecutionContext* context, const String& data)
+{
+    context->postTask(DispatchCallbackTask::create(this, data));
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/StringCallback.h b/Source/core/dom/StringCallback.h
new file mode 100644
index 0000000..92e83e2
--- /dev/null
+++ b/Source/core/dom/StringCallback.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StringCallback_h
+#define StringCallback_h
+
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class ScriptExecutionContext;
+
+class StringCallback : public RefCounted<StringCallback> {
+public:
+    virtual ~StringCallback() { }
+    virtual bool handleEvent(const String& data) = 0;
+
+    // Helper to post callback task.
+    void scheduleCallback(ScriptExecutionContext*, const String& data);
+};
+
+} // namespace WebCore
+
+#endif // StringCallback_h
diff --git a/Source/core/dom/StringCallback.idl b/Source/core/dom/StringCallback.idl
new file mode 100644
index 0000000..9ab79c1
--- /dev/null
+++ b/Source/core/dom/StringCallback.idl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+callback interface StringCallback {
+    boolean handleEvent(DOMString data);
+};
diff --git a/Source/core/dom/StyleElement.cpp b/Source/core/dom/StyleElement.cpp
new file mode 100644
index 0000000..0d961aa
--- /dev/null
+++ b/Source/core/dom/StyleElement.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2006, 2007 Rob Buis
+ * Copyright (C) 2008 Apple, Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/StyleElement.h"
+
+#include "core/css/MediaList.h"
+#include "core/css/MediaQueryEvaluator.h"
+#include "core/css/StyleSheetContents.h"
+#include "core/dom/Attribute.h"
+#include "core/dom/Document.h"
+#include "core/dom/DocumentStyleSheetCollection.h"
+#include "core/dom/Element.h"
+#include "core/dom/ScriptableDocumentParser.h"
+#include "core/page/ContentSecurityPolicy.h"
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/TextPosition.h>
+
+namespace WebCore {
+
+static bool isValidStyleChild(Node* node)
+{
+    ASSERT(node);
+    Node::NodeType nodeType = node->nodeType();
+    return nodeType == Node::TEXT_NODE || nodeType == Node::CDATA_SECTION_NODE;
+}
+
+static bool isCSS(Element* element, const AtomicString& type)
+{
+    return type.isEmpty() || (element->isHTMLElement() ? equalIgnoringCase(type, "text/css") : (type == "text/css"));
+}
+
+StyleElement::StyleElement(Document* document, bool createdByParser)
+    : m_createdByParser(createdByParser)
+    , m_loading(false)
+    , m_startLineNumber(WTF::OrdinalNumber::beforeFirst())
+{
+    if (createdByParser && document && document->scriptableDocumentParser() && !document->isInDocumentWrite())
+        m_startLineNumber = document->scriptableDocumentParser()->lineNumber();
+}
+
+StyleElement::~StyleElement()
+{
+}
+
+void StyleElement::insertedIntoDocument(Document* document, Element* element)
+{
+    ASSERT(document);
+    ASSERT(element);
+    document->styleSheetCollection()->addStyleSheetCandidateNode(element, m_createdByParser);
+    if (m_createdByParser)
+        return;
+
+    process(element);
+}
+
+void StyleElement::removedFromDocument(Document* document, Element* element)
+{
+    ASSERT(document);
+    ASSERT(element);
+    document->styleSheetCollection()->removeStyleSheetCandidateNode(element);
+
+    if (m_sheet)
+        clearSheet();
+
+    // If we're in document teardown, then we don't need to do any notification of our sheet's removal.
+    if (document->renderer())
+        document->styleResolverChanged(DeferRecalcStyle);
+}
+
+void StyleElement::clearDocumentData(Document* document, Element* element)
+{
+    if (m_sheet)
+        m_sheet->clearOwnerNode();
+
+    if (element->inDocument())
+        document->styleSheetCollection()->removeStyleSheetCandidateNode(element);
+}
+
+void StyleElement::childrenChanged(Element* element)
+{
+    ASSERT(element);
+    if (m_createdByParser)
+        return;
+
+    process(element);
+}
+
+void StyleElement::finishParsingChildren(Element* element)
+{
+    ASSERT(element);
+    process(element);
+    m_createdByParser = false;
+}
+
+void StyleElement::process(Element* e)
+{
+    if (!e || !e->inDocument())
+        return;
+
+    unsigned resultLength = 0;
+    for (Node* c = e->firstChild(); c; c = c->nextSibling()) {
+        if (isValidStyleChild(c)) {
+            unsigned length = c->nodeValue().length();
+            if (length > std::numeric_limits<unsigned>::max() - resultLength) {
+                createSheet(e, m_startLineNumber, "");
+                return;
+            }
+            resultLength += length;
+        }
+    }
+    StringBuilder sheetText;
+    sheetText.reserveCapacity(resultLength);
+
+    for (Node* c = e->firstChild(); c; c = c->nextSibling()) {
+        if (isValidStyleChild(c)) {
+            sheetText.append(c->nodeValue());
+        }
+    }
+    ASSERT(sheetText.length() == resultLength);
+
+    createSheet(e, m_startLineNumber, sheetText.toString());
+}
+
+void StyleElement::clearSheet()
+{
+    ASSERT(m_sheet);
+    m_sheet.release()->clearOwnerNode();
+}
+
+void StyleElement::createSheet(Element* e, WTF::OrdinalNumber startLineNumber, const String& text)
+{
+    ASSERT(e);
+    ASSERT(e->inDocument());
+    Document* document = e->document();
+    if (m_sheet) {
+        if (m_sheet->isLoading())
+            document->styleSheetCollection()->removePendingSheet();
+        clearSheet();
+    }
+
+    // If type is empty or CSS, this is a CSS style sheet.
+    const AtomicString& type = this->type();
+    if (document->contentSecurityPolicy()->allowInlineStyle(e->document()->url(), startLineNumber) && isCSS(e, type)) {
+        RefPtr<MediaQuerySet> mediaQueries;
+        if (e->isHTMLElement())
+            mediaQueries = MediaQuerySet::createAllowingDescriptionSyntax(media());
+        else
+            mediaQueries = MediaQuerySet::create(media());
+
+        MediaQueryEvaluator screenEval("screen", true);
+        MediaQueryEvaluator printEval("print", true);
+        if (screenEval.eval(mediaQueries.get()) || printEval.eval(mediaQueries.get())) {
+            document->styleSheetCollection()->addPendingSheet();
+            m_loading = true;
+
+            m_sheet = CSSStyleSheet::createInline(e, KURL(), document->inputEncoding());
+            m_sheet->setMediaQueries(mediaQueries.release());
+            m_sheet->setTitle(e->title());
+            m_sheet->contents()->parseStringAtLine(text, startLineNumber.zeroBasedInt(), m_createdByParser);
+
+            m_loading = false;
+        }
+    }
+
+    if (m_sheet)
+        m_sheet->contents()->checkLoaded();
+}
+
+bool StyleElement::isLoading() const
+{
+    if (m_loading)
+        return true;
+    return m_sheet ? m_sheet->isLoading() : false;
+}
+
+bool StyleElement::sheetLoaded(Document* document)
+{
+    ASSERT(document);
+    if (isLoading())
+        return false;
+
+    document->styleSheetCollection()->removePendingSheet();
+    return true;
+}
+
+void StyleElement::startLoadingDynamicSheet(Document* document)
+{
+    ASSERT(document);
+    document->styleSheetCollection()->addPendingSheet();
+}
+
+}
diff --git a/Source/core/dom/StyleElement.h b/Source/core/dom/StyleElement.h
new file mode 100644
index 0000000..83c8b9b
--- /dev/null
+++ b/Source/core/dom/StyleElement.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2006, 2007 Rob Buis
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyleElement_h
+#define StyleElement_h
+
+#include "core/css/CSSStyleSheet.h"
+#include <wtf/text/TextPosition.h>
+
+namespace WebCore {
+
+class Document;
+class Element;
+
+class StyleElement {
+public:
+    StyleElement(Document*, bool createdByParser);
+    virtual ~StyleElement();
+
+protected:
+    virtual const AtomicString& type() const = 0;
+    virtual const AtomicString& media() const = 0;
+
+    CSSStyleSheet* sheet() const { return m_sheet.get(); }
+
+    bool isLoading() const;
+    bool sheetLoaded(Document*);
+    void startLoadingDynamicSheet(Document*);
+
+    void insertedIntoDocument(Document*, Element*);
+    void removedFromDocument(Document*, Element*);
+    void clearDocumentData(Document*, Element*);
+    void childrenChanged(Element*);
+    void finishParsingChildren(Element*);
+
+    RefPtr<CSSStyleSheet> m_sheet;
+
+private:
+    void createSheet(Element*, WTF::OrdinalNumber startLineNumber, const String& text = String());
+    void process(Element*);
+    void clearSheet();
+
+    bool m_createdByParser;
+    bool m_loading;
+    WTF::OrdinalNumber m_startLineNumber;
+};
+
+}
+
+#endif
diff --git a/Source/core/dom/StyledElement.cpp b/Source/core/dom/StyledElement.cpp
new file mode 100644
index 0000000..a329f7f
--- /dev/null
+++ b/Source/core/dom/StyledElement.cpp
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Peter Kelly (pmk@post.com)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2008, 2010 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/StyledElement.h"
+
+#include "CSSPropertyNames.h"
+#include "CSSValueKeywords.h"
+#include "HTMLNames.h"
+#include "core/css/CSSImageValue.h"
+#include "core/css/CSSParser.h"
+#include "core/css/CSSStyleSheet.h"
+#include "core/css/CSSValuePool.h"
+#include "core/css/PropertySetCSSStyleDeclaration.h"
+#include "core/css/StylePropertySet.h"
+#include "core/css/StyleResolver.h"
+#include "core/dom/Attribute.h"
+#include "core/dom/Document.h"
+#include "core/dom/ScriptableDocumentParser.h"
+#include "core/html/ClassList.h"
+#include "core/html/DOMTokenList.h"
+#include "core/html/parser/HTMLParserIdioms.h"
+#include "core/page/ContentSecurityPolicy.h"
+#include "core/platform/graphics/Color.h"
+#include <wtf/HashFunctions.h>
+#include <wtf/text/TextPosition.h>
+
+using namespace std;
+
+namespace WebCore {
+
+COMPILE_ASSERT(sizeof(StyledElement) == sizeof(Element), styledelement_should_remain_same_size_as_element);
+
+using namespace HTMLNames;
+
+struct PresentationAttributeCacheKey {
+    PresentationAttributeCacheKey() : tagName(0) { }
+    AtomicStringImpl* tagName;
+    // Only the values need refcounting.
+    Vector<pair<AtomicStringImpl*, AtomicString>, 3> attributesAndValues;
+};
+
+struct PresentationAttributeCacheEntry {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    PresentationAttributeCacheKey key;
+    RefPtr<StylePropertySet> value;
+};
+
+typedef HashMap<unsigned, OwnPtr<PresentationAttributeCacheEntry>, AlreadyHashed> PresentationAttributeCache;
+    
+static bool operator!=(const PresentationAttributeCacheKey& a, const PresentationAttributeCacheKey& b)
+{
+    if (a.tagName != b.tagName)
+        return true;
+    return a.attributesAndValues != b.attributesAndValues;
+}
+
+static PresentationAttributeCache& presentationAttributeCache()
+{
+    DEFINE_STATIC_LOCAL(PresentationAttributeCache, cache, ());
+    return cache;
+}
+
+class PresentationAttributeCacheCleaner {
+    WTF_MAKE_NONCOPYABLE(PresentationAttributeCacheCleaner); WTF_MAKE_FAST_ALLOCATED;
+public:
+    PresentationAttributeCacheCleaner()
+        : m_cleanTimer(this, &PresentationAttributeCacheCleaner::cleanCache)
+    {
+    }
+
+    void didHitPresentationAttributeCache()
+    {
+        if (presentationAttributeCache().size() < minimumPresentationAttributeCacheSizeForCleaning)
+            return;
+
+        m_hitCount++;
+
+        if (!m_cleanTimer.isActive())
+            m_cleanTimer.startOneShot(presentationAttributeCacheCleanTimeInSeconds);
+     }
+
+private:
+    static const unsigned presentationAttributeCacheCleanTimeInSeconds = 60;
+    static const int minimumPresentationAttributeCacheSizeForCleaning = 100;
+    static const unsigned minimumPresentationAttributeCacheHitCountPerMinute = (100 * presentationAttributeCacheCleanTimeInSeconds) / 60;
+
+    void cleanCache(Timer<PresentationAttributeCacheCleaner>* timer)
+    {
+        ASSERT_UNUSED(timer, timer == &m_cleanTimer);
+        unsigned hitCount = m_hitCount;
+        m_hitCount = 0;
+        if (hitCount > minimumPresentationAttributeCacheHitCountPerMinute)
+            return;
+        presentationAttributeCache().clear();
+    }
+
+    unsigned m_hitCount;
+    Timer<PresentationAttributeCacheCleaner> m_cleanTimer;
+};
+
+static PresentationAttributeCacheCleaner& presentationAttributeCacheCleaner()
+{
+    DEFINE_STATIC_LOCAL(PresentationAttributeCacheCleaner, cleaner, ());
+    return cleaner;
+}
+
+void StyledElement::synchronizeStyleAttributeInternal() const
+{
+    ASSERT(elementData());
+    ASSERT(elementData()->m_styleAttributeIsDirty);
+    elementData()->m_styleAttributeIsDirty = false;
+    if (const StylePropertySet* inlineStyle = this->inlineStyle())
+        const_cast<StyledElement*>(this)->setSynchronizedLazyAttribute(styleAttr, inlineStyle->asText());
+}
+
+StyledElement::~StyledElement()
+{
+    if (PropertySetCSSStyleDeclaration* cssomWrapper = inlineStyleCSSOMWrapper())
+        cssomWrapper->clearParentElement();
+}
+
+CSSStyleDeclaration* StyledElement::style()
+{
+    return ensureMutableInlineStyle()->ensureInlineCSSStyleDeclaration(this);
+}
+
+MutableStylePropertySet* StyledElement::ensureMutableInlineStyle()
+{
+    RefPtr<StylePropertySet>& inlineStyle = ensureUniqueElementData()->m_inlineStyle;
+    if (!inlineStyle)
+        inlineStyle = StylePropertySet::create(strictToCSSParserMode(isHTMLElement() && !document()->inQuirksMode()));
+    else if (!inlineStyle->isMutable())
+        inlineStyle = inlineStyle->copy();
+    ASSERT(inlineStyle->isMutable());
+    return static_cast<MutableStylePropertySet*>(inlineStyle.get());
+}
+
+void StyledElement::attributeChanged(const QualifiedName& name, const AtomicString& newValue, AttributeModificationReason reason)
+{
+    if (name == styleAttr)
+        styleAttributeChanged(newValue, reason);
+    else if (isPresentationAttribute(name)) {
+        elementData()->m_presentationAttributeStyleIsDirty = true;
+        setNeedsStyleRecalc(InlineStyleChange);
+    }
+
+    Element::attributeChanged(name, newValue, reason);
+}
+
+PropertySetCSSStyleDeclaration* StyledElement::inlineStyleCSSOMWrapper()
+{
+    if (!inlineStyle() || !inlineStyle()->hasCSSOMWrapper())
+        return 0;
+    PropertySetCSSStyleDeclaration* cssomWrapper = ensureUniqueElementData()->m_inlineStyle->cssStyleDeclaration();
+    ASSERT(cssomWrapper && cssomWrapper->parentElement() == this);
+    return cssomWrapper;
+}
+
+inline void StyledElement::setInlineStyleFromString(const AtomicString& newStyleString)
+{
+    RefPtr<StylePropertySet>& inlineStyle = elementData()->m_inlineStyle;
+
+    // Avoid redundant work if we're using shared attribute data with already parsed inline style.
+    if (inlineStyle && !elementData()->isUnique())
+        return;
+
+    // We reconstruct the property set instead of mutating if there is no CSSOM wrapper.
+    // This makes wrapperless property sets immutable and so cacheable.
+    if (inlineStyle && !inlineStyle->isMutable())
+        inlineStyle.clear();
+
+    if (!inlineStyle)
+        inlineStyle = CSSParser::parseInlineStyleDeclaration(newStyleString, this);
+    else
+        inlineStyle->parseDeclaration(newStyleString, document()->elementSheet()->contents());
+}
+
+void StyledElement::styleAttributeChanged(const AtomicString& newStyleString, AttributeModificationReason modificationReason)
+{
+    WTF::OrdinalNumber startLineNumber = WTF::OrdinalNumber::beforeFirst();
+    if (document() && document()->scriptableDocumentParser() && !document()->isInDocumentWrite())
+        startLineNumber = document()->scriptableDocumentParser()->lineNumber();
+
+    if (newStyleString.isNull()) {
+        if (PropertySetCSSStyleDeclaration* cssomWrapper = inlineStyleCSSOMWrapper())
+            cssomWrapper->clearParentElement();
+        ensureUniqueElementData()->m_inlineStyle.clear();
+    } else if (modificationReason == ModifiedByCloning || document()->contentSecurityPolicy()->allowInlineStyle(document()->url(), startLineNumber))
+        setInlineStyleFromString(newStyleString);
+
+    elementData()->m_styleAttributeIsDirty = false;
+
+    setNeedsStyleRecalc(InlineStyleChange);
+    InspectorInstrumentation::didInvalidateStyleAttr(document(), this);
+}
+
+void StyledElement::inlineStyleChanged()
+{
+    setNeedsStyleRecalc(InlineStyleChange);
+    ASSERT(elementData());
+    elementData()->m_styleAttributeIsDirty = true;
+    InspectorInstrumentation::didInvalidateStyleAttr(document(), this);
+}
+    
+bool StyledElement::setInlineStyleProperty(CSSPropertyID propertyID, int identifier, bool important)
+{
+    ensureMutableInlineStyle()->setProperty(propertyID, cssValuePool().createIdentifierValue(identifier), important);
+    inlineStyleChanged();
+    return true;
+}
+
+bool StyledElement::setInlineStyleProperty(CSSPropertyID propertyID, double value, CSSPrimitiveValue::UnitTypes unit, bool important)
+{
+    ensureMutableInlineStyle()->setProperty(propertyID, cssValuePool().createValue(value, unit), important);
+    inlineStyleChanged();
+    return true;
+}
+
+bool StyledElement::setInlineStyleProperty(CSSPropertyID propertyID, const String& value, bool important)
+{
+    bool changes = ensureMutableInlineStyle()->setProperty(propertyID, value, important, document()->elementSheet()->contents());
+    if (changes)
+        inlineStyleChanged();
+    return changes;
+}
+
+bool StyledElement::removeInlineStyleProperty(CSSPropertyID propertyID)
+{
+    if (!inlineStyle())
+        return false;
+    bool changes = ensureMutableInlineStyle()->removeProperty(propertyID);
+    if (changes)
+        inlineStyleChanged();
+    return changes;
+}
+
+void StyledElement::removeAllInlineStyleProperties()
+{
+    if (!inlineStyle() || inlineStyle()->isEmpty())
+        return;
+    ensureMutableInlineStyle()->clear();
+    inlineStyleChanged();
+}
+
+void StyledElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
+{
+    if (const StylePropertySet* inlineStyle = elementData() ? elementData()->inlineStyle() : 0)
+        inlineStyle->addSubresourceStyleURLs(urls, document()->elementSheet()->contents());
+}
+
+static inline bool attributeNameSort(const pair<AtomicStringImpl*, AtomicString>& p1, const pair<AtomicStringImpl*, AtomicString>& p2)
+{
+    // Sort based on the attribute name pointers. It doesn't matter what the order is as long as it is always the same. 
+    return p1.first < p2.first;
+}
+
+void StyledElement::makePresentationAttributeCacheKey(PresentationAttributeCacheKey& result) const
+{    
+    // FIXME: Enable for SVG.
+    if (namespaceURI() != xhtmlNamespaceURI)
+        return;
+    // Interpretation of the size attributes on <input> depends on the type attribute.
+    if (hasTagName(inputTag))
+        return;
+    unsigned size = attributeCount();
+    for (unsigned i = 0; i < size; ++i) {
+        const Attribute* attribute = attributeItem(i);
+        if (!isPresentationAttribute(attribute->name()))
+            continue;
+        if (!attribute->namespaceURI().isNull())
+            return;
+        // FIXME: Background URL may depend on the base URL and can't be shared. Disallow caching.
+        if (attribute->name() == backgroundAttr)
+            return;
+        result.attributesAndValues.append(make_pair(attribute->localName().impl(), attribute->value()));
+    }
+    if (result.attributesAndValues.isEmpty())
+        return;
+    // Attribute order doesn't matter. Sort for easy equality comparison.
+    std::sort(result.attributesAndValues.begin(), result.attributesAndValues.end(), attributeNameSort);
+    // The cache key is non-null when the tagName is set.
+    result.tagName = localName().impl();
+}
+
+static unsigned computePresentationAttributeCacheHash(const PresentationAttributeCacheKey& key)
+{
+    if (!key.tagName)
+        return 0;
+    ASSERT(key.attributesAndValues.size());
+    unsigned attributeHash = StringHasher::hashMemory(key.attributesAndValues.data(), key.attributesAndValues.size() * sizeof(key.attributesAndValues[0]));
+    return WTF::pairIntHash(key.tagName->existingHash(), attributeHash);
+}
+
+void StyledElement::rebuildPresentationAttributeStyle()
+{
+    PresentationAttributeCacheKey cacheKey;
+    makePresentationAttributeCacheKey(cacheKey);
+
+    unsigned cacheHash = computePresentationAttributeCacheHash(cacheKey);
+
+    PresentationAttributeCache::iterator cacheIterator;
+    if (cacheHash) {
+        cacheIterator = presentationAttributeCache().add(cacheHash, nullptr).iterator;
+        if (cacheIterator->value && cacheIterator->value->key != cacheKey)
+            cacheHash = 0;
+    } else
+        cacheIterator = presentationAttributeCache().end();
+
+    RefPtr<StylePropertySet> style;
+    if (cacheHash && cacheIterator->value) {
+        style = cacheIterator->value->value;
+        presentationAttributeCacheCleaner().didHitPresentationAttributeCache();
+    } else {
+        style = StylePropertySet::create(isSVGElement() ? SVGAttributeMode : CSSQuirksMode);
+        unsigned size = attributeCount();
+        for (unsigned i = 0; i < size; ++i) {
+            const Attribute* attribute = attributeItem(i);
+            collectStyleForPresentationAttribute(attribute->name(), attribute->value(), static_cast<MutableStylePropertySet*>(style.get()));
+        }
+    }
+
+    // ShareableElementData doesn't store presentation attribute style, so make sure we have a UniqueElementData.
+    UniqueElementData* elementData = ensureUniqueElementData();
+
+    elementData->m_presentationAttributeStyleIsDirty = false;
+    elementData->m_presentationAttributeStyle = style->isEmpty() ? 0 : style;
+
+    if (!cacheHash || cacheIterator->value)
+        return;
+
+    OwnPtr<PresentationAttributeCacheEntry> newEntry = adoptPtr(new PresentationAttributeCacheEntry);
+    newEntry->key = cacheKey;
+    newEntry->value = style.release();
+
+    static const int presentationAttributeCacheMaximumSize = 4096;
+    if (presentationAttributeCache().size() > presentationAttributeCacheMaximumSize) {
+        // Start building from scratch if the cache ever gets big.
+        presentationAttributeCache().clear();
+        presentationAttributeCache().set(cacheHash, newEntry.release());
+    } else
+        cacheIterator->value = newEntry.release();
+}
+
+void StyledElement::addPropertyToPresentationAttributeStyle(MutableStylePropertySet* style, CSSPropertyID propertyID, int identifier)
+{
+    style->setProperty(propertyID, cssValuePool().createIdentifierValue(identifier));
+}
+
+void StyledElement::addPropertyToPresentationAttributeStyle(MutableStylePropertySet* style, CSSPropertyID propertyID, double value, CSSPrimitiveValue::UnitTypes unit)
+{
+    style->setProperty(propertyID, cssValuePool().createValue(value, unit));
+}
+    
+void StyledElement::addPropertyToPresentationAttributeStyle(MutableStylePropertySet* style, CSSPropertyID propertyID, const String& value)
+{
+    style->setProperty(propertyID, value, false, document()->elementSheet()->contents());
+}
+
+}
diff --git a/Source/core/dom/StyledElement.h b/Source/core/dom/StyledElement.h
new file mode 100644
index 0000000..c6811a9
--- /dev/null
+++ b/Source/core/dom/StyledElement.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Peter Kelly (pmk@post.com)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StyledElement_h
+#define StyledElement_h
+
+#include "CSSPropertyNames.h"
+#include "core/css/CSSPrimitiveValue.h"
+#include "core/dom/Element.h"
+
+namespace WebCore {
+
+class Attribute;
+class MutableStylePropertySet;
+class PropertySetCSSStyleDeclaration;
+class StylePropertySet;
+
+struct PresentationAttributeCacheKey;
+
+class StyledElement : public Element {
+public:
+    virtual ~StyledElement();
+
+    virtual const StylePropertySet* additionalPresentationAttributeStyle() { return 0; }
+    void invalidateStyleAttribute();
+
+    const StylePropertySet* inlineStyle() const { return elementData() ? elementData()->m_inlineStyle.get() : 0; }
+    
+    bool setInlineStyleProperty(CSSPropertyID, int identifier, bool important = false);
+    bool setInlineStyleProperty(CSSPropertyID, double value, CSSPrimitiveValue::UnitTypes, bool important = false);
+    bool setInlineStyleProperty(CSSPropertyID, const String& value, bool important = false);
+    bool removeInlineStyleProperty(CSSPropertyID);
+    void removeAllInlineStyleProperties();
+
+    void synchronizeStyleAttributeInternal() const;
+    
+    virtual CSSStyleDeclaration* style() OVERRIDE;
+
+    const StylePropertySet* presentationAttributeStyle();
+    virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) { }
+
+protected:
+    StyledElement(const QualifiedName& name, Document* document, ConstructionType type)
+        : Element(name, document, type)
+    {
+    }
+
+    virtual void attributeChanged(const QualifiedName&, const AtomicString&, AttributeModificationReason = ModifiedDirectly) OVERRIDE;
+
+    virtual bool isPresentationAttribute(const QualifiedName&) const { return false; }
+
+    void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, int identifier);
+    void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, double value, CSSPrimitiveValue::UnitTypes);
+    void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, const String& value);
+
+    virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const;
+
+private:
+    void styleAttributeChanged(const AtomicString& newStyleString, AttributeModificationReason);
+
+    void inlineStyleChanged();
+    PropertySetCSSStyleDeclaration* inlineStyleCSSOMWrapper();
+    void setInlineStyleFromString(const AtomicString&);
+    MutableStylePropertySet* ensureMutableInlineStyle();
+
+    void makePresentationAttributeCacheKey(PresentationAttributeCacheKey&) const;
+    void rebuildPresentationAttributeStyle();
+};
+
+inline void StyledElement::invalidateStyleAttribute()
+{
+    ASSERT(elementData());
+    elementData()->m_styleAttributeIsDirty = true;
+}
+
+inline const StylePropertySet* StyledElement::presentationAttributeStyle()
+{
+    if (!elementData())
+        return 0;
+    if (elementData()->m_presentationAttributeStyleIsDirty)
+        rebuildPresentationAttributeStyle();
+    return elementData()->presentationAttributeStyle();
+}
+
+} //namespace
+
+#endif
diff --git a/Source/core/dom/TagNodeList.cpp b/Source/core/dom/TagNodeList.cpp
new file mode 100644
index 0000000..1835c65
--- /dev/null
+++ b/Source/core/dom/TagNodeList.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/TagNodeList.h"
+
+#include "core/dom/Element.h"
+#include "core/dom/NodeRareData.h"
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+TagNodeList::TagNodeList(PassRefPtr<Node> rootNode, CollectionType type, const AtomicString& namespaceURI, const AtomicString& localName)
+    : LiveNodeList(rootNode, type, DoNotInvalidateOnAttributeChanges)
+    , m_namespaceURI(namespaceURI)
+    , m_localName(localName)
+{
+    ASSERT(m_namespaceURI.isNull() || !m_namespaceURI.isEmpty());
+}
+
+TagNodeList::~TagNodeList()
+{
+    if (m_namespaceURI == starAtom)
+        ownerNode()->nodeLists()->removeCacheWithAtomicName(this, type(), m_localName);
+    else
+        ownerNode()->nodeLists()->removeCacheWithQualifiedName(this, m_namespaceURI, m_localName);
+}
+
+bool TagNodeList::nodeMatches(Element* testNode) const
+{
+    // Implements http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-getelementsbytagnamens
+    if (m_localName != starAtom && m_localName != testNode->localName())
+        return false;
+
+    return m_namespaceURI == starAtom || m_namespaceURI == testNode->namespaceURI();
+}
+
+HTMLTagNodeList::HTMLTagNodeList(PassRefPtr<Node> rootNode, const AtomicString& localName)
+    : TagNodeList(rootNode, HTMLTagNodeListType, starAtom, localName)
+    , m_loweredLocalName(localName.lower())
+{
+}
+
+bool HTMLTagNodeList::nodeMatches(Element* testNode) const
+{
+    return nodeMatchesInlined(testNode);
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/TagNodeList.h b/Source/core/dom/TagNodeList.h
new file mode 100644
index 0000000..f580ca0
--- /dev/null
+++ b/Source/core/dom/TagNodeList.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TagNodeList_h
+#define TagNodeList_h
+
+#include "core/dom/Element.h"
+#include "core/dom/LiveNodeList.h"
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+// NodeList that limits to a particular tag.
+class TagNodeList : public LiveNodeList {
+public:
+    static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
+    {
+        ASSERT(namespaceURI != starAtom);
+        return adoptRef(new TagNodeList(rootNode, TagNodeListType, namespaceURI, localName));
+    }
+
+    static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, CollectionType type, const AtomicString& localName)
+    {
+        ASSERT_UNUSED(type, type == TagNodeListType);
+        return adoptRef(new TagNodeList(rootNode, TagNodeListType, starAtom, localName));
+    }
+
+    virtual ~TagNodeList();
+
+protected:
+    TagNodeList(PassRefPtr<Node> rootNode, CollectionType, const AtomicString& namespaceURI, const AtomicString& localName);
+
+    virtual bool nodeMatches(Element*) const;
+
+    AtomicString m_namespaceURI;
+    AtomicString m_localName;
+};
+
+class HTMLTagNodeList : public TagNodeList {
+public:
+    static PassRefPtr<HTMLTagNodeList> create(PassRefPtr<Node> rootNode, CollectionType type, const AtomicString& localName)
+    {
+        ASSERT_UNUSED(type, type == HTMLTagNodeListType);
+        return adoptRef(new HTMLTagNodeList(rootNode, localName));
+    }
+
+    bool nodeMatchesInlined(Element*) const;
+
+private:
+    HTMLTagNodeList(PassRefPtr<Node> rootNode, const AtomicString& localName);
+
+    virtual bool nodeMatches(Element*) const;
+
+    AtomicString m_loweredLocalName;
+};
+
+inline bool HTMLTagNodeList::nodeMatchesInlined(Element* testNode) const
+{
+    // Implements http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-getelementsbytagname
+    if (m_localName != starAtom) {
+        const AtomicString& localName = testNode->isHTMLElement() ? m_loweredLocalName : m_localName;
+        if (localName != testNode->localName())
+            return false;
+    }
+    ASSERT(m_namespaceURI == starAtom);
+    return true;
+}
+
+} // namespace WebCore
+
+#endif // TagNodeList_h
diff --git a/Source/core/dom/TemplateContentDocumentFragment.h b/Source/core/dom/TemplateContentDocumentFragment.h
new file mode 100644
index 0000000..6ede6f3
--- /dev/null
+++ b/Source/core/dom/TemplateContentDocumentFragment.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 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 TemplateContentDocumentFragment_h
+#define TemplateContentDocumentFragment_h
+
+#include "core/dom/DocumentFragment.h"
+
+namespace WebCore {
+
+class TemplateContentDocumentFragment FINAL : public DocumentFragment {
+public:
+    static PassRefPtr<TemplateContentDocumentFragment> create(Document* document, const Element* host)
+    {
+        return adoptRef(new TemplateContentDocumentFragment(document, host));
+    }
+
+    const Element* host() const { return m_host; }
+
+private:
+    TemplateContentDocumentFragment(Document* document, const Element* host)
+        : DocumentFragment(document, CreateDocumentFragment)
+        , m_host(host)
+    {
+    }
+
+    virtual bool isTemplateContent() const OVERRIDE { return true; }
+
+    const Element* m_host;
+};
+
+} // namespace WebCore
+
+#endif // TemplateContentDocumentFragment_h
diff --git a/Source/core/dom/Text.cpp b/Source/core/dom/Text.cpp
new file mode 100644
index 0000000..2fbc7b2
--- /dev/null
+++ b/Source/core/dom/Text.cpp
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/Text.h"
+
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/ExceptionCodePlaceholder.h"
+#include "core/dom/NodeRenderingContext.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/rendering/RenderCombineText.h"
+#include "core/rendering/RenderText.h"
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#endif
+
+#include "core/css/StyleResolver.h"
+#include "core/rendering/style/StyleInheritedData.h"
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
+
+using namespace std;
+
+namespace WebCore {
+
+PassRefPtr<Text> Text::create(Document* document, const String& data)
+{
+    return adoptRef(new Text(document, data, CreateText));
+}
+
+PassRefPtr<Text> Text::createEditingText(Document* document, const String& data)
+{
+    return adoptRef(new Text(document, data, CreateEditingText));
+}
+
+PassRefPtr<Text> Text::splitText(unsigned offset, ExceptionCode& ec)
+{
+    ec = 0;
+
+    // INDEX_SIZE_ERR: Raised if the specified offset is negative or greater than
+    // the number of 16-bit units in data.
+    if (offset > length()) {
+        ec = INDEX_SIZE_ERR;
+        return 0;
+    }
+
+    String oldStr = data();
+    RefPtr<Text> newText = cloneWithData(oldStr.substring(offset));
+    setDataWithoutUpdate(oldStr.substring(0, offset));
+
+    dispatchModifiedEvent(oldStr);
+
+    if (parentNode())
+        parentNode()->insertBefore(newText.get(), nextSibling(), ec);
+    if (ec)
+        return 0;
+
+    if (parentNode())
+        document()->textNodeSplit(this);
+
+    if (renderer())
+        toRenderText(renderer())->setTextWithOffset(dataImpl(), 0, oldStr.length());
+
+    return newText.release();
+}
+
+static const Text* earliestLogicallyAdjacentTextNode(const Text* t)
+{
+    const Node* n = t;
+    while ((n = n->previousSibling())) {
+        Node::NodeType type = n->nodeType();
+        if (type == Node::TEXT_NODE || type == Node::CDATA_SECTION_NODE) {
+            t = static_cast<const Text*>(n);
+            continue;
+        }
+
+        // We would need to visit EntityReference child text nodes if they existed
+        ASSERT(type != Node::ENTITY_REFERENCE_NODE || !n->hasChildNodes());
+        break;
+    }
+    return t;
+}
+
+static const Text* latestLogicallyAdjacentTextNode(const Text* t)
+{
+    const Node* n = t;
+    while ((n = n->nextSibling())) {
+        Node::NodeType type = n->nodeType();
+        if (type == Node::TEXT_NODE || type == Node::CDATA_SECTION_NODE) {
+            t = static_cast<const Text*>(n);
+            continue;
+        }
+
+        // We would need to visit EntityReference child text nodes if they existed
+        ASSERT(type != Node::ENTITY_REFERENCE_NODE || !n->hasChildNodes());
+        break;
+    }
+    return t;
+}
+
+String Text::wholeText() const
+{
+    const Text* startText = earliestLogicallyAdjacentTextNode(this);
+    const Text* endText = latestLogicallyAdjacentTextNode(this);
+
+    Node* onePastEndText = endText->nextSibling();
+    unsigned resultLength = 0;
+    for (const Node* n = startText; n != onePastEndText; n = n->nextSibling()) {
+        if (!n->isTextNode())
+            continue;
+        const Text* t = static_cast<const Text*>(n);
+        const String& data = t->data();
+        if (std::numeric_limits<unsigned>::max() - data.length() < resultLength)
+            CRASH();
+        resultLength += data.length();
+    }
+    StringBuilder result;
+    result.reserveCapacity(resultLength);
+    for (const Node* n = startText; n != onePastEndText; n = n->nextSibling()) {
+        if (!n->isTextNode())
+            continue;
+        const Text* t = static_cast<const Text*>(n);
+        result.append(t->data());
+    }
+    ASSERT(result.length() == resultLength);
+
+    return result.toString();
+}
+
+PassRefPtr<Text> Text::replaceWholeText(const String& newText, ExceptionCode&)
+{
+    // Remove all adjacent text nodes, and replace the contents of this one.
+
+    // Protect startText and endText against mutation event handlers removing the last ref
+    RefPtr<Text> startText = const_cast<Text*>(earliestLogicallyAdjacentTextNode(this));
+    RefPtr<Text> endText = const_cast<Text*>(latestLogicallyAdjacentTextNode(this));
+
+    RefPtr<Text> protectedThis(this); // Mutation event handlers could cause our last ref to go away
+    RefPtr<ContainerNode> parent = parentNode(); // Protect against mutation handlers moving this node during traversal
+    for (RefPtr<Node> n = startText; n && n != this && n->isTextNode() && n->parentNode() == parent;) {
+        RefPtr<Node> nodeToRemove(n.release());
+        n = nodeToRemove->nextSibling();
+        parent->removeChild(nodeToRemove.get(), IGNORE_EXCEPTION);
+    }
+
+    if (this != endText) {
+        Node* onePastEndText = endText->nextSibling();
+        for (RefPtr<Node> n = nextSibling(); n && n != onePastEndText && n->isTextNode() && n->parentNode() == parent;) {
+            RefPtr<Node> nodeToRemove(n.release());
+            n = nodeToRemove->nextSibling();
+            parent->removeChild(nodeToRemove.get(), IGNORE_EXCEPTION);
+        }
+    }
+
+    if (newText.isEmpty()) {
+        if (parent && parentNode() == parent)
+            parent->removeChild(this, IGNORE_EXCEPTION);
+        return 0;
+    }
+
+    setData(newText, IGNORE_EXCEPTION);
+    return protectedThis.release();
+}
+
+String Text::nodeName() const
+{
+    return textAtom.string();
+}
+
+Node::NodeType Text::nodeType() const
+{
+    return TEXT_NODE;
+}
+
+PassRefPtr<Node> Text::cloneNode(bool /*deep*/)
+{
+    return cloneWithData(data());
+}
+
+bool Text::textRendererIsNeeded(const NodeRenderingContext& context)
+{
+    if (isEditingText())
+        return true;
+
+    if (!length())
+        return false;
+
+    if (context.style()->display() == NONE)
+        return false;
+
+    bool onlyWS = containsOnlyWhitespace();
+    if (!onlyWS)
+        return true;
+
+    RenderObject* parent = context.parentRenderer();
+    if (parent->isTable() || parent->isTableRow() || parent->isTableSection() || parent->isRenderTableCol() || parent->isFrameSet())
+        return false;
+    
+    if (context.style()->preserveNewline()) // pre/pre-wrap/pre-line always make renderers.
+        return true;
+    
+    RenderObject* prev = context.previousRenderer();
+    if (prev && prev->isBR()) // <span><br/> <br/></span>
+        return false;
+        
+    if (parent->isRenderInline()) {
+        // <span><div/> <div/></span>
+        if (prev && !prev->isInline())
+            return false;
+    } else {
+        if (parent->isRenderBlock() && !parent->childrenInline() && (!prev || !prev->isInline()))
+            return false;
+        
+        RenderObject* first = parent->firstChild();
+        while (first && first->isFloatingOrOutOfFlowPositioned())
+            first = first->nextSibling();
+        RenderObject* next = context.nextRenderer();
+        if (!first || next == first)
+            // Whitespace at the start of a block just goes away.  Don't even
+            // make a render object for this text.
+            return false;
+    }
+    
+    return true;
+}
+
+#if ENABLE(SVG)
+static bool isSVGShadowText(Text* text)
+{
+    Node* parentNode = text->parentNode();
+    return parentNode->isShadowRoot() && toShadowRoot(parentNode)->host()->hasTagName(SVGNames::trefTag);
+}
+
+static bool isSVGText(Text* text)
+{
+    Node* parentOrShadowHostNode = text->parentOrShadowHostNode();
+    return parentOrShadowHostNode->isSVGElement() && !parentOrShadowHostNode->hasTagName(SVGNames::foreignObjectTag);
+}
+#endif
+
+void Text::createTextRendererIfNeeded()
+{
+    NodeRenderingContext(this).createRendererForTextIfNeeded();
+}
+
+RenderText* Text::createTextRenderer(RenderArena* arena, RenderStyle* style)
+{
+#if ENABLE(SVG)
+    if (isSVGText(this) || isSVGShadowText(this))
+        return new (arena) RenderSVGInlineText(this, dataImpl());
+#endif
+    if (style->hasTextCombine())
+        return new (arena) RenderCombineText(this, dataImpl());
+
+    return new (arena) RenderText(this, dataImpl());
+}
+
+void Text::attach()
+{
+    createTextRendererIfNeeded();
+    CharacterData::attach();
+}
+
+void Text::recalcTextStyle(StyleChange change)
+{
+    RenderText* renderer = toRenderText(this->renderer());
+
+    if (change != NoChange && renderer)
+        renderer->setStyle(document()->styleResolver()->styleForText(this));
+
+    if (needsStyleRecalc()) {
+        if (renderer)
+            renderer->setText(dataImpl());
+        else
+            reattach();
+    }
+    clearNeedsStyleRecalc();
+}
+
+void Text::updateTextRenderer(unsigned offsetOfReplacedData, unsigned lengthOfReplacedData)
+{
+    if (!attached())
+        return;
+    RenderText* textRenderer = toRenderText(renderer());
+    if (!textRenderer || !textRendererIsNeeded(NodeRenderingContext(this, textRenderer->style()))) {
+        reattach();
+        return;
+    }
+    textRenderer->setTextWithOffset(dataImpl(), offsetOfReplacedData, lengthOfReplacedData);
+}
+
+bool Text::childTypeAllowed(NodeType) const
+{
+    return false;
+}
+
+PassRefPtr<Text> Text::cloneWithData(const String& data)
+{
+    return create(document(), data);
+}
+
+PassRefPtr<Text> Text::createWithLengthLimit(Document* document, const String& data, unsigned start, unsigned maxChars)
+{
+    unsigned dataLength = data.length();
+
+    if (!start && dataLength <= maxChars)
+        return create(document, data);
+
+    RefPtr<Text> result = Text::create(document, String());
+    result->parserAppendData(data, start, maxChars);
+
+    return result;
+}
+
+#ifndef NDEBUG
+void Text::formatForDebugger(char *buffer, unsigned length) const
+{
+    StringBuilder result;
+    String s;
+
+    result.append(nodeName());
+
+    s = data();
+    if (s.length() > 0) {
+        if (result.length())
+            result.appendLiteral("; ");
+        result.appendLiteral("value=");
+        result.append(s);
+    }
+
+    strncpy(buffer, result.toString().utf8().data(), length - 1);
+}
+#endif
+
+} // namespace WebCore
diff --git a/Source/core/dom/Text.h b/Source/core/dom/Text.h
new file mode 100644
index 0000000..c105afd
--- /dev/null
+++ b/Source/core/dom/Text.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Text_h
+#define Text_h
+
+#include "core/dom/CharacterData.h"
+
+namespace WebCore {
+
+class RenderText;
+
+class Text : public CharacterData {
+public:
+    static const unsigned defaultLengthLimit = 1 << 16;
+
+    static PassRefPtr<Text> create(Document*, const String&);
+    static PassRefPtr<Text> createWithLengthLimit(Document*, const String&, unsigned positionInString, unsigned lengthLimit = defaultLengthLimit);
+    static PassRefPtr<Text> createEditingText(Document*, const String&);
+
+    PassRefPtr<Text> splitText(unsigned offset, ExceptionCode&);
+
+    // DOM Level 3: http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-1312295772
+
+    String wholeText() const;
+    PassRefPtr<Text> replaceWholeText(const String&, ExceptionCode&);
+    
+    void recalcTextStyle(StyleChange);
+    void createTextRendererIfNeeded();
+    bool textRendererIsNeeded(const NodeRenderingContext&);
+    RenderText* createTextRenderer(RenderArena*, RenderStyle*);
+    void updateTextRenderer(unsigned offsetOfReplacedData, unsigned lengthOfReplacedData);
+
+    virtual void attach() OVERRIDE FINAL;
+    
+    virtual bool canContainRangeEndPoint() const OVERRIDE FINAL { return true; }
+    virtual NodeType nodeType() const OVERRIDE;
+
+protected:
+    Text(Document* document, const String& data, ConstructionType type)
+        : CharacterData(document, data, type)
+    {
+        ScriptWrappable::init(this);
+    }
+
+private:
+    virtual String nodeName() const OVERRIDE;
+    virtual PassRefPtr<Node> cloneNode(bool deep) OVERRIDE FINAL;
+    virtual bool childTypeAllowed(NodeType) const OVERRIDE;
+
+    virtual PassRefPtr<Text> cloneWithData(const String&);
+
+#ifndef NDEBUG
+    virtual void formatForDebugger(char* buffer, unsigned length) const;
+#endif
+};
+
+inline Text* toText(Node* node)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isTextNode());
+    return static_cast<Text*>(node);
+}
+
+} // namespace WebCore
+
+#endif // Text_h
diff --git a/Source/core/dom/Text.idl b/Source/core/dom/Text.idl
new file mode 100644
index 0000000..68e1b8d
--- /dev/null
+++ b/Source/core/dom/Text.idl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+[
+    CustomToV8,
+    SkipVTableValidation,
+] interface Text : CharacterData {
+
+    // DOM Level 1
+
+    [RaisesException] Text splitText([IsIndex,Default=Undefined] optional unsigned long offset);
+
+    // Introduced in DOM Level 3:
+    readonly attribute DOMString       wholeText;
+    [RaisesException] Text               replaceWholeText([Default=Undefined] optional DOMString content);
+    // ShadowAware API
+    [ImplementedAs=insertionParentForBinding, PerWorldBindings] readonly attribute Node webkitInsertionParent;
+
+};
+
diff --git a/Source/core/dom/TextEvent.cpp b/Source/core/dom/TextEvent.cpp
new file mode 100644
index 0000000..7e5e6e9
--- /dev/null
+++ b/Source/core/dom/TextEvent.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "core/dom/TextEvent.h"
+
+#include "core/dom/DocumentFragment.h"
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+PassRefPtr<TextEvent> TextEvent::create()
+{
+    return adoptRef(new TextEvent);
+}
+
+PassRefPtr<TextEvent> TextEvent::create(PassRefPtr<AbstractView> view, const String& data, TextEventInputType inputType)
+{
+    return adoptRef(new TextEvent(view, data, inputType));
+}
+
+PassRefPtr<TextEvent> TextEvent::createForPlainTextPaste(PassRefPtr<AbstractView> view, const String& data, bool shouldSmartReplace)
+{
+    return adoptRef(new TextEvent(view, data, 0, shouldSmartReplace, false));
+}
+
+PassRefPtr<TextEvent> TextEvent::createForFragmentPaste(PassRefPtr<AbstractView> view, PassRefPtr<DocumentFragment> data, bool shouldSmartReplace, bool shouldMatchStyle)
+{
+    return adoptRef(new TextEvent(view, "", data, shouldSmartReplace, shouldMatchStyle));
+}
+
+PassRefPtr<TextEvent> TextEvent::createForDrop(PassRefPtr<AbstractView> view, const String& data)
+{
+    return adoptRef(new TextEvent(view, data, TextEventInputDrop));
+}
+
+PassRefPtr<TextEvent> TextEvent::createForDictation(PassRefPtr<AbstractView> view, const String& data, const Vector<DictationAlternative>& dictationAlternatives)
+{
+    return adoptRef(new TextEvent(view, data, dictationAlternatives));
+}
+
+TextEvent::TextEvent()
+    : m_inputType(TextEventInputKeyboard)
+    , m_shouldSmartReplace(false)
+    , m_shouldMatchStyle(false)
+{
+    ScriptWrappable::init(this);
+}
+
+TextEvent::TextEvent(PassRefPtr<AbstractView> view, const String& data, TextEventInputType inputType)
+    : UIEvent(eventNames().textInputEvent, true, true, view, 0)
+    , m_inputType(inputType)
+    , m_data(data)
+    , m_pastingFragment(0)
+    , m_shouldSmartReplace(false)
+    , m_shouldMatchStyle(false)
+{
+    ScriptWrappable::init(this);
+}
+
+TextEvent::TextEvent(PassRefPtr<AbstractView> view, const String& data, PassRefPtr<DocumentFragment> pastingFragment,
+                     bool shouldSmartReplace, bool shouldMatchStyle)
+    : UIEvent(eventNames().textInputEvent, true, true, view, 0)
+    , m_inputType(TextEventInputPaste)
+    , m_data(data)
+    , m_pastingFragment(pastingFragment)
+    , m_shouldSmartReplace(shouldSmartReplace)
+    , m_shouldMatchStyle(shouldMatchStyle)
+{
+    ScriptWrappable::init(this);
+}
+
+TextEvent::TextEvent(PassRefPtr<AbstractView> view, const String& data, const Vector<DictationAlternative>& dictationAlternatives)
+    : UIEvent(eventNames().textInputEvent, true, true, view, 0)
+    , m_inputType(TextEventInputDictation)
+    , m_data(data)
+    , m_shouldSmartReplace(false)
+    , m_shouldMatchStyle(false)
+    , m_dictationAlternatives(dictationAlternatives)
+{
+    ScriptWrappable::init(this);
+}
+
+TextEvent::~TextEvent()
+{
+}
+
+void TextEvent::initTextEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView> view, const String& data)
+{
+    if (dispatched())
+        return;
+
+    initUIEvent(type, canBubble, cancelable, view, 0);
+
+    m_data = data;
+}
+
+const AtomicString& TextEvent::interfaceName() const
+{
+    return eventNames().interfaceForTextEvent;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/TextEvent.h b/Source/core/dom/TextEvent.h
new file mode 100644
index 0000000..68e4aaa
--- /dev/null
+++ b/Source/core/dom/TextEvent.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef TextEvent_h
+#define TextEvent_h
+
+#include "core/dom/TextEventInputType.h"
+#include "core/dom/UIEvent.h"
+#include "core/editing/DictationAlternative.h"
+
+namespace WebCore {
+
+    class DocumentFragment;
+
+    class TextEvent : public UIEvent {
+    public:
+
+        static PassRefPtr<TextEvent> create();
+        static PassRefPtr<TextEvent> create(PassRefPtr<AbstractView>, const String& data, TextEventInputType = TextEventInputKeyboard);
+        static PassRefPtr<TextEvent> createForPlainTextPaste(PassRefPtr<AbstractView> view, const String& data, bool shouldSmartReplace);
+        static PassRefPtr<TextEvent> createForFragmentPaste(PassRefPtr<AbstractView> view, PassRefPtr<DocumentFragment> data, bool shouldSmartReplace, bool shouldMatchStyle);
+        static PassRefPtr<TextEvent> createForDrop(PassRefPtr<AbstractView> view, const String& data);
+        static PassRefPtr<TextEvent> createForDictation(PassRefPtr<AbstractView>, const String& data, const Vector<DictationAlternative>& dictationAlternatives);
+
+        virtual ~TextEvent();
+    
+        void initTextEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>, const String& data);
+    
+        String data() const { return m_data; }
+
+        virtual const AtomicString& interfaceName() const;
+
+        bool isLineBreak() const { return m_inputType == TextEventInputLineBreak; }
+        bool isComposition() const { return m_inputType == TextEventInputComposition; }
+        bool isBackTab() const { return m_inputType == TextEventInputBackTab; }
+        bool isPaste() const { return m_inputType == TextEventInputPaste; }
+        bool isDrop() const { return m_inputType == TextEventInputDrop; }
+        bool isDictation() const { return m_inputType == TextEventInputDictation; }
+
+        bool shouldSmartReplace() const { return m_shouldSmartReplace; }
+        bool shouldMatchStyle() const { return m_shouldMatchStyle; }
+        DocumentFragment* pastingFragment() const { return m_pastingFragment.get(); }
+        const Vector<DictationAlternative>& dictationAlternatives() const { return m_dictationAlternatives; }
+
+    private:
+        TextEvent();
+
+        TextEvent(PassRefPtr<AbstractView>, const String& data, TextEventInputType = TextEventInputKeyboard);
+        TextEvent(PassRefPtr<AbstractView>, const String& data, PassRefPtr<DocumentFragment>,
+                  bool shouldSmartReplace, bool shouldMatchStyle);
+        TextEvent(PassRefPtr<AbstractView>, const String& data, const Vector<DictationAlternative>& dictationAlternatives);
+
+        TextEventInputType m_inputType;
+        String m_data;
+
+        RefPtr<DocumentFragment> m_pastingFragment;
+        bool m_shouldSmartReplace;
+        bool m_shouldMatchStyle;
+        Vector<DictationAlternative> m_dictationAlternatives;
+    };
+
+} // namespace WebCore
+
+#endif // TextEvent_h
diff --git a/Source/core/dom/TextEvent.idl b/Source/core/dom/TextEvent.idl
new file mode 100644
index 0000000..4af1a6f
--- /dev/null
+++ b/Source/core/dom/TextEvent.idl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+// Introduced in DOM Level 3:
+interface TextEvent : UIEvent {
+
+    readonly attribute DOMString data;
+
+    void initTextEvent([Default=Undefined] optional DOMString typeArg, 
+                       [Default=Undefined] optional boolean canBubbleArg, 
+                       [Default=Undefined] optional boolean cancelableArg, 
+                       [Default=Undefined] optional DOMWindow viewArg, 
+                       [Default=Undefined] optional DOMString dataArg);
+
+};
+
diff --git a/Source/core/dom/TextEventInputType.h b/Source/core/dom/TextEventInputType.h
new file mode 100644
index 0000000..8be233c
--- /dev/null
+++ b/Source/core/dom/TextEventInputType.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 TextEventInputType_h
+#define TextEventInputType_h
+
+namespace WebCore {
+
+enum TextEventInputType {
+    TextEventInputKeyboard, // any newline characters in the text are line breaks only, not paragraph separators.
+    TextEventInputLineBreak, // any tab characters in the text are backtabs.
+    TextEventInputComposition,
+    TextEventInputBackTab,
+    TextEventInputPaste,
+    TextEventInputDrop,
+    TextEventInputDictation,
+    TextEventInputOther,
+};
+
+} // namespace WebCore
+
+#endif // TextEventInputType_h
diff --git a/Source/core/dom/Touch.cpp b/Source/core/dom/Touch.cpp
new file mode 100644
index 0000000..a6ccaa7
--- /dev/null
+++ b/Source/core/dom/Touch.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "core/dom/Touch.h"
+
+#include "core/page/DOMWindow.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+
+namespace WebCore {
+
+static int contentsX(Frame* frame)
+{
+    if (!frame)
+        return 0;
+    FrameView* frameView = frame->view();
+    if (!frameView)
+        return 0;
+    return frameView->scrollX() / frame->pageZoomFactor();
+}
+
+static int contentsY(Frame* frame)
+{
+    if (!frame)
+        return 0;
+    FrameView* frameView = frame->view();
+    if (!frameView)
+        return 0;
+    return frameView->scrollY() / frame->pageZoomFactor();
+}
+
+Touch::Touch(Frame* frame, EventTarget* target, unsigned identifier, int screenX, int screenY, int pageX, int pageY, int radiusX, int radiusY, float rotationAngle, float force)
+    : m_target(target)
+    , m_identifier(identifier)
+    , m_clientX(pageX - contentsX(frame))
+    , m_clientY(pageY - contentsY(frame))
+    , m_screenX(screenX)
+    , m_screenY(screenY)
+    , m_pageX(pageX)
+    , m_pageY(pageY)
+    , m_radiusX(radiusX)
+    , m_radiusY(radiusY)
+    , m_rotationAngle(rotationAngle)
+    , m_force(force)
+{
+    float scaleFactor = frame->pageZoomFactor();
+    float x = pageX * scaleFactor;
+    float y = pageY * scaleFactor;
+    m_absoluteLocation = roundedLayoutPoint(FloatPoint(x, y));
+}
+
+Touch::Touch(EventTarget* target, unsigned identifier, int clientX, int clientY, int screenX, int screenY, int pageX, int pageY, int radiusX, int radiusY, float rotationAngle, float force, LayoutPoint absoluteLocation)
+    : m_target(target)
+    , m_identifier(identifier)
+    , m_clientX(clientX)
+    , m_clientY(clientY)
+    , m_screenX(screenX)
+    , m_screenY(screenY)
+    , m_pageX(pageX)
+    , m_pageY(pageY)
+    , m_radiusX(radiusX)
+    , m_radiusY(radiusY)
+    , m_rotationAngle(rotationAngle)
+    , m_force(force)
+    , m_absoluteLocation(absoluteLocation)
+{
+}
+
+PassRefPtr<Touch> Touch::cloneWithNewTarget(EventTarget* eventTarget) const
+{
+    return adoptRef(new Touch(eventTarget, m_identifier, m_clientX, m_clientY, m_screenX, m_screenY, m_pageX, m_pageY, m_radiusX, m_radiusY, m_rotationAngle, m_force, m_absoluteLocation));
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/Touch.h b/Source/core/dom/Touch.h
new file mode 100644
index 0000000..f63a6bd
--- /dev/null
+++ b/Source/core/dom/Touch.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Touch_h
+#define Touch_h
+
+#include "core/dom/EventTarget.h"
+#include "core/platform/graphics/LayoutPoint.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Frame;
+
+class Touch : public RefCounted<Touch> {
+public:
+    static PassRefPtr<Touch> create(Frame* frame, EventTarget* target,
+            unsigned identifier, int screenX, int screenY, int pageX, int pageY,
+            int radiusX, int radiusY, float rotationAngle, float force)
+    {
+        return adoptRef(new Touch(frame, target, identifier, screenX, 
+                screenY, pageX, pageY, radiusX, radiusY, rotationAngle, force));
+    }
+
+    EventTarget* target() const { return m_target.get(); }
+    unsigned identifier() const { return m_identifier; }
+    int clientX() const { return m_clientX; }
+    int clientY() const { return m_clientY; }
+    int screenX() const { return m_screenX; }
+    int screenY() const { return m_screenY; }
+    int pageX() const { return m_pageX; }
+    int pageY() const { return m_pageY; }
+    int webkitRadiusX() const { return m_radiusX; }
+    int webkitRadiusY() const { return m_radiusY; }
+    float webkitRotationAngle() const { return m_rotationAngle; }
+    float webkitForce() const { return m_force; }
+    const LayoutPoint& absoluteLocation() const { return m_absoluteLocation; }
+    PassRefPtr<Touch> cloneWithNewTarget(EventTarget*) const;
+
+private:
+    Touch(Frame* frame, EventTarget* target, unsigned identifier,
+            int screenX, int screenY, int pageX, int pageY,
+            int radiusX, int radiusY, float rotationAngle, float force);
+
+    Touch(EventTarget*, unsigned identifier, int clientX, int clientY,
+        int screenX, int screenY, int pageX, int pageY,
+        int radiusX, int radiusY, float rotationAngle, float force, LayoutPoint absoluteLocation);
+
+    RefPtr<EventTarget> m_target;
+    unsigned m_identifier;
+    int m_clientX;
+    int m_clientY;
+    int m_screenX;
+    int m_screenY;
+    int m_pageX;
+    int m_pageY;
+    int m_radiusX;
+    int m_radiusY;
+    float m_rotationAngle;
+    float m_force;
+    LayoutPoint m_absoluteLocation;
+};
+
+} // namespace WebCore
+
+#endif /* Touch_h */
diff --git a/Source/core/dom/Touch.idl b/Source/core/dom/Touch.idl
new file mode 100644
index 0000000..4625083
--- /dev/null
+++ b/Source/core/dom/Touch.idl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    ImplementationLacksVTable
+] interface Touch {
+    readonly attribute long             clientX;
+    readonly attribute long             clientY;
+    readonly attribute long             screenX;
+    readonly attribute long             screenY;
+    readonly attribute long             pageX;
+    readonly attribute long             pageY;
+    readonly attribute EventTarget      target;
+    readonly attribute unsigned long    identifier;
+    readonly attribute long             webkitRadiusX;
+    readonly attribute long             webkitRadiusY;
+    readonly attribute float            webkitRotationAngle;
+    readonly attribute float            webkitForce;
+};
diff --git a/Source/core/dom/TouchEvent.cpp b/Source/core/dom/TouchEvent.cpp
new file mode 100644
index 0000000..aec39ef
--- /dev/null
+++ b/Source/core/dom/TouchEvent.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "core/dom/TouchEvent.h"
+
+#include "core/dom/EventDispatcher.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/EventRetargeter.h"
+#include "core/dom/TouchList.h"
+
+namespace WebCore {
+
+TouchEvent::TouchEvent()
+{
+    ScriptWrappable::init(this);
+}
+
+TouchEvent::TouchEvent(TouchList* touches, TouchList* targetTouches,
+        TouchList* changedTouches, const AtomicString& type, 
+        PassRefPtr<AbstractView> view, int screenX, int screenY, int pageX, int pageY,
+        bool ctrlKey, bool altKey, bool shiftKey, bool metaKey)
+    : MouseRelatedEvent(type, true, true, view, 0, IntPoint(screenX, screenY),
+                        IntPoint(pageX, pageY),
+                        IntPoint(0, 0),
+                        ctrlKey, altKey, shiftKey, metaKey)
+    , m_touches(touches)
+    , m_targetTouches(targetTouches)
+    , m_changedTouches(changedTouches)
+{
+    ScriptWrappable::init(this);
+}
+
+TouchEvent::~TouchEvent()
+{
+}
+
+void TouchEvent::initTouchEvent(TouchList* touches, TouchList* targetTouches,
+        TouchList* changedTouches, const AtomicString& type, 
+        PassRefPtr<AbstractView> view, int screenX, int screenY, int clientX, int clientY,
+        bool ctrlKey, bool altKey, bool shiftKey, bool metaKey)
+{
+    if (dispatched())
+        return;
+
+    initUIEvent(type, true, true, view, 0);
+
+    m_touches = touches;
+    m_targetTouches = targetTouches;
+    m_changedTouches = changedTouches;
+    m_screenLocation = IntPoint(screenX, screenY);
+    m_ctrlKey = ctrlKey;
+    m_altKey = altKey;
+    m_shiftKey = shiftKey;
+    m_metaKey = metaKey;
+    initCoordinates(IntPoint(clientX, clientY));
+}
+
+const AtomicString& TouchEvent::interfaceName() const
+{
+    return eventNames().interfaceForTouchEvent;
+}
+
+bool TouchEvent::isTouchEvent() const
+{
+    return true;
+}
+
+PassRefPtr<TouchEventDispatchMediator> TouchEventDispatchMediator::create(PassRefPtr<TouchEvent> touchEvent)
+{
+    return adoptRef(new TouchEventDispatchMediator(touchEvent));
+}
+
+TouchEventDispatchMediator::TouchEventDispatchMediator(PassRefPtr<TouchEvent> touchEvent)
+    : EventDispatchMediator(touchEvent)
+{
+}
+
+TouchEvent* TouchEventDispatchMediator::event() const
+{
+    return static_cast<TouchEvent*>(EventDispatchMediator::event());
+}
+
+bool TouchEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
+{
+    EventRetargeter::adjustForTouchEvent(dispatcher->node(), *event());
+    return dispatcher->dispatch();
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/TouchEvent.h b/Source/core/dom/TouchEvent.h
new file mode 100644
index 0000000..abbd7b8
--- /dev/null
+++ b/Source/core/dom/TouchEvent.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TouchEvent_h
+#define TouchEvent_h
+
+#include "core/dom/EventDispatchMediator.h"
+#include "core/dom/MouseRelatedEvent.h"
+#include "core/dom/TouchList.h"
+
+namespace WebCore {
+
+class TouchEvent : public MouseRelatedEvent {
+public:
+    virtual ~TouchEvent();
+
+    static PassRefPtr<TouchEvent> create()
+    {
+        return adoptRef(new TouchEvent);
+    }
+    static PassRefPtr<TouchEvent> create(TouchList* touches, 
+            TouchList* targetTouches, TouchList* changedTouches, 
+            const AtomicString& type, PassRefPtr<AbstractView> view,
+            int screenX, int screenY, int pageX, int pageY,
+            bool ctrlKey, bool altKey, bool shiftKey, bool metaKey)
+    {
+        return adoptRef(new TouchEvent(touches, targetTouches, changedTouches,
+                type, view, screenX, screenY, pageX, pageY,
+                ctrlKey, altKey, shiftKey, metaKey));
+    }
+
+    void initTouchEvent(TouchList* touches, TouchList* targetTouches,
+            TouchList* changedTouches, const AtomicString& type, 
+            PassRefPtr<AbstractView> view, int screenX, int screenY, 
+            int clientX, int clientY,
+            bool ctrlKey, bool altKey, bool shiftKey, bool metaKey);
+
+    TouchList* touches() const { return m_touches.get(); }
+    TouchList* targetTouches() const { return m_targetTouches.get(); }
+    TouchList* changedTouches() const { return m_changedTouches.get(); }
+
+    void setTouches(PassRefPtr<TouchList> touches) { m_touches = touches; }
+    void setTargetTouches(PassRefPtr<TouchList> targetTouches) { m_targetTouches = targetTouches; }
+    void setChangedTouches(PassRefPtr<TouchList> changedTouches) { m_changedTouches = changedTouches; }
+
+    virtual bool isTouchEvent() const OVERRIDE;
+
+    virtual const AtomicString& interfaceName() const;
+
+private:
+    TouchEvent();
+    TouchEvent(TouchList* touches, TouchList* targetTouches,
+            TouchList* changedTouches, const AtomicString& type,
+            PassRefPtr<AbstractView>, int screenX, int screenY, int pageX,
+            int pageY,
+            bool ctrlKey, bool altKey, bool shiftKey, bool metaKey);
+
+    RefPtr<TouchList> m_touches;
+    RefPtr<TouchList> m_targetTouches;
+    RefPtr<TouchList> m_changedTouches;
+};
+
+class TouchEventDispatchMediator : public EventDispatchMediator {
+public:
+    static PassRefPtr<TouchEventDispatchMediator> create(PassRefPtr<TouchEvent>);
+
+private:
+    explicit TouchEventDispatchMediator(PassRefPtr<TouchEvent>);
+    TouchEvent* event() const;
+    virtual bool dispatchEvent(EventDispatcher*) const OVERRIDE;
+};
+
+inline TouchEvent* toTouchEvent(Event* event)
+{
+    ASSERT(event && event->isTouchEvent());
+    return static_cast<TouchEvent*>(event);
+}
+
+} // namespace WebCore
+
+#endif // TouchEvent_h
diff --git a/Source/core/dom/TouchEvent.idl b/Source/core/dom/TouchEvent.idl
new file mode 100644
index 0000000..236aff2
--- /dev/null
+++ b/Source/core/dom/TouchEvent.idl
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+interface TouchEvent : UIEvent {
+    readonly attribute TouchList touches;
+    readonly attribute TouchList targetTouches;
+    readonly attribute TouchList changedTouches;
+    readonly attribute boolean ctrlKey;
+    readonly attribute boolean shiftKey;
+    readonly attribute boolean altKey;
+    readonly attribute boolean metaKey;
+
+    void initTouchEvent([Default=Undefined] optional TouchList touches,
+                        [Default=Undefined] optional TouchList targetTouches,
+                        [Default=Undefined] optional TouchList changedTouches,
+                        [Default=Undefined] optional DOMString type,
+                        [Default=Undefined] optional DOMWindow view,
+                        [Default=Undefined] optional long screenX, 
+                        [Default=Undefined] optional long screenY, 
+                        [Default=Undefined] optional long clientX, 
+                        [Default=Undefined] optional long clientY,
+                        [Default=Undefined] optional boolean ctrlKey,
+                        [Default=Undefined] optional boolean altKey,
+                        [Default=Undefined] optional boolean shiftKey,
+                        [Default=Undefined] optional boolean metaKey);
+};
diff --git a/Source/core/dom/TouchList.cpp b/Source/core/dom/TouchList.cpp
new file mode 100644
index 0000000..3653a2e
--- /dev/null
+++ b/Source/core/dom/TouchList.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "core/dom/TouchList.h"
+
+namespace WebCore {
+
+Touch* TouchList::item(unsigned index)
+{
+    if (index >= m_values.size())
+        return 0;
+    return m_values[index].get();
+}
+
+const Touch* TouchList::item(unsigned index) const
+{
+    return const_cast<TouchList*>(this)->item(index);
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/TouchList.h b/Source/core/dom/TouchList.h
new file mode 100644
index 0000000..ed87938
--- /dev/null
+++ b/Source/core/dom/TouchList.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TouchList_h
+#define TouchList_h
+
+#include "core/dom/Touch.h"
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class TouchList : public RefCounted<TouchList> {
+public:
+    static PassRefPtr<TouchList> create()
+    {
+        return adoptRef(new TouchList);
+    }
+
+    unsigned length() const { return m_values.size(); }
+
+    Touch* item(unsigned);
+    const Touch* item(unsigned) const;
+
+    void append(const PassRefPtr<Touch> touch) { m_values.append(touch); }
+
+private:
+    TouchList() {}
+
+    Vector<RefPtr<Touch> > m_values;
+};
+
+} // namespace WebCore
+
+#endif /* TouchList_h */
diff --git a/Source/core/dom/TouchList.idl b/Source/core/dom/TouchList.idl
new file mode 100644
index 0000000..0034249
--- /dev/null
+++ b/Source/core/dom/TouchList.idl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    ImplementationLacksVTable
+] interface TouchList {
+    readonly attribute unsigned long length;
+
+    getter Touch item(unsigned long index);
+};
diff --git a/Source/core/dom/TransformSource.h b/Source/core/dom/TransformSource.h
new file mode 100644
index 0000000..002e912
--- /dev/null
+++ b/Source/core/dom/TransformSource.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009 Jakub Wieczorek <faw217@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TransformSource_h
+#define TransformSource_h
+
+#include <libxml/tree.h>
+#include <wtf/FastAllocBase.h>
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+    class TransformSource {
+        WTF_MAKE_NONCOPYABLE(TransformSource); WTF_MAKE_FAST_ALLOCATED;
+    public:
+        explicit TransformSource(xmlDocPtr source);
+        ~TransformSource();
+
+        xmlDocPtr platformSource() const { return m_source; }
+
+    private:
+        xmlDocPtr m_source;
+    };
+
+} // namespace WebCore
+
+#endif // TransformSource_h
diff --git a/Source/core/dom/TransformSourceLibxslt.cpp b/Source/core/dom/TransformSourceLibxslt.cpp
new file mode 100644
index 0000000..6580a11
--- /dev/null
+++ b/Source/core/dom/TransformSourceLibxslt.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "core/dom/TransformSource.h"
+
+#include <libxml/tree.h>
+
+namespace WebCore {
+
+TransformSource::TransformSource(xmlDocPtr source)
+    : m_source(source)
+{
+}
+
+TransformSource::~TransformSource()
+{
+    xmlFreeDoc(m_source);
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/TransitionEvent.cpp b/Source/core/dom/TransitionEvent.cpp
new file mode 100644
index 0000000..7ddacd9
--- /dev/null
+++ b/Source/core/dom/TransitionEvent.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "core/dom/TransitionEvent.h"
+
+#include "core/dom/EventNames.h"
+
+namespace WebCore {
+
+TransitionEventInit::TransitionEventInit()
+    : elapsedTime(0)
+{
+}
+
+TransitionEvent::TransitionEvent()
+    : m_elapsedTime(0)
+{
+    ScriptWrappable::init(this);
+}
+
+TransitionEvent::TransitionEvent(const AtomicString& type, const String& propertyName, double elapsedTime, const String& pseudoElement)
+    : Event(type, true, true)
+    , m_propertyName(propertyName)
+    , m_elapsedTime(elapsedTime)
+    , m_pseudoElement(pseudoElement)
+{
+    ScriptWrappable::init(this);
+}
+
+TransitionEvent::TransitionEvent(const AtomicString& type, const TransitionEventInit& initializer)
+    : Event(type, initializer)
+    , m_propertyName(initializer.propertyName)
+    , m_elapsedTime(initializer.elapsedTime)
+    , m_pseudoElement(initializer.pseudoElement)
+{
+    ScriptWrappable::init(this);
+}
+
+TransitionEvent::~TransitionEvent()
+{
+}
+
+const String& TransitionEvent::propertyName() const
+{
+    return m_propertyName;
+}
+
+double TransitionEvent::elapsedTime() const
+{
+    return m_elapsedTime;
+}
+
+const String& TransitionEvent::pseudoElement() const
+{
+    return m_pseudoElement;
+}
+
+const AtomicString& TransitionEvent::interfaceName() const
+{
+    return eventNames().interfaceForTransitionEvent;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/TransitionEvent.h b/Source/core/dom/TransitionEvent.h
new file mode 100644
index 0000000..c27ce92
--- /dev/null
+++ b/Source/core/dom/TransitionEvent.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef TransitionEvent_h
+#define TransitionEvent_h
+
+#include "core/dom/Event.h"
+
+namespace WebCore {
+
+struct TransitionEventInit : public EventInit {
+    TransitionEventInit();
+
+    String propertyName;
+    double elapsedTime;
+    String pseudoElement;
+};
+
+class TransitionEvent : public Event {
+public:
+    static PassRefPtr<TransitionEvent> create()
+    {
+        return adoptRef(new TransitionEvent);
+    }
+    static PassRefPtr<TransitionEvent> create(const AtomicString& type, const String& propertyName, double elapsedTime, const String& pseudoElement)
+    {
+        return adoptRef(new TransitionEvent(type, propertyName, elapsedTime, pseudoElement));
+    }
+    static PassRefPtr<TransitionEvent> create(const AtomicString& type, const TransitionEventInit& initializer)
+    {
+        return adoptRef(new TransitionEvent(type, initializer));
+    }
+
+    virtual ~TransitionEvent();
+
+    const String& propertyName() const;
+    double elapsedTime() const;
+    const String& pseudoElement() const;
+
+    virtual const AtomicString& interfaceName() const;
+
+private:
+    TransitionEvent();
+    TransitionEvent(const AtomicString& type, const String& propertyName, double elapsedTime, const String& pseudoElement);
+    TransitionEvent(const AtomicString& type, const TransitionEventInit& initializer);
+
+    String m_propertyName;
+    double m_elapsedTime;
+    String m_pseudoElement;
+};
+
+} // namespace WebCore
+
+#endif // TransitionEvent_h
+
diff --git a/Source/core/dom/TransitionEvent.idl b/Source/core/dom/TransitionEvent.idl
new file mode 100644
index 0000000..afce660
--- /dev/null
+++ b/Source/core/dom/TransitionEvent.idl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+[
+    ConstructorTemplate=Event
+] interface TransitionEvent : Event {
+    [InitializedByEventConstructor] readonly attribute DOMString propertyName;
+    [InitializedByEventConstructor] readonly attribute double elapsedTime;
+    [InitializedByEventConstructor] readonly attribute DOMString pseudoElement;
+};
+
diff --git a/Source/core/dom/Traversal.cpp b/Source/core/dom/Traversal.cpp
new file mode 100644
index 0000000..207480c
--- /dev/null
+++ b/Source/core/dom/Traversal.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/Traversal.h"
+
+#include "core/dom/Node.h"
+#include "core/dom/NodeFilter.h"
+
+namespace WebCore {
+
+Traversal::Traversal(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> nodeFilter, bool expandEntityReferences)
+    : m_root(rootNode)
+    , m_whatToShow(whatToShow)
+    , m_filter(nodeFilter)
+    , m_expandEntityReferences(expandEntityReferences)
+{
+}
+
+short Traversal::acceptNode(ScriptState* state, Node* node) const
+{
+    // FIXME: To handle XML properly we would have to check m_expandEntityReferences.
+
+    // The bit twiddling here is done to map DOM node types, which are given as integers from
+    // 1 through 14, to whatToShow bit masks.
+    if (!(((1 << (node->nodeType() - 1)) & m_whatToShow)))
+        return NodeFilter::FILTER_SKIP;
+    if (!m_filter)
+        return NodeFilter::FILTER_ACCEPT;
+    return m_filter->acceptNode(state, node);
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/Traversal.h b/Source/core/dom/Traversal.h
new file mode 100644
index 0000000..45cd76e
--- /dev/null
+++ b/Source/core/dom/Traversal.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Traversal_h
+#define Traversal_h
+
+#include "bindings/v8/ScriptState.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+    class Node;
+    class NodeFilter;
+
+    class Traversal {
+    public:
+        Node* root() const { return m_root.get(); }
+        unsigned whatToShow() const { return m_whatToShow; }
+        NodeFilter* filter() const { return m_filter.get(); }
+        bool expandEntityReferences() const { return m_expandEntityReferences; }
+
+    protected:
+        Traversal(PassRefPtr<Node>, unsigned whatToShow, PassRefPtr<NodeFilter>, bool expandEntityReferences);
+        short acceptNode(ScriptState*, Node*) const;
+
+    private:
+        RefPtr<Node> m_root;
+        unsigned m_whatToShow;
+        RefPtr<NodeFilter> m_filter;
+        bool m_expandEntityReferences;
+    };
+
+} // namespace WebCore
+
+#endif // Traversal_h
diff --git a/Source/core/dom/TreeScope.cpp b/Source/core/dom/TreeScope.cpp
new file mode 100644
index 0000000..db2a3ff
--- /dev/null
+++ b/Source/core/dom/TreeScope.cpp
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2011 Google Inc. All Rights Reserved.
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/TreeScope.h"
+
+#include "HTMLNames.h"
+#include "core/dom/ContainerNode.h"
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/EventPathWalker.h"
+#include "core/dom/IdTargetObserverRegistry.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/dom/TreeScopeAdopter.h"
+#include "core/html/HTMLAnchorElement.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/html/HTMLLabelElement.h"
+#include "core/html/HTMLMapElement.h"
+#include "core/html/shadow/InsertionPoint.h"
+#include "core/page/DOMSelection.h"
+#include "core/page/DOMWindow.h"
+#include "core/page/FocusController.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "RuntimeEnabledFeatures.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderView.h"
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/CString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+struct SameSizeAsTreeScope {
+    virtual ~SameSizeAsTreeScope();
+    void* pointers[8];
+    int ints[1];
+};
+
+COMPILE_ASSERT(sizeof(TreeScope) == sizeof(SameSizeAsTreeScope), treescope_should_stay_small);
+
+using namespace HTMLNames;
+
+TreeScope::TreeScope(ContainerNode* rootNode, Document* document)
+    : m_rootNode(rootNode)
+    , m_documentScope(document)
+    , m_parentTreeScope(document)
+    , m_guardRefCount(0)
+    , m_idTargetObserverRegistry(IdTargetObserverRegistry::create())
+{
+    ASSERT(rootNode);
+    ASSERT(document);
+    ASSERT(rootNode != document);
+    m_parentTreeScope->guardRef();
+    m_rootNode->setTreeScope(this);
+}
+
+TreeScope::TreeScope(Document* document)
+    : m_rootNode(document)
+    , m_documentScope(document)
+    , m_parentTreeScope(0)
+    , m_guardRefCount(0)
+    , m_idTargetObserverRegistry(IdTargetObserverRegistry::create())
+{
+    ASSERT(document);
+    m_rootNode->setTreeScope(this);
+}
+
+TreeScope::TreeScope()
+    : m_rootNode(0)
+    , m_documentScope(0)
+    , m_parentTreeScope(0)
+    , m_guardRefCount(0)
+{
+}
+
+TreeScope::~TreeScope()
+{
+    ASSERT(!m_guardRefCount);
+    m_rootNode->setTreeScope(noDocumentInstance());
+
+    if (m_selection) {
+        m_selection->clearTreeScope();
+        m_selection = 0;
+    }
+
+    if (m_parentTreeScope)
+        m_parentTreeScope->guardDeref();
+}
+
+void TreeScope::destroyTreeScopeData()
+{
+    m_elementsById.clear();
+    m_imageMapsByName.clear();
+    m_labelsByForAttribute.clear();
+}
+
+void TreeScope::clearDocumentScope()
+{
+    ASSERT(rootNode()->isDocumentNode());
+    m_documentScope = 0;
+}
+
+void TreeScope::setParentTreeScope(TreeScope* newParentScope)
+{
+    // A document node cannot be re-parented.
+    ASSERT(!rootNode()->isDocumentNode());
+    // Every scope other than document needs a parent scope.
+    ASSERT(newParentScope);
+
+    newParentScope->guardRef();
+    if (m_parentTreeScope)
+        m_parentTreeScope->guardDeref();
+    m_parentTreeScope = newParentScope;
+    setDocumentScope(newParentScope->documentScope());
+}
+
+Element* TreeScope::getElementById(const AtomicString& elementId) const
+{
+    if (elementId.isEmpty())
+        return 0;
+    if (!m_elementsById)
+        return 0;
+    return m_elementsById->getElementById(elementId.impl(), this);
+}
+
+void TreeScope::addElementById(const AtomicString& elementId, Element* element)
+{
+    if (!m_elementsById)
+        m_elementsById = adoptPtr(new DocumentOrderedMap);
+    m_elementsById->add(elementId.impl(), element);
+    m_idTargetObserverRegistry->notifyObservers(elementId);
+}
+
+void TreeScope::removeElementById(const AtomicString& elementId, Element* element)
+{
+    if (!m_elementsById)
+        return;
+    m_elementsById->remove(elementId.impl(), element);
+    m_idTargetObserverRegistry->notifyObservers(elementId);
+}
+
+Node* TreeScope::ancestorInThisScope(Node* node) const
+{
+    while (node) {
+        if (node->treeScope() == this)
+            return node;
+        if (!node->isInShadowTree())
+            return 0;
+
+        node = node->shadowHost();
+    }
+
+    return 0;
+}
+
+void TreeScope::addImageMap(HTMLMapElement* imageMap)
+{
+    AtomicStringImpl* name = imageMap->getName().impl();
+    if (!name)
+        return;
+    if (!m_imageMapsByName)
+        m_imageMapsByName = adoptPtr(new DocumentOrderedMap);
+    m_imageMapsByName->add(name, imageMap);
+}
+
+void TreeScope::removeImageMap(HTMLMapElement* imageMap)
+{
+    if (!m_imageMapsByName)
+        return;
+    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;
+    if (!m_imageMapsByName)
+        return 0;
+    size_t hashPos = url.find('#');
+    String name = (hashPos == notFound ? url : url.substring(hashPos + 1)).impl();
+    if (rootNode()->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));
+}
+
+Node* nodeFromPoint(Document* document, int x, int y, LayoutPoint* localPoint)
+{
+    Frame* frame = document->frame();
+
+    if (!frame)
+        return 0;
+    FrameView* frameView = frame->view();
+    if (!frameView)
+        return 0;
+
+    float scaleFactor = frame->pageZoomFactor();
+    IntPoint point = roundedIntPoint(FloatPoint(x * scaleFactor  + frameView->scrollX(), y * scaleFactor + frameView->scrollY()));
+
+    if (!frameView->visibleContentRect().contains(point))
+        return 0;
+
+    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
+    HitTestResult result(point);
+    document->renderView()->hitTest(request, result);
+
+    if (localPoint)
+        *localPoint = result.localPoint();
+
+    return result.innerNode();
+}
+
+Element* TreeScope::elementFromPoint(int x, int y) const
+{
+    Node* node = nodeFromPoint(rootNode()->document(), x, y);
+    while (node && !node->isElementNode())
+        node = node->parentNode();
+    if (node)
+        node = ancestorInThisScope(node);
+    return toElement(node);
+}
+
+void TreeScope::addLabel(const AtomicString& forAttributeValue, HTMLLabelElement* element)
+{
+    ASSERT(m_labelsByForAttribute);
+    m_labelsByForAttribute->add(forAttributeValue.impl(), element);
+}
+
+void TreeScope::removeLabel(const AtomicString& forAttributeValue, HTMLLabelElement* element)
+{
+    ASSERT(m_labelsByForAttribute);
+    m_labelsByForAttribute->remove(forAttributeValue.impl(), element);
+}
+
+HTMLLabelElement* TreeScope::labelElementForId(const AtomicString& forAttributeValue)
+{
+    if (forAttributeValue.isEmpty())
+        return 0;
+
+    if (!m_labelsByForAttribute) {
+        // Populate the map on first access.
+        m_labelsByForAttribute = adoptPtr(new DocumentOrderedMap);
+        for (Element* element = ElementTraversal::firstWithin(rootNode()); element; element = ElementTraversal::next(element)) {
+            if (element->hasTagName(labelTag)) {
+                HTMLLabelElement* label = static_cast<HTMLLabelElement*>(element);
+                const AtomicString& forValue = label->fastGetAttribute(forAttr);
+                if (!forValue.isEmpty())
+                    addLabel(forValue, label);
+            }
+        }
+    }
+
+    return static_cast<HTMLLabelElement*>(m_labelsByForAttribute->getElementByLabelForAttribute(forAttributeValue.impl(), this));
+}
+
+DOMSelection* TreeScope::getSelection() const
+{
+    if (!rootNode()->document()->frame())
+        return 0;
+
+    if (m_selection)
+        return m_selection.get();
+
+    // FIXME: The correct selection in Shadow DOM requires that Position can have a ShadowRoot
+    // as a container.
+    // See https://bugs.webkit.org/show_bug.cgi?id=82697
+    m_selection = DOMSelection::create(this);
+    return m_selection.get();
+}
+
+Element* TreeScope::findAnchor(const String& name)
+{
+    if (name.isEmpty())
+        return 0;
+    if (Element* element = getElementById(name))
+        return element;
+    for (Element* element = ElementTraversal::firstWithin(rootNode()); element; element = ElementTraversal::next(element)) {
+        if (element->hasTagName(aTag)) {
+            HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(element);
+            if (rootNode()->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;
+}
+
+bool TreeScope::applyAuthorStyles() const
+{
+    return true;
+}
+
+bool TreeScope::resetStyleInheritance() const
+{
+    return false;
+}
+
+void TreeScope::adoptIfNeeded(Node* node)
+{
+    ASSERT(this);
+    ASSERT(node);
+    ASSERT(!node->isDocumentNode());
+    ASSERT(!node->m_deletionHasBegun);
+    TreeScopeAdopter adopter(node, this);
+    if (adopter.needsScopeChange())
+        adopter.execute();
+}
+
+static Node* focusedFrameOwnerElement(Frame* focusedFrame, Frame* currentFrame)
+{
+    for (; focusedFrame; focusedFrame = focusedFrame->tree()->parent()) {
+        if (focusedFrame->tree()->parent() == currentFrame)
+            return focusedFrame->ownerElement();
+    }
+    return 0;
+}
+
+Node* TreeScope::focusedNode()
+{
+    Document* document = rootNode()->document();
+    Node* node = document->focusedNode();
+    if (!node && document->page())
+        node = focusedFrameOwnerElement(document->page()->focusController()->focusedFrame(), document->frame());
+    if (!node)
+        return 0;
+    Vector<Node*> targetStack;
+    for (EventPathWalker walker(node); walker.node(); walker.moveToParent()) {
+        Node* node = walker.node();
+        if (targetStack.isEmpty())
+            targetStack.append(node);
+        else if (walker.isVisitingInsertionPointInReprojection())
+            targetStack.append(targetStack.last());
+        if (node == rootNode())
+            return targetStack.last();
+        if (node->isShadowRoot()) {
+            ASSERT(!targetStack.isEmpty());
+            targetStack.removeLast();
+        }
+    }
+    return 0;
+}
+
+void TreeScope::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
+    info.addMember(m_rootNode, "rootNode");
+    info.addMember(m_parentTreeScope, "parentTreeScope");
+    info.addMember(m_elementsById, "elementsById");
+    info.addMember(m_imageMapsByName, "imageMapsByName");
+    info.addMember(m_labelsByForAttribute, "labelsByForAttribute");
+    info.addMember(m_idTargetObserverRegistry, "idTargetObserverRegistry");
+    info.addMember(m_selection, "selection");
+    info.addMember(m_documentScope, "documentScope");
+
+}
+
+static void listTreeScopes(Node* node, Vector<TreeScope*, 5>& treeScopes)
+{
+    while (true) {
+        treeScopes.append(node->treeScope());
+        Element* ancestor = node->shadowHost();
+        if (!ancestor)
+            break;
+        node = ancestor;
+    }
+}
+
+TreeScope* commonTreeScope(Node* nodeA, Node* nodeB)
+{
+    if (!nodeA || !nodeB)
+        return 0;
+
+    if (nodeA->treeScope() == nodeB->treeScope())
+        return nodeA->treeScope();
+
+    Vector<TreeScope*, 5> treeScopesA;
+    listTreeScopes(nodeA, treeScopesA);
+
+    Vector<TreeScope*, 5> treeScopesB;
+    listTreeScopes(nodeB, treeScopesB);
+
+    size_t indexA = treeScopesA.size();
+    size_t indexB = treeScopesB.size();
+
+    for (; indexA > 0 && indexB > 0 && treeScopesA[indexA - 1] == treeScopesB[indexB - 1]; --indexA, --indexB) { }
+
+    return treeScopesA[indexA] == treeScopesB[indexB] ? treeScopesA[indexA] : 0;
+}
+
+#ifndef NDEBUG
+bool TreeScope::deletionHasBegun()
+{
+    return rootNode() && rootNode()->m_deletionHasBegun;
+}
+
+void TreeScope::beginDeletion()
+{
+    ASSERT(this != noDocumentInstance());
+    rootNode()->m_deletionHasBegun = true;
+}
+#endif
+
+int TreeScope::refCount() const
+{
+    if (Node* root = rootNode())
+        return root->refCount();
+    return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/TreeScope.h b/Source/core/dom/TreeScope.h
new file mode 100644
index 0000000..0d04f88
--- /dev/null
+++ b/Source/core/dom/TreeScope.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2011 Google Inc. All Rights Reserved.
+ * Copyright (C) 2012 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TreeScope_h
+#define TreeScope_h
+
+#include "core/dom/DocumentOrderedMap.h"
+#include <wtf/Forward.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class ContainerNode;
+class DOMSelection;
+class Document;
+class Element;
+class HTMLLabelElement;
+class HTMLMapElement;
+class LayoutPoint;
+class IdTargetObserverRegistry;
+class Node;
+
+// A class which inherits both Node and TreeScope must call clearRareData() in its destructor
+// so that the Node destructor no longer does problematic NodeList cache manipulation in
+// the destructor.
+class TreeScope {
+    friend class Document;
+    friend class TreeScopeAdopter;
+
+public:
+    TreeScope* parentTreeScope() const { return m_parentTreeScope; }
+    void setParentTreeScope(TreeScope*);
+
+    Node* focusedNode();
+    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*);
+
+    Document* documentScope() const { return m_documentScope; }
+
+    Node* ancestorInThisScope(Node*) const;
+
+    void addImageMap(HTMLMapElement*);
+    void removeImageMap(HTMLMapElement*);
+    HTMLMapElement* getImageMap(const String& url) const;
+
+    Element* elementFromPoint(int x, int y) const;
+
+    // For accessibility.
+    bool shouldCacheLabelsByForAttribute() const { return m_labelsByForAttribute; }
+    void addLabel(const AtomicString& forAttributeValue, HTMLLabelElement*);
+    void removeLabel(const AtomicString& forAttributeValue, HTMLLabelElement*);
+    HTMLLabelElement* labelElementForId(const AtomicString& forAttributeValue);
+
+    DOMSelection* getSelection() const;
+
+    // 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);
+
+    virtual bool applyAuthorStyles() const;
+    virtual bool resetStyleInheritance() const;
+
+    // Used by the basic DOM mutation methods (e.g., appendChild()).
+    void adoptIfNeeded(Node*);
+
+    Node* rootNode() const { return m_rootNode; }
+
+    IdTargetObserverRegistry& idTargetObserverRegistry() const { return *m_idTargetObserverRegistry.get(); }
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+
+    static TreeScope* noDocumentInstance()
+    {
+        DEFINE_STATIC_LOCAL(TreeScope, instance, ());
+        return &instance;
+    }
+
+    // Nodes belonging to this scope hold guard references -
+    // these are enough to keep the scope from being destroyed, but
+    // not enough to keep it from removing its children. This allows a
+    // node that outlives its scope to still have a valid document
+    // pointer without introducing reference cycles.
+    void guardRef()
+    {
+        ASSERT(!deletionHasBegun());
+        ++m_guardRefCount;
+    }
+
+    void guardDeref()
+    {
+        ASSERT(!deletionHasBegun());
+        --m_guardRefCount;
+        if (!m_guardRefCount && !refCount() && this != noDocumentInstance()) {
+            beginDeletion();
+            delete this;
+        }
+    }
+
+    void removedLastRefToScope();
+
+protected:
+    TreeScope(ContainerNode*, Document*);
+    TreeScope(Document*);
+    virtual ~TreeScope();
+
+    void destroyTreeScopeData();
+    void clearDocumentScope();
+    void setDocumentScope(Document* document)
+    {
+        ASSERT(document);
+        ASSERT(this != noDocumentInstance());
+        m_documentScope = document;
+    }
+
+    bool hasGuardRefCount() const { return m_guardRefCount; }
+
+private:
+    TreeScope();
+
+    virtual void dispose() { }
+
+    int refCount() const;
+#ifndef NDEBUG
+    bool deletionHasBegun();
+    void beginDeletion();
+#else
+    bool deletionHasBegun() { return false; }
+    void beginDeletion() { }
+#endif
+
+    Node* m_rootNode;
+    Document* m_documentScope;
+    TreeScope* m_parentTreeScope;
+    int m_guardRefCount;
+
+    OwnPtr<DocumentOrderedMap> m_elementsById;
+    OwnPtr<DocumentOrderedMap> m_imageMapsByName;
+    OwnPtr<DocumentOrderedMap> m_labelsByForAttribute;
+
+    OwnPtr<IdTargetObserverRegistry> m_idTargetObserverRegistry;
+
+    mutable RefPtr<DOMSelection> m_selection;
+};
+
+inline bool TreeScope::hasElementWithId(AtomicStringImpl* id) const
+{
+    ASSERT(id);
+    return m_elementsById && m_elementsById->contains(id);
+}
+
+inline bool TreeScope::containsMultipleElementsWithId(const AtomicString& id) const
+{
+    return m_elementsById && m_elementsById->containsMultiple(id.impl());
+}
+
+Node* nodeFromPoint(Document*, int x, int y, LayoutPoint* localPoint = 0);
+TreeScope* commonTreeScope(Node*, Node*);
+
+} // namespace WebCore
+
+#endif // TreeScope_h
diff --git a/Source/core/dom/TreeScopeAdopter.cpp b/Source/core/dom/TreeScopeAdopter.cpp
new file mode 100644
index 0000000..bd0911f
--- /dev/null
+++ b/Source/core/dom/TreeScopeAdopter.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include "config.h"
+#include "core/dom/TreeScopeAdopter.h"
+
+#include "core/dom/Attr.h"
+#include "core/dom/Document.h"
+#include "core/dom/ElementRareData.h"
+#include "core/dom/ElementShadow.h"
+#include "core/dom/NodeRareData.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/rendering/style/RenderStyle.h"
+
+namespace WebCore {
+
+void TreeScopeAdopter::moveTreeToNewScope(Node* root) const
+{
+    ASSERT(needsScopeChange());
+
+    m_oldScope->guardRef();
+
+    // 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.
+    Document* oldDocument = m_oldScope->documentScope();
+    Document* newDocument = m_newScope->documentScope();
+    bool willMoveToNewDocument = oldDocument != newDocument;
+    if (oldDocument && willMoveToNewDocument)
+        oldDocument->incDOMTreeVersion();
+
+    for (Node* node = root; node; node = NodeTraversal::next(node, root)) {
+        updateTreeScope(node);
+
+        if (willMoveToNewDocument)
+            moveNodeToNewDocument(node, oldDocument, newDocument);
+        else if (node->hasRareData()) {
+            NodeRareData* rareData = node->rareData();
+            if (rareData->nodeLists())
+                rareData->nodeLists()->adoptTreeScope();
+        }
+
+        if (!node->isElementNode())
+            continue;
+
+        if (node->hasSyntheticAttrChildNodes()) {
+            const Vector<RefPtr<Attr> >& attrs = toElement(node)->attrNodeList();
+            for (unsigned i = 0; i < attrs.size(); ++i)
+                moveTreeToNewScope(attrs[i].get());
+        }
+
+        for (ShadowRoot* shadow = node->youngestShadowRoot(); shadow; shadow = shadow->olderShadowRoot()) {
+            shadow->setParentTreeScope(m_newScope);
+            if (willMoveToNewDocument)
+                moveTreeToNewDocument(shadow, oldDocument, newDocument);
+        }
+    }
+
+    m_oldScope->guardDeref();
+}
+
+void TreeScopeAdopter::moveTreeToNewDocument(Node* root, Document* oldDocument, Document* newDocument) const
+{
+    for (Node* node = root; node; node = NodeTraversal::next(node, root)) {
+        moveNodeToNewDocument(node, oldDocument, newDocument);
+        for (ShadowRoot* shadow = node->youngestShadowRoot(); shadow; shadow = shadow->olderShadowRoot())
+            moveTreeToNewDocument(shadow, oldDocument, newDocument);
+    }
+}
+
+#ifndef NDEBUG
+static bool didMoveToNewDocumentWasCalled = false;
+static Document* oldDocumentDidMoveToNewDocumentWasCalledWith = 0;
+
+void TreeScopeAdopter::ensureDidMoveToNewDocumentWasCalled(Document* oldDocument)
+{
+    ASSERT(!didMoveToNewDocumentWasCalled);
+    ASSERT_UNUSED(oldDocument, oldDocument == oldDocumentDidMoveToNewDocumentWasCalledWith);
+    didMoveToNewDocumentWasCalled = true;
+}
+#endif
+
+inline void TreeScopeAdopter::updateTreeScope(Node* node) const
+{
+    ASSERT(!node->isTreeScope());
+    ASSERT(node->treeScope() == m_oldScope);
+    m_newScope->guardRef();
+    m_oldScope->guardDeref();
+    node->setTreeScope(m_newScope);
+}
+
+inline void TreeScopeAdopter::moveNodeToNewDocument(Node* node, Document* oldDocument, Document* newDocument) const
+{
+    ASSERT(!node->inDocument() || oldDocument != newDocument);
+
+    if (node->hasRareData()) {
+        NodeRareData* rareData = node->rareData();
+        if (rareData->nodeLists())
+            rareData->nodeLists()->adoptDocument(oldDocument, newDocument);
+    }
+
+    if (oldDocument)
+        oldDocument->moveNodeIteratorsToNewDocument(node, newDocument);
+
+    if (node->isShadowRoot())
+        toShadowRoot(node)->setDocumentScope(newDocument);
+
+#ifndef NDEBUG
+    didMoveToNewDocumentWasCalled = false;
+    oldDocumentDidMoveToNewDocumentWasCalledWith = oldDocument;
+#endif
+
+    node->didMoveToNewDocument(oldDocument);
+    ASSERT(didMoveToNewDocumentWasCalled);
+}
+
+}
diff --git a/Source/core/dom/TreeScopeAdopter.h b/Source/core/dom/TreeScopeAdopter.h
new file mode 100644
index 0000000..a629e9d
--- /dev/null
+++ b/Source/core/dom/TreeScopeAdopter.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef TreeScopeAdopter_h
+#define TreeScopeAdopter_h
+
+#include "core/dom/Node.h"
+
+namespace WebCore {
+
+class TreeScope;
+
+class TreeScopeAdopter {
+public:
+    explicit TreeScopeAdopter(Node* toAdopt, TreeScope* newScope);
+
+    void execute() const { moveTreeToNewScope(m_toAdopt); }
+    bool needsScopeChange() const { return m_oldScope != m_newScope; }
+
+#ifdef NDEBUG
+    static void ensureDidMoveToNewDocumentWasCalled(Document*) { }
+#else
+    static void ensureDidMoveToNewDocumentWasCalled(Document*);
+#endif
+
+private:
+    void updateTreeScope(Node*) const;
+    void moveTreeToNewScope(Node*) const;
+    void moveTreeToNewDocument(Node*, Document* oldDocument, Document* newDocument) const;
+    void moveNodeToNewDocument(Node*, Document* oldDocument, Document* newDocument) const;
+
+    Node* m_toAdopt;
+    TreeScope* m_newScope;
+    TreeScope* m_oldScope;
+};
+
+inline TreeScopeAdopter::TreeScopeAdopter(Node* toAdopt, TreeScope* newScope)
+    : m_toAdopt(toAdopt)
+    , m_newScope(newScope)
+    , m_oldScope(toAdopt->treeScope())
+{
+    ASSERT(newScope);
+}
+
+}
+
+#endif
diff --git a/Source/core/dom/TreeWalker.cpp b/Source/core/dom/TreeWalker.cpp
new file mode 100644
index 0000000..41c8210
--- /dev/null
+++ b/Source/core/dom/TreeWalker.cpp
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/TreeWalker.h"
+
+#include "bindings/v8/ScriptState.h"
+#include "core/dom/ContainerNode.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/NodeFilter.h"
+#include "core/dom/NodeTraversal.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+TreeWalker::TreeWalker(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter, bool expandEntityReferences)
+    : Traversal(rootNode, whatToShow, filter, expandEntityReferences)
+    , m_current(root())
+{
+    ScriptWrappable::init(this);
+}
+
+void TreeWalker::setCurrentNode(PassRefPtr<Node> node, ExceptionCode& ec)
+{
+    if (!node) {
+        ec = NOT_SUPPORTED_ERR;
+        return;
+    }
+    m_current = node;
+}
+
+inline Node* TreeWalker::setCurrent(PassRefPtr<Node> node)
+{
+    m_current = node;
+    return m_current.get();
+}
+
+Node* TreeWalker::parentNode(ScriptState* state)
+{
+    RefPtr<Node> node = m_current;
+    while (node != root()) {
+        node = node->parentNode();
+        if (!node)
+            return 0;
+        short acceptNodeResult = acceptNode(state, node.get());
+        if (state && state->hadException())
+            return 0;
+        if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
+            return setCurrent(node.release());
+    }
+    return 0;
+}
+
+Node* TreeWalker::firstChild(ScriptState* state)
+{
+    for (RefPtr<Node> node = m_current->firstChild(); node; ) {
+        short acceptNodeResult = acceptNode(state, node.get());
+        if (state && state->hadException())
+            return 0;
+        switch (acceptNodeResult) {
+            case NodeFilter::FILTER_ACCEPT:
+                m_current = node.release();
+                return m_current.get();
+            case NodeFilter::FILTER_SKIP:
+                if (node->firstChild()) {
+                    node = node->firstChild();
+                    continue;
+                }
+                break;
+            case NodeFilter::FILTER_REJECT:
+                break;
+        }
+        do {
+            if (node->nextSibling()) {
+                node = node->nextSibling();
+                break;
+            }
+            ContainerNode* parent = node->parentNode();
+            if (!parent || parent == root() || parent == m_current)
+                return 0;
+            node = parent;
+        } while (node);
+    }
+    return 0;
+}
+
+Node* TreeWalker::lastChild(ScriptState* state)
+{
+    for (RefPtr<Node> node = m_current->lastChild(); node; ) {
+        short acceptNodeResult = acceptNode(state, node.get());
+        if (state && state->hadException())
+            return 0;
+        switch (acceptNodeResult) {
+            case NodeFilter::FILTER_ACCEPT:
+                m_current = node.release();
+                return m_current.get();
+            case NodeFilter::FILTER_SKIP:
+                if (node->lastChild()) {
+                    node = node->lastChild();
+                    continue;
+                }
+                break;
+            case NodeFilter::FILTER_REJECT:
+                break;
+        }
+        do {
+            if (node->previousSibling()) {
+                node = node->previousSibling();
+                break;
+            }
+            ContainerNode* parent = node->parentNode();
+            if (!parent || parent == root() || parent == m_current)
+                return 0;
+            node = parent;
+        } while (node);
+    }
+    return 0;
+}
+
+Node* TreeWalker::previousSibling(ScriptState* state)
+{
+    RefPtr<Node> node = m_current;
+    if (node == root())
+        return 0;
+    while (1) {
+        for (RefPtr<Node> sibling = node->previousSibling(); sibling; ) {
+            short acceptNodeResult = acceptNode(state, sibling.get());
+            if (state && state->hadException())
+                return 0;
+            switch (acceptNodeResult) {
+                case NodeFilter::FILTER_ACCEPT:
+                    m_current = sibling.release();
+                    return m_current.get();
+                case NodeFilter::FILTER_SKIP:
+                    if (sibling->lastChild()) {
+                        sibling = sibling->lastChild();
+                        node = sibling;
+                        continue;
+                    }
+                    break;
+                case NodeFilter::FILTER_REJECT:
+                    break;
+            }
+            sibling = sibling->previousSibling();
+        }
+        node = node->parentNode();
+        if (!node || node == root())
+            return 0;
+        short acceptNodeResult = acceptNode(state, node.get());
+        if (state && state->hadException())
+            return 0;
+        if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
+            return 0;
+    }
+}
+
+Node* TreeWalker::nextSibling(ScriptState* state)
+{
+    RefPtr<Node> node = m_current;
+    if (node == root())
+        return 0;
+    while (1) {
+        for (RefPtr<Node> sibling = node->nextSibling(); sibling; ) {
+            short acceptNodeResult = acceptNode(state, sibling.get());
+            if (state && state->hadException())
+                return 0;
+            switch (acceptNodeResult) {
+                case NodeFilter::FILTER_ACCEPT:
+                    m_current = sibling.release();
+                    return m_current.get();
+                case NodeFilter::FILTER_SKIP:
+                    if (sibling->firstChild()) {
+                        sibling = sibling->firstChild();
+                        node = sibling;
+                        continue;
+                    }
+                    break;
+                case NodeFilter::FILTER_REJECT:
+                    break;
+            }
+            sibling = sibling->nextSibling();
+        }
+        node = node->parentNode();
+        if (!node || node == root())
+            return 0;
+        short acceptNodeResult = acceptNode(state, node.get());
+        if (state && state->hadException())
+            return 0;
+        if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
+            return 0;
+    }
+}
+
+Node* TreeWalker::previousNode(ScriptState* state)
+{
+    RefPtr<Node> node = m_current;
+    while (node != root()) {
+        while (Node* previousSibling = node->previousSibling()) {
+            node = previousSibling;
+            short acceptNodeResult = acceptNode(state, node.get());
+            if (state && state->hadException())
+                return 0;
+            if (acceptNodeResult == NodeFilter::FILTER_REJECT)
+                continue;
+            while (Node* lastChild = node->lastChild()) {
+                node = lastChild;
+                acceptNodeResult = acceptNode(state, node.get());
+                if (state && state->hadException())
+                    return 0;
+                if (acceptNodeResult == NodeFilter::FILTER_REJECT)
+                    break;
+            }
+            if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) {
+                m_current = node.release();
+                return m_current.get();
+            }
+        }
+        if (node == root())
+            return 0;
+        ContainerNode* parent = node->parentNode();
+        if (!parent)
+            return 0;
+        node = parent;
+        short acceptNodeResult = acceptNode(state, node.get());
+        if (state && state->hadException())
+            return 0;
+        if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
+            return setCurrent(node.release());
+    }
+    return 0;
+}
+
+Node* TreeWalker::nextNode(ScriptState* state)
+{
+    RefPtr<Node> node = m_current;
+Children:
+    while (Node* firstChild = node->firstChild()) {
+        node = firstChild;
+        short acceptNodeResult = acceptNode(state, node.get());
+        if (state && state->hadException())
+            return 0;
+        if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
+            return setCurrent(node.release());
+        if (acceptNodeResult == NodeFilter::FILTER_REJECT)
+            break;
+    }
+    while (Node* nextSibling = NodeTraversal::nextSkippingChildren(node.get(), root())) {
+        node = nextSibling;
+        short acceptNodeResult = acceptNode(state, node.get());
+        if (state && state->hadException())
+            return 0;
+        if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
+            return setCurrent(node.release());
+        if (acceptNodeResult == NodeFilter::FILTER_SKIP)
+            goto Children;
+    }
+    return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/TreeWalker.h b/Source/core/dom/TreeWalker.h
new file mode 100644
index 0000000..0fce42f
--- /dev/null
+++ b/Source/core/dom/TreeWalker.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TreeWalker_h
+#define TreeWalker_h
+
+#include "bindings/v8/ScriptWrappable.h"
+#include "core/dom/NodeFilter.h"
+#include "core/dom/Traversal.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+    typedef int ExceptionCode;
+
+    class TreeWalker : public ScriptWrappable, public RefCounted<TreeWalker>, public Traversal {
+    public:
+        static PassRefPtr<TreeWalker> create(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter, bool expandEntityReferences)
+        {
+            return adoptRef(new TreeWalker(rootNode, whatToShow, filter, expandEntityReferences));
+        }                            
+
+        Node* currentNode() const { return m_current.get(); }
+        void setCurrentNode(PassRefPtr<Node>, ExceptionCode&);
+
+        Node* parentNode(ScriptState*);
+        Node* firstChild(ScriptState*);
+        Node* lastChild(ScriptState*);
+        Node* previousSibling(ScriptState*);
+        Node* nextSibling(ScriptState*);
+        Node* previousNode(ScriptState*);
+        Node* nextNode(ScriptState*);
+
+    private:
+        TreeWalker(PassRefPtr<Node>, unsigned whatToShow, PassRefPtr<NodeFilter>, bool expandEntityReferences);
+        
+        Node* setCurrent(PassRefPtr<Node>);
+
+        RefPtr<Node> m_current;
+    };
+
+} // namespace WebCore
+
+#endif // TreeWalker_h
diff --git a/Source/core/dom/TreeWalker.idl b/Source/core/dom/TreeWalker.idl
new file mode 100644
index 0000000..7a81fec
--- /dev/null
+++ b/Source/core/dom/TreeWalker.idl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+// Introduced in DOM Level 2:
+[
+    ImplementationLacksVTable
+] interface TreeWalker {
+    readonly attribute Node root;
+    readonly attribute unsigned long whatToShow;
+    readonly attribute NodeFilter filter;
+    readonly attribute boolean expandEntityReferences;        
+             [SetterRaisesException] attribute Node currentNode;
+
+    [CallWith=ScriptState] Node parentNode();
+    [CallWith=ScriptState] Node firstChild();
+    [CallWith=ScriptState] Node lastChild();
+    [CallWith=ScriptState] Node previousSibling();
+    [CallWith=ScriptState] Node nextSibling();
+    [CallWith=ScriptState] Node previousNode();
+    [CallWith=ScriptState] Node nextNode();
+};
+
diff --git a/Source/core/dom/UIEvent.cpp b/Source/core/dom/UIEvent.cpp
new file mode 100644
index 0000000..641ebe6
--- /dev/null
+++ b/Source/core/dom/UIEvent.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/UIEvent.h"
+
+#include "core/dom/EventDispatcher.h"
+#include "core/dom/Node.h"
+#include "core/page/Console.h"
+#include "core/page/DOMWindow.h"
+
+namespace WebCore {
+
+UIEventInit::UIEventInit()
+    : view(0)
+    , detail(0)
+{
+}
+
+UIEvent::UIEvent()
+    : m_detail(0)
+{
+    ScriptWrappable::init(this);
+}
+
+UIEvent::UIEvent(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg, PassRefPtr<AbstractView> viewArg, int detailArg)
+    : Event(eventType, canBubbleArg, cancelableArg)
+    , m_view(viewArg)
+    , m_detail(detailArg)
+{
+    ScriptWrappable::init(this);
+}
+
+UIEvent::UIEvent(const AtomicString& eventType, const UIEventInit& initializer)
+    : Event(eventType, initializer)
+    , m_view(initializer.view)
+    , m_detail(initializer.detail)
+{
+    ScriptWrappable::init(this);
+}
+
+UIEvent::~UIEvent()
+{
+}
+
+void UIEvent::initUIEvent(const AtomicString& typeArg, bool canBubbleArg, bool cancelableArg, PassRefPtr<AbstractView> viewArg, int detailArg)
+{
+    if (dispatched())
+        return;
+
+    initEvent(typeArg, canBubbleArg, cancelableArg);
+
+    m_view = viewArg;
+    m_detail = detailArg;
+}
+
+bool UIEvent::isUIEvent() const
+{
+    return true;
+}
+
+const AtomicString& UIEvent::interfaceName() const
+{
+    return eventNames().interfaceForUIEvent;
+}
+
+int UIEvent::keyCode() const
+{
+    return 0;
+}
+
+int UIEvent::charCode() const
+{
+    return 0;
+}
+
+int UIEvent::layerX()
+{
+    return 0;
+}
+
+int UIEvent::layerY()
+{
+    return 0;
+}
+
+int UIEvent::pageX() const
+{
+    return 0;
+}
+
+int UIEvent::pageY() const
+{
+    return 0;
+}
+
+int UIEvent::which() const
+{
+    return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/UIEvent.h b/Source/core/dom/UIEvent.h
new file mode 100644
index 0000000..ae52a89
--- /dev/null
+++ b/Source/core/dom/UIEvent.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef UIEvent_h
+#define UIEvent_h
+
+#include "core/dom/Event.h"
+#include "core/dom/EventDispatchMediator.h"
+#include "core/page/DOMWindow.h"
+
+namespace WebCore {
+
+typedef DOMWindow AbstractView;
+
+struct UIEventInit : public EventInit {
+    UIEventInit();
+
+    RefPtr<AbstractView> view;
+    int detail;
+};
+
+class UIEvent : public Event {
+public:
+    static PassRefPtr<UIEvent> create()
+    {
+        return adoptRef(new UIEvent);
+    }
+    static PassRefPtr<UIEvent> create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView> view, int detail)
+    {
+        return adoptRef(new UIEvent(type, canBubble, cancelable, view, detail));
+    }
+    static PassRefPtr<UIEvent> create(const AtomicString& type, const UIEventInit& initializer)
+    {
+        return adoptRef(new UIEvent(type, initializer));
+    }
+    virtual ~UIEvent();
+
+    void initUIEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>, int detail);
+
+    AbstractView* view() const { return m_view.get(); }
+    int detail() const { return m_detail; }
+
+    virtual const AtomicString& interfaceName() const;
+    virtual bool isUIEvent() const;
+
+    virtual int keyCode() const;
+    virtual int charCode() const;
+
+    virtual int layerX();
+    virtual int layerY();
+
+    virtual int pageX() const;
+    virtual int pageY() const;
+
+    virtual int which() const;
+
+protected:
+    UIEvent();
+    UIEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>, int detail);
+    UIEvent(const AtomicString&, const UIEventInit&);
+
+private:
+    RefPtr<AbstractView> m_view;
+    int m_detail;
+};
+
+} // namespace WebCore
+
+#endif // UIEvent_h
diff --git a/Source/core/dom/UIEvent.idl b/Source/core/dom/UIEvent.idl
new file mode 100644
index 0000000..415078a
--- /dev/null
+++ b/Source/core/dom/UIEvent.idl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+[
+    ConstructorTemplate=Event
+] interface UIEvent : Event {
+    [InitializedByEventConstructor] readonly attribute DOMWindow view;
+    [InitializedByEventConstructor] readonly attribute long detail;
+    
+     void initUIEvent([Default=Undefined] optional DOMString type, 
+                                    [Default=Undefined] optional boolean canBubble, 
+                                    [Default=Undefined] optional boolean cancelable, 
+                                    [Default=Undefined] optional DOMWindow view, 
+                                    [Default=Undefined] optional long detail);
+
+    // extensions
+    readonly attribute long                 keyCode;
+    readonly attribute long                 charCode;
+    readonly attribute long                 layerX;
+    readonly attribute long                 layerY;
+    readonly attribute long                 pageX;
+    readonly attribute long                 pageY;
+    readonly attribute long                 which;
+};
+
diff --git a/Source/core/dom/UIEventWithKeyState.cpp b/Source/core/dom/UIEventWithKeyState.cpp
new file mode 100644
index 0000000..176eaa7
--- /dev/null
+++ b/Source/core/dom/UIEventWithKeyState.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/UIEventWithKeyState.h"
+
+namespace WebCore {
+    
+UIEventWithKeyState* findEventWithKeyState(Event* event)
+{
+    for (Event* e = event; e; e = e->underlyingEvent())
+        if (e->isKeyboardEvent() || e->isMouseEvent())
+            return static_cast<UIEventWithKeyState*>(e);
+    return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/UIEventWithKeyState.h b/Source/core/dom/UIEventWithKeyState.h
new file mode 100644
index 0000000..64fca1f
--- /dev/null
+++ b/Source/core/dom/UIEventWithKeyState.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef UIEventWithKeyState_h
+#define UIEventWithKeyState_h
+
+#include "core/dom/UIEvent.h"
+
+namespace WebCore {
+    
+    class UIEventWithKeyState : public UIEvent {
+    public:
+        bool ctrlKey() const { return m_ctrlKey; }
+        bool shiftKey() const { return m_shiftKey; }
+        bool altKey() const { return m_altKey; }
+        bool metaKey() const { return m_metaKey; }
+
+    protected:
+        UIEventWithKeyState()
+            : m_ctrlKey(false)
+            , m_altKey(false)
+            , m_shiftKey(false)
+            , m_metaKey(false)
+        {
+        }
+        
+        UIEventWithKeyState(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView> view,
+                            int detail, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey)
+            : UIEvent(type, canBubble, cancelable, view, detail)
+            , m_ctrlKey(ctrlKey)
+            , m_altKey(altKey)
+            , m_shiftKey(shiftKey)
+            , m_metaKey(metaKey)
+        {
+        }
+
+        // Expose these so init functions can set them.
+        bool m_ctrlKey : 1;
+        bool m_altKey : 1;
+        bool m_shiftKey : 1;
+        bool m_metaKey : 1;
+    };
+
+    UIEventWithKeyState* findEventWithKeyState(Event*);
+
+} // namespace WebCore
+
+#endif // UIEventWithKeyState_h
diff --git a/Source/core/dom/UserActionElementSet.cpp b/Source/core/dom/UserActionElementSet.cpp
new file mode 100644
index 0000000..03268fe
--- /dev/null
+++ b/Source/core/dom/UserActionElementSet.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2012 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 "core/dom/UserActionElementSet.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/Node.h"
+
+namespace WebCore {
+
+UserActionElementSet::UserActionElementSet()
+{
+}
+
+UserActionElementSet::~UserActionElementSet()
+{
+}
+
+void UserActionElementSet::didDetach(Node* node)
+{
+    ASSERT(node->isUserActionElement());
+    clearFlags(toElement(node), IsActiveFlag | InActiveChainFlag | IsHoveredFlag);
+}
+
+void UserActionElementSet::documentDidRemoveLastRef()
+{
+    m_elements.clear();
+}
+
+bool UserActionElementSet::hasFlags(const Node* node, unsigned flags) const
+{
+    ASSERT(node->isUserActionElement() && node->isElementNode());
+    return hasFlags(toElement(node), flags);
+}
+
+void UserActionElementSet::setFlags(Node* node, unsigned flags)
+{
+    if (!node->isElementNode())
+        return;
+    return setFlags(toElement(node), flags);
+}
+
+void UserActionElementSet::clearFlags(Node* node, unsigned flags)
+{
+    if (!node->isElementNode())
+        return;
+    return clearFlags(toElement(node), flags);
+}
+
+inline bool UserActionElementSet::hasFlags(const Element* element, unsigned flags) const
+{
+    ASSERT(element->isUserActionElement());
+    ElementFlagMap::const_iterator found = m_elements.find(const_cast<Element*>(element));
+    if (found == m_elements.end())
+        return false;
+    return found->value & flags;
+}
+
+inline void UserActionElementSet::clearFlags(Element* element, unsigned flags)
+{
+    if (!element->isUserActionElement()) {
+        ASSERT(m_elements.end() == m_elements.find(element));
+        return;
+    }
+
+    ElementFlagMap::iterator found = m_elements.find(element);
+    if (found == m_elements.end()) {
+        element->setUserActionElement(false);
+        return;
+    }
+
+    unsigned updated = found->value & ~flags;
+    if (!updated) {
+        element->setUserActionElement(false);
+        m_elements.remove(found);
+        return;
+    }
+
+    found->value = updated;
+}
+
+inline void UserActionElementSet::setFlags(Element* element, unsigned flags)
+{
+    ElementFlagMap::iterator result = m_elements.find(element);
+    if (result != m_elements.end()) {
+        ASSERT(element->isUserActionElement());
+        result->value |= flags;
+        return;
+    }
+
+    element->setUserActionElement(true);
+    m_elements.add(element, flags);
+}
+
+}
diff --git a/Source/core/dom/UserActionElementSet.h b/Source/core/dom/UserActionElementSet.h
new file mode 100644
index 0000000..fa4d53f
--- /dev/null
+++ b/Source/core/dom/UserActionElementSet.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 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 UserActionElementSet_h
+#define UserActionElementSet_h
+
+#include <wtf/HashMap.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Node;
+class Element;
+
+class UserActionElementSet {
+public:
+    static PassOwnPtr<UserActionElementSet> create() { return adoptPtr(new UserActionElementSet()); }
+
+    bool isFocused(const Node* node) { return hasFlags(node, IsFocusedFlag); }
+    bool isActive(const Node* node) { return hasFlags(node, IsActiveFlag); }
+    bool isInActiveChain(const Node* node) { return hasFlags(node, InActiveChainFlag); }
+    bool isHovered(const Node* node) { return hasFlags(node, IsHoveredFlag); }
+    void setFocused(Node* node, bool enable) { setFlags(node, enable, IsFocusedFlag); }
+    void setActive(Node* node, bool enable) { setFlags(node, enable, IsActiveFlag); }
+    void setInActiveChain(Node* node, bool enable) { setFlags(node, enable, InActiveChainFlag); }
+    void setHovered(Node* node, bool enable) { setFlags(node, enable, IsHoveredFlag); }
+
+    UserActionElementSet();
+    ~UserActionElementSet();
+
+    void didDetach(Node*);
+    void documentDidRemoveLastRef();
+
+private:
+    enum ElementFlags {
+        IsActiveFlag      = 1 ,
+        InActiveChainFlag = 1 << 1,
+        IsHoveredFlag     = 1 << 2,
+        IsFocusedFlag     = 1 << 3
+    };
+
+    void setFlags(Node* node, bool enable, unsigned flags) { enable ? setFlags(node, flags) : clearFlags(node, flags); }
+    void setFlags(Node*, unsigned);
+    void clearFlags(Node*, unsigned);
+    bool hasFlags(const Node*, unsigned flags) const;
+
+    void setFlags(Element*, unsigned);
+    void clearFlags(Element*, unsigned);
+    bool hasFlags(const Element*, unsigned flags) const;
+
+    typedef HashMap<RefPtr<Element>, unsigned> ElementFlagMap;
+    ElementFlagMap m_elements;
+};
+
+} // namespace
+
+#endif // UserActionElementSet_h
diff --git a/Source/core/dom/UserGestureIndicator.cpp b/Source/core/dom/UserGestureIndicator.cpp
new file mode 100644
index 0000000..c4e891f
--- /dev/null
+++ b/Source/core/dom/UserGestureIndicator.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "core/dom/UserGestureIndicator.h"
+
+namespace WebCore {
+
+namespace {
+
+class GestureToken : public UserGestureToken {
+public:
+    static PassRefPtr<UserGestureToken> create() { return adoptRef(new GestureToken); }
+
+    virtual ~GestureToken() { }
+    virtual bool hasGestures() const OVERRIDE { return m_consumableGestures > 0; }
+
+    void addGesture() { m_consumableGestures++; }
+    bool consumeGesture()
+    {
+        if (!m_consumableGestures)
+            return false;
+        m_consumableGestures--;
+        return true;
+    }
+
+private:
+    GestureToken()
+        : m_consumableGestures(0)
+    {
+    }
+
+    size_t m_consumableGestures;
+};
+
+}
+
+static bool isDefinite(ProcessingUserGestureState state)
+{
+    return state == DefinitelyProcessingNewUserGesture || state == DefinitelyProcessingUserGesture || state == DefinitelyNotProcessingUserGesture;
+}
+
+ProcessingUserGestureState UserGestureIndicator::s_state = DefinitelyNotProcessingUserGesture;
+UserGestureIndicator* UserGestureIndicator::s_topmostIndicator = 0;
+
+UserGestureIndicator::UserGestureIndicator(ProcessingUserGestureState state)
+    : m_previousState(s_state)
+{
+    // We overwrite s_state only if the caller is definite about the gesture state.
+    if (isDefinite(state)) {
+        if (!s_topmostIndicator) {
+            s_topmostIndicator = this;
+            m_token = GestureToken::create();
+        } else
+            m_token = s_topmostIndicator->currentToken();
+        s_state = state;
+    }
+
+    if (state == DefinitelyProcessingNewUserGesture)
+        static_cast<GestureToken*>(m_token.get())->addGesture();
+    else if (state == DefinitelyProcessingUserGesture && s_topmostIndicator == this)
+        static_cast<GestureToken*>(m_token.get())->addGesture();
+    ASSERT(isDefinite(s_state));
+}
+
+UserGestureIndicator::UserGestureIndicator(PassRefPtr<UserGestureToken> token)
+    : m_previousState(s_state)
+{
+    if (token && static_cast<GestureToken*>(token.get())->hasGestures()) {
+        if (!s_topmostIndicator) {
+            s_topmostIndicator = this;
+            m_token = token;
+        } else {
+            m_token = s_topmostIndicator->currentToken();
+            static_cast<GestureToken*>(m_token.get())->addGesture();
+            static_cast<GestureToken*>(token.get())->consumeGesture();
+        }
+        s_state = DefinitelyProcessingUserGesture;
+    }
+
+    ASSERT(isDefinite(s_state));
+}
+
+UserGestureIndicator::~UserGestureIndicator()
+{
+    s_state = m_previousState;
+    if (s_topmostIndicator == this)
+        s_topmostIndicator = 0;
+    ASSERT(isDefinite(s_state));
+}
+
+bool UserGestureIndicator::processingUserGesture()
+{
+    return s_topmostIndicator && static_cast<GestureToken*>(s_topmostIndicator->currentToken())->hasGestures() && (s_state == DefinitelyProcessingNewUserGesture || s_state == DefinitelyProcessingUserGesture);
+}
+
+bool UserGestureIndicator::consumeUserGesture()
+{
+    if (!s_topmostIndicator)
+        return false;
+    return static_cast<GestureToken*>(s_topmostIndicator->currentToken())->consumeGesture();
+}
+
+UserGestureToken* UserGestureIndicator::currentToken()
+{
+    if (!s_topmostIndicator)
+        return 0;
+    return s_topmostIndicator->m_token.get();
+}
+
+UserGestureIndicatorDisabler::UserGestureIndicatorDisabler()
+    : m_savedState(UserGestureIndicator::s_state)
+    , m_savedIndicator(UserGestureIndicator::s_topmostIndicator)
+{
+    UserGestureIndicator::s_state = DefinitelyNotProcessingUserGesture;
+    UserGestureIndicator::s_topmostIndicator = 0;
+}
+
+UserGestureIndicatorDisabler::~UserGestureIndicatorDisabler()
+{
+    UserGestureIndicator::s_state = m_savedState;
+    UserGestureIndicator::s_topmostIndicator = m_savedIndicator;
+}
+
+}
diff --git a/Source/core/dom/UserGestureIndicator.h b/Source/core/dom/UserGestureIndicator.h
new file mode 100644
index 0000000..4c29acb
--- /dev/null
+++ b/Source/core/dom/UserGestureIndicator.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 UserGestureIndicator_h
+#define UserGestureIndicator_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class UserGestureIndicator;
+
+enum ProcessingUserGestureState {
+    DefinitelyProcessingNewUserGesture,
+    DefinitelyProcessingUserGesture,
+    PossiblyProcessingUserGesture,
+    DefinitelyNotProcessingUserGesture
+};
+
+class UserGestureToken : public RefCounted<UserGestureToken> {
+public:
+    virtual ~UserGestureToken() { }
+    virtual bool hasGestures() const = 0;
+};
+
+class UserGestureIndicatorDisabler {
+    WTF_MAKE_NONCOPYABLE(UserGestureIndicatorDisabler);
+public:
+    UserGestureIndicatorDisabler();
+    ~UserGestureIndicatorDisabler();
+
+private:
+    ProcessingUserGestureState m_savedState;
+    UserGestureIndicator* m_savedIndicator;
+};
+
+class UserGestureIndicator {
+    WTF_MAKE_NONCOPYABLE(UserGestureIndicator);
+    friend class UserGestureIndicatorDisabler;
+public:
+    static bool processingUserGesture();
+    static bool consumeUserGesture();
+    static UserGestureToken* currentToken();
+
+    explicit UserGestureIndicator(ProcessingUserGestureState);
+    explicit UserGestureIndicator(PassRefPtr<UserGestureToken>);
+    ~UserGestureIndicator();
+
+
+private:
+    static ProcessingUserGestureState s_state;
+    static UserGestureIndicator* s_topmostIndicator;
+    ProcessingUserGestureState m_previousState;
+    RefPtr<UserGestureToken> m_token;
+};
+
+}
+
+#endif
diff --git a/Source/core/dom/UserTypingGestureIndicator.cpp b/Source/core/dom/UserTypingGestureIndicator.cpp
new file mode 100644
index 0000000..5b6684e
--- /dev/null
+++ b/Source/core/dom/UserTypingGestureIndicator.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "core/dom/UserTypingGestureIndicator.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/Node.h"
+#include "core/page/Frame.h"
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+static bool s_processingUserTypingGesture;
+bool UserTypingGestureIndicator::processingUserTypingGesture()
+{
+    return s_processingUserTypingGesture;
+}
+
+static RefPtr<Node>& focusedNode()
+{
+    DEFINE_STATIC_LOCAL(RefPtr<Node>, node, ());
+    return node;
+}
+
+Node* UserTypingGestureIndicator::focusedElementAtGestureStart()
+{
+    return focusedNode().get();
+}
+
+UserTypingGestureIndicator::UserTypingGestureIndicator(Frame* frame)
+    : m_previousProcessingUserTypingGesture(s_processingUserTypingGesture)
+    , m_previousFocusedNode(focusedNode())
+{
+    s_processingUserTypingGesture = true;
+    focusedNode() = frame->document() ? frame->document()->focusedNode() : 0;
+}
+
+UserTypingGestureIndicator::~UserTypingGestureIndicator()
+{
+    s_processingUserTypingGesture = m_previousProcessingUserTypingGesture;
+    focusedNode() = m_previousFocusedNode;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/UserTypingGestureIndicator.h b/Source/core/dom/UserTypingGestureIndicator.h
new file mode 100644
index 0000000..21f4c7e
--- /dev/null
+++ b/Source/core/dom/UserTypingGestureIndicator.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 UserTypingGestureIndicator_h
+#define UserTypingGestureIndicator_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Frame;
+class Node;
+
+class UserTypingGestureIndicator {
+    WTF_MAKE_NONCOPYABLE(UserTypingGestureIndicator);
+public:
+    static bool processingUserTypingGesture();
+    static Node* focusedElementAtGestureStart();
+
+    explicit UserTypingGestureIndicator(Frame*);
+    ~UserTypingGestureIndicator();
+
+private:
+    bool m_previousProcessingUserTypingGesture;
+    RefPtr<Node> m_previousFocusedNode;
+};    
+
+} // namespace WebCore
+
+#endif // UserTypingGestureIndicator_h
diff --git a/Source/core/dom/ViewportArguments.cpp b/Source/core/dom/ViewportArguments.cpp
new file mode 100644
index 0000000..ec88fbc
--- /dev/null
+++ b/Source/core/dom/ViewportArguments.cpp
@@ -0,0 +1,475 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "core/dom/ViewportArguments.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/ScriptableDocumentParser.h"
+#include "core/page/Chrome.h"
+#include "core/page/Console.h"
+#include "core/page/DOMWindow.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/platform/graphics/IntSize.h"
+#include <wtf/text/WTFString.h>
+
+using namespace std;
+
+namespace WebCore {
+
+const float ViewportArguments::deprecatedTargetDPI = 160;
+
+static const float& compareIgnoringAuto(const float& value1, const float& value2, const float& (*compare) (const float&, const float&))
+{
+    ASSERT(value1 != ViewportArguments::ValueAuto || value2 != ViewportArguments::ValueAuto);
+
+    if (value1 == ViewportArguments::ValueAuto)
+        return value2;
+
+    if (value2 == ViewportArguments::ValueAuto)
+        return value1;
+
+    return compare(value1, value2);
+}
+
+static inline float clampLengthValue(float value)
+{
+    ASSERT(value != ViewportArguments::ValueDeviceWidth);
+    ASSERT(value != ViewportArguments::ValueDeviceHeight);
+
+    // Limits as defined in the css-device-adapt spec.
+    if (value != ViewportArguments::ValueAuto)
+        return min(float(10000), max(value, float(1)));
+    return value;
+}
+
+static inline float clampScaleValue(float value)
+{
+    ASSERT(value != ViewportArguments::ValueDeviceWidth);
+    ASSERT(value != ViewportArguments::ValueDeviceHeight);
+
+    // Limits as defined in the css-device-adapt spec.
+    if (value != ViewportArguments::ValueAuto)
+        return min(float(10), max(value, float(0.1)));
+    return value;
+}
+
+ViewportAttributes ViewportArguments::resolve(const FloatSize& initialViewportSize, const FloatSize& deviceSize, int defaultWidth) const
+{
+    float resultWidth = width;
+    float resultMaxWidth = maxWidth;
+    float resultMinWidth = minWidth;
+    float resultHeight = height;
+    float resultMinHeight = minHeight;
+    float resultMaxHeight = maxHeight;
+    float resultZoom = zoom;
+    float resultMinZoom = minZoom;
+    float resultMaxZoom = maxZoom;
+    float resultUserZoom = userZoom;
+
+    switch (int(resultWidth)) {
+    case ViewportArguments::ValueDeviceWidth:
+        resultWidth = deviceSize.width();
+        break;
+    case ViewportArguments::ValueDeviceHeight:
+        resultWidth = deviceSize.height();
+        break;
+    }
+
+    switch (int(resultHeight)) {
+    case ViewportArguments::ValueDeviceWidth:
+        resultHeight = deviceSize.width();
+        break;
+    case ViewportArguments::ValueDeviceHeight:
+        resultHeight = deviceSize.height();
+        break;
+    }
+
+    if (type == ViewportArguments::CSSDeviceAdaptation) {
+        switch (int(resultMinWidth)) {
+        case ViewportArguments::ValueDeviceWidth:
+            resultMinWidth = deviceSize.width();
+            break;
+        case ViewportArguments::ValueDeviceHeight:
+            resultMinWidth = deviceSize.height();
+            break;
+        }
+
+        switch (int(resultMaxWidth)) {
+        case ViewportArguments::ValueDeviceWidth:
+            resultMaxWidth = deviceSize.width();
+            break;
+        case ViewportArguments::ValueDeviceHeight:
+            resultMaxWidth = deviceSize.height();
+            break;
+        }
+
+        switch (int(resultMinHeight)) {
+        case ViewportArguments::ValueDeviceWidth:
+            resultMinHeight = deviceSize.width();
+            break;
+        case ViewportArguments::ValueDeviceHeight:
+            resultMinHeight = deviceSize.height();
+            break;
+        }
+
+        switch (int(resultMaxHeight)) {
+        case ViewportArguments::ValueDeviceWidth:
+            resultMaxHeight = deviceSize.width();
+            break;
+        case ViewportArguments::ValueDeviceHeight:
+            resultMaxHeight = deviceSize.height();
+            break;
+        }
+
+        if (resultMinWidth != ViewportArguments::ValueAuto || resultMaxWidth != ViewportArguments::ValueAuto)
+            resultWidth = compareIgnoringAuto(resultMinWidth, compareIgnoringAuto(resultMaxWidth, deviceSize.width(), min), max);
+
+        if (resultMinHeight != ViewportArguments::ValueAuto || resultMaxHeight != ViewportArguments::ValueAuto)
+            resultHeight = compareIgnoringAuto(resultMinHeight, compareIgnoringAuto(resultMaxHeight, deviceSize.height(), min), max);
+
+        if (resultMinZoom != ViewportArguments::ValueAuto && resultMaxZoom != ViewportArguments::ValueAuto)
+            resultMaxZoom = max(resultMinZoom, resultMaxZoom);
+
+        if (resultZoom != ViewportArguments::ValueAuto)
+            resultZoom = compareIgnoringAuto(resultMinZoom, compareIgnoringAuto(resultMaxZoom, resultZoom, min), max);
+
+        if (resultWidth == ViewportArguments::ValueAuto && resultZoom == ViewportArguments::ValueAuto)
+            resultWidth = deviceSize.width();
+
+        if (resultWidth == ViewportArguments::ValueAuto && resultHeight == ViewportArguments::ValueAuto)
+            resultWidth = deviceSize.width() / resultZoom;
+
+        if (resultWidth == ViewportArguments::ValueAuto)
+            resultWidth = resultHeight * deviceSize.width() / deviceSize.height();
+
+        if (resultHeight == ViewportArguments::ValueAuto)
+            resultHeight = resultWidth * deviceSize.height() / deviceSize.width();
+
+        if (resultZoom != ViewportArguments::ValueAuto || resultMaxZoom != ViewportArguments::ValueAuto) {
+            resultWidth = compareIgnoringAuto(resultWidth, deviceSize.width() / compareIgnoringAuto(resultZoom, resultMaxZoom, min), max);
+            resultHeight = compareIgnoringAuto(resultHeight, deviceSize.height() / compareIgnoringAuto(resultZoom, resultMaxZoom, min), max);
+        }
+
+        resultWidth = max<float>(1, resultWidth);
+        resultHeight = max<float>(1, resultHeight);
+    }
+
+    if (type != ViewportArguments::CSSDeviceAdaptation && type != ViewportArguments::Implicit) {
+        // Clamp values to a valid range, but not for @viewport since is
+        // not mandated by the specification.
+        resultWidth = clampLengthValue(resultWidth);
+        resultHeight = clampLengthValue(resultHeight);
+        resultZoom = clampScaleValue(resultZoom);
+        resultMinZoom = clampScaleValue(resultMinZoom);
+        resultMaxZoom = clampScaleValue(resultMaxZoom);
+    }
+
+    ViewportAttributes result;
+    result.orientation = orientation;
+
+    // Resolve minimum-scale and maximum-scale values according to spec.
+    if (resultMinZoom == ViewportArguments::ValueAuto)
+        result.minimumScale = float(0.25);
+    else
+        result.minimumScale = resultMinZoom;
+
+    if (resultMaxZoom == ViewportArguments::ValueAuto) {
+        result.maximumScale = float(5.0);
+        result.minimumScale = min(float(5.0), result.minimumScale);
+    } else
+        result.maximumScale = resultMaxZoom;
+    result.maximumScale = max(result.minimumScale, result.maximumScale);
+
+    // Resolve initial-scale value.
+    result.initialScale = resultZoom;
+    if (resultZoom == ViewportArguments::ValueAuto) {
+        result.initialScale = initialViewportSize.width() / defaultWidth;
+        if (resultWidth != ViewportArguments::ValueAuto)
+            result.initialScale = initialViewportSize.width() / resultWidth;
+        if (resultHeight != ViewportArguments::ValueAuto) {
+            // if 'auto', the initial-scale will be negative here and thus ignored.
+            result.initialScale = max<float>(result.initialScale, initialViewportSize.height() / resultHeight);
+        }
+    }
+
+    // Constrain initial-scale value to minimum-scale/maximum-scale range.
+    result.initialScale = min(result.maximumScale, max(result.minimumScale, result.initialScale));
+
+    // Resolve width value.
+    if (resultWidth == ViewportArguments::ValueAuto) {
+        if (resultZoom == ViewportArguments::ValueAuto)
+            resultWidth = defaultWidth;
+        else if (resultHeight != ViewportArguments::ValueAuto)
+            resultWidth = resultHeight * (initialViewportSize.width() / initialViewportSize.height());
+        else
+            resultWidth = initialViewportSize.width() / result.initialScale;
+    }
+
+    // Resolve height value.
+    if (resultHeight == ViewportArguments::ValueAuto)
+        resultHeight = resultWidth * (initialViewportSize.height() / initialViewportSize.width());
+
+    if (type == ViewportArguments::ViewportMeta) {
+        // Extend width and height to fill the visual viewport for the resolved initial-scale.
+        resultWidth = max<float>(resultWidth, initialViewportSize.width() / result.initialScale);
+        resultHeight = max<float>(resultHeight, initialViewportSize.height() / result.initialScale);
+    }
+
+    result.layoutSize.setWidth(resultWidth);
+    result.layoutSize.setHeight(resultHeight);
+
+    // FIXME: This might affect some ports, but is the right thing to do.
+    // Only set initialScale to a value if it was explicitly set.
+    // if (resultZoom == ViewportArguments::ValueAuto)
+    //    result.initialScale = ViewportArguments::ValueAuto;
+
+    result.userScalable = resultUserZoom;
+    result.orientation = orientation;
+
+    return result;
+}
+
+static FloatSize convertToUserSpace(const FloatSize& deviceSize, float devicePixelRatio)
+{
+    FloatSize result = deviceSize;
+    if (devicePixelRatio != 1)
+        result.scale(1 / devicePixelRatio);
+    return result;
+}
+
+ViewportAttributes computeViewportAttributes(ViewportArguments args, int desktopWidth, int deviceWidth, int deviceHeight, float devicePixelRatio, IntSize visibleViewport)
+{
+    FloatSize initialViewportSize = convertToUserSpace(visibleViewport, devicePixelRatio);
+    FloatSize deviceSize = convertToUserSpace(FloatSize(deviceWidth, deviceHeight), devicePixelRatio);
+
+    return args.resolve(initialViewportSize, deviceSize, desktopWidth);
+}
+
+float computeMinimumScaleFactorForContentContained(const ViewportAttributes& result, const IntSize& visibleViewport, const IntSize& contentsSize)
+{
+    FloatSize viewportSize(visibleViewport);
+    return max<float>(result.minimumScale, max(viewportSize.width() / contentsSize.width(), viewportSize.height() / contentsSize.height()));
+}
+
+void restrictMinimumScaleFactorToViewportSize(ViewportAttributes& result, IntSize visibleViewport, float devicePixelRatio)
+{
+    FloatSize viewportSize = convertToUserSpace(visibleViewport, devicePixelRatio);
+
+    result.minimumScale = max<float>(result.minimumScale, max(viewportSize.width() / result.layoutSize.width(), viewportSize.height() / result.layoutSize.height()));
+}
+
+void restrictScaleFactorToInitialScaleIfNotUserScalable(ViewportAttributes& result)
+{
+    if (!result.userScalable)
+        result.maximumScale = result.minimumScale = result.initialScale;
+}
+
+static float numericPrefix(const String& keyString, const String& valueString, Document* document, bool* ok = 0)
+{
+    size_t parsedLength;
+    float value;
+    if (valueString.is8Bit())
+        value = charactersToFloat(valueString.characters8(), valueString.length(), parsedLength);
+    else
+        value = charactersToFloat(valueString.characters16(), valueString.length(), parsedLength);
+    if (!parsedLength) {
+        reportViewportWarning(document, UnrecognizedViewportArgumentValueError, valueString, keyString);
+        if (ok)
+            *ok = false;
+        return 0;
+    }
+    if (parsedLength < valueString.length())
+        reportViewportWarning(document, TruncatedViewportArgumentValueError, valueString, keyString);
+    if (ok)
+        *ok = true;
+    return value;
+}
+
+static float findSizeValue(const String& keyString, const String& valueString, Document* document)
+{
+    // 1) Non-negative number values are translated to px lengths.
+    // 2) Negative number values are translated to auto.
+    // 3) device-width and device-height are used as keywords.
+    // 4) Other keywords and unknown values translate to 0.0.
+
+    if (equalIgnoringCase(valueString, "device-width"))
+        return ViewportArguments::ValueDeviceWidth;
+    if (equalIgnoringCase(valueString, "device-height"))
+        return ViewportArguments::ValueDeviceHeight;
+
+    float value = numericPrefix(keyString, valueString, document);
+
+    if (value < 0)
+        return ViewportArguments::ValueAuto;
+
+    return value;
+}
+
+static float findScaleValue(const String& keyString, const String& valueString, Document* document)
+{
+    // 1) Non-negative number values are translated to <number> values.
+    // 2) Negative number values are translated to auto.
+    // 3) yes is translated to 1.0.
+    // 4) device-width and device-height are translated to 10.0.
+    // 5) no and unknown values are translated to 0.0
+
+    if (equalIgnoringCase(valueString, "yes"))
+        return 1;
+    if (equalIgnoringCase(valueString, "no"))
+        return 0;
+    if (equalIgnoringCase(valueString, "device-width"))
+        return 10;
+    if (equalIgnoringCase(valueString, "device-height"))
+        return 10;
+
+    float value = numericPrefix(keyString, valueString, document);
+
+    if (value < 0)
+        return ViewportArguments::ValueAuto;
+
+    if (value > 10.0)
+        reportViewportWarning(document, MaximumScaleTooLargeError, String(), String());
+
+    return value;
+}
+
+static float findUserScalableValue(const String& keyString, const String& valueString, Document* document)
+{
+    // yes and no are used as keywords.
+    // Numbers >= 1, numbers <= -1, device-width and device-height are mapped to yes.
+    // Numbers in the range <-1, 1>, and unknown values, are mapped to no.
+
+    if (equalIgnoringCase(valueString, "yes"))
+        return 1;
+    if (equalIgnoringCase(valueString, "no"))
+        return 0;
+    if (equalIgnoringCase(valueString, "device-width"))
+        return 1;
+    if (equalIgnoringCase(valueString, "device-height"))
+        return 1;
+
+    float value = numericPrefix(keyString, valueString, document);
+
+    if (fabs(value) < 1)
+        return 0;
+
+    return 1;
+}
+
+static float findTargetDensityDPIValue(const String& keyString, const String& valueString, Document* document)
+{
+    if (equalIgnoringCase(valueString, "device-dpi"))
+        return ViewportArguments::ValueDeviceDPI;
+    if (equalIgnoringCase(valueString, "low-dpi"))
+        return ViewportArguments::ValueLowDPI;
+    if (equalIgnoringCase(valueString, "medium-dpi"))
+        return ViewportArguments::ValueMediumDPI;
+    if (equalIgnoringCase(valueString, "high-dpi"))
+        return ViewportArguments::ValueHighDPI;
+
+    bool ok;
+    float value = numericPrefix(keyString, valueString, document, &ok);
+    if (!ok || value < 70 || value > 400)
+        return ViewportArguments::ValueAuto;
+
+    return value;
+}
+
+void setViewportFeature(const String& keyString, const String& valueString, Document* document, void* data)
+{
+    ViewportArguments* arguments = static_cast<ViewportArguments*>(data);
+
+    if (keyString == "width")
+        arguments->width = findSizeValue(keyString, valueString, document);
+    else if (keyString == "height")
+        arguments->height = findSizeValue(keyString, valueString, document);
+    else if (keyString == "initial-scale")
+        arguments->zoom = findScaleValue(keyString, valueString, document);
+    else if (keyString == "minimum-scale")
+        arguments->minZoom = findScaleValue(keyString, valueString, document);
+    else if (keyString == "maximum-scale")
+        arguments->maxZoom = findScaleValue(keyString, valueString, document);
+    else if (keyString == "user-scalable")
+        arguments->userZoom = findUserScalableValue(keyString, valueString, document);
+    else if (keyString == "target-densitydpi") {
+        arguments->deprecatedTargetDensityDPI = findTargetDensityDPIValue(keyString, valueString, document);
+        reportViewportWarning(document, TargetDensityDpiUnsupported, String(), String());
+    } else
+        reportViewportWarning(document, UnrecognizedViewportArgumentKeyError, keyString, String());
+}
+
+static const char* viewportErrorMessageTemplate(ViewportErrorCode errorCode)
+{
+    static const char* const errors[] = {
+        "Viewport argument key \"%replacement1\" not recognized and ignored.",
+        "Viewport argument value \"%replacement1\" for key \"%replacement2\" is invalid, and has been ignored.",
+        "Viewport argument value \"%replacement1\" for key \"%replacement2\" was truncated to its numeric prefix.",
+        "Viewport maximum-scale cannot be larger than 10.0. The maximum-scale will be set to 10.0.",
+        "Viewport target-densitydpi is not supported.",
+    };
+
+    return errors[errorCode];
+}
+
+static MessageLevel viewportErrorMessageLevel(ViewportErrorCode errorCode)
+{
+    switch (errorCode) {
+    case TruncatedViewportArgumentValueError:
+    case TargetDensityDpiUnsupported:
+        return WarningMessageLevel;
+    case UnrecognizedViewportArgumentKeyError:
+    case UnrecognizedViewportArgumentValueError:
+    case MaximumScaleTooLargeError:
+        return ErrorMessageLevel;
+    }
+
+    ASSERT_NOT_REACHED();
+    return ErrorMessageLevel;
+}
+
+void reportViewportWarning(Document* document, ViewportErrorCode errorCode, const String& replacement1, const String& replacement2)
+{
+    Frame* frame = document->frame();
+    if (!frame)
+        return;
+
+    String message = viewportErrorMessageTemplate(errorCode);
+    if (!replacement1.isNull())
+        message.replace("%replacement1", replacement1);
+    if (!replacement2.isNull())
+        message.replace("%replacement2", replacement2);
+
+    if ((errorCode == UnrecognizedViewportArgumentValueError || errorCode == TruncatedViewportArgumentValueError) && replacement1.find(';') != WTF::notFound)
+        message.append(" Note that ';' is not a separator in viewport values. The list should be comma-separated.");
+
+    // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
+    document->addConsoleMessage(RenderingMessageSource, viewportErrorMessageLevel(errorCode), message);
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/ViewportArguments.h b/Source/core/dom/ViewportArguments.h
new file mode 100644
index 0000000..e6c61e6
--- /dev/null
+++ b/Source/core/dom/ViewportArguments.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ViewportArguments_h
+#define ViewportArguments_h
+
+#include "core/platform/graphics/FloatSize.h"
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class Document;
+
+enum ViewportErrorCode {
+    UnrecognizedViewportArgumentKeyError,
+    UnrecognizedViewportArgumentValueError,
+    TruncatedViewportArgumentValueError,
+    MaximumScaleTooLargeError,
+    TargetDensityDpiUnsupported
+};
+
+struct ViewportAttributes {
+    FloatSize layoutSize;
+
+    float initialScale;
+    float minimumScale;
+    float maximumScale;
+
+    float userScalable;
+    float orientation;
+};
+
+struct ViewportArguments {
+
+    enum Type {
+        // These are ordered in increasing importance.
+        Implicit,
+        XHTMLMobileProfile,
+        HandheldFriendlyMeta,
+        MobileOptimizedMeta,
+        ViewportMeta,
+        CSSDeviceAdaptation
+    } type;
+
+    enum {
+        ValueAuto = -1,
+        ValueDeviceWidth = -2,
+        ValueDeviceHeight = -3,
+        ValuePortrait = -4,
+        ValueLandscape = -5,
+        ValueDeviceDPI = -6,
+        ValueLowDPI = -7,
+        ValueMediumDPI = -8,
+        ValueHighDPI = -9
+    };
+
+    ViewportArguments(Type type = Implicit)
+        : type(type)
+        , width(ValueAuto)
+        , minWidth(ValueAuto)
+        , maxWidth(ValueAuto)
+        , height(ValueAuto)
+        , minHeight(ValueAuto)
+        , maxHeight(ValueAuto)
+        , zoom(ValueAuto)
+        , minZoom(ValueAuto)
+        , maxZoom(ValueAuto)
+        , userZoom(ValueAuto)
+        , orientation(ValueAuto)
+        , deprecatedTargetDensityDPI(ValueAuto)
+    {
+    }
+
+    // All arguments are in CSS units.
+    ViewportAttributes resolve(const FloatSize& initialViewportSize, const FloatSize& deviceSize, int defaultWidth) const;
+
+    float width;
+    float minWidth;
+    float maxWidth;
+    float height;
+    float minHeight;
+    float maxHeight;
+    float zoom;
+    float minZoom;
+    float maxZoom;
+    float userZoom;
+    float orientation;
+    float deprecatedTargetDensityDPI; // Only used for Android WebView
+
+    bool operator==(const ViewportArguments& other) const
+    {
+        // Used for figuring out whether to reset the viewport or not,
+        // thus we are not taking type into account.
+        return width == other.width
+            && minWidth == other.minWidth
+            && maxWidth == other.maxWidth
+            && height == other.height
+            && minHeight == other.minHeight
+            && maxHeight == other.maxHeight
+            && zoom == other.zoom
+            && minZoom == other.minZoom
+            && maxZoom == other.maxZoom
+            && userZoom == other.userZoom
+            && orientation == other.orientation
+            && deprecatedTargetDensityDPI == other.deprecatedTargetDensityDPI;
+    }
+
+    bool operator!=(const ViewportArguments& other) const
+    {
+        return !(*this == other);
+    }
+
+    // FIXME: We're going to keep this constant around until all embedders
+    // refactor their code to no longer need it.
+    static const float deprecatedTargetDPI;
+};
+
+ViewportAttributes computeViewportAttributes(ViewportArguments args, int desktopWidth, int deviceWidth, int deviceHeight, float devicePixelRatio, IntSize visibleViewport);
+
+void restrictMinimumScaleFactorToViewportSize(ViewportAttributes& result, IntSize visibleViewport, float devicePixelRatio);
+void restrictScaleFactorToInitialScaleIfNotUserScalable(ViewportAttributes& result);
+float computeMinimumScaleFactorForContentContained(const ViewportAttributes& result, const IntSize& viewportSize, const IntSize& contentSize);
+
+void setViewportFeature(const String& keyString, const String& valueString, Document*, void* data);
+void reportViewportWarning(Document*, ViewportErrorCode, const String& replacement1, const String& replacement2);
+
+} // namespace WebCore
+
+#endif // ViewportArguments_h
diff --git a/Source/core/dom/VisitedLinkState.cpp b/Source/core/dom/VisitedLinkState.cpp
new file mode 100644
index 0000000..2e0e5e8
--- /dev/null
+++ b/Source/core/dom/VisitedLinkState.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/VisitedLinkState.h"
+
+#include "HTMLNames.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/html/HTMLAnchorElement.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/platform/VisitedLinks.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+inline static const AtomicString* linkAttribute(Element* element)
+{
+    if (!element->isLink())
+        return 0;
+    if (element->isHTMLElement())
+        return &element->fastGetAttribute(HTMLNames::hrefAttr);
+    if (element->isSVGElement())
+        return &element->getAttribute(XLinkNames::hrefAttr);
+    return 0;
+}
+
+PassOwnPtr<VisitedLinkState> VisitedLinkState::create(Document* document)
+{
+    return adoptPtr(new VisitedLinkState(document));
+}
+
+VisitedLinkState::VisitedLinkState(Document* document)
+    : m_document(document)
+{
+}
+
+void VisitedLinkState::invalidateStyleForAllLinks()
+{
+    if (m_linksCheckedForVisitedState.isEmpty())
+        return;
+    for (Element* element = ElementTraversal::firstWithin(m_document); element; element = ElementTraversal::next(element)) {
+        if (element->isLink())
+            element->setNeedsStyleRecalc();
+    }
+}
+
+inline static LinkHash linkHashForElement(Document* document, Element* element)
+{
+    if (element->hasTagName(aTag))
+        return static_cast<HTMLAnchorElement*>(element)->visitedLinkHash();
+    if (const AtomicString* attribute = linkAttribute(element))
+        return WebCore::visitedLinkHash(document->baseURL(), *attribute);
+    return 0;
+}
+
+void VisitedLinkState::invalidateStyleForLink(LinkHash linkHash)
+{
+    if (!m_linksCheckedForVisitedState.contains(linkHash))
+        return;
+    for (Element* element = ElementTraversal::firstWithin(m_document); element; element = ElementTraversal::next(element)) {
+        if (linkHashForElement(m_document, element) == linkHash)
+            element->setNeedsStyleRecalc();
+    }
+}
+
+EInsideLink VisitedLinkState::determineLinkStateSlowCase(Element* element)
+{
+    ASSERT(element->isLink());
+
+    const AtomicString* attribute = linkAttribute(element);
+    if (!attribute || attribute->isNull())
+        return NotInsideLink;
+
+    // An empty href refers to the document itself which is always visited. It is useful to check this explicitly so
+    // that visited links can be tested in platform independent manner, without explicit support in the test harness.
+    if (attribute->isEmpty())
+        return InsideVisitedLink;
+
+    LinkHash hash;
+    if (element->hasTagName(aTag))
+        hash = static_cast<HTMLAnchorElement*>(element)->visitedLinkHash();
+    else
+        hash = WebCore::visitedLinkHash(element->document()->baseURL(), *attribute);
+
+    if (!hash)
+        return InsideUnvisitedLink;
+
+    Frame* frame = element->document()->frame();
+    if (!frame)
+        return InsideUnvisitedLink;
+
+    Page* page = frame->page();
+    if (!page)
+        return InsideUnvisitedLink;
+
+    m_linksCheckedForVisitedState.add(hash);
+
+    return VisitedLinks::isLinkVisited(hash) ? InsideVisitedLink : InsideUnvisitedLink;
+}
+
+}
diff --git a/Source/core/dom/VisitedLinkState.h b/Source/core/dom/VisitedLinkState.h
new file mode 100644
index 0000000..74e6c1a
--- /dev/null
+++ b/Source/core/dom/VisitedLinkState.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef VisitedLinkState_h
+#define VisitedLinkState_h
+
+#include "XLinkNames.h"
+#include "core/dom/Element.h"
+#include "core/platform/LinkHash.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+#include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class Document;
+
+class VisitedLinkState {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<VisitedLinkState> create(Document*);
+
+    void invalidateStyleForAllLinks();
+    void invalidateStyleForLink(LinkHash);
+    EInsideLink determineLinkState(Element*);
+
+private:
+    VisitedLinkState(Document*);
+
+    EInsideLink determineLinkStateSlowCase(Element*);
+
+    Document* m_document;
+    HashSet<LinkHash, LinkHashHash> m_linksCheckedForVisitedState;
+};
+
+inline EInsideLink VisitedLinkState::determineLinkState(Element* element)
+{
+    if (!element || !element->isLink())
+        return NotInsideLink;
+    return determineLinkStateSlowCase(element);
+}
+
+}
+
+#endif
+
diff --git a/Source/core/dom/WebCoreMemoryInstrumentation.cpp b/Source/core/dom/WebCoreMemoryInstrumentation.cpp
new file mode 100644
index 0000000..f390792
--- /dev/null
+++ b/Source/core/dom/WebCoreMemoryInstrumentation.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderBox.h"
+
+namespace WebCore {
+
+MemoryObjectType WebCoreMemoryTypes::Page = "DOM";
+MemoryObjectType WebCoreMemoryTypes::DOM = "DOM";
+MemoryObjectType WebCoreMemoryTypes::CSS = "CSS";
+MemoryObjectType WebCoreMemoryTypes::Binding = "DOM";
+MemoryObjectType WebCoreMemoryTypes::RenderingStructures = "Rendering";
+
+MemoryObjectType WebCoreMemoryTypes::MemoryCacheStructures = "Resources";
+MemoryObjectType WebCoreMemoryTypes::CachedResource = "Resources";
+MemoryObjectType WebCoreMemoryTypes::CachedResourceRaw = "Resources";
+MemoryObjectType WebCoreMemoryTypes::CachedResourceCSS = "Resources";
+MemoryObjectType WebCoreMemoryTypes::CachedResourceFont = "Resources";
+MemoryObjectType WebCoreMemoryTypes::CachedResourceImage = "Resources";
+MemoryObjectType WebCoreMemoryTypes::CachedResourceScript = "Resources";
+MemoryObjectType WebCoreMemoryTypes::CachedResourceSVG = "Resources";
+MemoryObjectType WebCoreMemoryTypes::CachedResourceShader = "Resources";
+MemoryObjectType WebCoreMemoryTypes::CachedResourceXSLT = "Resources";
+
+MemoryObjectType WebCoreMemoryTypes::ExternalStrings = "JSExternalResources";
+MemoryObjectType WebCoreMemoryTypes::ExternalArrays = "JSExternalResources";
+
+MemoryObjectType WebCoreMemoryTypes::Inspector = "WebInspector";
+MemoryObjectType WebCoreMemoryTypes::InspectorController = "WebInspector";
+MemoryObjectType WebCoreMemoryTypes::InspectorMemoryAgent = "WebInspector";
+MemoryObjectType WebCoreMemoryTypes::InspectorDOMStorageAgent = "WebInspector";
+MemoryObjectType WebCoreMemoryTypes::InspectorOverlay = "WebInspector";
+MemoryObjectType WebCoreMemoryTypes::InspectorProfilerAgent = "WebInspector";
+MemoryObjectType WebCoreMemoryTypes::InspectorDebuggerAgent = "WebInspector";
+MemoryObjectType WebCoreMemoryTypes::InspectorResourceAgent = "WebInspector";
+
+MemoryObjectType WebCoreMemoryTypes::JSHeapUsed = "JSHeap.Used";
+MemoryObjectType WebCoreMemoryTypes::JSHeapUnused = "JSHeap.Unused";
+
+MemoryObjectType WebCoreMemoryTypes::DOMStorageCache = "DOMStorageCache";
+
+MemoryObjectType WebCoreMemoryTypes::RenderTreeUsed = "RenderTree";
+MemoryObjectType WebCoreMemoryTypes::RenderTreeUnused = "RenderTree";
+
+MemoryObjectType WebCoreMemoryTypes::ProcessPrivateMemory = "ProcessPrivateMemory";
+
+
+void WebCoreMemoryInstrumentation::reportStaticMembersMemoryUsage(WTF::MemoryInstrumentation* memoryInstrumentation)
+{
+    RenderBlock::reportStaticMembersMemoryUsage(memoryInstrumentation);
+    RenderBox::reportStaticMembersMemoryUsage(memoryInstrumentation);
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/WebCoreMemoryInstrumentation.h b/Source/core/dom/WebCoreMemoryInstrumentation.h
new file mode 100644
index 0000000..4fe69b2
--- /dev/null
+++ b/Source/core/dom/WebCoreMemoryInstrumentation.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebCoreMemoryInstrumentation_h
+#define WebCoreMemoryInstrumentation_h
+
+#include "core/platform/PlatformMemoryInstrumentation.h"
+#include <wtf/MemoryInstrumentationString.h>
+
+namespace WebCore {
+
+using WTF::MemoryClassInfo;
+using WTF::MemoryObjectType;
+
+class WebCoreMemoryTypes : public PlatformMemoryTypes {
+public:
+    static MemoryObjectType Page;
+    static MemoryObjectType DOM;
+    static MemoryObjectType CSS;
+    static MemoryObjectType Binding;
+    static MemoryObjectType RenderingStructures;
+
+    static MemoryObjectType MemoryCacheStructures;
+    static MemoryObjectType CachedResource;
+    static MemoryObjectType CachedResourceRaw;
+    static MemoryObjectType CachedResourceCSS;
+    static MemoryObjectType CachedResourceFont;
+    static MemoryObjectType CachedResourceImage;
+    static MemoryObjectType CachedResourceScript;
+    static MemoryObjectType CachedResourceSVG;
+    static MemoryObjectType CachedResourceShader;
+    static MemoryObjectType CachedResourceXSLT;
+
+    static MemoryObjectType ExternalStrings;
+    static MemoryObjectType ExternalArrays;
+
+    static MemoryObjectType Inspector;
+    static MemoryObjectType InspectorController;
+    static MemoryObjectType InspectorMemoryAgent;
+    static MemoryObjectType InspectorDOMStorageAgent;
+    static MemoryObjectType InspectorOverlay;
+    static MemoryObjectType InspectorProfilerAgent;
+    static MemoryObjectType InspectorDebuggerAgent;
+    static MemoryObjectType InspectorResourceAgent;
+
+    static MemoryObjectType JSHeapUsed;
+    static MemoryObjectType JSHeapUnused;
+
+    static MemoryObjectType DOMStorageCache;
+
+    static MemoryObjectType RenderTreeUsed;
+    static MemoryObjectType RenderTreeUnused;
+
+    static MemoryObjectType ProcessPrivateMemory;
+};
+
+class WebCoreMemoryInstrumentation {
+public:
+    static void reportStaticMembersMemoryUsage(WTF::MemoryInstrumentation*);
+};
+
+
+} // namespace WebCore
+
+#endif // !defined(WebCoreMemoryInstrumentation_h)
diff --git a/Source/core/dom/WheelEvent.cpp b/Source/core/dom/WheelEvent.cpp
new file mode 100644
index 0000000..81135f8
--- /dev/null
+++ b/Source/core/dom/WheelEvent.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2005, 2006, 2008, 2010 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/dom/WheelEvent.h"
+
+#include "core/dom/Clipboard.h"
+#include "core/dom/EventDispatcher.h"
+#include "core/dom/EventNames.h"
+#include "core/platform/PlatformWheelEvent.h"
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+WheelEventInit::WheelEventInit()
+    : wheelDeltaX(0)
+    , wheelDeltaY(0)
+    , deltaMode(WheelEvent::DOM_DELTA_PIXEL)
+{
+}
+
+WheelEvent::WheelEvent()
+    : m_deltaMode(DOM_DELTA_PIXEL)
+    , m_directionInvertedFromDevice(false)
+{
+    ScriptWrappable::init(this);
+}
+
+WheelEvent::WheelEvent(const AtomicString& type, const WheelEventInit& initializer)
+    : MouseEvent(type, initializer)
+    , m_wheelDelta(IntPoint(initializer.wheelDeltaX, initializer.wheelDeltaY))
+    , m_deltaMode(initializer.deltaMode)
+{
+    ScriptWrappable::init(this);
+}
+
+WheelEvent::WheelEvent(const FloatPoint& wheelTicks, const FloatPoint& rawDelta, unsigned deltaMode,
+    PassRefPtr<AbstractView> view, const IntPoint& screenLocation, const IntPoint& pageLocation,
+    bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool directionInvertedFromDevice)
+    : MouseEvent(eventNames().mousewheelEvent,
+                 true, true, view, 0, screenLocation.x(), screenLocation.y(),
+                 pageLocation.x(), pageLocation.y(),
+                 0, 0,
+                 ctrlKey, altKey, shiftKey, metaKey, 0, 0, 0, false)
+    , m_wheelDelta(IntPoint(static_cast<int>(wheelTicks.x() * TickMultiplier), static_cast<int>(wheelTicks.y() * TickMultiplier)))
+    , m_rawDelta(roundedIntPoint(rawDelta))
+    , m_deltaMode(deltaMode)
+    , m_directionInvertedFromDevice(directionInvertedFromDevice)
+{
+    ScriptWrappable::init(this);
+}
+
+void WheelEvent::initWheelEvent(int rawDeltaX, int rawDeltaY, PassRefPtr<AbstractView> view,
+                                int screenX, int screenY, int pageX, int pageY,
+                                bool ctrlKey, bool altKey, bool shiftKey, bool metaKey)
+{
+    if (dispatched())
+        return;
+    
+    initUIEvent(eventNames().mousewheelEvent, true, true, view, 0);
+    
+    m_screenLocation = IntPoint(screenX, screenY);
+    m_ctrlKey = ctrlKey;
+    m_altKey = altKey;
+    m_shiftKey = shiftKey;
+    m_metaKey = metaKey;
+    
+    // Normalize to the Windows 120 multiple
+    m_wheelDelta = IntPoint(rawDeltaX * TickMultiplier, rawDeltaY * TickMultiplier);
+    
+    m_rawDelta = IntPoint(rawDeltaX, rawDeltaY);
+    m_deltaMode = DOM_DELTA_PIXEL;
+    m_directionInvertedFromDevice = false;
+
+    initCoordinates(IntPoint(pageX, pageY));
+}
+
+void WheelEvent::initWebKitWheelEvent(int rawDeltaX, int rawDeltaY, PassRefPtr<AbstractView> view,
+                                      int screenX, int screenY, int pageX, int pageY,
+                                      bool ctrlKey, bool altKey, bool shiftKey, bool metaKey)
+{
+    initWheelEvent(rawDeltaX, rawDeltaY, view, screenX, screenY, pageX, pageY,
+                   ctrlKey, altKey, shiftKey, metaKey);
+}
+
+const AtomicString& WheelEvent::interfaceName() const
+{
+    return eventNames().interfaceForWheelEvent;
+}
+
+bool WheelEvent::isMouseEvent() const
+{
+    return false;
+}
+
+inline static unsigned deltaMode(const PlatformWheelEvent& event)
+{
+    return event.granularity() == ScrollByPageWheelEvent ? WheelEvent::DOM_DELTA_PAGE : WheelEvent::DOM_DELTA_PIXEL;
+}
+
+PassRefPtr<WheelEventDispatchMediator> WheelEventDispatchMediator::create(const PlatformWheelEvent& event, PassRefPtr<AbstractView> view)
+{
+    return adoptRef(new WheelEventDispatchMediator(event, view));
+}
+
+WheelEventDispatchMediator::WheelEventDispatchMediator(const PlatformWheelEvent& event, PassRefPtr<AbstractView> view)
+{
+    if (!(event.deltaX() || event.deltaY()))
+        return;
+
+    setEvent(WheelEvent::create(FloatPoint(event.wheelTicksX(), event.wheelTicksY()), FloatPoint(event.deltaX(), event.deltaY()),
+        deltaMode(event), view, event.globalPosition(), event.position(),
+        event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), event.directionInvertedFromDevice()));
+}
+
+WheelEvent* WheelEventDispatchMediator::event() const
+{
+    return static_cast<WheelEvent*>(EventDispatchMediator::event());
+}
+
+bool WheelEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
+{
+    ASSERT(event());
+    return EventDispatchMediator::dispatchEvent(dispatcher) && !event()->defaultHandled();
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/WheelEvent.h b/Source/core/dom/WheelEvent.h
new file mode 100644
index 0000000..ba17ab4
--- /dev/null
+++ b/Source/core/dom/WheelEvent.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2010 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WheelEvent_h
+#define WheelEvent_h
+
+#include "core/dom/EventDispatchMediator.h"
+#include "core/dom/MouseEvent.h"
+#include "core/platform/graphics/FloatPoint.h"
+
+namespace WebCore {
+
+class PlatformWheelEvent;
+
+struct WheelEventInit : public MouseEventInit {
+    WheelEventInit();
+
+    int wheelDeltaX;
+    int wheelDeltaY;
+    unsigned deltaMode;
+};
+
+class WheelEvent : public MouseEvent {
+public:
+    enum { TickMultiplier = 120 };
+
+    enum DeltaMode {
+        DOM_DELTA_PIXEL = 0,
+        DOM_DELTA_LINE,
+        DOM_DELTA_PAGE
+    };
+
+    static PassRefPtr<WheelEvent> create()
+    {
+        return adoptRef(new WheelEvent);
+    }
+
+    static PassRefPtr<WheelEvent> create(const AtomicString& type, const WheelEventInit& initializer)
+    {
+        return adoptRef(new WheelEvent(type, initializer));
+    }
+
+    static PassRefPtr<WheelEvent> create(const FloatPoint& wheelTicks,
+        const FloatPoint& rawDelta, unsigned deltaMode, PassRefPtr<AbstractView> view,
+        const IntPoint& screenLocation, const IntPoint& pageLocation,
+        bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool directionInvertedFromDevice)
+    {
+        return adoptRef(new WheelEvent(wheelTicks, rawDelta, deltaMode, view,
+        screenLocation, pageLocation, ctrlKey, altKey, shiftKey, metaKey, directionInvertedFromDevice));
+    }
+
+    void initWheelEvent(int rawDeltaX, int rawDeltaY, PassRefPtr<AbstractView>,
+        int screenX, int screenY, int pageX, int pageY,
+        bool ctrlKey, bool altKey, bool shiftKey, bool metaKey);
+
+    void initWebKitWheelEvent(int rawDeltaX, int rawDeltaY, PassRefPtr<AbstractView>,
+        int screenX, int screenY, int pageX, int pageY,
+        bool ctrlKey, bool altKey, bool shiftKey, bool metaKey);
+
+    int wheelDelta() const { return m_wheelDelta.y() ? m_wheelDelta.y() : m_wheelDelta.x(); }
+    int wheelDeltaX() const { return m_wheelDelta.x(); }
+    int wheelDeltaY() const { return m_wheelDelta.y(); }
+    int rawDeltaX() const { return m_rawDelta.x(); }
+    int rawDeltaY() const { return m_rawDelta.y(); }
+    unsigned deltaMode() const { return m_deltaMode; }
+
+    bool webkitDirectionInvertedFromDevice() const { return m_directionInvertedFromDevice; }
+
+    virtual const AtomicString& interfaceName() const;
+    virtual bool isMouseEvent() const;
+
+private:
+    WheelEvent();
+    WheelEvent(const AtomicString&, const WheelEventInit&);
+    WheelEvent(const FloatPoint& wheelTicks, const FloatPoint& rawDelta,
+        unsigned, PassRefPtr<AbstractView>, const IntPoint& screenLocation, const IntPoint& pageLocation,
+        bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool directionInvertedFromDevice);
+
+    IntPoint m_wheelDelta;
+    IntPoint m_rawDelta;
+    unsigned m_deltaMode;
+    bool m_directionInvertedFromDevice;
+};
+
+class WheelEventDispatchMediator : public EventDispatchMediator {
+public:
+    static PassRefPtr<WheelEventDispatchMediator> create(const PlatformWheelEvent&, PassRefPtr<AbstractView>);
+private:
+    WheelEventDispatchMediator(const PlatformWheelEvent&, PassRefPtr<AbstractView>);
+    WheelEvent* event() const;
+    virtual bool dispatchEvent(EventDispatcher*) const OVERRIDE;
+};
+
+} // namespace WebCore
+
+#endif // WheelEvent_h
diff --git a/Source/core/dom/WheelEvent.idl b/Source/core/dom/WheelEvent.idl
new file mode 100644
index 0000000..ec923b3
--- /dev/null
+++ b/Source/core/dom/WheelEvent.idl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2006, 2007, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+[
+    ConstructorTemplate=Event
+] interface WheelEvent : MouseEvent {
+    const unsigned long              DOM_DELTA_PIXEL = 0x00;
+    const unsigned long              DOM_DELTA_LINE  = 0x01;
+    const unsigned long              DOM_DELTA_PAGE  = 0x02;
+
+    [InitializedByEventConstructor] readonly attribute long wheelDeltaX;
+    [InitializedByEventConstructor] readonly attribute long wheelDeltaY;
+    [InitializedByEventConstructor] readonly attribute unsigned long deltaMode;
+
+    readonly attribute long wheelDelta;
+
+    // WebKit Extension
+    readonly attribute boolean webkitDirectionInvertedFromDevice;
+
+    void initWebKitWheelEvent([Default=Undefined] optional long wheelDeltaX,
+                              [Default=Undefined] optional long wheelDeltaY, 
+                              [Default=Undefined] optional DOMWindow view, 
+                              [Default=Undefined] optional long screenX,
+                              [Default=Undefined] optional long screenY,
+                              [Default=Undefined] optional long clientX,
+                              [Default=Undefined] optional long clientY,
+                              [Default=Undefined] optional boolean ctrlKey,
+                              [Default=Undefined] optional boolean altKey,
+                              [Default=Undefined] optional boolean shiftKey,
+                              [Default=Undefined] optional boolean metaKey);
+};
diff --git a/Source/core/dom/WindowEventContext.cpp b/Source/core/dom/WindowEventContext.cpp
new file mode 100644
index 0000000..af5facf
--- /dev/null
+++ b/Source/core/dom/WindowEventContext.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "core/dom/WindowEventContext.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/Event.h"
+#include "core/dom/EventContext.h"
+#include "core/dom/Node.h"
+#include "core/page/DOMWindow.h"
+
+namespace WebCore {
+
+WindowEventContext::WindowEventContext(Event* event, PassRefPtr<Node> node, const EventContext* topEventContext)
+{
+    // We don't dispatch load events to the window. This quirk was originally
+    // added because Mozilla doesn't propagate load events to the window object.
+    if (event->type() == eventNames().loadEvent)
+        return;
+
+    Node* topLevelContainer = topEventContext ? topEventContext->node() : node.get();
+    if (!topLevelContainer->isDocumentNode())
+        return;
+
+    m_window = toDocument(topLevelContainer)->domWindow();
+    m_target = topEventContext ? topEventContext->target() : node.get();
+}
+
+bool WindowEventContext::handleLocalEvents(Event* event)
+{
+    if (!m_window)
+        return false;
+
+    event->setTarget(target());
+    event->setCurrentTarget(window());
+    m_window->fireEventListeners(event);
+    return true;
+}
+
+}
diff --git a/Source/core/dom/WindowEventContext.h b/Source/core/dom/WindowEventContext.h
new file mode 100644
index 0000000..a19e04d
--- /dev/null
+++ b/Source/core/dom/WindowEventContext.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef WindowEventContext_h
+#define WindowEventContext_h
+
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class DOMWindow;
+class EventTarget;
+class EventContext;
+class Event;
+class Node;
+
+class WindowEventContext {
+public:
+    WindowEventContext(Event*, PassRefPtr<Node>, const EventContext*);
+
+    DOMWindow* window() const;
+    EventTarget* target() const;
+    bool handleLocalEvents(Event* event);
+
+private:
+    RefPtr<DOMWindow> m_window;
+    RefPtr<EventTarget> m_target;
+};
+
+inline DOMWindow* WindowEventContext::window() const
+{
+    return m_window.get();
+}
+
+inline EventTarget* WindowEventContext::target() const
+{
+    return m_target.get();
+}
+
+}
+
+#endif // WindowEventContext_h
diff --git a/Source/core/dom/default/PlatformMessagePortChannel.cpp b/Source/core/dom/default/PlatformMessagePortChannel.cpp
new file mode 100644
index 0000000..2837517
--- /dev/null
+++ b/Source/core/dom/default/PlatformMessagePortChannel.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/default/PlatformMessagePortChannel.h"
+
+#include "core/dom/MessagePort.h"
+#include "core/dom/ScriptExecutionContext.h"
+
+namespace WebCore {
+
+PassOwnPtr<PlatformMessagePortChannel::EventData> PlatformMessagePortChannel::EventData::create(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels)
+{
+    return adoptPtr(new EventData(message, channels));
+}
+
+PlatformMessagePortChannel::EventData::EventData(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels)
+    : m_message(message)
+    , m_channels(channels)
+{
+}
+
+void MessagePortChannel::createChannel(PassRefPtr<MessagePort> port1, PassRefPtr<MessagePort> port2)
+{
+    RefPtr<PlatformMessagePortChannel::MessagePortQueue> queue1 = PlatformMessagePortChannel::MessagePortQueue::create();
+    RefPtr<PlatformMessagePortChannel::MessagePortQueue> queue2 = PlatformMessagePortChannel::MessagePortQueue::create();
+
+    OwnPtr<MessagePortChannel> channel1 = adoptPtr(new MessagePortChannel(PlatformMessagePortChannel::create(queue1, queue2)));
+    OwnPtr<MessagePortChannel> channel2 = adoptPtr(new MessagePortChannel(PlatformMessagePortChannel::create(queue2, queue1)));
+
+    channel1->m_channel->m_entangledChannel = channel2->m_channel;
+    channel2->m_channel->m_entangledChannel = channel1->m_channel;
+
+    port1->entangle(channel2.release());
+    port2->entangle(channel1.release());
+}
+
+MessagePortChannel::MessagePortChannel(PassRefPtr<PlatformMessagePortChannel> channel)
+    : m_channel(channel)
+{
+}
+
+MessagePortChannel::~MessagePortChannel()
+{
+    close();
+}
+
+bool MessagePortChannel::entangleIfOpen(MessagePort* port)
+{
+    // We can't call member functions on our remote pair while holding our mutex or we'll deadlock,
+    // but we need to guard against the remote port getting closed/freed, so create a standalone reference.
+    RefPtr<PlatformMessagePortChannel> remote = m_channel->entangledChannel();
+    if (!remote)
+        return false;
+    remote->setRemotePort(port);
+    return true;
+}
+
+void MessagePortChannel::disentangle()
+{
+    RefPtr<PlatformMessagePortChannel> remote = m_channel->entangledChannel();
+    if (remote)
+        remote->setRemotePort(0);
+}
+
+void MessagePortChannel::postMessageToRemote(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels)
+{
+    MutexLocker lock(m_channel->m_mutex);
+    if (!m_channel->m_outgoingQueue)
+        return;
+    bool wasEmpty = m_channel->m_outgoingQueue->appendAndCheckEmpty(PlatformMessagePortChannel::EventData::create(message, channels));
+    if (wasEmpty && m_channel->m_remotePort)
+        m_channel->m_remotePort->messageAvailable();
+}
+
+bool MessagePortChannel::tryGetMessageFromRemote(RefPtr<SerializedScriptValue>& message, OwnPtr<MessagePortChannelArray>& channels)
+{
+    MutexLocker lock(m_channel->m_mutex);
+    OwnPtr<PlatformMessagePortChannel::EventData> result = m_channel->m_incomingQueue->tryGetMessage();
+    if (!result)
+        return false;
+
+    message = result->message();
+    channels = result->channels();
+
+    return true;
+}
+
+void MessagePortChannel::close()
+{
+    RefPtr<PlatformMessagePortChannel> remote = m_channel->entangledChannel();
+    if (!remote)
+        return;
+    m_channel->closeInternal();
+    remote->closeInternal();
+}
+
+bool MessagePortChannel::isConnectedTo(MessagePort* port)
+{
+    // FIXME: What guarantees that the result remains the same after we release the lock?
+    MutexLocker lock(m_channel->m_mutex);
+    return m_channel->m_remotePort == port;
+}
+
+bool MessagePortChannel::hasPendingActivity()
+{
+    // FIXME: What guarantees that the result remains the same after we release the lock?
+    MutexLocker lock(m_channel->m_mutex);
+    return !m_channel->m_incomingQueue->isEmpty();
+}
+
+MessagePort* MessagePortChannel::locallyEntangledPort(const ScriptExecutionContext* context)
+{
+    MutexLocker lock(m_channel->m_mutex);
+    // See if both contexts are run by the same thread (are the same context, or are both documents).
+    if (m_channel->m_remotePort) {
+        // The remote port's ScriptExecutionContext is guaranteed not to change here - MessagePort::contextDestroyed()
+        // will close the port before the context goes away, and close() will block because we are holding the mutex.
+        ScriptExecutionContext* remoteContext = m_channel->m_remotePort->scriptExecutionContext();
+        if (remoteContext == context || (remoteContext && remoteContext->isDocument() && context->isDocument()))
+            return m_channel->m_remotePort;
+    }
+    return 0;
+}
+
+PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::create(PassRefPtr<MessagePortQueue> incoming, PassRefPtr<MessagePortQueue> outgoing)
+{
+    return adoptRef(new PlatformMessagePortChannel(incoming, outgoing));
+}
+
+PlatformMessagePortChannel::PlatformMessagePortChannel(PassRefPtr<MessagePortQueue> incoming, PassRefPtr<MessagePortQueue> outgoing)
+    : m_incomingQueue(incoming)
+    , m_outgoingQueue(outgoing)
+    , m_remotePort(0)
+{
+}
+
+PlatformMessagePortChannel::~PlatformMessagePortChannel()
+{
+}
+
+void PlatformMessagePortChannel::setRemotePort(MessagePort* port)
+{
+    MutexLocker lock(m_mutex);
+    // Should never set port if it is already set.
+    ASSERT(!port || !m_remotePort);
+    m_remotePort = port;
+}
+
+PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::entangledChannel()
+{
+    // FIXME: What guarantees that the result remains the same after we release the lock?
+    // This lock only guarantees that the returned pointer will not be pointing to released memory,
+    // but not that it will still be pointing to this object's entangled port channel.
+    MutexLocker lock(m_mutex);
+    return m_entangledChannel;
+}
+
+void PlatformMessagePortChannel::closeInternal()
+{
+    MutexLocker lock(m_mutex);
+    // Disentangle ourselves from the other end. We still maintain a reference to our incoming queue, since previously-existing messages should still be delivered.
+    m_remotePort = 0;
+    m_entangledChannel = 0;
+    m_outgoingQueue = 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/default/PlatformMessagePortChannel.h b/Source/core/dom/default/PlatformMessagePortChannel.h
new file mode 100644
index 0000000..1a087af
--- /dev/null
+++ b/Source/core/dom/default/PlatformMessagePortChannel.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PlatformMessagePortChannel_h
+#define PlatformMessagePortChannel_h
+
+#include "core/dom/MessagePortChannel.h"
+
+#include <wtf/MessageQueue.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/Threading.h>
+
+namespace WebCore {
+
+    class MessagePort;
+
+    // PlatformMessagePortChannel is a platform-dependent interface to the remote side of a message channel.
+    // This default implementation supports multiple threads running within a single process. Implementations for multi-process platforms should define these public APIs in their own platform-specific PlatformMessagePortChannel file.
+    // The goal of this implementation is to eliminate contention except when cloning or closing the port, so each side of the channel has its own separate mutex.
+    class PlatformMessagePortChannel : public ThreadSafeRefCounted<PlatformMessagePortChannel> {
+    public:
+        class EventData {
+            WTF_MAKE_NONCOPYABLE(EventData); WTF_MAKE_FAST_ALLOCATED;
+        public:
+            static PassOwnPtr<EventData> create(PassRefPtr<SerializedScriptValue>, PassOwnPtr<MessagePortChannelArray>);
+
+            PassRefPtr<SerializedScriptValue> message() { return m_message; }
+            PassOwnPtr<MessagePortChannelArray> channels() { return m_channels.release(); }
+
+        private:
+            EventData(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray>);
+            RefPtr<SerializedScriptValue> m_message;
+            OwnPtr<MessagePortChannelArray> m_channels;
+        };
+
+        // Wrapper for MessageQueue that allows us to do thread safe sharing by two proxies.
+        class MessagePortQueue : public ThreadSafeRefCounted<MessagePortQueue> {
+        public:
+            static PassRefPtr<MessagePortQueue> create() { return adoptRef(new MessagePortQueue()); }
+
+            PassOwnPtr<PlatformMessagePortChannel::EventData> tryGetMessage()
+            {
+                return m_queue.tryGetMessage();
+            }
+
+            bool appendAndCheckEmpty(PassOwnPtr<PlatformMessagePortChannel::EventData> message)
+            {
+                return m_queue.appendAndCheckEmpty(message);
+            }
+
+            bool isEmpty()
+            {
+                return m_queue.isEmpty();
+            }
+
+        private:
+            MessagePortQueue() { }
+
+            MessageQueue<PlatformMessagePortChannel::EventData> m_queue;
+        };
+
+        ~PlatformMessagePortChannel();
+
+        static PassRefPtr<PlatformMessagePortChannel> create(PassRefPtr<MessagePortQueue> incoming, PassRefPtr<MessagePortQueue> outgoing);
+        PlatformMessagePortChannel(PassRefPtr<MessagePortQueue> incoming, PassRefPtr<MessagePortQueue> outgoing);
+
+        PassRefPtr<PlatformMessagePortChannel> entangledChannel();
+
+        void setRemotePort(MessagePort*);
+        void closeInternal();
+
+        // Mutex used to ensure exclusive access to the object internals.
+        Mutex m_mutex;
+
+        // Pointer to our entangled pair - cleared when close() is called.
+        RefPtr<PlatformMessagePortChannel> m_entangledChannel;
+
+        // Reference to the message queue for the (local) entangled port.
+        RefPtr<MessagePortQueue> m_incomingQueue;
+        RefPtr<MessagePortQueue> m_outgoingQueue;
+
+        // The port we are connected to (the remote port) - this is the port that is notified when new messages arrive.
+        MessagePort* m_remotePort;
+    };
+
+} // namespace WebCore
+
+#endif // PlatformMessagePortChannel_h
diff --git a/Source/core/dom/default/chromium/PlatformMessagePortChannelChromium.cpp b/Source/core/dom/default/chromium/PlatformMessagePortChannelChromium.cpp
new file mode 100644
index 0000000..59f84a6
--- /dev/null
+++ b/Source/core/dom/default/chromium/PlatformMessagePortChannelChromium.cpp
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/default/chromium/PlatformMessagePortChannelChromium.h"
+
+#include "bindings/v8/SerializedScriptValue.h"
+#include "core/dom/MessagePort.h"
+#include "core/dom/ScriptExecutionContext.h"
+
+#include <public/Platform.h>
+#include <public/WebMessagePortChannel.h>
+#include <public/WebString.h>
+
+namespace WebCore {
+
+PassOwnPtr<MessagePortChannel> MessagePortChannel::create(PassRefPtr<PlatformMessagePortChannel> channel)
+{
+    return adoptPtr(new MessagePortChannel(channel));
+}
+
+void MessagePortChannel::createChannel(PassRefPtr<MessagePort> port1, PassRefPtr<MessagePort> port2)
+{
+    PlatformMessagePortChannel::createChannel(port1, port2);
+}
+
+MessagePortChannel::MessagePortChannel(PassRefPtr<PlatformMessagePortChannel> channel)
+    : m_channel(channel)
+{
+}
+
+MessagePortChannel::~MessagePortChannel()
+{
+    // Make sure we close our platform channel when the base is freed, to keep the channel objects from leaking.
+    m_channel->close();
+}
+
+bool MessagePortChannel::entangleIfOpen(MessagePort* port)
+{
+    return m_channel->entangleIfOpen(port);
+}
+
+void MessagePortChannel::disentangle()
+{
+    m_channel->disentangle();
+}
+
+void MessagePortChannel::postMessageToRemote(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels)
+{
+    m_channel->postMessageToRemote(message, channels);
+}
+
+bool MessagePortChannel::tryGetMessageFromRemote(RefPtr<SerializedScriptValue>& message, OwnPtr<MessagePortChannelArray>& channels)
+{
+    return m_channel->tryGetMessageFromRemote(message, channels);
+}
+
+void MessagePortChannel::close()
+{
+    m_channel->close();
+}
+
+bool MessagePortChannel::isConnectedTo(MessagePort* port)
+{
+    return m_channel->isConnectedTo(port);
+}
+
+bool MessagePortChannel::hasPendingActivity()
+{
+    return m_channel->hasPendingActivity();
+}
+
+MessagePort* MessagePortChannel::locallyEntangledPort(const ScriptExecutionContext* context)
+{
+    // This is just an optimization, so return 0 always.
+    return 0;
+}
+
+
+PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::create()
+{
+    return adoptRef(new PlatformMessagePortChannel());
+}
+
+PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::create(
+    WebKit::WebMessagePortChannel* channel)
+{
+    return adoptRef(new PlatformMessagePortChannel(channel));
+}
+
+
+PlatformMessagePortChannel::PlatformMessagePortChannel()
+    : m_localPort(0)
+{
+    m_webChannel = WebKit::Platform::current()->createMessagePortChannel();
+    if (m_webChannel)
+        m_webChannel->setClient(this);
+}
+
+PlatformMessagePortChannel::PlatformMessagePortChannel(WebKit::WebMessagePortChannel* channel)
+    : m_localPort(0)
+    , m_webChannel(channel)
+{
+}
+
+PlatformMessagePortChannel::~PlatformMessagePortChannel()
+{
+    if (m_webChannel)
+        m_webChannel->destroy();
+}
+
+void PlatformMessagePortChannel::createChannel(PassRefPtr<MessagePort> port1, PassRefPtr<MessagePort> port2)
+{
+    // Create proxies for each endpoint.
+    RefPtr<PlatformMessagePortChannel> channel1 = PlatformMessagePortChannel::create();
+    RefPtr<PlatformMessagePortChannel> channel2 = PlatformMessagePortChannel::create();
+
+    // Entangle the two endpoints.
+    channel1->setEntangledChannel(channel2);
+    channel2->setEntangledChannel(channel1);
+
+    // Now entangle the proxies with the appropriate local ports.
+    port1->entangle(MessagePortChannel::create(channel2));
+    port2->entangle(MessagePortChannel::create(channel1));
+}
+
+void PlatformMessagePortChannel::messageAvailable()
+{
+    MutexLocker lock(m_mutex);
+    if (m_localPort)
+        m_localPort->messageAvailable();
+}
+
+bool PlatformMessagePortChannel::entangleIfOpen(MessagePort* port)
+{
+    MutexLocker lock(m_mutex);
+    m_localPort = port;
+    return true;
+}
+
+void PlatformMessagePortChannel::disentangle()
+{
+    MutexLocker lock(m_mutex);
+    m_localPort = 0;
+}
+
+void PlatformMessagePortChannel::postMessageToRemote(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels)
+{
+    if (!m_localPort || !m_webChannel)
+        return;
+
+    WebKit::WebString messageString = message->toWireString();
+    WebKit::WebMessagePortChannelArray* webChannels = 0;
+    if (channels && channels->size()) {
+        webChannels = new WebKit::WebMessagePortChannelArray(channels->size());
+        for (size_t i = 0; i < channels->size(); ++i) {
+            PlatformMessagePortChannel* platformChannel = (*channels)[i]->channel();
+            (*webChannels)[i] = platformChannel->webChannelRelease();
+            (*webChannels)[i]->setClient(0);
+        }
+    }
+    m_webChannel->postMessage(messageString, webChannels);
+}
+
+bool PlatformMessagePortChannel::tryGetMessageFromRemote(RefPtr<SerializedScriptValue>& serializedMessage, OwnPtr<MessagePortChannelArray>& channels)
+{
+    if (!m_webChannel)
+        return false;
+
+    WebKit::WebString message;
+    WebKit::WebMessagePortChannelArray webChannels;
+    bool rv = m_webChannel->tryGetMessage(&message, webChannels);
+    if (rv) {
+        if (webChannels.size()) {
+            channels = adoptPtr(new MessagePortChannelArray(webChannels.size()));
+            for (size_t i = 0; i < webChannels.size(); ++i) {
+                RefPtr<PlatformMessagePortChannel> platformChannel = create(webChannels[i]);
+                webChannels[i]->setClient(platformChannel.get());
+                (*channels)[i] = MessagePortChannel::create(platformChannel);
+            }
+        }
+        serializedMessage = SerializedScriptValue::createFromWire(message);
+    }
+
+    return rv;
+}
+
+void PlatformMessagePortChannel::close()
+{
+    MutexLocker lock(m_mutex);
+    // Disentangle ourselves from the other end. We still maintain a reference to m_webChannel,
+    // since previously-existing messages should still be delivered.
+    m_localPort = 0;
+    m_entangledChannel = 0;
+}
+
+bool PlatformMessagePortChannel::isConnectedTo(MessagePort* port)
+{
+    MutexLocker lock(m_mutex);
+    return m_entangledChannel && m_entangledChannel->m_localPort == port;
+}
+
+bool PlatformMessagePortChannel::hasPendingActivity()
+{
+    MutexLocker lock(m_mutex);
+    return m_localPort;
+}
+
+void PlatformMessagePortChannel::setEntangledChannel(PassRefPtr<PlatformMessagePortChannel> remote)
+{
+    if (m_webChannel)
+        m_webChannel->entangle(remote->m_webChannel);
+
+    MutexLocker lock(m_mutex);
+    m_entangledChannel = remote;
+}
+
+WebKit::WebMessagePortChannel* PlatformMessagePortChannel::webChannelRelease()
+{
+    WebKit::WebMessagePortChannel* rv = m_webChannel;
+    m_webChannel = 0;
+    return rv;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/default/chromium/PlatformMessagePortChannelChromium.h b/Source/core/dom/default/chromium/PlatformMessagePortChannelChromium.h
new file mode 100644
index 0000000..ba37f05
--- /dev/null
+++ b/Source/core/dom/default/chromium/PlatformMessagePortChannelChromium.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PlatformMessagePortChannelChromium_h
+#define PlatformMessagePortChannelChromium_h
+
+
+#include "core/dom/MessagePortChannel.h"
+#include <public/WebMessagePortChannelClient.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/Threading.h>
+
+namespace WebKit {
+class WebMessagePortChannel;
+}
+
+namespace WebCore {
+
+class MessagePort;
+
+// PlatformMessagePortChannel is a platform-dependent interface to the remote side of a message channel.
+class PlatformMessagePortChannel : public ThreadSafeRefCounted<PlatformMessagePortChannel>,
+    public WebKit::WebMessagePortChannelClient {
+public:
+    static void createChannel(PassRefPtr<MessagePort>, PassRefPtr<MessagePort>);
+    static PassRefPtr<PlatformMessagePortChannel> create();
+    static PassRefPtr<PlatformMessagePortChannel> create(WebKit::WebMessagePortChannel*);
+
+    // APIs delegated from core/dom/MessagePortChannel.h
+    bool entangleIfOpen(MessagePort*);
+    void disentangle();
+    void postMessageToRemote(PassRefPtr<SerializedScriptValue>, PassOwnPtr<MessagePortChannelArray>);
+    bool tryGetMessageFromRemote(RefPtr<SerializedScriptValue>&, OwnPtr<MessagePortChannelArray>&);
+    void close();
+    bool isConnectedTo(MessagePort*);
+    bool hasPendingActivity();
+
+    // Releases ownership of the contained web channel.
+    WebKit::WebMessagePortChannel* webChannelRelease();
+
+    virtual ~PlatformMessagePortChannel();
+
+private:
+    PlatformMessagePortChannel();
+    PlatformMessagePortChannel(WebKit::WebMessagePortChannel*);
+
+    void setEntangledChannel(PassRefPtr<PlatformMessagePortChannel>);
+
+    // WebKit::WebMessagePortChannelClient implementation
+    virtual void messageAvailable();
+
+    // Mutex used to ensure exclusive access to the object internals.
+    Mutex m_mutex;
+
+    // Pointer to our entangled pair - cleared when close() is called.
+    RefPtr<PlatformMessagePortChannel> m_entangledChannel;
+
+    // The port we are connected to - this is the port that is notified when new messages arrive.
+    MessagePort* m_localPort;
+
+    WebKit::WebMessagePortChannel* m_webChannel;
+};
+
+} // namespace WebCore
+
+#endif // PlatformMessagePortChannelChromium_h