jsExecutionTransformer.js 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. var debug = require('debug')('ylt:jsExecutionTransformer');
  2. var offendersHelpers = require('../offendersHelpers');
  3. var jsExecutionTransformer = function() {
  4. this.transform = function(data) {
  5. var javascriptExecutionTree = {};
  6. debug('Starting JS execution transformation');
  7. try {
  8. javascriptExecutionTree = JSON.parse(data.toolsResults.phantomas.offenders.javascriptExecutionTree[0]);
  9. if (javascriptExecutionTree.children) {
  10. javascriptExecutionTree.children.forEach(function(node) {
  11. // Mark abnormal things with a warning flag
  12. var contextLenght = (node.data.callDetails && node.data.callDetails.context) ? node.data.callDetails.context.length : null;
  13. if ((node.data.type === 'jQuery - bind' && contextLenght > 5) ||
  14. node.data.resultsNumber === 0 ||
  15. contextLenght === 0) {
  16. node.warning = true;
  17. }
  18. // Mark errors with an error flag
  19. if (node.data.type === 'error' || node.data.type === 'jQuery version change') {
  20. node.error = true;
  21. }
  22. // Mark a performance flag
  23. if (['domInteractive', 'domContentLoaded', 'domContentLoadedEnd', 'domComplete'].indexOf(node.data.type) >= 0) {
  24. node.windowPerformance = true;
  25. }
  26. // Read the execution tree and adjust the navigation timings (cause their not very well synchronised)
  27. switch(node.data.type) {
  28. case 'domInteractive':
  29. data.toolsResults.phantomas.metrics.domInteractive = node.data.timestamp;
  30. break;
  31. case 'domContentLoaded':
  32. data.toolsResults.phantomas.metrics.domContentLoaded = node.data.timestamp;
  33. break;
  34. case 'domContentLoadedEnd':
  35. data.toolsResults.phantomas.metrics.domContentLoadedEnd = node.data.timestamp;
  36. break;
  37. case 'domComplete':
  38. data.toolsResults.phantomas.metrics.domComplete = node.data.timestamp;
  39. break;
  40. }
  41. // Change the list of dom paths into a tree
  42. treeRecursiveParser(node, function(node) {
  43. if (node.data.callDetails && node.data.callDetails.context && node.data.callDetails.context.length > 0) {
  44. node.data.callDetails.context.elements = node.data.callDetails.context.elements.map(offendersHelpers.domPathToDomElementObj, offendersHelpers);
  45. }
  46. if (node.data.type === 'appendChild' || node.data.type === 'insertBefore') {
  47. node.data.callDetails.arguments[0] = offendersHelpers.domPathToDomElementObj(node.data.callDetails.arguments[0]);
  48. }
  49. if (node.data.type === 'insertBefore') {
  50. node.data.callDetails.arguments[1] = offendersHelpers.domPathToDomElementObj(node.data.callDetails.arguments[1]);
  51. }
  52. });
  53. });
  54. }
  55. debug('JS execution transformation complete');
  56. } catch(err) {
  57. throw err;
  58. }
  59. return javascriptExecutionTree;
  60. };
  61. function treeRecursiveParser(node, fn) {
  62. if (node.children) {
  63. node.children.forEach(function(child) {
  64. treeRecursiveParser(child, fn);
  65. });
  66. }
  67. fn(node);
  68. }
  69. };
  70. module.exports = new jsExecutionTransformer();