Web Inspector: JSContext inspection Resource search does not work
authorjoepeck@webkit.org <joepeck@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Nov 2014 23:49:40 +0000 (23:49 +0000)
committerjoepeck@webkit.org <joepeck@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Nov 2014 23:49:40 +0000 (23:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=131252

Reviewed by Timothy Hatcher.

Source/JavaScriptCore:

* inspector/agents/InspectorDebuggerAgent.cpp:
(Inspector::InspectorDebuggerAgent::searchInContent):
* inspector/protocol/Debugger.json:
Do some cleanup of the description and implementation of content searching.

Source/WebCore:

Test: inspector/debugger/search-scripts.html

* inspector/InspectorPageAgent.cpp:
(WebCore::InspectorPageAgent::searchInResources):
A little cleanup.

Source/WebInspectorUI:

* UserInterface/Views/ResourceSidebarPanel.js:
(WebInspector.ResourceSidebarPanel.prototype.performSearch.resourceCallback):
(WebInspector.ResourceSidebarPanel.prototype.performSearch.resourcesCallback):
Cleanup by reordering things a bit.

(WebInspector.ResourceSidebarPanel.prototype.performSearch.searchScripts.scriptCallback):
(WebInspector.ResourceSidebarPanel.prototype.performSearch.searchScripts):
(WebInspector.ResourceSidebarPanel.prototype.performSearch):
Search non-resource scripts individually.

(WebInspector.ResourceSidebarPanel.prototype._searchTreeElementForScript):
Lazily create a ScriptTreeElement for the search tree outline as needed.

(WebInspector.ResourceSidebarPanel.prototype._scriptsToSearch):
When searching scripts, just perform a shallow walk of the tree outline to find
Script resources that are not also Resources. Scripts are always guarenteed to
be in a folder when inspecting a web resource. For JSContext inspection, scripts
are promoted to the top level.

* UserInterface/Main.html:
* UserInterface/Models/SourceCodeSearchMatchObject.js: Renamed from Source/WebInspectorUI/UserInterface/Models/ResourceSearchMatchObject.js.
(WebInspector.SourceCodeSearchMatchObject):
* UserInterface/Views/SearchIcons.css:
(.source-code-match-icon .icon):
(.resource-match-icon .icon): Deleted.
* UserInterface/Views/SearchResultTreeElement.js:
(WebInspector.SearchResultTreeElement):
Rename ResourceSearchMatchObject to SourceCodeSearchMatchObject.

LayoutTests:

* inspector/debugger/search-scripts-expected.txt: Added.
* inspector/debugger/search-scripts.html: Added.
Tests for Debugger.searchInContent.

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

17 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/debugger/search-scripts-expected.txt [new file with mode: 0644]
LayoutTests/inspector/debugger/search-scripts.html [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp
Source/JavaScriptCore/inspector/protocol/Debugger.json
Source/JavaScriptCore/inspector/protocol/Page.json
Source/WebCore/ChangeLog
Source/WebCore/inspector/InspectorPageAgent.cpp
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/Main.html
Source/WebInspectorUI/UserInterface/Models/SourceCodeSearchMatchObject.js [moved from Source/WebInspectorUI/UserInterface/Models/ResourceSearchMatchObject.js with 70% similarity]
Source/WebInspectorUI/UserInterface/Views/ResourceSidebarPanel.js
Source/WebInspectorUI/UserInterface/Views/SearchIcons.css
Source/WebInspectorUI/UserInterface/Views/SearchResultTreeElement.js
Source/WebInspectorUI/WebInspectorUI.vcxproj/WebInspectorUI.vcxproj
Source/WebInspectorUI/WebInspectorUI.vcxproj/WebInspectorUI.vcxproj.filters

index 90f8f14..5dc470b 100644 (file)
@@ -1,5 +1,16 @@
 2014-11-19  Joseph Pecoraro  <pecoraro@apple.com>
 
+        Web Inspector: JSContext inspection Resource search does not work
+        https://bugs.webkit.org/show_bug.cgi?id=131252
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/debugger/search-scripts-expected.txt: Added.
+        * inspector/debugger/search-scripts.html: Added.
+        Tests for Debugger.searchInContent.
+
+2014-11-19  Joseph Pecoraro  <pecoraro@apple.com>
+
         Web Inspector: Provide $exception in the console for the thrown exception value
         https://bugs.webkit.org/show_bug.cgi?id=138726
 
diff --git a/LayoutTests/inspector/debugger/search-scripts-expected.txt b/LayoutTests/inspector/debugger/search-scripts-expected.txt
new file mode 100644 (file)
index 0000000..d7cca56
--- /dev/null
@@ -0,0 +1,28 @@
+Test DebuggerAgent.searchInContent to search script content.
+
+
+SCRIPT: LayoutTests/http/tests/inspector/inspector-test.js
+RESULTS: 0
+
+SCRIPT: LayoutTests/inspector/debugger/search-scripts.html
+RESULTS: 2
+  LINE: 1
+  CONTENT: // SEARCHTEST: Comment in inline <script>.
+  LINE: 28
+  CONTENT:         DebuggerAgent.searchInContent(script.id, "SEARCHTEST", false, false, function(error, results) {
+
+SCRIPT: LayoutTests/inspector/debugger/search-scripts.html
+RESULTS: 1
+  LINE: 0
+  CONTENT: (function(event) {runTest(); // SEARCHTEST: onload attribute string
+
+SCRIPT: eval1.js
+RESULTS: 1
+  LINE: 0
+  CONTENT: // SEARCHTEST: Eval 1
+
+SCRIPT: eval2.js
+RESULTS: 1
+  LINE: 0
+  CONTENT: var SEARCHTEST = "SEARCHTEST";
+
diff --git a/LayoutTests/inspector/debugger/search-scripts.html b/LayoutTests/inspector/debugger/search-scripts.html
new file mode 100644 (file)
index 0000000..e326a45
--- /dev/null
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+<head>
+<script type="text/javascript" src="../../http/tests/inspector/inspector-test.js"></script>
+<script>
+// SEARCHTEST: Comment in inline <script>.
+function performEvals()
+{
+    // Find the line with the search term.
+    eval("// SEARCH" + "TEST: Eval 1\n//# sourceURL=eval1.js");
+    // If the search term shows up multiple times on a single line, the line is returned once.
+    eval("var SEARCH" + "TEST = \"SEARCH" + "TEST\";\n//# sourceURL=eval2.js");
+};
+
+function test()
+{
+    function sanitizeScriptURL(url) {
+        return url.substring(url.indexOf("LayoutTests"));
+    }
+
+    function chomp(line) {
+        return line.replace(/\n$/, "");
+    }
+
+    var scriptsCount = 0;
+    const expectedScriptsCount = 5;
+
+    WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ScriptAdded, function(event) {
+        var script = event.data.script;
+        if (!/LayoutTests/.test(script.url) && !/eval\d\.js/.test(script.url))
+            return;
+
+        DebuggerAgent.searchInContent(script.id, "SEARCHTEST", false, false, function(error, results) {
+            InspectorTest.log("");
+            InspectorTest.log("SCRIPT: " + sanitizeScriptURL(script.url));
+            InspectorTest.log("RESULTS: " + results.length);
+            for (var result of results) {
+                InspectorTest.log("  LINE: " + result.lineNumber);
+                InspectorTest.log("  CONTENT: " + chomp(result.lineContent));
+            }
+
+            if (++scriptsCount === expectedScriptsCount)
+                InspectorTest.completeTest();
+        });
+    });
+
+    InspectorTest.eventDispatcher.addEventListener(InspectorTest.EventDispatcher.Event.TestPageDidLoad, function() {
+        InspectorTest.evaluateInPage("performEvals()");
+    });
+
+    InspectorTest.reloadPage();
+}
+</script>
+</head>
+<body onload="runTest(); // SEARCHTEST: onload attribute string">
+    <p>Test <code>DebuggerAgent.searchInContent</code> to search script content.</p>
+</body>
+</html>
index bcfe379..302cacc 100644 (file)
@@ -1,5 +1,17 @@
 2014-11-19  Joseph Pecoraro  <pecoraro@apple.com>
 
+        Web Inspector: JSContext inspection Resource search does not work
+        https://bugs.webkit.org/show_bug.cgi?id=131252
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/agents/InspectorDebuggerAgent.cpp:
+        (Inspector::InspectorDebuggerAgent::searchInContent):
+        * inspector/protocol/Debugger.json:
+        Do some cleanup of the description and implementation of content searching.
+
+2014-11-19  Joseph Pecoraro  <pecoraro@apple.com>
+
         Web Inspector: Provide $exception in the console for the thrown exception value
         https://bugs.webkit.org/show_bug.cgi?id=138726
 
index 28da2c2..29e16d5 100644 (file)
@@ -401,17 +401,18 @@ PassRefPtr<Inspector::Protocol::Debugger::Location> InspectorDebuggerAgent::reso
     return location;
 }
 
-void InspectorDebuggerAgent::searchInContent(ErrorString& error, const String& scriptIDStr, const String& query, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::GenericTypes::SearchMatch>>& results)
+void InspectorDebuggerAgent::searchInContent(ErrorString& error, const String& scriptIDStr, const String& query, const bool* optionalCaseSensitive, const bool* optionalIsRegex, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::GenericTypes::SearchMatch>>& results)
 {
-    bool isRegex = optionalIsRegex ? *optionalIsRegex : false;
-    bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false;
-
     JSC::SourceID sourceID = scriptIDStr.toIntPtr();
-    ScriptsMap::iterator it = m_scripts.find(sourceID);
-    if (it != m_scripts.end())
-        results = ContentSearchUtilities::searchInTextByLines(it->value.source, query, caseSensitive, isRegex);
-    else
+    auto it = m_scripts.find(sourceID);
+    if (it == m_scripts.end()) {
         error = ASCIILiteral("No script for id: ") + scriptIDStr;
+        return;
+    }
+
+    bool isRegex = optionalIsRegex ? *optionalIsRegex : false;
+    bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false;
+    results = ContentSearchUtilities::searchInTextByLines(it->value.source, query, caseSensitive, isRegex);
 }
 
 void InspectorDebuggerAgent::getScriptSource(ErrorString& error, const String& scriptIDStr, String* scriptSource)
index ebf73f8..fe6d4a1 100644 (file)
         },
         {
             "name": "searchInContent",
+            "description": "Searches for given string in script content.",
             "parameters": [
                 { "name": "scriptId", "$ref": "ScriptId", "description": "Id of the script to search in." },
-                { "name": "query", "type": "string", "description": "String to search for."  },
+                { "name": "query", "type": "string", "description": "String to search for." },
                 { "name": "caseSensitive", "type": "boolean", "optional": true, "description": "If true, search is case sensitive." },
                 { "name": "isRegex", "type": "boolean", "optional": true, "description": "If true, treats string parameter as regex." }
             ],
             "returns": [
                 { "name": "result", "type": "array", "items": { "$ref": "GenericTypes.SearchMatch" }, "description": "List of search matches." }
-            ],
-            "description": "Searches for given string in script content."
+            ]
         },
         {
             "name": "getScriptSource",
index 71813ea..c210a89 100644 (file)
             "parameters": [
                 { "name": "frameId", "$ref": "Network.FrameId", "description": "Frame id for resource to search in." },
                 { "name": "url", "type": "string", "description": "URL of the resource to search in." },
-                { "name": "query", "type": "string", "description": "String to search for."  },
+                { "name": "query", "type": "string", "description": "String to search for." },
                 { "name": "caseSensitive", "type": "boolean", "optional": true, "description": "If true, search is case sensitive." },
                 { "name": "isRegex", "type": "boolean", "optional": true, "description": "If true, treats string parameter as regex." }
             ],
             "name": "searchInResources",
             "description": "Searches for given string in frame / resource tree structure.",
             "parameters": [
-                { "name": "text", "type": "string", "description": "String to search for."  },
+                { "name": "text", "type": "string", "description": "String to search for." },
                 { "name": "caseSensitive", "type": "boolean", "optional": true, "description": "If true, search is case sensitive." },
                 { "name": "isRegex", "type": "boolean", "optional": true, "description": "If true, treats string parameter as regex." }
             ],
index 5fdf27a..84c7181 100644 (file)
@@ -1,5 +1,18 @@
 2014-11-19  Joseph Pecoraro  <pecoraro@apple.com>
 
+        Web Inspector: JSContext inspection Resource search does not work
+        https://bugs.webkit.org/show_bug.cgi?id=131252
+
+        Reviewed by Timothy Hatcher.
+
+        Test: inspector/debugger/search-scripts.html
+
+        * inspector/InspectorPageAgent.cpp:
+        (WebCore::InspectorPageAgent::searchInResources):
+        A little cleanup.
+
+2014-11-19  Joseph Pecoraro  <pecoraro@apple.com>
+
         Web Inspector: Provide $exception in the console for the thrown exception value
         https://bugs.webkit.org/show_bug.cgi?id=138726
 
index d7e018c..2f244ca 100644 (file)
@@ -607,9 +607,9 @@ static PassRefPtr<Inspector::Protocol::Page::SearchResult> buildObjectForSearchR
         .release();
 }
 
-void InspectorPageAgent::searchInResources(ErrorString&, const String& text, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Page::SearchResult>>& results)
+void InspectorPageAgent::searchInResources(ErrorString&, const String& text, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Page::SearchResult>>& result)
 {
-    RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Page::SearchResult>> searchResults = Inspector::Protocol::Array<Inspector::Protocol::Page::SearchResult>::create();
+    result = Inspector::Protocol::Array<Inspector::Protocol::Page::SearchResult>::create();
 
     bool isRegex = optionalIsRegex ? *optionalIsRegex : false;
     bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false;
@@ -622,18 +622,16 @@ void InspectorPageAgent::searchInResources(ErrorString&, const String& text, con
             if (textContentForCachedResource(cachedResource, &content)) {
                 int matchesCount = ContentSearchUtilities::countRegularExpressionMatches(regex, content);
                 if (matchesCount)
-                    searchResults->addItem(buildObjectForSearchResult(frameId(frame), cachedResource->url(), matchesCount));
+                    result->addItem(buildObjectForSearchResult(frameId(frame), cachedResource->url(), matchesCount));
             }
         }
 
         if (mainResourceContent(frame, false, &content)) {
             int matchesCount = ContentSearchUtilities::countRegularExpressionMatches(regex, content);
             if (matchesCount)
-                searchResults->addItem(buildObjectForSearchResult(frameId(frame), frame->document()->url(), matchesCount));
+                result->addItem(buildObjectForSearchResult(frameId(frame), frame->document()->url(), matchesCount));
         }
     }
-
-    results = searchResults;
 }
 
 void InspectorPageAgent::setDocumentContent(ErrorString& errorString, const String& frameId, const String& html)
index 5a24b74..491cc7a 100644 (file)
@@ -1,5 +1,41 @@
 2014-11-19  Joseph Pecoraro  <pecoraro@apple.com>
 
+        Web Inspector: JSContext inspection Resource search does not work
+        https://bugs.webkit.org/show_bug.cgi?id=131252
+
+        Reviewed by Timothy Hatcher.
+
+        * UserInterface/Views/ResourceSidebarPanel.js:
+        (WebInspector.ResourceSidebarPanel.prototype.performSearch.resourceCallback):
+        (WebInspector.ResourceSidebarPanel.prototype.performSearch.resourcesCallback):
+        Cleanup by reordering things a bit.
+
+        (WebInspector.ResourceSidebarPanel.prototype.performSearch.searchScripts.scriptCallback):
+        (WebInspector.ResourceSidebarPanel.prototype.performSearch.searchScripts):
+        (WebInspector.ResourceSidebarPanel.prototype.performSearch):
+        Search non-resource scripts individually.
+
+        (WebInspector.ResourceSidebarPanel.prototype._searchTreeElementForScript):
+        Lazily create a ScriptTreeElement for the search tree outline as needed.
+
+        (WebInspector.ResourceSidebarPanel.prototype._scriptsToSearch):
+        When searching scripts, just perform a shallow walk of the tree outline to find
+        Script resources that are not also Resources. Scripts are always guarenteed to
+        be in a folder when inspecting a web resource. For JSContext inspection, scripts
+        are promoted to the top level.
+
+        * UserInterface/Main.html:
+        * UserInterface/Models/SourceCodeSearchMatchObject.js: Renamed from Source/WebInspectorUI/UserInterface/Models/ResourceSearchMatchObject.js.
+        (WebInspector.SourceCodeSearchMatchObject):
+        * UserInterface/Views/SearchIcons.css:
+        (.source-code-match-icon .icon):
+        (.resource-match-icon .icon): Deleted.
+        * UserInterface/Views/SearchResultTreeElement.js:
+        (WebInspector.SearchResultTreeElement):
+        Rename ResourceSearchMatchObject to SourceCodeSearchMatchObject.
+
+2014-11-19  Joseph Pecoraro  <pecoraro@apple.com>
+
         Web Inspector: Provide $exception in the console for the thrown exception value
         https://bugs.webkit.org/show_bug.cgi?id=138726
 
index f92947b..cb6b177 100644 (file)
     <script src="Models/ReplaySessionSegment.js"></script>
     <script src="Models/Resource.js"></script>
     <script src="Models/ResourceCollection.js"></script>
-    <script src="Models/ResourceSearchMatchObject.js"></script>
     <script src="Models/ResourceTimelineRecord.js"></script>
     <script src="Models/Revision.js"></script>
     <script src="Models/ScopeChainNode.js"></script>
     <script src="Models/Setting.js"></script>
     <script src="Models/SourceCodePosition.js"></script>
     <script src="Models/SourceCodeRevision.js"></script>
+    <script src="Models/SourceCodeSearchMatchObject.js"></script>
     <script src="Models/SourceCodeTextRange.js"></script>
     <script src="Models/SourceCodeTimeline.js"></script>
     <script src="Models/SourceMap.js"></script>
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.ResourceSearchMatchObject = function(resource, lineText, searchTerm, textRange)
+WebInspector.SourceCodeSearchMatchObject = function(sourceCode, lineText, searchTerm, textRange)
 {
-    console.assert(resource instanceof WebInspector.Resource);
+    console.assert(sourceCode instanceof WebInspector.SourceCode);
 
     WebInspector.Object.call(this);
 
-    this._resource = resource;
+    this._sourceCode = sourceCode;
     this._lineText = lineText;
     this._searchTerm = searchTerm;
-    this._sourceCodeTextRange = resource.createSourceCodeTextRange(textRange);
+    this._sourceCodeTextRange = sourceCode.createSourceCodeTextRange(textRange);
 };
 
-WebInspector.ResourceSearchMatchObject.ResourceMatchIconStyleClassName = "resource-match-icon";
+WebInspector.SourceCodeSearchMatchObject.SourceCodeMatchIconStyleClassName = "source-code-match-icon";
 
-WebInspector.ResourceSearchMatchObject.prototype = {
-    constructor: WebInspector.ResourceSearchMatchObject,
+WebInspector.SourceCodeSearchMatchObject.prototype = {
+    constructor: WebInspector.SourceCodeSearchMatchObject,
 
-    get resource()
+    get sourceCode()
     {
-        return this._resource;
+        return this._sourceCode;
     },
 
     get title()
@@ -52,7 +52,7 @@ WebInspector.ResourceSearchMatchObject.prototype = {
 
     get className()
     {
-        return WebInspector.ResourceSearchMatchObject.ResourceMatchIconStyleClassName;
+        return WebInspector.SourceCodeSearchMatchObject.SourceCodeMatchIconStyleClassName;
     },
 
     get searchTerm()
@@ -66,4 +66,4 @@ WebInspector.ResourceSearchMatchObject.prototype = {
     }
 };
 
-WebInspector.ResourceSearchMatchObject.prototype.__proto__ = WebInspector.Object.prototype;
+WebInspector.SourceCodeSearchMatchObject.prototype.__proto__ = WebInspector.Object.prototype;
index 6bbc0d6..435ba20 100644 (file)
@@ -323,6 +323,10 @@ WebInspector.ResourceSidebarPanel.prototype = {
         this.filterBar.placeholder = WebInspector.UIString("Filter Search Results");
         this.contentTreeOutline = this._searchContentTreeOutline;
 
+        // FIXME: Provide UI to toggle regex and case sensitive searches.
+        var isCaseSensitive = false;
+        var isRegex = false;
+
         var updateEmptyContentPlaceholderTimeout = null;
 
         function updateEmptyContentPlaceholderSoon()
@@ -342,6 +346,14 @@ WebInspector.ResourceSidebarPanel.prototype = {
             this.updateEmptyContentPlaceholder(WebInspector.UIString("No Search Results"));
         }
 
+        function forEachMatch(searchTerm, lineContent, callback)
+        {
+            var lineMatch;
+            var searchRegex = new RegExp(searchTerm.escapeForRegExp(), "gi");
+            while ((searchRegex.lastIndex < lineContent.length) && (lineMatch = searchRegex.exec(lineContent)))
+                callback(lineMatch, searchRegex.lastIndex);
+        }
+
         function resourcesCallback(error, result)
         {
             updateEmptyContentPlaceholderSoon.call(this);
@@ -349,45 +361,74 @@ WebInspector.ResourceSidebarPanel.prototype = {
             if (error)
                 return;
 
+            function resourceCallback(url, error, resourceMatches)
+            {
+                updateEmptyContentPlaceholderSoon.call(this);
+
+                if (error || !resourceMatches || !resourceMatches.length)
+                    return;
+
+                var frame = WebInspector.frameResourceManager.frameForIdentifier(searchResult.frameId);
+                if (!frame)
+                    return;
+
+                var resource = frame.url === url ? frame.mainResource : frame.resourceForURL(url);
+                if (!resource)
+                    return;
+
+                var resourceTreeElement = this._searchTreeElementForResource(resource);
+
+                for (var i = 0; i < resourceMatches.length; ++i) {
+                    var match = resourceMatches[i];
+                    forEachMatch(searchTerm, match.lineContent, function(lineMatch, lastIndex) {
+                        var matchObject = new WebInspector.SourceCodeSearchMatchObject(resource, match.lineContent, searchTerm, new WebInspector.TextRange(match.lineNumber, lineMatch.index, match.lineNumber, lastIndex));
+                        var matchTreeElement = new WebInspector.SearchResultTreeElement(matchObject);
+                        resourceTreeElement.appendChild(matchTreeElement);
+                    });
+                }
+
+                updateEmptyContentPlaceholder.call(this);
+            }
+
             for (var i = 0; i < result.length; ++i) {
                 var searchResult = result[i];
                 if (!searchResult.url || !searchResult.frameId)
                     continue;
 
-                function resourceCallback(url, error, resourceMatches)
-                {
-                    updateEmptyContentPlaceholderSoon.call(this);
-
-                    if (error || !resourceMatches || !resourceMatches.length)
-                        return;
+                PageAgent.searchInResource(searchResult.frameId, searchResult.url, searchTerm, isCaseSensitive, isRegex, resourceCallback.bind(this, searchResult.url));
+            }
+        }
 
-                    var frame = WebInspector.frameResourceManager.frameForIdentifier(searchResult.frameId);
-                    if (!frame)
-                        return;
+        function searchScripts(scriptsToSearch)
+        {
+            updateEmptyContentPlaceholderSoon.call(this);
 
-                    var resource = frame.url === url ? frame.mainResource : frame.resourceForURL(url);
-                    if (!resource)
-                        return;
+            if (!scriptsToSearch.length)
+                return;
 
-                    var resourceTreeElement = this._searchTreeElementForResource(resource);
+            function scriptCallback(script, error, scriptMatches)
+            {
+                updateEmptyContentPlaceholderSoon.call(this);
 
-                    for (var i = 0; i < resourceMatches.length; ++i) {
-                        var match = resourceMatches[i];
+                if (error || !scriptMatches || !scriptMatches.length)
+                    return;
 
-                        var lineMatch;
-                        var searchRegex = new RegExp(searchTerm.escapeForRegExp(), "gi");
-                        while ((searchRegex.lastIndex < match.lineContent.length) && (lineMatch = searchRegex.exec(match.lineContent))) {
-                            var matchObject = new WebInspector.ResourceSearchMatchObject(resource, match.lineContent, searchTerm, new WebInspector.TextRange(match.lineNumber, lineMatch.index, match.lineNumber, searchRegex.lastIndex));
-                            var matchTreeElement = new WebInspector.SearchResultTreeElement(matchObject);
-                            resourceTreeElement.appendChild(matchTreeElement);
-                        }
-                    }
+                var scriptTreeElement = this._searchTreeElementForScript(script);
 
-                    updateEmptyContentPlaceholder.call(this);
+                for (var i = 0; i < scriptMatches.length; ++i) {
+                    var match = scriptMatches[i];
+                    forEachMatch(searchTerm, match.lineContent, function(lineMatch, lastIndex) {
+                        var matchObject = new WebInspector.SourceCodeSearchMatchObject(script, match.lineContent, searchTerm, new WebInspector.TextRange(match.lineNumber, lineMatch.index, match.lineNumber, lastIndex));
+                        var matchTreeElement = new WebInspector.SearchResultTreeElement(matchObject);
+                        scriptTreeElement.appendChild(matchTreeElement);
+                    });
                 }
 
-                PageAgent.searchInResource(searchResult.frameId, searchResult.url, searchTerm, false, false, resourceCallback.bind(this, searchResult.url));
+                updateEmptyContentPlaceholder.call(this);
             }
+
+            for (var script of scriptsToSearch)
+                DebuggerAgent.searchInContent(script.id, searchTerm, isCaseSensitive, isRegex, scriptCallback.bind(this, script));
         }
 
         function domCallback(error, searchId, resultsCount)
@@ -419,25 +460,22 @@ WebInspector.ResourceSidebarPanel.prototype = {
                     if (domNode.nodeType() === Node.DOCUMENT_NODE)
                         continue;
 
-                    // FIXME: Use this should use a frame to do resourceForURL, but DOMAgent does not provide a frameId.
+                    // FIXME: This should use a frame to do resourceForURL, but DOMAgent does not provide a frameId.
                     var resource = WebInspector.frameResourceManager.resourceForURL(domNode.ownerDocument.documentURL);
                     if (!resource)
                         continue;
 
                     var resourceTreeElement = this._searchTreeElementForResource(resource);
-
                     var domNodeTitle = WebInspector.DOMSearchMatchObject.titleForDOMNode(domNode);
-                    var searchRegex = new RegExp(searchTerm.escapeForRegExp(), "gi");
 
                     // Textual matches.
-                    var lineMatch;
                     var didFindTextualMatch = false;
-                    while ((searchRegex.lastIndex < domNodeTitle.length) && (lineMatch = searchRegex.exec(domNodeTitle))) {
-                        var matchObject = new WebInspector.DOMSearchMatchObject(resource, domNode, domNodeTitle, searchTerm, new WebInspector.TextRange(0, lineMatch.index, 0, searchRegex.lastIndex));
+                    forEachMatch(searchTerm, domNodeTitle, function(lineMatch, lastIndex) {
+                        var matchObject = new WebInspector.DOMSearchMatchObject(resource, domNode, domNodeTitle, searchTerm, new WebInspector.TextRange(0, lineMatch.index, 0, lastIndex));
                         var matchTreeElement = new WebInspector.SearchResultTreeElement(matchObject);
                         resourceTreeElement.appendChild(matchTreeElement);
                         didFindTextualMatch = true;
-                    }
+                    });
 
                     // Non-textual matches are CSS Selector or XPath matches. In such cases, display the node entirely highlighted.
                     if (!didFindTextualMatch) {
@@ -456,9 +494,10 @@ WebInspector.ResourceSidebarPanel.prototype = {
         if (window.DOMAgent)
             WebInspector.domTreeManager.requestDocument();
 
-        // FIXME: Should we be searching for regexes or just plain text?
         if (window.PageAgent)
-            PageAgent.searchInResources(searchTerm, false, false, resourcesCallback.bind(this));
+            PageAgent.searchInResources(searchTerm, isCaseSensitive, isRegex, resourcesCallback.bind(this));
+
+        setTimeout(searchScripts.bind(this, this._scriptsToSearch()), 0);
 
         if (window.DOMAgent) {
             if ("_domSearchIdentifier" in this) {
@@ -491,9 +530,6 @@ WebInspector.ResourceSidebarPanel.prototype = {
 
     _searchTreeElementForResource: function(resource)
     {
-        // FIXME: This should take a frame ID (if one is available) - so we can differentiate between multiple resources
-        // with the same URL.
-
         var resourceTreeElement = this._searchContentTreeOutline.getCachedTreeElement(resource);
         if (!resourceTreeElement) {
             resourceTreeElement = new WebInspector.ResourceTreeElement(resource);
@@ -506,6 +542,20 @@ WebInspector.ResourceSidebarPanel.prototype = {
         return resourceTreeElement;
     },
 
+    _searchTreeElementForScript: function(script)
+    {
+        var scriptTreeElement = this._searchContentTreeOutline.getCachedTreeElement(script);
+        if (!scriptTreeElement) {
+            scriptTreeElement = new WebInspector.ScriptTreeElement(script);
+            scriptTreeElement.hasChildren = true;
+            scriptTreeElement.expand();
+
+            this._searchContentTreeOutline.appendChild(scriptTreeElement);
+        }
+
+        return scriptTreeElement;
+    },
+
     _focusSearchField: function(keyboardShortcut, event)
     {
         this.show();
@@ -670,6 +720,33 @@ WebInspector.ResourceSidebarPanel.prototype = {
         }
     },
 
+    _scriptsToSearch: function(event)
+    {
+        var nonResourceScripts = [];
+
+        function collectFromTreeElement(folderTreeElement)
+        {
+            if (!folderTreeElement)
+                return;
+
+            var children = folderTreeElement.children;
+            for (var treeElement of children) {
+                if (treeElement instanceof WebInspector.ScriptTreeElement)
+                    nonResourceScripts.push(treeElement.script);
+            }
+        }
+
+        if (WebInspector.debuggableType === WebInspector.DebuggableType.JavaScript && !WebInspector.hasExtraDomains)
+            collectFromTreeElement(this._resourcesContentTreeOutline);
+        else {
+            collectFromTreeElement(this._extensionScriptsFolderTreeElement);
+            collectFromTreeElement(this._extraScriptsFolderTreeElement);
+            collectFromTreeElement(this._anonymousScriptsFolderTreeElement);
+        }
+
+        return nonResourceScripts;
+    },
+
     _treeElementSelected: function(treeElement, selectedByUser)
     {
         if (treeElement instanceof WebInspector.FolderTreeElement || treeElement instanceof WebInspector.DatabaseHostTreeElement ||
@@ -691,7 +768,7 @@ WebInspector.ResourceSidebarPanel.prototype = {
 
         if (treeElement.representedObject instanceof WebInspector.DOMSearchMatchObject)
             this.showMainFrameDOMTree(treeElement.representedObject.domNode, true);
-        else if (treeElement.representedObject instanceof WebInspector.ResourceSearchMatchObject)
+        else if (treeElement.representedObject instanceof WebInspector.SourceCodeSearchMatchObject)
             this.showOriginalOrFormattedSourceCodeTextRange(treeElement.representedObject.sourceCodeTextRange);
     },
 
index a4f2238..d1bf678 100644 (file)
@@ -47,6 +47,6 @@
     content: url(../Images/DOMNode.svg);
 }
 
-.resource-match-icon .icon {
+.source-code-match-icon .icon {
     content: url(../Images/ResultLine.svg);
 }
index 3a35fe9..67a38e5 100644 (file)
@@ -25,7 +25,7 @@
 
 WebInspector.SearchResultTreeElement = function(representedObject)
 {
-    console.assert(representedObject instanceof WebInspector.DOMSearchMatchObject || representedObject instanceof WebInspector.ResourceSearchMatchObject);
+    console.assert(representedObject instanceof WebInspector.DOMSearchMatchObject || representedObject instanceof WebInspector.SourceCodeSearchMatchObject);
 
     var title = WebInspector.SearchResultTreeElement.truncateAndHighlightTitle(representedObject.title, representedObject.searchTerm, representedObject.sourceCodeTextRange);
 
index 958cd0c..45d24d9 100644 (file)
     <None Include="..\UserInterface\ResourceContentView.js" />
     <None Include="..\UserInterface\ResourceDetailsSidebarPanel.js" />
     <None Include="..\UserInterface\ResourceIcons.css" />
-    <None Include="..\UserInterface\ResourceSearchMatchObject.js" />
     <None Include="..\UserInterface\ResourceSidebarPanel.css" />
     <None Include="..\UserInterface\ResourceSidebarPanel.js" />
     <None Include="..\UserInterface\ResourceTimelineDataGridNode.js" />
     <None Include="..\UserInterface\SourceCodeLocation.js" />
     <None Include="..\UserInterface\SourceCodePosition.js" />
     <None Include="..\UserInterface\SourceCodeRevision.js" />
+    <None Include="..\UserInterface\SourceCodeSearchMatchObject.js" />
     <None Include="..\UserInterface\SourceCodeTextEditor.css" />
     <None Include="..\UserInterface\SourceCodeTextEditor.js" />
     <None Include="..\UserInterface\SourceCodeTextRange.js" />
index 069e482..8c0d791 100644 (file)
     <None Include="..\UserInterface\ResourceIcons.css">
       <Filter>UserInterface</Filter>
     </None>
-    <None Include="..\UserInterface\ResourceSearchMatchObject.js">
-      <Filter>UserInterface</Filter>
-    </None>
     <None Include="..\UserInterface\ResourceSidebarPanel.css">
       <Filter>UserInterface</Filter>
     </None>
     <None Include="..\UserInterface\SourceCodeRevision.js">
       <Filter>UserInterface</Filter>
     </None>
+    <None Include="..\UserInterface\SourceCodeSearchMatchObject.js">
+      <Filter>UserInterface</Filter>
+    </None>
     <None Include="..\UserInterface\SourceCodeTextEditor.css">
       <Filter>UserInterface</Filter>
     </None>