Fill HighlightRangeGroup and HighlightMap with values from JavaScript
https://bugs.webkit.org/show_bug.cgi?id=204934
Source/WebCore:

rdar://problem/57686335

Reviewed by Simon Fraser.

Fillout HighlightMap and HighlightRangeGroup with the information that we're passed from
the JavaScript side. Make sure that the javascript objects are filled out correctly.

Test: highlight/highlight-map-and-group.html

* Modules/highlight/HighlightMap.cpp:
(WebCore::HighlightMap::synchronizeBackingMap):
(WebCore::HighlightMap::setFromMapLike):
(WebCore::HighlightMap::clear):
(WebCore::HighlightMap::remove):
(WebCore::HighlightMap::getGroupForStyle):
(WebCore::HighlightMap::addHighlightGroup): Deleted.
(WebCore::HighlightMap::namedItem const): Deleted.
(WebCore::HighlightMap::setNamedItem): Deleted.
(WebCore::HighlightMap::deleteNamedProperty): Deleted.
* Modules/highlight/HighlightMap.h:
(WebCore::HighlightMap::backingMap):
(WebCore::HighlightMap::synchronizeBackingMap): Deleted.
(WebCore::HighlightMap::clear): Deleted.
* Modules/highlight/HighlightMap.idl:
* Modules/highlight/HighlightRangeGroup.cpp:
(WebCore::HighlightRangeGroup::HighlightRangeGroup):
(WebCore::HighlightRangeGroup::initializeSetLike):
(WebCore::HighlightRangeGroup::removeFromSetLike):
(WebCore::HighlightRangeGroup::clearFromSetLike):
(WebCore::HighlightRangeGroup::addToSetLike):
(WebCore::HighlightRangeGroup::addRange): Deleted.
(WebCore::HighlightRangeGroup::removeRange): Deleted.
(WebCore::HighlightRangeGroup::Iterator::Iterator): Deleted.
(WebCore::HighlightRangeGroup::Iterator::next): Deleted.
* Modules/highlight/HighlightRangeGroup.h:
(WebCore::HighlightRangeGroup::ranges const):
(): Deleted.
(WebCore::HighlightRangeGroup::createIterator): Deleted.
* Modules/highlight/HighlightRangeGroup.idl:
* dom/StaticRange.cpp:
(WebCore::StaticRange::operator== const):
* dom/StaticRange.h:

LayoutTests:

Reviewed by Simon Fraser.

* highlight/highlight-map-and-group-expected.txt: Added.
* highlight/highlight-map-and-group.html: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@253309 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 50c3473..595f255 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,13 @@
+2019-12-09  Megan Gardner  <megan_gardner@apple.com>
+
+        Fill HighlightRangeGroup and HighlightMap with values from JavaScript
+        https://bugs.webkit.org/show_bug.cgi?id=204934
+
+        Reviewed by Simon Fraser.
+
+        * highlight/highlight-map-and-group-expected.txt: Added.
+        * highlight/highlight-map-and-group.html: Added.
+
 2019-12-09  Truitt Savell  <tsavell@apple.com>
 
         Unreviewed, rolling out r253299.
