This commit is contained in:
Simon Montagu 2008-06-04 23:33:16 +03:00
Родитель a4b045b511 a90e7ee1f2
Коммит 251a005e96
19 изменённых файлов: 860 добавлений и 20 удалений

Просмотреть файл

@ -952,6 +952,149 @@ nsGenericDOMDataNode::SplitText(PRUint32 aOffset, nsIDOMText** aReturn)
//----------------------------------------------------------------------
// Implementation of the nsGenericDOMDataNode nsIDOM3Text tearoff
NS_IMPL_CYCLE_COLLECTION_CLASS(nsText3Tearoff)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsText3Tearoff)
NS_INTERFACE_MAP_ENTRY(nsIDOM3Text)
NS_INTERFACE_MAP_END_AGGREGATED(mNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsText3Tearoff)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsText3Tearoff)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mNode, nsIContent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsText3Tearoff)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsText3Tearoff)
NS_IMETHODIMP
nsText3Tearoff::GetIsElementContentWhitespace(PRBool *aReturn)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsText3Tearoff::GetWholeText(nsAString& aWholeText)
{
return mNode->GetWholeText(aWholeText);
}
NS_IMETHODIMP
nsText3Tearoff::ReplaceWholeText(const nsAString& aContent,
nsIDOMText **aReturn)
{
return mNode->ReplaceWholeText(PromiseFlatString(aContent), aReturn);
}
// Implementation of the nsIDOM3Text interface
/* static */ PRUint32
nsGenericDOMDataNode::FirstLogicallyAdjacentTextNode(nsIContent* aParent,
PRUint32 aIndex)
{
while (aIndex-- > 0) {
nsIContent* sibling = aParent->GetChildAt(aIndex);
if (!sibling->IsNodeOfType(nsINode::eTEXT))
return aIndex + 1;
}
return 0;
}
/* static */ PRUint32
nsGenericDOMDataNode::LastLogicallyAdjacentTextNode(nsIContent* aParent,
PRUint32 aIndex,
PRUint32 aCount)
{
while (++aIndex < aCount) {
nsIContent* sibling = aParent->GetChildAt(aIndex);
if (!sibling->IsNodeOfType(nsINode::eTEXT))
return aIndex - 1;
}
return aCount - 1;
}
nsresult
nsGenericDOMDataNode::GetWholeText(nsAString& aWholeText)
{
nsIContent* parent = GetParent();
// Handle parent-less nodes
if (!parent)
return GetData(aWholeText);
PRUint32 index = parent->IndexOf(this);
PRUint32 first =
FirstLogicallyAdjacentTextNode(parent, index);
PRUint32 last =
LastLogicallyAdjacentTextNode(parent, index, parent->GetChildCount());
aWholeText.Truncate();
nsCOMPtr<nsIDOMText> node;
nsAutoString tmp;
do {
node = do_QueryInterface(parent->GetChildAt(first));
node->GetData(tmp);
aWholeText.Append(tmp);
} while (first++ < last);
return NS_OK;
}
nsresult
nsGenericDOMDataNode::ReplaceWholeText(const nsAFlatString& aContent,
nsIDOMText **aReturn)
{
// Batch possible DOMSubtreeModified events.
mozAutoSubtreeModified subtree(GetOwnerDoc(), nsnull);
mozAutoDocUpdate updateBatch(GetCurrentDoc(), UPDATE_CONTENT_MODEL, PR_TRUE);
nsCOMPtr<nsIContent> parent = GetParent();
// Handle parent-less nodes
if (!parent) {
if (aContent.IsEmpty()) {
*aReturn = nsnull;
return NS_OK;
}
SetText(aContent.get(), aContent.Length(), PR_TRUE);
return CallQueryInterface(this, aReturn);
}
// We don't support entity references or read-only nodes, so remove the
// logically adjacent text nodes (which therefore must all be siblings of
// this) and set this one to the provided text, if that text isn't empty.
PRUint32 index = parent->IndexOf(this);
PRUint32 first =
FirstLogicallyAdjacentTextNode(parent, index);
PRUint32 last =
LastLogicallyAdjacentTextNode(parent, index, parent->GetChildCount());
do {
if (last == index && !aContent.IsEmpty())
continue;
parent->RemoveChildAt(last, PR_TRUE);
} while (last-- > first);
// Empty string means we removed this node too.
if (aContent.IsEmpty()) {
*aReturn = nsnull;
return NS_OK;
}
SetText(aContent.get(), aContent.Length(), PR_TRUE);
return CallQueryInterface(this, aReturn);
}
//----------------------------------------------------------------------
// Implementation of the nsIContent interface text functions
const nsTextFragment *

