PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/resources/src/mediawiki/mediawiki.debug.js

https://gitlab.com/link233/bootmw
JavaScript | 384 lines | 227 code | 66 blank | 91 comment | 19 complexity | c125d03342da18484f6baf56f64080ac MD5 | raw file
  1. ( function ( mw, $ ) {
  2. 'use strict';
  3. var debug,
  4. hovzer = $.getFootHovzer();
  5. /**
  6. * Debug toolbar.
  7. *
  8. * Enabled server-side through `$wgDebugToolbar`.
  9. *
  10. * @class mw.Debug
  11. * @singleton
  12. * @author John Du Hart
  13. * @since 1.19
  14. */
  15. debug = mw.Debug = {
  16. /**
  17. * Toolbar container element
  18. *
  19. * @property {jQuery}
  20. */
  21. $container: null,
  22. /**
  23. * Object containing data for the debug toolbar
  24. *
  25. * @property {Object}
  26. */
  27. data: {},
  28. /**
  29. * Initialize the debugging pane
  30. *
  31. * Shouldn't be called before the document is ready
  32. * (since it binds to elements on the page).
  33. *
  34. * @param {Object} [data] Defaults to 'debugInfo' from mw.config
  35. */
  36. init: function ( data ) {
  37. this.data = data || mw.config.get( 'debugInfo' );
  38. this.buildHtml();
  39. // Insert the container into the DOM
  40. hovzer.$.append( this.$container );
  41. hovzer.update();
  42. $( '.mw-debug-panelink' ).click( this.switchPane );
  43. },
  44. /**
  45. * Switch between panes
  46. *
  47. * Should be called with an HTMLElement as its thisArg,
  48. * because it's meant to be an event handler.
  49. *
  50. * TODO: Store cookie for last pane open.
  51. *
  52. * @param {jQuery.Event} e
  53. */
  54. switchPane: function ( e ) {
  55. var currentPaneId = debug.$container.data( 'currentPane' ),
  56. requestedPaneId = $( this ).prop( 'id' ).slice( 9 ),
  57. $currentPane = $( '#mw-debug-pane-' + currentPaneId ),
  58. $requestedPane = $( '#mw-debug-pane-' + requestedPaneId ),
  59. hovDone = false;
  60. function updateHov() {
  61. if ( !hovDone ) {
  62. hovzer.update();
  63. hovDone = true;
  64. }
  65. }
  66. // Skip hash fragment handling. Prevents screen from jumping.
  67. e.preventDefault();
  68. $( this ).addClass( 'current ' );
  69. $( '.mw-debug-panelink' ).not( this ).removeClass( 'current ' );
  70. // Hide the current pane
  71. if ( requestedPaneId === currentPaneId ) {
  72. $currentPane.slideUp( updateHov );
  73. debug.$container.data( 'currentPane', null );
  74. return;
  75. }
  76. debug.$container.data( 'currentPane', requestedPaneId );
  77. if ( currentPaneId === undefined || currentPaneId === null ) {
  78. $requestedPane.slideDown( updateHov );
  79. } else {
  80. $currentPane.hide();
  81. $requestedPane.show();
  82. updateHov();
  83. }
  84. },
  85. /**
  86. * Construct the HTML for the debugging toolbar
  87. */
  88. buildHtml: function () {
  89. var $container, $bits, panes, id, gitInfo;
  90. $container = $( '<div id="mw-debug-toolbar" class="mw-debug" lang="en" dir="ltr"></div>' );
  91. $bits = $( '<div class="mw-debug-bits"></div>' );
  92. /**
  93. * Returns a jQuery element for a debug-bit div
  94. *
  95. * @ignore
  96. * @param {string} id
  97. * @return {jQuery}
  98. */
  99. function bitDiv( id ) {
  100. return $( '<div>' ).prop( {
  101. id: 'mw-debug-' + id,
  102. className: 'mw-debug-bit'
  103. } )
  104. .appendTo( $bits );
  105. }
  106. /**
  107. * Returns a jQuery element for a pane link
  108. *
  109. * @ignore
  110. * @param {string} id
  111. * @param {string} text
  112. * @return {jQuery}
  113. */
  114. function paneLabel( id, text ) {
  115. return $( '<a>' )
  116. .prop( {
  117. className: 'mw-debug-panelabel',
  118. href: '#mw-debug-pane-' + id
  119. } )
  120. .text( text );
  121. }
  122. /**
  123. * Returns a jQuery element for a debug-bit div with a for a pane link
  124. *
  125. * @ignore
  126. * @param {string} id CSS id snippet. Will be prefixed with 'mw-debug-'
  127. * @param {string} text Text to show
  128. * @param {string} count Optional count to show
  129. * @return {jQuery}
  130. */
  131. function paneTriggerBitDiv( id, text, count ) {
  132. if ( count ) {
  133. text = text + ' (' + count + ')';
  134. }
  135. return $( '<div>' ).prop( {
  136. id: 'mw-debug-' + id,
  137. className: 'mw-debug-bit mw-debug-panelink'
  138. } )
  139. .append( paneLabel( id, text ) )
  140. .appendTo( $bits );
  141. }
  142. paneTriggerBitDiv( 'console', 'Console', this.data.log.length );
  143. paneTriggerBitDiv( 'querylist', 'Queries', this.data.queries.length );
  144. paneTriggerBitDiv( 'debuglog', 'Debug log', this.data.debugLog.length );
  145. paneTriggerBitDiv( 'request', 'Request' );
  146. paneTriggerBitDiv( 'includes', 'PHP includes', this.data.includes.length );
  147. gitInfo = '';
  148. if ( this.data.gitRevision !== false ) {
  149. gitInfo = '(' + this.data.gitRevision.slice( 0, 7 ) + ')';
  150. if ( this.data.gitViewUrl !== false ) {
  151. gitInfo = $( '<a>' )
  152. .attr( 'href', this.data.gitViewUrl )
  153. .text( gitInfo );
  154. }
  155. }
  156. bitDiv( 'mwversion' )
  157. .append( $( '<a href="//www.mediawiki.org/">MediaWiki</a>' ) )
  158. .append( document.createTextNode( ': ' + this.data.mwVersion + ' ' ) )
  159. .append( gitInfo );
  160. if ( this.data.gitBranch !== false ) {
  161. bitDiv( 'gitbranch' ).text( 'Git branch: ' + this.data.gitBranch );
  162. }
  163. bitDiv( 'phpversion' )
  164. .append( $( this.data.phpEngine === 'HHVM'
  165. ? '<a href="http://hhvm.com/">HHVM</a>'
  166. : '<a href="https://php.net/">PHP</a>'
  167. ) )
  168. .append( ': ' + this.data.phpVersion );
  169. bitDiv( 'time' )
  170. .text( 'Time: ' + this.data.time.toFixed( 5 ) );
  171. bitDiv( 'memory' )
  172. .text( 'Memory: ' + this.data.memory + ' (Peak: ' + this.data.memoryPeak + ')' );
  173. $bits.appendTo( $container );
  174. panes = {
  175. console: this.buildConsoleTable(),
  176. querylist: this.buildQueryTable(),
  177. debuglog: this.buildDebugLogTable(),
  178. request: this.buildRequestPane(),
  179. includes: this.buildIncludesPane()
  180. };
  181. for ( id in panes ) {
  182. if ( !panes.hasOwnProperty( id ) ) {
  183. continue;
  184. }
  185. $( '<div>' )
  186. .prop( {
  187. className: 'mw-debug-pane',
  188. id: 'mw-debug-pane-' + id
  189. } )
  190. .append( panes[ id ] )
  191. .appendTo( $container );
  192. }
  193. this.$container = $container;
  194. },
  195. /**
  196. * Build the console panel
  197. */
  198. buildConsoleTable: function () {
  199. var $table, entryTypeText, i, length, entry;
  200. $table = $( '<table id="mw-debug-console">' );
  201. $( '<colgroup>' ).css( 'width', /* padding = */ 20 + ( 10 * /* fontSize = */ 11 ) ).appendTo( $table );
  202. $( '<colgroup>' ).appendTo( $table );
  203. $( '<colgroup>' ).css( 'width', 350 ).appendTo( $table );
  204. entryTypeText = function ( entryType ) {
  205. switch ( entryType ) {
  206. case 'log':
  207. return 'Log';
  208. case 'warn':
  209. return 'Warning';
  210. case 'deprecated':
  211. return 'Deprecated';
  212. default:
  213. return 'Unknown';
  214. }
  215. };
  216. for ( i = 0, length = this.data.log.length; i < length; i += 1 ) {
  217. entry = this.data.log[ i ];
  218. entry.typeText = entryTypeText( entry.type );
  219. $( '<tr>' )
  220. .append( $( '<td>' )
  221. .text( entry.typeText )
  222. .addClass( 'mw-debug-console-' + entry.type )
  223. )
  224. .append( $( '<td>' ).html( entry.msg ) )
  225. .append( $( '<td>' ).text( entry.caller ) )
  226. .appendTo( $table );
  227. }
  228. return $table;
  229. },
  230. /**
  231. * Build query list pane
  232. *
  233. * @return {jQuery}
  234. */
  235. buildQueryTable: function () {
  236. var $table, i, length, query;
  237. $table = $( '<table id="mw-debug-querylist"></table>' );
  238. $( '<tr>' )
  239. .append( $( '<th>#</th>' ).css( 'width', '4em' ) )
  240. .append( $( '<th>SQL</th>' ) )
  241. .append( $( '<th>Time</th>' ).css( 'width', '8em' ) )
  242. .append( $( '<th>Call</th>' ).css( 'width', '18em' ) )
  243. .appendTo( $table );
  244. for ( i = 0, length = this.data.queries.length; i < length; i += 1 ) {
  245. query = this.data.queries[ i ];
  246. $( '<tr>' )
  247. .append( $( '<td>' ).text( i + 1 ) )
  248. .append( $( '<td>' ).text( query.sql ) )
  249. .append( $( '<td class="stats">' ).text( ( query.time * 1000 ).toFixed( 4 ) + 'ms' ) )
  250. .append( $( '<td>' ).text( query[ 'function' ] ) )
  251. .appendTo( $table );
  252. }
  253. return $table;
  254. },
  255. /**
  256. * Build legacy debug log pane
  257. *
  258. * @return {jQuery}
  259. */
  260. buildDebugLogTable: function () {
  261. var $list, i, length, line;
  262. $list = $( '<ul>' );
  263. for ( i = 0, length = this.data.debugLog.length; i < length; i += 1 ) {
  264. line = this.data.debugLog[ i ];
  265. $( '<li>' )
  266. .html( mw.html.escape( line ).replace( /\n/g, '<br />\n' ) )
  267. .appendTo( $list );
  268. }
  269. return $list;
  270. },
  271. /**
  272. * Build request information pane
  273. *
  274. * @return {jQuery}
  275. */
  276. buildRequestPane: function () {
  277. function buildTable( title, data ) {
  278. var $unit, $table, key;
  279. $unit = $( '<div>' ).append( $( '<h2>' ).text( title ) );
  280. $table = $( '<table>' ).appendTo( $unit );
  281. $( '<tr>' )
  282. .html( '<th>Key</th><th>Value</th>' )
  283. .appendTo( $table );
  284. for ( key in data ) {
  285. if ( !data.hasOwnProperty( key ) ) {
  286. continue;
  287. }
  288. $( '<tr>' )
  289. .append( $( '<th>' ).text( key ) )
  290. .append( $( '<td>' ).text( data[ key ] ) )
  291. .appendTo( $table );
  292. }
  293. return $unit;
  294. }
  295. return $( '<div>' )
  296. .text( this.data.request.method + ' ' + this.data.request.url )
  297. .append( buildTable( 'Headers', this.data.request.headers ) )
  298. .append( buildTable( 'Parameters', this.data.request.params ) );
  299. },
  300. /**
  301. * Build included files pane
  302. *
  303. * @return {jQuery}
  304. */
  305. buildIncludesPane: function () {
  306. var $table, i, length, file;
  307. $table = $( '<table>' );
  308. for ( i = 0, length = this.data.includes.length; i < length; i += 1 ) {
  309. file = this.data.includes[ i ];
  310. $( '<tr>' )
  311. .append( $( '<td>' ).text( file.name ) )
  312. .append( $( '<td class="nr">' ).text( file.size ) )
  313. .appendTo( $table );
  314. }
  315. return $table;
  316. }
  317. };
  318. }( mediaWiki, jQuery ) );