+2008-02-08 Eric Seidel <eric@webkit.org>
+
+ Reviewed by darin.
+
+ Add support for Text.wholeText and Text.replaceWholeText from DOM Level 3 Core.
+ http://bugs.webkit.org/show_bug.cgi?id=17125
+
+ Test to make sure EntityReference nodes are always treated as read-only.
+
+ Added fast/dom/Text/replaceWholeText.html to catch a case the W3C missed.
+
+ All of these tests now pass.
+
+ * dom/xhtml/level3/core/textreplacewholetext01-expected.txt:
+ * dom/xhtml/level3/core/textreplacewholetext02-expected.txt:
+ * dom/xhtml/level3/core/textreplacewholetext03-expected.txt:
+ * dom/xhtml/level3/core/textreplacewholetext04-expected.txt:
+ * dom/xhtml/level3/core/textreplacewholetext05-expected.txt:
+ * dom/xhtml/level3/core/textreplacewholetext06-expected.txt:
+ * dom/xhtml/level3/core/textreplacewholetext07-expected.txt:
+ * dom/xhtml/level3/core/textwholetext01-expected.txt:
+ * dom/xhtml/level3/core/textwholetext02-expected.txt:
+ * dom/xhtml/level3/core/textwholetext03-expected.txt:
+ * fast/dom/EntityReference/readonly-exceptions-expected.txt: Added.
+ * fast/dom/EntityReference/readonly-exceptions.html: Added.
+ * fast/dom/EntityReference/resources/TEMPLATE.html: Added.
+ * fast/dom/EntityReference/resources/readonly-exceptions.js: Added.
+ * fast/dom/Text/replaceWholeText-expected.txt: Added.
+ * fast/dom/Text/replaceWholeText.html: Added.
+ * fast/dom/Text/resources/TEMPLATE.html: Added.
+ * fast/dom/Text/resources/replaceWholeText.js: Added.
+ * fast/dom/Window/window-properties-expected.txt: updated to reflect addition of replaceWholeText
+
2008-02-06 Kimmo Kinnunen <kimmok@iki.fi>
Reviewed by Tim Hatcher.
Test http://www.w3.org/2001/DOM-Test-Suite/level3/core/textreplacewholetext01
-Status error
-Message TypeError: Value undefined (result of expression textNode.replaceWholeText) is not object.
+Status Success
Test http://www.w3.org/2001/DOM-Test-Suite/level3/core/textreplacewholetext02
-Status error
-Message TypeError: Value undefined (result of expression textNode.replaceWholeText) is not object.
+Status Success
Test http://www.w3.org/2001/DOM-Test-Suite/level3/core/textreplacewholetext03
-Status error
-Message TypeError: Value undefined (result of expression textNode.replaceWholeText) is not object.
+Status Success
Test http://www.w3.org/2001/DOM-Test-Suite/level3/core/textreplacewholetext04
-Status error
-Message TypeError: Value undefined (result of expression textNode.replaceWholeText) is not object.
+Status Success
Test http://www.w3.org/2001/DOM-Test-Suite/level3/core/textreplacewholetext05
-Status error
-Message TypeError: Value undefined (result of expression textNode.replaceWholeText) is not object.
+Status Success
Test http://www.w3.org/2001/DOM-Test-Suite/level3/core/textreplacewholetext06
-Status error
-Message TypeError: Value undefined (result of expression textNode.replaceWholeText) is not object.
+Status Success
Test http://www.w3.org/2001/DOM-Test-Suite/level3/core/textreplacewholetext07
-Status error
-Message TypeError: Value undefined (result of expression textNode.replaceWholeText) is not object.
+Status Success
Test http://www.w3.org/2001/DOM-Test-Suite/level3/core/textwholetext01
-Status failure
-Message textwholetext01: assertEquals failed, actual null, expected Margaret Martin.
+Status Success
Test http://www.w3.org/2001/DOM-Test-Suite/level3/core/textwholetext02
-Status failure
-Message textwholetext02: assertEquals failed, actual null, expected Margaret MartinNew Text.
+Status Success
Test http://www.w3.org/2001/DOM-Test-Suite/level3/core/textwholetext03
-Status failure
-Message textwholetext03: assertEquals failed, actual null, expected Text I Text II.
+Status Success
--- /dev/null
+Test to make sure EntityReference nodes are always treated readonly
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS xmlDoc2.adoptNode(entityReference) threw exception Error: NO_MODIFICATION_ALLOWED_ERR: DOM Exception 7.
+PASS entityReference.ownerDocument is xmlDoc
+PASS entityReference.nodeValue = 'foo' threw exception Error: NO_MODIFICATION_ALLOWED_ERR: DOM Exception 7.
+PASS entityReference.nodeValue is null
+PASS entityReference.prefix = 'foo' threw exception Error: NAMESPACE_ERR: DOM Exception 14.
+PASS entityReference.prefix is null
+PASS entityReference.textContent = 'foo' threw exception Error: NO_MODIFICATION_ALLOWED_ERR: DOM Exception 7.
+FAIL entityReference.textContent should be >. Was .
+FAIL childrenBeforeFailedAppend should be 1. Was 0.
+PASS entityReference.appendChild(text) threw exception Error: NO_MODIFICATION_ALLOWED_ERR: DOM Exception 7.
+PASS entityReference.childNodes.length is childrenBeforeFailedAppend
+FAIL childrenBeforeFailedAppend should be 1. Was 0.
+PASS entityReference.insertBefore(text, entityReference.firstChild) threw exception Error: NO_MODIFICATION_ALLOWED_ERR: DOM Exception 7.
+PASS entityReference.childNodes.length is childrenBeforeFailedAppend
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../js/resources/js-test-style.css">
+<script src="../../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="resources/readonly-exceptions.js"></script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../js/resources/js-test-style.css">
+<script src="../../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="YOUR_JS_FILE_HERE"></script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
+</html>
--- /dev/null
+description("Test to make sure EntityReference nodes are always treated readonly")
+
+var xmlDoc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", null);
+var xmlDoc2 = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", null);
+var entityReference = xmlDoc.createEntityReference("gt");
+
+shouldThrow("xmlDoc2.adoptNode(entityReference)");
+shouldBe("entityReference.ownerDocument", "xmlDoc")
+
+// nodeValue is defined to be null for Entity Reference nodes, and thus should silently fail to modify
+// Spec is ambigious as to if we should throw here or not. I've requested clarification:
+// http://lists.w3.org/Archives/Public/www-dom/2008JanMar/0009.html
+shouldThrow("entityReference.nodeValue = 'foo'");
+shouldBe("entityReference.nodeValue", "null");
+
+shouldThrow("entityReference.prefix = 'foo'");
+shouldBe("entityReference.prefix", "null");
+
+shouldThrow("entityReference.textContent = 'foo'");
+shouldBe("entityReference.textContent", "'>'");
+
+var childrenBeforeFailedAppend = entityReference.childNodes.length;
+shouldBe("childrenBeforeFailedAppend", "1");
+var text = document.createTextNode("FAIL");
+shouldThrow("entityReference.appendChild(text)");
+shouldBe("entityReference.childNodes.length", "childrenBeforeFailedAppend");
+
+childrenBeforeFailedAppend = entityReference.childNodes.length;
+shouldBe("childrenBeforeFailedAppend", "1");
+shouldThrow("entityReference.insertBefore(text, entityReference.firstChild)");
+shouldBe("entityReference.childNodes.length", "childrenBeforeFailedAppend");
+
+var successfullyParsed = true;
--- /dev/null
+Test wholeText and replaceWholeText
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS textB.wholeText is 'AB'
+PASS para.textContent is 'ABC'
+PASS textB.wholeText is 'XYZ'
+PASS para.textContent is 'XYZC'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../js/resources/js-test-style.css">
+<script src="../../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="resources/replaceWholeText.js"></script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../js/resources/js-test-style.css">
+<script src="../../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="YOUR_JS_FILE_HERE"></script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
+</html>
--- /dev/null
+description("Test wholeText and replaceWholeText")
+
+var para = document.createElement('p');
+para.appendChild(document.createTextNode('A'));
+var textB = document.createTextNode('B');
+para.appendChild(textB);
+para.appendChild(document.createElement('p'));
+para.appendChild(document.createTextNode('C'));
+
+shouldBe("textB.wholeText", "'AB'");
+shouldBe("para.textContent", "'ABC'");
+textB.replaceWholeText("XYZ");
+shouldBe("textB.wholeText", "'XYZ'");
+shouldBe("para.textContent", "'XYZC'");
+
+var successfullyParsed = true;
window.CDATASection.prototype.removeEventListener [function]
window.CDATASection.prototype.replaceChild [function]
window.CDATASection.prototype.replaceData [function]
+window.CDATASection.prototype.replaceWholeText [function]
window.CDATASection.prototype.splitText [function]
window.CDATASection.prototype.substringData [function]
window.CSSCharsetRule [object CSSCharsetRuleConstructor]
+2008-02-08 Eric Seidel <eric@webkit.org>
+
+ Reviewed by darin.
+
+ Add support for Text.wholeText and Text.replaceWholeText
+ http://bugs.webkit.org/show_bug.cgi?id=17125
+
+ Test EntityReferences to make sure they're always treated as read-only
+ In doing so I discovered a bug in document.adoptNode(readonlyNode) (and fixed it)
+
+ * dom/Document.cpp:
+ (WebCore::Document::adoptNode): throw NO_MODIFICATION_ALLOWED_ERR when passed a readonly node
+ * dom/Node.cpp:
+ * dom/Node.cpp:
+ (WebCore::Node::textContent):
+ * dom/Text.cpp:
+ (WebCore::earliestLogicallyAdjacentTextNode):
+ (WebCore::latestLogicallyAdjacentTextNode):
+ (WebCore::Text::wholeText):
+ (WebCore::Text::replaceWholeText):
+ * dom/Text.h:
+ * dom/Text.idl:
+
2008-02-06 Kimmo Kinnunen <kimmok@iki.fi>
Reviewed by Tim Hatcher.
ec = NOT_SUPPORTED_ERR;
return 0;
}
-
+
+ if (source->isReadOnlyNode()) {
+ ec = NO_MODIFICATION_ALLOWED_ERR;
+ return 0;
+ }
+
switch (source->nodeType()) {
case ENTITY_NODE:
case NOTATION_NODE:
case DOCUMENT_TYPE_NODE:
case NOTATION_NODE:
default:
- return String();
+ return String();
}
}
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);
+
+ Vector<UChar> result;
+ Node* onePastEndText = endText->nextSibling();
+ 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();
+ result.append(data.characters(), data.length());
+ }
+
+ return String::adopt(result);
+}
+
+PassRefPtr<Text> Text::replaceWholeText(const String& newText, ExceptionCode&)
+{
+ // We don't support "read-only" text nodes (no Entity node support)
+ // Thus, we remove all adjacent text nodes, and replace the contents of this one.
+ ASSERT(!isReadOnlyNode());
+ // This method only raises exceptions when dealing with Entity nodes (which we don't support)
+
+ // 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
+ Node* parent = parentNode(); // Protect against mutation handlers moving this node during traversal
+ ExceptionCode ignored = 0;
+ 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(), ignored);
+ }
+
+ 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(), ignored);
+ }
+ }
+
+ if (newText.isEmpty()) {
+ if (parent && parentNode() == parent)
+ parent->removeChild(this, ignored);
+ return 0;
+ }
+
+ setData(newText, ignored);
+ return protectedThis.release();
+}
+
String Text::nodeName() const
{
return textAtom.domString();
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&);
+
// DOM methods overridden from parent classes
virtual String nodeName() const;
Text splitText(in [IsIndex] unsigned long offset)
raises (DOMException);
+ // Introduced in DOM Level 3:
+ readonly attribute DOMString wholeText;
+ Text replaceWholeText(in DOMString content)
+ raises(DOMException);
};
}