Просмотреть файл

@ -45,6 +45,7 @@
#include "nsIDOMCharacterData.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOM3Text.h"
#include "nsTextFragment.h"
#include "nsVoidArray.h"
#include "nsDOMError.h"
@ -310,6 +311,19 @@ protected:
nsresult SplitText(PRUint32 aOffset, nsIDOMText** aReturn);
friend class nsText3Tearoff;
static PRUint32 FirstLogicallyAdjacentTextNode(nsIContent* aParent,
PRUint32 aIndex);
static PRUint32 LastLogicallyAdjacentTextNode(nsIContent* aParent,
PRUint32 aIndex,
PRUint32 aCount);
nsresult GetWholeText(nsAString& aWholeText);
nsresult ReplaceWholeText(const nsAFlatString& aContent, nsIDOMText **aReturn);
nsresult SetTextInternal(PRUint32 aOffset, PRUint32 aCount,
const PRUnichar* aBuffer, PRUint32 aLength,
PRBool aNotify);
@ -333,6 +347,27 @@ private:
already_AddRefed<nsIAtom> GetCurrentValueAtom();
};
/** Tearoff class for the nsIDOM3Text portion of nsGenericDOMDataNode. */
class nsText3Tearoff : public nsIDOM3Text
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIDOM3TEXT
NS_DECL_CYCLE_COLLECTION_CLASS(nsText3Tearoff)
nsText3Tearoff(nsGenericDOMDataNode *aNode) : mNode(aNode)
{
}
protected:
virtual ~nsText3Tearoff() {}
private:
nsRefPtr<nsGenericDOMDataNode> mNode;
};
//----------------------------------------------------------------------
/**

Просмотреть файл

@ -41,6 +41,7 @@
#include "nsGenericDOMDataNode.h"
#include "nsIDOMText.h"
#include "nsIDOM3Text.h"
#include "nsContentUtils.h"
#include "nsIDOMEventListener.h"
#include "nsIDOMEventTarget.h"
@ -182,6 +183,7 @@ NS_INTERFACE_MAP_BEGIN(nsTextNode)
NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
NS_INTERFACE_MAP_ENTRY(nsIDOMText)
NS_INTERFACE_MAP_ENTRY(nsIDOMCharacterData)
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOM3Text, new nsText3Tearoff(this))
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(Text)
NS_INTERFACE_MAP_END_INHERITING(nsGenericDOMDataNode)

Просмотреть файл

@ -179,7 +179,10 @@ _TEST_FILES = test_bug5141.html \
file_bug428847-2.xhtml \
test_bug425201.html \
test_bug431833.html \
$(NULL)
test_text_replaceWholeText.html \
test_text_wholeText.html \
wholeTexty-helper.xml \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)

Просмотреть файл

@ -0,0 +1,273 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=421765
-->
<head>
<title>Text.replaceWholeText tests</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=421765">Mozilla Bug 421765</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<iframe id="xmlDocument" src="wholeTexty-helper.xml"></iframe>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 421765 **/
SimpleTest.waitForExplicitFinish();
var xmlDoc;
function entity(n) { return xmlDoc.createEntityReference(n); }
function text(t) { return document.createTextNode(t); }
function element() { return document.createElement("div"); }
function cdata(t)
{
xmlDoc = $("xmlDocument").contentDocument;
// document.createCDATASection isn't implemented; clone for the win
var node = xmlDoc.documentElement.firstChild.cloneNode(false);
is(node.nodeType, Node.CDATA_SECTION_NODE,
"er, why isn't this a CDATA section node?");
node.data = t;
return node;
}
function startTests()
{
var outer = element();
var first = text("first");
var second = element();
second.appendChild(text("element contents"));
outer.appendChild(first);
outer.appendChild(second);
is(first.wholeText, "first", "wrong initial wholeText");
is(first.replaceWholeText("start"), first,
"should have gotten first back");
is(first.data, "start", "should have modified first's data");
is(first.wholeText, "start", "should have gotten new wholeText");
var cdataNode = cdata("-cdata");
outer.insertBefore(cdataNode, second);
is(first.wholeText, "start-cdata",
"should have gotten first+cdataNode as wholeText");
var outer2 = outer.cloneNode(true); // save
is(first.replaceWholeText("first"), first,
"replaceWholeText on first returned wrong object");
is(first.nodeType, Node.TEXT_NODE, "node changed type?");
is(first.data, "first", "wrong data in first");
is(first.previousSibling, null, "wrong previousSibling for first");
is(first.nextSibling, second, "wrong nextSibling for first");
is(cdataNode.previousSibling, null, "wrong previousSibling for cdataNode");
is(cdataNode.nextSibling, null, "wrong nextSibling for cdataNode");
ok(first.replaceWholeText("") === null,
"empty string should cause a return of null");
is(first.data, "first", "wrong data after replacing with empty string");
is(outer.firstChild, second, "replaceWholeText('') removes the node");
// switcheroo, with sanity tests
outer = outer2;
is(outer.nodeType, Node.ELEMENT_NODE, "outer not element?");
first = outer.firstChild;
is(first.nodeType, Node.TEXT_NODE, "first not text?");
cdataNode = first.nextSibling;
is(cdataNode.nodeType, Node.CDATA_SECTION_NODE, "cdataNode not cdata?");
second = outer.lastChild;
is(second.nodeType, Node.ELEMENT_NODE, "second not element?");
is(cdataNode.replaceWholeText("cdata"), cdataNode,
"replaceWholeText on cdataNode returned wrong object");
is(cdataNode.nodeType, Node.CDATA_SECTION_NODE, "node changed type?");
is(cdataNode.nodeValue, "cdata", "wrong node value?");
is(cdataNode.previousSibling, null, "wrong previousSibling");
is(cdataNode.nextSibling, second, "wrong nextSibling");
ok(cdataNode.replaceWholeText("") === null,
"empty string should cause a return of null");
is(cdataNode.data, "cdata", "wrong data after replacing with empty string");
is(outer.firstChild, second, "should be no more text at start");
}
function middleTests()
{
var outer = element();
var first = element();
var middle = text("middle");
var last = element();
first.appendChild(text("first element contents"));
last.appendChild(text("last element contents"));
outer.appendChild(first);
outer.appendChild(middle);
outer.appendChild(last);
is(middle.wholeText, "middle", "wrong initial wholeText");
is(middle.replaceWholeText("center"), middle,
"should have gotten middle back");
is(middle.data, "center", "should have modified middle's data");
is(middle.wholeText, "center", "should have gotten new wholeText");
var cdataNode = cdata("-cdata");
outer.insertBefore(cdataNode, last);
is(middle.wholeText, "center-cdata",
"should have gotten middle+cdataNode as wholeText");
var outer2 = outer.cloneNode(true); // save
is(middle.replaceWholeText("middle"), middle,
"replaceWholeText on middle returned wrong object");
is(middle.nodeType, Node.TEXT_NODE, "node changed type?");
is(middle.data, "middle", "wrong data in middle");
is(middle.previousSibling, first, "wrong previousSibling");
is(middle.nextSibling, last, "wrong nextSibling");
ok(middle.replaceWholeText("") === null,
"empty string should cause a return of null");
is(middle.data, "middle", "wrong data after replacing with empty string");
// switcheroo, with sanity tests
outer = outer2;
is(outer.nodeType, Node.ELEMENT_NODE, "outer not element?");
first = outer.firstChild;
is(first.nodeType, Node.ELEMENT_NODE, "first not element?");
middle = first.nextSibling;
is(middle.nodeType, Node.TEXT_NODE, "middle not text?");
cdataNode = middle.nextSibling;
is(cdataNode.nodeType, Node.CDATA_SECTION_NODE, "cdataNode not cdata?");
last = outer.lastChild;
is(last.nodeType, Node.ELEMENT_NODE, "last not element?");
is(cdataNode.replaceWholeText("cdata"), cdataNode,
"replaceWholeText on cdataNode returned wrong object");
is(cdataNode.nodeType, Node.CDATA_SECTION_NODE, "node changed type?");
is(cdataNode.nodeValue, "cdata", "wrong node value?");
is(cdataNode.previousSibling, first, "wrong previousSibling");
is(cdataNode.nextSibling, last, "wrong nextSibling");
ok(cdataNode.replaceWholeText("") === null,
"empty string should cause a return of null");
is(cdataNode.data, "cdata", "wrong data after replacing with empty string");
is(middle.wholeText, "center", "wrong wholeText after removal");
is(first.nextSibling, last, "wrong nextSibling");
is(last.previousSibling, first, "wrong previousSibling");
}
function endTests()
{
var outer = element();
var first = element();
var second = text("second");
first.appendChild(text("element contents"));
outer.appendChild(first);
outer.appendChild(second);
is(second.wholeText, "second", "wrong initial wholeText");
is(second.replaceWholeText("end"), second,
"should have gotten second back");
is(second.data, "end", "should have modified second's data");
is(second.wholeText, "end", "should have gotten new wholeText");
var cdataNode = cdata("cdata-");
outer.insertBefore(cdataNode, second);
is(second.wholeText, "cdata-end",
"should have gotten cdataNode+second as wholeText");
is(cdataNode.wholeText, "cdata-end",
"should have gotten cdataNode+second as wholeText");
var outer2 = outer.cloneNode(true); // save
is(second.replaceWholeText("second"), second,
"replaceWholeText on second returned wrong object");
is(second.nodeType, Node.TEXT_NODE, "node changed type?");
is(second.data, "second", "wrong data in second");
is(second.previousSibling, first, "wrong previousSibling for second");
is(second.nextSibling, null, "wrong nextSibling for second");
is(cdataNode.previousSibling, null, "wrong previousSibling for cdataNode");
is(cdataNode.nextSibling, null, "wrong nextSibling for cdataNode");
ok(second.replaceWholeText("") === null,
"empty string should cause a return of null");
is(second.data, "second", "wrong data after replacing with empty string");
is(outer.lastChild, first, "replaceWholeText('') removes the node");
// switcheroo, with sanity tests
outer = outer2;
is(outer.nodeType, Node.ELEMENT_NODE, "outer not element?");
first = outer.firstChild;
is(first.nodeType, Node.ELEMENT_NODE, "first not element?");
cdataNode = first.nextSibling;
is(cdataNode.nodeType, Node.CDATA_SECTION_NODE, "cdataNode not cdata?");
second = outer.lastChild;
is(second.nodeType, Node.TEXT_NODE, "middle not text?");
is(cdataNode.replaceWholeText("cdata"), cdataNode,
"replaceWholeText on cdataNode returned wrong object");
is(cdataNode.nodeType, Node.CDATA_SECTION_NODE, "node changed type?");
is(cdataNode.nodeValue, "cdata", "wrong node value?");
is(cdataNode.previousSibling, first, "wrong previousSibling for cdataNode");
is(cdataNode.nextSibling, null, "wrong nextSibling for cdataNode");
is(second.previousSibling, null, "wrong previousSibling for second");
is(second.nextSibling, null, "wrong nextSibling for second");
ok(cdataNode.replaceWholeText("") === null,
"empty string should cause a return of null");
is(cdataNode.data, "cdata", "wrong data after replacing with empty string");
is(outer.lastChild, first, "should be no more text at end");
}
function entityTests()
{
todo_isnot(entity("bar"), null,
"need implementation update if we ever support entity nodes!");
var root = xmlDoc.documentElement;
is(root.lastChild.firstChild.nodeType, Node.TEXT_NODE,
"uh-oh, did we start supporting entity references as nodes?");
is(root.lastChild.lastChild.nodeType, Node.ELEMENT_NODE,
"uh-oh, did we start supporting entity references as nodes?");
// If any of the above ever fails, add tests here!
}
function test()
{
try
{
startTests();
middleTests();
endTests();
entityTests();
}
catch (e)
{
ok(false, "exception thrown: " + e);
}
finally
{
SimpleTest.finish();
}
}
window.addEventListener("load", test, false);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,249 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=421765
-->
<head>
<title>Text.wholeText tests</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=421765">Mozilla Bug 421765</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<iframe id="xmlDocument" src="wholeTexty-helper.xml"></iframe>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 421765 **/
SimpleTest.waitForExplicitFinish();
var xmlDoc;
function entity(n) { return xmlDoc.createEntityReference(n); }
function text(t) { return document.createTextNode(t); }
function element() { return document.createElement("div"); }
function cdata(t)
{
xmlDoc = $("xmlDocument").contentDocument;
// document.createCDATASection isn't implemented; clone for the win
var node = xmlDoc.documentElement.firstChild.cloneNode(false);
is(node.nodeType, Node.CDATA_SECTION_NODE,
"er, why isn't this a CDATA section node?");
node.data = t;
return node;
}
function firstTests()
{
var outer = element();
var first = text("first");
var second = element();
second.appendChild(text("element contents"));
outer.appendChild(first);
outer.appendChild(second);
is(first.wholeText, "first", "wrong wholeText for first");
var insertedText = text("-continued");
outer.insertBefore(insertedText, second);
is(first.wholeText, "first-continued",
"wrong wholeText for first after insertedText insertion");
is(insertedText.wholeText, "first-continued",
"wrong wholeText for insertedText after insertedText insertion");
var cdataNode = cdata("zero-")
outer.insertBefore(cdataNode, first);
is(first.wholeText, "zero-first-continued",
"wrong wholeText for first after cdataNode insertion");
is(cdataNode.wholeText, "zero-first-continued",
"wrong wholeText for cdataNode after cdataNode insertion");
is(insertedText.wholeText, "zero-first-continued",
"wrong wholeText for insertedText after cdataNode insertion");
outer.insertBefore(element(), first);
is(first.wholeText, "first-continued",
"wrong wholeText for first after element insertion");
is(cdataNode.wholeText, "zero-",
"wrong wholeText for cdataNode after element insertion");
is(insertedText.wholeText, "first-continued",
"wrong wholeText for insertedText after element insertion");
var cdataNode2 = cdata("-interrupted");
outer.insertBefore(cdataNode2, insertedText);
is(first.wholeText, "first-interrupted-continued",
"wrong wholeText for first after cdataNode2 insertion");
is(cdataNode2.wholeText, "first-interrupted-continued",
"wrong wholeText for cdataNode2 after cdataNode2 insertion");
is(insertedText.wholeText, "first-interrupted-continued",
"wrong wholeText for insertedText after cdataNode2 insertion");
}
function middleTests()
{
var outer = element();
var first = element();
var last = element();
var middle = text("middle");
first.appendChild(text("first element contents"));
last.appendChild(text("last element contents"));
outer.appendChild(first);
outer.appendChild(middle);
outer.appendChild(last);
is(middle.wholeText, "middle", "wrong wholeText for middle");
var beforeMiddle = text("before-");
outer.insertBefore(beforeMiddle, middle);
is(middle.wholeText, "before-middle",
"wrong wholeText for middle after beforeMiddle insertion");
is(beforeMiddle.wholeText, "before-middle",
"wrong wholeText for beforeMiddle after beforeMiddle insertion");
var midElement = element();
midElement.appendChild(text("middle element"));
outer.insertBefore(midElement, middle);
is(middle.wholeText, "middle",
"wrong wholeText for middle after midElement insertion");
is(beforeMiddle.wholeText, "before-",
"wrong wholeText for beforeMiddle after midElement insertion");
var cdataNode = cdata("after");
outer.insertBefore(cdataNode, midElement);
is(cdataNode.wholeText, "before-after",
"wrong wholeText for cdataNode after cdataNode insertion");
is(beforeMiddle.wholeText, "before-after",
"wrong wholeText for beforeMiddle after cdataNode insertion");
is(middle.wholeText, "middle",
"wrong wholeText for middle after cdataNode insertion");
var cdataNode2 = cdata("before-");
outer.insertBefore(cdataNode2, middle);
is(cdataNode.wholeText, "before-after",
"wrong wholeText for cdataNode after cdataNode2 insertion");
is(beforeMiddle.wholeText, "before-after",
"wrong wholeText for beforeMiddle after cdataNode2 insertion");
is(cdataNode2.wholeText, "before-middle",
"wrong wholeText for middle after cdataNode2 insertion");
is(middle.wholeText, "before-middle",
"wrong wholeText for middle after cdataNode2 insertion");
}
function lastTests()
{
var outer = element();
var first = element();
var second = text("second");
first.appendChild(text("element contents"));
outer.appendChild(first);
outer.appendChild(second);
is(second.wholeText, "second", "wrong wholeText for second");
var insertedText = text("before-");
outer.insertBefore(insertedText, second);
is(second.wholeText, "before-second",
"wrong wholeText for second after insertedText insertion");
is(insertedText.wholeText, "before-second",
"wrong wholeText for insertedText after insertedText insertion");
var cdataNode = cdata("zero-")
outer.insertBefore(cdataNode, insertedText);
is(cdataNode.wholeText, "zero-before-second",
"wrong wholeText for cdataNode after cdataNode insertion");
is(second.wholeText, "zero-before-second",
"wrong wholeText for second after cdataNode insertion");
is(insertedText.wholeText, "zero-before-second",
"wrong wholeText for insertedText after cdataNode insertion");
outer.insertBefore(element(), second);
is(second.wholeText, "second",
"wrong wholeText for second after element insertion");
is(cdataNode.wholeText, "zero-before-",
"wrong wholeText for cdataNode after element insertion");
is(insertedText.wholeText, "zero-before-",
"wrong wholeText for insertedText after element insertion");
var cdataNode2 = cdata("interrupted-");
outer.insertBefore(cdataNode2, insertedText);
is(second.wholeText, "second",
"wrong wholeText for second after cdataNode2 insertion");
is(cdataNode2.wholeText, "zero-interrupted-before-",
"wrong wholeText for cdataNode2 after cdataNode2 insertion");
is(insertedText.wholeText, "zero-interrupted-before-",
"wrong wholeText for insertedText after cdataNode2 insertion");
}
function noParentTests()
{
var textNode = text("foobar");
is(textNode.wholeText, textNode.data,
"orphaned textNode should have wholeText == data");
is(textNode.wholeText, "foobar",
"orphaned textNode should have wholeText == 'foobar'");
var cdataSection = cdata("baz");
is(cdataSection.wholeText, cdataSection.data,
"orphaned cdatasection should have wholeText == data");
is(cdataSection.wholeText, "baz",
"orphaned cdatasection should have wholeText == data");
}
function entityTests()
{
todo_isnot(entity("bar"), null,
"need implementation update if we ever support entity nodes!");
var root = xmlDoc.documentElement;
is(root.lastChild.firstChild.nodeType, Node.TEXT_NODE,
"uh-oh, did we start supporting entity references as nodes?");
is(root.lastChild.lastChild.nodeType, Node.ELEMENT_NODE,
"uh-oh, did we start supporting entity references as nodes?");
// If any of the above ever fails, add tests here!
}
function tests()
{
try
{
firstTests();
middleTests();
lastTests();
noParentTests();
entityTests();
}
catch (e)
{
ok(false, "error thrown: " + e);
}
finally
{
SimpleTest.finish();
}
}
window.addEventListener("load", tests, false);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0"?>
<!DOCTYPE document
[
<!ENTITY foobar "baz<quux/>">
]>
<document><![CDATA[]]><entity>&foobar;</entity></document>

