Web Inspector: support multiple selection/deletion of cookie records
authormattbaker@apple.com <mattbaker@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 2 Nov 2018 19:39:01 +0000 (19:39 +0000)
committermattbaker@apple.com <mattbaker@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 2 Nov 2018 19:39:01 +0000 (19:39 +0000)
https://bugs.webkit.org/show_bug.cgi?id=66381
<rdar://problem/19281525>

Reviewed by Devin Rousso.

* Localizations/en.lproj/localizedStrings.js:

* UserInterface/Views/CookieStorageContentView.js:
(WI.CookieStorageContentView):
(WI.CookieStorageContentView.prototype.get scrollableElements):
(WI.CookieStorageContentView.prototype.tableNumberOfRows):
(WI.CookieStorageContentView.prototype.tableSortChanged):
(WI.CookieStorageContentView.prototype.tableCellContextMenuClicked):
(WI.CookieStorageContentView.prototype.tableDidRemoveRows):
(WI.CookieStorageContentView.prototype.tablePopulateCell):
(WI.CookieStorageContentView.prototype.initialLayout):
(WI.CookieStorageContentView.prototype._generateSortComparator):
(WI.CookieStorageContentView.prototype._refreshButtonClicked):
(WI.CookieStorageContentView.prototype._reloadCookies):
(WI.CookieStorageContentView.prototype._updateSort):
(WI.CookieStorageContentView.prototype._handleTableKeyDown):
(WI.CookieStorageContentView.prototype.update): Deleted.
(WI.CookieStorageContentView.prototype._rebuildTable): Deleted.
(WI.CookieStorageContentView.prototype._sortDataGrid.localeCompare): Deleted.
(WI.CookieStorageContentView.prototype._sortDataGrid.numberCompare): Deleted.
(WI.CookieStorageContentView.prototype._sortDataGrid.expiresCompare): Deleted.
(WI.CookieStorageContentView.prototype._sortDataGrid): Deleted.
(WI.CookieStorageContentView.prototype._deleteCallback): Deleted.
Replace DataGrid with Table. The content view serves as the table
delegate and data source, and handles delete and backspace key events
to allow deleting the selected cookies. Cookies may also be deleted from
the table context menu and a new button in the navigation bar.

* UserInterface/Views/Table.js:
(WI.Table.prototype.isRowSelected):
(WI.Table.prototype.selectRow):
(WI.Table.prototype.deselectRow):
(WI.Table.prototype.removeRow):
(WI.Table.prototype._getOrCreateRow):
(WI.Table.prototype._handleMouseDown):
(WI.Table.prototype._removeRows):
(WI.Table.prototype._isRowSelected): Deleted.
Make `isSelectedRow` public. It is more convenient and efficient than
calling `Table.prototype.selectedRows.includes(rowIndex)`.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237746 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
Source/WebInspectorUI/UserInterface/Views/CookieStorageContentView.js
Source/WebInspectorUI/UserInterface/Views/Table.js

