| Differences between
and this patch
- a/Source/WebCore/ChangeLog +5 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2020-09-12  Darin Adler  <darin@apple.com>
2
3
        Make Selection throw same errors as other browsers and return same Range object from getRangeAt like other browsers
4
        https://bugs.webkit.org/show_bug.cgi?id=216325
5
1
2020-09-13  Sam Weinig  <weinig@apple.com>
6
2020-09-13  Sam Weinig  <weinig@apple.com>
2
7
3
        [WebIDL] Remove need for [MayThrowException] on constructors and legacy factory functions
8
        [WebIDL] Remove need for [MayThrowException] on constructors and legacy factory functions
- a/Source/WebCore/dom/Document.h +3 lines
Lines 1591-1596 public: a/Source/WebCore/dom/Document.h_sec1
1591
    void canvasResized(CanvasBase&) final { };
1591
    void canvasResized(CanvasBase&) final { };
1592
    void canvasDestroyed(CanvasBase&) final;
1592
    void canvasDestroyed(CanvasBase&) final;
1593
1593
1594
    bool contains(const Node& node) const { return this == &node.treeScope() && node.isConnected(); }
1595
    bool contains(const Node* node) const { return node && contains(*node); }
1596
1594
protected:
1597
protected:
1595
    enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
1598
    enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
1596
    WEBCORE_EXPORT Document(Frame*, const URL&, DocumentClassFlags = DefaultDocumentClass, unsigned constructionFlags = 0);
1599
    WEBCORE_EXPORT Document(Frame*, const URL&, DocumentClassFlags = DefaultDocumentClass, unsigned constructionFlags = 0);
- a/Source/WebCore/dom/Node.cpp -10 / +8 lines
Lines 2-8 a/Source/WebCore/dom/Node.cpp_sec1
2
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
2
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
3
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
4
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
5
 * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
5
 * Copyright (C) 2004-2020 Apple Inc. All rights reserved.
6
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
6
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
7
 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
7
 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
8
 *
8
 *
Lines 1021-1032 ExceptionOr<void> Node::checkSetPrefix(const AtomString& prefix) a/Source/WebCore/dom/Node.cpp_sec2
1021
1021
1022
bool Node::isDescendantOf(const Node& other) const
1022
bool Node::isDescendantOf(const Node& other) const
1023
{
1023
{
1024
    // Return true if other is an ancestor of this, otherwise false
1024
    // Return true if other is an ancestor of this.
1025
    if (other.isDocumentNode())
1026
        return &treeScope().rootNode() == &other && !isDocumentNode() && isConnected();
1025
    if (!other.hasChildNodes() || isConnected() != other.isConnected())
1027
    if (!other.hasChildNodes() || isConnected() != other.isConnected())
1026
        return false;
1028
        return false;
1027
    if (other.isDocumentNode())
1029
    for (auto ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) {
1028
        return &document() == &other && !isDocumentNode() && isConnected();
1029
    for (const auto* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) {
1030
        if (ancestor == &other)
1030
        if (ancestor == &other)
1031
            return true;
1031
            return true;
1032
    }
1032
    }
Lines 1035-1049 bool Node::isDescendantOf(const Node& other) const a/Source/WebCore/dom/Node.cpp_sec3
1035
1035
1036
bool Node::isDescendantOrShadowDescendantOf(const Node* other) const
1036
bool Node::isDescendantOrShadowDescendantOf(const Node* other) const
1037
{
1037
{
1038
    // FIXME: This element's shadow tree's host could be inside another shadow tree.
1038
    // FIXME: Correctly handle the case where the shadow host is itself in a shadow tree.
1039
    // This function doesn't handle that case correctly. Maybe share code with
1040
    // the containsIncludingShadowDOM function?
1041
    return other && (isDescendantOf(*other) || other->contains(shadowHost()));
1039
    return other && (isDescendantOf(*other) || other->contains(shadowHost()));
1042
}
1040
}
1043
1041
1044
bool Node::contains(const Node* node) const
1042
bool Node::contains(const Node& node) const
1045
{
1043
{
1046
    return this == node || (node && node->isDescendantOf(*this));
1044
    return this == &node || node.isDescendantOf(*this);
1047
}
1045
}
1048
1046
1049
bool Node::containsIncludingShadowDOM(const Node* node) const
1047
bool Node::containsIncludingShadowDOM(const Node* node) const
- a/Source/WebCore/dom/Node.h -2 / +3 lines
Lines 2-8 a/Source/WebCore/dom/Node.h_sec1
2
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
2
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
3
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
4
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
5
 * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
5
 * Copyright (C) 2004-2020 Apple Inc. All rights reserved.
6
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
6
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
7
 *
7
 *
8
 * This library is free software; you can redistribute it and/or
8
 * This library is free software; you can redistribute it and/or
Lines 371-379 public: a/Source/WebCore/dom/Node.h_sec2
371
371
372
    WEBCORE_EXPORT bool isDescendantOf(const Node&) const;
372
    WEBCORE_EXPORT bool isDescendantOf(const Node&) const;
373
    bool isDescendantOf(const Node* other) const { return other && isDescendantOf(*other); }
373
    bool isDescendantOf(const Node* other) const { return other && isDescendantOf(*other); }
374
    WEBCORE_EXPORT bool contains(const Node&) const;
375
    bool contains(const Node* other) const { return other && contains(*other); }
374
376
375
    bool isDescendantOrShadowDescendantOf(const Node*) const;
377
    bool isDescendantOrShadowDescendantOf(const Node*) const;
376
    WEBCORE_EXPORT bool contains(const Node*) const;
377
    WEBCORE_EXPORT bool containsIncludingShadowDOM(const Node*) const;
378
    WEBCORE_EXPORT bool containsIncludingShadowDOM(const Node*) const;
378
379
379
    // Whether or not a selection can be started in this object
380
    // Whether or not a selection can be started in this object
- a/Source/WebCore/dom/Range.cpp -17 / +29 lines
Lines 3-9 a/Source/WebCore/dom/Range.cpp_sec1
3
 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no)
3
 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no)
4
 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
4
 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
5
 * (C) 2001 Peter Kelly (pmk@post.com)
5
 * (C) 2001 Peter Kelly (pmk@post.com)
