LayoutTests:
[WebKit-https.git] / WebCore / dom / Document.cpp
index bd39b83..ae3ff06 100644 (file)
@@ -4,6 +4,7 @@
  * 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 Apple Computer, Inc.
  *
  * This library is free software; you can redistribute it and/or
 #include "CSSValueKeywords.h"
 #include "Comment.h"
 #include "DOMImplementation.h"
-#include "Decoder.h"
 #include "DocLoader.h"
 #include "DocumentFragment.h"
+#include "DocumentLoader.h"
 #include "DocumentType.h"
 #include "EditingText.h"
+#include "Editor.h"
+#include "EditorClient.h"
 #include "EntityReference.h"
 #include "Event.h"
+#include "EventHandler.h"
 #include "EventListener.h"
 #include "EventNames.h"
 #include "ExceptionCode.h"
+#include "FocusController.h"
 #include "Frame.h"
+#include "FrameLoader.h"
 #include "FrameTree.h"
+#include "FrameView.h"
+#include "HitTestRequest.h"
+#include "HitTestResult.h"
 #include "HTMLBodyElement.h"
 #include "HTMLDocument.h"
 #include "HTMLElementFactory.h"
+#include "HTMLFrameOwnerElement.h"
+#include "HTMLHeadElement.h"
 #include "HTMLImageLoader.h"
 #include "HTMLInputElement.h"
 #include "HTMLLinkElement.h"
@@ -53,6 +64,8 @@
 #include "HTMLNameCollection.h"
 #include "HTMLNames.h"
 #include "HTMLStyleElement.h"
+#include "HTMLTitleElement.h"
+#include "HTTPParsers.h"
 #include "JSEditor.h"
 #include "KeyboardEvent.h"
 #include "Logging.h"
 #include "StringHash.h"
 #include "StyleSheetList.h"
 #include "SystemTime.h"
+#include "TextEvent.h"
 #include "TextIterator.h"
+#include "TextResourceDecoder.h"
 #include "TreeWalker.h"
 #include "UIEvent.h"
+#include "XMLTokenizer.h"
 #include "csshelper.h"
 #include "cssstyleselector.h"
 #include "kjs_binding.h"
 #include "kjs_proxy.h"
-#include "XMLTokenizer.h"
 #include "xmlhttprequest.h"
 
-#ifdef XPATH_SUPPORT
+#if ENABLE(XPATH)
 #include "XPathEvaluator.h"
 #include "XPathExpression.h"
 #include "XPathNSResolver.h"
 #include "XPathResult.h"
 #endif
 
-#ifdef KHTML_XSLT
+#if ENABLE(XSLT)
 #include "XSLTProcessor.h"
 #endif
 
-#ifndef KHTML_NO_XBL
-#include "xbl_binding_manager.h"
-using XBL::XBLBindingManager;
+#if ENABLE(XBL)
+#include "XBLBindingManager.h"
 #endif
 
-#ifdef SVG_SUPPORT
+#if ENABLE(SVG)
 #include "SVGDocumentExtensions.h"
 #include "SVGElementFactory.h"
 #include "SVGZoomEvent.h"
 #include "SVGStyleElement.h"
-#include "KSVGTimeScheduler.h"
+#include "TimeScheduler.h"
 #endif
 
 using namespace std;
+using namespace WTF;
+using namespace Unicode;
 
 namespace WebCore {
 
@@ -120,10 +136,10 @@ using namespace HTMLNames;
 // 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. :)
-const int cLayoutScheduleThreshold = 250;
+static const int cLayoutScheduleThreshold = 250;
 
 // Use 1 to represent the document's default form.
-HTMLFormElement* const defaultForm = (HTMLFormElement*) 1;
+static HTMLFormElement* const defaultForm = reinterpret_cast<HTMLFormElement*>(1);
 
 // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
 static const unsigned PHI = 0x9e3779b9U;
@@ -154,8 +170,8 @@ static inline bool isValidNameStart(UChar32 c)
         return true;
 
     // rules (a) and (f) above
-    const uint32_t nameStartMask = U_GC_LL_MASK | U_GC_LU_MASK | U_GC_LO_MASK | U_GC_LT_MASK | U_GC_NL_MASK;
-    if (!(U_GET_GC_MASK(c) & nameStartMask))
+    const uint32_t nameStartMask = Letter_Lowercase | Letter_Uppercase | Letter_Other | Letter_Titlecase | Number_Letter;
+    if (!(Unicode::category(c) & nameStartMask))
         return false;
 
     // rule (c) above
@@ -163,8 +179,8 @@ static inline bool isValidNameStart(UChar32 c)
         return false;
 
     // rule (d) above
-    UDecompositionType decompType = static_cast<UDecompositionType>(u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE));
-    if (decompType == U_DT_FONT || decompType == U_DT_COMPAT)
+    DecompositionType decompType = decompositionType(c);
+    if (decompType == DecompositionFont || decompType == DecompositionCompat)
         return false;
 
     return true;
@@ -185,8 +201,8 @@ static inline bool isValidNamePart(UChar32 c)
         return true;
 
     // rules (b) and (f) above
-    const uint32_t otherNamePartMask = U_GC_MC_MASK | U_GC_ME_MASK | U_GC_MN_MASK | U_GC_LM_MASK | U_GC_ND_MASK;
-    if (!(U_GET_GC_MASK(c) & otherNamePartMask))
+    const uint32_t otherNamePartMask = Mark_NonSpacing | Mark_Enclosing | Mark_SpacingCombining | Letter_Modifier | Number_DecimalDigit;
+    if (!(Unicode::category(c) & otherNamePartMask))
         return false;
 
     // rule (c) above
@@ -194,14 +210,62 @@ static inline bool isValidNamePart(UChar32 c)
         return false;
 
     // rule (d) above
-    UDecompositionType decompType = static_cast<UDecompositionType>(u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE));
-    if (decompType == U_DT_FONT || decompType == U_DT_COMPAT)
+    DecompositionType decompType = decompositionType(c);
+    if (decompType == DecompositionFont || decompType == DecompositionCompat)
         return false;
 
     return true;
 }
 
-DeprecatedPtrList<Document> * Document::changedDocuments = 0;
+static Widget* widgetForNode(Node* focusedNode)
+  {
+    if (!focusedNode)
+        return 0;
+    RenderObject* renderer = focusedNode->renderer();
+    if (!renderer || !renderer->isWidget())
+        return 0;
+    return static_cast<RenderWidget*>(renderer)->widget();
+}
+
+static bool relinquishesEditingFocus(Node *node)
+{
+    assert(node);
+    assert(node->isContentEditable());
+
+    Node *root = node->rootEditableElement();
+    Frame* frame = node->document()->frame();
+    if (!frame || !root)
+        return false;
+
+    return frame->editor()->shouldEndEditing(rangeOfContents(root).get());
+}
+
+static bool acceptsEditingFocus(Node *node)
+{
+    assert(node);
+    assert(node->isContentEditable());
+
+    Node *root = node->rootEditableElement();
+    Frame* frame = node->document()->frame();
+    if (!frame || !root)
+        return false;
+
+    return frame->editor()->shouldBeginEditing(rangeOfContents(root).get());
+}
+
+static void clearSelectionIfNeeded(Frame* frame, Node* newFocusedNode)
+{
+    if (!frame)
+        return;
+
+    // Clear the selection when changing the focus node to null or to a node that is not 
+    // contained by the current selection.
+    Node* startContainer = frame->selectionController()->start().node();
+    if (!newFocusedNode || (startContainer && startContainer != newFocusedNode && !(startContainer->isDescendantOf(newFocusedNode)) && startContainer->shadowAncestorNode() != newFocusedNode))
+        frame->selectionController()->clear();
+}
+
+DeprecatedPtrList<Document>*  Document::changedDocuments = 0;
 
 // FrameView might be 0
 Document::Document(DOMImplementation* impl, FrameView *v)
@@ -212,27 +276,30 @@ Document::Document(DOMImplementation* impl, FrameView *v)
     , m_title("")
     , m_titleSetExplicitly(false)
     , m_imageLoadEventTimer(this, &Document::imageLoadEventTimerFired)
-#if !KHTML_NO_XBL
-    , m_bindingManager(new XBLBindingManager(this))
-#endif
-#ifdef KHTML_XSLT
+#if ENABLE(XSLT)
     , m_transformSource(0)
 #endif
+    , m_xmlVersion("1.0")
+    , m_xmlStandalone(false)
+#if ENABLE(XBL)
+    , m_bindingManager(new XBLBindingManager(this))
+#endif
     , m_savedRenderer(0)
     , m_passwordFields(0)
     , m_secureForms(0)
     , m_designMode(inherit)
     , m_selfOnlyRefCount(0)
-#ifdef SVG_SUPPORT
+#if ENABLE(SVG)
     , m_svgExtensions(0)
 #endif
-#if __APPLE__
+#if PLATFORM(MAC)
     , m_hasDashboardRegions(false)
     , m_dashboardRegionsDirty(false)
 #endif
     , m_accessKeyMapValid(false)
     , m_createRenderers(true)
     , m_inPageCache(false)
