Title: [241714] releases/WebKitGTK/webkit-2.24
Revision
241714
Author
carlo...@webkit.org
Date
2019-02-18 08:17:10 -0800 (Mon, 18 Feb 2019)

Log Message

Merge r241652 - Web Inspector: Frontend performance is very slow reloading theverge.com - 50% of time in TreeOutline _indexOfTreeElement
https://bugs.webkit.org/show_bug.cgi?id=193605
<rdar://problem/47403986>

Reviewed by Devin Rousso.

Source/WebInspectorUI:

SelectionController should track an unordered Set of represented objects
instead of an ordered set of indexes. This eliminates the costly and
error-prone updates needed to keep the selected indexes in sync as items
are added and removed from TreeOutline (and Table, to a far lesser extent).

The SelectionController interface is largely the same. Class and delegate
methods have been renamed to reflect the change from indexes to objects.
SelectionController tracks selected items in selection order. For the
operations that rely on objects being in insertion order, the controller
uses a comparator function provided at construction time.

* UserInterface/Base/IndexSet.js: Removed.
No longer used. SelectionController now uses a plain Set.

* UserInterface/Base/Utilities.js:
(value):
(get return):
Add utilities previously supplied by IndexSet and used by SelectionController.

* UserInterface/Controllers/SelectionController.js:
(WI.SelectionController):
(WI.SelectionController.prototype.get lastSelectedItem):
(WI.SelectionController.prototype.get selectedItems):
(WI.SelectionController.prototype.set allowsMultipleSelection):
(WI.SelectionController.prototype.hasSelectedItem):
(WI.SelectionController.prototype.selectItem):
(WI.SelectionController.prototype.deselectItem):
(WI.SelectionController.prototype.selectAll):
(WI.SelectionController.prototype.deselectAll):
(WI.SelectionController.prototype.removeSelectedItems):
(WI.SelectionController.prototype.reset):
(WI.SelectionController.prototype.didRemoveItems):
(WI.SelectionController.prototype.handleKeyDown):
(WI.SelectionController.prototype.handleItemMouseDown):
(WI.SelectionController.prototype._deselectAllAndSelect):
(WI.SelectionController.prototype._selectItemsFromArrowKey):
(WI.SelectionController.prototype._firstSelectableItem):
(WI.SelectionController.prototype._lastSelectableItem):
(WI.SelectionController.prototype._previousSelectableItem):
(WI.SelectionController.prototype._nextSelectableItem):
(WI.SelectionController.prototype._updateSelectedItems):
(WI.SelectionController.prototype._addRange):
(WI.SelectionController.prototype._deleteRange):
(WI.SelectionController.prototype.get numberOfItems): Deleted.
(WI.SelectionController.prototype.didInsertItem): Deleted.
(WI.SelectionController.prototype.handleItemMouseDown.normalizeRange): Deleted.
(WI.SelectionController.prototype._nextSelectableIndex): Deleted.
(WI.SelectionController.prototype._previousSelectableIndex): Deleted.

* UserInterface/Main.html:
* UserInterface/Test.html:
Remove IndexSet.

* UserInterface/Views/CookieStorageContentView.js:
(WI.CookieStorageContentView.prototype.tableIndexForRepresentedObject):
(WI.CookieStorageContentView.prototype.tableRepresentedObjectForIndex):

* UserInterface/Views/DOMTreeOutline.js:
(WI.DOMTreeOutline.prototype.objectForSelection):

* UserInterface/Views/NetworkTableContentView.js:
(WI.NetworkTableContentView.prototype.tableIndexForRepresentedObject):
(WI.NetworkTableContentView.prototype.tableRepresentedObjectForIndex):

* UserInterface/Views/Table.js:
(WI.Table):
(WI.Table.prototype.get selectedRow):
(WI.Table.prototype.get selectedRows):
(WI.Table.prototype.isRowSelected):
(WI.Table.prototype.selectRow):
(WI.Table.prototype.deselectRow):
(WI.Table.prototype.removeRow):
(WI.Table.prototype.removeSelectedRows):
(WI.Table.prototype.selectionControllerSelectionDidChange):
(WI.Table.prototype.selectionControllerFirstSelectableItem):
(WI.Table.prototype.selectionControllerLastSelectableItem):
(WI.Table.prototype.selectionControllerPreviousSelectableItem):
(WI.Table.prototype.selectionControllerNextSelectableItem):
(WI.Table.prototype._handleMouseDown):
(WI.Table.prototype._removeRows):
(WI.Table.prototype._indexForRepresentedObject):
(WI.Table.prototype._representedObjectForIndex):
(WI.Table.prototype.selectionControllerNumberOfItems): Deleted.
(WI.Table.prototype.selectionControllerNextSelectableIndex): Deleted.
(WI.Table.prototype.selectionControllerPreviousSelectableIndex): Deleted.
(WI.Table.prototype._toggleSelectedRowStyle): Deleted.

* UserInterface/Views/TreeOutline.js:
(WI.TreeOutline.compareSiblings):
(WI.TreeOutline):
(WI.TreeOutline.prototype.get selectedTreeElement):
(WI.TreeOutline.prototype.set selectedTreeElement):
(WI.TreeOutline.prototype.get selectedTreeElements):
(WI.TreeOutline.prototype.removeChildAtIndex):
(WI.TreeOutline.prototype.removeChildren):
(WI.TreeOutline.prototype._rememberTreeElement):
(WI.TreeOutline.prototype.getCachedTreeElement):
(WI.TreeOutline.prototype.selectionControllerSelectionDidChange):
(WI.TreeOutline.prototype.selectionControllerFirstSelectableItem):
(WI.TreeOutline.prototype.selectionControllerLastSelectableItem):
(WI.TreeOutline.prototype.selectionControllerPreviousSelectableItem):
(WI.TreeOutline.prototype.selectionControllerNextSelectableItem):
(WI.TreeOutline.prototype.objectForSelection):
(WI.TreeOutline._generateStyleRulesIfNeeded):
(WI.TreeOutline.prototype.selectionControllerNextSelectableIndex): Deleted.
(WI.TreeOutline.prototype.selectionControllerPreviousSelectableIndex): Deleted.
(WI.TreeOutline._generateStyleRulesIfNeeded._indexesForSubtree.numberOfElementsInSubtree): Deleted.

LayoutTests:

* inspector/table/resources/table-utilities.js:
(TestPage.registerInitializer.InspectorTest.TableDataSource.prototype.tableIndexForRepresentedObject):
(TestPage.registerInitializer.InspectorTest.TableDataSource.prototype.tableRepresentedObjectForIndex):
(TestPage.registerInitializer.InspectorTest.TableDataSource):
New Table data source methods.

* inspector/unit-tests/index-set-expected.txt: Removed.
* inspector/unit-tests/index-set.html: Removed.
* inspector/unit-tests/set-utilities-expected.txt:
* inspector/unit-tests/set-utilities.html:
Remove IndexSet tests and update tests for Set utilities to include new
helper methods `equals` and `difference`, and `firstValue`.

Modified Paths

Removed Paths

Diff

