scopeYLT.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /**
  2. * Overwritting the original spying functions in scope.js
  3. * This is done so we now have a before AND an after callback on the spy
  4. *
  5. * @see http://code.jquery.com/jquery-1.10.2.js
  6. * @see http://code.jquery.com/jquery-2.0.3.js
  7. */
  8. /* global document: true, window: true */
  9. exports.version = '0.1';
  10. exports.module = function(phantomas) {
  11. 'use strict';
  12. phantomas.once('init', function() {
  13. phantomas.evaluate(function(deepAnalysis) {
  14. (function(phantomas) {
  15. // Overwritting phantomas spy function
  16. (function() {
  17. var enabled = true;
  18. // turn off spying to not include internal phantomas actions
  19. function spyEnabled(state, reason) {
  20. enabled = (state === true);
  21. phantomas.log('Spying ' + (enabled ? 'enabled' : 'disabled') + (reason ? ' - ' + reason : ''));
  22. }
  23. phantomas.log('Overwritting phantomas spy function');
  24. function spy(obj, fn, callbackBefore, callbackAfter) {
  25. var origFn = obj[fn];
  26. if (typeof origFn !== 'function') {
  27. return false;
  28. }
  29. phantomas.log('Attaching a spy to "' + fn + '" function...');
  30. obj[fn] = function() {
  31. var result;
  32. // Before
  33. if (enabled) {
  34. callbackBefore.apply(this, arguments);
  35. }
  36. // Execute
  37. try {
  38. result = origFn.apply(this, arguments);
  39. } catch(e) {
  40. phantomas.log('Error catched on spyed function "' + fn + '"": ' + e);
  41. } finally {
  42. // After
  43. if (enabled && callbackAfter) {
  44. callbackAfter.apply(this, arguments);
  45. }
  46. }
  47. return result;
  48. };
  49. // copy custom properties of original function to the mocked one
  50. Object.keys(origFn).forEach(function(key) {
  51. obj[fn][key] = origFn[key];
  52. });
  53. obj[fn].prototype = origFn.prototype;
  54. return true;
  55. }
  56. phantomas.spyEnabled = spyEnabled;
  57. phantomas.spy = spy;
  58. })();
  59. // Adding some code for the Javascript execution tree construction
  60. (function() {
  61. var root = new ContextTreeNode(null, {type: 'main'});
  62. var currentContext = root;
  63. if (deepAnalysis) {
  64. phantomas.log('Entering deep Javascript analysis mode');
  65. }
  66. var depth = 0;
  67. // Add a child but don't enter his context
  68. function pushContext(data) {
  69. if (depth === 0 || deepAnalysis) {
  70. data.timestamp = Date.now();
  71. currentContext.addChild(data);
  72. }
  73. }
  74. // Add a child to the current context and enter his context
  75. function enterContext(data) {
  76. if (depth === 0 || deepAnalysis) {
  77. data.timestamp = Date.now();
  78. currentContext = currentContext.addChild(data);
  79. }
  80. depth ++;
  81. }
  82. // Save given data in the current context and jump change current context to its parent
  83. function leaveContext() {
  84. if (depth === 1 || deepAnalysis) {
  85. currentContext.data.time = Date.now() - currentContext.data.timestamp;
  86. var parent = currentContext.parent;
  87. if (parent === null) {
  88. console.error('Error: trying to close root context in ContextTree');
  89. } else {
  90. currentContext = parent;
  91. }
  92. }
  93. depth --;
  94. }
  95. function getContextData() {
  96. return currentContext.data;
  97. }
  98. // Returns a clean object, without the parent which causes recursive loops
  99. function readFullTree() {
  100. // Return null if the contextTree is not correctly closed
  101. if (root !== currentContext) {
  102. return null;
  103. }
  104. var current = currentContext;
  105. function recusiveRead(node) {
  106. if (node.children.length === 0) {
  107. delete node.children;
  108. } else {
  109. for (var i=0, max=node.children.length ; i<max ; i++) {
  110. recusiveRead(node.children[i]);
  111. }
  112. }
  113. delete node.parent;
  114. }
  115. recusiveRead(root);
  116. return root;
  117. }
  118. function ContextTreeNode(parent, data) {
  119. this.data = data;
  120. this.parent = parent;
  121. this.children = [];
  122. this.addChild = function(data) {
  123. var child = new ContextTreeNode(this, data);
  124. this.children.push(child);
  125. return child;
  126. };
  127. }
  128. phantomas.log('Adding some contextTree functions to phantomas');
  129. phantomas.pushContext = pushContext;
  130. phantomas.enterContext = enterContext;
  131. phantomas.leaveContext = leaveContext;
  132. phantomas.getContextData = getContextData;
  133. phantomas.readFullTree = readFullTree;
  134. })();
  135. })(window.__phantomas);
  136. }, phantomas.getParam('js-deep-analysis'));
  137. });
  138. };