Bug 1789967 - part 3: Make `HTMLEditor::CollapseSelectionToEndOfLastLeafNodeOfDocument` and `HTMLEditor::InitEditorContentAndSelection` do nothing if the document is partially editable r=m_kato

They and their callees work with the result of `GetRoot()` which is the document
element or the body element.  If the body is not editable, `Selection` should
not be updated in non-editable region nor `<br>` elements should not be
inserted in both non-focused editable elements and non-editable elements.
Therefore, they should run only when the document element or the `<body>`
element is editable.

To keep testing crashtests as reported, this patch makes tests which have
`contenteditable` except `<html>` and `<body>` initialize `Selection` as
what we've done.  And clean up the tests for helping to port them to WPT
in the future (bug 1725850).

Differential Revision: https://phabricator.services.mozilla.com/D157408
This commit is contained in:
Masayuki Nakano 2022-09-22 06:27:37 +00:00
Родитель b1f3f5e5af
Коммит a353ab7e90
63 изменённых файлов: 1005 добавлений и 578 удалений

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

@ -63,7 +63,7 @@
turnCaretBrowsing(true);
// test caret offsets
testCaretOffset(document, 15);
testCaretOffset(document, 0); // because of no selection ranges
testCaretOffset("textbox", -1);
testCaretOffset("textarea", -1);
testCaretOffset("p", -1);

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

@ -26,42 +26,67 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1101364
<pre id="test">
<script class="testbody" type="text/javascript">
async function test()
{
var iframe1 = document.getElementById('test1');
iframe1.focus();
var docShell = SpecialPowers.wrap(iframe1.contentWindow).docShell;
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(async () => {
await (async () => {
const iframe = document.getElementById("test1");
iframe.focus();
const docShell = SpecialPowers.wrap(iframe.contentWindow).docShell;
// test1
docShell.doCommand("cmd_selectAll");
var withoutContenteditable = await snapshotWindow(iframe1.contentWindow);
docShell.doCommand("cmd_selectAll");
info(
"Waiting for getting screenshot of \"Select All\" without contenteditable..."
);
const withoutContenteditable = await snapshotWindow(iframe.contentWindow);
iframe1.contentDocument.getElementById('testDiv').setAttribute('contentEditable', true);
docShell.doCommand("cmd_selectAll");
var withContenteditable = await snapshotWindow(iframe1.contentWindow);
dump(withoutContenteditable.toDataURL());
dump(withContenteditable.toDataURL());
iframe.contentDocument
.getElementById("testDiv")
.setAttribute("contentEditable", true);
docShell.doCommand("cmd_selectAll");
info(
"Waiting for getting screenshot of \"Select All\" in contenteditable..."
);
const withContenteditable = await snapshotWindow(iframe.contentWindow);
const result =
compareSnapshots(withoutContenteditable, withContenteditable, true);
ok(
result[0],
`Select all should look identical\ngot: ${
result[2]
}\nexpected: ${result[1]}`
);
})();
ok(compareSnapshots(withoutContenteditable, withContenteditable, true)[0], 'Select all should look identical');
await (async () => {
const iframe = document.getElementById("test2");
iframe.focus();
iframe.contentDocument.querySelector("div[contenteditable]").focus();
const docShell = SpecialPowers.wrap(iframe.contentWindow).docShell;
const test2Inner = iframe.contentDocument.getElementById("test2Inner");
test2Inner.style.MozUserSelect = "text";
docShell.doCommand("cmd_selectAll");
info(
"Waiting for getting screenshot of \"Select All\" in contenteditable (use-select: text)..."
);
const withoutUserSelect = await snapshotWindow(iframe.contentWindow);
// test2
var iframe2 = document.getElementById('test2');
iframe2.focus();
var docShell = SpecialPowers.wrap(iframe2.contentWindow).docShell;
var test2Inner = iframe2.contentDocument.getElementById('test2Inner');
test2Inner.style.MozUserSelect = 'text';
docShell.doCommand("cmd_selectAll");
var withoutUserSelect = await snapshotWindow(iframe2.contentWindow);
test2Inner.style.MozUserSelect = 'none';
docShell.doCommand("cmd_selectAll");
var withUserSelect = await snapshotWindow(iframe2.contentWindow);
ok(compareSnapshots(withoutUserSelect, withUserSelect, true)[0], 'Editable fields should ignore user select style');
test2Inner.style.MozUserSelect = "none";
docShell.doCommand("cmd_selectAll");
info(
"Waiting for getting screenshot of \"Select All\" in contenteditable (use-select: none)..."
);
const withUserSelect = await snapshotWindow(iframe.contentWindow);
const result = compareSnapshots(withoutUserSelect, withUserSelect, true);
ok(
result[0],
`Editable fields should ignore user select style\ngot: ${
result[2]
}\nexpected: ${result[1]}`
);
})();
SimpleTest.finish();
}
window.onload = function() { setTimeout(test, 0); };
SimpleTest.waitForExplicitFinish();
});
</script>
</pre>
</body>

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

