<!DOCTYPE html>
<title>Spelling error makers painting</title>
<script src="../resources/runner.js"></script>
<script src="resources/paint.js"></script>
<p>To run this test use: <code>content_shell --expose-internals-for-testing</code>.</p>
<p id="warning" style="color: red;"></p>
<pre id="log"></pre>
<div>Word count: <span id="wc">0</span></div>
<main contenteditable></main>
<script>
const LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ";
const INITIAL_WORDS = 3000;
const main = document.querySelector("main");
const wc = document.querySelector("#wc");
function createRange(element, start, end) {
let range = new Range();
range.setStart(element.firstChild, start);
range.setEnd(element.firstChild, end);
return range;
}
function setupTest() {
if (!window.internals)
document.querySelector("#warning").innerHTML = "WARNING: use <code>content_shell --expose-internals-for-testing</code> to run this test more accurately!";
// Use real spell checker as a last resort. content_shell only has intenals,
// while chrome only has real spell checker. Some words in the test input
// might be in the dictionary (e.g. sit, do).
main.spellcheck = !window.internals;
main.focus();
// Type the initial words in bulk. This is much faster than typing it one
// letter at a time with simulateTyping.
const wordsInSentence = LOREM_IPSUM.split(" ").length - 1;
const repeatedSentence = LOREM_IPSUM.repeat(Math.ceil(INITIAL_WORDS / wordsInSentence));
const repeatedWords = repeatedSentence.split(" ");
const input = repeatedWords.slice(0, INITIAL_WORDS).join(" ");
document.execCommand("insertText", false, input);
wc.textContent = INITIAL_WORDS;
// Mark the initial words as spelling errors.
try {
for (let i = 0, wordStart = 0; i < INITIAL_WORDS; i++) {
const wordEnd = wordStart + repeatedWords[i].length;
const range = createRange(main, wordStart, wordEnd);
internals.setMarker(document, range, "spelling");
wordStart = wordEnd + 1; // space (U+0020 or U+00A0)
}
} catch (_) {
/* empty */
}
}
function simulateTyping() {
// Type the input, one letter at a time.
document.execCommand("insertText", false, LOREM_IPSUM[main.textContent.length % LOREM_IPSUM.length]);
// After typing each word, mark that word as a spelling error.
// In content_shell, spaces are U+00A0 ( ) until they are no longer
// trailing, but in chrome, they can stay as U+00A0 permanently.
// https://w3c.github.io/editing/docs/execCommand/#canonical-space-sequences
// https://w3c.github.io/editing/docs/execCommand/#the-inserttext-command
const newContent = main.textContent;
if (newContent.at(-2) == " " || newContent.at(-2) == "\xA0") {
document.querySelector("#wc").textContent++;
const end = newContent.length - 2;
const words = newContent.slice(0, end);
let start;
for (start = words.length - 1; start >= 0; start--)
if (words[start] == " " || words[start] == "\xA0")
break;
try {
const range = createRange(main, start == -1 ? 0 : start + 1, end);
internals.setMarker(document, range, "spelling");
} catch (_) {
/* empty */
}
}
}
setupTest();
measurePaint({
description: "Measure frame time for typing in contenteditable with many spelling errors",
run: () => void simulateTyping(),
});
</script>