6
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
6
 * Copyright (C) 2004-2020 Apple Inc. All rights reserved.
7
 * Copyright (C) 2011 Motorola Mobility. All rights reserved.
7
 * Copyright (C) 2011 Motorola Mobility. All rights reserved.
8
 *
8
 *
9
 * This library is free software; you can redistribute it and/or
9
 * This library is free software; you can redistribute it and/or
Lines 29-53 a/Source/WebCore/dom/Range.cpp_sec2
29
#include "DOMRect.h"
29
#include "DOMRect.h"
30
#include "DOMRectList.h"
30
#include "DOMRectList.h"
31
#include "DocumentFragment.h"
31
#include "DocumentFragment.h"
32
#include "Editing.h"
33
#include "Event.h"
32
#include "Event.h"
34
#include "Frame.h"
33
#include "Frame.h"
34
#include "FrameSelection.h"
35
#include "FrameView.h"
35
#include "FrameView.h"
36
#include "GeometryUtilities.h"
36
#include "GeometryUtilities.h"
37
#include "HTMLBodyElement.h"
37
#include "HTMLBodyElement.h"
38
#include "HTMLElement.h"
39
#include "HTMLHtmlElement.h"
38
#include "HTMLHtmlElement.h"
40
#include "HTMLNames.h"
39
#include "HTMLNames.h"
41
#include "NodeTraversal.h"
40
#include "NodeTraversal.h"
42
#include "NodeWithIndex.h"
41
#include "NodeWithIndex.h"
43
#include "ProcessingInstruction.h"
42
#include "ProcessingInstruction.h"
44
#include "RenderBlock.h"
45
#include "RenderBoxModelObject.h"
46
#include "RenderText.h"
47
#include "RenderView.h"
48
#include "ScopedEventQueue.h"
43
#include "ScopedEventQueue.h"
49
#include "TextIterator.h"
44
#include "TextIterator.h"
50
#include "VisiblePosition.h"
51
#include "VisibleUnits.h"
45
#include "VisibleUnits.h"
52
#include "markup.h"
46
#include "markup.h"
53
#include <stdio.h>
47
#include <stdio.h>
Lines 55-64 a/Source/WebCore/dom/Range.cpp_sec3
55
#include <wtf/text/CString.h>
49
#include <wtf/text/CString.h>
56
#include <wtf/text/StringBuilder.h>
50
#include <wtf/text/StringBuilder.h>
57
51
58
#if PLATFORM(IOS_FAMILY)
59
#include "SelectionRect.h"
60
#endif
61
62
namespace WebCore {
52
namespace WebCore {
63
53
64
using namespace HTMLNames;
54
using namespace HTMLNames;
Lines 90-95 Ref<Range> Range::create(Document& ownerDocument) a/Source/WebCore/dom/Range.cpp_sec4
90
80
91
Range::~Range()
81
Range::~Range()
92
{
82
{
83
    ASSERT(!m_isAssociatedWithSelection);
84
93
    m_ownerDocument->detachRange(*this);
85
    m_ownerDocument->detachRange(*this);
94
86
95
#ifndef NDEBUG
87
#ifndef NDEBUG
Lines 102-112 void Range::updateDocument() a/Source/WebCore/dom/Range.cpp_sec5
102
    auto& document = startContainer().document();
94
    auto& document = startContainer().document();
103
    if (m_ownerDocument.ptr() == &document)
95
    if (m_ownerDocument.ptr() == &document)
104
        return;
96
        return;
97
    if (m_isAssociatedWithSelection) {
98
        m_ownerDocument->selection().clear();
99
        m_isAssociatedWithSelection = false;
100
    }
105
    m_ownerDocument->detachRange(*this);
101
    m_ownerDocument->detachRange(*this);
106
    m_ownerDocument = document;
102
    m_ownerDocument = document;
107
    m_ownerDocument->attachRange(*this);
103
    m_ownerDocument->attachRange(*this);
108
}
104
}
109
105
106
void Range::updateAssociatedSelection()
107
{
108
    if (m_isAssociatedWithSelection)
109
        m_ownerDocument->selection().updateFromAssociatedLiveRange();
110
}
111
110
ExceptionOr<void> Range::setStart(Ref<Node>&& container, unsigned offset)
112
ExceptionOr<void> Range::setStart(Ref<Node>&& container, unsigned offset)
111
{
113
{
112
    auto childNode = checkNodeOffsetPair(container, offset);
114
    auto childNode = checkNodeOffsetPair(container, offset);
Lines 117-122 ExceptionOr<void> Range::setStart(Ref<Node>&& container, unsigned offset) a/Source/WebCore/dom/Range.cpp_sec6
117
    if (!is_lteq(documentOrder(makeBoundaryPoint(m_start), makeBoundaryPoint(m_end))))
119
    if (!is_lteq(documentOrder(makeBoundaryPoint(m_start), makeBoundaryPoint(m_end))))
118
        m_end = m_start;
120
        m_end = m_start;
119
    updateDocument();
121
    updateDocument();
122
    updateAssociatedSelection();
120
    return { };
123
    return { };
121
}
124
}
122
125
Lines 130-135 ExceptionOr<void> Range::setEnd(Ref<Node>&& container, unsigned offset) a/Source/WebCore/dom/Range.cpp_sec7
130
    if (!is_lteq(documentOrder(makeBoundaryPoint(m_start), makeBoundaryPoint(m_end))))
133
    if (!is_lteq(documentOrder(makeBoundaryPoint(m_start), makeBoundaryPoint(m_end))))
131
        m_start = m_end;
134
        m_start = m_end;
132
    updateDocument();
135
    updateDocument();
136
    updateAssociatedSelection();
133
    return { };
137
    return { };
134
}
138
}
135
139
Lines 139-144 void Range::collapse(bool toStart) a/Source/WebCore/dom/Range.cpp_sec8
139
        m_end = m_start;
143
        m_end = m_start;
140
    else
144
    else
141
        m_start = m_end;
145
        m_start = m_end;
146
    updateAssociatedSelection();
142
}
147
}
143
148
144
ExceptionOr<bool> Range::isPointInRange(Node& container, unsigned offset)
149
ExceptionOr<bool> Range::isPointInRange(Node& container, unsigned offset)
Lines 368-374 ExceptionOr<RefPtr<DocumentFragment>> Range::processContents(ActionType action) a/Source/WebCore/dom/Range.cpp_sec9
368
            if (result.hasException())
