Web Inspector: Create general model object Collection class
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 27 Oct 2016 22:25:24 +0000 (22:25 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 27 Oct 2016 22:25:24 +0000 (22:25 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163995

Patch by Devin Rousso <dcrousso+webkit@gmail.com> on 2016-10-27
Reviewed by Joseph Pecoraro.

Source/WebInspectorUI:

* UserInterface/Models/Collection.js: Added.
(WebInspector.Collection):
(WebInspector.Collection.prototype.get items):
(WebInspector.Collection.prototype.get typeVerifier):
(WebInspector.Collection.prototype.add):
(WebInspector.Collection.prototype.remove):
(WebInspector.Collection.prototype.clear):
(WebInspector.Collection.prototype.toArray):
(WebInspector.Collection.prototype.toJSON):
(WebInspector.Collection.prototype.itemAdded):
(WebInspector.Collection.prototype.itemRemoved):
(WebInspector.Collection.prototype.itemsCleared):
Class that holds multiple model objects.  It can be limited to a specific type by supplying
a "typeVerifier", which is a function that accepts a single argument (the model object) and
returns true/false depending on if that argument matches the "type" of the collection.

* UserInterface/Main.html:
* UserInterface/Test.html:
* UserInterface/Models/Frame.js:
* UserInterface/Views/CookieStorageContentView.js:
* UserInterface/Views/DebuggerSidebarPanel.js:
* UserInterface/Views/FrameTreeElement.js:
* UserInterface/Views/OpenResourceDialog.js:
Add support for WebInspector.Collection.

* UserInterface/Models/ResourceCollection.js:
(WebInspector.ResourceCollection):
(WebInspector.ResourceCollection.verifierForType):
(WebInspector.ResourceCollection.prototype.resourceCollectionForType):
(WebInspector.ResourceCollection.prototype.clear):
(WebInspector.ResourceCollection.prototype.itemAdded):
(WebInspector.ResourceCollection.prototype.itemRemoved):
(WebInspector.ResourceCollection.prototype.itemsCleared):
(WebInspector.ResourceCollection.prototype._associateWithResource):
(WebInspector.ResourceCollection.prototype._disassociateWithResource):
(WebInspector.ResourceCollection.prototype._resourceURLDidChange):
(WebInspector.ResourceCollection.prototype._resourceTypeDidChange):
(WebInspector.ResourceCollection.prototype.get resources): Deleted.
(WebInspector.ResourceCollection.prototype.resourcesWithType): Deleted.
(WebInspector.ResourceCollection.prototype.addResource): Deleted.
(WebInspector.ResourceCollection.prototype.removeResource): Deleted.
(WebInspector.ResourceCollection.prototype.removeAllResources): Deleted.
Now a subclass of WebInspector.Collection.  Retrieving WebInspector.Resource objects by type
and URL is still supported, but requesting by type now returns another instance of
WebInspector.ResourceCollection that is configured to only accept the requested type.

LayoutTests:

* inspector/debugger/resources/log-pause-location.js:
(TestPage.registerInitializer.window.findScript):
Change name of getter to support WebInspector.Collection.

* inspector/unit-tests/collection-expected.txt: Added.
* inspector/unit-tests/collection.html: Added.
* inspector/unit-tests/resource-collection-expected.txt: Added.
* inspector/unit-tests/resource-collection.html: Added.
Created tests for WebInspector.Collection and WebInspector.ResourceCollection.

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

16 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/debugger/resources/log-pause-location.js
LayoutTests/inspector/unit-tests/collection-expected.txt [new file with mode: 0644]
LayoutTests/inspector/unit-tests/collection.html [new file with mode: 0644]
LayoutTests/inspector/unit-tests/resource-collection-expected.txt [new file with mode: 0644]
LayoutTests/inspector/unit-tests/resource-collection.html [new file with mode: 0644]
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/Main.html
Source/WebInspectorUI/UserInterface/Models/Collection.js [new file with mode: 0644]
Source/WebInspectorUI/UserInterface/Models/Frame.js
Source/WebInspectorUI/UserInterface/Models/ResourceCollection.js
Source/WebInspectorUI/UserInterface/Test.html
Source/WebInspectorUI/UserInterface/Views/CookieStorageContentView.js
Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js
Source/WebInspectorUI/UserInterface/Views/FrameTreeElement.js
Source/WebInspectorUI/UserInterface/Views/OpenResourceDialog.js

index 347413e..8237f1f 100644 (file)
@@ -1,3 +1,20 @@
+2016-10-27  Devin Rousso  <dcrousso+webkit@gmail.com>
+
+        Web Inspector: Create general model object Collection class
+        https://bugs.webkit.org/show_bug.cgi?id=163995
+
+        Reviewed by Joseph Pecoraro.
+
+        * inspector/debugger/resources/log-pause-location.js:
+        (TestPage.registerInitializer.window.findScript):
+        Change name of getter to support WebInspector.Collection.
+
+        * inspector/unit-tests/collection-expected.txt: Added.
+        * inspector/unit-tests/collection.html: Added.
+        * inspector/unit-tests/resource-collection-expected.txt: Added.
+        * inspector/unit-tests/resource-collection.html: Added.
+        Created tests for WebInspector.Collection and WebInspector.ResourceCollection.
+
 2016-10-27  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: Worker should recover if Inspector is closed and never sent Worker.initialized command
index 99ab63c..4bdba0d 100644 (file)
@@ -16,7 +16,7 @@ TestPage.registerInitializer(() => {
     }
 
     window.findScript = function(regex) {
-        let resources = WebInspector.frameResourceManager.mainFrame.resources;
+        let resources = WebInspector.frameResourceManager.mainFrame.resourceCollection.items;
         for (let resource of resources) {
             if (regex.test(resource.url))
                 return resource.scripts[0];
diff --git a/LayoutTests/inspector/unit-tests/collection-expected.txt b/LayoutTests/inspector/unit-tests/collection-expected.txt
new file mode 100644 (file)
index 0000000..2e4c517
--- /dev/null
@@ -0,0 +1,21 @@
+Testing all methods of Collection.
+
+
+== Running test suite: Collection
+-- Running test case: WebInspector.Collection.prototype.add
+["one","two"]
+["one","two",3]
+
+-- Running test case: WebInspector.Collection.prototype.remove
+["one","two"]
+["two"]
+
+-- Running test case: WebInspector.Collection.prototype.clear
+["one","two",3]
+[]
+
+-- Running test case: WebInspector.Collection.prototype.get typeVerifier
+["one","two"]
+["one","two"]
+PASS: typeVerifier is the given function.
+
diff --git a/LayoutTests/inspector/unit-tests/collection.html b/LayoutTests/inspector/unit-tests/collection.html
new file mode 100644 (file)
index 0000000..3225a47
--- /dev/null
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script>
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("Collection");
+
+    suite.addTestCase({
+        name: "WebInspector.Collection.prototype.add",
+        test(resolve, reject) {
+            let collection = new WebInspector.Collection;
+            collection.add("one");
+            collection.add("two");
+
+            InspectorTest.log(collection);
+
+            collection.add(3);
+
+            InspectorTest.log(collection);
+
+            resolve();
+        }
+    });
+
+    suite.addTestCase({
+        name: "WebInspector.Collection.prototype.remove",
+        test(resolve, reject) {
+            let item = "one";
+
+            let collection = new WebInspector.Collection;
+            collection.add(item);
+            collection.add("two");
+
+            InspectorTest.log(collection);
+
+            collection.remove(item);
+
+            InspectorTest.log(collection);
+
+            resolve();
+        }
+    });
+
+    suite.addTestCase({
+        name: "WebInspector.Collection.prototype.clear",
+        test(resolve, reject) {
+            let collection = new WebInspector.Collection;
+            collection.add("one");
+            collection.add("two");
+            collection.add(3);
+
+            InspectorTest.log(collection);
+
+            collection.clear();
+
+            InspectorTest.log(collection);
+
+            resolve();
+        }
+    });
+
+    suite.addTestCase({
+        name: "WebInspector.Collection.prototype.get typeVerifier",
+        test(resolve, reject) {
+            function stringVerifier(object) {
+                return typeof object === "string";
+            }
+
+            let collection = new WebInspector.Collection(stringVerifier);
+            collection.add("one");
+            collection.add("two");
+
+            InspectorTest.log(collection);
+
+            collection.add(3);
+
+            InspectorTest.log(collection);
+            InspectorTest.expectEqual(collection.typeVerifier, stringVerifier, "typeVerifier is the given function.");
+
+            resolve();
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="runTest()">
+    <p>Testing all methods of Collection.</p>
+</body>
+</html>
diff --git a/LayoutTests/inspector/unit-tests/resource-collection-expected.txt b/LayoutTests/inspector/unit-tests/resource-collection-expected.txt
new file mode 100644 (file)
index 0000000..46ae908
--- /dev/null
@@ -0,0 +1,20 @@
+Testing all methods of ResourceCollection.
+
+
+== Running test suite: ResourceCollection
+-- Running test case: WebInspector.ResourceCollection.verifierForType
+["two"]
+
+-- Running test case: WebInspector.ResourceCollection.prototype.resourceCollectionForType
+["one","three"]
+["one","three"]
+PASS: resourceCollectionForType will return `this` if a type is specified.
+
+-- Running test case: WebInspector.ResourceCollection.prototype._resourceTypeDidChange
+["one"]
+[]
+["one"]
+["one"]
+[]
+[]
+
diff --git a/LayoutTests/inspector/unit-tests/resource-collection.html b/LayoutTests/inspector/unit-tests/resource-collection.html
new file mode 100644 (file)
index 0000000..6d54c30
--- /dev/null
@@ -0,0 +1,88 @@
+<!doctype html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script>
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("ResourceCollection");
+
+    function createResource(url, type) {
+        return new WebInspector.Resource(url, null, type);
+    }
+
+    function logResourceNames(collection) {
+        let items = Array.from(collection.items);
+        InspectorTest.log(items.map((resource) => resource.displayName));
+    }
+
+    suite.addTestCase({
+        name: "WebInspector.ResourceCollection.verifierForType",
+        test(resolve, reject) {
+            let collection = new WebInspector.ResourceCollection(WebInspector.Resource.Type.Image);
+            collection.add(createResource("one"));
+            collection.add(createResource("two", WebInspector.Resource.Type.Image));
+            collection.add(3);
+
+            logResourceNames(collection);
+
+            resolve();
+        }
+    });
+
+    suite.addTestCase({
+        name: "WebInspector.ResourceCollection.prototype.resourceCollectionForType",
+        test(resolve, reject) {
+            let collection = new WebInspector.ResourceCollection;
+            collection.add(createResource("one", WebInspector.Resource.Type.Image));
+            collection.add(createResource("two", WebInspector.Resource.Type.Stylesheet));
+            collection.add(createResource("three", WebInspector.Resource.Type.Image));
+            collection.add(createResource("four", WebInspector.Resource.Type.Document));
+            collection.add(createResource("five", WebInspector.Resource.Type.Stylesheet));
+
+            logResourceNames(collection.resourceCollectionForType(WebInspector.Resource.Type.Image));
+
+            let typedCollection = new WebInspector.ResourceCollection(WebInspector.Resource.Type.Image);
+            typedCollection.add(createResource("one", WebInspector.Resource.Type.Image));
+            typedCollection.add(createResource("two", WebInspector.Resource.Type.Stylesheet));
+            typedCollection.add(createResource("three", WebInspector.Resource.Type.Image));
+
+            logResourceNames(typedCollection);
+            InspectorTest.expectEqual(typedCollection.resourceCollectionForType(WebInspector.Resource.Type.Image), typedCollection, "resourceCollectionForType will return `this` if a type is specified.")
+
+            resolve();
+        }
+    });
+
+    suite.addTestCase({
+        name: "WebInspector.ResourceCollection.prototype._resourceTypeDidChange",
+        test(resolve, reject) {
+            let imageResource = createResource("one");
+
+            let collection = new WebInspector.ResourceCollection;
+            collection.add(imageResource);
+
+            logResourceNames(collection);
+            logResourceNames(collection.resourceCollectionForType(WebInspector.Resource.Type.Image));
+            logResourceNames(collection.resourceCollectionForType(WebInspector.Resource.Type.Other));
+
+            // Dispatch a type change.
+            imageResource._type = WebInspector.Resource.Type.Image;
+            imageResource.dispatchEventToListeners(WebInspector.Resource.Event.TypeDidChange, {oldType: WebInspector.Resource.Type.Image});
+
+            logResourceNames(collection);
+            logResourceNames(collection.resourceCollectionForType(WebInspector.Resource.Type.Image));
+            logResourceNames(collection.resourceCollectionForType(WebInspector.Resource.Type.Other));
+
+            resolve();
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="runTest()">
+    <p>Testing all methods of ResourceCollection.</p>
+</body>
+</html>
index 72a5802..7e1de72 100644 (file)
@@ -1,3 +1,56 @@
+2016-10-27  Devin Rousso  <dcrousso+webkit@gmail.com>
+
+        Web Inspector: Create general model object Collection class
+        https://bugs.webkit.org/show_bug.cgi?id=163995
+
+        Reviewed by Joseph Pecoraro.
+
+        * UserInterface/Models/Collection.js: Added.
+        (WebInspector.Collection):
+        (WebInspector.Collection.prototype.get items):
+        (WebInspector.Collection.prototype.get typeVerifier):
+        (WebInspector.Collection.prototype.add):
+        (WebInspector.Collection.prototype.remove):
+        (WebInspector.Collection.prototype.clear):
+        (WebInspector.Collection.prototype.toArray):
+        (WebInspector.Collection.prototype.toJSON):
+        (WebInspector.Collection.prototype.itemAdded):
+        (WebInspector.Collection.prototype.itemRemoved):
+        (WebInspector.Collection.prototype.itemsCleared):
+        Class that holds multiple model objects.  It can be limited to a specific type by supplying
+        a "typeVerifier", which is a function that accepts a single argument (the model object) and
+        returns true/false depending on if that argument matches the "type" of the collection.
+
+        * UserInterface/Main.html:
+        * UserInterface/Test.html:
+        * UserInterface/Models/Frame.js:
+        * UserInterface/Views/CookieStorageContentView.js:
+        * UserInterface/Views/DebuggerSidebarPanel.js:
+        * UserInterface/Views/FrameTreeElement.js:
+        * UserInterface/Views/OpenResourceDialog.js:
+        Add support for WebInspector.Collection.
+        
+        * UserInterface/Models/ResourceCollection.js:
+        (WebInspector.ResourceCollection):
+        (WebInspector.ResourceCollection.verifierForType):
+        (WebInspector.ResourceCollection.prototype.resourceCollectionForType):
+        (WebInspector.ResourceCollection.prototype.clear):
+        (WebInspector.ResourceCollection.prototype.itemAdded):
+        (WebInspector.ResourceCollection.prototype.itemRemoved):
+        (WebInspector.ResourceCollection.prototype.itemsCleared):
+        (WebInspector.ResourceCollection.prototype._associateWithResource):
+        (WebInspector.ResourceCollection.prototype._disassociateWithResource):
+        (WebInspector.ResourceCollection.prototype._resourceURLDidChange):
+        (WebInspector.ResourceCollection.prototype._resourceTypeDidChange):
+        (WebInspector.ResourceCollection.prototype.get resources): Deleted.
+        (WebInspector.ResourceCollection.prototype.resourcesWithType): Deleted.
+        (WebInspector.ResourceCollection.prototype.addResource): Deleted.
+        (WebInspector.ResourceCollection.prototype.removeResource): Deleted.
+        (WebInspector.ResourceCollection.prototype.removeAllResources): Deleted.
+        Now a subclass of WebInspector.Collection.  Retrieving WebInspector.Resource objects by type
+        and URL is still supported, but requesting by type now returns another instance of
+        WebInspector.ResourceCollection that is configured to only accept the requested type.
+
 2016-10-27  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: Include ConsoleAgent in Workers - real console.log support
index dab583e..373a9e4 100644 (file)
     <script src="Models/CSSStyleDeclaration.js"></script>
     <script src="Models/CSSStyleSheet.js"></script>
     <script src="Models/CallFrame.js"></script>
+    <script src="Models/Collection.js"></script>
     <script src="Models/CollectionEntry.js"></script>
     <script src="Models/CollectionEntryPreview.js"></script>
     <script src="Models/Color.js"></script>
diff --git a/Source/WebInspectorUI/UserInterface/Models/Collection.js b/Source/WebInspectorUI/UserInterface/Models/Collection.js
new file mode 100644 (file)
index 0000000..db14a60
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2016 Devin Rousso <dcrousso+webkit@gmail.com>. 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.
+ */
+
+WebInspector.Collection = class Collection extends WebInspector.Object
+{
+    constructor(typeVerifier)
+    {
+        super();
+
+        this._items = new Set;
+
+        console.assert(!typeVerifier || typeof typeVerifier === "function");
+        this._typeVerifier = typeVerifier || WebInspector.Collection.TypeVerifier.Any;
+    }
+
+     // Public
+
+    get items() { return this._items; }
+    get typeVerifier() { return this._typeVerifier; }
+
+    add(item)
+    {
+        let isValidType = this._typeVerifier(item);
+        console.assert(isValidType);
+        if (!isValidType)
+            return;
+
+        console.assert(!this._items.has(item));
+        this._items.add(item);
+
+        this.itemAdded(item);
+
+        this.dispatchEventToListeners(WebInspector.Collection.Event.ItemAdded, {item});
+    }
+
+    remove(item)
+    {
+        let wasRemoved = this._items.delete(item);
+        console.assert(wasRemoved);
+
+        this.itemRemoved(item);
+
+        this.dispatchEventToListeners(WebInspector.Collection.Event.ItemRemoved, {item});
+    }
+
+    clear()
+    {
+        let items = new Set(this._items);
+
+        this._items.clear();
+
+        this.itemsCleared(items);
+
+        for (let item of items)
+            this.dispatchEventToListeners(WebInspector.Collection.Event.ItemRemoved, {item});
+    }
+
+    toArray()
+    {
+        return Array.from(this._items);
+    }
+
+    toJSON()
+    {
+        return this.toArray();
+    }
+
+     // Protected
+
+    itemAdded(item)
+    {
+        // Implemented by subclasses.
+    }
+
+    itemRemoved(item)
+    {
+        // Implemented by subclasses.
+    }
+
+    itemsCleared(items)
+    {
+        // Implemented by subclasses.
+    }
+};
+
+ WebInspector.Collection.Event = {
+    ItemAdded: "collection-item-added",
+    ItemRemoved: "collection-item-removed",
+};
+
+ WebInspector.Collection.TypeVerifier = {
+    Any: (object) => true,
+    Frame: (object) => object instanceof WebInspector.Frame,
+    Resource: (object) => object instanceof WebInspector.Resource,
+    Script: (object) => object instanceof WebInspector.Script,
+};
index 605e8b2..605975b 100644 (file)
@@ -41,7 +41,7 @@ WebInspector.Frame = class Frame extends WebInspector.Object
         this._extraScripts = [];
 
         this._childFrames = [];
-        this._childFrameIdentifierMap = {};
+        this._childFrameIdentifierMap = new Map;
 
         this._parentFrame = null;
         this._isMainFrame = false;
@@ -56,6 +56,8 @@ WebInspector.Frame = class Frame extends WebInspector.Object
 
     // Public
 
+    get resourceCollection() { return this._resourceCollection; }
+
     initialize(name, securityOrigin, loaderIdentifier, mainResource)
     {
         console.assert(loaderIdentifier);
@@ -99,7 +101,7 @@ WebInspector.Frame = class Frame extends WebInspector.Object
 
         this._provisionalLoaderIdentifier = provisionalMainResource.loaderIdentifier;
 
-        this._provisionalResourceCollection.removeAllResources();
+        this._provisionalResourceCollection.clear();
 
         this.dispatchEventToListeners(WebInspector.Frame.Event.ProvisionalLoadStarted);
     }
@@ -150,7 +152,7 @@ WebInspector.Frame = class Frame extends WebInspector.Object
 
         this._provisionalLoaderIdentifier = null;
         this._provisionalMainResource = null;
-        this._provisionalResourceCollection.removeAllResources();
+        this._provisionalResourceCollection.clear();
 
         if (!skipProvisionalLoadClearedEvent)
             this.dispatchEventToListeners(WebInspector.Frame.Event.ProvisionalLoadCleared);
@@ -289,7 +291,7 @@ WebInspector.Frame = class Frame extends WebInspector.Object
 
     childFrameForIdentifier(frameId)
     {
-        return this._childFrameIdentifierMap[frameId] || null;
+        return this._childFrameIdentifierMap.get(frameId) || null;
     }
 
     addChildFrame(frame)
@@ -305,7 +307,7 @@ WebInspector.Frame = class Frame extends WebInspector.Object
             frame._parentFrame.removeChildFrame(frame);
 
         this._childFrames.push(frame);
-        this._childFrameIdentifierMap[frame._id] = frame;
+        this._childFrameIdentifierMap.set(frame._id, frame);
 
         frame._parentFrame = this;
 
@@ -332,7 +334,7 @@ WebInspector.Frame = class Frame extends WebInspector.Object
         console.assert(childFrame.parentFrame === this);
 
         this._childFrames.remove(childFrame);
-        delete this._childFrameIdentifierMap[childFrame._id];
+        this._childFrameIdentifierMap.delete(childFrame._id);
 
         childFrame._detachFromParentFrame();
 
@@ -347,16 +349,11 @@ WebInspector.Frame = class Frame extends WebInspector.Object
             childFrame.removeAllChildFrames();
 
         this._childFrames = [];
-        this._childFrameIdentifierMap = {};
+        this._childFrameIdentifierMap.clear();
 
         this.dispatchEventToListeners(WebInspector.Frame.Event.AllChildFramesRemoved);
     }
 
-    get resources()
-    {
-        return this._resourceCollection.resources;
-    }
-
     resourceForURL(url, recursivelySearchChildFrames)
     {
         var resource = this._resourceCollection.resourceForURL(url);
@@ -383,9 +380,9 @@ WebInspector.Frame = class Frame extends WebInspector.Object
         return null;
     }
 
-    resourcesWithType(type)
+    resourceCollectionForType(type)
     {
-        return this._resourceCollection.resourcesWithType(type);
+        return this._resourceCollection.resourceCollectionForType(type);
     }
 
     addResource(resource)
@@ -398,15 +395,15 @@ WebInspector.Frame = class Frame extends WebInspector.Object
             return;
 
         if (resource.parentFrame)
-            resource.parentFrame.removeResource(resource);
+            resource.parentFrame.remove(resource);
 
         this._associateWithResource(resource);
 
         if (this._isProvisionalResource(resource)) {
-            this._provisionalResourceCollection.addResource(resource);
+            this._provisionalResourceCollection.add(resource);
             this.dispatchEventToListeners(WebInspector.Frame.Event.ProvisionalResourceWasAdded, {resource});
         } else {
-            this._resourceCollection.addResource(resource);
+            this._resourceCollection.add(resource);
             this.dispatchEventToListeners(WebInspector.Frame.Event.ResourceWasAdded, {resource});
         }
     }
@@ -415,7 +412,7 @@ WebInspector.Frame = class Frame extends WebInspector.Object
     {
         // This does not remove provisional resources.
 
-        var resource = this._resourceCollection.removeResource(resourceOrURL);
+        var resource = this._resourceCollection.remove(resourceOrURL);
         if (!resource)
             return;
 
@@ -428,14 +425,14 @@ WebInspector.Frame = class Frame extends WebInspector.Object
     {
         // This does not remove provisional resources, use clearProvisionalLoad for that.
 
-        var resources = this.resources;
-        if (!resources.length)
+        let resources = this._resourceCollection.items;
+        if (!resources.size)
             return;
 
-        for (var i = 0; i < resources.length; ++i)
-            this._disassociateWithResource(resources[i]);
+        for (let resource of resources)
+            this._disassociateWithResource(resource);
 
-        this._resourceCollection.removeAllResources();
+        this._resourceCollection.clear();
 
         this.dispatchEventToListeners(WebInspector.Frame.Event.AllResourcesRemoved);
     }
index 735ab3a..d9ab445 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2016 Devin Rousso <dcrousso+webkit@gmail.com>. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.ResourceCollection = class ResourceCollection extends WebInspector.Object
+WebInspector.ResourceCollection = class ResourceCollection extends WebInspector.Collection
 {
-    constructor()
+    constructor(resourceType)
     {
-        super();
+        super(WebInspector.ResourceCollection.verifierForType(resourceType));
 
-        this._resources = [];
+        this._resourceType = resourceType || null;
         this._resourceURLMap = new Map;
         this._resourcesTypeMap = new Map;
     }
 
-    // Public
-
-    get resources()
-    {
-        return this._resources;
+    // Static
+
+    static verifierForType(type) {
+        switch (type) {
+        case WebInspector.Resource.Type.Document:
+            return WebInspector.ResourceCollection.TypeVerifier.Document;
+        case WebInspector.Resource.Type.Stylesheet:
+            return WebInspector.ResourceCollection.TypeVerifier.Stylesheet;
+        case WebInspector.Resource.Type.Image:
+            return WebInspector.ResourceCollection.TypeVerifier.Image;
+        case WebInspector.Resource.Type.Font:
+            return WebInspector.ResourceCollection.TypeVerifier.Font;
+        case WebInspector.Resource.Type.Script:
+            return WebInspector.ResourceCollection.TypeVerifier.Script;
+        case WebInspector.Resource.Type.XHR:
+            return WebInspector.ResourceCollection.TypeVerifier.XHR;
+        case WebInspector.Resource.Type.WebSocket:
+            return WebInspector.ResourceCollection.TypeVerifier.WebSocket;
+        case WebInspector.Resource.Type.Other:
+            return WebInspector.ResourceCollection.TypeVerifier.Other;
+        default:
+            return WebInspector.Collection.TypeVerifier.Resource;
+        }
     }
 
+    // Public
+
     resourceForURL(url)
     {
         return this._resourceURLMap.get(url) || null;
     }
 
-    resourcesWithType(type)
+    resourceCollectionForType(type)
     {
-        return this._resourcesTypeMap.get(type) || [];
-    }
+        if (this._resourceType) {
+            console.assert(type === this._resourceType);
+            return this;
+        }
 
-    addResource(resource)
-    {
-        console.assert(resource instanceof WebInspector.Resource);
-        if (!(resource instanceof WebInspector.Resource))
-            return;
+        let resourcesCollectionForType = this._resourcesTypeMap.get(type);
+        if (!resourcesCollectionForType) {
+            resourcesCollectionForType = new WebInspector.ResourceCollection(type);
+            this._resourcesTypeMap.set(type, resourcesCollectionForType);
+        }
 
-        this._associateWithResource(resource);
+        return resourcesCollectionForType;
     }
 
-    removeResource(resourceOrURL)
+    clear()
     {
-        console.assert(resourceOrURL);
+        super.clear();
 
-        if (resourceOrURL instanceof WebInspector.Resource)
-            var url = resourceOrURL.url;
-        else
-            var url = resourceOrURL;
+        this._resourceURLMap.clear();
 
-        // Fetch the resource by URL even if we were passed a WebInspector.Resource.
-        // We do this incase the WebInspector.Resource is a new object that isn't in _resources,
-        // but the URL is a valid resource.
-        var resource = this.resourceForURL(url);
-        console.assert(resource instanceof WebInspector.Resource);
-        if (!(resource instanceof WebInspector.Resource))
-            return null;
+        if (!this._resourceType)
+            this._resourcesTypeMap.clear();
+    }
 
-        this._disassociateWithResource(resource);
+    // Protected
 
-        return resource;
+    itemAdded(item)
+    {
+        this._associateWithResource(item);
     }
 
-    removeAllResources()
+    itemRemoved(item)
     {
-        if (!this._resources.length)
-            return;
+        this._disassociateWithResource(item);
+    }
 
-        for (var i = 0; i < this._resources.length; ++i)
-            this._disassociateWithResource(this._resources[i], true);
+    itemsCleared(items)
+    {
+        const skipRemoval = true;
 
-        this._resources = [];
-        this._resourceURLMap.clear();
-        this._resourcesTypeMap.clear();
+        for (let item of items)
+            this._disassociateWithResource(item, skipRemoval);
     }
 
     // Private
 
     _associateWithResource(resource)
     {
-        this._resources.push(resource);
         this._resourceURLMap.set(resource.url, resource);
 
-        if (!this._resourcesTypeMap.has(resource.type))
-            this._resourcesTypeMap.set(resource.type, [resource]);
-        else
-            this._resourcesTypeMap.get(resource.type).push(resource);
+        if (!this._resourceType) {
+            let resourcesCollectionForType = this.resourceCollectionForType(resource.type);
+            resourcesCollectionForType.add(resource);
+        }
 
         resource.addEventListener(WebInspector.Resource.Event.URLDidChange, this._resourceURLDidChange, this);
         resource.addEventListener(WebInspector.Resource.Event.TypeDidChange, this._resourceTypeDidChange, this);
@@ -113,25 +130,28 @@ WebInspector.ResourceCollection = class ResourceCollection extends WebInspector.
 
     _disassociateWithResource(resource, skipRemoval)
     {
-        if (skipRemoval) {
-            this._resources.remove(resource);
-            if (this._resourcesTypeMap.has(resource.type))
-                this._resourcesTypeMap.get(resource.type).remove(resource);
-            this._resourceURLMap.delete(resource.url);
-        }
-
         resource.removeEventListener(WebInspector.Resource.Event.URLDidChange, this._resourceURLDidChange, this);
         resource.removeEventListener(WebInspector.Resource.Event.TypeDidChange, this._resourceTypeDidChange, this);
+
+        if (skipRemoval)
+            return;
+
+        if (!this._resourceType) {
+            let resourcesCollectionForType = this.resourceCollectionForType(resource.type);
+            resourcesCollectionForType.remove(resource);
+        }
+
+        this._resourceURLMap.delete(resource.url);
     }
 
     _resourceURLDidChange(event)
     {
-        var resource = event.target;
+        let resource = event.target;
         console.assert(resource instanceof WebInspector.Resource);
         if (!(resource instanceof WebInspector.Resource))
             return;
 
-        var oldURL = event.data.oldURL;
+        let oldURL = event.data.oldURL;
         console.assert(oldURL);
         if (!oldURL)
             return;
@@ -142,22 +162,37 @@ WebInspector.ResourceCollection = class ResourceCollection extends WebInspector.
 
     _resourceTypeDidChange(event)
     {
-        var resource = event.target;
+        let resource = event.target;
         console.assert(resource instanceof WebInspector.Resource);
         if (!(resource instanceof WebInspector.Resource))
             return;
 
-        var oldType = event.data.oldType;
+        if (this._resourceType) {
+            console.assert(resource.type !== this._resourceType);
+            this.remove(resource);
+            return;
+        }
+
+        let oldType = event.data.oldType;
         console.assert(oldType);
         if (!oldType)
             return;
 
-        if (!this._resourcesTypeMap.has(resource.type))
-            this._resourcesTypeMap.set(resource.type, [resource]);
-        else
-            this._resourcesTypeMap.get(resource.type).push(resource);
+        let resourcesWithNewType = this.resourceCollectionForType(resource.type);
+        resourcesWithNewType.add(resource);
 
-        if (this._resourcesTypeMap.has(oldType))
-            this._resourcesTypeMap.get(oldType).remove(resource);
+        let resourcesWithOldType = this.resourceCollectionForType(oldType);
+        resourcesWithOldType.remove(resource);
     }
 };
+
+WebInspector.ResourceCollection.TypeVerifier = {
+    Document: (object) => WebInspector.Collection.TypeVerifier.Resource(object) && object.type === WebInspector.Resource.Type.Document,
+    Stylesheet: (object) => WebInspector.Collection.TypeVerifier.Resource(object) && object.type === WebInspector.Resource.Type.Stylesheet,
+    Image: (object) => WebInspector.Collection.TypeVerifier.Resource(object) && object.type === WebInspector.Resource.Type.Image,
+    Font: (object) => WebInspector.Collection.TypeVerifier.Resource(object) && object.type === WebInspector.Resource.Type.Font,
+    Script: (object) => WebInspector.Collection.TypeVerifier.Resource(object) && object.type === WebInspector.Resource.Type.Script,
+    XHR: (object) => WebInspector.Collection.TypeVerifier.Resource(object) && object.type === WebInspector.Resource.Type.XHR,
+    WebSocket: (object) => WebInspector.Collection.TypeVerifier.Resource(object) && object.type === WebInspector.Resource.Type.WebSocket,
+    Other: (object) => WebInspector.Collection.TypeVerifier.Resource(object) && object.type === WebInspector.Resource.Type.Other,
+};
index 3117b10..7d905a4 100644 (file)
     <script src="Models/CallFrame.js"></script>
     <script src="Models/CallingContextTree.js"></script>
     <script src="Models/CallingContextTreeNode.js"></script>
+    <script src="Models/Collection.js"></script>
     <script src="Models/CollectionEntry.js"></script>
     <script src="Models/CollectionEntryPreview.js"></script>
     <script src="Models/Color.js"></script>
index 9885192..8442f98 100644 (file)
@@ -160,7 +160,7 @@ WebInspector.CookieStorageContentView = class CookieStorageContentView extends W
         for (let frame of WebInspector.frameResourceManager.frames) {
             // The main resource isn't in the list of resources, so add it as a candidate.
             allResources.push(frame.mainResource);
-            allResources = allResources.concat(frame.resources);
+            allResources = allResources.concat(frame.resourceCollection.toArray());
         }
 
         let resourcesForDomain = allResources.filter(resourceMatchesStorageDomain);
index c49de26..6d91dd8 100644 (file)
@@ -419,7 +419,7 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
     {
         this._addResource(frame.mainResource);
 
-        for (var resource of frame.resources)
+        for (let resource of frame.resourceCollection.items)
             this._addResource(resource);
 
         for (var childFrame of frame.childFrames)
index 9bc6db4..5b3cb61 100644 (file)
@@ -75,7 +75,7 @@ WebInspector.FrameTreeElement = class FrameTreeElement extends WebInspector.Reso
 
         function makeChildCountCallback(frame, resourceType) {
             return function() {
-                return frame.resourcesWithType(resourceType).length;
+                return frame.resourceCollectionForType(resourceType).items.size;
             };
         }
 
@@ -181,8 +181,8 @@ WebInspector.FrameTreeElement = class FrameTreeElement extends WebInspector.Reso
         for (var i = 0; i < this._frame.childFrames.length; ++i)
             this.addChildForRepresentedObject(this._frame.childFrames[i]);
 
-        for (var i = 0; i < this._frame.resources.length; ++i)
-            this.addChildForRepresentedObject(this._frame.resources[i]);
+        for (let resource of this._frame.resourceCollection.items)
+            this.addChildForRepresentedObject(resource);
 
         var sourceMaps = this.resource && this.resource.sourceMaps;
         for (var i = 0; i < sourceMaps.length; ++i) {
index 03d2279..3ac33e9 100644 (file)
@@ -268,7 +268,7 @@ WebInspector.OpenResourceDialog = class OpenResourceDialog extends WebInspector.
         let frames = [frame];
         while (frames.length) {
             let currentFrame = frames.shift();
-            let resources = [currentFrame.mainResource].concat(currentFrame.resources);
+            let resources = [currentFrame.mainResource].concat(Array.from(currentFrame.resourceCollection.items));
             for (let resource of resources)
                 this._addResource(resource, suppressFilterUpdate);