index 78f02a6..b944ecc 100644 (file)
@@ -1,3 +1,51 @@
+2018-11-02  Matt Baker  <mattbaker@apple.com>
+
+        Web Inspector: support multiple selection/deletion of cookie records
+        https://bugs.webkit.org/show_bug.cgi?id=66381
+        <rdar://problem/19281525>
+
+        Reviewed by Devin Rousso.
+
+        * Localizations/en.lproj/localizedStrings.js:
+
+        * UserInterface/Views/CookieStorageContentView.js:
+        (WI.CookieStorageContentView):
+        (WI.CookieStorageContentView.prototype.get scrollableElements):
+        (WI.CookieStorageContentView.prototype.tableNumberOfRows):
+        (WI.CookieStorageContentView.prototype.tableSortChanged):
+        (WI.CookieStorageContentView.prototype.tableCellContextMenuClicked):
+        (WI.CookieStorageContentView.prototype.tableDidRemoveRows):
+        (WI.CookieStorageContentView.prototype.tablePopulateCell):
+        (WI.CookieStorageContentView.prototype.initialLayout):
+        (WI.CookieStorageContentView.prototype._generateSortComparator):
+        (WI.CookieStorageContentView.prototype._refreshButtonClicked):
+        (WI.CookieStorageContentView.prototype._reloadCookies):
+        (WI.CookieStorageContentView.prototype._updateSort):
+        (WI.CookieStorageContentView.prototype._handleTableKeyDown):
+        (WI.CookieStorageContentView.prototype.update): Deleted.
+        (WI.CookieStorageContentView.prototype._rebuildTable): Deleted.
+        (WI.CookieStorageContentView.prototype._sortDataGrid.localeCompare): Deleted.
+        (WI.CookieStorageContentView.prototype._sortDataGrid.numberCompare): Deleted.
+        (WI.CookieStorageContentView.prototype._sortDataGrid.expiresCompare): Deleted.
+        (WI.CookieStorageContentView.prototype._sortDataGrid): Deleted.
+        (WI.CookieStorageContentView.prototype._deleteCallback): Deleted.
+        Replace DataGrid with Table. The content view serves as the table
+        delegate and data source, and handles delete and backspace key events
+        to allow deleting the selected cookies. Cookies may also be deleted from
+        the table context menu and a new button in the navigation bar.
+
+        * UserInterface/Views/Table.js:
+        (WI.Table.prototype.isRowSelected):
+        (WI.Table.prototype.selectRow):
+        (WI.Table.prototype.deselectRow):
+        (WI.Table.prototype.removeRow):
+        (WI.Table.prototype._getOrCreateRow):
+        (WI.Table.prototype._handleMouseDown):
+        (WI.Table.prototype._removeRows):
+        (WI.Table.prototype._isRowSelected): Deleted.
+        Make `isSelectedRow` public. It is more convenient and efficient than
+        calling `Table.prototype.selectedRows.includes(rowIndex)`.
+
 2018-11-01  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: View: introduce a didLayoutSubtree
index 4db8c16..6df6b4e 100644 (file)
@@ -375,7 +375,6 @@ localizedStrings["Expand All"] = "Expand All";
 localizedStrings["Expand columns"] = "Expand columns";
 localizedStrings["Expanded"] = "Expanded";
 localizedStrings["Experimental"] = "Experimental";
-localizedStrings["Expires"] = "Expires";
 localizedStrings["Export"] = "Export";
 localizedStrings["Export HAR"] = "Export HAR";
 localizedStrings["Export Result"] = "Export Result";
@@ -441,7 +440,6 @@ localizedStrings["Grouping Method"] = "Grouping Method";
 localizedStrings["HAR Export (%s)"] = "HAR Export (%s)";
 localizedStrings["HTML"] = "HTML";
 localizedStrings["HTML Attributes"] = "HTML Attributes";
-localizedStrings["HTTP"] = "HTTP";
 localizedStrings["Headers"] = "Headers";
 localizedStrings["Headers:"] = "Headers:";
 localizedStrings["Heading Level"] = "Heading Level";
@@ -746,7 +744,6 @@ localizedStrings["Reveal in Resources Tab"] = "Reveal in Resources Tab";
 localizedStrings["Role"] = "Role";
 localizedStrings["Run %d"] = "Run %d";
 localizedStrings["Running the ā€œ%sā€œ audit"] = "Running the ā€œ%sā€œ audit";
-localizedStrings["Same-Site"] = "Same-Site";
 localizedStrings["Samples"] = "Samples";
 localizedStrings["Save File"] = "Save File";
 localizedStrings["Save Selected"] = "Save Selected";
index 17ae869..d91601f 100644 (file)
@@ -31,10 +31,12 @@ WI.CookieStorageContentView = class CookieStorageContentView extends WI.ContentV
 
         this.element.classList.add("cookie-storage");
 
+        this._cookies = [];
+        this._sortComparator = null;
+        this._table = null;
+
         this._refreshButtonNavigationItem = new WI.ButtonNavigationItem("cookie-storage-refresh", WI.UIString("Refresh"), "Images/ReloadFull.svg", 13, 13);
         this._refreshButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._refreshButtonClicked, this);
-
-        this.update();
     }
 
     // Public
@@ -44,16 +46,6 @@ WI.CookieStorageContentView = class CookieStorageContentView extends WI.ContentV
         return [this._refreshButtonNavigationItem];
     }
 