+    , m_isAllowedToLoadLocalResources(false)
 {
     m_document.resetSkippingRef(this);
 
@@ -246,17 +313,16 @@ Document::Document(DOMImplementation* impl, FrameView *v)
     m_docLoader = new DocLoader(v ? v->frame() : 0, this);
 
     visuallyOrdered = false;
-    m_loadingSheet = false;
     m_bParsing = false;
     m_docChanged = false;
     m_tokenizer = 0;
+    m_wellFormed = false;
 
     pMode = Strict;
     hMode = XHtml;
     m_textColor = Color::black;
     m_listenerTypes = 0;
     m_inDocument = true;
-    m_styleSelectorDirty = false;
     m_inStyleRecalc = false;
     m_closeAfterStyleRecalc = false;
     m_usesDescendantRules = false;
@@ -265,7 +331,7 @@ Document::Document(DOMImplementation* impl, FrameView *v)
     m_styleSelector = new CSSStyleSelector(this, m_usersheet, m_styleSheets.get(), !inCompatMode());
     m_pendingStylesheets = 0;
     m_ignorePendingStylesheets = false;
-    m_didLayoutWithPendingStylesheets = false;
+    m_pendingSheetLayout = NoLayoutWithPendingSheets;
 
     m_cssTarget = 0;
 
@@ -296,7 +362,7 @@ void Document::removedLastRef()
         // 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_focusNode = 0;
+        m_focusedNode = 0;
         m_hoverNode = 0;
         m_activeNode = 0;
         m_titleElement = 0;
@@ -315,16 +381,21 @@ void Document::removedLastRef()
 
 Document::~Document()
 {
-    assert(!renderer());
-    assert(!m_inPageCache);
-    assert(m_savedRenderer == 0);
+    ASSERT(!renderer());
+    ASSERT(!m_inPageCache);
+    ASSERT(!m_savedRenderer);
 
-#ifdef SVG_SUPPORT
+    removeAllEventListeners();
+
+#if ENABLE(SVG)
     delete m_svgExtensions;
 #endif
 
     XMLHttpRequest::detachRequests(this);
-    KJS::ScriptInterpreter::forgetAllDOMNodesForDocument(this);
+    {
+        KJS::JSLock lock;
+        KJS::ScriptInterpreter::forgetAllDOMNodesForDocument(this);
+    }
 
     if (m_docChanged && changedDocuments)
         changedDocuments->remove(this);
@@ -338,11 +409,11 @@ Document::~Document()
         m_renderArena = 0;
     }
 
-#ifdef KHTML_XSLT
+#if ENABLE(XSLT)
     xmlFreeDoc((xmlDocPtr)m_transformSource);
 #endif
 
-#ifndef KHTML_NO_XBL
+#if ENABLE(XBL)
     delete m_bindingManager;
 #endif
 
@@ -462,7 +533,7 @@ PassRefPtr<EntityReference> Document::createEntityReference(const String &name,
         ec = NOT_SUPPORTED_ERR;
         return 0;
     }
-    return new EntityReference(this, name.impl());
+    return new EntityReference(this, name);
 }
 
 PassRefPtr<EditingText> Document::createEditingTextNode(const String &text)
@@ -570,17 +641,39 @@ PassRefPtr<Node> Document::adoptNode(PassRefPtr<Node> source, ExceptionCode& ec)
                 source->parentNode()->removeChild(source.get(), ec);
     }
                 
-    for (Node* node = source.get(); node; node = node->traverseNextNode(source.get())) {
-        KJS::ScriptInterpreter::updateDOMNodeDocument(node, node->document(), this);
+    for (Node* node = source.get(); node; node = node->traverseNextNode(source.get()))
         node->setDocument(this);
-    }
 
     return source;
 }
 
+// FIXME: This should really be in a possible ElementFactory class
+PassRefPtr<Element> Document::createElement(const QualifiedName& qName, bool createdByParser, ExceptionCode& ec)
+{
+    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.localName(), this, 0, createdByParser);
+#if ENABLE(SVG)
+    else if (qName.namespaceURI() == SVGNames::svgNamespaceURI)
+        e = SVGElementFactory::createSVGElement(qName, this, createdByParser);
+#endif
+    
+    if (!e)
+        e = new Element(qName, document());
+    
+    if (e && !qName.prefix().isNull()) {
+        e->setPrefix(qName.prefix(), ec);
+        if (ec)
+            return 0;
+    }    
+    
+    return e.release();
+}
+
 PassRefPtr<Element> Document::createElementNS(const String &_namespaceURI, const String &qualifiedName, ExceptionCode& ec)
 {
-    // FIXME: We'd like a faster code path that skips this check for calls from inside the engine where the name is known to be valid.
     String prefix, localName;
     if (!parseQualifiedName(qualifiedName, prefix, localName)) {
         ec = INVALID_CHARACTER_ERR;
@@ -590,24 +683,7 @@ PassRefPtr<Element> Document::createElementNS(const String &_namespaceURI, const
     RefPtr<Element> e;
     QualifiedName qName = QualifiedName(AtomicString(prefix), AtomicString(localName), AtomicString(_namespaceURI));
     
-    // FIXME: Use registered namespaces and look up in a hash to find the right factory.
-    if (_namespaceURI == xhtmlNamespaceURI) {
-        e = HTMLElementFactory::createHTMLElement(qName.localName(), this, 0, false);
-        if (e && !prefix.isNull()) {
-            e->setPrefix(qName.prefix(), ec);
-            if (ec)
-                return 0;
-        }
-    }
-#ifdef SVG_SUPPORT
-    else if (_namespaceURI == SVGNames::svgNamespaceURI)
-        e = SVGElementFactory::createSVGElement(qName, this, false);
-#endif
-    
-    if (!e)
-        e = new Element(qName, document());
-    
-    return e.release();
+    return createElement(qName, false, ec);
 }
 
 Element *Document::getElementById(const AtomicString& elementId) const
@@ -637,7 +713,7 @@ Element *Document::getElementById(const AtomicString& elementId) const
 String Document::readyState() const
 {
     if (Frame* f = frame()) {
-        if (f->isComplete()) 
+        if (f->loader()->isComplete()) 
             return "complete";
         if (parsing()) 
             return "loading";
@@ -650,15 +726,15 @@ String Document::readyState() const
 
 String Document::inputEncoding() const
 {
-    if (Decoder* d = decoder())
-        return d->encodingName();
+    if (TextResourceDecoder* d = decoder())
+        return d->encoding().name();
     return String();
 }
 
 String Document::defaultCharset() const
 {
     if (Frame* f = frame())
-        return f->settings()->encoding();
+        return f->settings()->defaultTextEncodingName();
     return String();
 }
 
@@ -666,7 +742,43 @@ void Document::setCharset(const String& charset)
 {
     if (!decoder())
         return;
-    decoder()->setEncodingName(charset.deprecatedString().ascii(), Decoder::UserChosenEncoding);
+    decoder()->setEncoding(charset, TextResourceDecoder::UserChosenEncoding);
+}
+
+void Document::setXMLVersion(const String& version, ExceptionCode& ec)
+{
+    // FIXME: also raise NOT_SUPPORTED_ERR if the version is set to a value that is not supported by this Document.
+    if (!implementation()->hasFeature("XML", String())) {
+        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;
+}
+
+String Document::documentURI() const
+{
+    return m_baseURL;
+}
+
+void Document::setDocumentURI(const String &uri)
+{
+    m_baseURL = uri.deprecatedString();
+}
+
+String Document::baseURI() const
+{
+    return documentURI();
 }
 
 Element* Document::elementFromPoint(int x, int y) const
@@ -674,10 +786,11 @@ Element* Document::elementFromPoint(int x, int y) const
     if (!renderer())
         return 0;
 
-    RenderObject::NodeInfo nodeInfo(true, true);
-    renderer()->layer()->hitTest(nodeInfo, IntPoint(x, y)); 
+    HitTestRequest request(true, true);
+    HitTestResult result(IntPoint(x, y));
+    renderer()->layer()->hitTest(request, result); 
 
-    Node* n = nodeInfo.innerNode();
+    Node* n = result.innerNode();
     while (n && !n->isElementNode())
         n = n->parentNode();
     if (n)
@@ -722,17 +835,27 @@ Element* Document::getElementByAccessKey(const String& key) const
 void Document::updateTitle()
 {
     if (Frame* f = frame())
-        f->setTitle(m_title);
+        f->loader()->setTitle(m_title);
 }
 
-void Document::setTitle(const String& title, Node* titleElement)
+void Document::setTitle(const String& title, Element* titleElement)
 {
     if (!titleElement) {
         // Title set by JavaScript -- overrides any title elements.
         m_titleSetExplicitly = true;
-        m_titleElement = 0;
+        if (!isHTMLDocument())
+            m_titleElement = 0;
+        else if (!m_titleElement) {
+            if (HTMLElement* headElement = head()) {
+                ExceptionCode ec = 0;
+                m_titleElement = createElement("title", ec);
+                ASSERT(!ec);
+                headElement->appendChild(m_titleElement, ec);
+                ASSERT(!ec);
+            }
+        }
     } else if (titleElement != m_titleElement) {
-        if (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;
@@ -743,17 +866,30 @@ void Document::setTitle(const String& title, Node* titleElement)
 
     m_title = title;
     updateTitle();
+
+    if (m_titleSetExplicitly && m_titleElement && m_titleElement->hasTagName(titleTag))
+        static_cast<HTMLTitleElement*>(m_titleElement.get())->setText(m_title);
 }
 
-void Document::removeTitle(Node* titleElement)
+void Document::removeTitle(Element* titleElement)
 {
     if (m_titleElement != titleElement)
         return;
 
-    // FIXME: Ideally we might want this to search for the first remaining title element, and use it.
     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);
+                setTitle(titleElement->text(), titleElement);
+                break;
+            }
+    }
 
-    if (!m_title.isEmpty()) {
+    if (!m_titleElement && !m_title.isEmpty()) {
         m_title = "";
         updateTitle();
     }
@@ -769,11 +905,22 @@ Node::NodeType Document::nodeType() const
     return DOCUMENT_NODE;
 }
 
+FrameView* Document::view() const
+{
+    return m_view;
+}
+
 Frame* Document::frame() const 
 {
     return m_view ? m_view->frame() : 0; 
 }
 
+Page* Document::page() const
+{
+    Frame* frame = this->frame();
+    return frame ? frame->page() : 0;    
+}
+
 PassRefPtr<Range> Document::createRange()
 {
     return new Range(this);
@@ -846,12 +993,13 @@ void Document::recalcStyle(StyleChange change)
             const Settings *settings = m_view->frame()->settings();
             if (printing() && !settings->shouldPrintBackgrounds())
                 _style->setForceBackgroundsToWhite(true);
-            const AtomicString& stdfont = settings->stdFontName();
+            const AtomicString& stdfont = settings->standardFontFamily();
             if (!stdfont.isEmpty()) {
                 fontDescription.firstFamily().setFamily(stdfont);
                 fontDescription.firstFamily().appendFamily(0);
             }
-            m_styleSelector->setFontSize(fontDescription, m_styleSelector->fontSizeForKeyword(CSS_VAL_MEDIUM, inCompatMode()));
+            fontDescription.setKeywordSize(CSS_VAL_MEDIUM - CSS_VAL_XX_SMALL + 1);
+            m_styleSelector->setFontSize(fontDescription, m_styleSelector->fontSizeForKeyword(CSS_VAL_MEDIUM, inCompatMode(), false));
         }
 
         _style->setFontDescription(fontDescription);
@@ -930,7 +1078,14 @@ void Document::updateLayoutIgnorePendingStylesheets()
     
     if (!haveStylesheetsLoaded()) {
         m_ignorePendingStylesheets = true;
-        m_didLayoutWithPendingStylesheets = 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.
+        if (body() && !body()->renderer() && m_pendingSheetLayout == NoLayoutWithPendingSheets)
+            m_pendingSheetLayout = DidLayoutWithPendingSheets;
         updateStyleSelector();    
     }
 
@@ -980,7 +1135,7 @@ void Document::detach()
     m_imageLoadEventDispatchingList.clear();
     
     m_hoverNode = 0;
-    m_focusNode = 0;
+    m_focusedNode = 0;
     m_activeNode = 0;
 
     ContainerNode::detach();
@@ -1067,45 +1222,44 @@ void Document::updateSelection()
         return;
     
     RenderView *canvas = static_cast<RenderView*>(renderer());
-    SelectionController s = frame()->selection();
+    Selection selection = frame()->selectionController()->selection();
         
-    if (!s.isRange())
+    if (!selection.isRange())
         canvas->clearSelection();
     else {
         // Use the rightmost candidate for the start of the selection, and the leftmost candidate for the end of the selection.
         // Example: foo <a>bar</a>.  Imagine that a line wrap occurs after 'foo', and that 'bar' is selected.   If we pass [foo, 3]
         // as the start of the selection, the selection painting code will think that content on the line containing 'foo' is selected
         // and will fill the gap before 'bar'.
-        Position startPos = s.selection().visibleStart().deepEquivalent();
-        if (startPos.downstream().inRenderedContent())
+        Position startPos = selection.visibleStart().deepEquivalent();
+        if (startPos.downstream().isCandidate())
             startPos = startPos.downstream();
-        Position endPos = s.selection().visibleEnd().deepEquivalent();
-        if (endPos.upstream().inRenderedContent())
+        Position endPos = selection.visibleEnd().deepEquivalent();
+        if (endPos.upstream().isCandidate())
             endPos = endPos.upstream();
         
         // We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted
         // because we don't yet notify the SelectionController of text removal.
-        if (startPos.isNotNull() && endPos.isNotNull() && s.selection().visibleStart() != s.selection().visibleEnd()) {
+        if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) {
             RenderObject *startRenderer = startPos.node()->renderer();
             RenderObject *endRenderer = endPos.node()->renderer();
             static_cast<RenderView*>(renderer())->setSelection(startRenderer, startPos.offset(), endRenderer, endPos.offset());
         }
     }
     
-#if __APPLE__
-    // FIXME: We shouldn't post this AX notification here since updateSelection() is called far to often: every time Safari gains
+#if PLATFORM(MAC)
+    // FIXME: We shouldn't post this AX notification here since updateSelection() is called far too often: every time Safari gains
     // or loses focus, and once for every low level change to the selection during an editing operation.
     // FIXME: We no longer blow away the selection before starting an editing operation, so the isNotNull checks below are no 
     // longer a correct way to check for user-level selection changes.
-    if (AXObjectCache::accessibilityEnabled() && s.start().isNotNull() && s.end().isNotNull()) {
-        axObjectCache()->postNotification(s.start().node()->renderer(), "AXSelectedTextChanged");
-    }
+    if (AXObjectCache::accessibilityEnabled() && selection.start().isNotNull() && selection.end().isNotNull())
+        axObjectCache()->postNotification(selection.start().node()->renderer(), "AXSelectedTextChanged");
 #endif
 }
 
-Tokenizer *Document::createTokenizer()
+TokenizerDocument::createTokenizer()
 {
-    return newXMLTokenizer(this, m_view);
+    return new XMLTokenizer(this, m_view);
 }
 
 void Document::open()
@@ -1116,17 +1270,14 @@ void Document::open()
         setURL(parent->baseURL());
         setBaseURL(parent->baseURL());
     }
-    else
-        setURL(DeprecatedString());
-        
 
-    if ((frame() && frame()->isLoadingMainResource()) || (tokenizer() && tokenizer()->executingScript()))
+    if ((frame() && frame()->loader()->isLoadingMainResource()) || (tokenizer() && tokenizer()->executingScript()))
         return;
 
     implicitOpen();
 
     if (frame())
-        frame()->didExplicitOpen();
+        frame()->loader()->didExplicitOpen();
 }
 
 void Document::cancelParsing()
@@ -1153,7 +1304,7 @@ void Document::implicitOpen()
 
 HTMLElement* Document::body()
 {
-    Node *de = documentElement();
+    Nodede = documentElement();
     if (!de)
         return 0;
     
@@ -1166,13 +1317,26 @@ HTMLElement* Document::body()
         if (i->hasTagName(bodyTag))
             body = i;
     }
-    return static_cast<HTMLElement *>(body);
+    return static_cast<HTMLElement*>(body);
+}
+
+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()
 {
     if (frame())
-        frame()->endIfNotLoading();
+        frame()->loader()->endIfNotLoading();
     implicitClose();
 }
 
@@ -1184,7 +1348,7 @@ void Document::implicitClose()
         return;
     }
 
