Bug 57079 - DeleteSelectionCommand::removeNode tries to insert block placeholder in non-editable table cell positions
Summary: DeleteSelectionCommand::removeNode tries to insert block placeholder in non-e...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: 528+ (Nightly build)
Hardware: Other OS X 10.5
: P2 Normal
Assignee: Benjamin (Ben) Kalman
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-03-24 21:57 PDT by Benjamin (Ben) Kalman
Modified: 2011-03-31 02:09 PDT (History)
9 users (show)

See Also:


Attachments
Patch (5.62 KB, patch)
2011-03-24 22:06 PDT, Benjamin (Ben) Kalman
no flags Details | Formatted Diff | Diff
Patch (6.41 KB, patch)
2011-03-24 22:33 PDT, Benjamin (Ben) Kalman
no flags Details | Formatted Diff | Diff
Patch (6.98 KB, patch)
2011-03-24 23:13 PDT, Benjamin (Ben) Kalman
no flags Details | Formatted Diff | Diff
Patch (7.36 KB, patch)
2011-03-27 23:49 PDT, Benjamin (Ben) Kalman
no flags Details | Formatted Diff | Diff
Patch (7.37 KB, patch)
2011-03-28 21:28 PDT, Benjamin (Ben) Kalman
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Benjamin (Ben) Kalman 2011-03-24 21:57:08 PDT
DeleteSelectionCommand::removeNode tries to insert block placeholder in non-editable table cell positions
Comment 1 Benjamin (Ben) Kalman 2011-03-24 22:06:00 PDT
Created attachment 86881 [details]
Patch
Comment 2 Ryosuke Niwa 2011-03-24 22:28:37 PDT
Comment on attachment 86881 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=86881&action=review

> Source/WebCore/editing/DeleteSelectionCommand.cpp:346
> +        Position firstEditablePositionInChild = firstEditablePositionInNode(child);
> +        if (firstEditablePositionInChild.isNotNull())
> +            return firstEditablePositionInChild;
> +        child = child->nextSibling();

I don't think this function needs be recursive.  Can't you just traverseNextNode(node)?
Comment 3 Benjamin (Ben) Kalman 2011-03-24 22:33:58 PDT
Created attachment 86884 [details]
Patch
Comment 4 Ryosuke Niwa 2011-03-24 22:46:02 PDT
Comment on attachment 86884 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=86884&action=review

> LayoutTests/editing/execCommand/delete-table-with-empty-contents-expected.txt:1
> +PASS

It'll be nice if you explain what this test is testing.

It'll be even nicer if you added some label next to each PASS/FAIL so that when a test fail, we can easily tell which one failed without having to count.
You can probably add a title attribute to each div and extract & print that in runTestForContainer.

> LayoutTests/editing/execCommand/delete-table-with-empty-contents.html:61
> +  var console = document.getElementsByTagName('pre')[0];

No need to indent these.

> LayoutTests/editing/execCommand/delete-table-with-empty-contents.html:75
> +  Array.prototype.slice.call(document.getElementsByTagName('div')).forEach(runTestForContainer);

Ah, this is really neat.
Comment 5 Benjamin (Ben) Kalman 2011-03-24 23:13:10 PDT
Created attachment 86891 [details]
Patch
Comment 6 Benjamin (Ben) Kalman 2011-03-24 23:16:48 PDT
Comment I was writing initially, but collided with your review :-)

---

As I've commented in the changelog, this bug is only observable in debug builds since it causes an ASSERT fail.

In any case, it's caused by the deletion of a non-editable table, when a cell's contents has no height.  This includes
 - no content
 - children amounting to no content (e.g. empty span(s))
 - editable children such that their contents is deleted, but due to one of the nodes being an editing root, not being deleted

An example of the latter case is:

<div contenteditable>
  <table contenteditable=false><tr><td>
    <span contenteditable=true>Deleting the whole table will crash a debug build</span>
  </td></tr></table>
</div>

Currently, removeNode inserts a placeholder when a table cell has no height after deletion.  However, it should only try to insert a placeholder if there actually is somewhere to insert one, and in which case, actually in that editable node rather than on the table cell itself.
Comment 7 Ryosuke Niwa 2011-03-25 00:06:12 PDT
Comment on attachment 86891 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=86891&action=review

> LayoutTests/editing/execCommand/delete-table-with-empty-contents-expected.txt:1
> +Tests that tables with inevitably empty content are deleted correctly.

I'm not sure if "inevitably empty content" is self-explanatory.  I wouldn't mind it be a little more verbose.

> LayoutTests/editing/execCommand/delete-table-with-empty-contents.html:2
> +<div contenteditable tests='empty'>

I'm not sure if it's really desirable to have custom "tests" attribute.  Is it allowed in HTML5 spec?  I mean what if in the future we decided to add tests attribute for whatever purpose in HTMLx.  Wouldn't this collide with that?  Ideally, we wouldn't need to worry about this test when that happens.

> LayoutTests/editing/execCommand/delete-table-with-empty-contents.html:73
> +      'FAIL (' + testDescription + '), should be empty but was ' + container.innerText;

Not necessarily "empty", right?  How about 'should contain exactly one LF but was' or 'should be "\n" but was'

