New Events Not Delegated rule

This commit is contained in:
Gaël Métais
2015-05-12 09:12:10 +02:00
parent d7d4fb36ad
commit 9bc6d2928b
6 changed files with 78 additions and 18 deletions
+47 -11
View File
@@ -13,16 +13,24 @@ var jsExecutionTransformer = function() {
var metrics = {
DOMaccesses: 0,
DOMaccessesOnScroll: 0,
queriesWithoutResults: 0,
jQueryCalls: 0,
jQueryCallsOnEmptyObject: 0,
jQueryNotDelegatedEvent: 0
queriesWithoutResults: 0
};
var offenders = {
};
var hasjQuery = (data.toolsResults.phantomas.metrics.jQueryVersionsLoaded > 0);
if (hasjQuery) {
metrics.jQueryCalls = 0;
metrics.jQueryFunctionsUsed = 0;
metrics.jQueryCallsOnEmptyObject = 0;
metrics.jQueryNotDelegatedEvents = 0;
offenders.jQueryFunctionsUsed = [];
offenders.jQueryNotDelegatedEvents = [];
}
try {
debug('Starting JS execution transformation');
@@ -31,11 +39,17 @@ var jsExecutionTransformer = function() {
if (javascriptExecutionTree.children) {
javascriptExecutionTree.children.forEach(function(node) {
var contextLenght = (node.data.callDetails && node.data.callDetails.context) ? node.data.callDetails.context.length : null;
var contextLength = (node.data.callDetails && node.data.callDetails.context) ? node.data.callDetails.context.length : null;
if ((node.data.type === 'jQuery - bind' || node.data.type === 'jQuery - on') && contextLenght > 3) {
metrics.jQueryNotDelegatedEvent += contextLenght - 1;
if (isABindWithoutEventDelegation(node, contextLength)) {
metrics.jQueryNotDelegatedEvents += contextLength;
offenders.jQueryNotDelegatedEvents.push({
functionName: node.data.type.substring(9),
contextLength: contextLength,
backtrace: offendersHelpers.backtraceToArray(node.data.backtrace)
});
node.warning = true;
node.eventNotDelegated = true;
}
if (node.data.resultsNumber === 0) {
@@ -43,7 +57,7 @@ var jsExecutionTransformer = function() {
node.warning = true;
}
if (contextLenght === 0) {
if (contextLength === 0) {
metrics.jQueryCallsOnEmptyObject ++;
node.warning = true;
}
@@ -87,9 +101,7 @@ var jsExecutionTransformer = function() {
});
// Count the number of different jQuery functions called
if (data.toolsResults.phantomas.metrics.jQueryVersionsLoaded) {
metrics.jQueryFunctionsUsed = 0;
offenders.jQueryFunctionsUsed = [];
if (hasjQuery) {
jQueryFunctionsCollection.sort().forEach(function(fnName, cnt) {
if (fnName === 'jQuery - find') {
@@ -181,6 +193,30 @@ var jsExecutionTransformer = function() {
return count;
}
function isPureString(str) {
return typeof str === 'string' && str[0] !== '{' && str !== '(function)' && str !== '[Object]' && str !== '[Array]' && str !== 'true' && str !== 'false' && str !== 'undefined' && str !== 'unknown' && str !== 'null';
}
function isABindWithoutEventDelegation(node, contextLength) {
// Count only on larger bindings
if (contextLength <= 3) {
return false;
}
if (node.data.type === 'jQuery - on' && node.data.callDetails.arguments[1] && !isPureString(node.data.callDetails.arguments[1])) {
return true;
}
if (node.data.type.indexOf('jQuery - ') === 0 && node.children && node.children.length === 1) {
var child = node.children[0];
if (child.data.type === 'jQuery - on' && child.data.callDetails.arguments[1] && !isPureString(child.data.callDetails.arguments[1])) {
return true;
}
}
return false;
}
};
module.exports = new jsExecutionTransformer();