Modified: releases/WebKitGTK/webkit-2.24/LayoutTests/ChangeLog (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/ChangeLog	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/ChangeLog	2019-02-18 16:17:10 UTC (rev 241714)
@@ -1,3 +1,24 @@
+2019-02-17  Matt Baker  <mattba...@apple.com>
+
+        Web Inspector: Frontend performance is very slow reloading theverge.com - 50% of time in TreeOutline _indexOfTreeElement
+        https://bugs.webkit.org/show_bug.cgi?id=193605
+        <rdar://problem/47403986>
+
+        Reviewed by Devin Rousso.
+
+        * inspector/table/resources/table-utilities.js:
+        (TestPage.registerInitializer.InspectorTest.TableDataSource.prototype.tableIndexForRepresentedObject):
+        (TestPage.registerInitializer.InspectorTest.TableDataSource.prototype.tableRepresentedObjectForIndex):
+        (TestPage.registerInitializer.InspectorTest.TableDataSource):
+        New Table data source methods.
+
+        * inspector/unit-tests/index-set-expected.txt: Removed.
+        * inspector/unit-tests/index-set.html: Removed.
+        * inspector/unit-tests/set-utilities-expected.txt:
+        * inspector/unit-tests/set-utilities.html:
+        Remove IndexSet tests and update tests for Set utilities to include new
+        helper methods `equals` and `difference`, and `firstValue`.
+
 2019-02-16  Zalan Bujtas  <za...@apple.com>
 
         [LFC] Apply min/max width constraints to preferred width computation

Modified: releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/table/resources/table-utilities.js (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/table/resources/table-utilities.js	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/table/resources/table-utilities.js	2019-02-18 16:17:10 UTC (rev 241714)
@@ -12,6 +12,16 @@
         {
             return this._items.length;
         }
+
+        tableIndexForRepresentedObject(table, object)
+        {
+            return this._items.indexOf(object);
+        }
+
+        tableRepresentedObjectForIndex(table, index)
+        {
+            return this._items[index];
+        }
     };
 
     InspectorTest.TableDelegate = class TableDelegate

Deleted: releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/unit-tests/index-set-expected.txt (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/unit-tests/index-set-expected.txt	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/unit-tests/index-set-expected.txt	2019-02-18 16:17:10 UTC (rev 241714)
@@ -1,153 +0,0 @@
-Tests for WI.IndexSet.
-
-
-== Running test suite: IndexSet
--- Running test case: IndexSet.constructor
-PASS: size should be zero.
-PASS: firstIndex should be NaN.
-PASS: lastIndex should be NaN.
-PASS: Should be [].
-
--- Running test case: IndexSet.constructor array
-Initialize IndexSet with an array.
-PASS: size should be 5.
-PASS: firstIndex should be 0.
-PASS: lastIndex should be 100.
-PASS: Should be [0,1,5,50,100].
-Initialize IndexSet with an array containing duplicate indexes.
-PASS: size should be 5.
-PASS: Should be [0,1,5,50,100].
-
--- Running test case: IndexSet.constructor invalid
-PASS: size should be zero.
-
--- Running test case: IndexSet.prototype.clear
-PASS: size should be zero.
-PASS: firstIndex should be NaN.
-PASS: lastIndex should be NaN.
-PASS: Should be [].
-
--- Running test case: IndexSet.prototype.add
-PASS: size should be 1.
-PASS: has should return true.
-
--- Running test case: IndexSet.prototype.add duplicate
-PASS: size should be 1.
-
--- Running test case: IndexSet.prototype.add invalid
-PASS: size should be zero.
-
--- Running test case: IndexSet.prototype.delete
-Given an IndexSet with values [1,2,3]:
-PASS: delete 3 should succeed.
-PASS: has 3 should return false.
-
--- Running test case: IndexSet.prototype.delete nonexistent
-Given an IndexSet with values [1,2,3]:
-PASS: delete 4 should fail.
-
--- Running test case: IndexSet.prototype.delete invalid
--- Running test case: IndexSet.prototype[Symbol.iterator]
-Given an IndexSet with values [20,1,10,2]:
-1
-2
-10
-20
-
--- Running test case: IndexSet.prototype.indexGreaterThan
-Given an IndexSet with values [1,2]:
-PASS: Index greater than 0 should be 1.
-PASS: Index greater than 1 should be 2.
-PASS: Index greater than 2 should be NaN.
-PASS: Index greater than 3 should be NaN.
-
--- Running test case: IndexSet.prototype.indexLessThan
-Given an IndexSet with values [1,2]:
-PASS: Index less than 0 should be NaN.
-PASS: Index less than 1 should be NaN.
-PASS: Index less than 2 should be 1.
-PASS: Index less than 3 should be 2.
-
--- Running test case: IndexSet.prototype.copy
-PASS: Copy and original should be different objects.
-PASS: Copy and original should have the same values.
-
--- Running test case: IndexSet.prototype.addRange
-Given an IndexSet with values []:
-Add range to an empty IndexSet.
-PASS: Should be [1,2,3] after adding [1,2,3].
-
-Given an IndexSet with values [10,11,12]:
-Add range before the beginning.
-PASS: Should be [0,1,2,10,11,12] after adding [0,1,2].
-
-Given an IndexSet with values [1,2,3]:
-Add range after the end.
-PASS: Should be [1,2,3,10,11,12] after adding [10,11,12].
-
-Given an IndexSet with values [1,5]:
-Add range in the middle.
-PASS: Should be [1,2,3,4,5] after adding [2,3,4].
-
-Given an IndexSet with values [1,3,5]:
-Add range overlapping the middle.
-PASS: Should be [1,2,3,4,5] after adding [2,3,4].
-
-Given an IndexSet with values [3,4,5]:
-Add range overlapping the beginning.
-PASS: Should be [1,2,3,4,5] after adding [1,2,3].
-
-Given an IndexSet with values [1,2,3]:
-Add range overlapping the end.
-PASS: Should be [1,2,3,4,5] after adding [3,4,5].
-
-
--- Running test case: IndexSet.prototype.deleteRange
-Given an IndexSet with values []:
-Remove range from an empty IndexSet.
-PASS: Should be [] after removing [1,2,3].
-
-Given an IndexSet with values [10,11,12]:
-Remove range before the beginning.
-PASS: Should be [10,11,12] after removing [0,1,2].
-
-Given an IndexSet with values [0,1,2]:
-Remove range after the end.
-PASS: Should be [0,1,2] after removing [10,11,12].
-
-Given an IndexSet with values [0,1,2,3]:
-Remove range in the middle.
-PASS: Should be [0,3] after removing [1,2].
-
-Given an IndexSet with values [1,3,5]:
-Remove range overlapping the middle.
-PASS: Should be [1,5] after removing [2,3,4].
-
-Given an IndexSet with values [1,2,3]:
-Remove range overlapping the beginning.
-PASS: Should be [3] after removing [0,1,2].
-
-Given an IndexSet with values [1,2,3]:
-Remove range overlapping the end.
-PASS: Should be [1] after removing [2,3,4].
-
-
--- Running test case: IndexSet.prototype.equals
-PASS: Should trivially equal itself.
-PASS: Copy and original should be equal.
-PASS: Modified copy and original should not be equal.
-
--- Running test case: IndexSet.prototype.difference
-Given an IndexSet with values [], and another IndexSet with values []:
-PASS: Difference between the first and second IndexSet should be [].
-
-Given an IndexSet with values [1,2,3], and another IndexSet with values []:
-PASS: Difference between the first and second IndexSet should be [1,2,3].
-
-Given an IndexSet with values [], and another IndexSet with values [1,2,3]:
-PASS: Difference between the first and second IndexSet should be [].
-
-Given an IndexSet with values [1,2,3], and another IndexSet with values [2,3,4]:
-PASS: Difference between the first and second IndexSet should be [1].
-
-

Deleted: releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/unit-tests/index-set.html (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/unit-tests/index-set.html	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/unit-tests/index-set.html	2019-02-18 16:17:10 UTC (rev 241714)
@@ -1,424 +0,0 @@
-<!doctype html>
-<html>
-<head>
-<script src=""
-<script>
-function test()
-{
-    let suite = InspectorTest.createSyncSuite("IndexSet");
-
-    function createIndexSet(values = []) {
-        if (!Array.isArray(values))
-            values = [values];
-        InspectorTest.log(`Given an IndexSet with values [${values}]:`);
-
-        return new WI.IndexSet(values);
-    }
-
-    function rangeToArray(startIndex, count) {
-        let result = [];
-        for (let i = 0; i < count; ++i)
-            result.push(startIndex + i);
-        return result;
-    }
-
-    suite.addTestCase({
-        name: "IndexSet.constructor",
-        test() {
-            let indexSet = new WI.IndexSet;
-            InspectorTest.expectEqual(indexSet.size, 0, "size should be zero.");
-            InspectorTest.expectThat(isNaN(indexSet.firstIndex), "firstIndex should be NaN.");
-            InspectorTest.expectThat(isNaN(indexSet.lastIndex), "lastIndex should be NaN.");
-            InspectorTest.expectShallowEqual(Array.from(indexSet), [], "Should be [].");
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.constructor array",
-        test() {
-            const values = [5, 1, 0, 100, 50];
-            const sortedValues = values.slice().sort((a, b) => a - b);
-
-            InspectorTest.log("Initialize IndexSet with an array.");
-            {
-                let indexSet = new WI.IndexSet(values);
-                InspectorTest.expectEqual(indexSet.size, values.length, `size should be ${values.length}.`);
-                InspectorTest.expectEqual(indexSet.firstIndex, sortedValues[0], `firstIndex should be ${sortedValues[0]}.`);
-                InspectorTest.expectEqual(indexSet.lastIndex, sortedValues.lastValue, `lastIndex should be ${sortedValues.lastValue}.`);
-                InspectorTest.expectShallowEqual(Array.from(indexSet), sortedValues, `Should be [${sortedValues}].`);
-            }
-
-            InspectorTest.log("Initialize IndexSet with an array containing duplicate indexes.");
-            {
-                let indexSet = new WI.IndexSet(values.concat(values));
-                InspectorTest.expectEqual(indexSet.size, values.length, `size should be ${values.length}.`);
-                InspectorTest.expectShallowEqual(Array.from(indexSet), sortedValues, `Should be [${sortedValues}].`);
-            }
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.constructor invalid",
-        test() {
-            let indexSet = new WI.IndexSet([-1, 1.5, "abc"]);
-            InspectorTest.expectEqual(indexSet.size, 0, "size should be zero.");
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype.clear",
-        test() {
-            let indexSet = new WI.IndexSet([1, 2, 3]);
-            indexSet.add(42);
-            indexSet.clear();
-            InspectorTest.expectEqual(indexSet.size, 0, "size should be zero.");
-            InspectorTest.expectThat(isNaN(indexSet.firstIndex), "firstIndex should be NaN.");
-            InspectorTest.expectThat(isNaN(indexSet.lastIndex), "lastIndex should be NaN.");
-            InspectorTest.expectShallowEqual(Array.from(indexSet), [], "Should be [].");
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype.add",
-        test() {
-            let indexSet = new WI.IndexSet;
-            indexSet.add(42);
-            InspectorTest.expectEqual(indexSet.size, 1, "size should be 1.");
-            InspectorTest.expectThat(indexSet.has(42), "has should return true.");
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype.add duplicate",
-        test() {
-            let indexSet = new WI.IndexSet;
-            indexSet.add(42);
-            indexSet.add(42);
-            InspectorTest.expectEqual(indexSet.size, 1, "size should be 1.");
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype.add invalid",
-        test() {
-            let indexSet = new WI.IndexSet;
-            indexSet.add(-1);
-            indexSet.add(1.5);
-            indexSet.add("abc");
-            InspectorTest.expectEqual(indexSet.size, 0, "size should be zero.");
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype.delete",
-        test() {
-            let indexSet = createIndexSet([1, 2, 3]);
-            const indexToDelete = indexSet.lastIndex;
-            let wasDeleted = indexSet.delete(indexToDelete);
-            InspectorTest.expectThat(wasDeleted, `delete ${indexToDelete} should succeed.`);
-            InspectorTest.expectFalse(indexSet.has(indexToDelete), `has ${indexToDelete} should return false.`);
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype.delete nonexistent",
-        test() {
-            let indexSet = createIndexSet([1, 2, 3]);
-            const indexToDelete = indexSet.lastIndex + 1;
-            let wasDeleted = indexSet.delete(indexToDelete);
-            InspectorTest.expectFalse(wasDeleted, `delete ${indexToDelete} should fail.`);
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype.delete invalid",
-        test() {
-            let indexSet = new WI.IndexSet;
-            indexSet.delete(-1);
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype[Symbol.iterator]",
-        test() {
-            let indexSet = createIndexSet([20, 1, 10, 2]);
-            for (let index of indexSet)
-                InspectorTest.log(index);
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype.indexGreaterThan",
-        test() {
-            let indexSet = createIndexSet([1, 2]);
-            const {firstIndex, lastIndex} = indexSet;
-            const indexBefore = firstIndex - 1;
-            const indexAfter = lastIndex + 1;
-            InspectorTest.expectEqual(indexSet.indexGreaterThan(indexBefore), firstIndex, `Index greater than ${indexBefore} should be ${firstIndex}.`);
-            InspectorTest.expectEqual(indexSet.indexGreaterThan(firstIndex), lastIndex, `Index greater than ${firstIndex} should be ${lastIndex}.`);
-            InspectorTest.expectThat(isNaN(indexSet.indexGreaterThan(lastIndex)), `Index greater than ${lastIndex} should be NaN.`);
-            InspectorTest.expectThat(isNaN(indexSet.indexGreaterThan(indexAfter)), `Index greater than ${indexAfter} should be NaN.`);
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype.indexLessThan",
-        test() {
-            let indexSet = createIndexSet([1, 2]);
-            const {firstIndex, lastIndex} = indexSet;
-            const indexBefore = firstIndex - 1;
-            const indexAfter = lastIndex + 1;
-
-            InspectorTest.expectThat(isNaN(indexSet.indexLessThan(indexBefore)), `Index less than ${indexBefore} should be NaN.`);
-            InspectorTest.expectThat(isNaN(indexSet.indexLessThan(firstIndex)), `Index less than ${firstIndex} should be NaN.`);
-            InspectorTest.expectEqual(indexSet.indexLessThan(lastIndex), firstIndex, `Index less than ${lastIndex} should be ${firstIndex}.`);
-            InspectorTest.expectEqual(indexSet.indexLessThan(indexAfter), lastIndex, `Index less than ${indexAfter} should be ${lastIndex}.`);
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype.copy",
-        test() {
-            let original = new WI.IndexSet([1, 2, 3]);
-            let copied = original.copy();
-            InspectorTest.expectNotEqual(copied, original, "Copy and original should be different objects.");
-            InspectorTest.expectShallowEqual(Array.from(copied), Array.from(original), "Copy and original should have the same values.");
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype.addRange",
-        test() {
-            function testAddRange({description, initialValues, startIndex, count, expectedValues}) {
-                let indexSet = createIndexSet(initialValues || []);
-
-                InspectorTest.log(description);
-                indexSet.addRange(startIndex, count);
-                InspectorTest.expectShallowEqual(Array.from(indexSet), expectedValues, `Should be [${expectedValues}] after adding [${rangeToArray(startIndex, count)}].`);
-                InspectorTest.log("");
-            }
-
-            testAddRange({
-                description: "Add range to an empty IndexSet.",
-                initialValues: [],
-                startIndex: 1,
-                count: 3,
-                expectedValues: [1, 2, 3],
-            });
-
-            testAddRange({
-                description: "Add range before the beginning.",
-                initialValues: [10, 11, 12],
-                startIndex: 0,
-                count: 3,
-                expectedValues: [0, 1, 2, 10, 11, 12],
-            });
-
-            testAddRange({
-                description: "Add range after the end.",
-                initialValues: [1, 2, 3],
-                startIndex: 10,
-                count: 3,
-                expectedValues: [1, 2, 3, 10, 11, 12],
-            });
-
-            testAddRange({
-                description: "Add range in the middle.",
-                initialValues: [1, 5],
-                startIndex: 2,
-                count: 3,
-                expectedValues: [1, 2, 3, 4, 5],
-            });
-
-            testAddRange({
-                description: "Add range overlapping the middle.",
-                initialValues: [1, 3, 5],
-                startIndex: 2,
-                count: 3,
-                expectedValues: [1, 2, 3, 4, 5],
-            });
-
-            testAddRange({
-                description: "Add range overlapping the beginning.",
-                initialValues: [3, 4, 5],
-                startIndex: 1,
-                count: 3,
-                expectedValues: [1, 2, 3, 4, 5],
-            });
-
-            testAddRange({
-                description: "Add range overlapping the end.",
-                initialValues: [1, 2, 3],
-                startIndex: 3,
-                count: 3,
-                expectedValues: [1, 2, 3, 4, 5],
-            });
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype.deleteRange",
-        test() {
-            function testDeleteRange({description, initialValues, startIndex, count, expectedValues}) {
-                let indexSet = createIndexSet(initialValues || []);
-
-                InspectorTest.log(description);
-                indexSet.deleteRange(startIndex, count);
-                InspectorTest.expectShallowEqual(Array.from(indexSet), expectedValues, `Should be [${expectedValues}] after removing [${rangeToArray(startIndex, count)}].`);
-                InspectorTest.log("");
-            }
-
-            testDeleteRange({
-                description: "Remove range from an empty IndexSet.",
-                initialValues: [],
-                startIndex: 1,
-                count: 3,
-                expectedValues: [],
-            });
-
-            testDeleteRange({
-                description: "Remove range before the beginning.",
-                initialValues: [10, 11, 12],
-                startIndex: 0,
-                count: 3,
-                expectedValues: [10, 11, 12],
-            });
-
-            testDeleteRange({
-                description: "Remove range after the end.",
-                initialValues: [0, 1, 2],
-                startIndex: 10,
-                count: 3,
-                expectedValues: [0, 1, 2],
-            });
-
-            testDeleteRange({
-                description: "Remove range in the middle.",
-                initialValues: [0, 1, 2, 3],
-                startIndex: 1,
-                count: 2,
-                expectedValues: [0, 3],
-            });
-
-            testDeleteRange({
-                description: "Remove range overlapping the middle.",
-                initialValues: [1, 3, 5],
-                startIndex: 2,
-                count: 3,
-                expectedValues: [1, 5],
-            });
-
-            testDeleteRange({
-                description: "Remove range overlapping the beginning.",
-                initialValues: [1, 2, 3],
-                startIndex: 0,
-                count: 3,
-                expectedValues: [3],
-            });
-
-            testDeleteRange({
-                description: "Remove range overlapping the end.",
-                initialValues: [1, 2, 3],
-                startIndex: 2,
-                count: 3,
-                expectedValues: [1],
-            });
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype.equals",
-        test() {
-            let original = new WI.IndexSet([1, 2, 3]);
-            let copied = original.copy();
-            InspectorTest.expectThat(original.equals(original), "Should trivially equal itself.");
-            InspectorTest.expectThat(original.equals(copied), "Copy and original should be equal.");
-
-            copied.delete(1);
-            InspectorTest.expectFalse(original.equals(copied), "Modified copy and original should not be equal.");
-
-            return true;
-        }
-    });
-
-    suite.addTestCase({
-        name: "IndexSet.prototype.difference",
-        test() {
-            function testDifference({values1, values2, expectedDifference}) {
-                let indexSet1 = new WI.IndexSet(values1);
-                let indexSet2 = new WI.IndexSet(values2);
-
-                InspectorTest.log(`Given an IndexSet with values [${values1}], and another IndexSet with values [${values2}]:`);
-
-                let difference = indexSet1.difference(indexSet2);
-                InspectorTest.expectShallowEqual(Array.from(difference), expectedDifference, `Difference between the first and second IndexSet should be [${expectedDifference}].`);
-                InspectorTest.log("");
-            }
-
-            testDifference({
-                values1: [],
-                values2: [],
-                expectedDifference: [],
-            });
-
-            testDifference({
-                values1: [1, 2, 3],
-                values2: [],
-                expectedDifference: [1, 2, 3],
-            });
-
-            testDifference({
-                values1: [],
-                values2: [1, 2, 3],
-                expectedDifference: [],
-            });
-
-            testDifference({
-                values1: [1, 2, 3],
-                values2: [2, 3, 4],
-                expectedDifference: [1],
-            });
-
-            return true;
-        }
-    });
-
-    suite.runTestCasesAndFinish();
-}
-</script>
-</head>
-<body _onLoad_="runTest()">
-    <p>Tests for WI.IndexSet.</p>
-</body>
-</html>

Modified: releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/unit-tests/set-utilities-expected.txt (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/unit-tests/set-utilities-expected.txt	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/unit-tests/set-utilities-expected.txt	2019-02-18 16:17:10 UTC (rev 241714)
@@ -16,3 +16,28 @@
 PASS: a set should be a subset of another set with same and additional values.
 PASS: a set should not be a subset of another set with same and different values.
 
+-- Running test case: Set.prototype.equals
+PASS: an empty set should be equal to another empty set.
+PASS: a set should be equal to another set with the same values.
+PASS: a set should be equal to another set with the same values in a different order.
+PASS: a set should not be a equal to another set with different values.
+PASS: a set should not be equal to another set with same and different values.
+
+-- Running test case: Set.prototype.difference
+Given a Set with values [], and another Set with values []:
+PASS: Set difference should be [].
+
+Given a Set with values [1,2,3], and another Set with values []:
+PASS: Set difference should be [1,2,3].
+
+Given a Set with values [], and another Set with values [1,2,3]:
+PASS: Set difference should be [].
+
+Given a Set with values [1,2,3], and another Set with values [2,3,4]:
+PASS: Set difference should be [1].
+
+
+-- Running test case: Set.prototype.firstValue
+PASS: Set with values [] should have firstValue equal to undefined.
+PASS: Set with values [1,2,3] should have firstValue equal to 1.
+

Modified: releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/unit-tests/set-utilities.html (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/unit-tests/set-utilities.html	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/inspector/unit-tests/set-utilities.html	2019-02-18 16:17:10 UTC (rev 241714)
@@ -59,6 +59,85 @@
         }
     });
 
+    suite.addTestCase({
+        name: "Set.prototype.equals",
+        test() {
+            function testTrue(a, b, message) {
+                InspectorTest.expectThat((new Set(a)).equals(new Set(b)), message);
+            }
+
+            function testFalse(a, b, message) {
+                InspectorTest.expectFalse((new Set(a)).equals(new Set(b)), message);
+            }
+
+            const object1 = {a: 1};
+            const object2 = {b: 2};
+            const object3 = {c: 3};
+
+            testTrue([], [], "an empty set should be equal to another empty set.");
+            testTrue([1, "a", object1], [1, "a", object1], "a set should be equal to another set with the same values.");
+            testTrue([1, "a", object1], [object1, 1, "a"], "a set should be equal to another set with the same values in a different order.");
+            testFalse([1, "a", object1], [2, "b", object2], "a set should not be a equal to another set with different values.");
+            testFalse([1, 2, "a", "b", object1, object2], [1, 3, "a", "c", object1, object3], "a set should not be equal to another set with same and different values.");
+
+            return true;
+        }
+    });
+
+    suite.addTestCase({
+        name: "Set.prototype.difference",
+        test() {
+            function testDifference({aValues, bValues, expectedDifference}) {
+                let a = new Set(aValues);
+                let b = new Set(bValues);
+
+                InspectorTest.log(`Given a Set with values [${aValues}], and another Set with values [${bValues}]:`);
+
+                let difference = a.difference(b);
+                InspectorTest.expectThat(difference.equals(new Set(expectedDifference)), `Set difference should be [${expectedDifference}].`);
+                InspectorTest.log("");
+            }
+
+            testDifference({
+                aValues: [],
+                bValues: [],
+                expectedDifference: [],
+            });
+
+            testDifference({
+                aValues: [1, 2, 3],
+                bValues: [],
+                expectedDifference: [1, 2, 3],
+            });
+
+            testDifference({
+                aValues: [],
+                bValues: [1, 2, 3],
+                expectedDifference: [],
+            });
+
+            testDifference({
+                aValues: [1, 2, 3],
+                bValues: [2, 3, 4],
+                expectedDifference: [1],
+            });
+
+            return true;
+        }
+    });
+
+    suite.addTestCase({
+        name: "Set.prototype.firstValue",
+        test() {
+            function testFirstValue(values) {
+                InspectorTest.expectEqual(new Set(values).firstValue, values[0], `Set with values [${values}] should have firstValue equal to ${values[0]}.`);
+            }
+
+            testFirstValue([]);
+            testFirstValue([1, 2, 3]);
+        }
+    });
+
     suite.runTestCasesAndFinish();
 }
 </script>

Modified: releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/ChangeLog (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/ChangeLog	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/ChangeLog	2019-02-18 16:17:10 UTC (rev 241714)
@@ -1,3 +1,119 @@
+2019-02-17  Matt Baker  <mattba...@apple.com>
+
+        Web Inspector: Frontend performance is very slow reloading theverge.com - 50% of time in TreeOutline _indexOfTreeElement
+        https://bugs.webkit.org/show_bug.cgi?id=193605
+        <rdar://problem/47403986>
+
+        Reviewed by Devin Rousso.
+
+        SelectionController should track an unordered Set of represented objects
+        instead of an ordered set of indexes. This eliminates the costly and
+        error-prone updates needed to keep the selected indexes in sync as items
+        are added and removed from TreeOutline (and Table, to a far lesser extent).
+
+        The SelectionController interface is largely the same. Class and delegate
+        methods have been renamed to reflect the change from indexes to objects.
+        SelectionController tracks selected items in selection order. For the
+        operations that rely on objects being in insertion order, the controller
+        uses a comparator function provided at construction time.
+
+        * UserInterface/Base/IndexSet.js: Removed.
+        No longer used. SelectionController now uses a plain Set.
+
+        * UserInterface/Base/Utilities.js:
+        (value):
+        (get return):
+        Add utilities previously supplied by IndexSet and used by SelectionController.
+
+        * UserInterface/Controllers/SelectionController.js:
+        (WI.SelectionController):
+        (WI.SelectionController.prototype.get lastSelectedItem):
+        (WI.SelectionController.prototype.get selectedItems):
+        (WI.SelectionController.prototype.set allowsMultipleSelection):
+        (WI.SelectionController.prototype.hasSelectedItem):
+        (WI.SelectionController.prototype.selectItem):
+        (WI.SelectionController.prototype.deselectItem):
+        (WI.SelectionController.prototype.selectAll):
+        (WI.SelectionController.prototype.deselectAll):
+        (WI.SelectionController.prototype.removeSelectedItems):
+        (WI.SelectionController.prototype.reset):
+        (WI.SelectionController.prototype.didRemoveItems):
+        (WI.SelectionController.prototype.handleKeyDown):
+        (WI.SelectionController.prototype.handleItemMouseDown):
+        (WI.SelectionController.prototype._deselectAllAndSelect):
+        (WI.SelectionController.prototype._selectItemsFromArrowKey):
+        (WI.SelectionController.prototype._firstSelectableItem):
+        (WI.SelectionController.prototype._lastSelectableItem):
+        (WI.SelectionController.prototype._previousSelectableItem):
+        (WI.SelectionController.prototype._nextSelectableItem):
+        (WI.SelectionController.prototype._updateSelectedItems):
+        (WI.SelectionController.prototype._addRange):
+        (WI.SelectionController.prototype._deleteRange):
+        (WI.SelectionController.prototype.get numberOfItems): Deleted.
+        (WI.SelectionController.prototype.didInsertItem): Deleted.
+        (WI.SelectionController.prototype.handleItemMouseDown.normalizeRange): Deleted.
+        (WI.SelectionController.prototype._nextSelectableIndex): Deleted.
+        (WI.SelectionController.prototype._previousSelectableIndex): Deleted.
+
+        * UserInterface/Main.html:
+        * UserInterface/Test.html:
+        Remove IndexSet.
+
+        * UserInterface/Views/CookieStorageContentView.js:
+        (WI.CookieStorageContentView.prototype.tableIndexForRepresentedObject):
+        (WI.CookieStorageContentView.prototype.tableRepresentedObjectForIndex):
+
+        * UserInterface/Views/DOMTreeOutline.js:
+        (WI.DOMTreeOutline.prototype.objectForSelection):
+
+        * UserInterface/Views/NetworkTableContentView.js:
+        (WI.NetworkTableContentView.prototype.tableIndexForRepresentedObject):
+        (WI.NetworkTableContentView.prototype.tableRepresentedObjectForIndex):
+
+        * UserInterface/Views/Table.js:
+        (WI.Table):
+        (WI.Table.prototype.get selectedRow):
+        (WI.Table.prototype.get selectedRows):
+        (WI.Table.prototype.isRowSelected):
+        (WI.Table.prototype.selectRow):
+        (WI.Table.prototype.deselectRow):
+        (WI.Table.prototype.removeRow):
+        (WI.Table.prototype.removeSelectedRows):
+        (WI.Table.prototype.selectionControllerSelectionDidChange):
+        (WI.Table.prototype.selectionControllerFirstSelectableItem):
+        (WI.Table.prototype.selectionControllerLastSelectableItem):
+        (WI.Table.prototype.selectionControllerPreviousSelectableItem):
+        (WI.Table.prototype.selectionControllerNextSelectableItem):
+        (WI.Table.prototype._handleMouseDown):
+        (WI.Table.prototype._removeRows):
+        (WI.Table.prototype._indexForRepresentedObject):
+        (WI.Table.prototype._representedObjectForIndex):
+        (WI.Table.prototype.selectionControllerNumberOfItems): Deleted.
+        (WI.Table.prototype.selectionControllerNextSelectableIndex): Deleted.
+        (WI.Table.prototype.selectionControllerPreviousSelectableIndex): Deleted.
+        (WI.Table.prototype._toggleSelectedRowStyle): Deleted.
+
+        * UserInterface/Views/TreeOutline.js:
+        (WI.TreeOutline.compareSiblings):
+        (WI.TreeOutline):
+        (WI.TreeOutline.prototype.get selectedTreeElement):
+        (WI.TreeOutline.prototype.set selectedTreeElement):
+        (WI.TreeOutline.prototype.get selectedTreeElements):
+        (WI.TreeOutline.prototype.removeChildAtIndex):
+        (WI.TreeOutline.prototype.removeChildren):
+        (WI.TreeOutline.prototype._rememberTreeElement):
+        (WI.TreeOutline.prototype.getCachedTreeElement):
+        (WI.TreeOutline.prototype.selectionControllerSelectionDidChange):
+        (WI.TreeOutline.prototype.selectionControllerFirstSelectableItem):
+        (WI.TreeOutline.prototype.selectionControllerLastSelectableItem):
+        (WI.TreeOutline.prototype.selectionControllerPreviousSelectableItem):
+        (WI.TreeOutline.prototype.selectionControllerNextSelectableItem):
+        (WI.TreeOutline.prototype.objectForSelection):
+        (WI.TreeOutline._generateStyleRulesIfNeeded):
+        (WI.TreeOutline.prototype.selectionControllerNextSelectableIndex): Deleted.
+        (WI.TreeOutline.prototype.selectionControllerPreviousSelectableIndex): Deleted.
+        (WI.TreeOutline._generateStyleRulesIfNeeded._indexesForSubtree.numberOfElementsInSubtree): Deleted.
+
 2019-02-15  Joseph Pecoraro  <pecor...@apple.com>
 
         Web Inspector: Logging a native function to the console, such as `alert`, produces unhandled rejection

Deleted: releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Base/IndexSet.js (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Base/IndexSet.js	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Base/IndexSet.js	2019-02-18 16:17:10 UTC (rev 241714)
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2018 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WI.IndexSet = class IndexSet
-{
-    constructor(values)
-    {
-        console.assert(!values || Array.isArray(values));
-
-        this._indexes = [];
-
-        if (values) {
-            for (let value of values.slice().sort((a, b) => a - b)) {
-                if (value === this._indexes.lastValue)
-                    continue;
-                if (this._validateIndex(value))
-                    this._indexes.push(value);
-            }
-        }
-    }
-
-    // Public
-
-    get size() { return this._indexes.length; }
-
-    get firstIndex()
-    {
-        return this._indexes.length ? this._indexes[0] : NaN;
-    }
-
-    get lastIndex()
-    {
-        return this._indexes.length ? this._indexes.lastValue : NaN;
-    }
-
-    add(value)
-    {
-        if (!this._validateIndex(value))
-            return;
-
-        let index = this._indexes.lowerBound(value);
-        if (this._indexes[index] === value)
-            return;
-
-        this._indexes.insertAtIndex(value, index);
-    }
-
-    delete(value)
-    {
-        if (!this._validateIndex(value))
-            return false;
-
-        if (!this.size)
-            return false;
-
-        let index = this._indexes.lowerBound(value);
-        if (index === this._indexes.length)
-            return false;
-        this._indexes.splice(index, 1);
-        return true;
-    }
-
-    has(value)
-    {
-        if (!this.size)
-            return false;
-
-        let index = this._indexes.lowerBound(value);
-        return this._indexes[index] === value;
-    }
-
-    addRange(startIndex, count)
-    {
-        if (!this._validateIndex(startIndex))
-            return;
-
-        console.assert(count > 0);
-        if (count <= 0)
-            return;
-
-        if (count === 1) {
-            this.add(startIndex);
-            return;
-        }
-
-        let range = new Array(count);
-        for (let i = 0; i < count; ++i)
-            range[i] = startIndex + i;
-
-        if (!this.size || (this.firstIndex >= range[0] && this.lastIndex <= range.lastValue)) {
-            this._indexes = range;
-            return;
-        }
-
-        let start = this._indexes.lowerBound(startIndex);
-        let numberToDelete = this._indexes.upperBound(range.lastValue) - start;
-        this._indexes.splice(start, numberToDelete, ...range);
-    }
-
-    deleteRange(startIndex, count)
-    {
-        if (!this._validateIndex(startIndex))
-            return;
-
-        console.assert(count > 0);
-        if (count <= 0)
-            return;
-
-        if (!this.size)
-            return;
-
-        if (count === 1) {
-            this.delete(startIndex);
-            return;
-        }
-
-        let lastIndex = startIndex + count - 1;
-        if (this.firstIndex >= startIndex && this.lastIndex <= lastIndex) {
-            this.clear();
-            return;
-        }
-
-        let start = this._indexes.lowerBound(startIndex);
-        let numberToDelete = this._indexes.upperBound(lastIndex) - start;
-        this._indexes.splice(start, numberToDelete);
-    }
-
-    clear()
-    {
-        this._indexes = [];
-    }
-
-    copy()
-    {
-        let indexSet = new WI.IndexSet;
-        indexSet._indexes = this._indexes.slice();
-        return indexSet;
-    }
-
-    equals(indexSet)
-    {
-        console.assert(indexSet instanceof WI.IndexSet);
-        if (!(indexSet instanceof WI.IndexSet))
-            return false;
-
-        if (indexSet === this)
-            return true;
-
-        return Array.shallowEqual(this._indexes, indexSet._indexes);
-    }
-
-    difference(indexSet)
-    {
-        console.assert(indexSet instanceof WI.IndexSet);
-
-        if (indexSet === this)
-            return new WI.IndexSet;
-
-        let result = new WI.IndexSet;
-        result._indexes = this._indexes.filter((value) => !indexSet.has(value));
-        return result;
-    }
-
-    indexGreaterThan(value)
-    {
-        const following = true;
-        return this._indexClosestTo(value, following);
-    }
-
-    indexLessThan(value)
-    {
-        const following = false;
-        return this._indexClosestTo(value, following);
-    }
-
-    [Symbol.iterator]()
-    {
-        return this._indexes[Symbol.iterator]();
-    }
-
-    // Private
-
-    _indexClosestTo(value, following)
-    {
-        if (!this.size)
-            return NaN;
-
-        if (this.size === 1) {
-            if (following)
-                return this.firstIndex > value ? this.firstIndex : NaN;
-            return this.firstIndex < value ? this.firstIndex : NaN;
-        }
-
-        let offset = following ? 1 : -1;
-        let position = this._indexes.lowerBound(value + offset);
-
-        let closestIndex = this._indexes[position];
-        if (closestIndex === undefined)
-            return NaN;
-
-        if (value === closestIndex)
-            return NaN;
-
-        if (!following && closestIndex > value)
-            return NaN;
-        return closestIndex;
-    }
-
-    _validateIndex(value)
-    {
-        console.assert(Number.isInteger(value) && value >= 0, "Index must be a non-negative integer.");
-        return Number.isInteger(value) && value >= 0;
-    }
-};

Modified: releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Base/Utilities.js (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Base/Utilities.js	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Base/Utilities.js	2019-02-18 16:17:10 UTC (rev 241714)
@@ -118,6 +118,39 @@
     }
 });
 
+Object.defineProperty(Set.prototype, "equals",
+{
+    value(other)
+    {
+        return this.size === other.size && this.isSubsetOf(other);
+    }
+});
+
+Object.defineProperty(Set.prototype, "difference",
+{
+    value(other)
+    {
+        if (other === this)
+            return new Set;
+
+        let result = new Set;
+        for (let item of this) {
+            if (!other.has(item))
+                result.add(item);
+        }
+
+        return result;
+    }
+});
+
+Object.defineProperty(Set.prototype, "firstValue",
+{
+    get()
+    {
+        return this.values().next().value;
+    }
+});
+
 Object.defineProperty(Set.prototype, "intersects",
 {
     value(other)
@@ -1456,6 +1489,12 @@
 {
     value(value, comparator)
     {
+        function defaultComparator(a, b)
+        {
+            return a - b;
+        }
+        comparator = comparator || defaultComparator;
+
         var index = this.lowerBound(value, comparator);
         return index < this.length && comparator(value, this[index]) === 0 ? index : -1;
     }

Modified: releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js	2019-02-18 16:17:10 UTC (rev 241714)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2018, 2019 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -25,30 +25,34 @@
 
 WI.SelectionController = class SelectionController extends WI.Object
 {
-    constructor(delegate)
+    constructor(delegate, comparator)
     {
         super();
 
         console.assert(delegate);
+        console.assert(typeof comparator === "function");
+
         this._delegate = delegate;
+        this._comparator = comparator;
 
         this._allowsEmptySelection = true;
         this._allowsMultipleSelection = false;
-        this._lastSelectedIndex = NaN;
-        this._shiftAnchorIndex = NaN;
-        this._selectedIndexes = new WI.IndexSet;
+        this._lastSelectedItem = null;
+        this._shiftAnchorItem = null;
+        this._selectedItems = new Set;
         this._suppressSelectionDidChange = false;
 
-        console.assert(this._delegate.selectionControllerNumberOfItems, "SelectionController delegate must implement selectionControllerNumberOfItems.");
-        console.assert(this._delegate.selectionControllerNextSelectableIndex, "SelectionController delegate must implement selectionControllerNextSelectableIndex.");
-        console.assert(this._delegate.selectionControllerPreviousSelectableIndex, "SelectionController delegate must implement selectionControllerPreviousSelectableIndex.");
+        console.assert(this._delegate.selectionControllerFirstSelectableItem, "SelectionController delegate must implement selectionControllerFirstSelectableItem.");
+        console.assert(this._delegate.selectionControllerLastSelectableItem, "SelectionController delegate must implement selectionControllerLastSelectableItem.");
+        console.assert(this._delegate.selectionControllerNextSelectableItem, "SelectionController delegate must implement selectionControllerNextSelectableItem.");
+        console.assert(this._delegate.selectionControllerPreviousSelectableItem, "SelectionController delegate must implement selectionControllerPreviousSelectableItem.");
     }
 
     // Public
 
     get delegate() { return this._delegate; }
-    get lastSelectedItem() { return this._lastSelectedIndex; }
-    get selectedItems() { return this._selectedIndexes; }
+    get lastSelectedItem() { return this._lastSelectedItem; }
+    get selectedItems() { return this._selectedItems; }
 
     get allowsEmptySelection() { return this._allowsEmptySelection; }
     set allowsEmptySelection(flag) { this._allowsEmptySelection = flag; }
@@ -67,225 +71,147 @@
         if (this._allowsMultipleSelection)
             return;
 
-        if (this._selectedIndexes.size > 1) {
-            console.assert(this._lastSelectedIndex >= 0);
-            this._updateSelectedItems(new WI.IndexSet([this._lastSelectedIndex]));
-        }
+        if (this._selectedItems.size > 1)
+            this._updateSelectedItems(new Set([this._lastSelectedItem]));
     }
 
-    get numberOfItems()
+    hasSelectedItem(item)
     {
-        return this._delegate.selectionControllerNumberOfItems(this);
+        return this._selectedItems.has(item);
     }
 
-    hasSelectedItem(index)
+    selectItem(item, extendSelection = false)
     {
-        return this._selectedIndexes.has(index);
-    }
-
-    selectItem(index, extendSelection = false)
-    {
+        console.assert(item, "Invalid item for selection.");
         console.assert(!extendSelection || this._allowsMultipleSelection, "Cannot extend selection with multiple selection disabled.");
-        console.assert(index >= 0 && index < this.numberOfItems);
 
         if (!this._allowsMultipleSelection)
             extendSelection = false;
 
-        if (this.hasSelectedItem(index)) {
+        if (this.hasSelectedItem(item)) {
             if (!extendSelection)
-                this._deselectAllAndSelect(index);
+                this._deselectAllAndSelect(item);
             return;
         }
 
-        let newSelectedItems = extendSelection ? this._selectedIndexes.copy() : new WI.IndexSet;
-        newSelectedItems.add(index);
+        this._lastSelectedItem = item;
+        this._shiftAnchorItem = null;
 
-        this._shiftAnchorIndex = NaN;
-        this._lastSelectedIndex = index;
+        let newItems = new Set(extendSelection ? this._selectedItems : null);
+        newItems.add(item);
 
-        this._updateSelectedItems(newSelectedItems);
+        this._updateSelectedItems(newItems);
     }
 
-    deselectItem(index)
+    deselectItem(item)
     {
-        console.assert(index >= 0 && index < this.numberOfItems);
+        console.assert(item, "Invalid item for selection.");
 
-        if (!this.hasSelectedItem(index))
+        if (!this.hasSelectedItem(item))
             return;
 
-        if (!this._allowsEmptySelection && this._selectedIndexes.size === 1)
+        if (!this._allowsEmptySelection && this._selectedItems.size === 1)
             return;
 
-        let newSelectedItems = this._selectedIndexes.copy();
-        newSelectedItems.delete(index);
+        let newItems = new Set(this._selectedItems);
+        newItems.delete(item);
 
-        if (this._shiftAnchorIndex === index)
-            this._shiftAnchorIndex = NaN;
+        if (this._lastSelectedItem === item) {
+            this._lastSelectedItem = null;
 
-        if (this._lastSelectedIndex === index) {
-            this._lastSelectedIndex = NaN;
-            if (newSelectedItems.size) {
+            if (newItems.size) {
                 // Find selected item closest to deselected item.
-                let preceding = newSelectedItems.indexLessThan(index);
-                let following = newSelectedItems.indexGreaterThan(index);
+                let previous = item;
+                let next = item;
+                while (!this._lastSelectedItem && previous && next) {
+                    previous = this._previousSelectableItem(previous);
+                    if (this.hasSelectedItem(previous)) {
+                        this._lastSelectedItem = previous;
+                        break;
+                    }
 
-                if (isNaN(preceding))
-                    this._lastSelectedIndex = following;
-                else if (isNaN(following))
-                    this._lastSelectedIndex = preceding;
-                else {
-                    if ((following - index) < (index - preceding))
-                        this._lastSelectedIndex = following;
-                    else
-                        this._lastSelectedIndex = preceding;
+                    next = this._nextSelectableItem(next);
+                    if (this.hasSelectedItem(next)) {
+                        this._lastSelectedItem = next;
+                        break;
+                    }
                 }
             }
         }
 
-        this._updateSelectedItems(newSelectedItems);
+        if (this._shiftAnchorItem === item)
+            this._shiftAnchorItem = null;
+
+        this._updateSelectedItems(newItems);
     }
 
     selectAll()
     {
-        if (!this.numberOfItems || !this._allowsMultipleSelection)
+        if (!this._allowsMultipleSelection)
             return;
 
-        if (this._selectedIndexes.size === this.numberOfItems)
-            return;
+        this._lastSelectedItem = this._lastSelectableItem();
 
-        let newSelectedItems = new WI.IndexSet;
-        newSelectedItems.addRange(0, this.numberOfItems);
+        let newItems = new Set;
+        this._addRange(newItems, this._firstSelectableItem(), this._lastSelectedItem);
 
-        this._lastSelectedIndex = newSelectedItems.lastIndex;
-        if (isNaN(this._shiftAnchorIndex))
-            this._shiftAnchorIndex = this._lastSelectedIndex;
+        if (!this._shiftAnchorItem)
+            this._shiftAnchorItem = this._lastSelectedItem;
 
-        this._updateSelectedItems(newSelectedItems);
+        this._updateSelectedItems(newItems);
     }
 
     deselectAll()
     {
-        const index = NaN;
-        this._deselectAllAndSelect(index);
+        this._deselectAllAndSelect(null);
     }
 
     removeSelectedItems()
     {
-        let numberOfSelectedItems = this._selectedIndexes.size;
-        if (!numberOfSelectedItems)
+        if (!this._selectedItems.size)
             return;
 
+        let orderedSelection = Array.from(this._selectedItems).sort(this._comparator);
+
         // Try selecting the item following the selection.
-        let lastSelectedIndex = this._selectedIndexes.lastIndex;
-        let indexToSelect = this._nextSelectableIndex(lastSelectedIndex);
-        if (isNaN(indexToSelect)) {
+        let lastSelectedItem = orderedSelection.lastValue;
+        let itemToSelect = this._nextSelectableItem(lastSelectedItem);
+        if (!itemToSelect) {
             // If no item exists after the last item in the selection, try selecting
             // a deselected item (hole) within the selection.
-            let firstSelectedIndex = this._selectedIndexes.firstIndex;
-            if (lastSelectedIndex - firstSelectedIndex > numberOfSelectedItems) {
-                indexToSelect = this._nextSelectableIndex(firstSelectedIndex);
-                while (this._selectedIndexes.has(indexToSelect))
-                    indexToSelect = this._nextSelectableIndex(firstSelectedIndex);
-            } else {
+            itemToSelect = orderedSelection[0];
+            while (itemToSelect && this.hasSelectedItem(itemToSelect))
+                itemToSelect = this._nextSelectableItem(itemToSelect);
+
+            if (!itemToSelect || this.hasSelectedItem(itemToSelect)) {
                 // If the selection contains no holes, try selecting the item
                 // preceding the selection.
-                indexToSelect = firstSelectedIndex > 0 ? this._previousSelectableIndex(firstSelectedIndex) : NaN;
+                itemToSelect = this._previousSelectableItem(orderedSelection[0]);
             }
         }
 
-        this._deselectAllAndSelect(indexToSelect);
+        this._deselectAllAndSelect(itemToSelect);
     }
 
     reset()
     {
-        this._shiftAnchorIndex = NaN;
-        this._lastSelectedIndex = NaN;
-        this._selectedIndexes.clear();
+        this._lastSelectedItem = null;
+        this._shiftAnchorItem = null;
+        this._selectedItems.clear();
     }
 
-    didInsertItem(index)
+    didRemoveItems(items)
     {
-        let current = this._selectedIndexes.lastIndex;
-        while (current >= index) {
-            this._selectedIndexes.delete(current);
-            this._selectedIndexes.add(current + 1);
+        console.assert(items instanceof Set);
 
-            current = this._selectedIndexes.indexLessThan(current);
-        }
+        if (!items.size || !this._selectedItems.size)
+           return;
 
-        if (this._lastSelectedIndex >= index)
-            this._lastSelectedIndex += 1;
-        if (this._shiftAnchorIndex >= index)
-            this._shiftAnchorIndex += 1;
+        this._updateSelectedItems(this._selectedItems.difference(items));
     }
 
-    didRemoveItems(indexes)
-    {
-        if (!indexes)
-            return;
-
-        console.assert(indexes instanceof WI.IndexSet);
-
-        if (!indexes.size || !this._selectedIndexes.size)
-            return;
-
-        let firstRemovedIndex = indexes.firstIndex;
-        if (this._selectedIndexes.lastIndex < firstRemovedIndex)
-            return;
-
-        let newSelectedIndexes = new WI.IndexSet;
-
-        let lastRemovedIndex = indexes.lastIndex;
-        if (this._selectedIndexes.firstIndex < lastRemovedIndex) {
-            let removedCount = 0;
-            let removedIndex = firstRemovedIndex;
-
-            this._suppressSelectionDidChange = true;
-
-            // Adjust the selected indexes that are in the range between the
-            // first and last removed index (inclusive).
-            for (let current = this._selectedIndexes.firstIndex; current < lastRemovedIndex; current = this._selectedIndexes.indexGreaterThan(current)) {
-                if (this.hasSelectedItem(current)) {
-                    this.deselectItem(current);
-                    removedCount++;
-                    continue;
-                }
-
-                while (removedIndex < current) {
-                    removedCount++;
-                    removedIndex = indexes.indexGreaterThan(removedIndex);
-                }
-
-                let newIndex = current - removedCount;
-                newSelectedIndexes.add(newIndex);
-
-                if (this._lastSelectedIndex === current)
-                    this._lastSelectedIndex = newIndex;
-                if (this._shiftAnchorIndex === current)
-                    this._shiftAnchorIndex = newIndex;
-            }
-
-            this._suppressSelectionDidChange = false;
-        }
-
-        let removedCount = indexes.size;
-        let current = lastRemovedIndex;
-        while (current = this._selectedIndexes.indexGreaterThan(current))
-            newSelectedIndexes.add(current - removedCount);
-
-        if (this._lastSelectedIndex > lastRemovedIndex)
-            this._lastSelectedIndex -= removedCount;
-        if (this._shiftAnchorIndex > lastRemovedIndex)
-            this._shiftAnchorIndex -= removedCount;
-
-        this._selectedIndexes = newSelectedIndexes;
-    }
-
     handleKeyDown(event)
     {
-        if (!this.numberOfItems)
-            return false;
-
         if (event.key === "a" && event.commandOrControlKey) {
             this.selectAll();
             return true;
@@ -305,8 +231,10 @@
         return false;
     }
 
-    handleItemMouseDown(index, event)
+    handleItemMouseDown(item, event)
     {
+        console.assert(item, "Invalid item for selection.");
+
         if (event.button !== 0 || event.ctrlKey)
             return;
 
@@ -313,33 +241,34 @@
         // Command (macOS) or Control (Windows) key takes precedence over shift
         // whether or not multiple selection is enabled, so handle it first.
         if (event.commandOrControlKey) {
-            if (this.hasSelectedItem(index))
-                this.deselectItem(index);
+            if (this.hasSelectedItem(item))
+                this.deselectItem(item);
             else
-                this.selectItem(index, this._allowsMultipleSelection);
+                this.selectItem(item, this._allowsMultipleSelection);
             return;
         }
 
         let shiftExtendSelection = this._allowsMultipleSelection && event.shiftKey;
         if (!shiftExtendSelection) {
-            this.selectItem(index);
+            this.selectItem(item);
             return;
         }
 
-        let newSelectedItems = this._selectedIndexes.copy();
+        let newItems = new Set(this._selectedItems);
 
         // Shift-clicking when nothing is selected should cause the first item
         // through the clicked item to be selected.
-        if (!newSelectedItems.size) {
-            this._shiftAnchorIndex = 0;
-            this._lastSelectedIndex = index;
-            newSelectedItems.addRange(0, index + 1);
-            this._updateSelectedItems(newSelectedItems);
+        if (!newItems.size) {
+            this._lastSelectedItem = item;
+            this._shiftAnchorItem = this._firstSelectableItem();
+
+            this._addRange(newItems, this._shiftAnchorItem, this._lastSelectedItem);
+            this._updateSelectedItems(newItems);
             return;
         }
 
-        if (isNaN(this._shiftAnchorIndex))
-            this._shiftAnchorIndex = this._lastSelectedIndex;
+        if (!this._shiftAnchorItem)
+            this._shiftAnchorItem = this._lastSelectedItem;
 
         // Shift-clicking will add to or delete from the current selection, or
         // pivot the selection around the anchor (a delete followed by an add).
@@ -347,58 +276,57 @@
         // that are necessary, but it is simpler to throw out the previous shift-
         // selected range and add the new range between the anchor and clicked item.
 
-        function normalizeRange(startIndex, endIndex) {
-            return startIndex > endIndex ? [endIndex, startIndex] : [startIndex, endIndex];
-        }
+        let sortItemPair = (a, b) => {
+            return [a, b].sort(this._comparator);
+        };
 
-        if (this._shiftAnchorIndex !== this._lastSelectedIndex) {
-            let [startIndex, endIndex] = normalizeRange(this._shiftAnchorIndex, this._lastSelectedIndex);
-            newSelectedItems.deleteRange(startIndex, endIndex - startIndex + 1);
+        if (this._shiftAnchorItem !== this._lastSelectedItem) {
+            let [startItem, endItem] = sortItemPair(this._shiftAnchorItem, this._lastSelectedItem);
+            this._deleteRange(newItems, startItem, endItem);
         }
 
-        let [startIndex, endIndex] = normalizeRange(this._shiftAnchorIndex, index);
-        newSelectedItems.addRange(startIndex, endIndex - startIndex + 1);
+        let [startItem, endItem] = sortItemPair(this._shiftAnchorItem, item);
+        this._addRange(newItems, startItem, endItem);
 
-        this._lastSelectedIndex = index;
+        this._lastSelectedItem = item;
 
-        this._updateSelectedItems(newSelectedItems);
+        this._updateSelectedItems(newItems);
     }
 
     // Private
 
-    _deselectAllAndSelect(index)
+    _deselectAllAndSelect(item)
     {
-        if (!this._selectedIndexes.size)
+        if (!this._selectedItems.size)
             return;
 
-        if (this._selectedIndexes.size === 1 && this._selectedIndexes.firstIndex === index)
+        if (this._selectedItems.size === 1 && this.hasSelectedItem(item))
             return;
 
-        this._shiftAnchorIndex = NaN;
-        this._lastSelectedIndex = index;
+        this._lastSelectedItem = item;
+        this._shiftAnchorItem = null;
 
-        let newSelectedItems = new WI.IndexSet;
-        if (!isNaN(index))
-            newSelectedItems.add(index);
+        let newItems = new Set;
+        if (item)
+            newItems.add(item);
 
-        this._updateSelectedItems(newSelectedItems);
+        this._updateSelectedItems(newItems);
     }
 
     _selectItemsFromArrowKey(goingUp, shiftKey)
     {
-        if (!this._selectedIndexes.size) {
-            let index = goingUp ? this.numberOfItems - 1 : 0;
-            this.selectItem(index);
+        if (!this._selectedItems.size) {
+            this.selectItem(goingUp ? this._lastSelectableItem() : this._firstSelectableItem());
             return;
         }
 
-        let index = goingUp ? this._previousSelectableIndex(this._lastSelectedIndex) : this._nextSelectableIndex(this._lastSelectedIndex);
-        if (isNaN(index))
+        let item = goingUp ? this._previousSelectableItem(this._lastSelectedItem) : this._nextSelectableItem(this._lastSelectedItem);
+        if (!item)
             return;
 
         let extendSelection = shiftKey && this._allowsMultipleSelection;
-        if (!extendSelection || !this.hasSelectedItem(index)) {
-            this.selectItem(index, extendSelection);
+        if (!extendSelection || !this.hasSelectedItem(item)) {
+            this.selectItem(item, extendSelection);
             return;
         }
 
@@ -405,9 +333,9 @@
         // Since the item in the direction of movement is selected, we are either
         // extending the selection into the item, or deselecting. Determine which
         // by checking whether the item opposite the anchor item is selected.
-        let priorIndex = goingUp ? this._nextSelectableIndex(this._lastSelectedIndex) : this._previousSelectableIndex(this._lastSelectedIndex);
-        if (!this.hasSelectedItem(priorIndex)) {
-            this.deselectItem(this._lastSelectedIndex);
+        let priorItem = goingUp ? this._nextSelectableItem(this._lastSelectedItem) : this._previousSelectableItem(this._lastSelectedItem);
+        if (!priorItem || !this.hasSelectedItem(priorItem)) {
+            this.deselectItem(this._lastSelectedItem);
             return;
         }
 
@@ -414,40 +342,74 @@
         // The selection is being extended into the item; make it the new
         // anchor item then continue searching in the direction of movement
         // for an unselected item to select.
-        while (!isNaN(index)) {
-            if (!this.hasSelectedItem(index)) {
-                this.selectItem(index, extendSelection);
+        while (item) {
+            if (!this.hasSelectedItem(item)) {
+                this.selectItem(item, extendSelection);
                 break;
             }
 
-            this._lastSelectedIndex = index;
-            index = goingUp ? this._previousSelectableIndex(index) : this._nextSelectableIndex(index);
+            this._lastSelectedItem = item;
+            item = goingUp ? this._previousSelectableItem(item) : this._nextSelectableItem(item);
         }
     }
 
-    _nextSelectableIndex(index)
+    _firstSelectableItem()
     {
-        return this._delegate.selectionControllerNextSelectableIndex(this, index);
+        return this._delegate.selectionControllerFirstSelectableItem(this);
     }
 
-    _previousSelectableIndex(index)
+    _lastSelectableItem()
     {
-        return this._delegate.selectionControllerPreviousSelectableIndex(this, index);
+        return this._delegate.selectionControllerLastSelectableItem(this);
     }
 
-    _updateSelectedItems(indexes)
+    _previousSelectableItem(item)
     {
-        if (this._selectedIndexes.equals(indexes))
-            return;
+        return this._delegate.selectionControllerPreviousSelectableItem(this, item);
+    }
 
-        let oldSelectedIndexes = this._selectedIndexes.copy();
-        this._selectedIndexes = indexes;
+    _nextSelectableItem(item)
+    {
+        return this._delegate.selectionControllerNextSelectableItem(this, item);
+    }
 
+    _updateSelectedItems(items)
+    {
+        let oldSelectedItems = this._selectedItems;
+        this._selectedItems = items;
+
         if (this._suppressSelectionDidChange || !this._delegate.selectionControllerSelectionDidChange)
             return;
 
-        let deselectedItems = oldSelectedIndexes.difference(indexes);
-        let selectedItems = indexes.difference(oldSelectedIndexes);
-        this._delegate.selectionControllerSelectionDidChange(this, deselectedItems, selectedItems);
+        let deselectedItems = oldSelectedItems.difference(items);
+        let selectedItems = items.difference(oldSelectedItems);
+        if (deselectedItems.size || selectedItems.size)
+            this._delegate.selectionControllerSelectionDidChange(this, deselectedItems, selectedItems);
     }
+
+    _addRange(items, firstItem, lastItem)
+    {
+        let current = firstItem;
+        while (current) {
+            items.add(current);
+            if (current === lastItem)
+                break;
+            current = this._nextSelectableItem(current);
+        }
+
+        console.assert(!lastItem || items.has(lastItem), "End of range could not be reached.");
+    }
+
+    _deleteRange(items, firstItem, lastItem)
+    {
+        let current = firstItem;
+        while (current) {
+            items.delete(current);
+            if (current === lastItem)
+                break;
+            current = this._nextSelectableItem(current);
+        }
+
+        console.assert(!lastItem || !items.has(lastItem), "End of range could not be reached.");
+    }
 };

Modified: releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Main.html (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Main.html	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Main.html	2019-02-18 16:17:10 UTC (rev 241714)
@@ -275,7 +275,6 @@
     <script src=""
     <script src=""
     <script src=""
-    <script src=""
     <script src=""
     <script src=""
     <script src=""

Modified: releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Test.html (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Test.html	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Test.html	2019-02-18 16:17:10 UTC (rev 241714)
@@ -38,7 +38,6 @@
     <script src=""
     <script src=""
     <script src=""
-    <script src=""
     <script src=""
     <script src=""
     <script src=""

Modified: releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/CookieStorageContentView.js (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/CookieStorageContentView.js	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/CookieStorageContentView.js	2019-02-18 16:17:10 UTC (rev 241714)
@@ -75,6 +75,19 @@
 
     // Table dataSource
 
+    tableIndexForRepresentedObject(table, object)
+    {
+        let index = this._cookies.indexOf(object);
+        console.assert(index >= 0);
+        return index;
+    }
+
+    tableRepresentedObjectForIndex(table, index)
+    {
+        console.assert(index >= 0 && index < this._cookies.length);
+        return this._cookies[index];
+    }
+
     tableNumberOfRows(table)
     {
         return this._cookies.length;

Modified: releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js	2019-02-18 16:17:10 UTC (rev 241714)
@@ -319,6 +319,23 @@
         return true;
     }
 
+    // Protected
+
+    objectForSelection(treeElement)
+    {
+        if (treeElement instanceof WI.DOMTreeElement && treeElement.isCloseTag()) {
+            // SelectionController requires every selectable item to be unique.
+            // The DOMTreeElement for a close tag has the same represented object
+            // as it's parent (the open tag). Return a proxy object associated
+            // with the tree element for the close tag so it can be selected.
+            if (!treeElement.__closeTagProxyObject)
+                treeElement.__closeTagProxyObject = {__proxyObjectTreeElement: treeElement};
+            return treeElement.__closeTagProxyObject;
+        }
+
+        return super.objectForSelection(treeElement);
+    }
+
     // Private
 
     _revealAndSelectNode(node, omitFocus)

Modified: releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js	2019-02-18 16:17:10 UTC (rev 241714)
@@ -327,6 +327,17 @@
 
     // Table dataSource
 
+    tableIndexForRepresentedObject(table, object)
+    {
+        return this._filteredEntries.indexOf(object);
+    }
+
+    tableRepresentedObjectForIndex(table, index)
+    {
+        console.assert(index >=0 && index < this._filteredEntries.length);
+        return this._filteredEntries[index];
+    }
+
     tableNumberOfRows(table)
     {
         return this._filteredEntries.length;

Modified: releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/Table.js (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/Table.js	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/Table.js	2019-02-18 16:17:10 UTC (rev 241714)
@@ -87,7 +87,7 @@
         this._columnWidths = null; // Calculated in _resizeColumnsAndFiller.
         this._fillerHeight = 0; // Calculated in _resizeColumnsAndFiller.
 
-        this._selectionController = new WI.SelectionController(this);
+        this._selectionController = new WI.SelectionController(this, (a, b) => this._indexForRepresentedObject(a) - this._indexForRepresentedObject(b));
 
         this._resizers = [];
         this._currentResizer = null;
@@ -113,6 +113,9 @@
         this._visibleRowIndexStart = NaN;
         this._visibleRowIndexEnd = NaN;
 
+        console.assert(this._dataSource.tableIndexForRepresentedObject, "Table data source must implement tableIndexForRepresentedObject.");
+        console.assert(this._dataSource.tableRepresentedObjectForIndex, "Table data source must implement tableRepresentedObjectForIndex.");
+
         console.assert(this._delegate.tablePopulateCell, "Table delegate must implement tablePopulateCell.");
     }
 
@@ -125,12 +128,17 @@
 
     get selectedRow()
     {
-        return this._selectionController.lastSelectedItem;
+        let item = this._selectionController.lastSelectedItem;
+        let index = this._indexForRepresentedObject(item);
+        return index >= 0 ? index : NaN;
     }
 
     get selectedRows()
     {
-        return Array.from(this._selectionController.selectedItems);
+        let rowIndexes = [];
+        for (let item of this._selectionController.selectedItems)
+            rowIndexes.push(this._indexForRepresentedObject(item));
+        return rowIndexes;
     }
 
     get scrollContainer() { return this._scrollContainerElement; }
@@ -236,7 +244,7 @@
 
     isRowSelected(rowIndex)
     {
-        return this._selectionController.hasSelectedItem(rowIndex);
+        return this._selectionController.hasSelectedItem(this._representedObjectForIndex(rowIndex));
     }
 
     reloadData()
@@ -313,12 +321,12 @@
 
     selectRow(rowIndex, extendSelection = false)
     {
-        this._selectionController.selectItem(rowIndex, extendSelection);
+        this._selectionController.selectItem(this._representedObjectForIndex(rowIndex), extendSelection);
     }
 
     deselectRow(rowIndex)
     {
-        this._selectionController.deselectItem(rowIndex);
+        this._selectionController.deselectItem(this._representedObjectForIndex(rowIndex));
     }
 
     selectAll()
@@ -338,20 +346,20 @@
         if (this.isRowSelected(rowIndex))
             this.deselectRow(rowIndex);
 
-        let rowIndexes = new WI.IndexSet([rowIndex]);
-        this._removeRows(rowIndexes);
+        this._removeRows(new Set([this._representedObjectForIndex(rowIndex)]));
     }
 
     removeSelectedRows()
     {
+        let selectedItems = this._selectionController.selectedItems;
+        if (!selectedItems.size)
+            return;
+
         // Change the selection before removing rows. This matches the behavior
         // of macOS Finder (in list and column modes) when removing selected items.
-        let oldSelectedItems = this._selectionController.selectedItems.copy();
-
         this._selectionController.removeSelectedItems();
 
-        if (!oldSelectedItems.equals(this._selectionController.selectedItems))
-            this._removeRows(oldSelectedItems);
+        this._removeRows(selectedItems);
     }
 
     revealRow(rowIndex)
@@ -597,13 +605,22 @@
 
     selectionControllerSelectionDidChange(controller, deselectedItems, selectedItems)
     {
-        if (deselectedItems.size)
-            this._toggleSelectedRowStyle(deselectedItems, false);
-        if (selectedItems.size)
-            this._toggleSelectedRowStyle(selectedItems, true);
+        for (let item of deselectedItems) {
+            let rowIndex = this._indexForRepresentedObject(item);
+            let row = this._cachedRows.get(rowIndex);
+            if (row)
+                row.classList.toggle("selected", false);
+        }
 
+        for (let item of selectedItems) {
+            let rowIndex = this._indexForRepresentedObject(item);
+            let row = this._cachedRows.get(rowIndex);
+            if (row)
+                row.classList.toggle("selected", true);
+        }
+
         if (selectedItems.size === 1) {
-            let rowIndex = selectedItems.firstIndex;
+            let rowIndex = this._indexForRepresentedObject(selectedItems.firstValue);
             if (!this._isRowVisible(rowIndex))
                 this.revealRow(rowIndex);
         }
@@ -612,25 +629,32 @@
             this._delegate.tableSelectionDidChange(this);
     }
 
-    selectionControllerNumberOfItems(controller)
+    selectionControllerFirstSelectableItem(controller)
     {
-        return this.numberOfRows;
+        return this._representedObjectForIndex(0);
     }
 
-    selectionControllerNextSelectableIndex(controller, index)
+    selectionControllerLastSelectableItem(controller)
     {
-        if (index >= this.numberOfRows - 1)
-            return NaN;
-        return index + 1;
+        return this._representedObjectForIndex(this.numberOfRows - 1);
     }
 
-    selectionControllerPreviousSelectableIndex(controller, index)
+    selectionControllerPreviousSelectableItem(controller, item)
     {
-        if (index <= 0)
-            return NaN;
-        return index - 1;
+        let index = this._indexForRepresentedObject(item);
+        console.assert(index >= 0 && index < this.numberOfRows);
+
+        return index > 0 ? this._representedObjectForIndex(index - 1) : null;
     }
 
+    selectionControllerNextSelectableItem(controller, item)
+    {
+        let index = this._indexForRepresentedObject(item);
+        console.assert(index >= 0 && index < this.numberOfRows);
+
+        return index < this.numberOfRows - 1 ? this._representedObjectForIndex(index + 1) : null;
+    }
+
     // Resizer delegate
 
     resizerDragStarted(resizer)
@@ -1295,7 +1319,7 @@
                 return;
         }
 
-        this._selectionController.handleItemMouseDown(rowIndex, event);
+        this._selectionController.handleItemMouseDown(this._representedObjectForIndex(rowIndex), event);
     }
 
     _handleContextMenu(event)
@@ -1374,7 +1398,7 @@
         }
     }
 
-    _removeRows(rowIndexes)
+    _removeRows(representedObjects)
     {
         let removed = 0;
 
@@ -1387,8 +1411,15 @@
             }
         };
 
-        for (let index = rowIndexes.firstIndex; index <= rowIndexes.lastIndex; ++index) {
-            if (rowIndexes.has(index)) {
+        let rowIndexes = [];
+        for (let object of representedObjects)
+            rowIndexes.push(this._indexForRepresentedObject(object));
+
+        rowIndexes.sort((a, b) => a - b);
+
+        let lastIndex = rowIndexes.lastValue;
+        for (let index = rowIndexes[0]; index <= lastIndex; ++index) {
+            if (rowIndexes.binaryIndexOf(index) >= 0) {
                 let row = this._cachedRows.get(index);
                 if (row) {
                     this._cachedRows.delete(index);
@@ -1405,28 +1436,29 @@
         if (!removed)
             return;
 
-        for (let index = rowIndexes.lastIndex + 1; index < this._cachedNumberOfRows; ++index)
+        for (let index = lastIndex + 1; index < this._cachedNumberOfRows; ++index)
             adjustRowAtIndex(index);
 
         this._cachedNumberOfRows -= removed;
         console.assert(this._cachedNumberOfRows >= 0);
 
-        this._selectionController.didRemoveItems(rowIndexes);
+        this._selectionController.didRemoveItems(representedObjects);
 
         if (this._delegate.tableDidRemoveRows) {
-            this._delegate.tableDidRemoveRows(this, Array.from(rowIndexes));
+            this._delegate.tableDidRemoveRows(this, rowIndexes);
             console.assert(this._cachedNumberOfRows === this._dataSource.tableNumberOfRows(this), "Table data source should update after removing rows.");
         }
     }
 
-    _toggleSelectedRowStyle(rowIndexes, flag)
+    _indexForRepresentedObject(object)
     {
-        for (let index of rowIndexes) {
-            let row = this._cachedRows.get(index);
-            if (row)
-                row.classList.toggle("selected", flag);
-        }
+        return this.dataSource.tableIndexForRepresentedObject(this, object);
     }
+
+    _representedObjectForIndex(index)
+    {
+        return this.dataSource.tableRepresentedObjectForIndex(this, index);
+    }
 };
 
 WI.Table.SortOrder = {

Modified: releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js (241713 => 241714)


--- releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js	2019-02-18 16:17:00 UTC (rev 241713)
+++ releases/WebKitGTK/webkit-2.24/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js	2019-02-18 16:17:10 UTC (rev 241714)
@@ -56,8 +56,55 @@
 
         this._cachedNumberOfDescendents = 0;
         this._previousSelectedTreeElement = null;
-        this._selectionController = new WI.SelectionController(this);
 
+        let comparator = (a, b) => {
+            function getLevel(treeElement) {
+                let level = 0;
+                while (treeElement = treeElement.parent)
+                    level++;
+                return level;
+            }
+
+            function compareSiblings(s, t) {
+                return s.parent.children.indexOf(s) - s.parent.children.indexOf(t);
+            }
+
+            // Translate represented objects to TreeElements, which have the
+            // hierarchical information needed to perform the comparison.
+            a = this.getCachedTreeElement(a);
+            b = this.getCachedTreeElement(b);
+            if (!a || !b)
+                return 0;
+
+            if (a.parent === b.parent)
+                return compareSiblings(a, b);
+
+            let aLevel = getLevel(a);
+            let bLevel = getLevel(b);
+            while (aLevel > bLevel) {
+                if (a.parent === b)
+                    return 1;
+                a = a.parent;
+                aLevel--;
+            }
+            while (bLevel > aLevel) {
+                if (b.parent === a)
+                    return -1;
+                b = b.parent;
+                bLevel--;
+            }
+
+            while (a.parent !== b.parent) {
+                a = a.parent;
+                b = b.parent;
+            }
+
+            console.assert(a.parent === b.parent, "Missing common ancestor for TreeElements.", a, b);
+            return compareSiblings(a, b);
+        };
+
+        this._selectionController = new WI.SelectionController(this, comparator);
+
         this._itemWasSelectedByUser = false;
         this._processingSelectionChange = false;
         this._suppressNextSelectionDidChangeEvent = false;
@@ -103,16 +150,14 @@
 
     get selectedTreeElement()
     {
-        let selectedIndex = this._selectionController.lastSelectedItem;
-        return this._treeElementAtIndex(selectedIndex) || null;
+        return this.getCachedTreeElement(this._selectionController.lastSelectedItem);
     }
 
     set selectedTreeElement(treeElement)
     {
-        if (treeElement) {
-            let index = this._indexOfTreeElement(treeElement);
-            this._selectionController.selectItem(index);
-        } else
+        if (treeElement)
+            this._selectionController.selectItem(this.objectForSelection(treeElement));
+        else
             this._selectionController.deselectAll();
     }
 
@@ -120,8 +165,8 @@
     {
         if (this.allowsMultipleSelection) {
             let treeElements = [];
-            for (let index of this._selectionController.selectedItems)
-                treeElements.push(this._treeElementAtIndex(index));
+            for (let representedObject of this._selectionController.selectedItems)
+                treeElements.push(this.getCachedTreeElement(representedObject));
             return treeElements;
         }
 
@@ -323,13 +368,10 @@
                 parent.select(true, false);
         }
 
-        let removedIndexes = null;
-
         let treeOutline = child.treeOutline;
         if (treeOutline) {
             treeOutline._forgetTreeElement(child);
             treeOutline._forgetChildrenRecursive(child);
-            removedIndexes = treeOutline._indexesForSubtree(child);
         }
 
         if (child.previousSibling)
@@ -345,10 +387,8 @@
         child.nextSibling = null;
         child.previousSibling = null;
 
-        if (treeOutline) {
-            treeOutline._selectionController.didRemoveItems(removedIndexes);
+        if (treeOutline)
             treeOutline.dispatchEventToListeners(WI.TreeOutline.Event.ElementRemoved, {element: child});
-        }
     }
 
     removeChild(child, suppressOnDeselect, suppressSelectSibling)
@@ -383,8 +423,6 @@
                 treeOutline._forgetChildrenRecursive(child);
             }
 
-            let removedIndexes = treeOutline._indexesForSubtree(child);
-
             child._detach();
             child.treeOutline = null;
             child.parent = null;
@@ -393,10 +431,8 @@
 
             this.children.shift();
 
-            if (treeOutline) {
-                treeOutline._selectionController.didRemoveItems(removedIndexes);
+            if (treeOutline)
                 treeOutline.dispatchEventToListeners(WI.TreeOutline.Event.ElementRemoved, {element: child});
-            }
         }
     }
 
@@ -413,12 +449,6 @@
         // add the element
         elements.push(element);
         this._cachedNumberOfDescendents++;
-
-        let index = this._indexOfTreeElement(element);
-        if (index >= 0) {
-            console.assert(!element.selected, "TreeElement should not be selected before being inserted.");
-            this._selectionController.didInsertItem(index);
-        }
     }
 
     _forgetTreeElement(element)
@@ -447,6 +477,13 @@
         if (!representedObject)
             return null;
 
+        // SelectionController requires every selectable object to be unique.
+        // A TreeOutline subclass where multiple TreeElements may be associated
+        // with one represented object can override objectForSelection, and return
+        // a proxy object that is associated with a single TreeElement.
+        if (representedObject.__proxyObjectTreeElement)
+            return representedObject.__proxyObjectTreeElement;
+
         if (representedObject.__treeElementIdentifier) {
             // If this representedObject has a tree element identifier, and it is a known TreeElement
             // in our tree we can just return that tree element.
@@ -806,25 +843,27 @@
     {
         this._processingSelectionChange = true;
 
-        for (let index of deselectedItems) {
-            let treeElement = this._treeElementAtIndex(index);
-            console.assert(treeElement, "Missing TreeElement for deselected index " + index);
-            if (treeElement) {
-                if (treeElement.listItemElement)
-                    treeElement.listItemElement.classList.remove("selected");
-                treeElement.deselect();
-            }
+        for (let representedObject of deselectedItems) {
+            let treeElement = this.getCachedTreeElement(representedObject);
+            if (!treeElement)
+                continue;
+
+            if (treeElement.listItemElement)
+                treeElement.listItemElement.classList.remove("selected");
+
+            treeElement.deselect();
         }
 
-        for (let index of selectedItems) {
-            let treeElement = this._treeElementAtIndex(index);
-            console.assert(treeElement, "Missing TreeElement for selected index " + index);
-            if (treeElement) {
-                if (treeElement.listItemElement)
-                    treeElement.listItemElement.classList.add("selected");
-                const omitFocus = true;
-                treeElement.select(omitFocus);
-            }
+        for (let representedObject of selectedItems) {
+            let treeElement = this.getCachedTreeElement(representedObject);
+            if (!treeElement)
+                continue;
+
+            if (treeElement.listItemElement)
+                treeElement.listItemElement.classList.add("selected");
+
+            const omitFocus = true;
+            treeElement.select(omitFocus);
         }
 
         let selectedTreeElement = this.selectedTreeElement;
@@ -843,44 +882,71 @@
         this._processingSelectionChange = false;
     }
 
-    selectionControllerNextSelectableIndex(controller, index)
+    selectionControllerFirstSelectableItem(controller)
     {
-        let treeElement = this._treeElementAtIndex(index);
+        let firstChild = this.children[0];
+        if (firstChild.selectable)
+            return firstChild.representedObject;
+        return this.selectionControllerNextSelectableItem(controller, firstChild.representedObject);
+    }
+
+    selectionControllerLastSelectableItem(controller)
+    {
+        let treeElement = this.children.lastValue;
+        while (treeElement.expanded && treeElement.children.length)
+            treeElement = treeElement.children.lastValue;
+
+        let item = this.objectForSelection(treeElement);
+        if (treeElement.selectable)
+            return item;
+        return this.selectionControllerPreviousSelectableItem(controller, item);
+    }
+
+    selectionControllerPreviousSelectableItem(controller, item)
+    {
+        let treeElement = this.getCachedTreeElement(item);
+        console.assert(treeElement, "Missing TreeElement for representedObject.", item);
         if (!treeElement)
-            return NaN;
+            return null;
 
         const skipUnrevealed = true;
         const stayWithin = null;
         const dontPopulate = true;
 
-        while (treeElement = treeElement.traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate)) {
+        while (treeElement = treeElement.traversePreviousTreeElement(skipUnrevealed, stayWithin, dontPopulate)) {
             if (treeElement.selectable)
-                return this._indexOfTreeElement(treeElement);
+                return this.objectForSelection(treeElement);
         }
 
-        return NaN;
+        return null;
     }
 
-    selectionControllerPreviousSelectableIndex(controller, index)
+    selectionControllerNextSelectableItem(controller, item)
     {
-        let treeElement = this._treeElementAtIndex(index);
+        let treeElement = this.getCachedTreeElement(item);
+        console.assert(treeElement, "Missing TreeElement for representedObject.", item);
         if (!treeElement)
-            return NaN;
+            return null;
 
         const skipUnrevealed = true;
         const stayWithin = null;
         const dontPopulate = true;
 
-        while (treeElement = treeElement.traversePreviousTreeElement(skipUnrevealed, stayWithin, dontPopulate)) {
+        while (treeElement = treeElement.traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate)) {
             if (treeElement.selectable)
-                return this._indexOfTreeElement(treeElement);
+                return this.objectForSelection(treeElement);
         }
 
-        return NaN;
+        return null;
     }
 
     // Protected
 
+    objectForSelection(treeElement)
+    {
+        return treeElement.representedObject;
+    }
+
     selectTreeElementInternal(treeElement, suppressNotification = false, selectedByUser = false)
     {
         if (this._processingSelectionChange)
@@ -1022,54 +1088,11 @@
             return;
         }
 
-        let index = this._indexOfTreeElement(treeElement);
-        if (isNaN(index))
-            return;
-
         this._itemWasSelectedByUser = true;
-        this._selectionController.handleItemMouseDown(index, event);
+        this._selectionController.handleItemMouseDown(this.objectForSelection(treeElement), event);
         this._itemWasSelectedByUser = false;
     }
 
-    _indexOfTreeElement(treeElement)
-    {
-        const skipUnrevealed = false;
-        const stayWithin = null;
-        const dontPopulate = true;
-
-        let index = 0;
-        let current = this.children[0];
-        while (current) {
-            if (treeElement === current)
-                return index;
-
-            current = current.traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate);
-            ++index;
-        }
-
-        console.assert(false, "Unable to get index for tree element.", treeElement);
-        return NaN;
-    }
-
-    _treeElementAtIndex(index)
-    {
-        const skipUnrevealed = false;
-        const stayWithin = null;
-        const dontPopulate = true;
-
-        let current = 0;
-        let treeElement = this.children[0];
-        while (treeElement) {
-            if (current === index)
-                return treeElement;
-
-            treeElement = treeElement.traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate);
-            ++current;
-        }
-
-        return null;
-    }
-
     _dispatchSelectionDidChangeEvent()
     {
         let selectedByUser = this._itemWasSelectedByUser;
@@ -1082,34 +1105,6 @@
 
         this.dispatchEventToListeners(WI.TreeOutline.Event.SelectionDidChange, {selectedByUser});
     }
-
-    _indexesForSubtree(treeElement)
-    {
-        let treeOutline = treeElement.treeOutline;
-        if (!treeOutline)
-            return null;
-
-        function numberOfElementsInSubtree(treeElement) {
-            let elements = treeElement.root ? Array.from(treeElement.children) : [treeElement];
-            let count = 0;
-            while (elements.length) {
-                let child = elements.pop();
-                if (child.hidden)
-                    continue;
-
-                count++;
-                elements = elements.concat(child.children);
-            }
-            return count;
-        }
-
-        let firstChild = treeElement.root ? treeElement.children[0] : treeElement;
-        let startIndex = treeOutline._indexOfTreeElement(firstChild);
-        let count = numberOfElementsInSubtree(treeElement);
-        let indexes = new WI.IndexSet;
-        indexes.addRange(startIndex, count);
-        return indexes;
-    }
 };
 
 WI.TreeOutline._styleElement = null;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to