Skip to content

Commit

Permalink
Fix search through draw panel.
Browse files Browse the repository at this point in the history
  • Loading branch information
Marco Minetti committed Jul 14, 2015
1 parent df57cd8 commit 47b25d6
Show file tree
Hide file tree
Showing 7 changed files with 320 additions and 1 deletion.
1 change: 1 addition & 0 deletions front-end-node/inspector.json
Expand Up @@ -5,6 +5,7 @@
{ "name": "node/settings", "type": "autostart" },
{ "name": "node/sources", "type": "autostart" },
{ "name": "node/console", "type": "autostart" },
{ "name": "node/search", "type": "autostart" },
{ "name": "node/main", "type": "autostart" },
{ "name": "platform", "type": "autostart" },
{ "name": "main", "type": "autostart" },
Expand Down
103 changes: 103 additions & 0 deletions front-end-node/search/SearchOverrides.js
@@ -0,0 +1,103 @@
/*jshint browser:true, nonew:false*/
/*global WebInspector:true, InspectorFrontendHost:true, InspectorFrontendHostAPI:true*/

(function() {
var createSearchRegex = function(query, caseSensitive, isRegex)
{
var regexFlags = caseSensitive ? "g" : "gi";
var regexObject;

if (isRegex) {
try {
regexObject = new RegExp('^.*?'+query+'.*?$|^.*?'+query+'.*?\n|\n.*?'+query+'.*?\n|\n.*?'+query+'.*?$', regexFlags);
} catch (e) {
// Silent catch.
}
}

if (!regexObject)
regexObject = createPlainTextSearchRegex(query, regexFlags);

return regexObject;
}

var createPlainTextSearchRegex = function(query, flags)
{
// This should be kept the same as the one in ContentSearchUtils.cpp.
var regexSpecialCharacters = "^[]{}()\\.^$*+?|-,";
var regex = "";
for (var i = 0; i < query.length; ++i) {
var c = query.charAt(i);
if (regexSpecialCharacters.indexOf(c) != -1)
regex += "\\";
regex += c;
}
return new RegExp('^.*?'+regex+'.*?$|^.*?'+regex+'.*?\n|\n.*?'+regex+'.*?\n|\n.*?'+regex+'.*?$', flags || "");
}

// performSearchInContent is based on /front-end/common/ContentProvider.js implementation
WebInspector.ContentProvider.performSearchInContent = function(content, query, caseSensitive, isRegex)
{
var regex = createSearchRegex(query, caseSensitive, isRegex);

var isMinified = false;

var firstNewLine = content.indexOf('\n');
if (content.length > 1024) {
if (firstNewLine > 1024 || firstNewLine === -1) {
isMinified = true;
}
}

var contentString = new String(content);
var result = [];
for (var i = 0; i < contentString.lineCount(); ++i) {
var lineContent = contentString.lineAt(i);
regex.lastIndex = 0;
if (regex.exec(lineContent)) {
result.push(new WebInspector.ContentProvider.SearchMatch(i, lineContent));
}
}
return result;
}

// _performSearchInContent tries to use regexp to gain performance
/*WebInspector.ContentProvider._performSearchInContent = function(content, query, caseSensitive, isRegex)
{
var regex = createSearchRegex(query, caseSensitive, isRegex);
var result = [];
var lastMatch;
var isMinified = false;
var firstNewLine = content.indexOf('\n');
if (content.length > 1024) {
if (firstNewLine > 1024 || firstNewLine === -1) {
isMinified = true;
}
}
while(lastMatch=regex.exec(content)) {
var lineContent = lastMatch[0];
var firstChar = lineContent.charCodeAt(0);
var lastChar = lineContent.charCodeAt(lineContent.length-1);
var lineMatchesBefore = content.substr(0,regex.lastIndex).match(/\n/g);
if (lineMatchesBefore){
var i = lineMatchesBefore.length;
if (lastChar !== 10){
++i;
} else {
lineContent = lineContent.substr(0,lineContent.length-1);
}
if (firstChar === 10){
lineContent = lineContent.substr(1);
}
if (isMinified === true && lineContent.length > 1024) {
lineContent = ' ... (line too long)';
}
result.push(new WebInspector.ContentProvider.SearchMatch(i-1, lineContent));
}
}
return result;
}*/
})()
9 changes: 9 additions & 0 deletions front-end-node/search/module.json
@@ -0,0 +1,9 @@
{
"dependencies": [
"sources",
"console"
],
"scripts": [
"SearchOverrides.js"
]
}
17 changes: 17 additions & 0 deletions lib/DebuggerAgent.js
Expand Up @@ -5,6 +5,7 @@ var convert = require('./convert.js'),
format = require('util').format,
path = require('path'),
async = require('async'),
search = require('./search.js'),
ScriptFileStorage = require('./ScriptFileStorage').ScriptFileStorage;

