Bug 1637856 - part 2: Get rid of `WSRunScanner::mNodeArray` r=m_kato

`WSRunScanner` scans around given point in `GetWSNodes()` at construction with
using `HTMLEditUtils` methods and caches editable text nodes between
`mStartReasonContent` and `mEndReasonContent`.  However, it's used only by
`GetNextCharPoint()` and `GetPreviousCharPoint()`, and they shouldn't be
referred after changing the DOM tree.  Therefore, we can scan it directly
only when it needs to scan.

The patch rewrites `GetNextCharPoint()` and `GetPreviousCharPoint()` without
`mNodeArray` and removes `mNodeArray` from its member.  This may increase the
cost of scanning next/previous text node, but improves the scan performance
when it does not treat so wide range and they are called with a point whose
container is not a text node.

This patch unexpectedly changes the behavior of them, that causes the fix of
2 failures in `insertlinebreak.html` and `insertparagraph.html`.  According to
debugger, previously GetNextCharPoint()` in
`ScanNextVisibleNodeOrBlockBoundaryFrom()` called point at `<br>` element
returned no next char, then, `ScanNextVisibleNodeOrBlockBoundaryFrom()` returned
end point which is block boundary of `<listing>` element (it is legacy HTML2
element and treated as `<pre>` element internally).  Therefore, the inserted
`<br>` element was misunderstood as invisible `<br>` at end of a block and
inserted another `<br>` element for making it visible.  However, the redesigned
one fixed this bug with searching correct text node.  Therefore, I cannot
keep the buggy behavior in the new designed methods.

Depends on D75470

Differential Revision: https://phabricator.services.mozilla.com/D75471
This commit is contained in:
Masayuki Nakano 2020-05-18 06:46:00 +00:00
Родитель 714518769f
Коммит c7249ef506
4 изменённых файлов: 156 добавлений и 572 удалений

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

@ -226,12 +226,12 @@ already_AddRefed<Element> WSRunObject::InsertBreak(
// Need to determine if break at front of non-nbsp run. If so, convert // Need to determine if break at front of non-nbsp run. If so, convert
// run to nbsp. // run to nbsp.
EditorDOMPointInText atNextCharOfInsertionPoint = EditorDOMPointInText atNextCharOfInsertionPoint =
GetNextCharPoint(pointToInsert); GetInclusiveNextEditableCharPoint(pointToInsert);
if (atNextCharOfInsertionPoint.IsSet() && if (atNextCharOfInsertionPoint.IsSet() &&
!atNextCharOfInsertionPoint.IsEndOfContainer() && !atNextCharOfInsertionPoint.IsEndOfContainer() &&
atNextCharOfInsertionPoint.IsCharASCIISpace()) { atNextCharOfInsertionPoint.IsCharASCIISpace()) {
EditorDOMPointInText atPreviousCharOfNextCharOfInsertionPoint = EditorDOMPointInText atPreviousCharOfNextCharOfInsertionPoint =
GetPreviousCharPointFromPointInText(atNextCharOfInsertionPoint); GetPreviousEditableCharPoint(atNextCharOfInsertionPoint);
if (!atPreviousCharOfNextCharOfInsertionPoint.IsSet() || if (!atPreviousCharOfNextCharOfInsertionPoint.IsSet() ||
atPreviousCharOfNextCharOfInsertionPoint.IsEndOfContainer() || atPreviousCharOfNextCharOfInsertionPoint.IsEndOfContainer() ||
!atPreviousCharOfNextCharOfInsertionPoint.IsCharASCIISpace()) { !atPreviousCharOfNextCharOfInsertionPoint.IsCharASCIISpace()) {
@ -377,7 +377,7 @@ nsresult WSRunObject::InsertText(Document& aDocument,
theString.SetCharAt(kNBSP, 0); theString.SetCharAt(kNBSP, 0);
} else if (beforeRun->IsVisible()) { } else if (beforeRun->IsVisible()) {
EditorDOMPointInText atPreviousChar = EditorDOMPointInText atPreviousChar =
GetPreviousCharPoint(pointToInsert); GetPreviousEditableCharPoint(pointToInsert);
if (atPreviousChar.IsSet() && !atPreviousChar.IsEndOfContainer() && if (atPreviousChar.IsSet() && !atPreviousChar.IsEndOfContainer() &&
atPreviousChar.IsCharASCIISpace()) { atPreviousChar.IsCharASCIISpace()) {
theString.SetCharAt(kNBSP, 0); theString.SetCharAt(kNBSP, 0);
@ -397,7 +397,8 @@ nsresult WSRunObject::InsertText(Document& aDocument,
if (afterRun->IsEndOfHardLine()) { if (afterRun->IsEndOfHardLine()) {
theString.SetCharAt(kNBSP, lastCharIndex); theString.SetCharAt(kNBSP, lastCharIndex);
} else if (afterRun->IsVisible()) { } else if (afterRun->IsVisible()) {
EditorDOMPointInText atNextChar = GetNextCharPoint(pointToInsert); EditorDOMPointInText atNextChar =
GetInclusiveNextEditableCharPoint(pointToInsert);
if (atNextChar.IsSet() && !atNextChar.IsEndOfContainer() && if (atNextChar.IsSet() && !atNextChar.IsEndOfContainer() &&
atNextChar.IsCharASCIISpace()) { atNextChar.IsCharASCIISpace()) {
theString.SetCharAt(kNBSP, lastCharIndex); theString.SetCharAt(kNBSP, lastCharIndex);
@ -455,7 +456,7 @@ nsresult WSRunObject::InsertText(Document& aDocument,
nsresult WSRunObject::DeleteWSBackward() { nsresult WSRunObject::DeleteWSBackward() {
EditorDOMPointInText atPreviousCharOfStart = EditorDOMPointInText atPreviousCharOfStart =
GetPreviousCharPoint(mScanStartPoint); GetPreviousEditableCharPoint(mScanStartPoint);
if (!atPreviousCharOfStart.IsSet() || if (!atPreviousCharOfStart.IsSet() ||
atPreviousCharOfStart.IsEndOfContainer()) { atPreviousCharOfStart.IsEndOfContainer()) {
return NS_OK; return NS_OK;
@ -531,7 +532,8 @@ nsresult WSRunObject::DeleteWSBackward() {
} }
nsresult WSRunObject::DeleteWSForward() { nsresult WSRunObject::DeleteWSForward() {
EditorDOMPointInText atNextCharOfStart = GetNextCharPoint(mScanStartPoint); EditorDOMPointInText atNextCharOfStart =
GetInclusiveNextEditableCharPoint(mScanStartPoint);
if (!atNextCharOfStart.IsSet() || atNextCharOfStart.IsEndOfContainer()) { if (!atNextCharOfStart.IsSet() || atNextCharOfStart.IsEndOfContainer()) {
return NS_OK; return NS_OK;
} }
@ -616,7 +618,8 @@ WSScanResult WSRunScanner::ScanPreviousVisibleNodeOrBlockBoundaryFrom(
// Is there a visible run there or earlier? // Is there a visible run there or earlier?
for (; run; run = run->mLeft) { for (; run; run = run->mLeft) {
if (run->IsVisibleAndMiddleOfHardLine()) { if (run->IsVisibleAndMiddleOfHardLine()) {
EditorDOMPointInText atPreviousChar = GetPreviousCharPoint(aPoint); EditorDOMPointInText atPreviousChar =
GetPreviousEditableCharPoint(aPoint);
// When it's a non-empty text node, return it. // When it's a non-empty text node, return it.
if (atPreviousChar.IsSet() && !atPreviousChar.IsContainerEmpty()) { if (atPreviousChar.IsSet() && !atPreviousChar.IsContainerEmpty()) {
MOZ_ASSERT(!atPreviousChar.IsEndOfContainer()); MOZ_ASSERT(!atPreviousChar.IsEndOfContainer());
@ -651,7 +654,8 @@ WSScanResult WSRunScanner::ScanNextVisibleNodeOrBlockBoundaryFrom(
// Is there a visible run there or later? // Is there a visible run there or later?
for (; run; run = run->mRight) { for (; run; run = run->mRight) {
if (run->IsVisibleAndMiddleOfHardLine()) { if (run->IsVisibleAndMiddleOfHardLine()) {
EditorDOMPointInText atNextChar = GetNextCharPoint(aPoint); EditorDOMPointInText atNextChar =
GetInclusiveNextEditableCharPoint(aPoint);
// When it's a non-empty text node, return it. // When it's a non-empty text node, return it.
if (atNextChar.IsSet() && !atNextChar.IsContainerEmpty()) { if (atNextChar.IsSet() && !atNextChar.IsContainerEmpty()) {
return WSScanResult( return WSScanResult(
@ -745,7 +749,6 @@ nsresult WSRunScanner::GetWSNodes() {
// first look backwards to find preceding ws nodes // first look backwards to find preceding ws nodes
if (Text* textNode = mScanStartPoint.GetContainerAsText()) { if (Text* textNode = mScanStartPoint.GetContainerAsText()) {
const nsTextFragment* textFrag = &textNode->TextFragment(); const nsTextFragment* textFrag = &textNode->TextFragment();
mNodeArray.InsertElementAt(0, textNode);
if (!mScanStartPoint.IsStartOfContainer()) { if (!mScanStartPoint.IsStartOfContainer()) {
for (uint32_t i = mScanStartPoint.Offset(); i; i--) { for (uint32_t i = mScanStartPoint.Offset(); i; i--) {
// sanity bounds check the char position. bug 136165 // sanity bounds check the char position. bug 136165
@ -791,7 +794,6 @@ nsresult WSRunScanner::GetWSNodes() {
} else if (previousLeafContentOrBlock->IsText() && } else if (previousLeafContentOrBlock->IsText() &&
previousLeafContentOrBlock->IsEditable()) { previousLeafContentOrBlock->IsEditable()) {
RefPtr<Text> textNode = previousLeafContentOrBlock->AsText(); RefPtr<Text> textNode = previousLeafContentOrBlock->AsText();
mNodeArray.InsertElementAt(0, textNode);
const nsTextFragment* textFrag = &textNode->TextFragment(); const nsTextFragment* textFrag = &textNode->TextFragment();
uint32_t len = textNode->TextLength(); uint32_t len = textNode->TextLength();
@ -901,7 +903,6 @@ nsresult WSRunScanner::GetWSNodes() {
} else if (nextLeafContentOrBlock->IsText() && } else if (nextLeafContentOrBlock->IsText() &&
nextLeafContentOrBlock->IsEditable()) { nextLeafContentOrBlock->IsEditable()) {
RefPtr<Text> textNode = nextLeafContentOrBlock->AsText(); RefPtr<Text> textNode = nextLeafContentOrBlock->AsText();
mNodeArray.AppendElement(textNode);
const nsTextFragment* textFrag = &textNode->TextFragment(); const nsTextFragment* textFrag = &textNode->TextFragment();
uint32_t len = textNode->TextLength(); uint32_t len = textNode->TextLength();
@ -1169,7 +1170,8 @@ nsresult WSRunObject::PrepareToDeleteRangePriv(WSRunObject* aEndObject) {
// make sure leading char of following ws is an nbsp, so that it will // make sure leading char of following ws is an nbsp, so that it will
// show up // show up
EditorDOMPointInText nextCharOfStartOfEnd = EditorDOMPointInText nextCharOfStartOfEnd =
aEndObject->GetNextCharPoint(aEndObject->mScanStartPoint); aEndObject->GetInclusiveNextEditableCharPoint(
aEndObject->mScanStartPoint);
if (nextCharOfStartOfEnd.IsSet() && if (nextCharOfStartOfEnd.IsSet() &&
!nextCharOfStartOfEnd.IsEndOfContainer() && !nextCharOfStartOfEnd.IsEndOfContainer() &&
nextCharOfStartOfEnd.IsCharASCIISpace()) { nextCharOfStartOfEnd.IsCharASCIISpace()) {
@ -1211,7 +1213,7 @@ nsresult WSRunObject::PrepareToDeleteRangePriv(WSRunObject* aEndObject) {
// make sure trailing char of starting ws is an nbsp, so that it will show // make sure trailing char of starting ws is an nbsp, so that it will show
// up // up
EditorDOMPointInText atPreviousCharOfStart = EditorDOMPointInText atPreviousCharOfStart =
GetPreviousCharPoint(mScanStartPoint); GetPreviousEditableCharPoint(mScanStartPoint);
if (atPreviousCharOfStart.IsSet() && if (atPreviousCharOfStart.IsSet() &&
!atPreviousCharOfStart.IsEndOfContainer() && !atPreviousCharOfStart.IsEndOfContainer() &&
atPreviousCharOfStart.IsCharASCIISpace()) { atPreviousCharOfStart.IsCharASCIISpace()) {
@ -1249,7 +1251,8 @@ nsresult WSRunObject::PrepareToSplitAcrossBlocksPriv() {
if (afterRun && afterRun->IsVisibleAndMiddleOfHardLine()) { if (afterRun && afterRun->IsVisibleAndMiddleOfHardLine()) {
// make sure leading char of following ws is an nbsp, so that it will show // make sure leading char of following ws is an nbsp, so that it will show
// up // up
EditorDOMPointInText atNextCharOfStart = GetNextCharPoint(mScanStartPoint); EditorDOMPointInText atNextCharOfStart =
GetInclusiveNextEditableCharPoint(mScanStartPoint);
if (atNextCharOfStart.IsSet() && !atNextCharOfStart.IsEndOfContainer() && if (atNextCharOfStart.IsSet() && !atNextCharOfStart.IsEndOfContainer() &&
atNextCharOfStart.IsCharASCIISpace()) { atNextCharOfStart.IsCharASCIISpace()) {
// mScanStartPoint will be referred bellow so that we need to keep // mScanStartPoint will be referred bellow so that we need to keep
@ -1271,7 +1274,7 @@ nsresult WSRunObject::PrepareToSplitAcrossBlocksPriv() {
// make sure trailing char of starting ws is an nbsp, so that it will show // make sure trailing char of starting ws is an nbsp, so that it will show
// up // up
EditorDOMPointInText atPreviousCharOfStart = EditorDOMPointInText atPreviousCharOfStart =
GetPreviousCharPoint(mScanStartPoint); GetPreviousEditableCharPoint(mScanStartPoint);
if (atPreviousCharOfStart.IsSet() && if (atPreviousCharOfStart.IsSet() &&
!atPreviousCharOfStart.IsEndOfContainer() && !atPreviousCharOfStart.IsEndOfContainer() &&
atPreviousCharOfStart.IsCharASCIISpace()) { atPreviousCharOfStart.IsCharASCIISpace()) {
@ -1296,83 +1299,139 @@ nsresult WSRunObject::PrepareToSplitAcrossBlocksPriv() {
} }
template <typename PT, typename CT> template <typename PT, typename CT>
EditorDOMPointInText WSRunScanner::GetNextCharPoint( EditorDOMPointInText WSRunScanner::GetInclusiveNextEditableCharPoint(
const EditorDOMPointBase<PT, CT>& aPoint) const { const EditorDOMPointBase<PT, CT>& aPoint) const {
MOZ_ASSERT(aPoint.IsSetAndValid()); MOZ_ASSERT(aPoint.IsSetAndValid());
size_t index = aPoint.IsInTextNode() if (NS_WARN_IF(!aPoint.IsInContentNode()) ||
? mNodeArray.IndexOf(aPoint.GetContainer()) NS_WARN_IF(!mScanStartPoint.IsInContentNode())) {
: decltype(mNodeArray)::NoIndex; return EditorDOMPointInText();
if (index == decltype(mNodeArray)::NoIndex) {
// Use range comparisons to get next text node which is in mNodeArray.
return LookForNextCharPointWithinAllTextNodes(aPoint);
} }
return GetNextCharPointFromPointInText(
EditorDOMPointInText(mNodeArray[index], aPoint.Offset())); EditorRawDOMPoint point;
if (nsIContent* child = aPoint.GetChild()) {
nsIContent* leafContent = child->HasChildren()
? HTMLEditUtils::GetFirstLeafChild(
*child, ChildBlockBoundary::Ignore)
: child;
if (NS_WARN_IF(!leafContent)) {
return EditorDOMPointInText();
}
point.Set(leafContent, 0);
} else {
point = aPoint;
}
// If it points a character in a text node, return it.
// XXX For the performance, this does not check whether the container
// is outside of our range.
if (point.IsInTextNode() && point.GetContainer()->IsEditable() &&
!point.IsEndOfContainer()) {
return EditorDOMPointInText(point.ContainerAsText(), point.Offset());
}
if (point.GetContainer() == mEndReasonContent) {
return EditorDOMPointInText();
}
nsIContent* editableBlockParentOrTopmotEditableInlineContent =
GetEditableBlockParentOrTopmotEditableInlineContent(
mScanStartPoint.ContainerAsContent());
if (NS_WARN_IF(!editableBlockParentOrTopmotEditableInlineContent)) {
// Meaning that the container of `mScanStartPoint` is not editable.
editableBlockParentOrTopmotEditableInlineContent =
mScanStartPoint.ContainerAsContent();
}
for (nsIContent* nextContent =
HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
*point.ContainerAsContent(),
*editableBlockParentOrTopmotEditableInlineContent, mEditingHost);
nextContent;
nextContent = HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
*nextContent, *editableBlockParentOrTopmotEditableInlineContent,
mEditingHost)) {
if (!nextContent->IsText() || !nextContent->IsEditable()) {
if (nextContent == mEndReasonContent) {
break; // Reached end of current runs.
}
continue;
}
return EditorDOMPointInText(nextContent->AsText(), 0);
}
return EditorDOMPointInText();
} }
template <typename PT, typename CT> template <typename PT, typename CT>
EditorDOMPointInText WSRunScanner::GetPreviousCharPoint( EditorDOMPointInText WSRunScanner::GetPreviousEditableCharPoint(
const EditorDOMPointBase<PT, CT>& aPoint) const { const EditorDOMPointBase<PT, CT>& aPoint) const {
MOZ_ASSERT(aPoint.IsSetAndValid()); MOZ_ASSERT(aPoint.IsSetAndValid());
size_t index = aPoint.IsInTextNode() if (NS_WARN_IF(!aPoint.IsInContentNode()) ||
? mNodeArray.IndexOf(aPoint.GetContainer()) NS_WARN_IF(!mScanStartPoint.IsInContentNode())) {
: decltype(mNodeArray)::NoIndex;
if (index == decltype(mNodeArray)::NoIndex) {
// Use range comparisons to get previous text node which is in mNodeArray.
return LookForPreviousCharPointWithinAllTextNodes(aPoint);
}
return GetPreviousCharPointFromPointInText(
EditorDOMPointInText(mNodeArray[index], aPoint.Offset()));
}
EditorDOMPointInText WSRunScanner::GetNextCharPointFromPointInText(
const EditorDOMPointInText& aPoint) const {
MOZ_ASSERT(aPoint.IsSet());
size_t index = mNodeArray.IndexOf(aPoint.GetContainer());
if (index == decltype(mNodeArray)::NoIndex) {
// Can't find point, but it's not an error
return EditorDOMPointInText(); return EditorDOMPointInText();
} }
if (aPoint.IsSetAndValid() && !aPoint.IsEndOfContainer()) { EditorRawDOMPoint point;
// XXX This may return empty text node. if (nsIContent* previousChild = aPoint.GetPreviousSiblingOfChild()) {
return aPoint; nsIContent* leafContent =
previousChild->HasChildren()
? HTMLEditUtils::GetLastLeafChild(*previousChild,
ChildBlockBoundary::Ignore)
: previousChild;
if (NS_WARN_IF(!leafContent)) {
return EditorDOMPointInText();
}
point.SetToEndOf(leafContent);
} else {
point = aPoint;
} }
if (index + 1 == mNodeArray.Length()) { // If it points a character in a text node and it's not first character
// in it, return its previous point.
// XXX For the performance, this does not check whether the container
// is outside of our range.
if (point.IsInTextNode() && point.GetContainer()->IsEditable() &&
!point.IsStartOfContainer()) {
return EditorDOMPointInText(point.ContainerAsText(), point.Offset() - 1);
}
if (point.GetContainer() == mStartReasonContent) {
return EditorDOMPointInText(); return EditorDOMPointInText();
} }
// XXX This may return empty text node. nsIContent* editableBlockParentOrTopmotEditableInlineContent =
return EditorDOMPointInText(mNodeArray[index + 1], 0); GetEditableBlockParentOrTopmotEditableInlineContent(
} mScanStartPoint.ContainerAsContent());
if (NS_WARN_IF(!editableBlockParentOrTopmotEditableInlineContent)) {
EditorDOMPointInText WSRunScanner::GetPreviousCharPointFromPointInText( // Meaning that the container of `mScanStartPoint` is not editable.
const EditorDOMPointInText& aPoint) const { editableBlockParentOrTopmotEditableInlineContent =
MOZ_ASSERT(aPoint.IsSet()); mScanStartPoint.ContainerAsContent();
size_t index = mNodeArray.IndexOf(aPoint.GetContainer());
if (index == decltype(mNodeArray)::NoIndex) {
// Can't find point, but it's not an error
return EditorDOMPointInText();
} }
if (!aPoint.IsStartOfContainer()) { for (nsIContent* previousContent =
return aPoint.PreviousPoint(); HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
*point.ContainerAsContent(),
*editableBlockParentOrTopmotEditableInlineContent, mEditingHost);
previousContent;
previousContent =
HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
*previousContent,
*editableBlockParentOrTopmotEditableInlineContent,
mEditingHost)) {
if (!previousContent->IsText() || !previousContent->IsEditable()) {
if (previousContent == mStartReasonContent) {
break; // Reached start of current runs.
}
continue;
}
return EditorDOMPointInText(
previousContent->AsText(),
previousContent->AsText()->TextLength()
? previousContent->AsText()->TextLength() - 1
: 0);
} }
return EditorDOMPointInText();
if (!index) {
return EditorDOMPointInText();
}
// XXX This may return empty text node.
return EditorDOMPointInText(mNodeArray[index - 1],
mNodeArray[index - 1]->TextLength()
? mNodeArray[index - 1]->TextLength() - 1
: 0);
} }
nsresult WSRunObject::InsertNBSPAndRemoveFollowingASCIIWhitespaces( nsresult WSRunObject::InsertNBSPAndRemoveFollowingASCIIWhitespaces(
@ -1432,19 +1491,19 @@ WSRunObject::GetASCIIWhitespacesBounds(
EditorDOMPointInText start, end; EditorDOMPointInText start, end;
if (aDir & eAfter) { if (aDir & eAfter) {
EditorDOMPointInText atNextChar = GetNextCharPoint(aPoint); EditorDOMPointInText atNextChar = GetInclusiveNextEditableCharPoint(aPoint);
if (atNextChar.IsSet()) { if (atNextChar.IsSet()) {
// We found a text node, at least. // We found a text node, at least.
start = end = atNextChar; start = end = atNextChar;
// Scan ahead to end of ASCII whitespaces. // Scan ahead to end of ASCII whitespaces.
// XXX Looks like that this is too expensive in most cases. While we // XXX Looks like that this is too expensive in most cases. While we
// are scanning a text node, we should do it without // are scanning a text node, we should do it without
// GetNextCharPointInText(). // GetInclusiveNextEditableCharPoint().
// XXX This loop ends at end of a text node. Shouldn't we keep looking // XXX This loop ends at end of a text node. Shouldn't we keep looking
// next text node? // next text node?
for (; atNextChar.IsSet() && !atNextChar.IsEndOfContainer() && for (; atNextChar.IsSet() && !atNextChar.IsEndOfContainer() &&
atNextChar.IsCharASCIISpace(); atNextChar.IsCharASCIISpace();
atNextChar = GetNextCharPointFromPointInText(atNextChar)) { atNextChar = GetInclusiveNextEditableCharPoint(atNextChar)) {
// End of the range should be after the whitespace. // End of the range should be after the whitespace.
end = atNextChar = atNextChar.NextPoint(); end = atNextChar = atNextChar.NextPoint();
} }
@ -1452,7 +1511,7 @@ WSRunObject::GetASCIIWhitespacesBounds(
} }
if (aDir & eBefore) { if (aDir & eBefore) {
EditorDOMPointInText atPreviousChar = GetPreviousCharPoint(aPoint); EditorDOMPointInText atPreviousChar = GetPreviousEditableCharPoint(aPoint);
if (atPreviousChar.IsSet()) { if (atPreviousChar.IsSet()) {
// We found a text node, at least. // We found a text node, at least.
start = atPreviousChar.NextPoint(); start = atPreviousChar.NextPoint();
@ -1462,13 +1521,12 @@ WSRunObject::GetASCIIWhitespacesBounds(
// Scan back to start of ASCII whitespaces. // Scan back to start of ASCII whitespaces.
// XXX Looks like that this is too expensive in most cases. While we // XXX Looks like that this is too expensive in most cases. While we
// are scanning a text node, we should do it without // are scanning a text node, we should do it without
// GetPreviousCharPointFromPointInText(). // GetPreviousEditableCharPoint().
// XXX This loop ends at end of a text node. Shouldn't we keep looking // XXX This loop ends at end of a text node. Shouldn't we keep looking
// the text node? // the text node?
for (; atPreviousChar.IsSet() && !atPreviousChar.IsEndOfContainer() && for (; atPreviousChar.IsSet() && !atPreviousChar.IsEndOfContainer() &&
atPreviousChar.IsCharASCIISpace(); atPreviousChar.IsCharASCIISpace();
atPreviousChar = atPreviousChar = GetPreviousEditableCharPoint(atPreviousChar)) {
GetPreviousCharPointFromPointInText(atPreviousChar)) {
start = atPreviousChar; start = atPreviousChar;
} }
} }
@ -1529,104 +1587,6 @@ char16_t WSRunScanner::GetCharAt(Text* aTextNode, int32_t aOffset) const {
return aTextNode->TextFragment().CharAt(aOffset); return aTextNode->TextFragment().CharAt(aOffset);
} }
template <typename PT, typename CT>
EditorDOMPointInText WSRunScanner::LookForNextCharPointWithinAllTextNodes(
const EditorDOMPointBase<PT, CT>& aPoint) const {
// Note: only to be called if aPoint.GetContainer() is not a ws node.
MOZ_ASSERT(aPoint.IsSetAndValid());
// Binary search on wsnodes
uint32_t numNodes = mNodeArray.Length();
if (!numNodes) {
// Do nothing if there are no nodes to search
return EditorDOMPointInText();
}
// Begin binary search. We do this because we need to minimize calls to
// ComparePoints(), which is expensive.
uint32_t firstNum = 0, curNum = numNodes / 2, lastNum = numNodes;
while (curNum != lastNum) {
Text* curNode = mNodeArray[curNum];
int16_t cmp = *nsContentUtils::ComparePoints(aPoint.ToRawRangeBoundary(),
RawRangeBoundary(curNode, 0u));
if (cmp < 0) {
lastNum = curNum;
} else {
firstNum = curNum + 1;
}
curNum = (lastNum - firstNum) / 2 + firstNum;
MOZ_ASSERT(firstNum <= curNum && curNum <= lastNum, "Bad binary search");
}
// When the binary search is complete, we always know that the current node
// is the same as the end node, which is always past our range. Therefore,
// we've found the node immediately after the point of interest.
if (curNum == mNodeArray.Length()) {
// hey asked for past our range (it's after the last node).
// GetNextCharPoint() will do the work for us when we pass it the last
// index of the last node.
return GetNextCharPointFromPointInText(
EditorDOMPointInText::AtEndOf(mNodeArray[curNum - 1]));
}
// The char after the point is the first character of our range.
return GetNextCharPointFromPointInText(
EditorDOMPointInText(mNodeArray[curNum], 0));
}
template <typename PT, typename CT>
EditorDOMPointInText WSRunScanner::LookForPreviousCharPointWithinAllTextNodes(
const EditorDOMPointBase<PT, CT>& aPoint) const {
// Note: only to be called if aNode is not a ws node.
MOZ_ASSERT(aPoint.IsSetAndValid());
// Binary search on wsnodes
uint32_t numNodes = mNodeArray.Length();
if (!numNodes) {
// Do nothing if there are no nodes to search
return EditorDOMPointInText();
}
uint32_t firstNum = 0, curNum = numNodes / 2, lastNum = numNodes;
int16_t cmp = 0;
// Begin binary search. We do this because we need to minimize calls to
// ComparePoints(), which is expensive.
while (curNum != lastNum) {
Text* curNode = mNodeArray[curNum];
cmp = *nsContentUtils::ComparePoints(aPoint.ToRawRangeBoundary(),
RawRangeBoundary(curNode, 0u));
if (cmp < 0) {
lastNum = curNum;
} else {
firstNum = curNum + 1;
}
curNum = (lastNum - firstNum) / 2 + firstNum;
MOZ_ASSERT(firstNum <= curNum && curNum <= lastNum, "Bad binary search");
}
// When the binary search is complete, we always know that the current node
// is the same as the end node, which is always past our range. Therefore,
// we've found the node immediately after the point of interest.
if (curNum == mNodeArray.Length()) {
// Get the point before the end of the last node, we can pass the length of
// the node into GetPreviousCharPoint(), and it will return the last
// character.
return GetPreviousCharPointFromPointInText(
EditorDOMPointInText::AtEndOf(mNodeArray[curNum - 1]));
}
// We can just ask the current node for the point immediately before it,
// it will handle moving to the previous node (if any) and returning the
// appropriate character
return GetPreviousCharPointFromPointInText(
EditorDOMPointInText(mNodeArray[curNum], 0));
}
nsresult WSRunObject::CheckTrailingNBSPOfRun(WSFragment* aRun) { nsresult WSRunObject::CheckTrailingNBSPOfRun(WSFragment* aRun) {
if (NS_WARN_IF(!aRun)) { if (NS_WARN_IF(!aRun)) {
return NS_ERROR_INVALID_ARG; return NS_ERROR_INVALID_ARG;
@ -1646,14 +1606,14 @@ nsresult WSRunObject::CheckTrailingNBSPOfRun(WSFragment* aRun) {
// first check for trailing nbsp // first check for trailing nbsp
EditorDOMPointInText atPreviousCharOfEndOfRun = EditorDOMPointInText atPreviousCharOfEndOfRun =
GetPreviousCharPoint(aRun->EndPoint()); GetPreviousEditableCharPoint(aRun->RawEndPoint());
if (atPreviousCharOfEndOfRun.IsSet() && if (atPreviousCharOfEndOfRun.IsSet() &&
!atPreviousCharOfEndOfRun.IsEndOfContainer() && !atPreviousCharOfEndOfRun.IsEndOfContainer() &&
atPreviousCharOfEndOfRun.IsCharNBSP()) { atPreviousCharOfEndOfRun.IsCharNBSP()) {
// now check that what is to the left of it is compatible with replacing // now check that what is to the left of it is compatible with replacing
// nbsp with space // nbsp with space
EditorDOMPointInText atPreviousCharOfPreviousCharOfEndOfRun = EditorDOMPointInText atPreviousCharOfPreviousCharOfEndOfRun =
GetPreviousCharPointFromPointInText(atPreviousCharOfEndOfRun); GetPreviousEditableCharPoint(atPreviousCharOfEndOfRun);
if (atPreviousCharOfPreviousCharOfEndOfRun.IsSet()) { if (atPreviousCharOfPreviousCharOfEndOfRun.IsSet()) {
if (atPreviousCharOfPreviousCharOfEndOfRun.IsEndOfContainer() || if (atPreviousCharOfPreviousCharOfEndOfRun.IsEndOfContainer() ||
!atPreviousCharOfPreviousCharOfEndOfRun.IsCharASCIISpace()) { !atPreviousCharOfPreviousCharOfEndOfRun.IsCharASCIISpace()) {
@ -1714,9 +1674,10 @@ nsresult WSRunObject::CheckTrailingNBSPOfRun(WSFragment* aRun) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
atPreviousCharOfEndOfRun = GetPreviousCharPoint(aRun->EndPoint()); atPreviousCharOfEndOfRun =
GetPreviousEditableCharPoint(aRun->RawEndPoint());
atPreviousCharOfPreviousCharOfEndOfRun = atPreviousCharOfPreviousCharOfEndOfRun =
GetPreviousCharPointFromPointInText(atPreviousCharOfEndOfRun); GetPreviousEditableCharPoint(atPreviousCharOfEndOfRun);
rightCheck = true; rightCheck = true;
} }
} }
@ -1824,11 +1785,11 @@ nsresult WSRunObject::ReplacePreviousNBSPIfUnnecessary(
// about what is after it. What is after it now will end up after the // about what is after it. What is after it now will end up after the
// inserted object. // inserted object.
bool canConvert = false; bool canConvert = false;
EditorDOMPointInText atPreviousChar = GetPreviousCharPoint(aPoint); EditorDOMPointInText atPreviousChar = GetPreviousEditableCharPoint(aPoint);
if (atPreviousChar.IsSet() && !atPreviousChar.IsEndOfContainer() && if (atPreviousChar.IsSet() && !atPreviousChar.IsEndOfContainer() &&
atPreviousChar.IsCharNBSP()) { atPreviousChar.IsCharNBSP()) {
EditorDOMPointInText atPreviousCharOfPreviousChar = EditorDOMPointInText atPreviousCharOfPreviousChar =
GetPreviousCharPointFromPointInText(atPreviousChar); GetPreviousEditableCharPoint(atPreviousChar);
if (atPreviousCharOfPreviousChar.IsSet()) { if (atPreviousCharOfPreviousChar.IsSet()) {
if (atPreviousCharOfPreviousChar.IsEndOfContainer() || if (atPreviousCharOfPreviousChar.IsEndOfContainer() ||
!atPreviousCharOfPreviousChar.IsCharASCIISpace()) { !atPreviousCharOfPreviousChar.IsCharASCIISpace()) {
@ -1890,14 +1851,14 @@ nsresult WSRunObject::CheckLeadingNBSP(WSFragment* aRun, nsINode* aNode,
// before it. What is before it now will end up before the inserted text. // before it. What is before it now will end up before the inserted text.
bool canConvert = false; bool canConvert = false;
EditorDOMPointInText atNextChar = EditorDOMPointInText atNextChar =
GetNextCharPoint(EditorRawDOMPoint(aNode, aOffset)); GetInclusiveNextEditableCharPoint(EditorRawDOMPoint(aNode, aOffset));
if (!atNextChar.IsSet() || NS_WARN_IF(atNextChar.IsEndOfContainer())) { if (!atNextChar.IsSet() || NS_WARN_IF(atNextChar.IsEndOfContainer())) {
return NS_OK; return NS_OK;
} }
if (atNextChar.IsCharNBSP()) { if (atNextChar.IsCharNBSP()) {
EditorDOMPointInText atNextCharOfNextCharOfNBSP = EditorDOMPointInText atNextCharOfNextCharOfNBSP =
GetNextCharPointFromPointInText(atNextChar.NextPoint()); GetInclusiveNextEditableCharPoint(atNextChar.NextPoint());
if (atNextCharOfNextCharOfNBSP.IsSet()) { if (atNextCharOfNextCharOfNBSP.IsSet()) {
if (atNextCharOfNextCharOfNBSP.IsEndOfContainer() || if (atNextCharOfNextCharOfNBSP.IsEndOfContainer() ||
!atNextCharOfNextCharOfNBSP.IsCharASCIISpace()) { !atNextCharOfNextCharOfNBSP.IsCharASCIISpace()) {

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

@ -546,30 +546,24 @@ class MOZ_STACK_CLASS WSRunScanner {
bool aForward) const; bool aForward) const;
/** /**
* GetNextCharPoint() and GetNextCharPointFromPointInText() return next * GetInclusiveNextEditableCharPoint() returns aPoint if it points a character
* character's point of aPoint. If there is no character after aPoint, * in an editable text node, or start of next editable text node otherwise.
* mTextNode is set to nullptr. * FYI: For the performance, this does not check whether given container
* is not after mStartReasonContent or not.
*/ */
template <typename PT, typename CT> template <typename PT, typename CT>
EditorDOMPointInText GetNextCharPoint( EditorDOMPointInText GetInclusiveNextEditableCharPoint(
const EditorDOMPointBase<PT, CT>& aPoint) const; const EditorDOMPointBase<PT, CT>& aPoint) const;
EditorDOMPointInText GetNextCharPointFromPointInText(
const EditorDOMPointInText& aPoint) const;
/** /**
* LookForNextCharPointWithinAllTextNodes() and * GetPreviousEditableCharPoint() returns previous editable point in a
* LookForPreviousCharPointWithinAllTextNodes() are helper methods of * text node. Note that this returns last character point when it meets
* GetNextCharPoint(const EditorRawDOMPoint&) and GetPreviousCharPoint(const * non-empty text node, otherwise, returns a point in an empty text node.
* EditorRawDOMPoint&). When the container isn't in mNodeArray, they call one * FYI: For the performance, this does not check whether given container
* of these methods. Then, these methods look for nearest text node in * is not before mEndReasonContent or not.
* mNodeArray from aPoint. Then, will call GetNextCharPointFromPointInText()
* or GetPreviousCharPointFromPointInText() and returns its result.
*/ */
template <typename PT, typename CT> template <typename PT, typename CT>
EditorDOMPointInText LookForNextCharPointWithinAllTextNodes( EditorDOMPointInText GetPreviousEditableCharPoint(
const EditorDOMPointBase<PT, CT>& aPoint) const;
template <typename PT, typename CT>
EditorDOMPointInText LookForPreviousCharPointWithinAllTextNodes(
const EditorDOMPointBase<PT, CT>& aPoint) const; const EditorDOMPointBase<PT, CT>& aPoint) const;
nsresult GetWSNodes(); nsresult GetWSNodes();
@ -581,14 +575,6 @@ class MOZ_STACK_CLASS WSRunScanner {
nsIContent* GetEditableBlockParentOrTopmotEditableInlineContent( nsIContent* GetEditableBlockParentOrTopmotEditableInlineContent(
nsIContent* aContent) const; nsIContent* aContent) const;
/**
* GetPreviousCharPoint() and GetPreviousCharPointFromPointInText() return
* previous character's point of of aPoint. If there is no character before
* aPoint, mTextNode is set to nullptr.
*/
template <typename PT, typename CT>
EditorDOMPointInText GetPreviousCharPoint(
const EditorDOMPointBase<PT, CT>& aPoint) const;
EditorDOMPointInText GetPreviousCharPointFromPointInText( EditorDOMPointInText GetPreviousCharPointFromPointInText(
const EditorDOMPointInText& aPoint) const; const EditorDOMPointInText& aPoint) const;
@ -601,9 +587,6 @@ class MOZ_STACK_CLASS WSRunScanner {
WSFragment::StartOfHardLine aIsStartOfHardLine, WSFragment::StartOfHardLine aIsStartOfHardLine,
WSFragment::EndOfHardLine aIsEndOfHardLine); WSFragment::EndOfHardLine aIsEndOfHardLine);
// The list of nodes containing ws in this run.
nsTArray<RefPtr<dom::Text>> mNodeArray;
// The node passed to our constructor. // The node passed to our constructor.
EditorDOMPoint mScanStartPoint; EditorDOMPoint mScanStartPoint;
EditorDOMPoint mScanEndPoint; EditorDOMPoint mScanEndPoint;

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

@ -9,9 +9,6 @@
[[["insertlinebreak",""\]\] "<script>foo[\]bar</script>baz" compare innerHTML] [[["insertlinebreak",""\]\] "<script>foo[\]bar</script>baz" compare innerHTML]
expected: FAIL expected: FAIL
[[["insertlinebreak",""\]\] "<listing>foo[\]bar</listing>" compare innerHTML]
expected: FAIL
[[["insertlinebreak",""\]\] "<p>foo<span style=color:#aBcDeF>[bar\]</span>baz" compare innerHTML] [[["insertlinebreak",""\]\] "<p>foo<span style=color:#aBcDeF>[bar\]</span>baz" compare innerHTML]
expected: FAIL expected: FAIL

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

@ -1,357 +1,3 @@
[insertparagraph.html]
prefs: [editor.use_div_for_default_newlines:true]
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<table><tr><td>[foo<td>bar\]<tr><td>baz<td>quz</table>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<table><tr><td>[foo<td>bar\]<tr><td>baz<td>quz</table>" compare innerHTML]
expected: FAIL
[[["insertparagraph",""\]\] "<table><tbody data-start=0 data-end=1><tr><td>foo<td>bar<tr><td>baz<td>quz</table>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<table><tr><td>fo[o</table>b\]ar" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<table><tr><td>fo[o</table>b\]ar" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<table><tr><td>fo[o<td>b\]ar<td>baz</table>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<table><tr><td>fo[o<td>b\]ar<td>baz</table>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<table><tr><td>[foo\]</table>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<table><tr><td>[foo\]</table>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<span>foo[\]</span>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<span>foo[\]</span>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<script>foo[\]bar</script>baz" compare innerHTML]
expected: FAIL
[[["stylewithcss","true"\],["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<div style=display:none>foo[\]bar</div>baz" compare innerHTML]
expected: FAIL
[[["stylewithcss","false"\],["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<div style=display:none>foo[\]bar</div>baz" compare innerHTML]
expected: FAIL
[[["insertparagraph",""\]\] "<dl><dt>foo<dd>bar<dl><dt>{}<br><dd>baz</dl></dl>" compare innerHTML]
expected: FAIL
[[["insertparagraph",""\]\] "<dl><dt>foo<dd>bar<dl><dt>baz<dd>{}<br></dl></dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p>foo</p>{<h1>bar</h1>}<p>baz</p>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<p>foo</p>{<h1>bar</h1>}<p>baz</p>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<table><tr><td>foo[\]bar</table>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<table><tr><td>foo[\]bar</table>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<blockquote>[\]foo</blockquote>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<blockquote>[\]foo</blockquote>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<blockquote>foo[\]</blockquote>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<blockquote>foo[\]</blockquote>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<blockquote>foo[\]<br></blockquote>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<blockquote>foo[\]<br></blockquote>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<blockquote>foo[\]bar</blockquote>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<blockquote>foo[\]bar</blockquote>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "foo<b>[\]bar</b>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "foo<b>[\]bar</b>" compare innerHTML]
expected: FAIL
[[["stylewithcss","true"\],["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<b id=x class=y>foo[\]bar</b>" compare innerHTML]
expected: FAIL
[[["stylewithcss","false"\],["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<b id=x class=y>foo[\]bar</b>" compare innerHTML]
expected: FAIL
[[["stylewithcss","true"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<b id=x class=y>foo[\]bar</b>" compare innerHTML]
expected: FAIL
[[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<b id=x class=y>foo[\]bar</b>" compare innerHTML]
expected: FAIL
[[["stylewithcss","true"\],["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p><b id=x class=y>foo[\]bar</b></p>" compare innerHTML]
expected: FAIL
[[["stylewithcss","false"\],["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p><b id=x class=y>foo[\]bar</b></p>" compare innerHTML]
expected: FAIL
[[["stylewithcss","true"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<p><b id=x class=y>foo[\]bar</b></p>" compare innerHTML]
expected: FAIL
[[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<p><b id=x class=y>foo[\]bar</b></p>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p><b><a href=foo>foo[\]</a></b></p>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<div><b><a href=foo>foo[\]</a></b></div>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p><b><a href=foo>foo [\]<br></a></b></p>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<div><b><a href=foo>foo [\]<br></a></b></div>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p><b><a href=foo>foo {}<br></a></b></p>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<div><b><a href=foo>foo {}<br></a></b></div>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p><a href=foo>foo [\]<br><br></a></p>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<div><a href=foo>foo [\]<br><br></a></div>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p><a href=foo><b>foo [\]<br><br></b></a></p>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<div><a href=foo><b>foo [\]<br><br></b></a></div>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p><a href=foo><b>foo [\]<br></b><br></a></p>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<div><a href=foo><b>foo [\]<br></b><br></a></div>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p><a href=foo>foo {}<br><br></a></p>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<div><a href=foo>foo {}<br><br></a></div>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p><a href=foo><b>foo {}<br><br></b></a></p>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<div><a href=foo><b>foo {}<br><br></b></a></div>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p><a href=foo><b>foo {}<br></b><br></a></p>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<div><a href=foo><b>foo {}<br></b><br></a></div>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p>foo[\]<!--bar-->" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<p>foo[\]<!--bar-->" compare innerHTML]
expected: FAIL
[[["stylewithcss","true"\],["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p>[foo<span style=color:#aBcDeF>bar\]</span>baz" compare innerHTML]
expected: FAIL
[[["stylewithcss","false"\],["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p>[foo<span style=color:#aBcDeF>bar\]</span>baz" compare innerHTML]
expected: FAIL
[[["stylewithcss","true"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<p>[foo<span style=color:#aBcDeF>bar\]</span>baz" compare innerHTML]
expected: FAIL
[[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<p>[foo<span style=color:#aBcDeF>bar\]</span>baz" compare innerHTML]
expected: FAIL
[[["stylewithcss","true"\],["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p>{foo<span style=color:#aBcDeF>bar}</span>baz" compare innerHTML]
expected: FAIL
[[["stylewithcss","false"\],["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p>{foo<span style=color:#aBcDeF>bar}</span>baz" compare innerHTML]
expected: FAIL
[[["stylewithcss","true"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<p>{foo<span style=color:#aBcDeF>bar}</span>baz" compare innerHTML]
expected: FAIL
[[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<p>{foo<span style=color:#aBcDeF>bar}</span>baz" compare innerHTML]
expected: FAIL
[[["stylewithcss","true"\],["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p>foo<span style=color:#aBcDeF>[bar</span><span style=color:#fEdCbA>baz\]</span>quz" compare innerHTML]
expected: FAIL
[[["stylewithcss","false"\],["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p>foo<span style=color:#aBcDeF>[bar</span><span style=color:#fEdCbA>baz\]</span>quz" compare innerHTML]
expected: FAIL
[[["stylewithcss","true"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<p>foo<span style=color:#aBcDeF>[bar</span><span style=color:#fEdCbA>baz\]</span>quz" compare innerHTML]
expected: FAIL
[[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<p>foo<span style=color:#aBcDeF>[bar</span><span style=color:#fEdCbA>baz\]</span>quz" compare innerHTML]
expected: FAIL
[[["insertparagraph",""\]\] "<ul contenteditable><li>{}<br></ul>" compare innerHTML]
expected: FAIL
[[["insertparagraph",""\]\] "<div contenteditable=false><ul contenteditable><li>{}<br></ul></div>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<dl><dt><p>foo[\]</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<dl><dt><p>foo[\]</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<dl><dd><p>foo[\]</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<dl><dd><p>foo[\]</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<ol><li><p>foo[\]</ol>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<ol><li><p>foo[\]</ol>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<ul><li><p>foo[\]</ul>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<ul><li><p>foo[\]</ul>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<dl><dt><div>foo[\]</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<dl><dt><div>foo[\]</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<dl><dd><div>foo[\]</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<dl><dd><div>foo[\]</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<ol><li><div>foo[\]</ol>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<ol><li><div>foo[\]</ol>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<ul><li><div>foo[\]</ul>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<ul><li><div>foo[\]</ul>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<dl><dt><p>[\]foo</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<dl><dt><p>[\]foo</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<dl><dd><p>[\]foo</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<dl><dd><p>[\]foo</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<ol><li><p>[\]foo</ol>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<ol><li><p>[\]foo</ol>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<ul><li><p>[\]foo</ul>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<ul><li><p>[\]foo</ul>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<dl><dt><div>[\]foo</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<dl><dt><div>[\]foo</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<dl><dd><div>[\]foo</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<dl><dd><div>[\]foo</dl>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<ol><li><div>[\]foo</ol>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<ol><li><div>[\]foo</ol>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<ul><li><div>[\]foo</ul>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<ul><li><div>[\]foo</ul>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<ol><li class=a id=x><p class=b id=y>foo[\]</ol>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<ol><li class=a id=x><p class=b id=y>foo[\]</ol>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<ol><li class=a id=x><p class=b id=y>[\]foo</ol>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<ol><li class=a id=x><p class=b id=y>[\]foo</ol>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<ol><li class=a id=x><p class=b id=y>foo[\]bar</ol>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<ol><li class=a id=x><p class=b id=y>foo[\]bar</ol>" compare innerHTML]
expected: FAIL
[[["insertparagraph",""\]\] "<pre>foo[\]&#10;</pre>" compare innerHTML]
expected: FAIL
[[["insertparagraph",""\]\] "<xmp>foo[\]bar</xmp>" compare innerHTML]
expected: FAIL
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<script>foo[\]bar</script>baz" compare innerHTML]
expected: FAIL
[[["stylewithcss","true"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<div style=display:none>foo[\]bar</div>baz" compare innerHTML]
expected: FAIL
[[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<div style=display:none>foo[\]bar</div>baz" compare innerHTML]
expected: FAIL
[[["insertparagraph",""\]\] "<listing>foo[\]bar</listing>" compare innerHTML]
expected: FAIL
[insertparagraph - HTML editing conformance tests]
expected: FAIL
[insertparagraph.html?2001-3000] [insertparagraph.html?2001-3000]
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<blockquote><p>foo[\]<p>bar</blockquote>" compare innerHTML] [[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<blockquote><p>foo[\]<p>bar</blockquote>" compare innerHTML]
expected: FAIL expected: FAIL
@ -638,9 +284,6 @@
[[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<div style=display:none>foo[\]bar</div>baz" compare innerHTML] [[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<div style=display:none>foo[\]bar</div>baz" compare innerHTML]
expected: FAIL expected: FAIL
[[["insertparagraph",""\]\] "<listing>foo[\]bar</listing>" compare innerHTML]
expected: FAIL
[[["insertparagraph",""\]\] "<dl><dt>foo<dd>bar<dl><dt>{}<br><dd>baz</dl></dl>" compare innerHTML] [[["insertparagraph",""\]\] "<dl><dt>foo<dd>bar<dl><dt>{}<br><dd>baz</dl></dl>" compare innerHTML]
expected: FAIL expected: FAIL