Просмотреть файл

@ -85,9 +85,7 @@ nsDOMDataContainerEvent::SetData(const nsAString& aKey, nsIVariant *aData)
NS_ENSURE_ARG(aData);
// Make sure this event isn't already being dispatched.
NS_ENSURE_STATE(!(NS_IS_EVENT_IN_DISPATCH(mEvent) ||
(mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY)));
NS_ENSURE_STATE(!(NS_IS_EVENT_IN_DISPATCH(mEvent)));
NS_ENSURE_STATE(mData.IsInitialized());
return mData.Put(aKey, aData) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}

Просмотреть файл

@ -601,11 +601,6 @@ nsDOMEvent::InitEvent(const nsAString& aEventTypeArg, PRBool aCanBubbleArg, PRBo
mEvent->target = nsnull;
mEvent->originalTarget = nsnull;
// Unset the NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY bit (which is
// set at the end of event dispatch) so that this event can be
// dispatched.
mEvent->flags &= ~NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY;
return NS_OK;
}

Просмотреть файл

@ -376,11 +376,6 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
NS_ASSERTION(aEvent, "Trying to dispatch without nsEvent!");
NS_ENSURE_TRUE(!NS_IS_EVENT_IN_DISPATCH(aEvent),
NS_ERROR_ILLEGAL_VALUE);
// This is strange, but nsEvents are sometimes reused and they don't need
// re-initialization.
NS_ENSURE_TRUE(!(aDOMEvent &&
(aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY)),
NS_ERROR_ILLEGAL_VALUE);
#ifdef DEBUG
if (aDOMEvent) {
@ -532,7 +527,7 @@ nsEventDispatcher::DispatchDOMEvent(nsISupports* aTarget,
nsevent->GetIsTrusted(&trusted);
if (!trusted) {
if (!trusted || (innerEvent->flags & NS_EVENT_DISPATCHED)) {
//Check security state to determine if dispatcher is trusted
privEvt->SetTrusted(nsContentUtils::IsCallerTrustedForWrite());
}

Просмотреть файл

@ -58,6 +58,7 @@ _TEST_FILES = \
test_bug402089.html \
test_bug405632.html \
test_bug409604.html \
test_bug412567.html \
$(NULL)
_CHROME_FILES = \

Просмотреть файл

@ -0,0 +1,48 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=412567
-->
<head>
<title>Test for Bug 412567</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="testRedispatching(event);">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=412567">Mozilla Bug 412567</a>
<p id="display"></p>
<div id="content" style="display: none" onload="redispatchinHandler(event)">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 412567 **/
var loadEvent = null;
function redispatchinHandler(evt) {
is(evt.type, "load", "Wrong event type!");
ok(!evt.isTrusted, "Event should not be trusted!");
SimpleTest.finish();
}
function redispatch() {
ok(loadEvent.isTrusted, "Event should be trusted before redispatching!");
document.getElementById('content').dispatchEvent(loadEvent);
}
function testRedispatching(evt) {
is(evt.type, "load", "Wrong event type!");
ok(evt.isTrusted, "Event should be trusted!");
loadEvent = evt;
setTimeout(redispatch, 0);
}
SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -3877,19 +3877,21 @@ nsHTMLDocument::GetDocumentAllResult(const nsAString& aID, nsISupports** aResult
NS_ENSURE_TRUE(entry->mDocAllList, NS_ERROR_OUT_OF_MEMORY);
}
nsRefPtr<nsContentList> docAllList = entry->mDocAllList;
// Check if there are more than 1 entries. Do this by getting the second one
// rather than the length since getting the length always requires walking
// the entire document.
nsIContent* cont = entry->mDocAllList->Item(1, PR_TRUE);
nsIContent* cont = docAllList->Item(1, PR_TRUE);
if (cont) {
NS_ADDREF(*aResult = static_cast<nsIDOMNodeList*>(entry->mDocAllList));
NS_ADDREF(*aResult = static_cast<nsIDOMNodeList*>(docAllList));
return NS_OK;
}
// There's only 0 or 1 items. Return the first one or null.
NS_IF_ADDREF(*aResult = entry->mDocAllList->Item(0, PR_TRUE));
NS_IF_ADDREF(*aResult = docAllList->Item(0, PR_TRUE));
return NS_OK;
}

Просмотреть файл

@ -36,6 +36,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsIDOMCDATASection.h"
#include "nsIDOM3Text.h"
#include "nsGenericDOMDataNode.h"
#include "nsGkAtoms.h"
#include "nsIDocument.h"
@ -111,6 +112,7 @@ NS_INTERFACE_MAP_BEGIN(nsXMLCDATASection)
NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
NS_INTERFACE_MAP_ENTRY(nsIDOMCharacterData)
NS_INTERFACE_MAP_ENTRY(nsIDOMText)
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOM3Text, new nsText3Tearoff(this))
NS_INTERFACE_MAP_ENTRY(nsIDOMCDATASection)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CDATASection)
NS_INTERFACE_MAP_END_INHERITING(nsGenericDOMDataNode)

