hooks.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. var _hooking = 3,
  2. _layoutRuns = []
  3. _syncStatusCheck = function () {
  4. _hooking--;
  5. };
  6. Ext.require([
  7. 'Ext.perf.Monitor',
  8. 'Ext.perf.Accumulator'
  9. ],
  10. function(){
  11. if (typeof _accumulatorCfg != 'undefined') {
  12. Ext.Perf.setup(_accumulatorCfg);
  13. }
  14. _syncStatusCheck();
  15. }
  16. )
  17. Ext.define('PageAnalyzer.hook.Context', function () {
  18. function compareTriggers (a, b) {
  19. if (a.value === undefined) {
  20. if (b.value !== undefined) {
  21. return -1;
  22. }
  23. } else if (b.value === undefined) {
  24. return 1;
  25. }
  26. return a.name < b.name ? -1 : (b.name < a.name ? 1 : 0);
  27. }
  28. function getLayoutName (layout) {
  29. return layout.owner.id + '<' + layout.type + '>';
  30. }
  31. function getLayoutResults (me, layout, reported, orphan) {
  32. var owner = layout.owner,
  33. ownerContext = me.getCmp(owner),
  34. sizeModel = ownerContext.sizeModel,
  35. stats = me.layoutsById[layout.id],
  36. results = {
  37. allDone: layout.done,
  38. done: layout.done,
  39. id: layout.id,
  40. type: layout.type,
  41. name: getLayoutName(layout),
  42. blocks: [],
  43. boxParent: ownerContext.boxParent ? ownerContext.boxParent.id : null,
  44. isBoxParent: ownerContext.isBoxParent,
  45. triggers: [],
  46. orphan: !!orphan,
  47. heightModel: ownerContext.heightModel.name,
  48. widthModel: ownerContext.widthModel.name,
  49. children: [],
  50. duration: stats ? stats.duration : 0,
  51. totalTime: stats ? stats.duration : 0,
  52. count: stats ? stats.count : 1
  53. },
  54. order = [false, true],
  55. child, i;
  56. reported[layout.id] = true;
  57. if (results.heightModel != sizeModel.height.name) {
  58. results.heightModel += ' (' + sizeModel.height.name + ')';
  59. }
  60. if (results.widthModel != sizeModel.width.name) {
  61. results.widthModel += ' (' + sizeModel.width.name + ')';
  62. }
  63. Ext.Object.each(layout.blockedBy, function (t) {
  64. results.blocks.push(t);
  65. });
  66. Ext.Object.each(me.triggersByLayoutId[layout.id], function (name, info) {
  67. var item = info.item,
  68. dirty = item.dirty || false,
  69. prop = info.name,
  70. value = item.props[prop];
  71. results.triggers.push({
  72. name: name,
  73. prop: prop,
  74. value: value,
  75. dirty: dirty && (prop in dirty),
  76. missing: value === undefined,
  77. setBy: (item.setBy && item.setBy[prop]) || '??'
  78. });
  79. });
  80. results.blocks.sort();
  81. results.triggers.sort(compareTriggers);
  82. for (i = 0; i < 2; ++i) {
  83. Ext.Object.each(me.layouts, function (id, childLayout) {
  84. if (childLayout.done === order[i] && childLayout.owner.ownerLayout === layout) {
  85. child = getLayoutResults(me, childLayout, reported);
  86. if (!child.allDone) {
  87. results.allDone = false;
  88. }
  89. results.totalTime += child.totalTime;
  90. results.children.push(child);
  91. }
  92. });
  93. }
  94. return results;
  95. }
  96. function beforeRun (me) {
  97. me.calcsByType = {};
  98. me.numByType = {};
  99. me.timesByType = {};
  100. me.triggersByLayoutId = {};
  101. me.layoutsById = {};
  102. me.layoutsByType = {};
  103. me.flushLayoutStats = {};
  104. return {
  105. startTime: Ext.perf.getTimestamp()
  106. };
  107. }
  108. function afterRun (me, before, ok) {
  109. var t2 = new Date(),
  110. reported = {};
  111. var data = {
  112. duration: Ext.perf.getTimestamp() - before.startTime,
  113. time: t2,
  114. success: ok,
  115. cycleCount: me.cycleCount,
  116. flushCount: me.flushCount,
  117. calcCount: me.calcCount,
  118. orphans: 0,
  119. layouts: [],
  120. statsById: me.layoutsById,
  121. statsByType: me.layoutsByType,
  122. flushTime: me.flushTime,
  123. flushInvalidateTime: me.flushInvalidateTime,
  124. flushCount: me.flushCount,
  125. flushInvalidateCount: me.flushInvalidateCount,
  126. flushLayoutStats: me.flushLayoutStats
  127. };
  128. data.totalTime = data.duration;
  129. Ext.Object.each(me.layouts, function (id, layout) {
  130. if (me.items[layout.owner.el.id].isTopLevel) {
  131. data.layouts.push(getLayoutResults(me, layout, reported));
  132. }
  133. });
  134. Ext.Object.each(me.layouts, function (id, layout) {
  135. if (!reported[layout.id]) {
  136. ++data.orphans;
  137. data.layouts.push(getLayoutResults(me, layout, reported, true));
  138. }
  139. });
  140. _layoutRuns.push(Ext.encode(data));
  141. }
  142. function beforeRunLayout (me) {
  143. return {
  144. startTime: Ext.perf.getTimestamp()
  145. };
  146. }
  147. function afterRunLayout (me, layout, before) {
  148. var id = layout.id,
  149. type = layout.type,
  150. duration = Ext.perf.getTimestamp() - before.startTime,
  151. typeMapping = me.layoutsByType[type] || (me.layoutsByType[type] = {
  152. duration: 0,
  153. layoutCount: 0,
  154. count: 0
  155. }),
  156. idMapping = me.layoutsById[id];
  157. if(!idMapping) {
  158. typeMapping.layoutCount++;
  159. idMapping = me.layoutsById[id] = {
  160. duration: 0,
  161. count: 0
  162. };
  163. }
  164. idMapping.duration += duration;
  165. typeMapping.duration += duration;
  166. idMapping.count++;
  167. typeMapping.count++;
  168. }
  169. return {
  170. override: 'Ext.layout.Context',
  171. flushInvalidateTime: 0,
  172. flushInvalidateCount: 0,
  173. flushTime: 0,
  174. flushCount: 0,
  175. flush: function() {
  176. var start = Ext.perf.getTimestamp();
  177. this.callParent(arguments);
  178. this.flushTime += Ext.perf.getTimestamp() - start;
  179. this.flushCount++;
  180. },
  181. flushInvalidates: function() {
  182. var start = Ext.perf.getTimestamp();
  183. this.callParent(arguments);
  184. this.flushInvalidateTime += Ext.perf.getTimestamp() - start;
  185. this.flushInvalidateCount++;
  186. },
  187. flushLayouts: function (queueName, methodName, dontClear) {
  188. var start = Ext.perf.getTimestamp(),
  189. stats = this.flushLayoutStats[methodName] ||
  190. (this.flushLayoutStats[methodName] = {
  191. count: 0,
  192. time: 0
  193. });
  194. this.callParent(arguments);
  195. stats.time += Ext.perf.getTimestamp() - start;
  196. stats.count++;
  197. },
  198. run: function () {
  199. var me = this,
  200. before = beforeRun(me),
  201. ok = me.callParent(arguments);
  202. afterRun(me, before, ok);
  203. return ok;
  204. },
  205. runLayout: function (layout) {
  206. var me = this,
  207. before = beforeRunLayout(me);
  208. me.callParent(arguments);
  209. afterRunLayout(me, layout, before);
  210. }
  211. };
  212. }(), _syncStatusCheck);
  213. //-----------------------------------------------------------------------------
  214. Ext.define('PageAnalyzer.hook.ContextItem', function () {
  215. function getLayoutName (layout) {
  216. return layout.owner.id + '<' + layout.type + '>';
  217. }
  218. return {
  219. override: 'Ext.layout.ContextItem',
  220. addBlock: function (name, layout, propName) {
  221. //Ext.log(this.id,'.',propName,' ',name,': ',getLayoutName(layout));
  222. (layout.blockedBy || (layout.blockedBy = {}))[
  223. this.id+'.'+propName+(name.substring(0,3)=='dom' ? ':dom' : '')] = 1;
  224. return this.callParent(arguments);
  225. },
  226. addBoxChild: function (boxChildItem) {
  227. var ret = this.callParent(arguments),
  228. boxChildren = this.boxChildren,
  229. boxParents;
  230. if (boxChildren && boxChildren.length == 1) {
  231. // the boxParent collection is created by the run override found in
  232. // Ext.diag.layout.Context, but IE sometimes does not load that override, so
  233. // we work around it for now
  234. boxParents = this.context.boxParents ||
  235. (this.context.boxParents = new Ext.util.MixedCollection());
  236. boxParents.add(this);
  237. }
  238. return ret;
  239. },
  240. addTrigger: function (propName, inDom) {
  241. var layout = this.context.currentLayout,
  242. triggers;
  243. this.callParent(arguments);
  244. //Ext.log(this.id,'.',propName,' ',name = inDom ? ':dom' : '',' ',getLayoutName(layout));
  245. triggers = this.context.triggersByLayoutId;
  246. (triggers[layout.id] || (triggers[layout.id] = {}))[
  247. this.id+'.'+propName+(inDom ? ':dom' : '')] = {
  248. item: this,
  249. name: propName
  250. };
  251. },
  252. clearBlocks: function (name, propName) {
  253. var collection = this[name],
  254. blockedLayouts = collection && collection[propName],
  255. key = this.id+'.'+propName+(name.substring(0,3)=='dom' ? ':dom' : ''),
  256. layout, layoutId;
  257. if (blockedLayouts) {
  258. for (layoutId in blockedLayouts) {
  259. layout = blockedLayouts[layoutId];
  260. delete layout.blockedBy[key];
  261. }
  262. }
  263. return this.callParent(arguments);
  264. },
  265. setProp: function (propName, value, dirty) {
  266. var me = this,
  267. layout = me.context.currentLayout,
  268. setBy = getLayoutName(layout),
  269. //fullName = me.id + '.' + propName,
  270. setByProps;
  271. if (value !== null) {
  272. setByProps = me.setBy || (me.setBy = {});
  273. if (!setByProps[propName]) {
  274. setByProps[propName] = setBy;
  275. } else if (setByProps[propName] != setBy) {
  276. //Ext.log({level: 'warn'}, 'BAD! ', fullName, ' set by ', setByProps[propName], ' and ', setBy);
  277. }
  278. }
  279. if (typeof value != 'undefined' && !isNaN(value) && me.props[propName] !== value) {
  280. //Ext.log('set ', fullName, ' = ', value, ' (', dirty, ')');
  281. }
  282. return this.callParent(arguments);
  283. }
  284. };
  285. }(), _syncStatusCheck);