diff --git a/LayoutTests/highlight/highlight-map-and-group-expected.txt b/LayoutTests/highlight/highlight-map-and-group-expected.txt
new file mode 100644
index 0000000..fb13219
--- /dev/null
+++ b/LayoutTests/highlight/highlight-map-and-group-expected.txt
@@ -0,0 +1,13 @@
+PASS highlightRangeGroup1.size is 1
+PASS highlightRangeGroup2.size is 2
+PASS highlightRangeGroup3.size is 3
+PASS CSS.highlights.size is 3
+PASS CSS.highlights.has("example-highlight1") is true
+PASS CSS.highlights.has("example-highlight2") is true
+PASS CSS.highlights.has("example-highlight3") is true
+PASS CSS.highlights.get("example-highlight1").entries().next().value[0].startOffset is 1
+PASS CSS.highlights.get("example-highlight1").entries().next().value[0].endOffset is 2
+PASS successfullyParsed is true
+
+TEST COMPLETE
+One two three...
diff --git a/LayoutTests/highlight/highlight-map-and-group.html b/LayoutTests/highlight/highlight-map-and-group.html
new file mode 100644
index 0000000..5b4bfab
--- /dev/null
+++ b/LayoutTests/highlight/highlight-map-and-group.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ experimental:HighlightAPIEnabled=true ] -->
+<html>
+<script src="../resources/js-test.js"></script>
+<head>
+    <style>
+    :root::highlight(example-highlight1) {
+        background-color: yellow;
+        color:blue;
+    }
+    :root::highlight(example-highlight2) {
+        background-color: yellow;
+        color:blue;
+    }
+    :root::highlight(example-highlight3) {
+        background-color: yellow;
+        color:blue;
+    }
+    </style>
+</head>
+    <body><span>One </span><span>two </span><span>three...</span>
+
+    <script>
+        let highlightRangeGroup1 = new HighlightRangeGroup(new StaticRange({startContainer: document.body, startOffset: 1, endContainer: document.body, endOffset: 2}));
+
+        let highlightRangeGroup2 = new HighlightRangeGroup(new StaticRange({startContainer: document.body, startOffset: 2, endContainer: document.body, endOffset: 3}));
+        highlightRangeGroup2.add(new StaticRange({startContainer: document.body, startOffset: 4, endContainer: document.body, endOffset: 5}));
+
+        let highlightRangeGroup3 = new HighlightRangeGroup(new StaticRange({startContainer: document.body, startOffset: 4, endContainer: document.body, endOffset: 8}));
+        highlightRangeGroup3.add(new StaticRange({startContainer: document.body, startOffset: 10, endContainer: document.body, endOffset: 12}));
+        highlightRangeGroup3.add(new StaticRange({startContainer: document.body, startOffset: 5, endContainer: document.body, endOffset: 6}));
+        
+
+        CSS.highlights.set("example-highlight1", highlightRangeGroup1);
+        CSS.highlights.set("example-highlight2", highlightRangeGroup2);
+        CSS.highlights.set("example-highlight3", highlightRangeGroup3);
+
+        shouldBe("highlightRangeGroup1.size","1");
+        shouldBe("highlightRangeGroup2.size","2");
+        shouldBe("highlightRangeGroup3.size","3");
+
+        shouldBe("CSS.highlights.size","3");
+
+        shouldBeTrue("CSS.highlights.has(\"example-highlight1\")");
+        shouldBeTrue("CSS.highlights.has(\"example-highlight2\")");
+        shouldBeTrue("CSS.highlights.has(\"example-highlight3\")");
+
+        shouldBe("CSS.highlights.get(\"example-highlight1\").entries().next().value[0].startOffset","1");
+        shouldBe("CSS.highlights.get(\"example-highlight1\").entries().next().value[0].endOffset","2");
+
+        
+    </script>
+
+    </body>
+</html>
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 7448554..90b26bc 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,50 @@
+2019-12-09  Megan Gardner  <megan_gardner@apple.com>
+
+        Fill HighlightRangeGroup and HighlightMap with values from JavaScript
+        https://bugs.webkit.org/show_bug.cgi?id=204934
+        rdar://problem/57686335
+
+        Reviewed by Simon Fraser.
+
+        Fillout HighlightMap and HighlightRangeGroup with the information that we're passed from
+        the JavaScript side. Make sure that the javascript objects are filled out correctly.
+
+        Test: highlight/highlight-map-and-group.html
+
+        * Modules/highlight/HighlightMap.cpp:
+        (WebCore::HighlightMap::synchronizeBackingMap):
+        (WebCore::HighlightMap::setFromMapLike):
+        (WebCore::HighlightMap::clear):
+        (WebCore::HighlightMap::remove):
+        (WebCore::HighlightMap::getGroupForStyle):
+        (WebCore::HighlightMap::addHighlightGroup): Deleted.
+        (WebCore::HighlightMap::namedItem const): Deleted.
+        (WebCore::HighlightMap::setNamedItem): Deleted.
+        (WebCore::HighlightMap::deleteNamedProperty): Deleted.
+        * Modules/highlight/HighlightMap.h:
+        (WebCore::HighlightMap::backingMap):
+        (WebCore::HighlightMap::synchronizeBackingMap): Deleted.
+        (WebCore::HighlightMap::clear): Deleted.
+        * Modules/highlight/HighlightMap.idl:
+        * Modules/highlight/HighlightRangeGroup.cpp:
+        (WebCore::HighlightRangeGroup::HighlightRangeGroup):
+        (WebCore::HighlightRangeGroup::initializeSetLike):
+        (WebCore::HighlightRangeGroup::removeFromSetLike):
+        (WebCore::HighlightRangeGroup::clearFromSetLike):
+        (WebCore::HighlightRangeGroup::addToSetLike):
+        (WebCore::HighlightRangeGroup::addRange): Deleted.
+        (WebCore::HighlightRangeGroup::removeRange): Deleted.
+        (WebCore::HighlightRangeGroup::Iterator::Iterator): Deleted.
+        (WebCore::HighlightRangeGroup::Iterator::next): Deleted.
+        * Modules/highlight/HighlightRangeGroup.h:
+        (WebCore::HighlightRangeGroup::ranges const):
+        (): Deleted.
+        (WebCore::HighlightRangeGroup::createIterator): Deleted.
+        * Modules/highlight/HighlightRangeGroup.idl:
+        * dom/StaticRange.cpp:
+        (WebCore::StaticRange::operator== const):
+        * dom/StaticRange.h:
+
 2019-12-09  Truitt Savell  <tsavell@apple.com>
 
         Unreviewed, rolling out r253299.
