WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
NEW
Bug 89159
Selecting from a table and deleting causes an assertion failure
https://bugs.webkit.org/show_bug.cgi?id=89159
Summary
Selecting from a table and deleting causes an assertion failure
Shinya Kawanaka
Reported
2012-06-14 19:45:58 PDT
Created
attachment 147714
[details]
Repro Select from "hoge 2" to its some right area. Then you can see just below of "hoge 2" is selected. Then push JustifyCenter button, then TD 1 and TD 2 will be justified to center, though they are not content editable. Or press 'Delete' key, then assert will be triggered. ASSERTION FAILED: isEditablePosition(*this) Position.cpp::trailingWhitespacePosition
Attachments
Repro
(3.69 KB, text/html)
2012-06-14 19:45 PDT
,
Shinya Kawanaka
no flags
Details
Repro
(807 bytes, text/html)
2012-06-27 11:33 PDT
,
Shinya Kawanaka
no flags
Details
Show Obsolete
(1)
View All
Add attachment
proposed patch, testcase, etc.
Shinya Kawanaka
Comment 1
2012-06-21 16:46:44 PDT
In DeleteSelectionCommand::initializePositionData(), there are a few call of Position::upstream() and Position::downstream(). They break shadow boundaries. Fixing Position::upstream() and Position::downstream() will fix this issue, I believe. I tried fixing them before, but it's harder than I expected...
Shinya Kawanaka
Comment 2
2012-06-22 14:45:19 PDT
The sentence "breaking Shadow boundaries" is not correct. I should have said: element having Shadow DOM should be treated as atomic...
Hayato Ito
Comment 3
2012-06-26 12:17:36 PDT
I've filed a bug for the spec:
https://www.w3.org/Bugs/Public/show_bug.cgi?id=17608
I think hoge1 and hoge2 should be contenteditable in this case. But in current WebKit implementation, we use '-user-modify' style property to judge it is contenteditable or not. So the implementation might be tricky. 'hoge1 and hoge2' should not inherit 'user-modify' in this case because there is a shadow boundary. We use 'composed shadow DOM tree' in resolving style inheritance. So these elements must not be 'contenteditable' in current WebKit's style resolution. But it seems the 'user-modify' property of those elements became READ-WRITE. It's like 'an unexpected pass'. We should investigate further...
Hayato Ito
Comment 4
2012-06-26 16:47:07 PDT
It seems that the root cause is ComparePositions() in the repro case. Let me explain using the following simplified example. <div id=top contenteditable> // There is no contenteditable ancestor <div>hello</div> <div>world</div> </div> After mouse dragging from [wo|rld] to outside of top, suppose VisibleSelection::validate() is called with the status: start: {anchorNode: text node of [world], anchorType: OffsetInAnchor} end: {anchorNode: #top, anchorType: AfterAnchor} After validate(), a visibleSelection should be: start: {anchorNode: text node of [world], anchorType: OffsetInAnchor} end: {anchorNode: #top, anchorType: AfterChildren} But the actual result is: start: {anchorNode: text node of [world], anchorType: OffsetInAnchor} end: {anchorNode: #top, anchorType: AfterAnchor} Yeah, nothing changes. That should be changed after adjustSelectionToAvoidCrossingEditingBoundaries() is called in validate(). The following code in adjustSelectionToAvoidCrossingEditingBoundaries(): VisiblePosition last = lastEditablePositionBeforePositionInRoot(m_end, baseRoot); returns Position: {anchorNode: #top, anchorType: AfterAnchor} as last. In lastEditablePositionBeforePositionInRoot(m_end, baseRoot), comparePositions is called as follows: if (comparePositions(position, lastPositionInNode(highestRoot)) == 1) with position: anchorNode: {anchorNode: #top, anchorType: AfterAnchor} lastPositionInNode(highestRoot): {anchorNode: #top, anchorType: AfterChildren} Ideally, comparePositions() should return 1 in this case. But that seemed to return non-1 value. If it returns 1, lastPositionInNode(highestRoot) is used as end() and things will work well.
Shinya Kawanaka
Comment 5
2012-06-27 10:59:36 PDT
I found that this happend even if Shadow DOM is not attached. It's a real editing problem.
Shinya Kawanaka
Comment 6
2012-06-27 11:00:01 PDT
So I remove the dependency from
Shinya Kawanaka
Comment 7
2012-06-27 11:00:38 PDT
Oops... So I remove the dependency to 82697.
Shinya Kawanaka
Comment 8
2012-06-27 11:33:17 PDT
Created
attachment 149776
[details]
Repro Removed Shadow DOM from tests.
Hayato Ito
Comment 9
2012-06-27 13:17:37 PDT
Quick update: Now ComparePositions() were fixed. But it seemed there are other code places we needed to fix after ComparePositions returns correct value. (In reply to
comment #8
)
> Created an attachment (id=149776) [details] > Repro > > Removed Shadow DOM from tests.
(In reply to
comment #4
)
> It seems that the root cause is ComparePositions() in the repro case. > > Let me explain using the following simplified example. > > <div id=top contenteditable> // There is no contenteditable ancestor > <div>hello</div> > <div>world</div> > </div> > > After mouse dragging from [wo|rld] to outside of top, suppose VisibleSelection::validate() is called with the status: > > start: {anchorNode: text node of [world], anchorType: OffsetInAnchor} > end: {anchorNode: #top, anchorType: AfterAnchor} > > After validate(), a visibleSelection should be: > > start: {anchorNode: text node of [world], anchorType: OffsetInAnchor} > end: {anchorNode: #top, anchorType: AfterChildren} > > But the actual result is: > > start: {anchorNode: text node of [world], anchorType: OffsetInAnchor} > end: {anchorNode: #top, anchorType: AfterAnchor} > > Yeah, nothing changes. That should be changed after adjustSelectionToAvoidCrossingEditingBoundaries() is called in validate(). > The following code in adjustSelectionToAvoidCrossingEditingBoundaries(): > > VisiblePosition last = lastEditablePositionBeforePositionInRoot(m_end, baseRoot); > > returns Position: {anchorNode: #top, anchorType: AfterAnchor} as last. > > In lastEditablePositionBeforePositionInRoot(m_end, baseRoot), comparePositions is called as follows: > > if (comparePositions(position, lastPositionInNode(highestRoot)) == 1) > > with position: anchorNode: {anchorNode: #top, anchorType: AfterAnchor} > lastPositionInNode(highestRoot): {anchorNode: #top, anchorType: AfterChildren} > > Ideally, comparePositions() should return 1 in this case. But that seemed to return non-1 value. If it returns 1, lastPositionInNode(highestRoot) is used as end() and things will work well.
Ahmad Saleem
Comment 10
2024-10-22 17:48:40 PDT
Blink fix (for similar assertion):
https://chromium.googlesource.com/chromium/src/+/308ca1b8a40d58ec8e8c1bf6a0f62a7681c62fea
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug