Changeset 248909 in webkit
- Timestamp:
- Aug 20, 2019 11:46:36 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r248908 r248909 1 2019-08-20 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 Clicking the search icon on ae.com hangs the web content process 4 https://bugs.webkit.org/show_bug.cgi?id=200889 5 <rdar://problem/54359330> 6 7 Reviewed by Ryosuke Niwa. 8 9 * editing/selection/modify-backward-inline-block-containers-expected.txt: Added. 10 * editing/selection/modify-backward-inline-block-containers.html: Added. 11 12 Add a layout test to ensure that the selection may be moved through empty inline-block containers that span the 13 width of the page. 14 15 * fast/events/focus-anchor-with-tabindex-hang-expected.txt: Added. 16 * fast/events/focus-anchor-with-tabindex-hang.html: Added. 17 18 Add a layout test to ensure that clicking an empty span under a focusable anchor element moves focus to the 19 anchor element instead of hanging the web content process or hitting a debug assertion. 20 1 21 2019-08-20 Ryan Haddad <ryanhaddad@apple.com> 2 22 -
trunk/Source/WebCore/ChangeLog
r248907 r248909 1 2019-08-20 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 Clicking the search icon on ae.com hangs the web content process 4 https://bugs.webkit.org/show_bug.cgi?id=200889 5 <rdar://problem/54359330> 6 7 Reviewed by Ryosuke Niwa. 8 9 The hang occurs under FrameSelection::selectionAtSentenceStart, while computing an EditorState to send to the UI 10 process. This act of determining whether the given positon is at the start of sentence entails moving backwards 11 from the start of the current visible selection until the start of a paragraph or sentence is found, using 12 VisiblePosition::previous to iterate backwards through VisiblePositions. 13 14 However, on this website, VisiblePosition::previous ends up just returning the current position, and we loop 15 infinitely as a result because we never actually move backwards. This happens because VisiblePosition::previous 16 first uses previousVisuallyDistinctCandidate to find a candidate Position before the current position, but when 17 the position is canonicalized to create a VisiblePosition, it is moved back to its original Position as the deep 18 equivalent. 19 20 In the attached test case (which is representative of the relevant part of the DOM on ae.com), we try to find 21 the previous VisiblePosition from (#c, 0). The previous visually distinct candidate we initially find is 22 (#b, 0), since: 23 24 1. The enclosing renderer is a RenderBlock with a non-zero height. 25 2. The enclosing renderer has no rendered children. 26 3. The position is at the first editing position in the node (i.e. the span element). 27 28 However, when canonicalizing the position, we find that neither the upstream nor the downstream position is a 29 candidate because both the upstream and downstream nodes end up well outside of the span (the upstream node ends 30 up being at the start of the body element, and the downstream position ends up right before the start of #c's 31 container). The downstream position is at the end of a text node with a leading newline, it's not a candidate 32 because its last caret offset is less than the length of the text node. 33 34 As a result, even though the given position (#b, 0) is a candidate itself, its downstream and upstream positions 35 are not. Thus, VisiblePosition::canonicalPosition expands the scope of its candidate positions to the next 36 closest candidate positions; the next candidate position is (#c, 0). Both of these candidates are outside of the 37 containing block, so we (somewhat arbitrarily) break the tie by choosing the next visible position, bringing us 38 back to (#c, 0). 39 40 There are several ways to fix this, one of which involves fixing the downstream/upstream positions of (#b, 0) so 41 that they no longer jump out of the containing block of #b and cause (#b, 0) to be an invalid visible position 42 despite being a candidate position. This can be achieved by adjusting the heuristic in 43 endsOfNodeAreVisuallyDistinctPositions (used when moving upstream or downstream). Currently, this helper 44 function returns false for #b because they contain a single (non-rendered) whitespace character. Removing this 45 extraneous whitespace character actually causes the problem to stop reproducing, since #b and #c no longer 46 contain any child nodes. This is important because the heuristic in Position::downstream attempts to keep the 47 downstream position within the confines of the enclosing visual boundary, which (currently) ends up being the 48 entire body element because endsOfNodeAreVisuallyDistinctPositions returns false for #b. 49 50 To avoid this scenario, we teach endsOfNodeAreVisuallyDistinctPositions to treat inline-block containers that 51 are empty (that is, contain no rendered content) but may have children for editing in the same way as inline- 52 block containers that don't have any children; in both scenarios, they may contain a candidate position, so we 53 should treat the ends of the container node as being visually distinct. 54 55 Doing so causes the downstream position of (#b, 0) to be kept within the immediate containing span element, 56 which then allows (#b, 0) to be a canonical VisiblePosition. 57 58 Tests: fast/events/focus-anchor-with-tabindex-hang.html 59 editing/selection/modify-backward-inline-block-containers.html 60 61 * editing/VisiblePosition.cpp: 62 (WebCore::VisiblePosition::previous const): 63 1 64 2019-08-20 Brent Fulgham <bfulgham@apple.com> 2 65 -
trunk/Source/WebCore/dom/Position.cpp
r240905 r248909 626 626 return false; 627 627 628 if (!node->renderer()->isReplaced() || !canHaveChildrenForEditing(*node) || !downcast<RenderBox>(*node->renderer()).height()) 629 return false; 630 628 631 // There is a VisiblePosition inside an empty inline-block container. 629 return node->renderer()->isReplaced() && canHaveChildrenForEditing(*node) && downcast<RenderBox>(*node->renderer()).height() && !node->firstChild(); 632 if (!node->hasChildNodes()) 633 return true; 634 635 return !Position::hasRenderedNonAnonymousDescendantsWithHeight(downcast<RenderElement>(*node->renderer())); 630 636 } 631 637
Note: See TracChangeset
for help on using the changeset viewer.