diff --git a/Source/WebCore/Modules/highlight/HighlightMap.cpp b/Source/WebCore/Modules/highlight/HighlightMap.cpp
index 433cd6e..3a02331 100644
--- a/Source/WebCore/Modules/highlight/HighlightMap.cpp
+++ b/Source/WebCore/Modules/highlight/HighlightMap.cpp
@@ -26,52 +26,36 @@
 #include "config.h"
 #include "HighlightMap.h"
 
+#include "IDLTypes.h"
 #include "JSDOMMapLike.h"
 #include "JSHighlightRangeGroup.h"
 
 namespace WebCore {
-
-void HighlightMap::addHighlightGroup(String& cssStyle, HighlightRangeGroup &group)
-{
-    UNUSED_PARAM(cssStyle);
-    UNUSED_PARAM(group);
-}
-
+    
 void HighlightMap::initializeMapLike(DOMMapAdapter& map)
 {
     for (auto& keyValue : m_map)
         map.set<IDLDOMString, IDLInterface<HighlightRangeGroup>>(keyValue.key, keyValue.value);
 }
 
-void HighlightMap::setFromMapLike(String&&, Ref<HighlightRangeGroup>&&)
+void HighlightMap::setFromMapLike(String&& key, Ref<HighlightRangeGroup>&& value)
 {
+    m_map.set(WTFMove(key), WTFMove(value));
 }
 
-bool HighlightMap::remove(const String& value)
+void HighlightMap::clear()
 {
-    UNUSED_PARAM(value);
-    return false;
+    m_map.clear();
 }
 
-String HighlightMap::namedItem(const AtomString& name) const
+bool HighlightMap::remove(const String& key)
 {
-    UNUSED_PARAM(name);
-    
-    return String { };
+    return m_map.remove(key);
 }
 
-ExceptionOr<void> HighlightMap::setNamedItem(const String& name, const HighlightRangeGroup& value)
+RefPtr<HighlightRangeGroup> HighlightMap::getGroupForKey(const String& key)
 {
-    UNUSED_PARAM(name);
-    UNUSED_PARAM(value);
-    
-    return { };
-}
-
-bool HighlightMap::deleteNamedProperty(const String& name)
-{
-    UNUSED_PARAM(name);
-    return false;
+    return m_map.get(key);
 }
 
 }
diff --git a/Source/WebCore/Modules/highlight/HighlightMap.h b/Source/WebCore/Modules/highlight/HighlightMap.h
index 69a70b0..ff98cc3 100644
--- a/Source/WebCore/Modules/highlight/HighlightMap.h
+++ b/Source/WebCore/Modules/highlight/HighlightMap.h
@@ -39,17 +39,12 @@
 public:
     static Ref<HighlightMap> create() { return adoptRef(*new HighlightMap); }
 