Просмотреть файл

@ -152,6 +152,8 @@
#include "nsEventDispatcher.h"
#include "nsPresShellIterator.h"
#include "mozAutoDocUpdate.h"
#include "nsIDOMXULCommandEvent.h"
#include "nsIDOMNSEvent.h"
/**
* Three bits are used for XUL Element's lazy state.
@ -1648,6 +1650,22 @@ nsXULElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
EmptyString(),
&aVisitor.mDOMEvent);
}
nsCOMPtr<nsIDOMNSEvent> nsevent =
do_QueryInterface(aVisitor.mDOMEvent);
while (nsevent) {
nsCOMPtr<nsIDOMEventTarget> oTarget;
nsevent->GetOriginalTarget(getter_AddRefs(oTarget));
NS_ENSURE_STATE(!SameCOMIdentity(oTarget, commandContent));
nsCOMPtr<nsIDOMEvent> tmp;
nsCOMPtr<nsIDOMXULCommandEvent> commandEvent =
do_QueryInterface(nsevent);
if (commandEvent) {
commandEvent->GetSourceEvent(getter_AddRefs(tmp));
}
nsevent = do_QueryInterface(tmp);
}
event.sourceEvent = aVisitor.mDOMEvent;
nsEventStatus status = nsEventStatus_eIgnore;

Просмотреть файл

@ -69,6 +69,7 @@ SDK_XPIDLSRCS = \
XPIDLSRCS = \
nsIDOM3Document.idl \
nsIDOM3Node.idl \
nsIDOM3Text.idl \
nsIDOM3TypeInfo.idl \
nsIDOM3Attr.idl \
nsIDOMDOMStringList.idl \

Просмотреть файл

@ -0,0 +1,65 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is DOM 3 Core interface definitions.
*
* The Initial Developer of the Original Code is
* Jeff Walden <jwalden+code@mit.edu>.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "domstubs.idl"
[scriptable, uuid(BCCA052E-46F4-4B8E-8859-A86776C2F1D7)]
interface nsIDOM3Text : nsISupports
{
/**
* Indicates whether this text node contains element content whitespace.
* A text node is element content whitespace if it contains only XML
* white space characters and is a child of an element whose content
* model allows only child elements optionally separated by white space.
*/
readonly attribute boolean isElementContentWhitespace;
/**
* The concatenation of all logically adjacent text nodes with this text
* node, where "logically adjacent" consists of all text nodes which can be
* reached by traversing the document tree in either direction without
* passing an element, comment, or processing-instruction boundary.
*/
readonly attribute DOMString wholeText;
/**
* If content is empty, removes all logically adjacent text nodes (including
* this node) from the DOM tree, returning null; otherwise, replaces the
* contents of this node with aContent and removes all other logically
* adjacent text nodes from the DOM tree, returning this node.
*/
nsIDOMText replaceWholeText(in DOMString content) raises(DOMException);
};