> Source/WebCore/editing/DeleteSelectionCommand.cpp:344
> +    Node* next = node;
> +    while (next) {
> +        if (next->isContentEditable())
> +            return firstPositionInNode(next);
> +        next = next->traverseNextNode(node);
> +    }

First off, it's wrong to always return firstPositionInNode because next could be img element with width & height 0px. r- because of this.

I would make it a for loop as in:
for (Node* next = node; next && !next->isContentEditable(); next = next->traverseNextNode(node)) {}
return firstPositionInOrBeforeNode(next);

> Source/WebCore/editing/DeleteSelectionCommand.cpp:389
> +            Position firstEditablePosition = firstEditablePositionInNode(node.get());

Presumably firstEditablePosition is visually coinciding with firstPositionInOrBeforeNode(node).  Can we assert that by e.g. comparing that the canonicalized visible positions created by those two positions are identical?
Comment 8 WebKit Review Bot 2011-03-27 12:39:15 PDT
Attachment 86891 [details] did not build on chromium:
Build output: http://queues.webkit.org/results/8266503
Comment 9 Benjamin (Ben) Kalman 2011-03-27 23:47:52 PDT
Comment on attachment 86891 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=86891&action=review

>> LayoutTests/editing/execCommand/delete-table-with-empty-contents.html:2
>> +<div contenteditable tests='empty'>
> 
> I'm not sure if it's really desirable to have custom "tests" attribute.  Is it allowed in HTML5 spec?  I mean what if in the future we decided to add tests attribute for whatever purpose in HTMLx.  Wouldn't this collide with that?  Ideally, we wouldn't need to worry about this test when that happens.

I used "tests" to match junit terminology (for lack of any other), though it should actually be "test".  As in "testWithEmptySpan", "testWithEditableNonEmptySpan", etc.  It really makes no difference to me either way what is used, though I highly doubt that HTML5 will add a test or tests attribute.  And that if it did, it would collide.

>> Source/WebCore/editing/DeleteSelectionCommand.cpp:344
>> +    }
> 
> First off, it's wrong to always return firstPositionInNode because next could be img element with width & height 0px. r- because of this.
> 
> I would make it a for loop as in:
> for (Node* next = node; next && !next->isContentEditable(); next = next->traverseNextNode(node)) {}
> return firstPositionInOrBeforeNode(next);

Images can be contenteditable?  Really?  Wow.

>> Source/WebCore/editing/DeleteSelectionCommand.cpp:389
>> +            Position firstEditablePosition = firstEditablePositionInNode(node.get());
> 
> Presumably firstEditablePosition is visually coinciding with firstPositionInOrBeforeNode(node).  Can we assert that by e.g. comparing that the canonicalized visible positions created by those two positions are identical?

Yes and no.  Yes, they should be visually coinciding.  No, it can't be asserted that they're canonicalised the same, since editability affects canonicalisation.  The following positions
<td>|<span contenteditable></span></td>
and
<td><span contenteditable>|</span></td>
are... kind of visually coinciding, but certainly not canonicalised identically.  And this is one of the cases that has a bug, fixed by this patch.
Comment 10 Benjamin (Ben) Kalman 2011-03-27 23:49:10 PDT
Created attachment 87104 [details]
Patch
Comment 11 WebKit Review Bot 2011-03-27 23:52:02 PDT
Attachment 87104 [details] did not build on chromium:
Build output: http://queues.webkit.org/results/8266953
Comment 12 Early Warning System Bot 2011-03-27 23:58:48 PDT
Attachment 87104 [details] did not build on qt:
Build output: http://queues.webkit.org/results/8270710
Comment 13 Build Bot 2011-03-28 00:11:17 PDT
Attachment 87104 [details] did not build on win:
Build output: http://queues.webkit.org/results/8267864
Comment 14 Benjamin (Ben) Kalman 2011-03-28 01:24:36 PDT
Erm, am I missing something?  Why are all these bots saying

DeleteSelectionCommand.cpp:342: error: ‘class WebCore::Node’ has no member named ‘isContentEditable’

Since (a) Node definitely does have isContentEditable, and (b) that line doesn't appear on line 342 of the patch, and (c) it compiles locally.
Comment 15 Adam Barth 2011-03-28 11:50:53 PDT
http://trac.webkit.org/browser/trunk/Source/WebCore/dom/Node.h#L322

#if PLATFORM(MAC)
    // Objective-C extensions
    bool isContentEditable() const { return rendererIsEditable(Editable); }
#endif

Those bots do not build with PLATFORM(MAC) because they do not run Mac OS.
Comment 16 Benjamin (Ben) Kalman 2011-03-28 15:19:39 PDT
Ah, I didn't realise that isContentEditable had been renamed recently to renderIsEditable.
Comment 17 Benjamin (Ben) Kalman 2011-03-28 21:28:43 PDT
Created attachment 87257 [details]
Patch
Comment 18 WebKit Commit Bot 2011-03-31 00:38:32 PDT
Comment on attachment 87257 [details]
Patch

Clearing flags on attachment: 87257

Committed r82550: <http://trac.webkit.org/changeset/82550>
Comment 19 WebKit Commit Bot 2011-03-31 00:38:38 PDT
All reviewed patches have been landed.  Closing bug.
Comment 20 WebKit Review Bot 2011-03-31 02:09:08 PDT
http://trac.webkit.org/changeset/82550 might have broken GTK Linux 32-bit Debug