tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

input-events-get-target-ranges-forwarddelete.tentative.html (76753B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <meta name="timeout" content="long">
      4 <title>InputEvent.getTargetRanges() at Delete (forward delete)</title>
      5 <div contenteditable></div>
      6 <script src="input-events-get-target-ranges.js"></script>
      7 <script src="/resources/testharness.js"></script>
      8 <script src="/resources/testharnessreport.js"></script>
      9 <script src="/resources/testdriver.js"></script>
     10 <script src="/resources/testdriver-vendor.js"></script>
     11 <script src="/resources/testdriver-actions.js"></script>
     12 <script>
     13 "use strict";
     14 
     15 // Simply deletes the next ASCII character of caret position.
     16 promise_test(async (t) => {
     17  initializeTest("<p>abc</p>");
     18  gSelection.collapse(gEditor.firstChild.firstChild, 2);
     19  await sendDeleteKey();
     20  checkEditorContentResultAsSubTest("<p>ab</p>", t.name);
     21  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
     22    startContainer: gEditor.firstChild.firstChild,
     23    startOffset: 2,
     24    endContainer: gEditor.firstChild.firstChild,
     25    endOffset: 3,
     26  });
     27  checkGetTargetRangesOfInputOnDeleteSomething();
     28 }, 'Delete at "<p>ab[]c</p>"');
     29 
     30 // Simply deletes the next ASCII character of caret position.
     31 promise_test(async (t) => {
     32  initializeTest("<p>abc</p>");
     33  gSelection.collapse(gEditor.firstChild.firstChild, 1);
     34  await sendDeleteKey();
     35  checkEditorContentResultAsSubTest("<p>ac</p>", t.name);
     36  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
     37    startContainer: gEditor.firstChild.firstChild,
     38    startOffset: 1,
     39    endContainer: gEditor.firstChild.firstChild,
     40    endOffset: 2,
     41  });
     42  checkGetTargetRangesOfInputOnDeleteSomething();
     43 }, 'Delete at "<p>a[]bc</p>"');
     44 
     45 // Simply deletes the next ASCII character of caret position.
     46 promise_test(async (t) => {
     47  initializeTest("<p>abc</p>");
     48  gSelection.collapse(gEditor.firstChild.firstChild, 0);
     49  await sendDeleteKey();
     50  checkEditorContentResultAsSubTest("<p>bc</p>", t.name);
     51  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
     52    startContainer: gEditor.firstChild.firstChild,
     53    startOffset: 0,
     54    endContainer: gEditor.firstChild.firstChild,
     55    endOffset: 1,
     56  });
     57  checkGetTargetRangesOfInputOnDeleteSomething();
     58 }, 'Delete at "<p>[]abc</p>"');
     59 
     60 promise_test(async (t) => {
     61  initializeTest("<p>abc</p>");
     62  let abc = gEditor.querySelector("p").firstChild;
     63  gSelection.collapse(abc, 3);
     64  await sendDeleteKey();
     65  checkEditorContentResultAsSubTest("<p>abc</p>", t.name);
     66  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
     67    startContainer: abc,
     68    startOffset: 3,
     69    endContainer: abc,
     70    endOffset: 3,
     71  });
     72  checkGetTargetRangesOfInputOnDoNothing();
     73 }, 'Delete at "<p>abc[]</p>"');
     74 
     75 promise_test(async (t) => {
     76  initializeTest("<p>abc<br></p>");
     77  let abc = gEditor.querySelector("p").firstChild;
     78  gSelection.collapse(abc, 3);
     79  await sendDeleteKey();
     80  checkEditorContentResultAsSubTest("<p>abc<br></p>", t.name);
     81  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
     82    startContainer: abc,
     83    startOffset: 3,
     84    endContainer: abc,
     85    endOffset: 3,
     86  });
     87  checkGetTargetRangesOfInputOnDoNothing();
     88 }, 'Delete at "<p>abc[]<br></p>"');
     89 
     90 promise_test(async (t) => {
     91  initializeTest(`<p><img src="${kImgSrc}"><br></p>`);
     92  let p = gEditor.querySelector("p");
     93  gSelection.collapse(p, 1);
     94  await sendDeleteKey();
     95  checkEditorContentResultAsSubTest(
     96    `<p><img src="${kImgSrc}"><br></p>`,
     97    t.name
     98  );
     99  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    100    startContainer: p,
    101    startOffset: 1,
    102    endContainer: p,
    103    endOffset: 1,
    104  });
    105  checkGetTargetRangesOfInputOnDoNothing();
    106 }, 'Delete at "<p><img>[]<br></p>"');
    107 
    108 // Should delete the `<span>` element because it becomes empty.
    109 // However, we need discussion whether the `<span>` element should be
    110 // contained by a range of `getTargetRanges()`.
    111 // https://github.com/w3c/input-events/issues/112
    112 promise_test(async (t) => {
    113  initializeTest("<p>a<span>b</span>c</p>");
    114  let a = gEditor.querySelector("span").previousSibling;
    115  gSelection.collapse(a, 1);
    116  await sendDeleteKey();
    117  checkEditorContentResultAsSubTest("<p>ac</p>", t.name);
    118  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    119    startContainer: a,
    120    startOffset: 1,
    121    endContainer: gEditor.firstChild,
    122    endOffset: 2,
    123  });
    124  checkGetTargetRangesOfInputOnDeleteSomething();
    125 }, 'Delete at "<p>a[]<span>b</span>c</p>"');
    126 
    127 // Should delete the `<span>` element because it becomes empty.
    128 // However, we need discussion whether the `<span>` element should be
    129 // contained by a range of `getTargetRanges()`.
    130 // https://github.com/w3c/input-events/issues/112
    131 promise_test(async (t) => {
    132  initializeTest("<p>a<span>b</span>c</p>");
    133  let b = gEditor.querySelector("span").firstChild;
    134  gSelection.collapse(b, 0);
    135  await sendDeleteKey();
    136  checkEditorContentResultAsSubTest("<p>ac</p>", t.name);
    137  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    138    startContainer: gEditor.firstChild,
    139    startOffset: 1,
    140    endContainer: gEditor.firstChild,
    141    endOffset: 2,
    142  });
    143  checkGetTargetRangesOfInputOnDeleteSomething();
    144 }, 'Delete at "<p>a<span>[]b</span>c</p>"');
    145 
    146 // Invisible trailing white-space may be deleted when the last visible
    147 // character is deleted.  If it's deleted, it should be contained by
    148 // the range of `getTargetRanges()`, but needs discussion.
    149 // https://github.com/w3c/input-events/issues/112
    150 promise_test(async (t) => {
    151  initializeTest("<p>abc </p>");
    152  gSelection.collapse(gEditor.firstChild.firstChild, 2);
    153  await sendDeleteKey();
    154  checkEditorContentResultAsSubTest(
    155    [
    156      "<p>ab</p>",
    157      "<p>ab </p>",
    158    ],
    159    t.name
    160  );
    161  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    162    startContainer: gEditor.firstChild.firstChild,
    163    startOffset: 2,
    164    endContainer: gEditor.firstChild.firstChild,
    165    endOffset: gEditor.firstChild.firstChild.data.length == 2 ? 4 : 3,
    166  });
    167  checkGetTargetRangesOfInputOnDeleteSomething();
    168 }, 'Delete at "<p>ab[]c </p>"');
    169 
    170 promise_test(async (t) => {
    171  initializeTest("<p>abc</p><p>def</p>");
    172  let p1 = gEditor.firstChild;
    173  let abc = p1.firstChild;
    174  let p2 = p1.nextSibling;
    175  let def = p2.firstChild;
    176  gSelection.collapse(abc, 3);
    177  await sendDeleteKey();
    178  checkEditorContentResultAsSubTest("<p>abcdef</p>", t.name);
    179  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    180    startContainer: abc,
    181    startOffset: 3,
    182    endContainer: def,
    183    endOffset: 0,
    184  });
    185  checkGetTargetRangesOfInputOnDeleteSomething();
    186 }, 'Delete at "<p>abc[]</p><p>def</p>"');
    187 
    188 // Invisible trailing white-spaces in current block and invisible leading
    189 // white-spaces in the following block should be deleted for avoiding they
    190 // becoming visible when the blocks are joined.  Perhaps, they should be
    191 // contained by the range of `getTargetRanges()`, but needs discussion.
    192 // https://github.com/w3c/input-events/issues/112
    193 promise_test(async (t) => {
    194  initializeTest("<p>abc   </p><p>   def</p>");
    195  let p1 = gEditor.firstChild;
    196  let abc = p1.firstChild;
    197  let p2 = p1.nextSibling;
    198  let def = p2.firstChild;
    199  gSelection.collapse(abc, 3);
    200  await sendDeleteKey();
    201  checkEditorContentResultAsSubTest("<p>abcdef</p>", t.name);
    202  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    203    startContainer: abc,
    204    startOffset: 3,
    205    endContainer: def,
    206    endOffset: 3,
    207  });
    208  checkGetTargetRangesOfInputOnDeleteSomething();
    209 }, 'Delete at "<p>abc[]   </p><p>   def</p>"');
    210 
    211 // Invisible trailing white-spaces in current block and invisible leading
    212 // white-spaces in the following block should be deleted for avoiding they
    213 // becoming visible when the blocks are joined.  Perhaps, they should be
    214 // contained by the range of `getTargetRanges()`, but needs discussion.
    215 // https://github.com/w3c/input-events/issues/112
    216 promise_test(async (t) => {
    217  initializeTest("<p>abc   </p><p>   def</p>");
    218  let p1 = gEditor.firstChild;
    219  let abc = p1.firstChild;
    220  let p2 = p1.nextSibling;
    221  let def = p2.firstChild;
    222  gSelection.collapse(abc, 4);
    223  await sendDeleteKey();
    224  checkEditorContentResultAsSubTest("<p>abcdef</p>", t.name);
    225  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    226    startContainer: abc,
    227    startOffset: 3,
    228    endContainer: def,
    229    endOffset: 3,
    230  });
    231  checkGetTargetRangesOfInputOnDeleteSomething();
    232 }, 'Delete at "<p>abc []  </p><p>   def</p>"');
    233 
    234 // Invisible trailing white-spaces in current block and invisible leading
    235 // white-spaces in the following block should be deleted for avoiding they
    236 // becoming visible when the blocks are joined.  Perhaps, they should be
    237 // contained by the range of `getTargetRanges()`, but needs discussion.
    238 // https://github.com/w3c/input-events/issues/112
    239 promise_test(async (t) => {
    240  initializeTest("<p>abc   </p><p>   def</p>");
    241  let p1 = gEditor.firstChild;
    242  let abc = p1.firstChild;
    243  let p2 = p1.nextSibling;
    244  let def = p2.firstChild;
    245  gSelection.collapse(abc, 5);
    246  await sendDeleteKey();
    247  checkEditorContentResultAsSubTest("<p>abcdef</p>", t.name);
    248  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    249    startContainer: abc,
    250    startOffset: 3,
    251    endContainer: def,
    252    endOffset: 3,
    253  });
    254  checkGetTargetRangesOfInputOnDeleteSomething();
    255 }, 'Delete at "<p>abc  [] </p><p>   def</p>"');
    256 
    257 // Invisible trailing white-spaces in current block and invisible leading
    258 // white-spaces in the following block should be deleted for avoiding they
    259 // becoming visible when the blocks are joined.  Perhaps, they should be
    260 // contained by the range of `getTargetRanges()`, but needs discussion.
    261 // https://github.com/w3c/input-events/issues/112
    262 promise_test(async (t) => {
    263  initializeTest("<p>abc   </p><p>   def</p>");
    264  let p1 = gEditor.firstChild;
    265  let abc = p1.firstChild;
    266  let p2 = p1.nextSibling;
    267  let def = p2.firstChild;
    268  gSelection.collapse(abc, 6);
    269  await sendDeleteKey();
    270  checkEditorContentResultAsSubTest("<p>abcdef</p>", t.name);
    271  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    272    startContainer: abc,
    273    startOffset: 3,
    274    endContainer: def,
    275    endOffset: 3,
    276  });
    277  checkGetTargetRangesOfInputOnDeleteSomething();
    278 }, 'Delete at "<p>abc   []</p><p>   def</p>"');
    279 
    280 promise_test(async (t) => {
    281  initializeTest("<p>abc</p><p><b>def</b></p>");
    282  let abc = gEditor.querySelector("p").firstChild;
    283  let def = gEditor.querySelector("b").firstChild;
    284  gSelection.collapse(abc, 3);
    285  await sendDeleteKey();
    286  checkEditorContentResultAsSubTest("<p>abc<b>def</b></p>", t.name);
    287  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    288    startContainer: abc,
    289    startOffset: 3,
    290    endContainer: def,
    291    endOffset: 0,
    292  });
    293  checkGetTargetRangesOfInputOnDeleteSomething();
    294 }, 'Delete at "<p>abc[]</p><p><b>def</b></p>"');
    295 
    296 promise_test(async (t) => {
    297  initializeTest("<p><b>abc</b></p><p><b>def</b></p>");
    298  let abc = gEditor.querySelector("p > b").firstChild;
    299  let def = gEditor.querySelector("P + p > b").firstChild;
    300  gSelection.collapse(abc, 3);
    301  await sendDeleteKey();
    302  checkEditorContentResultAsSubTest(
    303    [
    304      "<p><b>abc</b><b>def</b></p>",
    305      "<p><b>abcdef</b></p>",
    306    ],
    307    t.name
    308  );
    309  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    310    startContainer: abc,
    311    startOffset: 3,
    312    endContainer: def,
    313    endOffset: 0,
    314  });
    315  checkGetTargetRangesOfInputOnDeleteSomething();
    316 }, 'Delete at "<p><b>abc[]</b></p><p><b>def</b></p>"');
    317 
    318 promise_test(async (t) => {
    319  initializeTest("<p><i>abc</i></p><p><b>def</b></p>");
    320  let abc = gEditor.querySelector("i").firstChild;
    321  let def = gEditor.querySelector("b").firstChild;
    322  gSelection.collapse(abc, 3);
    323  await sendDeleteKey();
    324  checkEditorContentResultAsSubTest("<p><i>abc</i><b>def</b></p>", t.name);
    325  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    326    startContainer: abc,
    327    startOffset: 3,
    328    endContainer: def,
    329    endOffset: 0,
    330  });
    331  checkGetTargetRangesOfInputOnDeleteSomething();
    332 }, 'Delete at "<p><i>abc[]</i></p><p><b>def</b></p>"');
    333 
    334 // Invisible leading white-spaces in the following block should be deleted
    335 // for avoiding they becoming visible when the blocks are joined, but
    336 // preformatted trailing white-spaces in the first block shouldn't be
    337 // deleted.  Perhaps, the invisible white-spaces should be contained by
    338 // the range of `getTargetRanges()`, but needs discussion.
    339 // https://github.com/w3c/input-events/issues/112
    340 promise_test(async (t) => {
    341  initializeTest("<pre>abc   </pre><p>   def</p>");
    342  let pre = gEditor.firstChild;
    343  let abc = pre.firstChild;
    344  let p = pre.nextSibling;
    345  let def = p.firstChild;
    346  gSelection.collapse(abc, 6);
    347  await sendDeleteKey();
    348  checkEditorContentResultAsSubTest("<pre>abc   def</pre>", t.name);
    349  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    350    startContainer: abc,
    351    startOffset: 6,
    352    endContainer: def,
    353    endOffset: 3,
    354  });
    355  checkGetTargetRangesOfInputOnDeleteSomething();
    356 }, 'Delete at "<pre>abc   []</pre><p>   def</p>"');
    357 
    358 // Invisible leading/trailing white-spaces in the following block should be
    359 // deleted for avoiding they becoming visible when the blocks are joined, but
    360 // preformatted trailing white-spaces in the first block shouldn't be
    361 // deleted.  Perhaps, the invisible leading white-spaces should be contained
    362 // by the range of `getTargetRanges()`, but needs discussion.
    363 // And also not sure whether the trailing white-spaces should be contained
    364 // by additional range of `getTargetRanges()` or not because of the
    365 // implementation cost and runtime cost.  Needs discuss.
    366 // https://github.com/w3c/input-events/issues/112
    367 promise_test(async (t) => {
    368  initializeTest("<pre>abc   </pre><p>   def</p>");
    369  let pre = gEditor.firstChild;
    370  let abc = pre.firstChild;
    371  let p = pre.nextSibling;
    372  let def = p.firstChild;
    373  gSelection.collapse(abc, 6);
    374  await sendDeleteKey();
    375  checkEditorContentResultAsSubTest("<pre>abc   def</pre>", t.name);
    376  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    377    startContainer: abc,
    378    startOffset: 6,
    379    endContainer: def,
    380    endOffset: 3,
    381  });
    382  checkGetTargetRangesOfInputOnDeleteSomething();
    383 }, 'Delete at "<pre>abc   []</pre><p>   def   </p>"');
    384 
    385 // Invisible trailing white-spaces in the first block should be deleted
    386 // when the block is joined with the preformatted following block, but
    387 // the leading white-spaces in the preformatted block shouldn't be
    388 // removed.  So, in this case, the invisible trailing white-spaces should
    389 // be in the range of `getTargetRanges()`, but not so for the preformatted
    390 // visible leading white-spaces.  But needs discussion.
    391 // https://github.com/w3c/input-events/issues/112
    392 promise_test(async (t) => {
    393  initializeTest("<p>abc   </p><pre>   def</pre>");
    394  let p = gEditor.firstChild;
    395  let abc = p.firstChild;
    396  let pre = p.nextSibling;
    397  let def = pre.firstChild;
    398  gSelection.collapse(abc, 3);
    399  await sendDeleteKey();
    400  checkEditorContentResultAsSubTest(
    401    [
    402      "<p>abc &nbsp; def</p>",
    403      "<p>abc&nbsp;&nbsp; def</p>",
    404      "<p>abc&nbsp; &nbsp;def</p>",
    405      "<p>abc &nbsp;&nbsp;def</p>",
    406    ],
    407    t.name
    408  );
    409  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    410    startContainer: abc,
    411    startOffset: 3,
    412    endContainer: def,
    413    endOffset: 0,
    414  });
    415  checkGetTargetRangesOfInputOnDeleteSomething();
    416 }, 'Delete at "<p>abc[]   </p><pre>   def</pre>"');
    417 
    418 promise_test(async (t) => {
    419  initializeTest('<p style="white-space:pre-line">abc\ndef</p>');
    420  const p = gEditor.firstChild;
    421  const text = p.firstChild;
    422  gSelection.collapse(text, "abc".length);
    423  await sendDeleteKey();
    424  checkEditorContentResultAsSubTest(
    425    '<p style="white-space:pre-line">abcdef</p>',
    426    t.name
    427  );
    428  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    429    startContainer: text,
    430    startOffset: "abc".length,
    431    endContainer: text,
    432    endOffset: "abc\n".length,
    433  });
    434  checkGetTargetRangesOfInputOnDeleteSomething();
    435 }, 'Delete at "<p style="white-space:pre-line">abc[]\\ndef</p>"');
    436 
    437 promise_test(async (t) => {
    438  initializeTest('<p style="white-space:pre-line">abc\n def</p>');
    439  const p = gEditor.firstChild;
    440  const text = p.firstChild;
    441  gSelection.collapse(text, "abc".length);
    442  await sendDeleteKey();
    443  checkEditorContentResultAsSubTest(
    444    '<p style="white-space:pre-line">abcdef</p>',
    445    t.name
    446  );
    447  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    448    startContainer: text,
    449    startOffset: "abc".length,
    450    endContainer: text,
    451    endOffset: "abc\n ".length,
    452  });
    453  checkGetTargetRangesOfInputOnDeleteSomething();
    454 }, 'Delete at "<p style="white-space:pre-line">abc[]\\n def</p>"');
    455 
    456 promise_test(async (t) => {
    457  initializeTest('<p style="white-space:pre-line">abc \ndef</p>');
    458  const p = gEditor.firstChild;
    459  const text = p.firstChild;
    460  gSelection.collapse(text, "abc".length);
    461  await sendDeleteKey();
    462  checkEditorContentResultAsSubTest(
    463    '<p style="white-space:pre-line">abcdef</p>',
    464    t.name
    465  );
    466  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    467    startContainer: text,
    468    startOffset: "abc".length,
    469    endContainer: text,
    470    endOffset: "abc \n ".length,
    471  });
    472  checkGetTargetRangesOfInputOnDeleteSomething();
    473 }, 'Delete at "<p style="white-space:pre-line">abc[] \\ndef</p>"');
    474 
    475 promise_test(async (t) => {
    476  initializeTest('<p style="white-space:pre-line">abc \n def</p>');
    477  const p = gEditor.firstChild;
    478  const text = p.firstChild;
    479  gSelection.collapse(text, "abc".length);
    480  await sendDeleteKey();
    481  checkEditorContentResultAsSubTest(
    482    '<p style="white-space:pre-line">abcdef</p>',
    483    t.name
    484  );
    485  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    486    startContainer: text,
    487    startOffset: "abc".length,
    488    endContainer: text,
    489    endOffset: "abc \n ".length,
    490  });
    491  checkGetTargetRangesOfInputOnDeleteSomething();
    492 }, 'Delete at "<p style="white-space:pre-line">abc[] \\n def</p>"');
    493 
    494 promise_test(async (t) => {
    495  initializeTest('<p style="white-space:pre-line">abc \n \n def</p>');
    496  const p = gEditor.firstChild;
    497  const text = p.firstChild;
    498  gSelection.collapse(text, "abc".length);
    499  await sendDeleteKey();
    500  checkEditorContentResultAsSubTest(
    501    '<p style="white-space:pre-line">abc\n def</p>',
    502    t.name
    503  );
    504  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    505    startContainer: text,
    506    startOffset: "abc".length,
    507    endContainer: text,
    508    endOffset: "abc \n \n ".length,
    509  });
    510  checkGetTargetRangesOfInputOnDeleteSomething();
    511 }, 'Delete at "<p style="white-space:pre-line">abc[] \\n \\n def</p>"');
    512 
    513 // Deleting from before invisible trailing `<br>` element of a block
    514 // should delete the `<br>` element and join the blocks.  Therefore,
    515 // the target range should contain the `<br>` element and block boundaries.
    516 // But maybe needs discussion.
    517 // https://github.com/w3c/input-events/issues/112
    518 promise_test(async (t) => {
    519  initializeTest("<p>abc<br></p><p>def</p>");
    520  let p1 = gEditor.firstChild;
    521  let abc = p1.firstChild;
    522  let p2 = p1.nextSibling;
    523  let def = p2.firstChild;
    524  gSelection.collapse(abc, 3);
    525  await sendDeleteKey();
    526  checkEditorContentResultAsSubTest("<p>abcdef</p>", t.name);
    527  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    528    startContainer: abc,
    529    startOffset: 3,
    530    endContainer: def,
    531    endOffset: 0,
    532  });
    533  checkGetTargetRangesOfInputOnDeleteSomething();
    534 }, 'Delete at "<p>abc[]<br></p><p>def</p>"');
    535 
    536 promise_test(async (t) => {
    537  initializeTest(`<p><img src="${kImgSrc}"><br></p><p>def</p>`);
    538  let p1 = gEditor.firstChild;
    539  let img = p1.firstChild;
    540  let p2 = p1.nextSibling;
    541  let def = p2.firstChild;
    542  gSelection.collapse(p1, 1);
    543  await sendDeleteKey();
    544  checkEditorContentResultAsSubTest(`<p><img src="${kImgSrc}">def</p>`, t.name);
    545  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    546    startContainer: p1,
    547    startOffset: 1,
    548    endContainer: def,
    549    endOffset: 0,
    550  });
    551  checkGetTargetRangesOfInputOnDeleteSomething();
    552 }, `Delete at "<p><img>{}<br></p><p>def</p>"`);
    553 
    554 // Deleting from last empty line in the first block should delete the
    555 // invisible `<br>` element for the last empty line and join the blocks.
    556 // In this case, the invisible `<br>` element should be contained in the
    557 // range of `getTargetRanges()`, but needs discussion.
    558 // https://github.com/w3c/input-events/issues/112
    559 promise_test(async (t) => {
    560  initializeTest("<p>abc<br><br></p><p>def</p>");
    561  let p1 = gEditor.firstChild;
    562  let abc = p1.firstChild;
    563  let p2 = p1.nextSibling;
    564  let def = p2.firstChild;
    565  gSelection.collapse(p1, 2);
    566  await sendDeleteKey();
    567  checkEditorContentResultAsSubTest("<p>abc<br>def</p>", t.name);
    568  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    569    startContainer: p1,
    570    startOffset: 2,
    571    endContainer: def,
    572    endOffset: 0,
    573  });
    574  checkGetTargetRangesOfInputOnDeleteSomething();
    575 }, 'Delete at "<p>abc<br>{}<br></p><p>def</p>"');
    576 
    577 // Deleting visible `<br>` element should be contained by a range of
    578 // `getTargetRanges()`.
    579 promise_test(async (t) => {
    580  initializeTest("<p>abc<br>def</p>");
    581  let p = gEditor.querySelector("p");
    582  let abc = p.firstChild;
    583  gSelection.collapse(abc, 3);
    584  await sendDeleteKey();
    585  checkEditorContentResultAsSubTest("<p>abcdef</p>", t.name);
    586  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    587    startContainer: p,
    588    startOffset: 1,
    589    endContainer: p,
    590    endOffset: 2,
    591  });
    592  checkGetTargetRangesOfInputOnDeleteSomething();
    593 }, 'Delete at "<p>abc[]<br>def</p>"');
    594 
    595 // Deleting visible `<br>` element following white-space should not include
    596 // the preceding white-space in the range.
    597 promise_test(async (t) => {
    598  initializeTest("<p>abc <br>def</p>");
    599  let p = gEditor.querySelector("p");
    600  let abc = p.firstChild;
    601  gSelection.collapse(abc, 4);
    602  await sendDeleteKey();
    603  checkEditorContentResultAsSubTest("<p>abc def</p>", t.name);
    604  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    605    startContainer: p,
    606    startOffset: 1,
    607    endContainer: p,
    608    endOffset: 2,
    609  });
    610  checkGetTargetRangesOfInputOnDeleteSomething();
    611 }, 'Delete at "<p>abc []<br>def</p>"');
    612 
    613 // Deleting visible `<br>` element followed by white-space should include
    614 // the following white-space in the range because it shouldn't become
    615 // visible and should be deleted for avoiding it.
    616 // https://github.com/w3c/input-events/issues/112
    617 promise_test(async (t) => {
    618  initializeTest("<p>abc<br> def</p>");
    619  let p = gEditor.querySelector("p");
    620  let abc = p.firstChild;
    621  let def = gEditor.querySelector("br").nextSibling;
    622  gSelection.collapse(abc, 3);
    623  await sendDeleteKey();
    624  checkEditorContentResultAsSubTest("<p>abcdef</p>", t.name);
    625  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    626    startContainer: p,
    627    startOffset: 1,
    628    endContainer: def,
    629    endOffset: 1,
    630  });
    631  checkGetTargetRangesOfInputOnDeleteSomething();
    632 }, 'Delete at "<p>abc[]<br> def</p>"');
    633 
    634 promise_test(async (t) => {
    635  initializeTest(`<p>abc<img src="${kImgSrc}">def</p>`);
    636  let p = gEditor.querySelector("p");
    637  let abc = p.firstChild;
    638  gSelection.collapse(abc, 3);
    639  await sendDeleteKey();
    640  checkEditorContentResultAsSubTest("<p>abcdef</p>", t.name);
    641  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    642    startContainer: p,
    643    startOffset: 1,
    644    endContainer: p,
    645    endOffset: 2,
    646  });
    647  checkGetTargetRangesOfInputOnDeleteSomething();
    648 }, 'Delete at "<p>abc[]<img>def</p>"');
    649 
    650 // White-spaces around `<img>` element are visible so that they shouldn't
    651 // be included into the target ranges.
    652 promise_test(async (t) => {
    653  initializeTest(`<p>abc <img src="${kImgSrc}">def</p>`);
    654  let p = gEditor.querySelector("p");
    655  let abc = p.firstChild;
    656  gSelection.collapse(abc, 4);
    657  await sendDeleteKey();
    658  // If the browser does not join `Text` nodes around <img>, it's fine to
    659  // convert the preceding white-space to an NBSP.
    660  if (
    661    gEditor.querySelector("p")?.childNodes.length == 2 &&
    662    gEditor.querySelector("p").childNodes[0].length == "abc ".length
    663  ) {
    664    checkEditorContentResultAsSubTest([
    665      "<p>abc&nbsp;def</p>",
    666      "<p>abc def</p>",
    667    ], t.name);
    668  } else {
    669    checkEditorContentResultAsSubTest("<p>abc def</p>", t.name);
    670  }
    671  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    672    startContainer: p,
    673    startOffset: 1,
    674    endContainer: p,
    675    endOffset: 2,
    676  });
    677  checkGetTargetRangesOfInputOnDeleteSomething();
    678 }, 'Delete at "<p>abc []<img>def</p>"');
    679 
    680 // White-spaces around `<img>` element are visible so that they shouldn't
    681 // be included into the target ranges.
    682 promise_test(async (t) => {
    683  initializeTest(`<p>abc<img src="${kImgSrc}"> def</p>`);
    684  let p = gEditor.querySelector("p");
    685  let abc = p.firstChild;
    686  gSelection.collapse(abc, 3);
    687  await sendDeleteKey();
    688  // If the browser does not join `Text` nodes around <img>, it's fine to
    689  // convert the preceding white-space to an NBSP.
    690  if (
    691    gEditor.querySelector("p")?.childNodes.length == 2 &&
    692    gEditor.querySelector("p").childNodes[0].length == "abc".length
    693  ) {
    694    checkEditorContentResultAsSubTest([
    695      "<p>abc&nbsp;def</p>",
    696      "<p>abc def</p>",
    697    ], t.name);
    698  } else {
    699    checkEditorContentResultAsSubTest("<p>abc def</p>", t.name);
    700  }
    701  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    702    startContainer: p,
    703    startOffset: 1,
    704    endContainer: p,
    705    endOffset: 2,
    706  });
    707  checkGetTargetRangesOfInputOnDeleteSomething();
    708 }, 'Delete at "<p>abc[]<img> def</p>"');
    709 
    710 promise_test(async (t) => {
    711  initializeTest(`<p>abc<img src="${kImgSrc}"><img src="${kImgSrc}">def</p>`);
    712  let p = gEditor.querySelector("p");
    713  let abc = p.firstChild;
    714  gSelection.collapse(abc, 3);
    715  await sendDeleteKey();
    716  checkEditorContentResultAsSubTest(
    717    `<p>abc<img src="${kImgSrc}">def</p>`,
    718    t.name
    719  );
    720  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    721    startContainer: p,
    722    startOffset: 1,
    723    endContainer: p,
    724    endOffset: 2,
    725  });
    726  checkGetTargetRangesOfInputOnDeleteSomething();
    727 }, 'Delete at "<p>abc[]<img><img>def</p>"');
    728 
    729 promise_test(async (t) => {
    730  initializeTest(`<p>abc<img src="${kImgSrc}"><img src="${kImgSrc}">def</p>`);
    731  let p = gEditor.querySelector("p");
    732  gSelection.collapse(p, 2);
    733  await sendDeleteKey();
    734  checkEditorContentResultAsSubTest(
    735    `<p>abc<img src="${kImgSrc}">def</p>`,
    736    t.name
    737  );
    738  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    739    startContainer: p,
    740    startOffset: 2,
    741    endContainer: p,
    742    endOffset: 3,
    743  });
    744  checkGetTargetRangesOfInputOnDeleteSomething();
    745 }, 'Delete at "<p>abc<img>{}<img>def</p>"');
    746 
    747 promise_test(async (t) => {
    748  initializeTest(`<div>abc<hr>def</div>`);
    749  let div = gEditor.querySelector("div");
    750  let abc = div.firstChild;
    751  gSelection.collapse(abc, 3);
    752  await sendDeleteKey();
    753  checkEditorContentResultAsSubTest("<div>abcdef</div>", t.name);
    754  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    755    startContainer: div,
    756    startOffset: 1,
    757    endContainer: div,
    758    endOffset: 2,
    759  });
    760  checkGetTargetRangesOfInputOnDeleteSomething();
    761 }, 'Delete at "<div>abc[]<hr>def</div>"');
    762 
    763 // White-spaces around block element are invisible white-spaces so that
    764 // they should be included into the target ranges to avoid they become
    765 // visible.
    766 // https://github.com/w3c/input-events/issues/112
    767 promise_test(async (t) => {
    768  initializeTest(`<div>abc <hr>def</div>`);
    769  let div = gEditor.querySelector("div");
    770  let abc = div.firstChild;
    771  gSelection.collapse(abc, 3);
    772  await sendDeleteKey();
    773  checkEditorContentResultAsSubTest("<div>abcdef</div>", t.name);
    774  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    775    startContainer: div,
    776    startOffset: 1,
    777    endContainer: div,
    778    endOffset: 2,
    779  });
    780  checkGetTargetRangesOfInputOnDeleteSomething();
    781 }, 'Delete at "<div>abc[] <hr>def</div>"');
    782 
    783 // White-spaces around block element are invisible white-spaces so that
    784 // they should be included into the target ranges to avoid they become
    785 // visible.
    786 // https://github.com/w3c/input-events/issues/112
    787 promise_test(async (t) => {
    788  initializeTest(`<div>abc<hr> def</div>`);
    789  let div = gEditor.querySelector("div");
    790  let abc = div.firstChild;
    791  gSelection.collapse(abc, 3);
    792  await sendDeleteKey();
    793  checkEditorContentResultAsSubTest("<div>abcdef</div>", t.name);
    794  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    795    startContainer: div,
    796    startOffset: 1,
    797    endContainer: div,
    798    endOffset: 2,
    799  });
    800  checkGetTargetRangesOfInputOnDeleteSomething();
    801 }, 'Delete at "<div>abc[]<hr> def</div>"');
    802 
    803 // Invisible `<br>` element immediately before `<hr>` element should be
    804 // delete once, and both of them should be included in the target range.
    805 promise_test(async (t) => {
    806  initializeTest(`<div>abc<br><hr>def</div>`);
    807  let div = gEditor.querySelector("div");
    808  let abc = div.firstChild;
    809  gSelection.collapse(abc, 3);
    810  await sendDeleteKey();
    811  checkEditorContentResultAsSubTest("<div>abcdef</div>", t.name);
    812  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    813    startContainer: div,
    814    startOffset: 1,
    815    endContainer: div,
    816    endOffset: 3,
    817  });
    818  checkGetTargetRangesOfInputOnDeleteSomething();
    819 }, 'Delete at "<div>abc[]<br><hr>def</div>"');
    820 
    821 promise_test(async (t) => {
    822  initializeTest(`<div><img src="${kImgSrc}"><br><hr>def</div>`);
    823  let div = gEditor.querySelector("div");
    824  let img = div.firstChild;
    825  gSelection.collapse(div, 1);
    826  await sendDeleteKey();
    827  checkEditorContentResultAsSubTest(
    828    `<div><img src="${kImgSrc}">def</div>`,
    829    t.name
    830  );
    831  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    832    startContainer: div,
    833    startOffset: 1,
    834    endContainer: div,
    835    endOffset: 3,
    836  });
    837  checkGetTargetRangesOfInputOnDeleteSomething();
    838 }, 'Delete at "<div><img>{}<br><hr>def</div>"');
    839 
    840 promise_test(async (t) => {
    841  initializeTest("<div>abc<p>def<br>ghi</p></div>");
    842  let p = gEditor.querySelector("p");
    843  let def = p.firstChild;
    844  let abc = gEditor.firstChild.firstChild;
    845  gSelection.collapse(abc, 3);
    846  await sendDeleteKey();
    847  checkEditorContentResultAsSubTest(
    848    [
    849      "<div>abcdef<p>ghi</p></div>",
    850      "<div>abcdef<br><p>ghi</p></div>",
    851    ],
    852    t.name
    853  );
    854  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    855    startContainer: abc,
    856    startOffset: 3,
    857    endContainer: def,
    858    endOffset: 0,
    859  });
    860  checkGetTargetRangesOfInputOnDeleteSomething();
    861 }, 'Delete at "<div>abc[]<p>def<br>ghi</p></div>"');
    862 
    863 promise_test(async (t) => {
    864  initializeTest("<div>abc<br><p>def<br>ghi</p></div>");
    865  let div = gEditor.firstChild;
    866  let p = gEditor.querySelector("p");
    867  let def = p.firstChild;
    868  let abc = div.firstChild;
    869  gSelection.collapse(abc, 3);
    870  await sendDeleteKey();
    871  checkEditorContentResultAsSubTest(
    872    [
    873      "<div>abcdef<p>ghi</p></div>",
    874      "<div>abcdef<br><p>ghi</p></div>",
    875    ],
    876    t.name
    877  );
    878  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    879    startContainer: div,
    880    startOffset: 1,
    881    endContainer: def,
    882    endOffset: 0,
    883  });
    884  checkGetTargetRangesOfInputOnDeleteSomething();
    885 }, 'Delete at "<div>abc[]<br><p>def<br>ghi</p></div>"');
    886 
    887 promise_test(async (t) => {
    888  initializeTest(`<div><img src="${kImgSrc}"><br><p>def<br>ghi</p></div>`);
    889  let div = gEditor.firstChild;
    890  let p = gEditor.querySelector("p");
    891  let def = p.firstChild;
    892  let abc = div.firstChild;
    893  gSelection.collapse(div, 1);
    894  await sendDeleteKey();
    895  checkEditorContentResultAsSubTest(
    896    [
    897      `<div><img src="${kImgSrc}">def<p>ghi</p></div>`,
    898      `<div><img src="${kImgSrc}">def<br><p>ghi</p></div>`,
    899    ],
    900    t.name
    901  );
    902  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    903    startContainer: div,
    904    startOffset: 1,
    905    endContainer: def,
    906    endOffset: 0,
    907  });
    908  checkGetTargetRangesOfInputOnDeleteSomething();
    909 }, 'Delete at "<div><img>{}<br><p>def<br>ghi</p></div>"');
    910 
    911 // Joining parent block and child block should remove invisible preceding
    912 // white-spaces of the child block and invisible leading white-spaces in
    913 // the child block, and they should be contained in a range of
    914 // `getTargetRanges()`, but maybe needs discussion.
    915 // https://github.com/w3c/input-events/issues/112
    916 promise_test(async (t) => {
    917  initializeTest("<div>abc   <p>   def<br>ghi</p></div>");
    918  let p = gEditor.querySelector("p");
    919  let def = p.firstChild;
    920  let abc = gEditor.firstChild.firstChild;
    921  gSelection.collapse(abc, 3);
    922  await sendDeleteKey();
    923  checkEditorContentResultAsSubTest(
    924    [
    925      "<div>abcdef<p>ghi</p></div>",
    926      "<div>abcdef<br><p>ghi</p></div>",
    927    ],
    928    t.name
    929  );
    930  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    931    startContainer: abc,
    932    startOffset: 3,
    933    endContainer: def,
    934    endOffset: 3,
    935  });
    936  checkGetTargetRangesOfInputOnDeleteSomething();
    937 }, 'Delete at "<div>abc[]   <p>   def<br>ghi</p></div>"');
    938 
    939 promise_test(async (t) => {
    940  initializeTest("<div>abc<p><b>def</b></p></div>");
    941  let abc = gEditor.querySelector("div").firstChild;
    942  let def = gEditor.querySelector("b").firstChild;
    943  gSelection.collapse(abc, 3);
    944  await sendDeleteKey();
    945  checkEditorContentResultAsSubTest("<div>abc<b>def</b></div>", t.name);
    946  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    947    startContainer: abc,
    948    startOffset: 3,
    949    endContainer: def,
    950    endOffset: 0,
    951  });
    952  checkGetTargetRangesOfInputOnDeleteSomething();
    953 }, 'Delete at "<div>abc[]<p><b>def</b></p></div>"');
    954 
    955 promise_test(async (t) => {
    956  initializeTest("<div><b>abc</b><p><b>def</b></p></div>");
    957  let abc = gEditor.querySelector("b").firstChild;
    958  let def = gEditor.querySelector("p > b").firstChild;
    959  gSelection.collapse(abc, 3);
    960  await sendDeleteKey();
    961  checkEditorContentResultAsSubTest(
    962    [
    963      "<div><b>abc</b><b>def</b></div>",
    964      "<div><b>abcdef</b></div>",
    965    ],
    966    t.name
    967  );
    968  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    969    startContainer: abc,
    970    startOffset: 3,
    971    endContainer: def,
    972    endOffset: 0,
    973  });
    974  checkGetTargetRangesOfInputOnDeleteSomething();
    975 }, 'Delete at "<div><b>abc[]</b><p><b>def</b></p></div>"');
    976 
    977 promise_test(async (t) => {
    978  initializeTest("<div><i>abc</i><p><b>def</b></p></div>");
    979  let abc = gEditor.querySelector("i").firstChild;
    980  let def = gEditor.querySelector("b").firstChild;
    981  gSelection.collapse(abc, 3);
    982  await sendDeleteKey();
    983  checkEditorContentResultAsSubTest("<div><i>abc</i><b>def</b></div>", t.name);
    984  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
    985    startContainer: abc,
    986    startOffset: 3,
    987    endContainer: def,
    988    endOffset: 0,
    989  });
    990  checkGetTargetRangesOfInputOnDeleteSomething();
    991 }, 'Delete at "<div><i>abc[]</i><p><b>def</b></p></div>"');
    992 
    993 promise_test(async (t) => {
    994  initializeTest("<div><p>abc</p>def</div>");
    995  let abc = gEditor.querySelector("p").firstChild;
    996  let def = gEditor.querySelector("p").nextSibling;
    997  gSelection.collapse(abc, 3);
    998  await sendDeleteKey();
    999  checkEditorContentResultAsSubTest(
   1000    [
   1001      "<div><p>abcdef</p></div>",
   1002      "<div><p>abcdef<br></p></div>",
   1003    ],
   1004    t.name
   1005  );
   1006  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1007    startContainer: abc,
   1008    startOffset: 3,
   1009    endContainer: def,
   1010    endOffset: 0,
   1011  });
   1012  checkGetTargetRangesOfInputOnDeleteSomething();
   1013 }, 'Delete at "<div><p>abc[]</p>def</div>"');
   1014 
   1015 promise_test(async (t) => {
   1016  initializeTest("<div><p>abc<br></p>def</div>");
   1017  let p = gEditor.querySelector("p");
   1018  let abc = p.firstChild;
   1019  let def = p.nextSibling;
   1020  gSelection.collapse(abc, 3);
   1021  await sendDeleteKey();
   1022  checkEditorContentResultAsSubTest(
   1023    [
   1024      "<div><p>abcdef</p></div>",
   1025      "<div><p>abcdef<br></p></div>",
   1026    ],
   1027    t.name
   1028  );
   1029  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1030    startContainer: p,
   1031    startOffset: 1,
   1032    endContainer: def,
   1033    endOffset: 0,
   1034  });
   1035  checkGetTargetRangesOfInputOnDeleteSomething();
   1036 }, 'Delete at "<div><p>abc[]<br></p>def</div>"');
   1037 
   1038 promise_test(async (t) => {
   1039  initializeTest(`<div><p><img src="${kImgSrc}"><br></p>def</div>`);
   1040  let p = gEditor.querySelector("p");
   1041  let abc = p.firstChild;
   1042  let def = p.nextSibling;
   1043  gSelection.collapse(p, 1);
   1044  await sendDeleteKey();
   1045  checkEditorContentResultAsSubTest(
   1046    [
   1047      `<div><p><img src="${kImgSrc}">def</p></div>`,
   1048      `<div><p><img src="${kImgSrc}">def<br></p></div>`,
   1049    ],
   1050    t.name
   1051  );
   1052  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1053    startContainer: p,
   1054    startOffset: 1,
   1055    endContainer: def,
   1056    endOffset: 0,
   1057  });
   1058  checkGetTargetRangesOfInputOnDeleteSomething();
   1059 }, 'Delete at "<div><p><img>{}<br></p>def</div>"');
   1060 
   1061 // Joining child block and parent block should remove invisible trailing
   1062 // white-spaces of the child block and invisible following white-spaces
   1063 // in the parent block, and they should be contained by a range of
   1064 // `getTargetRanges()`, but maybe needs discussion.
   1065 // https://github.com/w3c/input-events/issues/112
   1066 promise_test(async (t) => {
   1067  initializeTest("<div><p>abc   </p>   def</div>");
   1068  let abc = gEditor.querySelector("p").firstChild;
   1069  let def = gEditor.querySelector("p").nextSibling;
   1070  gSelection.collapse(abc, 3);
   1071  await sendDeleteKey();
   1072  checkEditorContentResultAsSubTest(
   1073    [
   1074      "<div><p>abcdef</p></div>",
   1075      "<div><p>abcdef<br></p></div>",
   1076    ],
   1077    t.name
   1078  );
   1079  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1080    startContainer: abc,
   1081    startOffset: 3,
   1082    endContainer: def,
   1083    endOffset: 3,
   1084  });
   1085  checkGetTargetRangesOfInputOnDeleteSomething();
   1086 }, 'Delete at "<div><p>abc[]   </p>   def</div>"');
   1087 
   1088 promise_test(async (t) => {
   1089  initializeTest("<div><p><b>abc</b></p>def</div>");
   1090  let abc = gEditor.querySelector("b").firstChild;
   1091  let def = gEditor.querySelector("p").nextSibling;
   1092  gSelection.collapse(abc, 3);
   1093  await sendDeleteKey();
   1094  checkEditorContentResultAsSubTest("<div><p><b>abc</b>def</p></div>", t.name);
   1095  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1096    startContainer: abc,
   1097    startOffset: 3,
   1098    endContainer: def,
   1099    endOffset: 0,
   1100  });
   1101  checkGetTargetRangesOfInputOnDeleteSomething();
   1102 }, 'Delete at "<div><p><b>abc[]</b></p>def</div>"');
   1103 
   1104 promise_test(async (t) => {
   1105  initializeTest("<div><p><b>abc</b></p><b>def</b></div>");
   1106  let abc = gEditor.querySelector("b").firstChild;
   1107  let def = gEditor.querySelector("div > b").firstChild;
   1108  gSelection.collapse(abc, 3);
   1109  await sendDeleteKey();
   1110  checkEditorContentResultAsSubTest(
   1111    [
   1112      "<div><p><b>abc</b><b>def</b></p></div>",
   1113      "<div><p><b>abcdef</b></p></div>",
   1114    ],
   1115    t.name
   1116  );
   1117  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1118    startContainer: abc,
   1119    startOffset: 3,
   1120    endContainer: def,
   1121    endOffset: 0,
   1122  });
   1123  checkGetTargetRangesOfInputOnDeleteSomething();
   1124 }, 'Delete at "<div><p><b>abc[]</b></p><b>def</b></div>"');
   1125 
   1126 promise_test(async (t) => {
   1127  initializeTest("<div><p><b>abc</b></p><i>def</i></div>");
   1128  let abc = gEditor.querySelector("b").firstChild;
   1129  let def = gEditor.querySelector("i").firstChild;
   1130  gSelection.collapse(abc, 3);
   1131  await sendDeleteKey();
   1132  checkEditorContentResultAsSubTest(
   1133    "<div><p><b>abc</b><i>def</i></p></div>",
   1134    t.name
   1135  );
   1136  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1137    startContainer: abc,
   1138    startOffset: 3,
   1139    endContainer: def,
   1140    endOffset: 0,
   1141  });
   1142  checkGetTargetRangesOfInputOnDeleteSomething();
   1143 }, 'Delete at "<div><p><b>abc[]</b></p><i>def</i></div>"');
   1144 
   1145 promise_test(async (t) => {
   1146  initializeTest("<div>abc<ul><li>def</li></ul>ghi</div>");
   1147  let abc = gEditor.querySelector("div").firstChild;
   1148  let def = gEditor.querySelector("li").firstChild;
   1149  gSelection.collapse(abc, 3);
   1150  await sendDeleteKey();
   1151  checkEditorContentResultAsSubTest("<div>abcdefghi</div>", t.name);
   1152  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1153    startContainer: abc,
   1154    startOffset: 3,
   1155    endContainer: def,
   1156    endOffset: 0,
   1157  });
   1158  checkGetTargetRangesOfInputOnDeleteSomething();
   1159 }, 'Delete at "<div>abc[]<ul><li>def</li></ul>ghi</div>"');
   1160 
   1161 promise_test(async (t) => {
   1162  initializeTest("<div>abc  <ul><li> def </li></ul>  ghi</div>");
   1163  let abc = gEditor.querySelector("div").firstChild;
   1164  let def = gEditor.querySelector("li").firstChild;
   1165  gSelection.collapse(abc, 3);
   1166  await sendDeleteKey();
   1167  checkEditorContentResultAsSubTest("<div>abcdefghi</div>", t.name);
   1168  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1169    startContainer: abc,
   1170    startOffset: 3,
   1171    endContainer: def,
   1172    endOffset: 1,
   1173  });
   1174  checkGetTargetRangesOfInputOnDeleteSomething();
   1175 }, 'Delete at "<div>abc[]  <ul><li> def </li></ul>  ghi</div>"');
   1176 
   1177 promise_test(async (t) => {
   1178  initializeTest("<div>abc  <ul><li> def </li></ul>  ghi</div>");
   1179  let abc = gEditor.querySelector("div").firstChild;
   1180  let def = gEditor.querySelector("li").firstChild;
   1181  gSelection.collapse(abc, abc.length);
   1182  await sendDeleteKey();
   1183  checkEditorContentResultAsSubTest("<div>abcdefghi</div>", t.name);
   1184  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1185    startContainer: abc,
   1186    startOffset: 3,
   1187    endContainer: def,
   1188    endOffset: 1,
   1189  });
   1190  checkGetTargetRangesOfInputOnDeleteSomething();
   1191 }, 'Delete at "<div>abc  []<ul><li> def </li></ul>  ghi</div>"');
   1192 
   1193 promise_test(async (t) => {
   1194  initializeTest("<div>abc<ul><li>def</li></ul>ghi</div>");
   1195  let def = gEditor.querySelector("li").firstChild;
   1196  let ghi = gEditor.querySelector("ul").nextSibling;
   1197  gSelection.collapse(def, 3);
   1198  await sendDeleteKey();
   1199  checkEditorContentResultAsSubTest(
   1200    "<div>abc<ul><li>defghi</li></ul></div>",
   1201    t.name
   1202  );
   1203  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1204    startContainer: def,
   1205    startOffset: 3,
   1206    endContainer: ghi,
   1207    endOffset: 0,
   1208  });
   1209  checkGetTargetRangesOfInputOnDeleteSomething();
   1210 }, 'Delete at "<div>abc<ul><li>def[]</li></ul>ghi</div>"');
   1211 
   1212 promise_test(async (t) => {
   1213  initializeTest("<div>abc <ul><li>  def  </li></ul> ghi</div>");
   1214  let def = gEditor.querySelector("li").firstChild;
   1215  let ghi = gEditor.querySelector("ul").nextSibling;
   1216  gSelection.collapse(def, 5);
   1217  await sendDeleteKey();
   1218  checkEditorContentResultAsSubTest(
   1219    [
   1220      "<div>abc <ul><li>  defghi</li></ul></div>",
   1221      "<div>abc <ul><li>defghi</li></ul></div>",
   1222      "<div>abc<ul><li>defghi</li></ul></div>",
   1223    ],
   1224    t.name
   1225  );
   1226  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1227    startContainer: def,
   1228    startOffset: 5,
   1229    endContainer: ghi,
   1230    endOffset: 1,
   1231  });
   1232  checkGetTargetRangesOfInputOnDeleteSomething();
   1233 }, 'Delete at "<div>abc <ul><li>  def[]  </li></ul> ghi</div>"');
   1234 
   1235 promise_test(async (t) => {
   1236  initializeTest("<div>abc <ul><li>  def  </li></ul> ghi</div>");
   1237  let def = gEditor.querySelector("li").firstChild;
   1238  let ghi = gEditor.querySelector("ul").nextSibling;
   1239  gSelection.collapse(def, def.length);
   1240  await sendDeleteKey();
   1241  checkEditorContentResultAsSubTest(
   1242    [
   1243      "<div>abc <ul><li>  defghi</li></ul></div>",
   1244      "<div>abc <ul><li>defghi</li></ul></div>",
   1245      "<div>abc<ul><li>defghi</li></ul></div>",
   1246    ],
   1247    t.name
   1248  );
   1249  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1250    startContainer: def,
   1251    startOffset: 5,
   1252    endContainer: ghi,
   1253    endOffset: 1,
   1254  });
   1255  checkGetTargetRangesOfInputOnDeleteSomething();
   1256 }, 'Delete at "<div>abc <ul><li>  def  []</li></ul> ghi</div>"');
   1257 
   1258 promise_test(async (t) => {
   1259  initializeTest("<div>abc<ul><li>def</li><li>ghi</li></ul>jkl</div>");
   1260  let abc = gEditor.querySelector("div").firstChild;
   1261  let def = gEditor.querySelector("li").firstChild;
   1262  gSelection.collapse(abc, 3);
   1263  await sendDeleteKey();
   1264  checkEditorContentResultAsSubTest(
   1265    "<div>abcdef<ul><li>ghi</li></ul>jkl</div>",
   1266    t.name
   1267  );
   1268  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1269    startContainer: abc,
   1270    startOffset: 3,
   1271    endContainer: def,
   1272    endOffset: 0,
   1273  });
   1274  checkGetTargetRangesOfInputOnDeleteSomething();
   1275 }, 'Delete at "<div>abc[]<ul><li>def</li><li>ghi</li></ul>jkl</div>"');
   1276 
   1277 promise_test(async (t) => {
   1278  initializeTest("<div>abc<ul><li>def</li><li>ghi</li></ul>jkl</div>");
   1279  let def = gEditor.querySelector("li").firstChild;
   1280  let ghi = gEditor.querySelector("li + li").firstChild;
   1281  gSelection.collapse(def, 3);
   1282  await sendDeleteKey();
   1283  checkEditorContentResultAsSubTest(
   1284    "<div>abc<ul><li>defghi</li></ul>jkl</div>",
   1285    t.name
   1286  );
   1287  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1288    startContainer: def,
   1289    startOffset: 3,
   1290    endContainer: ghi,
   1291    endOffset: 0,
   1292  });
   1293  checkGetTargetRangesOfInputOnDeleteSomething();
   1294 }, 'Delete at "<div>abc<ul><li>def[]</li><li>ghi</li></ul>jkl</div>"');
   1295 
   1296 promise_test(async (t) => {
   1297  initializeTest("<div>abc<ul><li>def</li><li>ghi</li></ul>jkl</div>");
   1298  let ghi = gEditor.querySelector("li + li").firstChild;
   1299  let jkl = gEditor.querySelector("ul").nextSibling;
   1300  gSelection.collapse(ghi, 3);
   1301  await sendDeleteKey();
   1302  checkEditorContentResultAsSubTest(
   1303    "<div>abc<ul><li>def</li><li>ghijkl</li></ul></div>",
   1304    t.name
   1305  );
   1306  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1307    startContainer: ghi,
   1308    startOffset: 3,
   1309    endContainer: jkl,
   1310    endOffset: 0,
   1311  });
   1312  checkGetTargetRangesOfInputOnDeleteSomething();
   1313 }, 'Delete at "<div>abc<ul><li>def</li><li>ghi[]</li></ul>jkl</div>"');
   1314 
   1315 // Delete in empty paragraph should remove the empty paragraph.  In this
   1316 // case, it should be treated as joining with the previous paragraph.
   1317 // The target range should include the invisible <br> element in the empty
   1318 // paragraph.
   1319 promise_test(async (t) => {
   1320  initializeTest("<p><br></p><p>abc</p>");
   1321  let p1 = gEditor.querySelector("p");
   1322  let p2 = p1.nextSibling;
   1323  let abc = p2.firstChild;
   1324  gSelection.collapse(p1, 0);
   1325  await sendDeleteKey();
   1326  checkEditorContentResultAsSubTest("<p>abc</p>", t.name);
   1327  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1328    startContainer: p1,
   1329    startOffset: 0,
   1330    endContainer: abc,
   1331    endOffset: 0,
   1332  });
   1333  checkGetTargetRangesOfInputOnDeleteSomething();
   1334 }, 'Delete at "<p>{}<br></p><p>abc</p>"');
   1335 
   1336 // Delete ignore the empty span and the other things must be same as the
   1337 // previous test.
   1338 promise_test(async (t) => {
   1339  initializeTest("<p><span></span><br></p><p>abc</p>");
   1340  let p1 = gEditor.querySelector("p");
   1341  let span = p1.firstChild;
   1342  let p2 = p1.nextSibling;
   1343  let abc = p2.firstChild;
   1344  gSelection.collapse(span, 0);
   1345  await sendDeleteKey();
   1346  checkEditorContentResultAsSubTest("<p>abc</p>", t.name);
   1347  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1348    startContainer: p1,
   1349    startOffset: 0,
   1350    endContainer: abc,
   1351    endOffset: 0,
   1352  });
   1353  checkGetTargetRangesOfInputOnDeleteSomething();
   1354 }, 'Delete at "<p><span>{}</span><br></p><p>abc</p>"');
   1355 
   1356 // If invisible white-spaces are removed with same action as above tests,
   1357 // the range should be included in the target ranges.
   1358 promise_test(async (t) => {
   1359  initializeTest("<p><br></p><p>  abc</p>");
   1360  let p1 = gEditor.querySelector("p");
   1361  let p2 = p1.nextSibling;
   1362  let abc = p2.firstChild;
   1363  gSelection.collapse(p1, 0);
   1364  await sendDeleteKey();
   1365  checkEditorContentResultAsSubTest(
   1366    [
   1367      "<p>  abc</p>",
   1368      "<p>abc</p>",
   1369    ],
   1370    t.name
   1371  );
   1372  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1373    startContainer: p1,
   1374    startOffset: 0,
   1375    endContainer: abc,
   1376    endOffset: 5 - abc.length,
   1377  });
   1378  checkGetTargetRangesOfInputOnDeleteSomething();
   1379 }, 'Delete at "<p>{}<br></p><p>  abc</p>"');
   1380 
   1381 // If the next block begins with non-editable content, target range
   1382 // should be at the non-editable content node.
   1383 promise_test(async (t) => {
   1384  initializeTest("<p><br></p><p><span contenteditable=\"false\">abc</span>def</p>");
   1385  let p1 = gEditor.querySelector("p");
   1386  let p2 = p1.nextSibling;
   1387  let span = gEditor.querySelector("span");
   1388  gSelection.collapse(p1, 0);
   1389  await sendDeleteKey();
   1390  checkEditorContentResultAsSubTest(
   1391    "<p><span contenteditable=\"false\">abc</span>def</p>",
   1392    t.name
   1393  );
   1394  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1395    startContainer: p1,
   1396    startOffset: 0,
   1397    endContainer: p2,
   1398    endOffset: 0,
   1399  });
   1400  checkGetTargetRangesOfInputOnDeleteSomething();
   1401 }, 'Delete at "<p>{}<br></p><p><span contenteditable="false">abc</span>def</p>"');
   1402 
   1403 // If next non-editable paragraph is deleted, target range should end
   1404 // with start of the text node in the last paragraph.  Otherwise, ends at
   1405 // the non-editable paragraph.
   1406 promise_test(async (t) => {
   1407  initializeTest("<p><br></p><p contenteditable=\"false\">abc</p><p>def</p>");
   1408  let p1 = gEditor.querySelector("p");
   1409  let p2 = p1.nextSibling;
   1410  let p3 = p2.nextSibling;
   1411  let def = p3.firstChild;
   1412  gSelection.collapse(p3, 0);
   1413  await sendDeleteKey();
   1414  checkEditorContentResultAsSubTest(
   1415    [
   1416      "<p>def</p>",
   1417      "<p contenteditable=\"false\">abc</p><p>def</p>",
   1418    ],
   1419    t.name
   1420  );
   1421  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1422    startContainer: p1,
   1423    startOffset: 0,
   1424    endContainer: p2.isConnected ? gEditor : p3,
   1425    endOffset: p2.isConnected ? 1 : 0,
   1426  });
   1427  checkGetTargetRangesOfInputOnDeleteSomething();
   1428 }, 'Delete at "<p>{}<br></p><p contenteditable=\"false\">abc</p><p>def</p>"');
   1429 
   1430 promise_test(async (t) => {
   1431  initializeTest("<p>abc<span contenteditable=\"false\">def</span>ghi</p>");
   1432  let p = gEditor.querySelector("p");
   1433  let abc = p.firstChild;
   1434  gSelection.collapse(abc, 3);
   1435  await sendDeleteKey();
   1436  checkEditorContentResultAsSubTest(
   1437    [
   1438      "<p>abc<span contenteditable=\"false\">def</span>ghi</p>",
   1439      "<p>abcghi</p>",
   1440      "<p>abcghi<br></p>",
   1441    ],
   1442    t.name
   1443  );
   1444  if (gEditor.innerHTML === "<p>abc<span contenteditable=\"false\">def</span>ghi</p>") {
   1445    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1446      startContainer: abc,
   1447      startOffset: 3,
   1448      endContainer: abc,
   1449      endOffset: 3,
   1450    });
   1451    checkGetTargetRangesOfInputOnDoNothing();
   1452  } else {
   1453    // If the non-editable `<span>` is deleted, it should be treated as
   1454    // an atomic node.
   1455    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1456      startContainer: p,
   1457      startOffset: 1,
   1458      endContainer: p,
   1459      endOffset: 2,
   1460    });
   1461    checkGetTargetRangesOfInputOnDeleteSomething();
   1462  }
   1463 }, 'Delete at "<p>abc[]<span contenteditable=\"false\">def</span>ghi</p>"');
   1464 
   1465 // If just removes the paragraph, target range should end at the table element.
   1466 promise_test(async (t) => {
   1467  initializeTest("<p><br></p><table><tr><td>cell</td></tr></table>");
   1468  let cell = gEditor.querySelector("td");
   1469  let p = gEditor.querySelector("p");
   1470  gSelection.collapse(p, 0);
   1471  await sendDeleteKey();
   1472  checkEditorContentResultAsSubTest(
   1473    [
   1474      "<table><tbody><tr><td>cell</td></tr></tbody></table>",
   1475      "<p><br></p><table><tbody><tr><td>cell</td></tr></tbody></table>",
   1476    ],
   1477    t.name
   1478  );
   1479  if (p.isConnected) {
   1480    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1481      startContainer: p,
   1482      startOffset: 0,
   1483      endContainer: p,
   1484      endOffset: 0,
   1485    });
   1486    checkGetTargetRangesOfInputOnDoNothing();
   1487  } else {
   1488    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1489      startContainer: p,
   1490      startOffset: 0,
   1491      endContainer: gEditor,
   1492      endOffset: 1,
   1493    });
   1494    checkGetTargetRangesOfInputOnDeleteSomething();
   1495  }
   1496 }, 'Delete at "<p>{}<br></p><table><tr><td>cell</td></tr></table>"');
   1497 
   1498 // If table cell won't be joined, target range should be collapsed in the
   1499 // cell.
   1500 promise_test(async (t) => {
   1501  initializeTest("<table><tr><td><br></td><td>cell2</td></tr></table>");
   1502  let cell1 = gEditor.querySelector("td");
   1503  let cell2 = cell1.nextSibling;
   1504  gSelection.collapse(cell1, 0);
   1505  await sendDeleteKey();
   1506  checkEditorContentResultAsSubTest(
   1507    "<table><tbody><tr><td><br></td><td>cell2</td></tr></tbody></table>",
   1508    t.name
   1509  );
   1510  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1511    startContainer: cell1,
   1512    startOffset: 0,
   1513    endContainer: cell1,
   1514    endOffset: 0,
   1515  });
   1516  checkGetTargetRangesOfInputOnDoNothing();
   1517 }, 'Delete at "<table><tr><td>{}<br></td><td>cell2</td></tr></table>"');
   1518 
   1519 // If table caption won't be deleted, target range should be collapsed in the
   1520 // caption element.
   1521 promise_test(async (t) => {
   1522  initializeTest("<table><caption><br></caption><tr><td>cell</td></tr></table>");
   1523  let caption = gEditor.querySelector("caption");
   1524  gSelection.collapse(caption, 0);
   1525  await sendDeleteKey();
   1526  checkEditorContentResultAsSubTest(
   1527    "<table><caption><br></caption><tbody><tr><td>cell</td></tr></tbody></table>",
   1528    t.name
   1529  );
   1530  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1531    startContainer: caption,
   1532    startOffset: 0,
   1533    endContainer: caption,
   1534    endOffset: 0,
   1535  });
   1536  checkGetTargetRangesOfInputOnDoNothing();
   1537 }, 'Delete at "<table><caption>{}<br></caption><tr><td>cell</td></tr></table>"');
   1538 
   1539 // If a table cell element is selected, only its content should be deleted.
   1540 promise_test(async (t) => {
   1541  initializeTest("<table><tr><td>cell1</td><td>cell2</td></tr></table>");
   1542  let cell1 = gEditor.querySelector("td");
   1543  let tr = cell1.parentNode;
   1544  gSelection.setBaseAndExtent(tr, 0, tr, 1);
   1545  await sendDeleteKey();
   1546  checkEditorContentResultAsSubTest(
   1547    [
   1548      "<table><tbody><tr><td></td><td>cell2</td></tr></tbody></table>",
   1549      "<table><tbody><tr><td><br></td><td>cell2</td></tr></tbody></table>",
   1550    ],
   1551    t.name
   1552  );
   1553  // XXX Perhaps, target range should be selecting only all children of
   1554  //     cell1 instead.
   1555  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1556    startContainer: tr,
   1557    startOffset: 0,
   1558    endContainer: tr,
   1559    endOffset: 1,
   1560  });
   1561  checkGetTargetRangesOfInputOnDeleteSomething();
   1562 }, 'Delete at "<table><tr>{<td>cell1</td>}<td>cell2</td></tr></table>"');
   1563 
   1564 promise_test(async (t) => {
   1565  initializeTest("<table><tr><td>cell1</td><td>cell2</td></tr></table>");
   1566  let cell2 = gEditor.querySelector("td + td");
   1567  let tr = cell2.parentNode;
   1568  gSelection.setBaseAndExtent(tr, 1, tr, 2);
   1569  await sendDeleteKey();
   1570  checkEditorContentResultAsSubTest(
   1571    [
   1572      "<table><tbody><tr><td>cell1</td><td></td></tr></tbody></table>",
   1573      "<table><tbody><tr><td>cell1</td><td><br></td></tr></tbody></table>",
   1574    ],
   1575    t.name
   1576  );
   1577  // XXX Perhaps, target range should be selecting only all children of
   1578  //     cell1 instead.
   1579  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1580    startContainer: tr,
   1581    startOffset: 1,
   1582    endContainer: tr,
   1583    endOffset: 2,
   1584  });
   1585  checkGetTargetRangesOfInputOnDeleteSomething();
   1586 }, 'Delete at "<table><tr><td>cell1</td>{<td>cell2</td>}</tr></table>"');
   1587 
   1588 // If the last table cell element is selected, what browsers should do?
   1589 promise_test(async (t) => {
   1590  initializeTest("<table><tr><td>cell</td></tr></table>");
   1591  let cell = gEditor.querySelector("td");
   1592  let tr = cell.parentNode;
   1593  let table = gEditor.querySelector("table");
   1594  gSelection.setBaseAndExtent(tr, 0, tr, 1);
   1595  await sendDeleteKey();
   1596  checkEditorContentResultAsSubTest(
   1597    [
   1598      "<table><tbody><tr><td></td></tr></tbody></table>",
   1599      "<table><tbody><tr><td><br></td></tr></tbody></table>",
   1600      "<br>",
   1601    ],
   1602    t.name
   1603  );
   1604  if (gEditor.querySelector("table")) {
   1605    // XXX Perhaps, target range should be selecting only all children of
   1606    //     cell1 instead.
   1607    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1608      startContainer: tr,
   1609      startOffset: 0,
   1610      endContainer: tr,
   1611      endOffset: 1,
   1612    });
   1613  } else {
   1614    // If it causes deleting entire the table, the `<table>` element should
   1615    // be in the target range.
   1616    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1617      startContainer: gEditor,
   1618      startOffset: 0,
   1619      endContainer: gEditor,
   1620      endOffset: 1,
   1621    });
   1622  }
   1623  checkGetTargetRangesOfInputOnDeleteSomething();
   1624 }, 'Delete at "<table><tr>{<td>cell</td>}</tr></table>"');
   1625 
   1626 // Testing multiple cell selection mode.
   1627 promise_test(async (t) => {
   1628  initializeTest("<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>");
   1629  let cell1 = gEditor.querySelector("td");
   1630  let cell4 = gEditor.querySelector("tr + tr > td + td");
   1631  let tr1 = cell1.parentNode;
   1632  let tr2 = cell4.parentNode;
   1633  gSelection.removeAllRanges();
   1634  let range = document.createRange();
   1635  range.selectNode(cell1);
   1636  gSelection.addRange(range);
   1637  range = document.createRange();
   1638  range.selectNode(cell4);
   1639  gSelection.addRange(range);
   1640  assert_equals(gSelection.rangeCount, 2, "Should support multiple cell selection");
   1641  await sendDeleteKey();
   1642  checkEditorContentResultAsSubTest(
   1643    [
   1644      "<table><tbody><tr><td></td><td>cell2</td></tr><tr><td>cell3</td><td></td></tr></tbody></table>",
   1645      "<table><tbody><tr><td><br></td><td>cell2</td></tr><tr><td>cell3</td><td><br></td></tr></tbody></table>",
   1646    ],
   1647    t.name
   1648  );
   1649  // XXX Perhaps, target range should be selecting only all children of
   1650  //     cell1 and cell4 instead.
   1651  checkGetTargetRangesOfBeforeinputOnDeleteSomething([
   1652    {
   1653      startContainer: tr1,
   1654      startOffset: 0,
   1655      endContainer: tr1,
   1656      endOffset: 1,
   1657    },
   1658    {
   1659      startContainer: tr2,
   1660      startOffset: 1,
   1661      endContainer: tr2,
   1662      endOffset: 2,
   1663    },
   1664  ]);
   1665  checkGetTargetRangesOfInputOnDeleteSomething();
   1666 }, 'Delete at "<table><tr>{<td>cell1</td>}<td>cell2</td></tr><tr><td>cell3</td>{<td>cell4</td>}</tr></table>"');
   1667 
   1668 promise_test(async (t) => {
   1669  initializeTest("<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>");
   1670  let cell1 = gEditor.querySelector("td");
   1671  let cell3 = gEditor.querySelector("tr + tr > td");
   1672  let tr1 = cell1.parentNode;
   1673  let tr2 = cell3.parentNode;
   1674  gSelection.removeAllRanges();
   1675  let range = document.createRange();
   1676  range.selectNode(cell1);
   1677  gSelection.addRange(range);
   1678  range = document.createRange();
   1679  range.selectNode(cell3);
   1680  gSelection.addRange(range);
   1681  assert_equals(gSelection.rangeCount, 2, "Should support multiple cell selection");
   1682  await sendDeleteKey();
   1683  checkEditorContentResultAsSubTest(
   1684    [
   1685      "<table><tbody><tr><td></td><td>cell2</td></tr><tr><td></td><td>cell4</td></tr></tbody></table>",
   1686      "<table><tbody><tr><td><br></td><td>cell2</td></tr><tr><td><br></td><td>cell4</td></tr></tbody></table>",
   1687      "<table><tbody><tr><td>cell2</td></tr><tr><td>cell4</td></tr></tbody></table>",
   1688    ],
   1689    t.name
   1690  );
   1691  // XXX Perhaps, target range should be selecting only all children of
   1692  //     cell1 and cell3 instead.
   1693  checkGetTargetRangesOfBeforeinputOnDeleteSomething([
   1694    {
   1695      startContainer: tr1,
   1696      startOffset: 0,
   1697      endContainer: tr1,
   1698      endOffset: 1,
   1699    },
   1700    {
   1701      startContainer: tr2,
   1702      startOffset: 0,
   1703      endContainer: tr2,
   1704      endOffset: 1,
   1705    },
   1706  ]);
   1707  checkGetTargetRangesOfInputOnDeleteSomething();
   1708 }, 'Delete at "<table><tr>{<td>cell1</td>}<td>cell2</td></tr><tr>{<td>cell3</td>}<td>cell4</td></tr></table>"');
   1709 
   1710 promise_test(async (t) => {
   1711  initializeTest("<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>");
   1712  let cell1 = gEditor.querySelector("td");
   1713  let cell2 = gEditor.querySelector("td + td");
   1714  let tr1 = cell1.parentNode;
   1715  let tbody = tr1.parentNode;
   1716  gSelection.removeAllRanges();
   1717  let range = document.createRange();
   1718  range.selectNode(cell1);
   1719  gSelection.addRange(range);
   1720  range = document.createRange();
   1721  range.selectNode(cell2);
   1722  gSelection.addRange(range);
   1723  assert_equals(gSelection.rangeCount, 2, "Should support multiple cell selection");
   1724  await sendDeleteKey();
   1725  checkEditorContentResultAsSubTest(
   1726    [
   1727      "<table><tbody><tr><td></td><td></td></tr><tr><td>cell3</td><td>cell4</td></tr></tbody></table>",
   1728      "<table><tbody><tr><td><br></td><td><br></td></tr><tr><td>cell3</td><td>cell4</td></tr></tbody></table>",
   1729      "<table><tbody><tr><td>cell3</td><td>cell4</td></tr></tbody></table>",
   1730    ],
   1731    t.name
   1732  );
   1733  if (gEditor.querySelector("tr + tr")) {
   1734    // XXX Perhaps, target range should be selecting only all children of
   1735    //     cell1 and cell2 instead.
   1736    checkGetTargetRangesOfBeforeinputOnDeleteSomething([
   1737      {
   1738        startContainer: tr1,
   1739        startOffset: 0,
   1740        endContainer: tr1,
   1741        endOffset: 1,
   1742      },
   1743      {
   1744        startContainer: tr1,
   1745        startOffset: 1,
   1746        endContainer: tr1,
   1747        endOffset: 2,
   1748      },
   1749    ]);
   1750  } else {
   1751    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1752      startContainer: tbody,
   1753      startOffset: 0,
   1754      endContainer: tbody,
   1755      endOffset: 1,
   1756    });
   1757  }
   1758  checkGetTargetRangesOfInputOnDeleteSomething();
   1759 }, 'Delete at "<table><tr>{<td>cell1</td>}{<td>cell2</td>}</tr><tr><td>cell3</td><td>cell4</td></tr></table>"');
   1760 
   1761 promise_test(async (t) => {
   1762  initializeTest("<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>");
   1763  let cell3 = gEditor.querySelector("tr + tr > td");
   1764  let cell4 = gEditor.querySelector("tr + tr > td + td");
   1765  let tr2 = cell3.parentNode;
   1766  gSelection.removeAllRanges();
   1767  let range = document.createRange();
   1768  range.selectNode(cell3);
   1769  gSelection.addRange(range);
   1770  range = document.createRange();
   1771  range.selectNode(cell4);
   1772  gSelection.addRange(range);
   1773  assert_equals(gSelection.rangeCount, 2, "Should support multiple cell selection");
   1774  await sendDeleteKey();
   1775  checkEditorContentResultAsSubTest(
   1776    [
   1777      "<table><tbody><tr><td>cell1</td><td>cell2</td></tr><tr><td></td><td></td></tr></tbody></table>",
   1778      "<table><tbody><tr><td>cell1</td><td>cell2</td></tr><tr><td><br></td><td><br></td></tr></tbody></table>",
   1779      "<table><tbody><tr><td>cell1</td><td>cell2</td></tr></tbody></table>",
   1780    ],
   1781    t.name
   1782  );
   1783  if (gEditor.querySelector("tr + tr")) {
   1784    // XXX Perhaps, target range should be selecting only all children of
   1785    //     cell3 and cell4 instead.
   1786    checkGetTargetRangesOfBeforeinputOnDeleteSomething([
   1787      {
   1788        startContainer: tr2,
   1789        startOffset: 0,
   1790        endContainer: tr2,
   1791        endOffset: 1,
   1792      },
   1793      {
   1794        startContainer: tr2,
   1795        startOffset: 1,
   1796        endContainer: tr2,
   1797        endOffset: 2,
   1798      },
   1799    ]);
   1800  } else {
   1801    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1802      startContainer: tbody,
   1803      startOffset: 1,
   1804      endContainer: tbody,
   1805      endOffset: 2,
   1806    });
   1807  }
   1808  checkGetTargetRangesOfInputOnDeleteSomething();
   1809 }, 'Delete at "<table><tr><td>cell1</td><td>cell2</td></tr><tr>{<td>cell3</td>}{<td>cell4</td>}</tr></table>"');
   1810 
   1811 promise_test(async (t) => {
   1812  initializeTest("<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>");
   1813  let cell1 = gEditor.querySelector("td");
   1814  let cell2 = gEditor.querySelector("td + td");
   1815  let cell3 = gEditor.querySelector("tr + tr > td");
   1816  let cell4 = gEditor.querySelector("tr + tr > td + td");
   1817  let tr1 = cell1.parentNode;
   1818  let tr2 = cell3.parentNode;
   1819  gSelection.removeAllRanges();
   1820  let range = document.createRange();
   1821  range.selectNode(cell1);
   1822  gSelection.addRange(range);
   1823  range = document.createRange();
   1824  range.selectNode(cell2);
   1825  gSelection.addRange(range);
   1826  range = document.createRange();
   1827  range.selectNode(cell3);
   1828  gSelection.addRange(range);
   1829  range = document.createRange();
   1830  range.selectNode(cell4);
   1831  gSelection.addRange(range);
   1832  assert_equals(gSelection.rangeCount, 4, "Should support multiple cell selection");
   1833  await sendDeleteKey();
   1834  checkEditorContentResultAsSubTest(
   1835    [
   1836      "<table><tbody><tr><td></td><td></td></tr><tr><td></td><td></td></tr></tbody></table>",
   1837      "<table><tbody><tr><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td></tr></tbody></table>",
   1838      "<br>",
   1839    ],
   1840    t.name
   1841  );
   1842  if (gEditor.querySelector("table")) {
   1843    // XXX Perhaps, target range should be selecting only all children of
   1844    //     cell1, cell2, cell3 and cell4 instead.
   1845    checkGetTargetRangesOfBeforeinputOnDeleteSomething([
   1846      {
   1847        startContainer: tr1,
   1848        startOffset: 0,
   1849        endContainer: tr1,
   1850        endOffset: 1,
   1851      },
   1852      {
   1853        startContainer: tr1,
   1854        startOffset: 1,
   1855        endContainer: tr1,
   1856        endOffset: 2,
   1857      },
   1858      {
   1859        startContainer: tr2,
   1860        startOffset: 0,
   1861        endContainer: tr2,
   1862        endOffset: 1,
   1863      },
   1864      {
   1865        startContainer: tr2,
   1866        startOffset: 1,
   1867        endContainer: tr2,
   1868        endOffset: 2,
   1869      },
   1870    ]);
   1871  } else {
   1872    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1873      startContainer: gEditor,
   1874      startOffset: 0,
   1875      endContainer: gEditor,
   1876      endOffset: 1,
   1877    });
   1878  }
   1879  checkGetTargetRangesOfInputOnDeleteSomething();
   1880 }, 'Delete at "<table><tr>{<td>cell1</td>}{<td>cell2</td>}</tr><tr>{<td>cell3</td>}{<td>cell4</td>}</tr></table>"');
   1881 
   1882 promise_test(async (t) => {
   1883  initializeTest("<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>");
   1884  let cell1 = gEditor.querySelector("td");
   1885  let cell2 = gEditor.querySelector("td + td");
   1886  let cell4 = gEditor.querySelector("tr + tr > td + td");
   1887  let tr1 = cell1.parentNode;
   1888  let tr2 = cell4.parentNode;
   1889  gSelection.removeAllRanges();
   1890  let range = document.createRange();
   1891  range.selectNode(cell1);
   1892  gSelection.addRange(range);
   1893  range = document.createRange();
   1894  range.setStart(cell2.firstChild, 1);
   1895  range.setEnd(cell2.firstChild, 4);
   1896  gSelection.addRange(range);
   1897  range = document.createRange();
   1898  range.selectNode(cell4);
   1899  gSelection.addRange(range);
   1900  assert_equals(gSelection.rangeCount, 3, "Should support multiple cell selection");
   1901  await sendDeleteKey();
   1902  checkEditorContentResultAsSubTest(
   1903    [
   1904      "<table><tbody><tr><td></td><td>cell2</td></tr><tr><td>cell3</td><td></td></tr></tbody></table>",
   1905      "<table><tbody><tr><td><br></td><td>cell2</td></tr><tr><td>cell3</td><td><br></td></tr></tbody></table>",
   1906      "<table><tbody><tr><td></td><td>c2</td></tr><tr><td>cell3</td><td></td></tr></tbody></table>",
   1907      "<table><tbody><tr><td><br></td><td>c2</td></tr><tr><td>cell3</td><td><br></td></tr></tbody></table>",
   1908    ],
   1909    t.name
   1910  );
   1911  if (cell2.firstChild.length == "cell2".length) {
   1912    // XXX Perhaps, target range should be selecting only all children of
   1913    //     cell1 and cell4 instead.
   1914    checkGetTargetRangesOfBeforeinputOnDeleteSomething([
   1915      {
   1916        startContainer: tr1,
   1917        startOffset: 0,
   1918        endContainer: tr1,
   1919        endOffset: 1,
   1920      },
   1921      {
   1922        startContainer: tr2,
   1923        startOffset: 1,
   1924        endContainer: tr2,
   1925        endOffset: 2,
   1926      },
   1927    ]);
   1928  } else {
   1929    checkGetTargetRangesOfBeforeinputOnDeleteSomething([
   1930      {
   1931        startContainer: tr1,
   1932        startOffset: 0,
   1933        endContainer: tr1,
   1934        endOffset: 1,
   1935      },
   1936      {
   1937        startContainer: cell2.firstChild,
   1938        startOffset: 1,
   1939        endContainer: cell2.firstChild,
   1940        endOffset: 4,
   1941      },
   1942      {
   1943        startContainer: tr2,
   1944        startOffset: 1,
   1945        endContainer: tr2,
   1946        endOffset: 2,
   1947      },
   1948    ]);
   1949  }
   1950  checkGetTargetRangesOfInputOnDeleteSomething();
   1951 }, 'Delete at "<table><tr>{<td>cell1</td>}<td>c[ell]2</td></tr><tr>{<td>cell3</td>}<td>cell4</td></tr></table>"');
   1952 
   1953 // If caret is not adjacent of deleting character, browser may not delete the
   1954 // character, but update the caret position for next deletion.
   1955 promise_test(async (t) => {
   1956  initializeTest("<p>hello&#x5E9;&#x5DC;&#x5D5;&#x5DD;</p>");
   1957  let text1 = gEditor.querySelector("p").firstChild;
   1958  let text2 = text1.nextSibling;
   1959  gSelection.collapse(text1, 4);
   1960  await sendArrowRightKey();
   1961  await sendDeleteKey();
   1962  checkEditorContentResultAsSubTest(
   1963    [
   1964      "<p>hello\u05E9\u05DC\u05D5\u05DD</p>",
   1965      "<p>hello\u05DC\u05D5\u05DD</p>",
   1966      "<p>hello\u05E9\u05DC\u05D5</p>",
   1967    ],
   1968    t.name
   1969  );
   1970  if (gEditor.innerHTML === "<p>hello\u05E9\u05DC\u05D5\u05DD</p>") {
   1971    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1972      startContainer: text2 ? text2 : text1,
   1973      startOffset: text2 ? 0 : 5,
   1974      endContainer: text2 ? text2 : text1,
   1975      endOffset: text2 ? 0 : 5,
   1976    });
   1977    checkGetTargetRangesOfInputOnDoNothing();
   1978  } else if (gEditor.innerHTML === "<p>hello\u05DC\u05D5\u05DD</p>") {
   1979    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1980      startContainer: text2 ? text2: text1,
   1981      startOffset: text2 ? 0 : 5,
   1982      endContainer: text2 ? text2 : text1,
   1983      endOffset: text2 ? 1 : 6,
   1984    });
   1985    checkGetTargetRangesOfInputOnDeleteSomething();
   1986  } else {
   1987    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   1988      startContainer: text2 ? text2: text1,
   1989      startOffset: text2 ? 3 : 8,
   1990      endContainer: text2 ? text2 : text1,
   1991      endOffset: text2 ? 4 : 9,
   1992    });
   1993    checkGetTargetRangesOfInputOnDeleteSomething();
   1994  }
   1995 }, 'Delete at "<p>hello[]&#x5E9;&#x5DC;&#x5D5;&#x5DD;</p>"');
   1996 
   1997 // The following tests check whether the range returned from
   1998 // `beforeinput[0].getTargetRanges()` is modified or different range is
   1999 // modified instead.  I.e., they don't test which type of deletion should
   2000 // occur.  Therefore, their result depends on browser's key bindings,
   2001 // system settings and running OS.
   2002 
   2003 function getFirstDifferentOffset(currentString, originalString) {
   2004  for (let i = 0; i < currentString.length; i++) {
   2005    if (currentString.charAt(i) !== originalString.charAt(i) &&
   2006        (originalString.charAt(i) !== " " || !currentString.charAt("\u00A0"))) {
   2007      return i;
   2008    }
   2009  }
   2010  return currentString.length;
   2011 }
   2012 
   2013 promise_test(async (t) => {
   2014  const kText = "abc def ghi";
   2015  initializeTest(`<p>${kText}</p>`);
   2016  let p = gEditor.querySelector("p");
   2017  gSelection.collapse(p.firstChild, "abc ".length);
   2018  await sendDeleteKey(kShift);
   2019  let startOffset = getFirstDifferentOffset(p.firstChild.data, kText);
   2020  let length = kText.length - p.firstChild.data.length;
   2021  checkEditorContentResultAsSubTest(
   2022    `<p>${kText.substr(0, startOffset) + kText.substr(startOffset + length)}</p>`,
   2023    t.name,
   2024    { ignoreWhiteSpaceDifference: true }
   2025  );
   2026  if (startOffset === kText.length) {
   2027    checkBeforeinputAndInputEventsOnNOOP();
   2028    return;
   2029  }
   2030  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   2031    startContainer: p.firstChild,
   2032    startOffset: startOffset,
   2033    endContainer: p.firstChild,
   2034    endOffset: startOffset + length,
   2035  });
   2036  checkGetTargetRangesOfInputOnDeleteSomething();
   2037 }, 'Shift + Delete at "<p>abc []def ghi</p>"');
   2038 
   2039 promise_test(async (t) => {
   2040  const kText = "abc def ghi";
   2041  initializeTest(`<p>${kText}</p>`);
   2042  let p = gEditor.querySelector("p");
   2043  gSelection.collapse(p.firstChild, "abc ".length);
   2044  await sendDeleteKey(kControl);
   2045  let startOffset = getFirstDifferentOffset(p.firstChild.data, kText);
   2046  let length = kText.length - p.firstChild.data.length;
   2047  checkEditorContentResultAsSubTest(
   2048    `<p>${kText.substr(0, startOffset) + kText.substr(startOffset + length)}</p>`,
   2049    t.name,
   2050    { ignoreWhiteSpaceDifference: true }
   2051  );
   2052  if (startOffset === kText.length) {
   2053    checkBeforeinputAndInputEventsOnNOOP();
   2054    return;
   2055  }
   2056  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   2057    startContainer: p.firstChild,
   2058    startOffset: startOffset,
   2059    endContainer: p.firstChild,
   2060    endOffset: startOffset + length,
   2061  });
   2062  checkGetTargetRangesOfInputOnDeleteSomething();
   2063 }, 'Control + Delete at "<p>abc []def ghi</p>"');
   2064 
   2065 promise_test(async (t) => {
   2066  const kText = "abc def ghi";
   2067  initializeTest(`<p>${kText}</p>`);
   2068  let p = gEditor.querySelector("p");
   2069  gSelection.collapse(p.firstChild, "abc ".length);
   2070  await sendDeleteKey(kAlt);
   2071  let startOffset = getFirstDifferentOffset(p.firstChild.data, kText);
   2072  let length = kText.length - p.firstChild.data.length;
   2073  checkEditorContentResultAsSubTest(
   2074    `<p>${kText.substr(0, startOffset) + kText.substr(startOffset + length)}</p>`,
   2075    t.name,
   2076    { ignoreWhiteSpaceDifference: true }
   2077  );
   2078  if (startOffset === kText.length) {
   2079    checkBeforeinputAndInputEventsOnNOOP();
   2080    return;
   2081  }
   2082  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   2083    startContainer: p.firstChild,
   2084    startOffset: startOffset,
   2085    endContainer: p.firstChild,
   2086    endOffset: startOffset + length,
   2087  });
   2088  checkGetTargetRangesOfInputOnDeleteSomething();
   2089 }, 'Alt + Delete at "<p>abc []def ghi</p>"');
   2090 
   2091 promise_test(async (t) => {
   2092  const kText = "abc def ghi";
   2093  initializeTest(`<p>${kText}</p>`);
   2094  let p = gEditor.querySelector("p");
   2095  gSelection.collapse(p.firstChild, "abc ".length);
   2096  await sendDeleteKey(kMeta);
   2097  let startOffset = getFirstDifferentOffset(p.firstChild.data, kText);
   2098  let length = kText.length - p.firstChild.data.length;
   2099  checkEditorContentResultAsSubTest(
   2100    `<p>${kText.substr(0, startOffset) + kText.substr(startOffset + length)}</p>`,
   2101    t.name,
   2102    { ignoreWhiteSpaceDifference: true }
   2103  );
   2104  if (startOffset === kText.length) {
   2105    checkBeforeinputAndInputEventsOnNOOP();
   2106    return;
   2107  }
   2108  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   2109    startContainer: p.firstChild,
   2110    startOffset: startOffset,
   2111    endContainer: p.firstChild,
   2112    endOffset: startOffset + length,
   2113  });
   2114  checkGetTargetRangesOfInputOnDeleteSomething();
   2115 }, 'Meta + Delete at "<p>abc []def ghi</p>"');
   2116 
   2117 promise_test(async (t) => {
   2118  const kText = "abc def";
   2119  initializeTest(`<p>${kText}   </p>`);
   2120  let p = gEditor.querySelector("p");
   2121  gSelection.collapse(p.firstChild, "abc ".length);
   2122  await sendDeleteKey(kShift);
   2123  let visibleText = p.firstChild.data.replace(/%s+$/, "");
   2124  let invisibleWhiteSpaces = " ".repeat(p.firstChild.data.length - visibleText.length);
   2125  let startOffset = invisibleWhiteSpaces.length + getFirstDifferentOffset(visibleText, kText);
   2126  let length = kText.length + 3 - p.firstChild.data.length;
   2127  // If invisible white-spaces are deleted, they should be contained in the target range.
   2128  checkEditorContentResultAsSubTest(
   2129    `<p>${kText.substr(0, startOffset) + kText.substr(startOffset + length) + invisibleWhiteSpaces}</p>`,
   2130    t.name,
   2131    { ignoreWhiteSpaceDifference: true }
   2132  );
   2133  if (startOffset === kText.length) {
   2134    checkBeforeinputAndInputEventsOnNOOP();
   2135    return;
   2136  }
   2137  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   2138    startContainer: p.firstChild,
   2139    startOffset: startOffset,
   2140    endContainer: p.firstChild,
   2141    endOffset: startOffset + length,
   2142  });
   2143  checkGetTargetRangesOfInputOnDeleteSomething();
   2144 }, 'Shift + Delete at "<p>abc []def   </p>"');
   2145 
   2146 promise_test(async (t) => {
   2147  const kText = "abc def";
   2148  initializeTest(`<p>${kText}   </p>`);
   2149  let p = gEditor.querySelector("p");
   2150  gSelection.collapse(p.firstChild, "abc ".length);
   2151  await sendDeleteKey(kControl);
   2152  let visibleText = p.firstChild.data.replace(/%s+$/, "");
   2153  let invisibleWhiteSpaces = " ".repeat(p.firstChild.data.length - visibleText.length);
   2154  let startOffset = invisibleWhiteSpaces.length + getFirstDifferentOffset(visibleText, kText);
   2155  let length = kText.length + 3 - p.firstChild.data.length;
   2156  // If invisible white-spaces are deleted, they should be contained in the target range.
   2157  checkEditorContentResultAsSubTest(
   2158    `<p>${kText.substr(0, startOffset) + kText.substr(startOffset + length) + invisibleWhiteSpaces}</p>`,
   2159    t.name,
   2160    { ignoreWhiteSpaceDifference: true }
   2161  );
   2162  if (startOffset === kText.length) {
   2163    checkBeforeinputAndInputEventsOnNOOP();
   2164    return;
   2165  }
   2166  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   2167    startContainer: p.firstChild,
   2168    startOffset: startOffset,
   2169    endContainer: p.firstChild,
   2170    endOffset: startOffset + length,
   2171  });
   2172  checkGetTargetRangesOfInputOnDeleteSomething();
   2173 }, 'Control + Delete at "<p>abc []def   </p>"');
   2174 
   2175 promise_test(async (t) => {
   2176  const kText = "abc def";
   2177  initializeTest(`<p>${kText}   </p>`);
   2178  let p = gEditor.querySelector("p");
   2179  gSelection.collapse(p.firstChild, "abc ".length);
   2180  await sendDeleteKey(kAlt);
   2181  let visibleText = p.firstChild.data.replace(/%s+$/, "");
   2182  let invisibleWhiteSpaces = " ".repeat(p.firstChild.data.length - visibleText.length);
   2183  let startOffset = invisibleWhiteSpaces.length + getFirstDifferentOffset(visibleText, kText);
   2184  let length = kText.length + 3 - p.firstChild.data.length;
   2185  // If invisible white-spaces are deleted, they should be contained in the target range.
   2186  checkEditorContentResultAsSubTest(
   2187    `<p>${kText.substr(0, startOffset) + kText.substr(startOffset + length) + invisibleWhiteSpaces}</p>`,
   2188    t.name,
   2189    { ignoreWhiteSpaceDifference: true }
   2190  );
   2191  if (startOffset === kText.length) {
   2192    checkBeforeinputAndInputEventsOnNOOP();
   2193    return;
   2194  }
   2195  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   2196    startContainer: p.firstChild,
   2197    startOffset: startOffset,
   2198    endContainer: p.firstChild,
   2199    endOffset: startOffset + length,
   2200  });
   2201  checkGetTargetRangesOfInputOnDeleteSomething();
   2202 }, 'Alt + Delete at "<p>abc []def   </p>"');
   2203 
   2204 promise_test(async (t) => {
   2205  const kText = "abc def";
   2206  initializeTest(`<p>${kText}   s</p>`);
   2207  let p = gEditor.querySelector("p");
   2208  gSelection.collapse(p.firstChild, "abc ".length);
   2209  await sendDeleteKey(kMeta);
   2210  let visibleText = p.firstChild.data.replace(/%s+$/, "");
   2211  let invisibleWhiteSpaces = " ".repeat(p.firstChild.data.length - visibleText.length);
   2212  let startOffset = invisibleWhiteSpaces.length + getFirstDifferentOffset(visibleText, kText);
   2213  let length = kText.length + 3 - p.firstChild.data.length;
   2214  // If invisible white-spaces are deleted, they should be contained in the target range.
   2215  checkEditorContentResultAsSubTest(
   2216      `<p>${kText.substr(0, startOffset) + kText.substr(startOffset + length) + invisibleWhiteSpaces}</p>`,
   2217      t.name,
   2218      { ignoreWhiteSpaceDifference: true }
   2219  );
   2220  if (startOffset === kText.length) {
   2221    checkBeforeinputAndInputEventsOnNOOP();
   2222    return;
   2223  }
   2224  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
   2225    startContainer: p.firstChild,
   2226    startOffset: startOffset,
   2227    endContainer: p.firstChild,
   2228    endOffset: startOffset + length,
   2229  });
   2230  checkGetTargetRangesOfInputOnDeleteSomething();
   2231 }, 'Meta + Delete at "<p>abc []def</p>"');
   2232 
   2233 </script>