/**
Expand Down Expand Up @@ -510,6 +511,22 @@ DebuggerAgent.prototype = {
done(new Error('Not implemented.'));
else
done();
},

searchInContent: function(params, done) {

function initSearch(content) {
if (content) {
done(null, {result: search.performSearchInContent(content, params.query, params.caseSensitive, params.isRegex)});
} else {
done(null, {result: []});
}
}

this._scriptManager.getScriptSourceById(Number(params.scriptId), function (err, data) {
if (err) return done(null, {result: []});
initSearch(data.scriptSource);
});
}
};

Expand Down
17 changes: 17 additions & 0 deletions lib/PageAgent.js
Expand Up @@ -6,6 +6,7 @@ var fs = require('fs'),
EventEmitter = require('events').EventEmitter,
async = require('async'),
convert = require('./convert.js'),
search = require('./search.js'),
ScriptFileStorage = require('./ScriptFileStorage.js').ScriptFileStorage;


Expand Down Expand Up @@ -186,6 +187,22 @@ extend(PageAgent.prototype, {
reload: function(params, done) {
// This is called when user press Cmd+R (F5?), do we want to perform an action on this?
done();
},

searchInResource: function(params, done){

function initSearch(content){
if (content) {
done(null,{ result: search.performSearchInContent(content, params.query, params.caseSensitive, params.isRegex) });
} else {
done(null,{ result: [] });
}
}

this.getResourceContent({ url: params.url }, function(err,data){
if (err) return done(null,{ result: [] });
initSearch(data.content);
});
}
});

Expand Down
2 changes: 1 addition & 1 deletion lib/ScriptManager.js
Expand Up @@ -143,7 +143,7 @@ ScriptManager.prototype = Object.create(events.EventEmitter.prototype, {
this._debuggerClient.request(
'scripts',
{
includeSource: false,
includeSource: true,
filter: id
},
function(error, scripts) {
Expand Down
172 changes: 172 additions & 0 deletions lib/search.js
@@ -0,0 +1,172 @@
// code extracted and adapted from /front-end/platform/utilities.js
// performSearchInContent is based on /front-end/common/ContentProvider.js implementation
// _performSearchInContent tries to use regexp to gain performance


var findAll = function(content, string)
{
var matches = [];
var i = content.indexOf(string);
while (i !== -1) {
matches.push(i);
i = content.indexOf(string, i + string.length);
}
return matches;
}

var getlineEndings = function(content)
{
var _lineEndings = findAll(content, "\n");
_lineEndings.push(content.length);
return _lineEndings;
}

var getlineAt = function(content, lineNumber, lineEndings) {
var lineStart = lineNumber > 0 ? lineEndings[lineNumber - 1] + 1 : 0;
var lineEnd = lineEndings[lineNumber];
var lineContent = content.substring(lineStart, lineEnd);
if (lineContent.length > 0 && lineContent.charAt(lineContent.length - 1) === "\r")
lineContent = lineContent.substring(0, lineContent.length - 1);
return lineContent;
}

var createSearchRegex = function(query, caseSensitive, isRegex)
{
var regexFlags = caseSensitive ? "g" : "gi";
var regexObject;

if (isRegex) {
try {
regexObject = new RegExp(query, regexFlags);
} catch (e) {
// Silent catch.
}
}

if (!regexObject)
regexObject = createPlainTextSearchRegex(query, regexFlags);

return regexObject;
}

var createPlainTextSearchRegex = function(query, flags)
{
// This should be kept the same as the one in ContentSearchUtils.cpp.
var regexSpecialCharacters = "^[]{}()\\.^$*+?|-,";
var regex = "";
for (var i = 0; i < query.length; ++i) {
var c = query.charAt(i);
if (regexSpecialCharacters.indexOf(c) != -1)
regex += "\\";
regex += c;
}
return new RegExp(regex, flags || "");
}

exports.performSearchInContent = function(content, query, caseSensitive, isRegex)
{
var regex = createSearchRegex(query, caseSensitive, isRegex);

var isMinified = false;

var firstNewLine = content.indexOf('\n');
if (content.length > 1024) {
if (firstNewLine > 1024 || firstNewLine === -1) {
isMinified = true;
}
}

var result = [];
var lineEndings = getlineEndings(content);
var lineCount = lineEndings.length;
for (var i = 0; i < lineCount; ++i) {
var lineContent = getlineAt(content, i, lineEndings);
regex.lastIndex = 0;
if (regex.exec(lineContent)) {
if (isMinified === true && lineContent.length > 1024) {
lineContent = ' ... (line too long)';
}
result.push(new SearchMatch(i, lineContent));
}
}
return result;
}

var SearchMatch = function(lineNumber, lineContent) {
this.lineNumber = lineNumber;
this.lineContent = lineContent;
}

var _createSearchRegex = function(query, caseSensitive, isRegex)
{
var regexFlags = caseSensitive ? "g" : "gi";
var regexObject;

if (isRegex) {
try {
regexObject = new RegExp('^.*?'+query+'.*?$|^.*?'+query+'.*?\n|\n.*?'+query+'.*?\n|\n.*?'+query+'.*?$', regexFlags);
} catch (e) {
// Silent catch.
}
}

if (!regexObject)
regexObject = _createPlainTextSearchRegex(query, regexFlags);

return regexObject;
}

var _createPlainTextSearchRegex = function(query, flags)
{
// This should be kept the same as the one in ContentSearchUtils.cpp.
var regexSpecialCharacters = "^[]{}()\\.^$*+?|-,";
var regex = "";
for (var i = 0; i < query.length; ++i) {
var c = query.charAt(i);
if (regexSpecialCharacters.indexOf(c) != -1)
regex += "\\";
regex += c;
}
return new RegExp('^.*?'+regex+'.*?$|^.*?'+regex+'.*?\n|\n.*?'+regex+'.*?\n|\n.*?'+regex+'.*?$', flags || "");
}

exports._performSearchInContent = function(content, query, caseSensitive, isRegex)
{
var regex = _createSearchRegex(query, caseSensitive, isRegex);

var result = [];
var lastMatch;
var isMinified = false;

var firstNewLine = content.indexOf('\n');
if (content.length > 1024) {
if (firstNewLine > 1024 || firstNewLine === -1) {
isMinified = true;
}
}

while(lastMatch=regex.exec(content)) {
var lineContent = lastMatch[0];
var firstChar = lineContent.charCodeAt(0);
var lastChar = lineContent.charCodeAt(lineContent.length-1);
var lineMatchesBefore = content.substr(0,regex.lastIndex).match(/\n/g);
if (lineMatchesBefore){
var i = lineMatchesBefore.length;
if (lastChar !== 10){
++i;
} else {
lineContent = lineContent.substr(0,lineContent.length-1);
}
if (firstChar === 10){
lineContent = lineContent.substr(1);
}
if (isMinified === true && lineContent.length > 1024) {
lineContent = ' ... (line too long)';
}
result.push(new SearchMatch(i-1, lineContent));
}
}
return result;
}

//exports.performSearchInContent = exports._performSearchInContent;

0 comments on commit 47b25d6

Please sign in to comment.