Index: Source/core/dom/Range.cpp |
diff --git a/Source/core/dom/Range.cpp b/Source/core/dom/Range.cpp |
index 297a585406d2dd338481097fe27ea6b4a3c301b5..440598a2f15961e54ebf92e03775d34fec51bfb5 100644 |
--- a/Source/core/dom/Range.cpp |
+++ b/Source/core/dom/Range.cpp |
@@ -25,6 +25,7 @@ |
#include "config.h" |
#include "core/dom/Range.h" |
+#include "HTMLNames.h" |
#include "bindings/v8/ExceptionState.h" |
#include "core/dom/ClientRect.h" |
#include "core/dom/ClientRectList.h" |
@@ -34,15 +35,18 @@ |
#include "core/dom/NodeTraversal.h" |
#include "core/dom/NodeWithIndex.h" |
#include "core/dom/ProcessingInstruction.h" |
-#include "core/events/ScopedEventQueue.h" |
#include "core/dom/Text.h" |
#include "core/editing/TextIterator.h" |
#include "core/editing/VisiblePosition.h" |
#include "core/editing/VisibleUnits.h" |
#include "core/editing/markup.h" |
+#include "core/events/ScopedEventQueue.h" |
+#include "core/html/HTMLBodyElement.h" |
+#include "core/html/HTMLDocument.h" |
#include "core/html/HTMLElement.h" |
#include "core/rendering/RenderBoxModelObject.h" |
#include "core/rendering/RenderText.h" |
+#include "core/svg/SVGElement.h" |
#include "platform/geometry/FloatQuad.h" |
#include "wtf/RefCountedLeakCounter.h" |
#include "wtf/text/CString.h" |
@@ -1103,18 +1107,55 @@ String Range::text() const |
PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& markup, ExceptionState& exceptionState) |
{ |
- if (!m_start.container()) { |
+ // Algorithm at http://domparsing.spec.whatwg.org/#extensions-to-the-range-interface |
+ |
+ Node* startContainer = m_start.container(); |
+ if (!startContainer) { |
exceptionState.throwDOMException(InvalidStateError, "The range has no container. Perhaps 'detatch()' has been invoked on this object?"); |
return 0; |
} |
- Node* element = m_start.container()->isElementNode() ? m_start.container() : m_start.container()->parentNode(); |
- if (!element || !element->isHTMLElement()) { |
- exceptionState.throwDOMException(NotSupportedError, "The range's container must be an HTML element."); |
- return 0; |
+ // Step 1. |
+ Node* element; |
+ if (!m_start.offset() && (m_start.container()->isDocumentNode() || m_start.container()->isDocumentFragment())) { |
+ element = 0; |
+ } else if (startContainer->isElementNode()) { |
+ element = startContainer; |
+ } else { |
+ element = startContainer->parentNode(); |
+ if (!element || !element->isElementNode()) { |
+ exceptionState.throwDOMException(NotSupportedError, "The range's container must be an Element, Document, or DocumentFragment."); |
+ return 0; |
+ } |
} |
+ ASSERT(!element || element->isElementNode()); |
+ |
+ // Step 2. |
+ RefPtr<HTMLBodyElement> fakeBody = 0; |
+ if (!element || (element->isHTMLElement() && toHTMLElement(element)->hasLocalName(HTMLNames::htmlTag))) { |
+ // Try to use the existing <body> element, if it is available. |
+ if (startContainer->document().isHTMLDocument()) // FIXME: this returns false for XHTML documents, and they probably have a <body> |
+ element = toHTMLDocument(startContainer->document()).htmlBodyElement(); |
+ |
+ if (!element) { |
+ fakeBody = HTMLBodyElement::create(startContainer->document()); |
+ element = fakeBody.get(); |
+ } |
+ } else { |
+ if (!element->isHTMLElement() && !element->isSVGElement()) { |
+ exceptionState.throwDOMException(NotSupportedError, "The range's container must be an Element, Document, or DocumentFragment."); |
+ return 0; |
+ } |
+ } |
+ ASSERT(element && (element->isHTMLElement() || element->isSVGElement())); |
+ |
+ // Steps 3, 4, 5. |
+ RefPtr<DocumentFragment> fragment; |
+ if (element->isHTMLElement()) |
+ fragment = WebCore::createContextualFragment(markup, toHTMLElement(element), AllowScriptingContentAndDoNotMarkAlreadyStarted, exceptionState); |
+ else |
+ fragment = WebCore::createContextualFragment(markup, toSVGElement(element), AllowScriptingContentAndDoNotMarkAlreadyStarted, exceptionState); |
- RefPtr<DocumentFragment> fragment = WebCore::createContextualFragment(markup, toHTMLElement(element), AllowScriptingContentAndDoNotMarkAlreadyStarted, exceptionState); |
if (!fragment) |
return 0; |