-    void addHighlightGroup(String&, HighlightRangeGroup&);
     void initializeMapLike(DOMMapAdapter&);
-
-    // Bindings support.
-    String namedItem(const AtomString& name) const;
-    ExceptionOr<void> setNamedItem(const String& name, const HighlightRangeGroup& value);
-    bool deleteNamedProperty(const String& name);
-    
     void setFromMapLike(String&&, Ref<HighlightRangeGroup>&&);
-    void clear() { };
-    bool remove(const String& value);
+    void clear();
+    bool remove(const String&);
+    
+    RefPtr<HighlightRangeGroup> getGroupForKey(const String& key);
     
 private:
     HighlightMap() = default;
diff --git a/Source/WebCore/Modules/highlight/HighlightMap.idl b/Source/WebCore/Modules/highlight/HighlightMap.idl
index 36e5b55..d897a78 100644
--- a/Source/WebCore/Modules/highlight/HighlightMap.idl
+++ b/Source/WebCore/Modules/highlight/HighlightMap.idl
@@ -29,5 +29,4 @@
     ImplementationLacksVTable
 ] interface HighlightMap {
     maplike<DOMString, HighlightRangeGroup>;
-    [CEReactions, MayThrowException] setter void (DOMString style, HighlightRangeGroup group);
 };
diff --git a/Source/WebCore/Modules/highlight/HighlightRangeGroup.cpp b/Source/WebCore/Modules/highlight/HighlightRangeGroup.cpp
index 856ba386..dd53cbb 100644
--- a/Source/WebCore/Modules/highlight/HighlightRangeGroup.cpp
+++ b/Source/WebCore/Modules/highlight/HighlightRangeGroup.cpp
@@ -26,15 +26,18 @@
 #include "config.h"
 #include "HighlightRangeGroup.h"
 
+#include "IDLTypes.h"
+#include "JSDOMSetLike.h"
+#include "JSStaticRange.h"
 #include "PropertySetCSSStyleDeclaration.h"
 #include "StaticRange.h"
 #include "StyleProperties.h"
 
 namespace WebCore {
 
-HighlightRangeGroup::HighlightRangeGroup(StaticRange& range)
+HighlightRangeGroup::HighlightRangeGroup(Ref<StaticRange>&& range)
 {
-    addRange(range);
+    m_ranges.append(WTFMove(range));
 }
 
 Ref<HighlightRangeGroup> HighlightRangeGroup::create(StaticRange& range)
@@ -42,30 +45,30 @@
     return adoptRef(*new HighlightRangeGroup(range));
 }
 
-ExceptionOr<void> HighlightRangeGroup::addRange(StaticRange& range)
+void HighlightRangeGroup::initializeSetLike(DOMSetAdapter& set)
 {
-    UNUSED_PARAM(range);
-
-    return { };
+    for (auto& range : m_ranges)
+        set.add<IDLInterface<StaticRange>>(range);
 }
 
-ExceptionOr<void> HighlightRangeGroup::removeRange(StaticRange& range)
+bool HighlightRangeGroup::removeFromSetLike(const StaticRange& range)
 {
-    UNUSED_PARAM(range);
-    
-    return { };
+    return m_ranges.removeFirstMatching([&range](const Ref<StaticRange>& current) {
+        return current.get() == range;
+    });
 }
 
-HighlightRangeGroup::Iterator::Iterator(HighlightRangeGroup& group)
-    : m_group(group)
+void HighlightRangeGroup::clearFromSetLike()
 {
+    m_ranges.clear();
 }
 
-RefPtr<StaticRange> HighlightRangeGroup::Iterator::next()
+bool HighlightRangeGroup::addToSetLike(StaticRange& range)
 {
-    if (m_index == m_group->ranges.size())
-        return nullptr;
-    return m_group->ranges[m_index++].ptr();
+    if (notFound != m_ranges.findMatching([&range](const Ref<StaticRange>& current) { return current.get() == range; }))
+        return false;
+    m_ranges.append(makeRef(range));
+    return true;
 }
 
 }