-    bool wasLocationChangePending = frame() && frame()->isScheduledLocationChangePending();
+    bool wasLocationChangePending = frame() && frame()->loader()->isScheduledLocationChangePending();
     bool doload = !parsing() && m_tokenizer && !m_processingLoadEvent && !wasLocationChangePending;
     
     if (!doload)
@@ -1192,6 +1356,8 @@ void Document::implicitClose()
 
     m_processingLoadEvent = true;
 
+    m_wellFormed = m_tokenizer && m_tokenizer->wellFormed();
+
     // We have to clear the tokenizer, in case someone document.write()s from the
     // onLoad event handler, as in Radar 3206524.
     delete m_tokenizer;
@@ -1214,8 +1380,8 @@ void Document::implicitClose()
     
     dispatchImageLoadEventsNow();
     this->dispatchWindowEvent(loadEvent, false, false);
-    if (Frame *p = frame())
-        p->handledOnloadEvents();
+    if (Frame* f = frame())
+        f->loader()->handledOnloadEvents();
 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
     if (!ownerElement())
         printf("onload fired at %d\n", elapsedTime());
@@ -1223,19 +1389,22 @@ void Document::implicitClose()
 
     m_processingLoadEvent = false;
 
+    // An event handler may have removed the frame
+    if (!frame())
+        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() && frame()->isScheduledLocationChangePending() && elapsedTime() < cLayoutScheduleThreshold) {
+    if (frame()->loader()->isScheduledLocationChangePending() && elapsedTime() < cLayoutScheduleThreshold) {
         // Just bail out. Before or during the onload we were shifted to another page.
         // The old i-Bench suite does this. When this happens don't bother painting or laying out.        
         view()->unscheduleRelayout();
         return;
     }
 
-    if (frame())
-        frame()->checkEmitLoadEvent();
+    frame()->loader()->checkEmitLoadEvent();
 
     // Now do our painting/layout, but only if we aren't in a subframe or if we're in a subframe
     // that has been sized already.  Otherwise, our view size would be incorrect, so doing any 
@@ -1247,12 +1416,13 @@ void Document::implicitClose()
         if (view() && renderer() && (!renderer()->firstChild() || renderer()->needsLayout()))
             view()->layout();
     }
-#if __APPLE__
+
+#if PLATFORM(MAC)
     if (renderer() && AXObjectCache::accessibilityEnabled())
         axObjectCache()->postNotificationToElement(renderer(), "AXLoadComplete");
 #endif
 
-#ifdef SVG_SUPPORT
+#if ENABLE(SVG)
     // FIXME: Officially, time 0 is when the outermost <svg> receives its
     // SVGLoad event, but we don't implement those yet.  This is close enough
     // for now.  In some cases we should have fired earlier.
@@ -1301,12 +1471,12 @@ int Document::elapsedTime() const
     return static_cast<int>((currentTime() - m_startTime) * 1000);
 }
 
-void Document::write(const String &text)
+void Document::write(const DeprecatedString& text)
 {
-    write(text.deprecatedString());
+    write(String(text));
 }
 
-void Document::write(const DeprecatedString &text)
+void Document::write(const String& text)
 {
 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
     if (!ownerElement())
@@ -1357,23 +1527,48 @@ void Document::clear()
 
     removeChildren();
 
-    RegisteredEventListenerList::iterator end = m_windowEventListeners.end();
-    for (RegisteredEventListenerList::iterator it = m_windowEventListeners.begin(); it != end; ++it)
-        m_windowEventListeners.remove(it);
+    m_windowEventListeners.clear();
 }
 
 void Document::setURL(const DeprecatedString& url)
 {
+    if (url == m_url)
+        return;
+
     m_url = url;
     if (m_styleSelector)
         m_styleSelector->setEncodedURL(m_url);
+
+    m_isAllowedToLoadLocalResources = shouldBeAllowedToLoadLocalResources();
+ }
+bool Document::shouldBeAllowedToLoadLocalResources() const
+{
+    if (FrameLoader::shouldTreatURLAsLocal(m_url))
+        return true;
+
+    Frame* frame = this->frame();
+    if (!frame)
+        return false;
+    
+    DocumentLoader* documentLoader = frame->loader()->documentLoader();
+    if (!documentLoader)
+        return false;
+    
+    return documentLoader->substituteData().isValid();
+}
+
+void Document::setBaseURL(const DeprecatedString& baseURL) 
+{ 
+    m_baseURL = baseURL; 
+    if (m_elemSheet)
+        m_elemSheet->setHref(m_baseURL);
 }
 
-void Document::setStyleSheet(const String &url, const String &sheet)
+void Document::setCSSStyleSheet(const String &url, const String& charset, const String &sheet)
 {
-    m_sheet = new CSSStyleSheet(this, url);
+    m_sheet = new CSSStyleSheet(this, url, charset);
     m_sheet->parseString(sheet);
-    m_loadingSheet = false;
 
     updateStyleSelector();
 }