373
            if (result.hasException())
369
                return result.releaseException();
374
                return result.releaseException();
370
        }
375
        }
371
        m_end = m_start;
376
        collapse(true);
372
    }
377
    }
373
378
374
    // Now add leftContents, stuff in between, and rightContents to the fragment
379
    // Now add leftContents, stuff in between, and rightContents to the fragment
Lines 771-779 ExceptionOr<void> Range::selectNodeContents(Node& node) a/Source/WebCore/dom/Range.cpp_sec10
771
{
776
{
772
    if (node.isDocumentTypeNode())
777
    if (node.isDocumentTypeNode())
773
        return Exception { InvalidNodeTypeError };
778
        return Exception { InvalidNodeTypeError };
774
775
    m_start.setToBeforeContents(node);
779
    m_start.setToBeforeContents(node);
776
    m_end.setToAfterContents(node);
780
    m_end.setToAfterContents(node);
781
    updateDocument();
782
    updateAssociatedSelection();
777
    return { };
783
    return { };
778
}
784
}
779
785
Lines 1057-1067 Optional<SimpleRange> makeSimpleRange(const RefPtr<Range>& range) a/Source/WebCore/dom/Range.cpp_sec11
1057
Ref<Range> createLiveRange(const SimpleRange& range)
1063
Ref<Range> createLiveRange(const SimpleRange& range)
1058
{
1064
{
1059
    auto result = Range::create(range.start.document());
1065
    auto result = Range::create(range.start.document());
1066
    result.get() = range;
1067
    return result;
1068
}
1069
1070
Range& Range::operator=(const SimpleRange& range)
1071
{
1060
    auto startContainer = range.start.container;
1072
    auto startContainer = range.start.container;
1061
    result->setStart(WTFMove(startContainer), range.start.offset);
1073
    setStart(WTFMove(startContainer), range.start.offset);
1062
    auto endContainer = range.end.container;
1074
    auto endContainer = range.end.container;
1063
    result->setEnd(WTFMove(endContainer), range.end.offset);
1075
    setEnd(WTFMove(endContainer), range.end.offset);
1064
    return result;
1076
    return *this;
1065
}
1077
}
1066
1078
1067
RefPtr<Range> createLiveRange(const Optional<SimpleRange>& range)
1079
RefPtr<Range> createLiveRange(const Optional<SimpleRange>& range)
- a/Source/WebCore/dom/Range.h +7 lines
Lines 99-120 public: a/Source/WebCore/dom/Range.h_sec1
99
    void textNodesMerged(NodeWithIndex& oldNode, unsigned offset);
99
    void textNodesMerged(NodeWithIndex& oldNode, unsigned offset);
100
    void textNodeSplit(Text& oldNode);
100
    void textNodeSplit(Text& oldNode);
101
101
102
    void wasAssociatedWithSelection() { m_isAssociatedWithSelection = true; }
103
    void wasDisassociatedFromSelection() { m_isAssociatedWithSelection = false; }
104
102
#if ENABLE(TREE_DEBUGGING)
105
#if ENABLE(TREE_DEBUGGING)
103
    String debugDescription() const;
106
    String debugDescription() const;
104
#endif
107
#endif
105
108
106
    enum ActionType : uint8_t { Delete, Extract, Clone };
109
    enum ActionType : uint8_t { Delete, Extract, Clone };
107
110
111
    Range& operator=(const SimpleRange&);
112
108
private:
113
private:
109
    explicit Range(Document&);
114
    explicit Range(Document&);
110
115
111
    void updateDocument();
116
    void updateDocument();
117
    void updateAssociatedSelection();
112
    ExceptionOr<Node*> checkNodeOffsetPair(Node&, unsigned offset) const;
118
    ExceptionOr<Node*> checkNodeOffsetPair(Node&, unsigned offset) const;
113
    ExceptionOr<RefPtr<DocumentFragment>> processContents(ActionType);
119
    ExceptionOr<RefPtr<DocumentFragment>> processContents(ActionType);
114
120
115
    Ref<Document> m_ownerDocument;
121
    Ref<Document> m_ownerDocument;
116
    RangeBoundaryPoint m_start;
122
    RangeBoundaryPoint m_start;
117
    RangeBoundaryPoint m_end;
123
    RangeBoundaryPoint m_end;
124
    bool m_isAssociatedWithSelection { false };
118
};
125
};
119
126
120
WEBCORE_EXPORT SimpleRange makeSimpleRange(const Range&);
127
WEBCORE_EXPORT SimpleRange makeSimpleRange(const Range&);
- a/Source/WebCore/editing/FrameSelection.cpp -7 / +68 lines
Lines 1-5 a/Source/WebCore/editing/FrameSelection.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2004, 2008, 2009, 2010, 2014-2015 Apple Inc. All rights reserved.
2
 * Copyright (C) 2004-2020 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 314-320 void FrameSelection::setSelectionByMouseIfDifferent(const VisibleSelection& pass a/Source/WebCore/editing/FrameSelection.cpp_sec2
314
    newSelection.setIsDirectional(isDirectional); // Adjusting base and extent will make newSelection always directional
314
    newSelection.setIsDirectional(isDirectional); // Adjusting base and extent will make newSelection always directional
315
    if (m_selection == newSelection || !shouldChangeSelection(newSelection))
315
    if (m_selection == newSelection || !shouldChangeSelection(newSelection))
316
        return;
316
        return;
317
318
    
317
    
319
    AXTextStateChangeIntent intent;
318
    AXTextStateChangeIntent intent;
320
    if (AXObjectCache::accessibilityEnabled() && newSelection.isCaret())
319
    if (AXObjectCache::accessibilityEnabled() && newSelection.isCaret())
Lines 335-340 bool FrameSelection::setSelectionWithoutUpdatingAppearance(const VisibleSelectio a/Source/WebCore/editing/FrameSelection.cpp_sec3
335
334
336
    if (!m_document || !m_document->frame()) {
335
    if (!m_document || !m_document->frame()) {
337
        m_selection = newSelection;
336
        m_selection = newSelection;
337
        updateAssociatedLiveRange();
338
        return false;
338
        return false;
339
    }
339
    }
340
340
Lines 368-373 bool FrameSelection::setSelectionWithoutUpdatingAppearance(const VisibleSelectio a/Source/WebCore/editing/FrameSelection.cpp_sec4
368
        m_document->editor().selectionWillChange();
368
        m_document->editor().selectionWillChange();
369
369
370
    m_selection = newSelection;
370
    m_selection = newSelection;
371
    updateAssociatedLiveRange();
371
372
372
    // Selection offsets should increase when LF is inserted before the caret in InsertLineBreakCommand. See <https://webkit.org/b/56061>.
373
    // Selection offsets should increase when LF is inserted before the caret in InsertLineBreakCommand. See <https://webkit.org/b/56061>.
373
    if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(newSelection.start()))
374
    if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(newSelection.start()))
Lines 2776-2796 void FrameSelection::setCaretColor(const Color& caretColor) a/Source/WebCore/editing/FrameSelection.cpp_sec5
2776
            invalidateCaretRect();
2777
            invalidateCaretRect();
2777
    }
