Bug 177713 - RenderView does not need to be a SelectionSubtreeRoot
Summary: RenderView does not need to be a SelectionSubtreeRoot
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Layout and Rendering (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: zalan
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2017-09-30 20:38 PDT by zalan
Modified: 2017-10-02 01:30 PDT (History)
9 users (show)

See Also:


Attachments
Patch (58.76 KB, patch)
2017-09-30 20:44 PDT, zalan
no flags Details | Formatted Diff | Diff
Patch (56.53 KB, patch)
2017-09-30 21:01 PDT, zalan
no flags Details | Formatted Diff | Diff
Patch (69.99 KB, patch)
2017-10-01 10:56 PDT, zalan
no flags Details | Formatted Diff | Diff
Patch (69.99 KB, patch)
2017-10-01 11:19 PDT, zalan
no flags Details | Formatted Diff | Diff
Patch (70.69 KB, patch)
2017-10-01 12:44 PDT, zalan
no flags Details | Formatted Diff | Diff
Patch (71.23 KB, patch)
2017-10-01 19:17 PDT, zalan
no flags Details | Formatted Diff | Diff
Patch (71.20 KB, patch)
2017-10-01 20:35 PDT, zalan
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description zalan 2017-09-30 20:38:51 PDT
It's the only selection root (it's not even a thing)
Comment 1 zalan 2017-09-30 20:44:19 PDT
Created attachment 322307 [details]
Patch
Comment 2 zalan 2017-09-30 21:01:05 PDT
Created attachment 322311 [details]
Patch
Comment 3 Radar WebKit Bug Importer 2017-09-30 21:44:56 PDT
<rdar://problem/34758519>
Comment 4 zalan 2017-10-01 10:56:29 PDT
Created attachment 322323 [details]
Patch
Comment 5 zalan 2017-10-01 11:19:59 PDT
Created attachment 322324 [details]
Patch
Comment 6 zalan 2017-10-01 12:44:54 PDT
Created attachment 322327 [details]
Patch
Comment 7 Antti Koivisto 2017-10-01 13:22:54 PDT
Comment on attachment 322327 [details]
Patch

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

r=me