@@ -1393,205 +1588,111 @@ CSSStyleSheet* Document::elementSheet()
     return m_elemSheet.get();
 }
 
-void Document::determineParseMode(const DeprecatedString &/*str*/)
+void Document::determineParseMode(const String&)
 {
-    // For XML documents use strict parse mode.  HTML docs will override this method to
-    // determine their parse mode.
+    // For XML documents use strict parse mode.
+    // HTML overrides this method to determine the parse mode.
     pMode = Strict;
     hMode = XHtml;
 }
 
-Node *Document::nextFocusNode(Node *fromNode)
+static Node* nextNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
 {
-    unsigned short fromTabIndex;
-
-    if (!fromNode) {
-        // No starting node supplied; begin with the top of the document
-        Node *n;
-
-        int lowestTabIndex = 65535;
-        for (n = this; n != 0; n = n->traverseNextNode()) {
-            if (n->isKeyboardFocusable()) {
-                if ((n->tabIndex() > 0) && (n->tabIndex() < lowestTabIndex))
-                    lowestTabIndex = n->tabIndex();
-            }
-        }
-
-        if (lowestTabIndex == 65535)
-            lowestTabIndex = 0;
-
-        // Go to the first node in the document that has the desired tab index
-        for (n = this; n != 0; n = n->traverseNextNode()) {
-            if (n->isKeyboardFocusable() && (n->tabIndex() == lowestTabIndex))
-                return n;
-        }
-
-        return 0;
-    }
-    else {
-        fromTabIndex = fromNode->tabIndex();
-    }
-
-    if (fromTabIndex == 0) {
-        // Just need to find the next selectable node after fromNode (in document order) that doesn't have a tab index
-        Node *n = fromNode->traverseNextNode();
-        while (n && !(n->isKeyboardFocusable() && n->tabIndex() == 0))
-            n = n->traverseNextNode();
-        return n;
-    }
-    else {
-        // Find the lowest tab index out of all the nodes except fromNode, that is greater than or equal to fromNode's
-        // tab index. For nodes with the same tab index as fromNode, we are only interested in those that come after
-        // fromNode in document order.
-        // If we don't find a suitable tab index, the next focus node will be one with a tab index of 0.
-        unsigned short lowestSuitableTabIndex = 65535;
-        Node *n;
-
-        bool reachedFromNode = false;
-        for (n = this; n != 0; n = n->traverseNextNode()) {
-            if (n->isKeyboardFocusable() &&
-                ((reachedFromNode && (n->tabIndex() >= fromTabIndex)) ||
-                 (!reachedFromNode && (n->tabIndex() > fromTabIndex))) &&
-                (n->tabIndex() < lowestSuitableTabIndex) &&
-                (n != fromNode)) {
-
-                // We found a selectable node with a tab index at least as high as fromNode's. Keep searching though,
-                // as there may be another node which has a lower tab index but is still suitable for use.
-                lowestSuitableTabIndex = n->tabIndex();
-            }
-
-            if (n == fromNode)
-                reachedFromNode = true;
-        }
-
-        if (lowestSuitableTabIndex == 65535) {
-            // No next node with a tab index -> just take first node with tab index of 0
-            Node *n = this;
-            while (n && !(n->isKeyboardFocusable() && n->tabIndex() == 0))
-                n = n->traverseNextNode();
+    // Search is inclusive of start
+    for (Node* n = start; n; n = n->traverseNextNode())
+        if (n->isKeyboardFocusable(event) && n->tabIndex() == tabIndex)
             return n;
-        }
+    
+    return 0;
+}
 
-        // Search forwards from fromNode
-        for (n = fromNode->traverseNextNode(); n != 0; n = n->traverseNextNode()) {
-            if (n->isKeyboardFocusable() && (n->tabIndex() == lowestSuitableTabIndex))
-                return n;
-        }
+static Node* previousNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
+{
+    // Search is inclusive of start
+    for (Node* n = start; n; n = n->traversePreviousNode())
+        if (n->isKeyboardFocusable(event) && n->tabIndex() == tabIndex)
+            return n;
+    
+    return 0;
+}
 
-        // The next node isn't after fromNode, start from the beginning of the document
-        for (n = this; n != fromNode; n = n->traverseNextNode()) {
-            if (n->isKeyboardFocusable() && (n->tabIndex() == lowestSuitableTabIndex))
-                return n;
+static Node* nextNodeWithGreaterTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
+{
+    // Search is inclusive of start
+    int winningTabIndex = SHRT_MAX + 1;
+    Node* winner = 0;
+    for (Node* n = start; n; n = n->traverseNextNode())
+        if (n->isKeyboardFocusable(event) && n->tabIndex() > tabIndex && n->tabIndex() < winningTabIndex) {
+            winner = n;
+            winningTabIndex = n->tabIndex();
         }
-
-        assert(false); // should never get here
-        return 0;
-    }
+    
+    return winner;
 }
 
-Node *Document::previousFocusNode(Node *fromNode)
+static Node* previousNodeWithLowerTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
 {
-    Node *lastNode = this;
-    while (lastNode->lastChild())
-        lastNode = lastNode->lastChild();
-
-    if (!fromNode) {
-        // No starting node supplied; begin with the very last node in the document
-        Node *n;
-
-        int highestTabIndex = 0;
-        for (n = lastNode; n != 0; n = n->traversePreviousNode()) {
-            if (n->isKeyboardFocusable()) {
-                if (n->tabIndex() == 0)
-                    return n;
-                else if (n->tabIndex() > highestTabIndex)
-                    highestTabIndex = n->tabIndex();
-            }
+    // Search is inclusive of start
+    int winningTabIndex = 0;
+    Node* winner = 0;
+    for (Node* n = start; n; n = n->traversePreviousNode())
+        if (n->isKeyboardFocusable(event) && n->tabIndex() < tabIndex && n->tabIndex() > winningTabIndex) {
+            winner = n;
+            winningTabIndex = n->tabIndex();
         }
+    
+    return winner;
+}
 
-        // No node with a tab index of 0; just go to the last node with the highest tab index
-        for (n = lastNode; n != 0; n = n->traversePreviousNode()) {
-            if (n->isKeyboardFocusable() && (n->tabIndex() == highestTabIndex))
-                return n;
-        }
+Node* Document::nextFocusableNode(Node* start, KeyboardEvent* event)
+{
+    if (start) {
+        // First try to find a node with the same tabindex as start that comes after start in the document.
+        if (Node* winner = nextNodeWithExactTabIndex(start->traverseNextNode(), start->tabIndex(), event))
+            return winner;
 
-        return 0;
+        if (start->tabIndex() == 0)
+            // We've reached the last node in the document with a tabindex of 0. This is the end of the tabbing order.
+            return 0;
     }
-    else {
-        unsigned short fromTabIndex = fromNode->tabIndex();
-
-        if (fromTabIndex == 0) {
-            // Find the previous selectable node before fromNode (in document order) that doesn't have a tab index
-            Node *n = fromNode->traversePreviousNode();
-            while (n && !(n->isKeyboardFocusable() && n->tabIndex() == 0))
-                n = n->traversePreviousNode();
-            if (n)
-                return n;
-
-            // No previous nodes with a 0 tab index, go to the last node in the document that has the highest tab index
-            int highestTabIndex = 0;
-            for (n = this; n != 0; n = n->traverseNextNode()) {
-                if (n->isKeyboardFocusable() && (n->tabIndex() > highestTabIndex))
-                    highestTabIndex = n->tabIndex();
-            }
 
-            if (highestTabIndex == 0)
-                return 0;
-
-            for (n = lastNode; n != 0; n = n->traversePreviousNode()) {
-                if (n->isKeyboardFocusable() && (n->tabIndex() == highestTabIndex))
-                    return n;
-            }
+    // Look for the first node in the document that:
+    // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and
+    // 2) comes first in the document, if there's a tie.
+    if (Node* winner = nextNodeWithGreaterTabIndex(this, start ? start->tabIndex() : 0, event))
+        return winner;
 
-            assert(false); // should never get here
-            return 0;
-        }
-        else {
-            // Find the lowest tab index out of all the nodes except fromNode, that is less than or equal to fromNode's
-            // tab index. For nodes with the same tab index as fromNode, we are only interested in those before
-            // fromNode.
-            // If we don't find a suitable tab index, then there will be no previous focus node.
-            unsigned short highestSuitableTabIndex = 0;
-            Node *n;
-
-            bool reachedFromNode = false;
-            for (n = this; n != 0; n = n->traverseNextNode()) {
-                if (n->isKeyboardFocusable() &&
-                    ((!reachedFromNode && (n->tabIndex() <= fromTabIndex)) ||
-                     (reachedFromNode && (n->tabIndex() < fromTabIndex)))  &&
-                    (n->tabIndex() > highestSuitableTabIndex) &&
-                    (n != fromNode)) {
-
-                    // We found a selectable node with a tab index no higher than fromNode's. Keep searching though, as
-                    // there may be another node which has a higher tab index but is still suitable for use.
-                    highestSuitableTabIndex = n->tabIndex();
-                }
+    // There are no nodes with a tabindex greater than start's tabindex,
+    // so find the first node with a tabindex of 0.
+    return nextNodeWithExactTabIndex(this, 0, event);
+}
 
-                if (n == fromNode)
-                    reachedFromNode = true;
-            }
+Node* Document::previousFocusableNode(Node* start, KeyboardEvent* event)
+{
+    Node* last;
+    for (last = this; last->lastChild(); last = last->lastChild())
+        ; // Empty loop.
 
-            if (highestSuitableTabIndex == 0) {
-                // No previous node with a tab index. Since the order specified by HTML is nodes with tab index > 0
-                // first, this means that there is no previous node.
-                return 0;
-            }
+    // First try to find the last node in the document that comes before start and has the same tabindex as start.
+    // If start is null, find the last node in the document with a tabindex of 0.
+    Node* startingNode;
+    int startingTabIndex;
+    if (start) {
+        startingNode = start->traversePreviousNode();
+        startingTabIndex = start->tabIndex();
+    } else {
+        startingNode = last;
+        startingTabIndex = 0;
+    }
 
-            // Search backwards from fromNode
-            for (n = fromNode->traversePreviousNode(); n != 0; n = n->traversePreviousNode()) {
-                if (n->isKeyboardFocusable() && (n->tabIndex() == highestSuitableTabIndex))
-                    return n;
-            }
-            // The previous node isn't before fromNode, start from the end of the document
-            for (n = lastNode; n != fromNode; n = n->traversePreviousNode()) {
-                if (n->isKeyboardFocusable() && (n->tabIndex() == highestSuitableTabIndex))
-                    return n;
-            }
+    if (Node* winner = previousNodeWithExactTabIndex(startingNode, startingTabIndex, event))
+        return winner;
 
-            assert(false); // should never get here
-            return 0;
-        }
-    }
+    // There are no nodes before start with the same tabindex as start, so look for a node that:
+    // 1) has the highest non-zero tabindex (that is less than start's tabindex), and
+    // 2) comes last in the document, if there's a tie.
+    startingTabIndex = (start && start->tabIndex()) ? start->tabIndex() : SHRT_MAX;
+    return previousNodeWithLowerTabIndex(last, startingTabIndex, event);
 }
 
 int Document::nodeAbsIndex(Node *node)
@@ -1630,68 +1731,41 @@ void Document::processHttpEquiv(const String &equiv, const String &content)
         m_preferredStylesheetSet = content;
         updateStyleSelector();
     } else if (equalIgnoringCase(equiv, "refresh")) {
-        // get delay and url
-        DeprecatedString str = content.deprecatedString().stripWhiteSpace();
-        int pos = str.find(RegularExpression("[;,]"));
-        if (pos == -1)
-            pos = str.find(RegularExpression("[ \t]"));
-
-        if (pos == -1) // There can be no url (David)
-        {
-            bool ok = false;
-            int delay = 0;
-            delay = str.toInt(&ok);
-            // We want a new history item if the refresh timeout > 1 second
-            if (ok && frame)
-                frame->scheduleRedirection(delay, frame->url().url(), delay <= 1);
-        } else {
-            double delay = 0;
-            bool ok = false;
-            delay = str.left(pos).stripWhiteSpace().toDouble(&ok);
-
-            pos++;
-            while(pos < (int)str.length() && str[pos].isSpace()) pos++;
-            str = str.mid(pos);
-            if (str.find("url", 0,  false) == 0)
-                str = str.mid(3);
-            str = str.stripWhiteSpace();
-            if (str.length() && str[0] == '=')
-                str = str.mid(1).stripWhiteSpace();
-            str = parseURL(String(str)).deprecatedString();
-            if (ok && frame)
+        double delay;
+        String url;
+        if (frame && parseHTTPRefresh(content, true, delay, url)) {
+            if (url.isEmpty())
+                frame->loader()->scheduleRedirection(delay, frame->loader()->url().url(), delay <= 1);
+            else
                 // We want a new history item if the refresh timeout > 1 second
-                frame->scheduleRedirection(delay, completeURL(str), delay <= 1);
+                frame->loader()->scheduleRedirection(delay, completeURL(url), delay <= 1);
         }
     } else if (equalIgnoringCase(equiv, "expires")) {
-        DeprecatedString str = content.deprecatedString().stripWhiteSpace();
+        String str = content.stripWhiteSpace();
         time_t expire_date = str.toInt();
-        if (m_docLoader)
-            m_docLoader->setExpireDate(expire_date);
-    } else if ((equalIgnoringCase(equiv, "pragma") || equalIgnoringCase(equiv, "cache-control")) && frame) {
-        DeprecatedString str = content.deprecatedString().lower().stripWhiteSpace();
-        KURL url = frame->url();
+        m_docLoader->setExpireDate(expire_date);
     } else if (equalIgnoringCase(equiv, "set-cookie")) {
-        // ### FIXME: make setCookie work on XML documents too; e.g. in case of <html:meta .....>
+        // FIXME: make setCookie work on XML documents too; e.g. in case of <html:meta .....>
         if (isHTMLDocument())
-            static_cast<HTMLDocument *>(this)->setCookie(content);
+            static_cast<HTMLDocument*>(this)->setCookie(content);
     }
 }
 
-MouseEventWithHitTestResults Document::prepareMouseEvent(bool readonly, bool active, bool mouseMove,
-                                                         const IntPoint& point, const PlatformMouseEvent& event)
+MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& request, const IntPoint& documentPoint, const PlatformMouseEvent& event)
 {
+    ASSERT(!renderer() || renderer()->isRenderView());
+
     if (!renderer())
-        return MouseEventWithHitTestResults(event, 0, false);
+        return MouseEventWithHitTestResults(event, 0, IntPoint(), 0, false);
 
-    assert(renderer()->isRenderView());
-    RenderObject::NodeInfo renderInfo(readonly, active, mouseMove);
-    renderer()->layer()->hitTest(renderInfo, point);
+    HitTestResult result(documentPoint);
+    renderer()->layer()->hitTest(request, result);
 
-    if (!readonly)
+    if (!request.readonly)
         updateRendering();
 
-    bool isOverLink = renderInfo.URLElement() && !renderInfo.URLElement()->getAttribute(hrefAttr).isNull();
-    return MouseEventWithHitTestResults(event, renderInfo.innerNode(), isOverLink);
+    bool isOverLink = result.URLElement() && result.URLElement()->isLink();
+    return MouseEventWithHitTestResults(event, result.innerNode(), result.localPoint(), result.scrollbar(), isOverLink);
 }
 
 // DOM Section 1.1.1
@@ -1723,6 +1797,87 @@ bool Document::childTypeAllowed(NodeType type)
     return false;
 }
 