2778
    }
2778
}
2779
}
2780
2779
#endif // PLATFORM(IOS_FAMILY)
2781
#endif // PLATFORM(IOS_FAMILY)
2780
2782
2783
static bool isRootNode(Document* document, const Optional<SimpleRange>& range)
2784
{
2785
    return document && range && document->contains(range->start.container) && document->contains(range->end.container);
2786
}
2787
2788
static bool isRootNode(Document* document, const Range& liveRange)
2789
{
2790
    // Only need to check the start container because live ranges enforce the invariant that start and end have a common ancestor.
2791
    return document && document->contains(liveRange.startContainer());
2792
}
2793
2794
RefPtr<Range> FrameSelection::associatedLiveRange()
2795
{
2796
    if (!m_associatedLiveRange) {
2797
        if (auto range = m_selection.firstRange(); isRootNode(m_document, range)) {
2798
            m_associatedLiveRange = createLiveRange(*range);
2799
            m_associatedLiveRange->wasAssociatedWithSelection();
2800
        }
2801
    }
2802
    return m_associatedLiveRange;
2803
}
2804
2805
void FrameSelection::disassociateLiveRange()
2806
{
2807
    if (auto previouslyAssociatedLiveRange = std::exchange(m_associatedLiveRange, nullptr))
2808
        previouslyAssociatedLiveRange->wasDisassociatedFromSelection();
2809
}
2810
2811
void FrameSelection::associateLiveRange(Range& liveRange)
2812
{
2813
    disassociateLiveRange();
2814
    m_associatedLiveRange = &liveRange;
2815
    liveRange.wasAssociatedWithSelection();
2816
    updateFromAssociatedLiveRange();
2817
}
2818
2819
void FrameSelection::updateFromAssociatedLiveRange()
2820
{
2821
    ASSERT(m_associatedLiveRange);
2822
    if (!isRootNode(m_document, *m_associatedLiveRange))
2823
        disassociateLiveRange();
2824
    else
2825
        setSelection(makeSimpleRange(*m_associatedLiveRange));
2826
    // FIXME: Normalization done by setSelection will be visible next time updateAssociatedLiveRange is called. Instead the Selection API specification calls for allowing non-normalized selection ranges.
2827
}
2828
2829
void FrameSelection::updateAssociatedLiveRange()
2830
{
2831
    auto range = m_selection.firstRange();
2832
    if (!isRootNode(m_document, range))
2833
        disassociateLiveRange();
2834
    else if (m_associatedLiveRange) {
2835
        // Tell the live range it's not associated while modifying it so it doesn't call updateFromAssociatedLiveRange.
2836
        m_associatedLiveRange->wasDisassociatedFromSelection();
2837
        *m_associatedLiveRange = *range;
2838
        m_associatedLiveRange->wasAssociatedWithSelection();
2839
    }
2840
}
2841
2781
}
2842
}
2782
2843
2783
#if ENABLE(TREE_DEBUGGING)
2844
#if ENABLE(TREE_DEBUGGING)
2784
2845
2785
void showTree(const WebCore::FrameSelection& sel)
2846
void showTree(const WebCore::FrameSelection& selection)
2786
{
2847
{
2787
    sel.showTreeForThis();
2848
    selection.showTreeForThis();
2788
}
2849
}
2789
2850
2790
void showTree(const WebCore::FrameSelection* sel)
2851
void showTree(const WebCore::FrameSelection* selection)
2791
{
2852
{
2792
    if (sel)
2853
    if (selection)
2793
        sel->showTreeForThis();
2854
        selection->showTreeForThis();
2794
}
2855
}
2795
2856
2796
#endif
2857
#endif
- a/Source/WebCore/editing/FrameSelection.h -2 / +10 lines
Lines 1-5 a/Source/WebCore/editing/FrameSelection.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
2
 * Copyright (C) 2004-2020 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 271-276 public: a/Source/WebCore/editing/FrameSelection.h_sec2
271
    bool shouldShowBlockCursor() const { return m_shouldShowBlockCursor; }
271
    bool shouldShowBlockCursor() const { return m_shouldShowBlockCursor; }
272
    void setShouldShowBlockCursor(bool);
272
    void setShouldShowBlockCursor(bool);
273
273
274
    RefPtr<Range> associatedLiveRange();
275
    void associateLiveRange(Range&);
276
    void disassociateLiveRange();
277
    void updateFromAssociatedLiveRange();
278
274
private:
279
private:
275
    enum EPositionType { START, END, BASE, EXTENT };
280
    enum EPositionType { START, END, BASE, EXTENT };
276
281
Lines 328-334 private: a/Source/WebCore/editing/FrameSelection.h_sec3
328
    Optional<SimpleRange> rangeByAlteringCurrentSelection(EAlteration, int amount) const;
333
    Optional<SimpleRange> rangeByAlteringCurrentSelection(EAlteration, int amount) const;
329
#endif
334
#endif
330
335
331
    Document* m_document;
336
    void updateAssociatedLiveRange();
337
338
    Document* m_document { nullptr };
339
    RefPtr<Range> m_associatedLiveRange;
332
340
333
    LayoutUnit m_xPosForVerticalArrowNavigation;