-    update()
-    {
-        PageAgent.getCookies().then((payload) => {
-            this._cookies = this._filterCookies(payload.cookies);
-            this._rebuildTable();
-        }).catch((error) => {
-            console.error("Could not fetch cookies: ", error);
-        });
-    }
-
     saveToCookie(cookie)
     {
         cookie.type = WI.ContentViewCookieType.CookieStorage;
@@ -62,97 +54,196 @@ WI.CookieStorageContentView = class CookieStorageContentView extends WI.ContentV
 
     get scrollableElements()
     {
-        if (!this._dataGrid)
+        if (!this._table)
             return [];
-        return [this._dataGrid.scrollContainer];
+        return [this._table.scrollContainer];
     }
 
-    // Private
+    // Table dataSource
 
-    _rebuildTable()
-    {
-        // FIXME <https://webkit.org/b/151400>: If there are no cookies, add placeholder explanatory text.
-        if (!this._dataGrid) {
-            var columns = {name: {}, value: {}, domain: {}, path: {}, expires: {}, size: {}, http: {}, secure: {}, sameSite: {}};
-
-            columns.name.title = WI.UIString("Name");
-            columns.name.sortable = true;
-            columns.name.width = "24%";
-            columns.name.locked = true;
-
-            columns.value.title = WI.UIString("Value");
-            columns.value.sortable = true;
-            columns.value.width = "34%";
-            columns.value.locked = true;
-
-            columns.domain.title = WI.UIString("Domain");
-            columns.domain.sortable = true;
-            columns.domain.width = "6%";
-
-            columns.path.title = WI.UIString("Path");
-            columns.path.sortable = true;
-            columns.path.width = "6%";
-
-            columns.expires.title = WI.UIString("Expires");
-            columns.expires.sortable = true;
-            columns.expires.width = "6%";
-
-            columns.size.title = WI.UIString("Size");
-            columns.size.aligned = "right";
-            columns.size.sortable = true;
-            columns.size.width = "6%";
-
-            columns.http.title = WI.UIString("HTTP");
-            columns.http.aligned = "centered";
-            columns.http.sortable = true;
-            columns.http.width = "6%";
-
-            columns.secure.title = WI.UIString("Secure");
-            columns.secure.aligned = "centered";
-            columns.secure.sortable = true;
-            columns.secure.width = "6%";
-
-            columns.sameSite.title = WI.UIString("Same-Site");
-            columns.sameSite.sortable = true;
-            columns.sameSite.width = "6%";
-
-            this._dataGrid = new WI.DataGrid(columns, null, this._deleteCallback.bind(this));
-            this._dataGrid.columnChooserEnabled = true;
-            this._dataGrid.addEventListener(WI.DataGrid.Event.SortChanged, this._sortDataGrid, this);
-            this._dataGrid.sortColumnIdentifier = "name";
-            this._dataGrid.createSettings("cookie-storage-content-view");
-
-            this.addSubview(this._dataGrid);
-            this._dataGrid.updateLayout();
-        }
+    tableNumberOfRows(table)
+    {
+        return this._cookies.length;
+    }
 
-        console.assert(this._dataGrid);
-        this._dataGrid.removeChildren();
-
-        for (let cookie of this._cookies) {
-            const checkmark = "\u2713";
-            var data = {
-                name: cookie.name,
-                value: cookie.value,
-                domain: cookie.domain || "",
-                path: cookie.path || "",
-                expires: "",
-                size: Number.bytesToString(cookie.size),
-                http: cookie.httpOnly ? checkmark : "",
-                secure: cookie.secure ? checkmark : "",
-                sameSite: cookie.sameSite && cookie.sameSite !== WI.Cookie.SameSiteType.None ? WI.Cookie.displayNameForSameSiteType(cookie.sameSite) : "",
-            };
+    tableSortChanged(table)
+    {
+        this._generateSortComparator();
+
+        if (!this._sortComparator)
+            return;
+
+        this._updateSort();
+        this._table.reloadData();
+    }
+
+    // Table delegate
 
-            if (cookie.type !== WI.CookieType.Request)
-                data["expires"] = cookie.session ? WI.UIString("Session") : new Date(cookie.expires).toLocaleString();
+    tableCellContextMenuClicked(table, cell, column, rowIndex, event)
+    {
+        let contextMenu = WI.ContextMenu.createFromEvent(event);
+
+        contextMenu.appendSeparator();
+        contextMenu.appendItem(WI.UIString("Delete"), () => {
+            if (table.isRowSelected(rowIndex))
+                table.removeSelectedRows();
+            else
+                table.removeRow(rowIndex);
+        });
+        contextMenu.appendSeparator();
+    }
+
+    tableDidRemoveRows(table, rowIndexes)
+    {
+        if (!rowIndexes.length)
+            return;
 
-            var node = new WI.DataGridNode(data);
-            node.cookie = cookie;
+        for (let i = rowIndexes.length - 1; i >= 0; --i) {
+            let rowIndex = rowIndexes[i];
+            let cookie = this._cookies[rowIndex];
+            console.assert(cookie, "Missing cookie for row " + rowIndex);
+            if (!cookie)
+                continue;
 
-            this._dataGrid.appendChild(node);
+            this._cookies.splice(rowIndex, 1);
+
+            // FIXME: <https://bugs.webkit.org/b/189533> add a WI.Cookie.url property
+            // once we switch over to using model objects instead of raw payload data.
+            let cookieURL = (cookie.secure ? "https://" : "http://") + cookie.domain + cookie.path;
+            PageAgent.deleteCookie(cookie.name, cookieURL);
         }
     }
 
+    tablePopulateCell(table, cell, column, rowIndex)
+    {
+        let cookie = this._cookies[rowIndex];
+
+        const checkmark = "\u2713";
+
+        switch (column.identifier) {
+        case "name":
+            cell.textContent = cookie.name;
+            break;
+        case "value":
+            cell.textContent = cookie.value;
+            break;
+        case "domain":
+            cell.textContent = cookie.domain || emDash;
+            break;
+        case "path":
+            cell.textContent = cookie.path || emDash;
+            break;
+        case "expires":
+            cell.textContent = cookie.expires ? new Date(cookie.expires).toLocaleString() : WI.UIString("Session");
+            break;
+        case "size":
+            cell.textContent = Number.bytesToString(cookie.size);
+            break;
+        case "secure":
+            cell.textContent = cookie.secure ? checkmark : zeroWidthSpace;
+            break;
+        case "httpOnly":
+            cell.textContent = cookie.httpOnly ? checkmark : zeroWidthSpace;
+            break;
+        case "sameSite":
+            cell.textContent = cookie.sameSite === WI.Cookie.SameSiteType.None ? emDash : WI.Cookie.displayNameForSameSiteType(cookie.sameSite);
+            break;
+        }
+
+        return cell;
+    }
+
+    // Protected
+
+    initialLayout()
+    {
+        super.initialLayout();
+
+        this._table = new WI.Table("cookies-table", this, this, 20);
+        this._table.allowsMultipleSelection = true;
+
+        this._nameColumn = new WI.TableColumn("name", WI.UIString("Name"), {
+            minWidth: 70,
+            maxWidth: 300,
+            initialWidth: 200,
+            resizeType: WI.TableColumn.ResizeType.Locked,
+        });
+
+        this._valueColumn = new WI.TableColumn("value", WI.UIString("Value"), {
+            minWidth: 100,
+            maxWidth: 600,
+            initialWidth: 200,
+            hideable: false,
+        });
+
+        this._domainColumn = new WI.TableColumn("domain", WI.unlocalizedString("Domain"), {
+            minWidth: 100,
+            maxWidth: 200,
+            initialWidth: 120,
+        });
+
+        this._pathColumn = new WI.TableColumn("path", WI.unlocalizedString("Path"), {
+            minWidth: 50,
+            maxWidth: 300,
+            initialWidth: 100,
+        });
+
+        this._expiresColumn = new WI.TableColumn("expires", WI.unlocalizedString("Expires"), {
+            minWidth: 100,
+            maxWidth: 200,
+            initialWidth: 150,
+        });
+
+        this._sizeColumn = new WI.TableColumn("size", WI.unlocalizedString("Size"), {
+            minWidth: 50,
+            maxWidth: 80,
+            initialWidth: 65,
+            align: "right",
+        });
+
+        this._secureColumn = new WI.TableColumn("secure", WI.unlocalizedString("Secure"), {
+            minWidth: 70,
+            maxWidth: 70,
+            align: "center",
+        });
+
+        this._httpOnlyColumn = new WI.TableColumn("httpOnly", WI.unlocalizedString("HttpOnly"), {
+            minWidth: 80,
+            maxWidth: 80,
+            align: "center",
+        });
+
+        this._sameSiteColumn = new WI.TableColumn("sameSite", WI.unlocalizedString("SameSite"), {
+            minWidth: 40,
+            maxWidth: 80,
+            initialWidth: 70,
+            align: "center",
+        });
+
+        this._table.addColumn(this._nameColumn);
+        this._table.addColumn(this._valueColumn);
+        this._table.addColumn(this._domainColumn);
+        this._table.addColumn(this._pathColumn);
+        this._table.addColumn(this._expiresColumn);
+        this._table.addColumn(this._sizeColumn);
+        this._table.addColumn(this._secureColumn);
+        this._table.addColumn(this._httpOnlyColumn);
+        this._table.addColumn(this._sameSiteColumn);
+
+        if (!this._table.sortColumnIdentifier) {
+            this._table.sortOrder = WI.Table.SortOrder.Ascending;
+            this._table.sortColumnIdentifier = "name";
+         }
+
+        this.addSubview(this._table);
+
+        this._table.element.addEventListener("keydown", this._handleTableKeyDown.bind(this));
+
+        this._reloadCookies();
+    }
+
+    // Private
+
     _filterCookies(cookies)
     {
         let resourceMatchesStorageDomain = (resource) => {
@@ -176,62 +267,78 @@ WI.CookieStorageContentView = class CookieStorageContentView extends WI.ContentV
         return cookiesForDomain;
     }
 
-    _sortDataGrid()
+    _generateSortComparator()
     {
-        function localeCompare(field, nodeA, nodeB)
-        {
-            return (nodeA.data[field] + "").extendedLocaleCompare(nodeB.data[field] + "");
-        }
-
-        function numberCompare(field, nodeA, nodeB)
-        {
-            return nodeA.cookie[field] - nodeB.cookie[field];
+        let sortColumnIdentifier = this._table.sortColumnIdentifier;
+        if (!sortColumnIdentifier) {
+            this._sortComparator = null;
+            return;
         }
 
-        function expiresCompare(nodeA, nodeB)
-        {
-            if (nodeA.cookie.session !== nodeB.cookie.session)
-                return nodeA.cookie.session ? -1 : 1;
-
-            if (nodeA.cookie.session)
-                return 0;
+        let comparator = null;
+
+        switch (sortColumnIdentifier) {
+        case "name":
+        case "value":
+        case "domain":
+        case "path":
+        case "sameSite":
+            comparator = (a, b) => (a[sortColumnIdentifier] || "").extendedLocaleCompare(b[sortColumnIdentifier] || "");
+            break;
+
+        case "size":
+        case "httpOnly":
+        case "secure":
+            comparator = (a, b) => a[sortColumnIdentifier] - b[sortColumnIdentifier];
+            break;
+
+        case "expires":
+            comparator = (a, b) => {
+                if (!a.expires)
+                    return 1;
+                if (!b.expires)
+                    return -1;
+                return a.expires - b.expires;
+            };
+            break;
 
-            return nodeA.cookie.expires - nodeB.cookie.expires;
+        default:
+            console.assert("Unexpected sort column", sortColumnIdentifier);
+            return;
         }
 
-        var comparator;
-        switch (this._dataGrid.sortColumnIdentifier) {
-            case "value": comparator = localeCompare.bind(this, "value"); break;
-            case "domain": comparator = localeCompare.bind(this, "domain"); break;
-            case "path": comparator = localeCompare.bind(this, "path"); break;
-            case "expires": comparator = expiresCompare; break;
-            case "size": comparator = numberCompare.bind(this, "size"); break;
-            case "http": comparator = localeCompare.bind(this, "http"); break;
-            case "secure": comparator = localeCompare.bind(this, "secure"); break;
-            case "sameSite": comparator = localeCompare.bind(this, "sameSite"); break;
-            case "name":
-            default: comparator = localeCompare.bind(this, "name"); break;
-        }
+        let reverseFactor = this._table.sortOrder === WI.Table.SortOrder.Ascending ? 1 : -1;
+        this._sortComparator = (a, b) => reverseFactor * comparator(a, b);
+    }
+
+    _refreshButtonClicked(event)
+    {
+        this._reloadCookies();
+    }
 
-        console.assert(comparator);
-        this._dataGrid.sortNodes(comparator);
+    _reloadCookies()
+    {
+        PageAgent.getCookies().then((payload) => {
+            this._cookies = this._filterCookies(payload.cookies);
+            this._updateSort();
+            this._table.reloadData();
+        }).catch((error) => {
+            console.error("Could not fetch cookies: ", error);
+        });
     }
 
-    _deleteCallback(node)
+    _updateSort()
     {
-        if (!node || !node.cookie)
+        if (!this._sortComparator)
             return;
 
-        var cookie = node.cookie;
-        var cookieURL = (cookie.secure ? "https://" : "http://") + cookie.domain + cookie.path;
-        PageAgent.deleteCookie(cookie.name, cookieURL);
-
-        this.update();
+        this._cookies.sort(this._sortComparator);
     }
 
-    _refreshButtonClicked(event)
+    _handleTableKeyDown(event)
     {
-        this.update();
+        if (event.keyCode === WI.KeyboardShortcut.Key.Backspace.keyCode || event.keyCode === WI.KeyboardShortcut.Key.Delete.keyCode)
+            this._table.removeSelectedRows();
     }
 };
 
index 51208d8..cdca16e 100644 (file)
@@ -235,6 +235,11 @@ WI.Table = class Table extends WI.View
             this._notifySelectionDidChange();
     }
 
+    isRowSelected(rowIndex)
+    {
+        return this._selectedRows.has(rowIndex);
+    }
+
     resize()
     {
         this._cachedWidth = NaN;
@@ -321,7 +326,7 @@ WI.Table = class Table extends WI.View
         console.assert(!extendSelection || this._allowsMultipleSelection, "Cannot extend selection with multiple selection disabled.");
         console.assert(rowIndex >= 0 && rowIndex < this.numberOfRows);
 
-        if (this._isRowSelected(rowIndex)) {
+        if (this.isRowSelected(rowIndex)) {
             if (!extendSelection)
                 this._deselectAllAndSelect(rowIndex);
             return;
@@ -346,7 +351,7 @@ WI.Table = class Table extends WI.View
     {
         console.assert(rowIndex >= 0 && rowIndex < this.numberOfRows);
 
-        if (!this._isRowSelected(rowIndex))
+        if (!this.isRowSelected(rowIndex))
             return;
 
         let oldSelectedRow = this._cachedRows.get(rowIndex);
@@ -390,7 +395,7 @@ WI.Table = class Table extends WI.View
     {
         console.assert(rowIndex >= 0 && rowIndex < this.numberOfRows);
 
-        if (this._isRowSelected(rowIndex))
+        if (this.isRowSelected(rowIndex))
             this.deselectRow(rowIndex);
 
         this._removeRows(new WI.IndexSet([rowIndex]));
@@ -797,7 +802,7 @@ WI.Table = class Table extends WI.View
         let row = document.createElement("li");
         row.__index = rowIndex;
         row.__widthGeneration = 0;
-        if (this._isRowSelected(rowIndex))
+        if (this.isRowSelected(rowIndex))
             row.classList.add("selected");
 
         this._cachedRows.set(rowIndex, row);
@@ -1321,7 +1326,7 @@ WI.Table = class Table extends WI.View
         let column = this._visibleColumns[columnIndex];
         let rowIndex = row.__index;
 
-        if (this._isRowSelected(rowIndex)) {
+        if (this.isRowSelected(rowIndex)) {
             if (event.metaKey)
                 this.deselectRow(rowIndex)
             else
@@ -1452,7 +1457,7 @@ WI.Table = class Table extends WI.View
                 this._cachedRows.set(newIndex, row);
             }
 
-            if (this._isRowSelected(index)) {
+            if (this.isRowSelected(index)) {
                 this._selectedRows.delete(index);
                 this._selectedRows.add(newIndex);
                 if (this._selectedRowIndex === index)
@@ -1493,11 +1498,6 @@ WI.Table = class Table extends WI.View
         }
     }
 
-    _isRowSelected(rowIndex)
-    {
-        return this._selectedRows.has(rowIndex);
-    }
-
     _notifySelectionDidChange()
     {
         if (this._suppressNextSelectionDidChange) {