+bool Document::canReplaceChild(Node* newChild, Node* oldChild)
+{
+    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 = 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"
@@ -1766,7 +1921,7 @@ void Document::stylesheetLoaded()
         printf("Stylesheet loaded at time %d. %d stylesheets still remain.\n", elapsedTime(), m_pendingStylesheets);
 #endif
 
-    updateStyleSelector();    
+    updateStyleSelector();
 }
 
 void Document::updateStyleSelector()
@@ -1775,8 +1930,8 @@ void Document::updateStyleSelector()
     if (!haveStylesheetsLoaded())
         return;
 
-    if (m_didLayoutWithPendingStylesheets) {
-        m_didLayoutWithPendingStylesheets = false;
+    if (didLayoutWithPendingStylesheets() && m_pendingStylesheets <= 0) {
+        m_pendingSheetLayout = IgnoreLayoutWithPendingSheets;
         if (renderer())
             renderer()->repaint();
     }
@@ -1801,12 +1956,6 @@ void Document::updateStyleSelector()
     }
 }
 
-
-DeprecatedStringList Document::availableStyleSheets() const
-{
-    return m_availableSheets;
-}
-
 void Document::recalcStyleSelector()
 {
     if (!renderer() || !attached())
@@ -1814,7 +1963,6 @@ void Document::recalcStyleSelector()
 
     DeprecatedPtrList<StyleSheet> oldStyleSheets = m_styleSheets->styleSheets;
     m_styleSheets->styleSheets.clear();
-    m_availableSheets.clear();
     Node *n;
     for (n = this; n; n = n->traverseNextNode()) {
         StyleSheet *sheet = 0;
@@ -1824,7 +1972,7 @@ void Document::recalcStyleSelector()
             // Processing instruction (XML documents only)
             ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(n);
             sheet = pi->sheet();
-#ifdef KHTML_XSLT
+#if ENABLE(XSLT)
             // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806>
             if (pi->isXSL() && !transformSourceDocument()) {
                 // Don't apply XSL transforms until loading is finished.
@@ -1850,14 +1998,17 @@ void Document::recalcStyleSelector()
 
                     CSSStyleSheet *cssSheet = new CSSStyleSheet(this);
                     cssSheet->parseString(sheetText);
-                    pi->setStyleSheet(cssSheet);
+                    pi->setCSSStyleSheet(cssSheet);
                     sheet = cssSheet;
                 }
             }
 
-        }
-        else if (n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag))) {
-            HTMLElement *e = static_cast<HTMLElement *>(n);
+        } else if (n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag))
+#if ENABLE(SVG)
+            ||  (n->isSVGElement() && n->hasTagName(SVGNames::styleTag))
+#endif
+        ) {
+            Element* e = static_cast<Element*>(n);
             DeprecatedString title = e->getAttribute(titleAttr).deprecatedString();
             bool enabledViaScript = false;
             if (e->hasLocalName(linkTag)) {
@@ -1872,6 +2023,11 @@ void Document::recalcStyleSelector()
 
             // 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
@@ -1892,39 +2048,16 @@ void Document::recalcStyleSelector()
                     if (e->hasLocalName(styleTag) || !rel.contains("alternate"))
                         m_preferredStylesheetSet = m_selectedStylesheetSet = title;
                 }
-                      
-                if (!m_availableSheets.contains(title))
-                    m_availableSheets.append(title);
                 
                 if (title != m_preferredStylesheetSet)
                     sheet = 0;
-            }
-        }
-#ifdef SVG_SUPPORT
-        else if (n->isSVGElement() && n->hasTagName(SVGNames::styleTag)) {
-            DeprecatedString title;
-            // <STYLE> element
-            SVGStyleElement *s = static_cast<SVGStyleElement*>(n);
-            if (!s->isLoading()) {
-                sheet = s->sheet();
-                if(sheet)
-                    title = s->getAttribute(SVGNames::titleAttr).deprecatedString();
-            }
-
-            if (!title.isEmpty() && m_preferredStylesheetSet.isEmpty())
-                m_preferredStylesheetSet = m_selectedStylesheetSet = title;
 
-            if (!title.isEmpty()) {
-                if (title != m_preferredStylesheetSet)
-                    sheet = 0; // don't use it
-
-                title = title.replace('&', "&&");
-
-                if (!m_availableSheets.contains(title))
-                    m_availableSheets.append(title);
-            }
-       }
+#if ENABLE(SVG)
+                if (!n->isHTMLElement())
+                    title = title.replace('&', "&&");
 #endif