341
    LayoutUnit m_xPosForVerticalArrowNavigation;
334
342
- a/Source/WebCore/page/DOMSelection.cpp -47 / +108 lines
Lines 1-5 a/Source/WebCore/page/DOMSelection.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2007, 2009, 2016 Apple Inc. All rights reserved.
2
 * Copyright (C) 2007-2020 Apple Inc. All rights reserved.
3
 * Copyright (C) 2012 Google Inc. All rights reserved.
3
 * Copyright (C) 2012 Google Inc. All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
Lines 39-44 a/Source/WebCore/page/DOMSelection.cpp_sec2
39
39
40
namespace WebCore {
40
namespace WebCore {
41
41
42
static bool shouldUseSelectionAssociatedRange()
43
{
44
    // FIXME: This will be controlled by a feature flag during development, I guess.
45
    return false;
46
}
47
42
static Node* selectionShadowAncestor(Frame& frame)
48
static Node* selectionShadowAncestor(Frame& frame)
43
{
49
{
44
    auto* node = frame.selection().selection().base().anchorNode();
50
    auto* node = frame.selection().selection().base().anchorNode();
Lines 166-240 unsigned DOMSelection::rangeCount() const a/Source/WebCore/page/DOMSelection.cpp_sec3
166
    return !frame || frame->selection().isNone() ? 0 : 1;
172
    return !frame || frame->selection().isNone() ? 0 : 1;
167
}
173
}
168
174
169
void DOMSelection::collapse(Node* node, unsigned offset)
175
ExceptionOr<void> DOMSelection::collapse(Node* node, unsigned offset)
170
{
176
{
171
    if (!isValidForPosition(node))
177
    auto frame = makeRefPtr(this->frame());
172
        return;
178
    if (!frame)
173
179
        return { };
174
    Ref<Frame> protectedFrame(*frame());
180
    if (shouldUseSelectionAssociatedRange()) {
175
    protectedFrame->selection().moveTo(createLegacyEditingPosition(node, offset), Affinity::Downstream);
181
        if (!node) {
182
            removeAllRanges();
183
            return { };
184
        }
185
        // FIXME: The Selection API specification does not mention this, but Web Platform Tests results expect it.
186
        if (node->isDocumentTypeNode())
187
            return Exception { InvalidNodeTypeError };
188
        // FIXME: The Selection API specification requires this exception, but it may be incompatible in practice.
189
        if (offset > node->length())
190
            return Exception { IndexSizeError };
191
        if (!frame->document()->contains(*node))
192
            return { };
193
    } else {
194
        if (!isValidForPosition(node))
195
            return { };
196
    }
197
    auto& selection = frame->selection();
198
    selection.disassociateLiveRange();
199
    selection.moveTo(createLegacyEditingPosition(node, offset), Affinity::Downstream);
200
    return { };
176
}
201
}
177
202
178
ExceptionOr<void> DOMSelection::collapseToEnd()
203
ExceptionOr<void> DOMSelection::collapseToEnd()
179
{
204
{
180
    auto* frame = this->frame();
205
    auto frame = makeRefPtr(this->frame());
181
    if (!frame)
206
    if (!frame)
182
        return { };
207
        return { };
183
    auto& selection = frame->selection();
208
    auto& selection = frame->selection();
184
    if (selection.isNone())
209
    if (selection.isNone())
185
        return Exception { InvalidStateError };
210
        return Exception { InvalidStateError };
186
211
    selection.disassociateLiveRange();
187
    Ref<Frame> protector(*frame);
188
    selection.moveTo(selection.selection().end(), Affinity::Downstream);
212
    selection.moveTo(selection.selection().end(), Affinity::Downstream);
189
    return { };
213
    return { };
190
}
214
}
191
215
192
ExceptionOr<void> DOMSelection::collapseToStart()
216
ExceptionOr<void> DOMSelection::collapseToStart()
193
{
217
{
194
    auto* frame = this->frame();
218
    auto frame = makeRefPtr(this->frame());
195
    if (!frame)
219
    if (!frame)
196
        return { };
220
        return { };
197
    auto& selection = frame->selection();
221
    auto& selection = frame->selection();
198
    if (selection.isNone())
222
    if (selection.isNone())
199
        return Exception { InvalidStateError };
223
        return Exception { InvalidStateError };
200
224
    selection.disassociateLiveRange();
201
    Ref<Frame> protector(*frame);
202
    selection.moveTo(selection.selection().start(), Affinity::Downstream);
225
    selection.moveTo(selection.selection().start(), Affinity::Downstream);
203
    return { };
226
    return { };
204
}
227
}
205
228
206
void DOMSelection::empty()
229
void DOMSelection::empty()
207
{
230
{
208
    auto* frame = this->frame();
231
    removeAllRanges();
209
    if (!frame)
210
        return;
211
    frame->selection().clear();
212
}
232
}
213
233
214
void DOMSelection::setBaseAndExtent(Node* baseNode, unsigned baseOffset, Node* extentNode, unsigned extentOffset)
234
ExceptionOr<void> DOMSelection::setBaseAndExtent(Node* baseNode, unsigned baseOffset, Node* extentNode, unsigned extentOffset)
215
{
235
{
216
    if (!isValidForPosition(baseNode) || !isValidForPosition(extentNode))
236
    auto frame = makeRefPtr(this->frame());
217
        return;
237
    if (!frame)
218
238
        return { };
219
    Ref<Frame> protectedFrame(*frame());
239
    if (shouldUseSelectionAssociatedRange()) {
220
    protectedFrame->selection().moveTo(createLegacyEditingPosition(baseNode, baseOffset), createLegacyEditingPosition(extentNode, extentOffset), Affinity::Downstream);
240
        // FIXME: The Selection API specification requires this exception, but it may be incompatible in practice.
241
        // FIXME: We should do this by making the arguments non-nullable in the IDL file, once shouldUseSelectionAssociatedRange is always true.
242
        if (!baseNode || !extentNode)
243
            return Exception { TypeError };
244
        // FIXME: The Selection API specification requires this exception, but it may be incompatible in practice.
245
        if (baseOffset > baseNode->length() || extentOffset > extentNode->length())
246
            return Exception { IndexSizeError };
247
        auto& document = *frame->document();
248
        if (!document.contains(*baseNode) || !document.contains(*extentNode))
249
            return { };
250
    } else {
251
        if (!isValidForPosition(baseNode) || !isValidForPosition(extentNode))
252
            return { };
253
    }
254
    auto& selection = frame->selection();
255
    selection.disassociateLiveRange();
256
    selection.moveTo(createLegacyEditingPosition(baseNode, baseOffset), createLegacyEditingPosition(extentNode, extentOffset), Affinity::Downstream);
257
    return { };
221
}
258
}
222
259
223
void DOMSelection::setPosition(Node* node, unsigned offset)
260
ExceptionOr<void> DOMSelection::setPosition(Node* node, unsigned offset)
224
{
261
{
225
    if (!isValidForPosition(node))
262
    return collapse(node, offset);
226
        return;
227
228
    Ref<Frame> protectedFrame(*frame());
229
    protectedFrame->selection().moveTo(createLegacyEditingPosition(node, offset), Affinity::Downstream);
230
}
263
}
231
264
232
void DOMSelection::modify(const String& alterString, const String& directionString, const String& granularityString)
265
void DOMSelection::modify(const String& alterString, const String& directionString, const String& granularityString)
233
{
266
{
234
    auto* frame = this->frame();
235
    if (!frame)
236
        return;
237
238
    FrameSelection::EAlteration alter;
267
    FrameSelection::EAlteration alter;
239
    if (equalLettersIgnoringASCIICase(alterString, "extend"))
268
    if (equalLettersIgnoringASCIICase(alterString, "extend"))
240
        alter = FrameSelection::AlterationExtend;
269
        alter = FrameSelection::AlterationExtend;
Lines 277-284 void DOMSelection::modify(const String& alterString, const String& directionStri a/Source/WebCore/page/DOMSelection.cpp_sec4
277
    else
306
    else
278
        return;
307
        return;
279
308
280
    Ref<Frame> protector(*frame);
309
    if (auto frame = makeRefPtr(this->frame()))
281
    frame->selection().modify(alter, direction, granularity);
310
        frame->selection().modify(alter, direction, granularity);
282
}
311
}
283
312
284
ExceptionOr<void> DOMSelection::extend(Node& node, unsigned offset)
313
ExceptionOr<void> DOMSelection::extend(Node& node, unsigned offset)
Lines 288-296 ExceptionOr<void> DOMSelection::extend(Node& node, unsigned offset) a/Source/WebCore/page/DOMSelection.cpp_sec5
288
        return { };
317
        return { };
289
    if (offset > node.length())
318
    if (offset > node.length())
290
        return Exception { IndexSizeError };
319
        return Exception { IndexSizeError };
291
    if (!isValidForPosition(&node))
320
    if (shouldUseSelectionAssociatedRange()) {
292
        return { };
321
        if (!frame->document()->contains(node))
293
    frame->selection().setExtent(createLegacyEditingPosition(&node, offset), Affinity::Downstream);
322
            return { };
323
    } else {
324
        if (!isValidForPosition(&node))
325
            return { };
326
    }
327
    auto& selection = frame->selection();
328
    selection.disassociateLiveRange();
329
    selection.setExtent(createLegacyEditingPosition(&node, offset), Affinity::Downstream);
294
    return { };
330
    return { };
295
}
331
}
296
332
Lines 299-304 ExceptionOr<Ref<Range>> DOMSelection::getRangeAt(unsigned index) a/Source/WebCore/page/DOMSelection.cpp_sec6
299
    if (index >= rangeCount())
335
    if (index >= rangeCount())
300
        return Exception { IndexSizeError };
336
        return Exception { IndexSizeError };
301
    auto& frame = *this->frame();
337
    auto& frame = *this->frame();
338
    if (shouldUseSelectionAssociatedRange())
339
        return frame.selection().associatedLiveRange().releaseNonNull();
302
    if (auto shadowAncestor = selectionShadowAncestor(frame))
340
    if (auto shadowAncestor = selectionShadowAncestor(frame))
303
        return createLiveRange(makeSimpleRange(*makeBoundaryPointBeforeNode(*shadowAncestor)));
341
        return createLiveRange(makeSimpleRange(*makeBoundaryPointBeforeNode(*shadowAncestor)));
304
    return createLiveRange(*frame.selection().selection().firstRange());
342
    return createLiveRange(*frame.selection().selection().firstRange());
Lines 317-341 void DOMSelection::addRange(Range& liveRange) a/Source/WebCore/page/DOMSelection.cpp_sec7
317
    auto frame = makeRefPtr(this->frame());
355
    auto frame = makeRefPtr(this->frame());
318
    if (!frame)
356
    if (!frame)
319
        return;
357
        return;
320
321
    auto range = makeSimpleRange(liveRange);
322
    auto& selection = frame->selection();
358
    auto& selection = frame->selection();
323
359
    if (shouldUseSelectionAssociatedRange()) {
360
        if (selection.isNone())
361
            selection.associateLiveRange(liveRange);
362
        return;
363
    }
364
    auto range = makeSimpleRange(liveRange);
324
    if (auto selectedRange = selection.selection().toNormalizedRange()) {
365
    if (auto selectedRange = selection.selection().toNormalizedRange()) {
325
        if (!selectedRange->start.container->containingShadowRoot() && intersects(*selectedRange, range))
366
        if (!selectedRange->start.container->containingShadowRoot() && intersects(*selectedRange, range))
326
            selection.setSelection(unionRange(*selectedRange, range));
367
            selection.setSelection(unionRange(*selectedRange, range));
327
        return;
368
        return;
328
    }
369
    }
329
330
    selection.setSelection(range);
370
    selection.setSelection(range);
331
}
371
}
332
372
373
ExceptionOr<void> DOMSelection::removeRange(Range& liveRange)
374
{
375
    if (&liveRange != frame()->selection().associatedLiveRange())
376
        return Exception { NotFoundError };
377
    removeAllRanges();
378
    return { };
379
}
380
333
void DOMSelection::deleteFromDocument()
381
void DOMSelection::deleteFromDocument()
334
{
382
{
335
    auto frame = makeRefPtr(this->frame());
383
    auto frame = makeRefPtr(this->frame());
336
    if (!frame)
384
    if (!frame)
337
        return;
385
        return;
338
386
387
    if (shouldUseSelectionAssociatedRange()) {
388
        if (auto associatedRange = frame->selection().associatedLiveRange())
389
            associatedRange->deleteContents();
390
        return;
391
    }
392
339
    auto selectedRange = frame->selection().selection().toNormalizedRange();
393
    auto selectedRange = frame->selection().selection().toNormalizedRange();
340
    if (!selectedRange || selectedRange->start.container->containingShadowRoot())
394
    if (!selectedRange || selectedRange->start.container->containingShadowRoot())
341
        return;
395
        return;
Lines 346-354 void DOMSelection::deleteFromDocument() a/Source/WebCore/page/DOMSelection.cpp_sec8
346
400
347
bool DOMSelection::containsNode(Node& node, bool allowPartial) const
401
bool DOMSelection::containsNode(Node& node, bool allowPartial) const
348
{
402
{
349
    // FIXME: This behavior does not match what the selection API standard specifies.
403
    if (!shouldUseSelectionAssociatedRange()) {
350
    if (node.isTextNode())
404
        // FIXME: This does not match the Selection API specification.
351
        allowPartial = true;
405
        if (node.isTextNode())
406
            allowPartial = true;
407
    }
352
408
353
    auto* frame = this->frame();
409
    auto* frame = this->frame();
354
    if (!frame)
410
    if (!frame)
Lines 363-370 bool DOMSelection::containsNode(Node& node, bool allowPartial) const a/Source/WebCore/page/DOMSelection.cpp_sec9
363
419
364
void DOMSelection::selectAllChildren(Node& node)
420
void DOMSelection::selectAllChildren(Node& node)
365
{
421
{
366
    // This doesn't (and shouldn't) select text node characters.
422
    if (shouldUseSelectionAssociatedRange())
367
    setBaseAndExtent(&node, 0, &node, node.countChildNodes());
423
        setBaseAndExtent(&node, 0, &node, node.length());
424
    else {
425
        // This doesn't select text node characters.
426
        setBaseAndExtent(&node, 0, &node, node.countChildNodes());
427
    }
368
}
428
}
369
429
370
String DOMSelection::toString()
430
String DOMSelection::toString()
Lines 410-415 unsigned DOMSelection::shadowAdjustedOffset(const Position& position) const a/Source/WebCore/page/DOMSelection.cpp_sec10
410
470
411
bool DOMSelection::isValidForPosition(Node* node) const
471
bool DOMSelection::isValidForPosition(Node* node) const
412
{
472
{
473
    ASSERT(!shouldUseSelectionAssociatedRange());
413
    auto* frame = this->frame();
474
    auto* frame = this->frame();
414
    return frame && (!node || &node->document() == frame->document());
475
    return frame && (!node || &node->document() == frame->document());
415
}
476
}
- a/Source/WebCore/page/DOMSelection.h -4 / +5 lines
Lines 1-5 a/Source/WebCore/page/DOMSelection.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2007 Apple Inc. All rights reserved.
2
 * Copyright (C) 2007-2020 Apple Inc. All rights reserved.
3
 * Copyright (C) 2012 Google Inc. All rights reserved.
3
 * Copyright (C) 2012 Google Inc. All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
Lines 51-58 public: a/Source/WebCore/page/DOMSelection.h_sec2
51
    unsigned baseOffset() const;
51
    unsigned baseOffset() const;
52
    unsigned extentOffset() const;
52
    unsigned extentOffset() const;
53
    String type() const;
53
    String type() const;
54
    void setBaseAndExtent(Node* baseNode, unsigned baseOffset, Node* extentNode, unsigned extentOffset);
54
    ExceptionOr<void> setBaseAndExtent(Node* baseNode, unsigned baseOffset, Node* extentNode, unsigned extentOffset);
55
    void setPosition(Node*, unsigned offset);
55
    ExceptionOr<void> setPosition(Node*, unsigned offset);
56
    void modify(const String& alter, const String& direction, const String& granularity);
56
    void modify(const String& alter, const String& direction, const String& granularity);
57
57
58
    // The anchor and focus are the start and end of the selection, and
58
    // The anchor and focus are the start and end of the selection, and
Lines 64-76 public: a/Source/WebCore/page/DOMSelection.h_sec3
64
    unsigned focusOffset() const;
64
    unsigned focusOffset() const;
65
    bool isCollapsed() const;
65
    bool isCollapsed() const;
66
    unsigned rangeCount() const;
66
    unsigned rangeCount() const;
67
    void collapse(Node*, unsigned offset);
67
    ExceptionOr<void> collapse(Node*, unsigned offset);
68
    ExceptionOr<void> collapseToEnd();
68
    ExceptionOr<void> collapseToEnd();
69
    ExceptionOr<void> collapseToStart();
69
    ExceptionOr<void> collapseToStart();
70
    ExceptionOr<void> extend(Node&, unsigned offset);
70
    ExceptionOr<void> extend(Node&, unsigned offset);
71
    ExceptionOr<Ref<Range>> getRangeAt(unsigned);
71
    ExceptionOr<Ref<Range>> getRangeAt(unsigned);
72
    void removeAllRanges();
72
    void removeAllRanges();
73
    void addRange(Range&);
73
    void addRange(Range&);
74
    ExceptionOr<void> removeRange(Range&);
74
    void deleteFromDocument();
75
    void deleteFromDocument();
75
    bool containsNode(Node&, bool partlyContained) const;
76
    bool containsNode(Node&, bool partlyContained) const;
76
    void selectAllChildren(Node&);
77
    void selectAllChildren(Node&);
- a/Source/WebCore/page/DOMSelection.idl -19 / +19 lines
Lines 41-74 a/Source/WebCore/page/DOMSelection.idl_sec1
41
    readonly attribute boolean isCollapsed;
41
    readonly attribute boolean isCollapsed;
42
    readonly attribute unsigned long rangeCount;
42
    readonly attribute unsigned long rangeCount;
43
43
44
    undefined collapse(Node? node, optional unsigned long offset = 0);
44
    readonly attribute DOMString type;
45
    [MayThrowException] undefined collapseToEnd();
46
    [MayThrowException] undefined collapseToStart();
47
48
    [CEReactions] undefined deleteFromDocument();
49
    boolean containsNode(Node node, optional boolean allowPartial = false);
50
    undefined selectAllChildren(Node node);
51
52
    [MayThrowException] undefined extend(Node node, optional unsigned long offset = 0);
53
45
54
    [MayThrowException] Range getRangeAt(unsigned long index);
46
    [MayThrowException] Range getRangeAt(unsigned long index);
55
    undefined removeAllRanges();
56
    undefined addRange(Range range);
47
    undefined addRange(Range range);
48
    [MayThrowException] undefined removeRange(Range range);
49
    undefined removeAllRanges();
57
50
58
    [NotEnumerable] DOMString toString();
51
    undefined empty();
59
52
60
    readonly attribute DOMString type;
53
    [MayThrowException] undefined collapse(Node? node, optional unsigned long offset = 0);
54
    [MayThrowException] undefined setPosition(Node? node, optional unsigned long offset = 0);
55
56
    [MayThrowException] undefined collapseToStart();
57
    [MayThrowException] undefined collapseToEnd();
61
58
62
    undefined setBaseAndExtent(Node? baseNode, unsigned long baseOffset, Node? extentNode, unsigned long extentOffset);
59
    [MayThrowException] undefined extend(Node node, optional unsigned long offset = 0);
63
    undefined setPosition(Node? node, optional unsigned long offset = 0);
64
60
65
    undefined empty();
61
    [MayThrowException] undefined setBaseAndExtent(Node? baseNode, unsigned long baseOffset, Node? extentNode, unsigned long extentOffset);
62
    undefined selectAllChildren(Node node);
63
64
    [CEReactions] undefined deleteFromDocument();
65
    boolean containsNode(Node node, optional boolean allowPartialContainment = false);
66
67
    [NotEnumerable] DOMString toString();
66
68
67
    // FIXME: The following operation should be implemented.
69
    // Non-standard methods and attributes.
68
    // undefined removeRange(Range range);
69
70
70
    // FIXME: Using "undefined" as default parameter value is wrong.
71
    undefined modify(optional DOMString alter, optional DOMString direction, optional DOMString granularity);
71
    undefined modify(optional DOMString alter = "undefined", optional DOMString direction = "undefined", optional DOMString granularity = "undefined");
72
72
73
    readonly attribute Node? baseNode;
73
    readonly attribute Node? baseNode;
74
    readonly attribute unsigned long baseOffset;
74
    readonly attribute unsigned long baseOffset;
- a/LayoutTests/imported/w3c/web-platform-tests/selection/removeRange-expected.txt -28 / +28 lines
Lines 3-35 Äb̈c̈d̈ëf̈g̈ḧ a/LayoutTests/imported/w3c/web-platform-tests/selection/removeRange-expected.txt_sec1
3
Qrstuvwx
3
Qrstuvwx
4
4
5
5
6
FAIL removeRange() with Range 0 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
6
FAIL removeRange() with Range 0 The object can not be found here.
7
FAIL removeRange() with Range 1 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
7
FAIL removeRange() with Range 1 The object can not be found here.
8
FAIL removeRange() with Range 2 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
8
FAIL removeRange() with Range 2 The object can not be found here.
9
FAIL removeRange() with Range 3 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
9
FAIL removeRange() with Range 3 The object can not be found here.
10
FAIL removeRange() with Range 4 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
10
FAIL removeRange() with Range 4 The object can not be found here.
11
FAIL removeRange() with Range 5 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
11
FAIL removeRange() with Range 5 The object can not be found here.
12
FAIL removeRange() with Range 6 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
12
FAIL removeRange() with Range 6 The object can not be found here.
13
FAIL removeRange() with Range 7 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
13
FAIL removeRange() with Range 7 The object can not be found here.
14
FAIL removeRange() with Range 14 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
14
FAIL removeRange() with Range 14 The object can not be found here.
15
FAIL removeRange() with Range 15 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
15
FAIL removeRange() with Range 15 The object can not be found here.
16
FAIL removeRange() with Range 16 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
16
FAIL removeRange() with Range 16 The object can not be found here.
17
FAIL removeRange() with Range 17 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
17
FAIL removeRange() with Range 17 The object can not be found here.
18
FAIL removeRange() with Range 18 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
18
FAIL removeRange() with Range 18 The object can not be found here.
19
FAIL removeRange() with Range 22 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
19
FAIL removeRange() with Range 22 The object can not be found here.
20
FAIL removeRange() with Range 23 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
20
FAIL removeRange() with Range 23 The object can not be found here.
21
FAIL removeRange() with Range 26 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
21
FAIL removeRange() with Range 26 The object can not be found here.
22
FAIL removeRange() with Range 27 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
22
FAIL removeRange() with Range 27 The object can not be found here.
23
FAIL removeRange() with Range 28 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
23
FAIL removeRange() with Range 28 The object can not be found here.
24
FAIL removeRange() with Range 29 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
24
FAIL removeRange() with Range 29 The object can not be found here.
25
FAIL removeRange() with Range 30 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
25
FAIL removeRange() with Range 30 The object can not be found here.
26
FAIL removeRange() with Range 31 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
26
FAIL removeRange() with Range 31 The object can not be found here.
27
FAIL removeRange() with Range 32 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
27
FAIL removeRange() with Range 32 The object can not be found here.
28
FAIL removeRange() with Range 34 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
28
FAIL removeRange() with Range 34 The object can not be found here.
29
FAIL removeRange() with Range 35 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
29
FAIL removeRange() with Range 35 The object can not be found here.
30
FAIL removeRange() with Range 36 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
30
FAIL removeRange() with Range 36 The object can not be found here.
31
FAIL removeRange() with Range 37 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
31
FAIL removeRange() with Range 37 The object can not be found here.
32
FAIL removeRange() with Range 38 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
32
FAIL removeRange() with Range 38 The object can not be found here.
33
FAIL removeRange() with Range 39 selection.removeRange is not a function. (In 'selection.removeRange(range)', 'selection.removeRange' is undefined)
33
FAIL removeRange() with Range 39 The object can not be found here.
34
PASS removeRange() argument is non-optional Range 
34
PASS removeRange() argument is non-optional Range 
35
35

Return to Bug 216325