@ -131,6 +131,12 @@ HTMLEditor::CreateRangeIncludingAdjuscentWhiteSpaces(
nsresult HTMLEditor::InitEditorContentAndSelection() {
MOZ_ASSERT(IsEditActionDataAvailable());
// We should do nothing with the result of GetRoot() if only a part of the
// document is editable.
if (!EntireDocumentIsEditable()) {
return NS_OK;
}
nsresult rv = MaybeCreatePaddingBRElementForEmptyEditor();
if (NS_FAILED(rv)) {
NS_WARNING(
@ -141,8 +147,8 @@ nsresult HTMLEditor::InitEditorContentAndSelection() {
// If the selection hasn't been set up yet, set it up collapsed to the end of
// our editable content.
// XXX I think that this shouldn't do it in `HTMLEditor` because it maybe
// removed by the web app and if they call `Selection::AddRange()`,
// it may cause multiple selection ranges.
// removed by the web app and if they call `Selection::AddRange()` without
// checking the range count, it may cause multiple selection ranges.
if (!SelectionRef().RangeCount()) {
nsresult rv = CollapseSelectionToEndOfLastLeafNodeOfDocument();
if (NS_FAILED(rv)) {
@ -154,6 +160,8 @@ nsresult HTMLEditor::InitEditorContentAndSelection() {
}
if (IsInPlaintextMode()) {
// XXX Should we do this in HTMLEditor? It's odd to guarantee that last
// empty line is visible only when it's in the plain text mode.
nsresult rv = EnsurePaddingBRElementInMultilineEditor();
if (NS_FAILED(rv)) {
NS_WARNING(

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

@ -733,6 +733,13 @@ bool HTMLEditor::IsInDesignMode() const {
return document && document->IsInDesignMode();
}
bool HTMLEditor::EntireDocumentIsEditable() const {
Document* document = GetDocument();
return document && document->GetDocumentElement() &&
(document->GetDocumentElement()->IsEditable() ||
(document->GetBody() && document->GetBody()->IsEditable()));
}
void HTMLEditor::CreateEventListeners() {
// Don't create the handler twice
if (!mEventListener) {
@ -807,6 +814,12 @@ NS_IMETHODIMP HTMLEditor::EndOfDocument() {
nsresult HTMLEditor::CollapseSelectionToEndOfLastLeafNodeOfDocument() const {
MOZ_ASSERT(IsEditActionDataAvailable());
// We should do nothing with the result of GetRoot() if only a part of the
// document is editable.
if (!EntireDocumentIsEditable()) {
return NS_OK;
}
RefPtr<Element> bodyOrDocumentElement = GetRoot();
if (NS_WARN_IF(!bodyOrDocumentElement)) {
return NS_ERROR_NULL_POINTER;

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

@ -667,10 +667,17 @@ class HTMLEditor final : public EditorBase,
}
/**
* Retruns true if we're in designMode.
* Return true if we're in designMode.
*/
bool IsInDesignMode() const;
/**
* Return true if entire the document is editable (although the document
* may have non-editable nodes, e.g.,
* <body contenteditable><div contenteditable="false"></div></body>
*/
bool EntireDocumentIsEditable() const;
/**
* Basically, this always returns true if we're for `contenteditable` or
* `designMode` editor in web apps. However, e.g., Composer of SeaMonkey

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

@ -2,21 +2,22 @@
<!-- saved from url=(0065)https://bug1134545.bugzilla.mozilla.org/attachment.cgi?id=8566418 -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<script>
function boom()
{
textNode = document.createTextNode(" ");
x.appendChild(textNode);
x.setAttribute('contenteditable', "true");
textNode.remove();
window.getSelection().selectAllChildren(textNode);
document.execCommand("increasefontsize", false, null);
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <body>, i.e., at the text node after the <div contenteditable>.
getSelection().collapse(document.body, document.body.childNodes.length);
const textNode = document.createTextNode(" ");
const editingHost = document.querySelector("div[contenteditable]");
editingHost.appendChild(textNode);
editingHost.setAttribute('contenteditable', "true");
textNode.remove();
getSelection().selectAllChildren(textNode);
document.execCommand("increasefontsize");
}
</script>
</head>
<body onload="boom();">
<div id="x" contenteditable="true"></div>
<body onload="onLoad();">
<div contenteditable></div>
</body></html>

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

@ -1,11 +1,14 @@
<body>
<table contenteditable="true"></table>
<table contenteditable></table>
</body>
<script>
window.onload = function() {
document.execCommand("useCSS", false, false);
document.designMode = 'on';
document.execCommand("insertunorderedlist", false);
document.execCommand("justifyfull", false);
// For emulating the traditional behavior, collapse Selection to end of the
// <body>, i.e., at the text node after the <table>.
getSelection().collapse(document.body, document.body.childNodes.length);
document.execCommand("styleWithCSS", false, false);
document.designMode = "on";
document.execCommand("insertUnorderedList");
document.execCommand("justifyFull");
};
</script>

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

@ -3,22 +3,25 @@
<head>
<meta charset="utf-8">
<script>
addEventListener('DOMContentLoaded', function(){
document.documentElement.className = 'lizard';
setTimeout(function(){
document.execCommand('selectAll', false, null);
document.designMode = 'on';
document.execCommand('removeformat', false, null);
}, 0);
addEventListener('DOMContentLoaded', () => {
// For emulating the traditional behavior, collapse Selection to end of the
// <body>, i.e., at the text node after the last invalid </span>.
getSelection().collapse(document.body, document.body.childNodes.length);
document.documentElement.className = 'lizard';
setTimeout(() => {
document.execCommand('selectAll');
document.designMode = 'on';
document.execCommand('removeformat');
}, 0);
});
</script>
<style>
.lizard{
-webkit-user-select:all;
.lizard {
-webkit-user-select: all;
}
*{
position:fixed;
display:table-column;
* {
position: fixed;
display: table-column;
}
</style>
</head>

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

@ -1,23 +1,60 @@
<html>
<head>
<script>
try { o1 = document.createElement('style'); } catch(e) { }
try { o2 = document.createElement('output') } catch(e) { }
try { o3 = document.createElement('input') } catch(e) { }
try { o4 = document.createElement('script'); } catch(e) { }
try { o5 = o2.cloneNode(false); } catch(e) { }
try { document.documentElement.appendChild(o1) } catch(e) { }
try { o1.outerHTML = '<a contenteditable=\'true\'>'; } catch(e) { }
try { document.documentElement.appendChild(o3) } catch(e) { }
try { o7 = document.createTextNode(' '); } catch(e) { }
try { o4.appendChild(o7) } catch(e) { }
try { document.documentElement.appendChild(o4) } catch(e) { }
try { o6 = window.getSelection() } catch(e) { }
try { o3.select() } catch(e) { }
try { document.replaceChild(document.documentElement, document.documentElement); } catch(e) { }
try { o6.setBaseAndExtent(o7, 0, o5, 0) } catch(e) { }
try { document.designMode = 'on'; } catch(e) { }
try { document.execCommand('insertimage', false, 'http://localhost/') } catch(e) { }
</script>
</head>
<head>
<script>
try {
var style = document.createElement("style");
} catch(e) {}
try {
var output = document.createElement("output");
} catch(e) {}
try {
var input = document.createElement("input");
} catch(e) {}
try {
var script = document.createElement("script");
} catch(e) {}
try {
var clonedOutput = output.cloneNode(false);
} catch(e) {}
try {
document.documentElement.appendChild(style);
} catch(e) {}
try {
style.outerHTML = '<a contenteditable="true">';
} catch(e) {}
// For emulating the traditional behavior, collapse Selection to end of the
// <body> which must be empty (<style> was added after the <body>).
getSelection().collapse(document.body, document.body.childNodes.length);
try {
document.documentElement.appendChild(input);
} catch(e) {}
try {
var text = document.createTextNode(" ");
} catch(e) {}
try {
script.appendChild(text);
} catch(e) {}
try {
document.documentElement.appendChild(script);
} catch(e) {}
try {
var selection = getSelection();
} catch(e) {}
try {
input.select();
} catch(e) {}
try {
document.replaceChild(document.documentElement, document.documentElement);
} catch(e) {}
try {
selection.setBaseAndExtent(text, 0, clonedOutput, 0);
} catch(e) {}
try {
document.designMode = "on";
} catch(e) {}
try {
document.execCommand("insertImage", false, "http://localhost/");
} catch(e) {}
</script>
</head>
</html>

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

@ -2,20 +2,28 @@
<html class="reftest-wait">
<head>
<script>
function load() {
document.getElementById("spacer").addEventListener("DOMNodeInserted", () => {
document.getElementById("style").appendChild(
document.getElementById("table"));
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <p> which is the deepest last child of the <body> (<spacer> can contain
// <p>).
getSelection().collapse(
document.querySelector("p"),
document.querySelector("p").childNodes.length
);
document.querySelector("spacer").addEventListener("DOMNodeInserted", () => {
document.querySelector("style").appendChild(
document.querySelector("table")
);
document.documentElement.classList.remove("reftest-wait");
});
document.execCommand("insertOrderedList", false);
document.execCommand("insertOrderedList");
}
</script>
</head>
<body onload="load()">
<table id="table"></table>
<style id="style"></style>
<spacer id="spacer" contenteditable="true">
<p id="p"></p>
<body onload="onLoad()">
<table></table>
<style></style>
<spacer contenteditable>
<p></p>
</body>
</html>

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

@ -1,15 +1,18 @@
<html>
<head>
<script type="application/javascript">
function do_test() {
document.execCommand("insertUnorderedList", false);
<script>
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <body>, i.e., at the text node after the <table>.
getSelection().collapse(document.body, document.body.childNodes.length);
document.execCommand("insertUnorderedList");
}
</script>
</head>
<body onload="do_test()">
<body onload="onLoad()">
<table>
<th contenteditable="true">
<ol contenteditable="false">
<th contenteditable>
<ol contenteditable>
</th>
</table>
</body>

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

@ -1,14 +1,24 @@
<script>
function jsfuzzer() {
try { var var00007 = eventhandler5; } catch(e) { }
try { var var00006 = var00007; } catch(e) { }
try { htmlvar00007.addEventListener("DOMNodeInserted", var00006); } catch(e) { }
try { document.execCommand("justifyFull", false); } catch(e) { }
}
function eventhandler5() {
try { htmlvar00008.replaceWith("1"); } catch(e) { }
function onLoad() {
const shadow = document.querySelector("shadow");
// For emulating the traditional behavior, collapse Selection to end of the
// <shadow> which is the deepest last child of the <body>.
getSelection().collapse(shadow, shadow.childNodes.length);
try {
document.querySelector("dd[contenteditable]").addEventListener(
"DOMNodeInserted",
() => {
try {
shadow.replaceWith("1");
} catch(e) {}
}
);
} catch(e) {}
try {
document.execCommand("justifyFull");
} catch(e) {}
}
</script>
<body onload=jsfuzzer()>
<dd id="htmlvar00007" contenteditable="true">
<shadow id="htmlvar00008">
<body onload="onLoad();">
<dd contenteditable>
<shadow>

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

@ -1,29 +1,36 @@
<script>
function jsfuzzer() {
var option = document.getElementById("option");
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// parent of <embed> (<embed> is not a container, therefore, its parent is the
// deepest last child container element of the <body>).
getSelection().collapse(
document.querySelector("embed").parentElement,
document.querySelector("embed").parentElement.childNodes.length
); // Point the <embed>
const option = document.querySelector("option");
option.addEventListener("click", () => {
document.execCommand("forwardDelete", false);
document.execCommand("forwardDelete");
});
var li2 = document.getElementById("li2");
const li2 = document.getElementById("li2");
li2.addEventListener("DOMNodeInserted", () => {
option.click();
});
var select = document.getElementById("select");
const select = document.querySelector("select");
select.parentElement.setAttribute("onpageshow", "onPageShow()");
}
function onPageShow() {
var li1 = document.getElementById("li1");
const li1 = document.getElementById("li1");
li1.addEventListener("DOMSubtreeModified", () => {
document.execCommand("selectAll", false);
document.execCommand("indent", false);
document.execCommand("selectAll");
document.execCommand("indent");
});
li1.appendChild(document.createElement("legend"));
}
</script>
<body onload=jsfuzzer()>
<select id="select">
<option id="option"></option>
<body onload="onLoad()">
<select>
<option></option>
</select>
<li id="li1"></li>
<ul contenteditable="true">

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

@ -1,23 +1,40 @@
<script>
var target;
function jsfuzzer() {
target = htmlvar00017; // Cache the target for removing the event handler.
try { target.addEventListener("DOMSubtreeModified", eventhandler5); } catch(e) { }
try { target.align = ""; } catch(e) { }
let th;
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <colgroup> which is the last child of the <body>.
getSelection().collapse(
document.querySelector("colgroup"),
document.querySelector("colgroup").childNodes.length
);
th = document.querySelector("th"); // Cache the target for removing the event handler.
try {
th.addEventListener("DOMSubtreeModified", onDOMSubtreeModified);
} catch(e) {}
try {
th.align = "";
} catch(e) {}
}
var count = 0;
function eventhandler5() {
if (count++ == 1) {
// If we didn't stop testing this, this event handler would be called too
// many times. It's enough to run twice to reproduce the bug report.
target.removeEventListener("DOMSubtreeModified", eventhandler5);
}
try { document.execCommand("selectAll", false); } catch(e) { }
try { document.execCommand("justifyCenter", false); } catch(e) { }
try { document.execCommand("forwardDelete", false); } catch(e) { }
let count = 0;
function onDOMSubtreeModified() {
if (count++ == 1) {
// If we didn't stop testing this, this event handler would be called too
// many times. It's enough to run twice to reproduce the bug report.
th.removeEventListener("DOMSubtreeModified", onDOMSubtreeModified);
}
try {
document.execCommand("selectAll");
} catch(e) {}
try {
document.execCommand("justifyCenter");
} catch(e) {}
try {
document.execCommand("forwardDelete");
} catch(e) {}
}
</script>
<body onload=jsfuzzer()>
<table contenteditable="">
<th id="htmlvar00017"></th>
<body onload="onLoad()">
<table contenteditable>
<th></th>
<colgroup>

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

@ -2,15 +2,22 @@
* { position: absolute; }
</style>
<script>
function jsfuzzer() {
del1.addEventListener("DOMSubtreeModified", () => {
document.execCommand("italic", false);
document.execCommand("selectAll", false);
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <iframe> which is the last child of the <body>. Note that <iframe> is
// treated as a container in HTMLEditor.
getSelection().collapse(document.body, document.body.childNodes.length);
document.querySelector("del").addEventListener("DOMSubtreeModified", () => {
document.execCommand("italic");
document.execCommand("selectAll");
});
a1.replaceChild(iframe1, a1.childNodes[0]);
document.querySelector("a[contenteditable]").replaceChild(
document.querySelector("iframe"),
document.querySelector("a[contenteditable]").childNodes[0]
);
}
</script>
<body onload=jsfuzzer()>
<a contenteditable="" id="a1">
<del id="del1">
<iframe id="iframe1">
<body onload="onLoad()">
<a contenteditable>
<del>
<iframe>

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

@ -1,20 +1,41 @@
<script>
function jsfuzzer() {
try { document.execCommand("insertUnorderedList", false); } catch(e) { }
try { document.execCommand("delete", false); } catch(e) { }
function onLoad() {
try {
document.execCommand("insertUnorderedList");
} catch(e) {}
try {
document.execCommand("delete");
} catch(e) {}
}
function eventhandler1() {
try { window.getSelection().collapse(htmlvar00001,1); } catch(e) { }
function onToggle1() {
try {
getSelection().collapse(
document.querySelector("font"),
1
);
} catch(e) {}
}
function eventhandler2() {
try { htmlvar00002.appendChild(htmlvar00001); } catch(e) { }
function onToggle2() {
// For emulating the traditional behavior, collapse Selection to end of the
// <summary> which is the last child of the <body>.
getSelection().collapse(
document.querySelector("summary"),
document.querySelector("summary").childNodes.length
);
try {
document.querySelector("label").appendChild(
document.querySelector("font")
);
} catch(e) {}
}
</script>
<body onload=jsfuzzer()>
<label id="htmlvar00002" contenteditable="true">
<details ontoggle="eventhandler2()" open="true">
<body onload="onLoad()">
<label contenteditable>
<details ontoggle="onToggle2()" open>
</details>
</label>
<details ontoggle="eventhandler1()" open="true">
<font id="htmlvar00001" dir="rtl">
<details ontoggle="onToggle1()" open>
<font dir="rtl">
<summary>

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

@ -1,17 +1,27 @@
<script>
function jsfuzzer() {
var var00043 = window.getSelection();
htmlvar00018.addEventListener("DOMNodeRemoved", eh1);
var00043.setPosition(htmlvar00016);
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <option> which is the last child of the <body>.
getSelection().collapse(
document.querySelector("option"),
document.querySelector("option").childNodes.length
);
document.querySelector("ins").addEventListener(
"DOMNodeRemoved",
onDOMNodeRemoved
);
getSelection().setPosition(
document.querySelector("shadow")
);
document.execCommand("insertText", false, "1");
}
function eh1() {
document.execCommand("insertHorizontalRule", false);
document.execCommand("justifyCenter", false);
function onDOMNodeRemoved() {
document.execCommand("insertHorizontalRule");
document.execCommand("justifyCenter");
}
</script>
<body onload=jsfuzzer()>
<li contenteditable="true">
<shadow id="htmlvar00016">
<ins id="htmlvar00018">
<body onload="onLoad()">
<li contenteditable>
<shadow>
<ins>
<option>

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

@ -1,13 +1,17 @@
<script>
function go() {
document.getElementById("label1").addEventListener("DOMNodeRemoved", () => {
document.getElementById("a1").innerText = "";
function onLoad() {
const label = document.querySelector("label");
// For emulating the traditional behavior, collapse Selection to end of the
// <label> which is the last child of the <body>, i.e., at the comment node.
getSelection().collapse(label, label.childNodes.length);
label.addEventListener("DOMNodeRemoved", () => {
document.querySelector("a").innerText = "";
});
document.execCommand("indent", false);
document.execCommand("indent");
}
</script>
<body onload=go()>
<li contenteditable="">
<a id="a1">
<label id="label1"></br>
<body onload="onLoad()">
<li contenteditable>
<a>
<label></br>
<!---

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

@ -1,15 +1,24 @@
<script>
function go() {
svgvar00002.addEventListener("DOMNodeInserted", () => {
svg.appendChild(svgvar00008);
function onLoad() {
const svg = document.querySelector("svg");
const feConvolveMatrix = document.querySelectorAll("feConvolveMatrix");
// For emulating the traditional behavior, collapse Selection to end of the
// last <svg> which is the deepest last child of the <body> (i.e., at the
// text node after the last <feConvolveMatrix>).
getSelection().collapse(svg, svg.childNodes.length);
feConvolveMatrix[0].addEventListener("DOMNodeInserted", () => {
svg.appendChild(feConvolveMatrix[1]);
document.execCommand("insertOrderedList", false);
});
svgvar00002.insertAdjacentHTML("afterBegin", table.outerHTML);
feConvolveMatrix[0].insertAdjacentHTML(
"afterBegin",
document.querySelector("table").outerHTML
);
}
</script>
<body onload=go()>
<table id="table"></table>
<b contenteditable="true">
<svg id="svg">
<feConvolveMatrix id="svgvar00002"/>
<feConvolveMatrix id="svgvar00008"/>
<body onload="onLoad()">
<table></table>
<b contenteditable>
<svg>
<feConvolveMatrix/>
<feConvolveMatrix/>

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

@ -1,29 +1,49 @@
<script>
function go() {
let selection = window.getSelection();
selection.setPosition(htmlvar00007, 1);
selection.setBaseAndExtent(htmlvar00011, 0, htmlvar00043, 0);
svgvar00014.before(svgvar00008.previousElementSibling);
function onLoad() {
const feComponentTransfer = document.querySelector("feComponentTransfer");
// For emulating the traditional behavior, collapse Selection to end of the
// <feComponentTransfer> which is the deepest last child of the <body>.
getSelection().collapse(
feComponentTransfer,
feComponentTransfer.childNodes.length
);
getSelection().setPosition(
document.querySelector("pre[contenteditable]"),
1
);
getSelection().setBaseAndExtent(
document.querySelector("fieldset"),
0,
document.querySelector("use"),
0
);
feComponentTransfer.before(
document.querySelector("font-face-uri").previousElementSibling
);
document.execCommand("removeFormat", false);
document.execCommand("removeFormat");
document.execCommand("hiliteColor", false, "-moz-buttondefault");
document.execCommand("insertText", false, "");
}
function eh1() {
svgvar00007.appendChild(htmlvar00011);
htmlvar00003.appendChild(htmlvar00035);
function onBegin() {
document.querySelector("desc").appendChild(
document.querySelector("fieldset")
);
document.querySelector("span").appendChild(
document.querySelector("a[hidden][contenteditable]")
);
}
</script>
<body onload=go()>
<span id="htmlvar00003">
<pre id="htmlvar00007" contenteditable="true">
<fieldset id="htmlvar00011"></fieldset>
<body onload="onLoad()">
<span>
<pre contenteditable>
<fieldset></fieldset>
<iframe srcdoc="H"></iframe>
<a id="htmlvar00035" hidden="hidden" contenteditable="true">
<a hidden contenteditable>
<svg>
<set onbegin="eh1()"/>
<use id="htmlvar00043">
<desc id="svgvar00007"></desc>
<set onbegin="onBegin()"/>
<use>
<desc></desc>
</use>
<font-face-uri id="svgvar00008"/>
<feComponentTransfer id="svgvar00014">
<font-face-uri/>
<feComponentTransfer>

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

@ -1,15 +1,20 @@
<script>
function go() {
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <body>, i.e., at the text node after the <meter>.
getSelection().collapse(document.body, document.body.childNodes.length);
document.scrollingElement.addEventListener("DOMNodeInserted", () => {
document.execCommand("selectAll", false);
document.execCommand("insertOrderedList", false);
document.execCommand("selectAll");
document.execCommand("insertOrderedList");
});
a.appendChild(document.createElement("e"));
document.querySelector("style").appendChild(
document.createElement("e")
);
}
</script>
<body onload=go()>
<meter contenteditable="true">
<body onload="onLoad()">
<meter contenteditable>
<dialog>
<style id="a"></style>
<style></style>
</dialog>
</meter>

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

@ -1,17 +1,26 @@
<script>
function go() {
a.setAttribute("contenteditable", "true");
b.addEventListener("DOMNodeRemoved", eh);
b.appendChild(c);
function onLoad() {
const pre = document.querySelector("pre[contenteditable]");
// For emulating the traditional behavior, collapse Selection to end of the
// <pre> which is the deepest last child of the <body>, i.e., at the text
// node after the <input>.
getSelection().collapse(pre, pre.childNodes.length);
document.querySelector("li").setAttribute("contenteditable", "true");
pre.addEventListener("DOMNodeRemoved", onDOMNodeRemoved);
pre.appendChild(
document.querySelector("input")
);
}
function eh() {
document.body.appendChild(b);
document.execCommand("justifyFull", false);
document.execCommand("delete", false);
function onDOMNodeRemoved() {
document.body.appendChild(
document.querySelector("pre[contenteditable]")
);
document.execCommand("justifyFull");
document.execCommand("delete");
}
</script>
<body onload=go()>
<li id="a">
<body onload="onLoad()">
<li>
A
<pre id="b" contenteditable="true">
<input autofocus="autofocus" id="c">
<pre contenteditable>
<input autofocus>

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

@ -2,9 +2,12 @@
input:focus { counter-increment: c; }
</style>
<script>
function go() {
a.select();
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <body>, i.e., at the text node after the <input contenteditable>.
getSelection().collapse(document.body, document.body.childNodes.length);
document.querySelector("input[type=number][contenteditable]").select();
}
</script>
<body onload=go()>
<input id="a" type="number" contenteditable="true">
<body onload="onLoad()">
<input type="number" contenteditable>

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

@ -1,8 +1,14 @@
<script>
function go() {
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <dialog> which is the deepest last child of the <body>.
getSelection().collapse(
document.querySelector("dialog"),
document.querySelector("dialog").childNodes.length
);
document.execCommand("insertImage", false, "o")
}
</script>
<body onload=go()>
<meter contenteditable="true">
<body onload="onLoad()">
<meter contenteditable>
<dialog>

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

@ -1,21 +1,27 @@
<script>
var count = 0;
function go() {
document.execCommand("delete", false);
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <s> which is the deepest last child (and a container) of the <body> (i.e.,
// at the the text node after the last comment node).
getSelection().collapse(
document.querySelector("s"),
document.querySelector("s").childNodes.length
);
document.execCommand("delete");
}
function eh() {
count++;
if (count >= 3) {
function onInputOrDOMNodeInserted() {
if (++count >= 3) {
return;
}
window.addEventListener("DOMNodeInserted", eh);
document.execCommand("removeFormat", false);
addEventListener("DOMNodeInserted", onInputOrDOMNodeInserted);
document.execCommand("removeFormat");
document.execCommand("insertText", false, "1");
}
</script>
<body onload=go()>
<ol oninput="eh()" contenteditable="true">
<body onload="onLoad()">
<ol oninput="onInputOrDOMNodeInserted()" contenteditable>
<!-- x -->
<s>
<!-- x -->

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

@ -1,14 +1,20 @@
<script>
function go() {
document.getSelection().setPosition(b);
a.addEventListener("DOMNodeInserted", eh);
function onLoad() {
const dd = document.querySelector("dd[contenteditable]");
// For emulating the traditional behavior, collapse Selection to end of the
// <dd contenteditable> which is the deepest last child of the <body> (at the
// text node after the <template>).
getSelection().collapse(dd, dd.childNodes.length);
getSelection().setPosition(
document.querySelector("template")
);
dd.addEventListener("DOMNodeInserted", () => {
document.execCommand("selectAll");
document.execCommand("insertText", false, "");
});
document.execCommand("insertImage", false, "#");
}
function eh() {
document.execCommand("selectAll", false);
document.execCommand("insertText", false, "");
}
</script>
<body onload=go()>
<dd id="a" contenteditable="true">
<template id="b"></template>
<body onload="onLoad()">
<dd contenteditable>
<template></template>

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

@ -2,16 +2,21 @@
abc
<head>
<script>
function start() {
document.execCommand('justifyleft', false, )
document.designMode = 'on'
document.execCommand('insertparagraph', false, )
}
document.addEventListener('DOMContentLoaded', start)
</script>
document.addEventListener('DOMContentLoaded', () => {
// For emulating the traditional behavior, collapse Selection to end of the
// <em> which is the deepest last child of the <body> (at the comment node).
getSelection().collapse(
document.querySelector("em[contenteditable]"),
document.querySelector("em[contenteditable]").childNodes.length
);
document.execCommand("justifyLeft");
document.designMode = 'on';
document.execCommand("insertParagraph");
});
</script>
</head>
<h4>
<em contenteditable="">
<em contenteditable>
<big>
<button autofocus formnovalidate formtarget="">
</button>

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

@ -1,19 +1,23 @@
<script>
function go() {
document.execCommand("styleWithCSS", false, true)
document.execCommand("delete", false)
a.addEventListener("DOMNodeRemoved", function() {
var c = window.getSelection()
var d = document.createRange()
d.setEndAfter(b)
c.addRange(d)
c.deleteFromDocument()
})
document.execCommand("outdent", false)
function onLoad() {
const button = document.querySelector("button");
// For emulating the traditional behavior, collapse Selection to end of the
// <button> which is the deepest last child of the <body>.
getSelection().collapse(button, button.childNodes.length);
document.execCommand("styleWithCSS", false, true);
document.execCommand("delete");
document.querySelector("ul[contenteditable]")
.addEventListener("DOMNodeRemoved", () => {
const range = document.createRange();
range.setEndAfter(button);
getSelection().addRange(range);
getSelection().deleteFromDocument();
});
document.execCommand("outdent");
}
</script>
<body onload=go()>
<ul id="a" contenteditable="true" style="margin: -1px 0px 1px 6px">
<body onload="onLoad()">
<ul contenteditable style="margin: -1px 0px 1px 6px">
<dd></dd>
<dd>
<button id="b">
<button>

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

@ -1,14 +1,19 @@
<script>
function go() {
document.execCommand("justifyFull", false)
document.execCommand("selectAll", false)
window.top.addEventListener("DOMNodeRemoved", eh)
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <dd contenteditable> which is the last child of the <body>.
getSelection().collapse(
document.querySelector("dd[contenteditable]"),
document.querySelector("dd[contenteditable]").childNodes.length
);
document.execCommand("justifyFull");
document.execCommand("selectAll");
window.top.addEventListener("DOMNodeRemoved", () => {
document.execCommand("insertHTML", false, undefined)
});
document.execCommand("heading", false, "H1")
}
function eh() {
document.execCommand("insertHTML", false, undefined)
}
</script>
<body onload=go()>
<dd contenteditable="true">A
<body onload="onLoad()">
<dd contenteditable>A
<!-- A -->

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

@ -1,16 +1,21 @@
<html>
<head>
<script>
function start () {
const selection = window.getSelection()
selection.setPosition(hr, 0)
document.execCommand('delete', false)
}
</script>
<body onload="start()">
<p id="" hidden="">
<canvas id="" contenteditable="">
<hr id="hr" contenteditable="true">
<script>
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <body> (at the text node after the <p hidden>).
getSelection().collapse(document.body, document.body.childNodes.length);
getSelection().setPosition(
document.querySelector("hr"),
0
);
document.execCommand("delete");
}
</script>
<body onload="onLoad()">
<p hidden>
<canvas contenteditable>
<hr contenteditable>
3uW4*</hr></canvas>
</p>
</body>

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

@ -1,11 +1,19 @@
<script>
function go() {
document.getSelection().selectAllChildren(a)
document.execCommand("insertUnorderedList", false)
document.execCommand("enableObjectResizing", false)
function onError() {
// For emulating the traditional behavior, collapse Selection to end of the
// <dl> which is the last deepest child of the <body>.
getSelection().collapse(
document.querySelector("dl"),
document.querySelector("dl").childNodes.length
);
getSelection().selectAllChildren(
document.querySelector("img")
);
document.execCommand("insertUnorderedList");
document.execCommand("enableObjectResizing");
}
</script>
<dd contenteditable="true">
<audio src="data:text/html,foo" onerror="go()">
<img id="a"></img>
<audio src="data:text/html,foo" onerror="onError()">
<img></img>
<dl>

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

@ -3,10 +3,16 @@
body { display: contents }
</style>
<script>
function go() {
document.execCommand("enableInlineTableEditing", false)
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <th> which is the deepest last child of the <body>.
getSelection().collapse(
document.querySelector("th"),
document.querySelector("th").childNodes.length
);
document.execCommand("enableInlineTableEditing");
}
</script>
<body onload=go()>
<table contenteditable="true">
<body onload="onLoad()">
<table contenteditable>
<th>

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

@ -1,15 +1,28 @@
<script>
function go() {
b.appendChild(document.body.firstChild)
document.getSelection().setBaseAndExtent(c.appendChild(b),0,b,1)
a.addEventListener("DOMCharacterDataModified", function() {
window.getSelection().removeAllRanges()
})
document.execCommand("delete", false)
function onLoad() {
const data = document.querySelector("data");
const source = document.querySelector("source");
// For emulating the traditional behavior, collapse Selection to end of the
// <data> which is the deepest last child (and a container) of the <body>.
getSelection().collapse(data, data.childNodes.length);
source.appendChild(
document.body.firstChild // The invisible text node
);
getSelection().setBaseAndExtent(
data.appendChild(source),
0,
source,
1
);
document.querySelector("audio")
.addEventListener("DOMCharacterDataModified", () => {
getSelection().removeAllRanges()
});
document.execCommand("delete");
}
</script>
<body onload=go()>
<audio id="a">
<li contenteditable="true">
<data id="c">
<source id="b">
<body onload="onLoad()">
<audio>
<li contenteditable>
<data>
<source>

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

@ -1,19 +1,40 @@
<html id="a"><script type="text/javascript" id="__gaOptOutExtension">window["_gaUserPrefs"] = { ioo : function() { return true; } }</script><head>
<meta http-equiv="content-type" content="text/html; charset=windows-1252"><script>
function go() {
b.addEventListener("DOMCharacterDataModified", () => {
a.appendChild(b)
})
document.execCommand("delete", false)
<html><script>
window["_gaUserPrefs"] = { ioo : function() { return true; } }
</script><head>
<meta charset="windows-1252"><script>
function onLoad() {
const form = document.querySelector("form");
form.addEventListener("DOMCharacterDataModified", () => {
document.documentElement.appendChild(form);
});
document.execCommand("delete");
}
function eh() {
b.reset()
function onToggle() {
// For emulating the traditional behavior, collapse Selection to end of the
// <button> which is the deepest last child of the <body>.
getSelection().collapse(
document.querySelector("button"),
document.querySelector("button").childNodes.length
);
document.querySelector("form").reset();
}
</script>
</head><body onload="go()">
<details ontoggle="eh()" open="">
<dt contenteditable="">
</head><body onload="onLoad()">
<details ontoggle="onToggle()" open>
<dt contenteditable>
</dt>
</details><aside style="position: fixed; top: 0px; right: 0px; font-family: &quot;Lucida Console&quot;, monospace; background-color: rgb(242, 230, 217); padding: 3px; z-index: 10000; text-align: center; max-width: 120px; opacity: 0; transition: opacity 0.5s linear 0s;">1194 x 73</aside></body><form id="b"><keygen>
<button autofocus="">
</details><aside style="
position: fixed;
top: 0px;
right: 0px;
font-family: &quot;Lucida Console&quot;, monospace;
background-color: rgb(242, 230, 217);
padding: 3px;
z-index: 10000;
text-align: center;
max-width: 120px;
opacity: 0;
transition: opacity 0.5s linear 0s;">1194 x 73</aside></body><form id="b"><keygen>
<button autofocus>
</button></form></html>

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

@ -1,11 +1,19 @@
<script id="a">
function go() {
a.appendChild(b)
document.execCommand("indent", false)
document.execCommand("delete", false)
<script>
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <textarea> which is the last child of the <body>.
getSelection().collapse(
document.querySelector("textarea"),
document.querySelector("textarea").childNodes.length
);
document.querySelector("script").appendChild(
document.querySelector("li[contenteditable=false]")
);
document.execCommand("indent");
document.execCommand("delete");
}
</script>
<body onload=go()>
<ul contenteditable="true">
<li id="b" contenteditable="false">
<body onload="onLoad()">
<ul contenteditable>
<li contenteditable="false">
<textarea autofocus>

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

@ -1,9 +1,13 @@
<script>
window.onload = () => {
a.addEventListener("DOMNodeRemoved", () => {
document.getSelection().collapse(document.getElementById(""))
})
document.execCommand("delete", false)
}
addEventListener("load", () => {
const editingHost = document.querySelector("div[contenteditable]");
// For emulating the traditional behavior, collapse Selection to end of the
// <div contenteditable> which is the last child of the <body>.
getSelection().collapse(editingHost, editingHost.childNodes.length);
editingHost.addEventListener("DOMNodeRemoved", () => {
getSelection().collapse(null);
});
document.execCommand("delete");
});
</script>
<div id="a" contenteditable>x</link>
<div contenteditable>x</link>

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

@ -1,17 +1,20 @@
<html>
<head>
<script>
document.addEventListener('DOMContentLoaded', () => {
const br = document.getElementById('id_29')
br.contentEditable = true
document.execCommand('indent', false, null)
})
</script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const code = document.querySelector("code[contenteditable=false]");
// For emulating the traditional behavior, collapse Selection to end of the
// <code> which is the last inline container of the <body>.
getSelection().collapse(code, code.childNodes.length);
code.querySelector("br").contentEditable = true;
document.execCommand("indent");
});
</script>
<body>
<b class='' contenteditable='true' hidden>
<script class=''></script>
<code class='' contenteditable='false'>
<br class='' id='id_29'>
<b contenteditable hidden>
<script></script>
<code contenteditable="false">
<br>
</body>
</head>
</html>

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

@ -1,23 +1,27 @@
<html>
<head>
<script>
window.addEventListener('load', () => {
const el_0 = document.createElement('a')
const el_1 = document.createElement('b')
const el_2 = document.createElement('c')
document.documentElement.appendChild(el_0)
el_0.appendChild(el_1)
el_1.setAttribute('contenteditable', 'true')
el_1.appendChild(el_2)
el_2.outerHTML = '<s contenteditable=\'false\'><b contenteditable=\'true\'>'
const selection = self.getSelection()
selection.setBaseAndExtent(document, 0, document.documentElement, 0)
const range = selection.getRangeAt((260523900 % selection.rangeCount))
selection.selectAllChildren(el_1)
range.collapse(false)
range.setEndAfter(document.documentElement)
range.extractContents()
})
</script>
<script>
addEventListener("load", () => {
const anchor = document.createElement("a");
const b = document.createElement("b");
const c = document.createElement("c");
document.documentElement.appendChild(anchor);
anchor.appendChild(b);
b.setAttribute("contenteditable", "true");
// For emulating the traditional behavior, collapse Selection to end of the
// <body> which must be empty because this test appends the new elements after
// the <body>.
const selection = self.getSelection();
selection.collapse(document.body, document.body.childNodes.length);
b.appendChild(c);
c.outerHTML = '<s contenteditable="false"><b contenteditable="true">';
selection.setBaseAndExtent(document, 0, document.documentElement, 0);
const range = selection.getRangeAt((260523900 % selection.rangeCount));
selection.selectAllChildren(b);
range.collapse(false);
range.setEndAfter(document.documentElement);
range.extractContents();
});
</script>
</head>
</html>

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

@ -1,14 +1,17 @@
<script>
window.onload = () => {
document.execCommand("undo", false)
document.execCommand("undo");
}
function go() {
var a = document.getElementById("a")
document.execCommand("delete", false)
b.contentDocument.adoptNode(a)
function onToggle() {
// For emulating the traditional behavior, collapse Selection to end of the
// <body> (at the text node after the <iframe>).
getSelection().collapse(document.body, document.body.childNodes.length);
const link = document.querySelector("link");
document.execCommand("delete");
document.querySelector("iframe").contentDocument.adoptNode(link);
}
</script>
<p contenteditable="true">
<link id="a" item="">
<details open="" ontoggle="go()">
<iframe id="b"></iframe>
<p contenteditable>
<link item="">
<details open ontoggle="onToggle()">
<iframe></iframe>

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

@ -1,8 +1,10 @@
<div contenteditable>&nbsp;a</div>
<script>
let editor = document.querySelector("div[contenteditable]");
editor.insertBefore(document.createTextNode(""), editor.firstChild);
let selection = getSelection();
selection.collapse(editor.firstChild.nextSibling, 2);
document.execCommand("delete", false);
// For emulating the traditional behavior, collapse Selection to end of the
// <body>, i.e., at the text node after this <script>.
getSelection().collapse(document.body, document.body.childNodes.length);
const editingHost = document.querySelector("div[contenteditable]");
editingHost.insertBefore(document.createTextNode(""), editingHost.firstChild);
getSelection().collapse(editingHost.firstChild.nextSibling, 2);
document.execCommand("delete");
</script>

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

@ -1,7 +1,10 @@
<!doctype html>
<div contenteditable>abc<span></span><span></span></div>
<script>
let editor = document.querySelector("div[contenteditable]");
getSelection().collapse(editor, 3);
document.execCommand("inserttext", false, " ");
// For emulating the traditional behavior, collapse Selection to end of the
// <body>, i.e., at the text node after this <script>.
getSelection().collapse(document.body, document.body.childNodes.length);
const editingHost = document.querySelector("div[contenteditable]");
getSelection().collapse(editingHost, 3);
document.execCommand("insertText", false, " ");
</script>

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

@ -1,19 +1,29 @@
<script>
window.addEventListener('load', () => {
const map = document.getElementById('id_2')
const anchor = document.getElementById('id_9')
map.replaceChild(anchor, map.childNodes[(2828994049 % map.childNodes.length)])
anchor.innerHTML = '<o>'
const selection = self.getSelection()
selection.setBaseAndExtent(document, (2019424593 % document.childNodes.length), document.documentElement, (3503355750 % document.documentElement.childNodes.length))
document.designMode = 'on'
document.execCommand('forwardDelete', false, null)
document.execCommand('forwardDelete', false, null)
})
window.addEventListener('load', () => {
// For emulating the traditional behavior, collapse Selection to end of the
// <body> (at the comment node).
getSelection().collapse(document.body, document.body.childNodes.length);
const map = document.querySelector("map");
const anchor = document.querySelector("a");
map.replaceChild(
anchor,
map.childNodes[(2828994049 % map.childNodes.length)]
);
anchor.innerHTML = "<o>";
getSelection().setBaseAndExtent(
document,
(2019424593 % document.childNodes.length),
document.documentElement,
(3503355750 % document.documentElement.childNodes.length)
);
document.designMode = "on";
document.execCommand("forwardDelete");
document.execCommand("forwardDelete");
});
</script>
<sub contenteditable='true'>
<map id='id_2'>
<sub contenteditable>
<map>
<address></address>
<a id='id_9'>
<a>
</a>
<!-- COMMENT -->

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

@ -1,27 +1,30 @@
<html>
<head>
<script>
document.addEventListener('DOMContentLoaded', () => {
let node
const textarea = document.getElementById('id_14')
const abbr = document.getElementById('id_9')
document.addEventListener('DOMAttrModified', (e) => {
node = e.originalTarget.getRootNode({})
abbr.insertBefore(textarea, abbr.childNodes[0])
}, false)
abbr.contentEditable = false
node.normalize()
document.designMode = 'on'
document.execCommand('insertParagraph', false, null)
})
</script>
<script>
document.addEventListener("DOMContentLoaded", () => {
// For emulating the traditional behavior, collapse Selection to end of the
// <body> (at the text node after the <h3>).
getSelection().collapse(document.body, document.body.childNodes.length);
const textarea = document.querySelector("textarea");
const abbr = document.querySelector("abbr");
let node;
document.addEventListener("DOMAttrModified", event => {
node = event.originalTarget.getRootNode({});
abbr.insertBefore(textarea, abbr.childNodes[0]);
}, false);
abbr.contentEditable = false;
node.normalize();
document.designMode = "on";
document.execCommand("insertParagraph");
});
</script>
</head>
<body>
<dfn contenteditable='true'>
<abbr id='id_9'></abbr>
<dfn contenteditable>
<abbr></abbr>
</dfn>
<h3>
<textarea id='id_14' autofocus></textarea>
<textarea autofocus></textarea>
<script></script>
</h3>
</body>

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

@ -1,21 +1,24 @@
<html>
<head>
<script>
document.addEventListener('DOMContentLoaded', () => {
const element_0 = document.getElementById('id_0')
const element_1 = document.getElementById('id_1')
element_1.after('foo')
element_0.addEventListener('DOMAttrModified', () => {
window.find('foo')
document.execCommand('insertImage', false, '#')
})
element_0.setAttribute('i', '')
})
</script>
<script>
document.addEventListener("DOMContentLoaded", () => {
// For emulating the traditional behavior, collapse Selection to end of the
// <body> (at the text node after the <feDistantLight>).
getSelection().collapse(document.body, document.body.childNodes.length);
const feDistantLight = document.querySelector("feDistantLight");
const li = document.querySelector("li");
li.after('foo');
feDistantLight.addEventListener("DOMAttrModified", () => {
window.find("foo");
document.execCommand("insertImage", false, "#");
})
feDistantLight.setAttribute("i", "");
});
</script>
</head>
<body>
<feDistantLight id="id_0" contenteditable="true">
<li id="id_1">A</li>
<feDistantLight contenteditable>
<li>A</li>
<!-- COMMENT -->
</feDistantLight>
</body>

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

@ -1,13 +1,18 @@
<script>
window.onload = () => {
document.execCommand("insertHorizontalRule", false)
window.getSelection().collapse(b)
document.execCommand("forwardDelete", false)
// For emulating the traditional behavior, collapse Selection to end of the
// <body> (at the text node after the <input>).
getSelection().collapse(document.body, document.body.childNodes.length);
document.execCommand("insertHorizontalRule");
getSelection().collapse(
document.querySelector("b")
);
document.execCommand("forwardDelete");
}
function go() {
document.getSelection().setPosition(a)
function onFocusChangeOfInput() {
document.getSelection().setPosition(document.querySelector("pre"));
}
</script>
<pre id="a">
<pre>
<time contenteditable>a|</t>
<input id="b" onfocus="go()" autofocus onblur="go()">
<input onfocus="onFocusChangeOfInput()" autofocus onblur="onFocusChangeOfInput()">

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

@ -1,19 +1,28 @@
<script>
function func_a() {
a.appendChild(b)
document.execCommand("indent", false)
function onError() {
document.querySelector("details").appendChild(
document.querySelector("p")
);
document.execCommand("indent");
}
function func_b() {
document.execCommand("delete", false)
a.contentEditable = "true"
c.select()
function onLoadOfStyle() {
document.execCommand("delete");
document.querySelector("details").contentEditable = "true";
// For emulating the traditional behavior, collapse Selection to end of the
// <style>.
getSelection().collapse(
document.querySelector("style"),
document.querySelector("style").childNodes.length
);
document.querySelector("input").select();
}
</script>
<video focus="false">
<source onerror="func_a()">
<source onerror="onError()">
</video>
<details id="a" open="tru">
<p id="b">
<input id="c" contenteditable="pla">
<style onload="func_b()">
<details open>
<p>
<input contenteditable="false">
<style onload="onLoadOfStyle()">
<!-- x -->

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

@ -1,24 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<script>
document.addEventListener('DOMContentLoaded', () => {
const table = document.getElementById('id_39')
const paragraph = document.getElementById('id_41')
document.documentElement.contentEditable = true
const selection = document.getSelection()
selection.setBaseAndExtent(document, 0, document.documentElement, 1)
paragraph.contentEditable = false
table.insertRow(0)
document.execCommand('forwardDelete', false, null)
})
</script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const table = document.querySelector("table");
// For emulating traditional behavior, collapse Selection to end of the
// <table>.
getSelection().collapse(table, table.childNodes.length);
const paragraph = document.querySelector("p");
document.documentElement.contentEditable = true;
getSelection().setBaseAndExtent(document, 0, document.documentElement, 1);
paragraph.contentEditable = false;
table.insertRow(0);
document.execCommand("forwardDelete");
});
</script>
</head>
<p id='id_41'>
<p>
<del>
<button contenteditable='true'>
<button contenteditable>
</button>
<table id='id_39'>
<table>
</table>
</del>
</p>

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

@ -1,13 +1,21 @@
<script>
window.onload = () => {
b.style.setProperty("text-decoration", "overline underline line-through")
b.appendChild(a)
document.execCommand("selectAll", false)
window.getSelection().extend(b, 0)
document.execCommand("underline", false)
const font = document.querySelector("font");
// For emulating traditional behavior, collapse Selection to end of the
// <font>.
getSelection().collapse(font, font.childNodes.length);
const meta = document.querySelector("meta");
meta.style.setProperty(
"text-decoration",
"overline underline line-through"
);
meta.appendChild(font);
document.execCommand("selectAll");
getSelection().extend(meta, 0);
document.execCommand("underline");
}
</script>
<ins contenteditable="true">
<ins contenteditable>
a
<meta id="b"></meta>
<font id="a">
<meta></meta>
<font>

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

@ -1,20 +1,21 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
function boom()
{
document.getElementsByTagName("td")[0].contentEditable = "true";
document.getElementsByTagName("td")[0].focus();
function onLoad() {
document.querySelector("td").contentEditable = "true";
getSelection().collapse(
document.querySelector("td"),
document.querySelector("td").childNodes.length
);
document.querySelector("td").focus();
document.documentElement.contentEditable = "true";
document.documentElement.focus();
document.execCommand("indent", false, null);
document.execCommand("insertParagraph", false, null);
document.execCommand("indent");
document.execCommand("insertParagraph");
}
</script>
</head>
<body onload="boom();" contenteditable="false"><td></td></body>
<body onload="onLoad();" contenteditable="false"><td></td></body>
</html>

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

@ -2,18 +2,18 @@
<head contenteditable="true">
<script type="text/javascript">
<![CDATA[
function boom()
{
var r = document.createRange();
function onLoad() {
getSelection().collapse(document.body, document.body.childNodes.length);
const r = document.createRange();
r.selectNode(document.body);
r.deleteContents();
try { document.execCommand("selectAll", false, null); } catch(e) { }
try {
document.execCommand("selectAll");
} catch(e) {}
}
]]>
</script>
</head>
<body onload="boom();" contenteditable="true"></body>
<body onload="onLoad();" contenteditable="true"></body>
</html>

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

@ -1,15 +1,17 @@
<html xmlns="http://www.w3.org/1999/xhtml"><head><script>
<![CDATA[
function boom()
{
document.execCommand("selectAll", false, null);
document.execCommand("selectAll", false, null);
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <textarea> which is the deepest last child of the <body>.
getSelection().collapse(
document.querySelector("textarea"),
document.querySelector("textarea").childNodes.length
);
document.execCommand("selectAll");
document.execCommand("selectAll");
document.execCommand("inserthtml", false, "<span><div>");
var textarea = document.getElementById("textarea");
var span = document.createElementNS("http://www.w3.org/1999/xhtml", "span");
textarea.appendChild(span);
const span = document.createElementNS("http://www.w3.org/1999/xhtml", "span");
document.querySelector("textarea").appendChild(span);
}
]]>
</script></head><div contenteditable="true"></div><body onload="boom();"><textarea id="textarea">f</textarea></body></html>
</script></head><div contenteditable="true"></div><body onload="onLoad();"><textarea>f</textarea></body></html>

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

@ -1,35 +1,67 @@
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
<body><div contenteditable="true"></div><div><input id="i"><div></div></input></div></body>
<body><div contenteditable="true"></div><div><input><div></div></input></div></body>
<script id="s">
<script>
<![CDATA[
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// parent <div> of the <input>. In XHTML document, the <input> may have the
// <div> child. Therefore, the deepest last child container element of the
// <body> is the parent of the <input>.
getSelection().collapse(
document.querySelector("input").parentElement,
document.querySelector("input").parentElement.childNodes.length
);
document.querySelector("input").focus();
function boom()
{
document.getElementById("i").focus();
try {
document.execCommand("stylewithcss", false, "true");
} catch(e) {}
try {
document.execCommand("inserthtml", false, "<x>X</x>");
} catch(e) {}
try {
document.execCommand("underline");
} catch(e) {}
try {
document.execCommand("justifyfull");
} catch(e) {}
try {
document.execCommand("underline");
} catch(e) {}
try {
document.execCommand("insertParagraph");
} catch(e) {}
try {
document.execCommand("delete");
} catch(e) {}
try { document.execCommand("stylewithcss", false, "true") } catch(e) { }
try { document.execCommand("inserthtml", false, "<x>X</x>"); } catch(e) { }
try { document.execCommand("underline", false, null); } catch(e) { }
try { document.execCommand("justifyfull", false, null); } catch(e) { }
try { document.execCommand("underline", false, null); } catch(e) { }
try { document.execCommand("insertParagraph", false, null); } catch(e) { }
try { document.execCommand("delete", false, null); } catch(e) { }
try { document.execCommand("stylewithcss", false, "false") } catch(e) { }
try { document.execCommand("inserthtml", false, "<x>X</x>"); } catch(e) { }
try { document.execCommand("underline", false, null); } catch(e) { }
try { document.execCommand("justifyfull", false, null); } catch(e) { }
try { document.execCommand("underline", false, null); } catch(e) { }
try { document.execCommand("insertParagraph", false, null); } catch(e) { }
try { document.execCommand("delete", false, null); } catch(e) { }
try {
document.execCommand("stylewithcss", false, "false");
} catch(e) {}
try {
document.execCommand("inserthtml", false, "<x>X</x>");
} catch(e) {}
try {
document.execCommand("underline");
} catch(e) {}
try {
document.execCommand("justifyfull");
} catch(e) {}
try {
document.execCommand("underline");
} catch(e) {}
try {
document.execCommand("insertParagraph");
} catch(e) {}
try {
document.execCommand("delete");
} catch(e) {}
document.documentElement.removeAttribute("class");
}
setTimeout(boom, 10);
addEventListener("load", onLoad);
]]>
</script>

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

@ -1,14 +1,19 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script>
function boom()
{
try { document.execCommand("removeformat", false, null); } catch(e) { }
function onLoad() {
// For emulating the traditional behavior, collapse Selection to end of the
// <td> which is the deepest last child of the <body>.
getSelection().collapse(
document.querySelector("td"),
document.querySelector("td").childNodes.length
);
try {
document.execCommand("removeformat");
} catch(e) {}
document.adoptNode(document.documentElement);
}
</script>
</head>
<body onload="boom();"><td contenteditable="true" /></body>
<body onload="onLoad();"><td contenteditable="true"/></body>
</html>

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

@ -2,19 +2,20 @@
<html>
<head>
<script>
function boom()
{
window.getSelection().removeAllRanges();
var r = document.createRange();
r.setStart(document.getElementById("x"), 1);
r.setEnd(document.getElementById("y"), 0);
window.getSelection().addRange(r);
document.execCommand("insertorderedlist", false, null);
function onLoad() {
const editingHost = document.querySelectorAll("div[contenteditable]");
// For emulating the traditional behavior, collapse Selection to end of the
// last <div contenteditable> which is the deepest last child of the <body>.
getSelection().collapse(editingHost[1], editingHost[1].childNodes.length);
getSelection().removeAllRanges();
const r = document.createRange();
r.setStart(editingHost[0], 1);
r.setEnd(editingHost[1], 0);
getSelection().addRange(r);
document.execCommand("insertOrderedList");
}
</script>
</head>
<body onload="boom();"><div id="x" contenteditable="true">a</div><div id="y" contenteditable="true"></div></body>
<body onload="onLoad();"><div contenteditable>a</div><div contenteditable></div></body>
</html>

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

@ -37,23 +37,25 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1268736
function getEditor() {
const Ci = SpecialPowers.Ci;
var editingSession = SpecialPowers.wrap(window).docShell.editingSession;
const editingSession = SpecialPowers.wrap(window).docShell.editingSession;
return editingSession.getEditorForWindow(window).QueryInterface(Ci.nsITableEditor);
}
var table = document.getElementById("table");
var tableHTML = table.innerHTML;
var editor = getEditor();
const table = document.getElementById("table");
const tableHTML = table.innerHTML;
const editor = getEditor();
var cell = document.getElementById("cell_readonly");
cell.focus();
editor.deleteTableCellContents();
const readOnlyCell = document.getElementById("cell_readonly");
readOnlyCell.focus();
try {
editor.deleteTableCellContents();
} catch (e) {}
is(table.innerHTML == tableHTML, true, "editor should not modify non-editable table cell" );
cell = document.getElementById("cell_writable");
cell.focus();
const editableCell = document.getElementById("cell_writable");
editableCell.focus();
editor.deleteTableCellContents();
is(cell.innerHTML == "<br>", true, "editor can modify editable table cells" );
is(editableCell.innerHTML == "<br>", true, "editor can modify editable table cells" );
</script>
</body>

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

@ -85,10 +85,7 @@ SimpleTest.waitForFocus(() => {
const otherEditor = document.getElementById("otherEditor");
(function test_initial_state_on_load() {
// XXX if there is a contenteditable element, HTML editor sets dom selection
// to first editable node, but this makes inconsistency with normal document
// behavior.
todo_is(
is(
getSelection().rangeCount,
0,
"There should be no selection range at start"

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

@ -29,9 +29,7 @@
if (done)
return;
try {
var r = window.getSelection().getRangeAt(0);
r.setStart(p.childNodes[0],14);
r.setEnd(p.childNodes[0],14);
getSelection().collapse(p.childNodes[0], 14);
} catch (e) {}
document.documentElement.removeAttribute('class');
done = true;

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

@ -28,9 +28,7 @@
if (done)
return;
try {
var r = window.getSelection().getRangeAt(0);
r.setStart(p.childNodes[0],14);
r.setEnd(p.childNodes[0],14);
getSelection().collapse(p.childNodes[0], 14);
} catch (e) {}
document.documentElement.removeAttribute('class');
done = true;

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

@ -10,10 +10,14 @@
</style>
<script>
window.onload = () => {
document.execCommand("selectAll", false)
document.execCommand("selectAll", false)
document.execCommand("backColor", false, "r")
document.execCommand("superscript", false)
getSelection().collapse(
document.querySelector("dl"),
document.querySelector("dl").childNodes.length
);
document.execCommand("selectAll");
document.execCommand("selectAll");
document.execCommand("backColor", false, "r");
document.execCommand("superscript");
}
</script>
<dl style="columns:1px">

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

@ -80,7 +80,11 @@ alert(e+'\n'+elm.id+'\n'+t)
}
}
function selectText() {
var divs = document.getElementsByTagName('div');
// For putting selection ranges to multiple editing hosts, we need to put
// a range outside all editable elements first, then, selection's ancestor
// limiter won't be set to an editing host.
getSelection().collapse(document.body, document.body.childNodes.length);
var divs = document.getElementsByTagName('div');
for (i = 0; i < divs.length; ++i) {
addRange(divs[i]);
}

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

@ -82,7 +82,11 @@ alert(e+'\n'+elm.id+'\n'+t)
}
}
function selectText() {
var divs = document.getElementsByTagName('div');
// For putting selection ranges to multiple editing hosts, we need to put
// a range outside all editable elements first, then, selection's ancestor
// limiter won't be set to an editing host.
getSelection().collapse(document.body, document.body.childNodes.length);
var divs = document.getElementsByTagName('div');
for (i = 0; i < divs.length; ++i) {
addRange(divs[i]);
}

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

@ -1,2 +0,0 @@
[selection-contenteditable-011.html]
expected: FAIL

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

@ -1,5 +1,4 @@
[forced-colors-mode-43.html]
expected:
if (os == "mac") and debug: [FAIL, PASS]
if os == "android": PASS
[PASS, FAIL]