+            }
+        }
 
         if (sheet) {
             sheet->ref();
@@ -1949,7 +2082,6 @@ void Document::recalcStyleSelector()
         usersheet += m_printSheet;
     m_styleSelector = new CSSStyleSelector(this, usersheet, m_styleSheets.get(), !inCompatMode());
     m_styleSelector->setEncodedURL(m_url);
-    m_styleSelectorDirty = false;
 }
 
 void Document::setHoverNode(PassRefPtr<Node> newHoverNode)
@@ -1962,6 +2094,11 @@ void Document::setActiveNode(PassRefPtr<Node> newActiveNode)
     m_activeNode = newActiveNode;
 }
 
+void Document::focusedNodeRemoved(Node* node)
+{
+    setFocusedNode(0);
+}
+
 void Document::hoveredNodeDetached(Node* node)
 {
     if (!m_hoverNode || (node != m_hoverNode && (!m_hoverNode->isTextNode() || node != m_hoverNode->parent())))
@@ -1970,8 +2107,8 @@ void Document::hoveredNodeDetached(Node* node)
     m_hoverNode = node->parent();
     while (m_hoverNode && !m_hoverNode->renderer())
         m_hoverNode = m_hoverNode->parent();
-    if (view())
-        view()->scheduleHoverStateUpdate();
+    if (frame())
+        frame()->eventHandler()->scheduleHoverStateUpdate();
 }
 
 void Document::activeChainNodeDetached(Node* node)
@@ -1984,163 +2121,112 @@ void Document::activeChainNodeDetached(Node* node)
         m_activeNode = m_activeNode->parent();
 }
 
-bool Document::relinquishesEditingFocus(Node *node)
-{
-    assert(node);
-    assert(node->isContentEditable());
-
-    Node *root = node->rootEditableElement();
-    if (!frame() || !root)
-        return false;
-
-    return frame()->shouldEndEditing(rangeOfContents(root).get());
-}
-
-bool Document::acceptsEditingFocus(Node *node)
-{
-    assert(node);
-    assert(node->isContentEditable());
-
-    Node *root = node->rootEditableElement();
-    if (!frame() || !root)
-        return false;
-
-    return frame()->shouldBeginEditing(rangeOfContents(root).get());
-}
-
-void Document::didBeginEditing()
-{
-    if (!frame())
-        return;
-    
-    frame()->didBeginEditing();
-}
+#if PLATFORM(MAC)
 
-void Document::didEndEditing()
-{
-    if (!frame())
-        return;
-    
-    frame()->didEndEditing();
-}
-
-#if __APPLE__
-const DeprecatedValueList<DashboardRegionValue> & Document::dashboardRegions() const
+const Vector<DashboardRegionValue>& Document::dashboardRegions() const
 {
     return m_dashboardRegions;
 }
 
-void Document::setDashboardRegions (const DeprecatedValueList<DashboardRegionValue>& regions)
+void Document::setDashboardRegions(const Vector<DashboardRegionValue>& regions)
 {
     m_dashboardRegions = regions;
-    setDashboardRegionsDirty (false);
+    setDashboardRegionsDirty(false);
 }
-#endif
 
-static Widget *widgetForNode(Node *focusNode)
-{
-    if (!focusNode)
-        return 0;
-    RenderObject *renderer = focusNode->renderer();
-    if (!renderer || !renderer->isWidget())
-        return 0;
-    return static_cast<RenderWidget*>(renderer)->widget();
-}
+#endif
 
