Separate offender analyze, parsing in the core, display in the front

This commit is contained in:
Gaël Métais
2015-01-26 11:34:38 +01:00
parent d829525ab8
commit 901116fde6
17 changed files with 1436 additions and 563 deletions
+527 -321
View File
File diff suppressed because it is too large Load Diff
+44 -58
View File
@@ -31,70 +31,69 @@ var OffendersHelpers = function() {
return result;
};
this.domTreeToHTML = function(domTree) {
function recursiveHtmlBuilder(tree) {
var html = '';
var keys = Object.keys(tree);
keys.forEach(function(key) {
if (isNaN(tree[key])) {
html += '<div><span>' + key + '</span>' + recursiveHtmlBuilder(tree[key]) + '</div>';
} else if (tree[key] > 1) {
html += '<div><span>' + key + ' <span>(x' + tree[key] + ')</span></span></div>';
} else {
html += '<div><span>' + key + '</span></div>';
}
});
return html;
}
return '<div class="domTree">' + recursiveHtmlBuilder(domTree) + '</div>';
};
this.listOfDomPathsToHTML = function(domPaths) {
var domArrays = domPaths.map(this.domPathToArray);
var domTree = this.listOfDomArraysToTree(domArrays);
return this.domTreeToHTML(domTree);
};
this.domPathToButton = function(domPath) {
this.domPathToDomElementObj = function(domPath) {
var domArray = this.domPathToArray(domPath);
var domTree = this.listOfDomPathsToHTML([domPath]);
var domTree = this.listOfDomArraysToTree([this.domPathToArray(domPath)]);
if (domArray[0] === 'html') {
return '<div class="offenderButton"><b>html</b></div>';
return {
type: 'html'
};
}
if (domArray[0] === 'body') {
if (domArray.length === 1) {
return '<div class="offenderButton"><b>body</b></div>';
return {
type: 'body'
};
} else {
return '<div class="offenderButton opens">DOM element <b>' + domArray[domArray.length - 1] + '</b>' + domTree + '</div>';
return {
type: 'domElement',
element: domArray[domArray.length - 1],
tree: domTree
};
}
}
if (domArray[0] === 'head') {
return '<div class="offenderButton"><b>head</b></div>';
return {
type: 'head'
};
}
if (domArray[0] === '#document') {
return '<div class="offenderButton"><b>document</b></div>';
return {
type: 'document'
};
}
if (domArray[0] === 'window') {
return '<div class="offenderButton"><b>window</b></div>';
return {
type: 'window'
};
}
if (domArray[0] === 'DocumentFragment') {
if (domArray.length === 1) {
return '<div class="offenderButton">Fragment</div>';
return {
type: 'fragment'
};
} else {
return '<div class="offenderButton opens">Fragment element <b>' + domArray[domArray.length - 1] + '</b>' + domTree + '</div>';
return {
type: 'fragmentElement',
element: domArray[domArray.length - 1],
tree: domTree
};
}
}
// Not attached element, such as just created with document.createElement()
if (domArray.length === 1) {
return '<div class="offenderButton">Created element <b>' + domPath + '</b></div>';
return {
type: 'createdElement',
element: domPath
};
} else {
return '<div class="offenderButton opens">Created element <b>' + domArray[domArray.length - 1] + '</b>' + domTree + '</div>';
return {
type: 'createdElement',
element: domArray[domArray.length - 1],
tree: domTree
};
}
};
@@ -130,20 +129,6 @@ var OffendersHelpers = function() {
}
};
this.backtraceArrayToHtml = function(backtraceArray) {
if (backtraceArray.length === 0) {
return '<div class="offenderButton">no backtrace</div>';
}
var html = '<div class="offenderButton opens">backtrace<div class="backtrace">';
var that = this;
backtraceArray.forEach(function(backtraceObj) {
var functionName = (backtraceObj.functionName) ? backtraceObj.functionName + '() ' : '';
html += '<div>' + functionName + that.urlToLink(backtraceObj.file) + ' line ' + backtraceObj.line + '</div>';
});
return html + '</div></div>';
};
this.sortVarsLikeChromeDevTools = function(vars) {
return vars.sort(function(a, b) {
@@ -157,7 +142,7 @@ var OffendersHelpers = function() {
};
this.cssOffenderPattern = function(offender) {
var parts = /^(.*) @ (\d+):(\d+)$/.exec(offender);
var parts = /^(.*) (?:<([^ \(]*)>|\[inline CSS\]) @ (\d+):(\d+)$/.exec(offender);
if (!parts) {
return {
@@ -165,9 +150,10 @@ var OffendersHelpers = function() {
};
} else {
return {
offender: parts[1],
line: parseInt(parts[2], 10),
character: parseInt(parts[3], 10)
css: parts[1],
file: parts[2] || null,
line: parseInt(parts[3], 10),
column: parseInt(parts[4], 10)
};
}
};
+50 -38
View File
@@ -26,52 +26,64 @@ var RulesChecker = function() {
policy: extend({}, policy) // Clone object policy instead of reference
};
var offenders = [];
// Take DOMqueriesAvoidable's offenders from DOMqueriesDuplicated, for example.
if (policy.takeOffendersFrom) {
var fromList = policy.takeOffendersFrom;
// takeOffendersFrom option can be a string or an array of strings.
if (typeof fromList === 'string') {
fromList = [fromList];
}
fromList.forEach(function(from) {
if (data.toolsResults[policy.tool] &&
data.toolsResults[policy.tool].offenders &&
data.toolsResults[policy.tool].offenders[from]) {
offenders = offenders.concat(data.toolsResults[policy.tool].offenders[from]);
// Deal with offenders
if (policy.hasOffenders) {
var offenders = [];
// Take DOMqueriesAvoidable's offenders from DOMqueriesDuplicated, for example.
if (policy.takeOffendersFrom) {
var fromList = policy.takeOffendersFrom;
// takeOffendersFrom option can be a string or an array of strings.
if (typeof fromList === 'string') {
fromList = [fromList];
}
});
fromList.forEach(function(from) {
if (data.toolsResults[policy.tool] &&
data.toolsResults[policy.tool].offenders &&
data.toolsResults[policy.tool].offenders[from]) {
offenders = offenders.concat(data.toolsResults[policy.tool].offenders[from]);
}
});
data.toolsResults[policy.tool].offenders[metricName] = offenders;
data.toolsResults[policy.tool].offenders[metricName] = offenders;
} else if (data.toolsResults[policy.tool] &&
data.toolsResults[policy.tool].offenders &&
data.toolsResults[policy.tool].offenders[metricName]) {
offenders = data.toolsResults[policy.tool].offenders[metricName];
}
// It is possible to declare a transformation function for the offenders.
// The function should take an array of strings as single parameter and return a string.
if (policy.offendersTransformFn) {
rule.offendersCount = offenders.length;
try {
offenders = policy.offendersTransformFn(offenders);
} catch(err) {
debug('Error while transforming offenders for %s', metricName);
debug(err);
} else if (data.toolsResults[policy.tool] &&
data.toolsResults[policy.tool].offenders &&
data.toolsResults[policy.tool].offenders[metricName]) {
offenders = data.toolsResults[policy.tool].offenders[metricName];
}
var offendersObj = {};
delete rule.policy.offendersTransformFn;
// It is possible to declare a transformation function for the offenders.
// The function should take an array of strings as single parameter and return a string.
if (policy.offendersTransformFn) {
try {
offendersObj = policy.offendersTransformFn(offenders);
} catch(err) {
debug('Error while transforming offenders for %s', metricName);
debug(err);
}
delete rule.policy.offendersTransformFn;
} else {
offendersObj = {
count: offenders.length,
list: offenders
};
}
rule.offendersObj = offendersObj;
}
if (offenders && offenders.length > 0) {
rule.offenders = offenders;
}
rule.bad = rule.value > policy.isOkThreshold;
rule.abnormal = policy.isAbnormalThreshold && rule.value >= policy.isAbnormalThreshold;
+2 -1
View File
@@ -40,7 +40,8 @@ var PhantomasWrapper = function() {
'eventListeners', // overridden
'filmStrip', // not needed
'har', // not needed for the moment
'javaScriptBottlenecks', // needs to be launched after custom module scopeYLT,
'javaScriptBottlenecks', // needs to be launched after custom module scopeYLT
'jQuery', // overridden
'jserrors', // overridden
'pageSource', // not needed
'screenshot', // not needed for the moment