diff --git a/Source/WebCore/Modules/highlight/HighlightRangeGroup.h b/Source/WebCore/Modules/highlight/HighlightRangeGroup.h
index b8bc8e2..9724506 100644
--- a/Source/WebCore/Modules/highlight/HighlightRangeGroup.h
+++ b/Source/WebCore/Modules/highlight/HighlightRangeGroup.h
@@ -32,33 +32,26 @@
 namespace WebCore {
 
 class CSSStyleDeclaration;
+class DOMSetAdapter;
 class StaticRange;
 class PropertySetCSSStyleDeclaration;
 
 class HighlightRangeGroup : public RefCounted<HighlightRangeGroup> {
 public:
     static Ref<HighlightRangeGroup> create(StaticRange&);
-
-    ExceptionOr<void> addRange(StaticRange&);
-    ExceptionOr<void> removeRange(StaticRange&);
     
-    Vector<Ref<StaticRange>> ranges;
-
-    WEBCORE_EXPORT CSSStyleDeclaration& style();
+    void clearFromSetLike();
+    bool addToSetLike(StaticRange&);
+    bool removeFromSetLike(const StaticRange&);
+    void initializeSetLike(DOMSetAdapter&);
     
-    class Iterator {
-    public:
-        explicit Iterator(HighlightRangeGroup&);
-        RefPtr<StaticRange> next();
-        
-    private:
-        Ref<HighlightRangeGroup> m_group;
-        size_t m_index { 0 }; // FIXME: There needs to be a mechanism to handle when ranges are added or removed from the middle of the HighlightRangeGroup.
-    };
-    Iterator createIterator() { return Iterator(*this); }
+    const Vector<Ref<StaticRange>>& ranges() const { return m_ranges; }
+
+    // FIXME: Add WEBCORE_EXPORT CSSStyleDeclaration& style();
     
 private:
-    HighlightRangeGroup(StaticRange&);
+    Vector<Ref<StaticRange>> m_ranges; // TODO: use a HashSet instead of a Vector <rdar://problem/57760614>
+    explicit HighlightRangeGroup(Ref<StaticRange>&&);
 };
 
 }
diff --git a/Source/WebCore/Modules/highlight/HighlightRangeGroup.idl b/Source/WebCore/Modules/highlight/HighlightRangeGroup.idl
index 1ec20e9..4fc0013 100644
--- a/Source/WebCore/Modules/highlight/HighlightRangeGroup.idl
+++ b/Source/WebCore/Modules/highlight/HighlightRangeGroup.idl
@@ -28,6 +28,6 @@
     EnabledAtRuntime=HighlightAPI,
     ImplementationLacksVTable
 ] interface HighlightRangeGroup {
-    iterable<StaticRange>;  // FIXME: should be setlike
+    setlike<StaticRange>;
     // FIXME: Add readonly attribute CSSStyleDeclaration style;
 };
diff --git a/Source/WebCore/dom/StaticRange.cpp b/Source/WebCore/dom/StaticRange.cpp
index 198aa1a..8136da1 100644
--- a/Source/WebCore/dom/StaticRange.cpp
+++ b/Source/WebCore/dom/StaticRange.cpp
@@ -81,4 +81,9 @@
     return m_startOffset == m_endOffset && m_startContainer.ptr() == m_endContainer.ptr();
 }
 
+bool StaticRange::operator==(const StaticRange& other) const
+{
+    return (m_startOffset == other.startOffset() && m_endOffset == other.endOffset() && m_startContainer->isEqualNode(other.startContainer()) && m_endContainer->isEqualNode(other.endContainer()));
+}
+
 }
diff --git a/Source/WebCore/dom/StaticRange.h b/Source/WebCore/dom/StaticRange.h
index f48c8d4..f80d85e 100644
--- a/Source/WebCore/dom/StaticRange.h
+++ b/Source/WebCore/dom/StaticRange.h
@@ -55,6 +55,8 @@
     Node* startContainer() const;
     Node* endContainer() const;
     bool collapsed() const;
+    
+    bool operator==(const StaticRange&) const;
 
 private:
     StaticRange(Ref<Node>&& startContainer, unsigned startOffset, Ref<Node>&& endContainer, unsigned endOffset);