-bool Document::setFocusNode(PassRefPtr<Node> newFocusNode)
+bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode)
 {    
-    // Make sure newFocusNode is actually in this document
-    if (newFocusNode && (newFocusNode->document() != this))
+    // Make sure newFocusedNode is actually in this document
+    if (newFocusedNode && (newFocusedNode->document() != this))
         return true;
 
-    if (m_focusNode == newFocusNode)
+    if (m_focusedNode == newFocusedNode)
         return true;
 
-    if (m_focusNode && m_focusNode.get() == m_focusNode->rootEditableElement() && !relinquishesEditingFocus(m_focusNode.get()))
-        return false;
+    if (m_focusedNode && m_focusedNode.get() == m_focusedNode->rootEditableElement() && !relinquishesEditingFocus(m_focusedNode.get()))
+          return false;
         
     bool focusChangeBlocked = false;
-    RefPtr<Node> oldFocusNode = m_focusNode;
-    m_focusNode = 0;
-    clearSelectionIfNeeded(newFocusNode.get());
+    RefPtr<Node> oldFocusedNode = m_focusedNode;
+    m_focusedNode = 0;
+    clearSelectionIfNeeded(frame(), newFocusedNode.get());
 
     // Remove focus from the existing focus node (if any)
-    if (oldFocusNode && !oldFocusNode->m_inDetach) { 
-        if (oldFocusNode->active())
-            oldFocusNode->setActive(false);
+    if (oldFocusedNode && !oldFocusedNode->m_inDetach) { 
+        if (oldFocusedNode->active())
+            oldFocusedNode->setActive(false);
 
-        oldFocusNode->setFocus(false);
+        oldFocusedNode->setFocus(false);
                 
         // Dispatch a change event for text fields or textareas that have been edited
-        RenderObject *r = static_cast<RenderObject*>(oldFocusNode.get()->renderer());
+        RenderObject *r = static_cast<RenderObject*>(oldFocusedNode.get()->renderer());
         if (r && (r->isTextArea() || r->isTextField()) && r->isEdited()) {
-            EventTargetNodeCast(oldFocusNode.get())->dispatchHTMLEvent(changeEvent, true, false);
-            if ((r = static_cast<RenderObject*>(oldFocusNode.get()->renderer())))
+            EventTargetNodeCast(oldFocusedNode.get())->dispatchHTMLEvent(changeEvent, true, false);
+            if ((r = static_cast<RenderObject*>(oldFocusedNode.get()->renderer())))
                 r->setEdited(false);
         }
 
         // Dispatch the blur event and let the node do any other blur related activities (important for text fields)
-        EventTargetNodeCast(oldFocusNode.get())->dispatchBlurEvent();
+        EventTargetNodeCast(oldFocusedNode.get())->dispatchBlurEvent();
 
-        if (m_focusNode) {
+        if (m_focusedNode) {
             // handler shifted focus
             focusChangeBlocked = true;
-            newFocusNode = 0;
+            newFocusedNode = 0;
         }
-        clearSelectionIfNeeded(newFocusNode.get());
-        EventTargetNodeCast(oldFocusNode.get())->dispatchUIEvent(DOMFocusOutEvent);
-        if (m_focusNode) {
+        clearSelectionIfNeeded(frame(), newFocusedNode.get());
+        EventTargetNodeCast(oldFocusedNode.get())->dispatchUIEvent(DOMFocusOutEvent);
+        if (m_focusedNode) {
             // handler shifted focus
             focusChangeBlocked = true;
-            newFocusNode = 0;
+            newFocusedNode = 0;
         }
-        clearSelectionIfNeeded(newFocusNode.get());
-        if ((oldFocusNode.get() == this) && oldFocusNode->hasOneRef())
+        clearSelectionIfNeeded(frame(), newFocusedNode.get());
+        if ((oldFocusedNode.get() == this) && oldFocusedNode->hasOneRef())
             return true;
             
-        if (oldFocusNode.get() == oldFocusNode->rootEditableElement())
-            didEndEditing();
+        if (oldFocusedNode.get() == oldFocusedNode->rootEditableElement())
+            frame()->editor()->didEndEditing();
     }
 
-    if (newFocusNode) {
-        if (newFocusNode == newFocusNode->rootEditableElement() && !acceptsEditingFocus(newFocusNode.get())) {
+    if (newFocusedNode) {
+        if (newFocusedNode == newFocusedNode->rootEditableElement() && !acceptsEditingFocus(newFocusedNode.get())) {
             // delegate blocks focus change
             focusChangeBlocked = true;
-            goto SetFocusNodeDone;
+            goto SetFocusedNodeDone;
         }
         // Set focus on the new node
-        m_focusNode = newFocusNode.get();
+        m_focusedNode = newFocusedNode.get();
 
         // Dispatch the focus event and let the node do any other focus related activities (important for text fields)
-        EventTargetNodeCast(m_focusNode.get())->dispatchFocusEvent();
+        EventTargetNodeCast(m_focusedNode.get())->dispatchFocusEvent();
 
-        if (m_focusNode != newFocusNode) {
+        if (m_focusedNode != newFocusedNode) {
             // handler shifted focus
             focusChangeBlocked = true;
-            goto SetFocusNodeDone;
+            goto SetFocusedNodeDone;
         }
-        EventTargetNodeCast(m_focusNode.get())->dispatchUIEvent(DOMFocusInEvent);
-        if (m_focusNode != newFocusNode) { 
+        EventTargetNodeCast(m_focusedNode.get())->dispatchUIEvent(DOMFocusInEvent);
+        if (m_focusedNode != newFocusedNode) { 
             // handler shifted focus
             focusChangeBlocked = true;
-            goto SetFocusNodeDone;
+            goto SetFocusedNodeDone;
         }
-        m_focusNode->setFocus();
-        
-        if (m_focusNode.get() == m_focusNode->rootEditableElement())
-            didBeginEditing();
-        
+        m_focusedNode->setFocus();
+
         // eww, I suck. set the qt focus correctly
         // ### find a better place in the code for this
         if (view()) {
-            Widget *focusWidget = widgetForNode(m_focusNode.get());
+            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_focusNode.get());
+                focusWidget = widgetForNode(m_focusedNode.get());
             }
             if (focusWidget)
                 focusWidget->setFocus();
@@ -2149,29 +2235,16 @@ bool Document::setFocusNode(PassRefPtr<Node> newFocusNode)
         }
    }
 
-#if __APPLE__
-    if (!focusChangeBlocked && m_focusNode && AXObjectCache::accessibilityEnabled())
+#if PLATFORM(MAC)
+    if (!focusChangeBlocked && m_focusedNode && AXObjectCache::accessibilityEnabled())
         axObjectCache()->handleFocusedUIElementChanged();
 #endif
 
-SetFocusNodeDone:
+SetFocusedNodeDone:
     updateRendering();
     return !focusChangeBlocked;
-}
-
-void Document::clearSelectionIfNeeded(Node *newFocusNode)
-{
-    if (!frame())
-        return;
-
-    // Clear the selection when changing the focus node to null or to a node that is not 
-    // contained by the current selection.
-    Node *startContainer = frame()->selection().start().node();
-    if (!newFocusNode || (startContainer && startContainer != newFocusNode && !(startContainer->isAncestor(newFocusNode)) && startContainer->shadowAncestorNode() != newFocusNode))
-        // FIXME: 6498 Should just be able to call m_frame->selection().clear()
-        frame()->setSelection(SelectionController());
-}
-
+  }
+  
 void Document::setCSSTarget(Node* n)
 {
     if (m_cssTarget)
@@ -2188,7 +2261,7 @@ Node* Document::getCSSTarget() const
 
 void Document::attachNodeIterator(NodeIterator *ni)
 {
-    m_nodeIterators.append(ni);
+    m_nodeIterators.add(ni);
 }
 
 void Document::detachNodeIterator(NodeIterator *ni)
@@ -2199,12 +2272,13 @@ void Document::detachNodeIterator(NodeIterator *ni)
 void Document::notifyBeforeNodeRemoval(Node *n)
 {
     if (Frame* f = frame()) {
-        f->selection().nodeWillBeRemoved(n);
-        f->dragCaret().nodeWillBeRemoved(n);
+        f->selectionController()->nodeWillBeRemoved(n);
+        f->dragCaretController()->nodeWillBeRemoved(n);
     }
-    DeprecatedPtrListIterator<NodeIterator> it(m_nodeIterators);
-    for (; it.current(); ++it)
-        it.current()->notifyBeforeNodeRemoval(n);
+
+    HashSet<NodeIterator*>::const_iterator end = m_nodeIterators.end();
+    for (HashSet<NodeIterator*>::const_iterator it = m_nodeIterators.begin(); it != end; ++it)
+        (*it)->notifyBeforeNodeRemoval(n);
 }
 
 DOMWindow* Document::defaultView() const
@@ -2218,20 +2292,22 @@ DOMWindow* Document::defaultView() const
 PassRefPtr<Event> Document::createEvent(const String &eventType, ExceptionCode& ec)
 {
     if (eventType == "UIEvents" || eventType == "UIEvent")
-        return new UIEvent();
+        return new UIEvent;
     if (eventType == "MouseEvents" || eventType == "MouseEvent")
-        return new MouseEvent();
+        return new MouseEvent;
     if (eventType == "MutationEvents" || eventType == "MutationEvent")
-        return new MutationEvent();
+        return new MutationEvent;
     if (eventType == "KeyboardEvents" || eventType == "KeyboardEvent")
-        return new KeyboardEvent();
+        return new KeyboardEvent;
     if (eventType == "HTMLEvents" || eventType == "Event" || eventType == "Events")
-        return new Event();
-#ifdef SVG_SUPPORT
+        return new Event;
+    if (eventType == "TextEvent")
+        return new TextEvent;
+#if ENABLE(SVG)
     if (eventType == "SVGEvents")
-        return new Event();
+        return new Event;
     if (eventType == "SVGZoomEvents")
-        return new SVGZoomEvent();
+        return new SVGZoomEvent;
 #endif
     ec = NOT_SUPPORTED_ERR;
     return 0;
@@ -2269,9 +2345,12 @@ void Document::defaultEventHandler(Event *evt)
             if (elem) {
                 elem->accessKeyAction(false);
                 evt->setDefaultHandled();
+                return;
             }
         }
     }
+
+    ContainerNode::defaultEventHandler(evt);
 }
 
 void Document::setHTMLWindowEventListener(const AtomicString &eventType, PassRefPtr<EventListener> listener)
@@ -2333,7 +2412,7 @@ bool Document::hasWindowEventListener(const AtomicString &eventType)
 PassRefPtr<EventListener> Document::createHTMLEventListener(const String& functionName, const String& code, Node *node)
 {
     if (Frame* frm = frame())
-        if (KJSProxy* proxy = frm->jScript())
+        if (KJSProxy* proxy = frm->scriptProxy())
             return proxy->createHTMLEventHandler(functionName, code, node);
     return 0;
 }
@@ -2391,7 +2470,7 @@ void Document::imageLoadEventTimerFired(Timer<Document>*)
     dispatchImageLoadEventsNow();
 }
 
-Element *Document::ownerElement() const
+ElementDocument::ownerElement() const
 {
     if (!frame())
         return 0;
@@ -2401,8 +2480,7 @@ Element *Document::ownerElement() const
 String Document::referrer() const
 {
     if (frame())
-        return frame()->incomingReferrer();
-    
+        return frame()->loader()->referrer();
     return String();
 }
 
@@ -2528,11 +2606,12 @@ HTMLMapElement *Document::getImageMap(const String& URL) const
     if (URL.isNull())
         return 0;
     int hashPos = URL.find('#');
-    AtomicString name = (hashPos < 0 ? URL : URL.substring(hashPos + 1)).impl();
-    return m_imageMapsByName.get(name.impl());
+    String name = (hashPos < 0 ? URL : URL.substring(hashPos + 1)).impl();
+    AtomicString mapName = hMode == XHtml ? name : name.lower();
+    return m_imageMapsByName.get(mapName.impl());
 }
 
-void Document::setDecoder(Decoder *decoder)
+void Document::setDecoder(TextResourceDecoder *decoder)
 {
     m_decoder = decoder;
 }
@@ -2544,14 +2623,15 @@ UChar Document::backslashAsCurrencySymbol() const
     return m_decoder->encoding().backslashAsCurrencySymbol();
 }
 
-DeprecatedString Document::completeURL(const DeprecatedString &URL)
+DeprecatedString Document::completeURL(const DeprecatedStringURL)
 {
+    // FIXME: This treats null URLs the same as empty URLs, unlike the String function below.
+
     // If both the URL and base URL are empty, like they are for documents
     // created using DOMImplementation::createDocument, just return the passed in URL.
     // (We do this because URL() returns "about:blank" for empty URLs.
     if (m_url.isEmpty() && m_baseURL.isEmpty())
         return URL;
-    
     if (!m_decoder)
         return KURL(baseURL(), URL).url();
     return KURL(baseURL(), URL, m_decoder->encoding()).url();
@@ -2559,6 +2639,7 @@ DeprecatedString Document::completeURL(const DeprecatedString &URL)
 
 String Document::completeURL(const String &URL)
 {
+    // FIXME: This always returns null when passed a null URL, unlike the String function above.
     if (URL.isNull())
         return URL;
     return completeURL(URL.deprecatedString());
@@ -2579,7 +2660,7 @@ void Document::setInPageCache(bool flag)
         ASSERT(m_savedRenderer == 0);
         m_savedRenderer = renderer();
         if (m_view)
-            m_view->resetScrollBars();
+            m_view->resetScrollbars();
     } else {
         ASSERT(renderer() == 0 || renderer() == m_savedRenderer);
         ASSERT(m_renderArena);
@@ -2685,13 +2766,13 @@ static IntRect placeholderRectForMarker(void)
     return IntRect(-1,-1,-1,-1);
 }
 
-void Document::addMarker(Range *range, DocumentMarker::MarkerType type)
+void Document::addMarker(Range *range, DocumentMarker::MarkerType type, 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();
         int exception = 0;
-        DocumentMarker marker = {type, textPiece->startOffset(exception), textPiece->endOffset(exception)};
+        DocumentMarker marker = {type, textPiece->startOffset(exception), textPiece->endOffset(exception), description};
         addMarker(textPiece->startContainer(exception), marker);
     }
 }
@@ -2728,17 +2809,17 @@ void Document::addMarker(Node *node, DocumentMarker newMarker)
         Vector<DocumentMarker>& markers = vectorPair->first;
         Vector<IntRect>& rects = vectorPair->second;
         ASSERT(markers.size() == rects.size());
-        Vector<DocumentMarker>::iterator it;
-        for (it = markers.begin(); it != markers.end();) {
-            DocumentMarker marker = *it;
+        size_t i;
+        for (i = 0; i != markers.size();) {
+            DocumentMarker marker = markers[i];
             
             if (newMarker.endOffset < marker.startOffset+1) {
                 // This is the first marker that is completely after newMarker, and disjoint from it.
-                // We found our insertion point.\10
+                // We found our insertion point.
                 break;
             } else if (newMarker.startOffset > marker.endOffset) {
                 // maker is before newMarker, and disjoint from it.  Keep scanning.
-                it++;
+                i++;
             } else if (newMarker == marker) {
                 // already have this one, NOP
                 return;
@@ -2747,16 +2828,14 @@ void Document::addMarker(Node *node, DocumentMarker newMarker)
                 newMarker.startOffset = min(newMarker.startOffset, marker.startOffset);
                 newMarker.endOffset = max(newMarker.endOffset, marker.endOffset);
                 // remove old one, we'll add newMarker later
-                unsigned removalIndex = it - markers.begin();
-                markers.remove(removalIndex);
-                rects.remove(removalIndex);
+                markers.remove(i);
+                rects.remove(i);
                 // it points to the next marker to consider
             }
         }
-        // at this point it points to the node before which we want to insert
-        unsigned insertionIndex = it - markers.begin();
-        markers.insert(insertionIndex, newMarker);
-        rects.insert(insertionIndex, placeholderRectForMarker());
+        // at this point i points to the node before which we want to insert
+        markers.insert(i, newMarker);
+        rects.insert(i, placeholderRectForMarker());
     }
     
     // repaint the affected node
@@ -2779,10 +2858,9 @@ void Document::copyMarkers(Node *srcNode, unsigned startOffset, int length, Node
 
     bool docDirty = false;
     unsigned endOffset = startOffset + length - 1;
-    Vector<DocumentMarker>::iterator it;
     Vector<DocumentMarker>& markers = vectorPair->first;
-    for (it = markers.begin(); it != markers.end(); ++it) {
-        DocumentMarker marker = *it;
+    for (size_t i = 0; i != markers.size(); ++i) {
+        DocumentMarker marker = markers[i];
 
         // stop if we are now past the specified range
         if (marker.startOffset > endOffset)
@@ -2823,9 +2901,8 @@ void Document::removeMarkers(Node *node, unsigned startOffset, int length, Docum
     ASSERT(markers.size() == rects.size());
     bool docDirty = false;
     unsigned endOffset = startOffset + length - 1;
-    Vector<DocumentMarker>::iterator it;
-    for (it = markers.begin(); it < markers.end();) {
-        DocumentMarker marker = *it;
+    for (size_t i = 0; i < markers.size();) {
+        DocumentMarker marker = markers[i];
 
         // markers are returned in order, so stop if we are now past the specified range
         if (marker.startOffset > endOffset)
@@ -2833,7 +2910,7 @@ void Document::removeMarkers(Node *node, unsigned startOffset, int length, Docum
         
         // skip marker that is wrong type or before target
         if (marker.endOffset < startOffset || (marker.type != markerType && markerType != DocumentMarker::AllMarkers)) {
-            it++;
+            i++;
             continue;
         }
 
@@ -2841,29 +2918,25 @@ void Document::removeMarkers(Node *node, unsigned startOffset, int length, Docum
         docDirty = true;
 
         // pitch the old marker and any associated rect
-        unsigned removalIndex = it - markers.begin();
-        markers.remove(removalIndex);
-        rects.remove(removalIndex);
-        // it now points to the next node
+        markers.remove(i);
+        rects.remove(i);
         
         // add either of the resulting slices that are left after removing target
         if (startOffset > marker.startOffset) {
             DocumentMarker newLeft = marker;
             newLeft.endOffset = startOffset;
-            unsigned insertionIndex = it - markers.begin();
-            markers.insert(insertionIndex, newLeft);
-            rects.insert(insertionIndex, placeholderRectForMarker());
-            // it now points to the newly-inserted node, but we want to skip that one
-            it++;
+            markers.insert(i, newLeft);
+            rects.insert(i, placeholderRectForMarker());
+            // i now points to the newly-inserted node, but we want to skip that one
+            i++;
         }
         if (marker.endOffset > endOffset) {
             DocumentMarker newRight = marker;
             newRight.startOffset = endOffset;
-            unsigned insertionIndex = it - markers.begin();
-            markers.insert(insertionIndex, newRight);
-            rects.insert(insertionIndex, placeholderRectForMarker());
-            // it now points to the newly-inserted node, but we want to skip that one
-            it++;
+            markers.insert(i, newRight);
+            rects.insert(i, placeholderRectForMarker());
+            // i now points to the newly-inserted node, but we want to skip that one
+            i++;
         }
     }
 
@@ -2878,6 +2951,38 @@ void Document::removeMarkers(Node *node, unsigned startOffset, int length, Docum
         node->renderer()->repaint();
 }
 
+DocumentMarker* Document::markerContainingPoint(const IntPoint& point, DocumentMarker::MarkerType markerType)
+{
+    // 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
+        MarkerMapVectorPair* vectorPair = nodeIterator->second;
+        Vector<DocumentMarker>& markers = vectorPair->first;
+        Vector<IntRect>& rects = vectorPair->second;
+        ASSERT(markers.size() == rects.size());
+        unsigned markerCount = markers.size();
+        for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
+            DocumentMarker& marker = markers[markerIndex];
+            
+            // skip marker that is wrong type
+            if (marker.type != markerType && markerType != DocumentMarker::AllMarkers)
+                continue;
+            
+            IntRect& r = rects[markerIndex];
+            
+            // skip placeholder rects
+            if (r == placeholderRectForMarker())
+                continue;
+            
+            if (r.contains(point))
+                return &marker;
+        }
+    }
+    
+    return 0;
+}
+
 Vector<DocumentMarker> Document::markersForNode(Node* node)
 {
     MarkerMapVectorPair* vectorPair = m_markers.get(node);
@@ -2944,19 +3049,18 @@ void Document::removeMarkers(DocumentMarker::MarkerType markerType)
         Vector<DocumentMarker>& markers = vectorPair->first;
         Vector<IntRect>& rects = vectorPair->second;
         ASSERT(markers.size() == rects.size());
-        Vector<DocumentMarker>::iterator markerIterator;
-        for (markerIterator = markers.begin(); markerIterator != markers.end();) {
-            DocumentMarker marker = *markerIterator;
+        for (size_t i = 0; i != markers.size();) {
+            DocumentMarker marker = markers[i];
 
             // skip nodes that are not of the specified type
             if (marker.type != markerType && markerType != DocumentMarker::AllMarkers) {
-                ++markerIterator;
+                ++i;
                 continue;
             }
 
             // pitch the old marker
-            markers.remove(markerIterator - markers.begin());
-            rects.remove(markerIterator - markers.begin());
+            markers.remove(i);
+            rects.remove(i);
             nodeNeedsRepaint = true;
             // markerIterator now points to the next node
         }
@@ -2988,10 +3092,9 @@ void Document::repaintMarkers(DocumentMarker::MarkerType markerType)
         // inner loop: process each marker in the current node
         MarkerMapVectorPair* vectorPair = i->second;
         Vector<DocumentMarker>& markers = vectorPair->first;
-        Vector<DocumentMarker>::iterator markerIterator;
         bool nodeNeedsRepaint = false;
-        for (markerIterator = markers.begin(); markerIterator != markers.end(); ++markerIterator) {
-            DocumentMarker marker = *markerIterator;
+        for (size_t i = 0; i != markers.size(); ++i) {
+            DocumentMarker marker = markers[i];
             
             // skip nodes that are not of the specified type
             if (marker.type == markerType || markerType == DocumentMarker::AllMarkers) {
@@ -3059,9 +3162,8 @@ void Document::shiftMarkers(Node *node, unsigned startOffset, int delta, Documen
     ASSERT(markers.size() == rects.size());
     
     bool docDirty = false;
-    Vector<DocumentMarker>::iterator it;
-    for (it = markers.begin(); it != markers.end(); ++it) {
-        DocumentMarker &marker = *it;
+    for (size_t i = 0; i != markers.size(); ++i) {
+        DocumentMarker &marker = markers[i];
         if (marker.startOffset >= startOffset && (markerType == DocumentMarker::AllMarkers || marker.type == markerType)) {
             assert((int)marker.startOffset + delta >= 0);
             marker.startOffset += delta;
@@ -3069,7 +3171,7 @@ void Document::shiftMarkers(Node *node, unsigned startOffset, int delta, Documen
             docDirty = true;
             
             // Marker moved, so previously-computed rendered rectangle is now invalid
-            rects[it - markers.begin()] = placeholderRectForMarker();
+            rects[i] = placeholderRectForMarker();
         }
     }
     
@@ -3078,7 +3180,7 @@ void Document::shiftMarkers(Node *node, unsigned startOffset, int delta, Documen
         node->renderer()->repaint();
 }
 
-#ifdef KHTML_XSLT
+#if ENABLE(XSLT)
 
 void Document::applyXSLTransform(ProcessingInstruction* pi)
 {
@@ -3130,7 +3232,7 @@ Document *Document::topDocument() const
 {
     Document *doc = const_cast<Document *>(this);
     Element *element;
-    while ((element = doc->ownerElement()) != 0)
+    while ((element = doc->ownerElement()))
         doc = element->document();
     
     return doc;
@@ -3160,12 +3262,10 @@ PassRefPtr<Attr> Document::createAttributeNS(const String &namespaceURI, const S
     
     // FIXME: Assume this is a mapped attribute, since createAttribute isn't namespace-aware.  There's no harm to XML
     // documents if we're wrong.
-    return new Attr(0, this, new MappedAttribute(QualifiedName(prefix.impl(), 
-                                                                       localName.impl(),
-                                                                       namespaceURI.impl()), String("").impl()));
+    return new Attr(0, this, new MappedAttribute(QualifiedName(prefix, localName, namespaceURI), StringImpl::empty()));
 }
 
-#ifdef SVG_SUPPORT
+#if ENABLE(SVG)
 const SVGDocumentExtensions* Document::svgExtensions()
 {
     return m_svgExtensions;
@@ -3302,14 +3402,14 @@ void Document::finishedParsing()
 {
     setParsing(false);
     if (Frame* f = frame())
-        f->finishedParsing();
+        f->loader()->finishedParsing();
 }
 
 Vector<String> Document::formElementsState() const
 {
     Vector<String> stateVector;
     stateVector.reserveCapacity(m_formElementsWithState.size() * 3);
-    typedef HashSet<HTMLGenericFormElement*>::const_iterator Iterator;
+    typedef ListHashSet<HTMLGenericFormElement*>::const_iterator Iterator;
     Iterator end = m_formElementsWithState.end();
     for (Iterator it = m_formElementsWithState.begin(); it != end; ++it) {
         HTMLGenericFormElement* e = *it;
@@ -3320,7 +3420,7 @@ Vector<String> Document::formElementsState() const
     return stateVector;
 }
 
-#ifdef XPATH_SUPPORT
+#if ENABLE(XPATH)
 
 PassRefPtr<XPathExpression> Document::createExpression(const String& expression,
                                                        XPathNSResolver* resolver,
@@ -3350,7 +3450,7 @@ PassRefPtr<XPathResult> Document::evaluate(const String& expression,
     return m_xpathEvaluator->evaluate(expression, contextNode, resolver, type, result, ec);
 }
 
-#endif // XPATH_SUPPORT
+#endif // ENABLE(XPATH)
 
 void Document::setStateForNewFormElements(const Vector<String>& stateVector)
 {
@@ -3475,4 +3575,19 @@ FormElementKey FormElementKeyHashTraits::deletedValue()
     return HashTraits<AtomicStringImpl*>::deletedValue();
 }
 
+
+String Document::iconURL()
+{
+    return m_iconURL;
+}
+
+void Document::setIconURL(const String& iconURL, const String& type)
+{
+    // FIXME - <rdar://problem/4727645> - At some point in the future, we might actually honor the "type" 
+    if (m_iconURL.isEmpty())
+        m_iconURL = iconURL;
+    else if (!type.isEmpty())
+        m_iconURL = iconURL;
+}
+
 }