Просмотреть файл

@ -225,6 +225,7 @@
#include "nsIDOMDocumentEvent.h"
#include "nsIDOMAttr.h"
#include "nsIDOMText.h"
#include "nsIDOM3Text.h"
#include "nsIDOMComment.h"
#include "nsIDOMCDATASection.h"
#include "nsIDOMProcessingInstruction.h"
@ -1986,6 +1987,7 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMText)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node)
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Text)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(Comment, nsIDOMComment)
@ -1998,6 +2000,7 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCDATASection)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node)
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Text)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(ProcessingInstruction, nsIDOMProcessingInstruction)

Просмотреть файл

@ -120,7 +120,8 @@ class nsHashKey;
#define NS_PRIV_EVENT_FLAG_SCRIPT 0x0080
#define NS_EVENT_FLAG_NO_CONTENT_DISPATCH 0x0100
#define NS_EVENT_FLAG_SYSTEM_EVENT 0x0200
#define NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY 0x0400 // @see nsIDOM3Event::stopImmediatePropagation()
// Event has been dispatched at least once
#define NS_EVENT_DISPATCHED 0x0400
#define NS_EVENT_FLAG_DISPATCHING 0x0800
#define NS_PRIV_EVENT_UNTRUSTED_PERMITTED 0x8000
@ -1123,7 +1124,7 @@ enum nsDragDropEventStatus {
NS_ASSERTION(NS_IS_EVENT_IN_DISPATCH(event), \
"Event never got marked for dispatch!"); \
(event)->flags &= ~NS_EVENT_FLAG_DISPATCHING; \
(event)->flags |= NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY;
(event)->flags |= NS_EVENT_DISPATCHED;
/*
* Virtual key bindings for keyboard events.