> Source/WebCore/rendering/SelectionRangeData.cpp:56
> +struct SelectionIterator {

This looks more like a class than a struct.
Comment 8 Darin Adler 2017-10-01 13:36:26 PDT
Comment on attachment 322327 [details]
Patch

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

Feels like the code might need a struct with start and end in it. Lots of code manipulating the two together.

> Source/WebCore/editing/FrameSelection.cpp:2117
> +        view->selection().set({startRenderer, endRenderer, startOffset, endOffset});

We normally put spaces after "{" and before "}". Not sure I would chose that style for my own project, but I like the idea of staying consistent in WebKit.

> Source/WebCore/editing/FrameSelection.cpp:2237
> +    auto* renderView = m_frame->contentRenderer();
> +    auto* view = m_frame->view();
> +    if (!renderView || !view)
>          return LayoutRect();

You can get the FrameView from a RenderView. It returns a reference and never returns null. So there is no reason to go back to the Frame to get the view and just have to null check it. We can remove view and the one place below that says "view->" could instead just say "renderView->frameView()." instead. Or you could have a local variable, but it could be a reference rather than a pointer.

> Source/WebCore/platform/DragImage.cpp:186
> +    view->selection().set({startRenderer, endRenderer, startOffset, endOffset}, SelectionRangeData::RepaintMode::Nothing);

Same braces thing.

> Source/WebCore/rendering/InlineTextBox.cpp:148
> +        auto startPos = renderer().view().selection().startPosition();
> +        auto endPos = renderer().view().selection().endPosition();

If it was me, I would put renderer().view().selectIon() into a local variable rather than evaluating it twice. No idea if that’s helpful or not. Maybe one of those three functions is not inlined? If so, then it will pay off, I think.

> Source/WebCore/rendering/InlineTextBox.cpp:643
> +    auto start = renderer().view().selection().startPosition();
> +    auto end = renderer().view().selection().endPosition();

Ditto.

> Source/WebCore/rendering/SelectionRangeData.cpp:3
> + * Copyright (C) 2015, 2017 Apple Inc. All rights reserved.

Should be 2015-2017 at least. I think most of this code is older and should have additional publication dates from those older times it was published (checked in).

> Source/WebCore/rendering/SelectionRangeData.cpp:48
> +    typedef HashMap<RenderObject*, std::unique_ptr<RenderSelectionInfo>> RendererMap;
> +    typedef HashMap<const RenderBlock*, std::unique_ptr<RenderBlockSelectionInfo>> RenderBlockMap;

In our modern code we use "using" instead of "typedef".

> Source/WebCore/rendering/SelectionRangeData.cpp:56
> +struct SelectionIterator {

This looks like a class, not a struct. It has public function members and private data members.

> Source/WebCore/rendering/SelectionRangeData.cpp:93
> +    Vector<RenderMultiColumnSpannerPlaceholder*> m_spannerStack;

Comment on the moved, not new, code: Do we really want a stack here? Maybe a deque instead?

> Source/WebCore/rendering/SelectionRangeData.cpp:106
> +    return (renderer.canBeSelectionLeaf()
> +        || &renderer == selection.start
> +        || &renderer == selection.end)

This part would read better on one line.

> Source/WebCore/rendering/SelectionRangeData.cpp:117
> +    SelectionData oldSelectionData;
> +    // Record the old selected objects. These will be used later
> +    // when we compare against the new selected objects.
> +    oldSelectionData.startPosition = selection.startPosition;
> +    oldSelectionData.endPosition = selection.endPosition;

Could do this with initialization rather than assignment:

    SelectionData oldSelectionData { selection.startPosition, selection.endPosition, { } { } };

But also, the comment (old, moved here not just written) says we record the old "selected objects", but we don’t seem to quite do that; we just record the old start and end positions, not the maps of renderers and blocks.

> Source/WebCore/rendering/SelectionRangeData.cpp:127
> +    SelectionIterator selectionIterator(start);
> +    while (start && start != stop) {

Should be a for loop.

> Source/WebCore/rendering/SelectionRangeData.cpp:133
> +                RenderBlock* block = start->containingBlock();
> +                while (block && !is<RenderView>(*block)) {

I’d like to write this loop better at some point. Probably as a for loop. Here are four versions:

Try 1:

    for (auto* block = start->containingBlock(); block && !is<RenderView>(*block); block = block->containingBlock()) {

Try 2:

    for (auto* block = start; (block = block->containingBlock()) && !is<RenderView>(block); ) {

Try 3:

    auto containingBlockBelowView = [] (RenderObject& block)
    {
        auto* containingBlock = block.containingBlock();
        return is<RenderView>(containingBlock) ? nullptr : containingBlock;
    }

    for (auto* block = start; (block = containingBlockBelowView(*block)); ) {

Try 4:

    auto containingBlockBelowView = [] (RenderObject& block)
    {
        auto* containingBlock = block.containingBlock();
        return is<RenderView>(containingBlock) ? nullptr : containingBlock;
    }

    for (auto* block = containingBlockBelowView(*start); block; block = containingBlockBelowView(*block)) {

> Source/WebCore/rendering/SelectionRangeData.cpp:134
> +                    std::unique_ptr<RenderBlockSelectionInfo>& blockInfo = oldSelectionData.blocks.add(block, nullptr).iterator->value;

Using auto& here would be good.

> Source/WebCore/rendering/SelectionRangeData.cpp:168
> +    std::unique_ptr<SelectionRectGatherer::Notifier> rectNotifier = m_selectionRectGatherer.clearAndCreateNotifier();

I suggest using auto instead of writing out the type here.

> Source/WebCore/rendering/SelectionRangeData.cpp:169
> +#endif // ENABLE(SERVICE_CONTROLS)

I would remove this comment. Makes it harder to read.

> Source/WebCore/rendering/SelectionRangeData.cpp:194
> +        for (RenderBlock* block = renderer->containingBlock(); block && !is<RenderView>(*block); block = block->containingBlock()) {

Same loop as above, only this time written as a for loop (my Try 1, in fact).

> Source/WebCore/rendering/SelectionRangeData.cpp:210
> +    SelectionIterator selectionIterator(start);
> +    while (start && start != stop) {

Should be a for loop.

> Source/WebCore/rendering/SelectionRangeData.cpp:222
> +            // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
> +            renderers.set(start, std::make_unique<RenderSelectionInfo>(*start, clipToVisibleContent));
> +            auto* block = start->containingBlock();
> +            while (block && !is<RenderView>(*block)) {
> +                std::unique_ptr<RenderSelectionInfo>& blockInfo = renderers.add(block, nullptr).iterator->value;
> +                if (blockInfo)
> +                    break;
> +                blockInfo = std::make_unique<RenderSelectionInfo>(*block, clipToVisibleContent);
> +                block = block->containingBlock();
> +            }

This code is so close to the code from collect above. Would be good to find a way to share more if we can do that in a clean way.

> Source/WebCore/rendering/SelectionRangeData.cpp:231
> +    auto end = renderers.end();
> +    for (auto i = renderers.begin(); i != end; ++i) {
> +        auto* info = i->value.get();

Should be a modern for loop:

    for (auto& info : renderers.values()) {

> Source/WebCore/rendering/SelectionRangeData.h:3
> + * Copyright (C) 2017 Apple Inc.

Need "All rights reserved."

> Source/WebCore/rendering/SelectionRangeData.h:33
> +#include "RenderObject.h"

Don’t need this include. RenderSelectionInfo.h includes RenderBlock.h which includes RenderObject.h.

> Source/WebCore/rendering/SelectionRangeData.h:37
> +#if ENABLE(SERVICE_CONTROLS)
> +#include "SelectionRectGatherer.h"
> +#endif

Should have a blank line before so it can be a separate paragraph.

> Source/WebCore/rendering/SelectionRangeData.h:51
> +        bool operator==(const Context& other) const
> +        {
> +            return start == other.start && end == other.end && startPosition == other.startPosition && endPosition == other.endPosition;
> +        }

I suggest putting this after the data members. In classes we put functions first, but in a struct it makes sense to have the data first since that’s the public interface.

> Source/WebCore/rendering/SelectionRangeData.h:61
> +    Context get() const { return m_selectionContext; }

Should consider having this return const Context& so it doesn’t have to copy.

> Source/WebCore/rendering/SelectionRangeData.h:69
> +    IntRect bounds(bool clipToVisibleContent = true) const;

Can we use two separate functions here instead of a function with a boolean argument? The boolean argument version could be a separate implementation detail.
Comment 9 zalan 2017-10-01 19:17:44 PDT
Created attachment 322343 [details]
Patch
Comment 10 zalan 2017-10-01 20:35:35 PDT
Created attachment 322352 [details]
Patch
Comment 11 WebKit Commit Bot 2017-10-01 21:46:36 PDT
Comment on attachment 322352 [details]
Patch

Clearing flags on attachment: 322352

Committed r222697: <http://trac.webkit.org/changeset/222697>
Comment 12 WebKit Commit Bot 2017-10-01 21:46:38 PDT
All reviewed patches have been landed.  Closing bug.
Comment 13 Fujii Hironori 2017-10-01 23:30:37 PDT
Builds break for Apple Win and WinCairo port:

https://build.webkit.org/builders/WinCairo%2064-Bit%20Release/builds/6775

> C:\WebKit-BuildSlave\win-cairo-release\build\Source\WebCore\editing\FrameSelection.cpp(2117): error C2397: conversion from 'int' to 'std::optional<unsigned int>' requires a narrowing conversion

https://build.webkit.org/builders/Apple%20Win%20Release%20%28Build%29/builds/4835

> C:\cygwin\home\buildbot\slave\win-release\build\Source\WebCore\editing\FrameSelection.cpp(2117): error C2664: 'void WebCore::SelectionRangeData::set(const WebCore::SelectionRangeData::Context &,WebCore::SelectionRangeData::RepaintMode)': cannot convert argument 1 from 'initializer list' to 'const WebCore::SelectionRangeData::Context &' (compiling source file C:\cygwin\home\buildbot\slave\win-release\build\Source\WebCore\editing\EditingAllInOne.cpp) [C:\cygwin\home\buildbot\slave\win-release\build\WebKitBuild\Release\Source\WebCore\WebCore.vcxproj]
> C:\cygwin\home\buildbot\slave\win-release\build\Source\WebCore\editing\FrameSelection.cpp(2117): note: Reason: cannot convert from 'initializer list' to 'const WebCore::SelectionRangeData::Context' (compiling source file C:\cygwin\home\buildbot\slave\win-release\build\Source\WebCore\editing\EditingAllInOne.cpp)
> C:\cygwin\home\buildbot\slave\win-release\build\Source\WebCore\editing\FrameSelection.cpp(2117): note: No constructor could take the source type, or constructor overload resolution was ambiguous (compiling source file C:\cygwin\home\buildbot\slave\win-release\build\Source\WebCore\editing\EditingAllInOne.cpp)

> C:\cygwin\home\buildbot\slave\win-release\build\Source\WebCore\platform\DragImage.cpp(188): error C2664: 'void WebCore::SelectionRangeData::set(const WebCore::SelectionRangeData::Context &,WebCore::SelectionRangeData::RepaintMode)': cannot convert argument 1 from 'initializer list' to 'const WebCore::SelectionRangeData::Context &' [C:\cygwin\home\buildbot\slave\win-release\build\WebKitBuild\Release\Source\WebCore\WebCore.vcxproj]
> C:\cygwin\home\buildbot\slave\win-release\build\Source\WebCore\platform\DragImage.cpp(188): note: Reason: cannot convert from 'initializer list' to 'const WebCore::SelectionRangeData::Context'
> C:\cygwin\home\buildbot\slave\win-release\build\Source\WebCore\platform\DragImage.cpp(188): note: No constructor could take the source type, or constructor overload resolution was ambiguous

> c:\cygwin\home\buildbot\slave\win-release\build\source\webcore\rendering\SelectionRangeData.cpp(175): error C2664: 'void WebCore::SelectionRangeData::set(const WebCore::SelectionRangeData::Context &,WebCore::SelectionRangeData::RepaintMode)': cannot convert argument 1 from 'initializer list' to 'const WebCore::SelectionRangeData::Context &' (compiling source file C:\cygwin\home\buildbot\slave\win-release\build\Source\WebCore\rendering\RenderingAllInOne.cpp) [C:\cygwin\home\buildbot\slave\win-release\build\WebKitBuild\Release\Source\WebCore\WebCore.vcxproj]
> c:\cygwin\home\buildbot\slave\win-release\build\source\webcore\rendering\SelectionRangeData.cpp(175): note: Reason: cannot convert from 'initializer list' to 'const WebCore::SelectionRangeData::Context' (compiling source file C:\cygwin\home\buildbot\slave\win-release\build\Source\WebCore\rendering\RenderingAllInOne.cpp)
> c:\cygwin\home\buildbot\slave\win-release\build\source\webcore\rendering\SelectionRangeData.cpp(175): note: No constructor could take the source type, or constructor overload resolution was ambiguous (compiling source file C:\cygwin\home\buildbot\slave\win-release\build\Source\WebCore\rendering\RenderingAllInOne.cpp)
Comment 14 Ryosuke Niwa 2017-10-02 00:26:43 PDT
Windows build fix attempt: https://trac.webkit.org/changeset/222700
Comment 15 Ryosuke Niwa 2017-10-02 01:30:40 PDT
Fixed Windows build in https://trac.webkit.org/changeset/222701.