]> git.stg.codes - stg.git/blob - doc/xslt/slides/browser/xbDebug.js
New style tut-headers
[stg.git] / doc / xslt / slides / browser / xbDebug.js
1 /*
2  * xbDebug.js
3  * $Revision: 1.2 $ $Date: 2003/02/07 16:04:19 $
4  */
5
6 /* ***** BEGIN LICENSE BLOCK *****
7  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
8  *
9  * The contents of this file are subject to the Mozilla Public License Version
10  * 1.1 (the "License"); you may not use this file except in compliance with
11  * the License. You may obtain a copy of the License at
12  * http://www.mozilla.org/MPL/
13  *
14  * Software distributed under the License is distributed on an "AS IS" basis,
15  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16  * for the specific language governing rights and limitations under the
17  * License.
18  *
19  * The Original Code is Netscape code.
20  *
21  * The Initial Developer of the Original Code is
22  * Netscape Corporation.
23  * Portions created by the Initial Developer are Copyright (C) 2001
24  * the Initial Developer. All Rights Reserved.
25  *
26  * Contributor(s): Bob Clary <bclary@netscape.com>
27  *
28  * ***** END LICENSE BLOCK ***** */
29
30 /*
31 ChangeLog:
32
33 2002-02-25: bclary - modified xbDebugTraceOject to make sure 
34             that original versions of wrapped functions were not
35             rewrapped. This had caused an infinite loop in IE.
36
37 2002-02-07: bclary - modified xbDebug.prototype.close to not null
38             the debug window reference. This can cause problems with
39                   Internet Explorer if the page is refreshed. These issues will
40                   be addressed at a later date.
41 */
42
43 function xbDebug()
44 {
45   this.on = false;
46   this.stack = new Array();
47   this.debugwindow = null;
48   this.execprofile = new Object();
49 }
50
51 xbDebug.prototype.push = function ()
52 {
53   this.stack[this.stack.length] = this.on;
54   this.on = true;
55 }
56
57 xbDebug.prototype.pop = function ()
58 {
59   this.on = this.stack[this.stack.length - 1];
60   --this.stack.length;
61 }
62
63 xbDebug.prototype.open =  function ()
64 {
65   if (this.debugwindow && !this.debugwindow.closed)
66     this.close();
67     
68   this.debugwindow = window.open('about:blank', 'DEBUGWINDOW', 'height=400,width=600,resizable=yes,scrollbars=yes');
69   this.debugwindow.moveTo(0,0);
70   window.focus();
71
72   this.debugwindow.document.write('<html><head><title>xbDebug Window</title></head><body><h3>Javascript Debug Window</h3></body></html>');
73 }
74
75 xbDebug.prototype.close = function ()
76 {
77   if (!this.debugwindow)
78     return;
79     
80   if (!this.debugwindow.closed)
81     this.debugwindow.close();
82
83   // bc 2002-02-07, other windows may still hold a reference to this: this.debugwindow = null;
84 }
85
86 xbDebug.prototype.dump = function (msg)
87 {
88   if (!this.on)
89     return;
90     
91   if (!this.debugwindow || this.debugwindow.closed)
92     this.open();
93     
94   this.debugwindow.document.write(msg + '<br>');
95   
96   return;
97 }
98
99 var xbDEBUG = new xbDebug();
100
101 window.onunload = function () { xbDEBUG.close(); }
102
103 function xbDebugGetFunctionName(funcref)
104 {
105
106   if (!funcref)
107   {
108     return '';
109   }
110
111   if (funcref.name)
112     return funcref.name;
113
114   var name = funcref + '';
115   name = name.substring(name.indexOf(' ') + 1, name.indexOf('('));
116   funcref.name = name;
117
118   if (!name) alert('name not defined');
119   return name;
120 }
121
122
123 // emulate functionref.apply for IE mac and IE win < 5.5
124 function xbDebugApplyFunction(funcname, funcref, thisref, argumentsref)
125 {
126   var rv;
127
128   if (!funcref)
129   {
130     alert('xbDebugApplyFunction: funcref is null');
131   }
132
133   if (typeof(funcref.apply) != 'undefined')
134       return funcref.apply(thisref, argumentsref);
135
136   var applyexpr = 'thisref.xbDebug_orig_' + funcname + '(';
137   var i;
138
139   for (i = 0; i < argumentsref.length; i++)
140   {
141     applyexpr += 'argumentsref[' + i + '],';
142   }
143
144   if (argumentsref.length > 0)
145   {
146     applyexpr = applyexpr.substring(0, applyexpr.length - 1);
147   }
148
149   applyexpr += ')';
150
151   return eval(applyexpr);
152 }
153
154 function xbDebugCreateFunctionWrapper(scopename, funcname, precall, postcall)
155 {
156   var wrappedfunc;
157   var scopeobject = eval(scopename);
158   var funcref = scopeobject[funcname];
159
160   scopeobject['xbDebug_orig_' + funcname] = funcref;
161
162   wrappedfunc = function () 
163   {
164     var rv;
165
166     precall(scopename, funcname, arguments);
167     rv = xbDebugApplyFunction(funcname, funcref, scopeobject, arguments);
168     postcall(scopename, funcname, arguments, rv);
169     return rv;
170   };
171
172   if (typeof(funcref.constructor) != 'undefined')
173     wrappedfunc.constructor = funcref.constuctor;
174
175   if (typeof(funcref.prototype) != 'undefined')
176     wrappedfunc.prototype = funcref.prototype;
177
178   scopeobject[funcname] = wrappedfunc;
179 }
180
181 function xbDebugCreateMethodWrapper(contextname, classname, methodname, precall, postcall)
182 {
183   var context = eval(contextname);
184   var methodref = context[classname].prototype[methodname];
185
186   context[classname].prototype['xbDebug_orig_' + methodname] = methodref;
187
188   var wrappedmethod = function () 
189   {
190     var rv;
191     // eval 'this' at method run time to pick up reference to the object's instance
192     var thisref = eval('this');
193     // eval 'arguments' at method run time to pick up method's arguments
194     var argsref = arguments;
195
196     precall(contextname + '.' + classname, methodname, argsref);
197     rv = xbDebugApplyFunction(methodname, methodref, thisref, argsref);
198     postcall(contextname + '.' + classname, methodname, argsref, rv);
199     return rv;
200   };
201
202   return wrappedmethod;
203 }
204
205 function xbDebugPersistToString(obj)
206 {
207   var s = '';
208
209   if (obj == null)
210      return 'null';
211
212   switch(typeof(obj))
213   {
214     case 'number':
215        return obj;
216     case 'string':
217        return '"' + obj + '"';
218     case 'undefined':
219        return 'undefined';
220     case 'boolean':
221        return obj + '';
222   }
223
224   if (obj.constructor)
225     return '[' + xbDebugGetFunctionName(obj.constructor) + ']';
226
227   return null;
228 }
229
230 function xbDebugTraceBefore(scopename, funcname, funcarguments) 
231 {
232   var i;
233   var s = '';
234   var execprofile = xbDEBUG.execprofile[scopename + '.' + funcname];
235   if (!execprofile)
236     execprofile = xbDEBUG.execprofile[scopename + '.' + funcname] = { started: 0, time: 0, count: 0 };
237
238   for (i = 0; i < funcarguments.length; i++)
239   {
240     s += xbDebugPersistToString(funcarguments[i]);
241     if (i < funcarguments.length - 1)
242       s += ', ';
243   }
244
245   xbDEBUG.dump('enter ' + scopename + '.' + funcname + '(' + s + ')');
246   execprofile.started = (new Date()).getTime();
247 }
248
249 function xbDebugTraceAfter(scopename, funcname, funcarguments, rv) 
250 {
251   var i;
252   var s = '';
253   var execprofile = xbDEBUG.execprofile[scopename + '.' + funcname];
254   if (!execprofile)
255     xbDEBUG.dump('xbDebugTraceAfter: execprofile not created for ' + scopename + '.' + funcname);
256   else if (execprofile.started == 0)
257     xbDEBUG.dump('xbDebugTraceAfter: execprofile.started == 0 for ' + scopename + '.' + funcname);
258   else 
259   {
260     execprofile.time += (new Date()).getTime() - execprofile.started;
261     execprofile.count++;
262     execprofile.started = 0;
263   }
264
265   for (i = 0; i < funcarguments.length; i++)
266   {
267     s += xbDebugPersistToString(funcarguments[i]);
268     if (i < funcarguments.length - 1)
269       s += ', ';
270   }
271
272   xbDEBUG.dump('exit  ' + scopename + '.' + funcname + '(' + s + ')==' + xbDebugPersistToString(rv));
273 }
274
275 function xbDebugTraceFunction(scopename, funcname)
276 {
277   xbDebugCreateFunctionWrapper(scopename, funcname, xbDebugTraceBefore, xbDebugTraceAfter);
278 }
279
280 function xbDebugTraceObject(contextname, classname)
281 {
282   var classref = eval(contextname + '.' + classname);
283   var p;
284   var sp;
285
286   if (!classref || !classref.prototype)
287      return;
288
289   for (p in classref.prototype)
290   {
291     sp = p + '';
292     if (typeof(classref.prototype[sp]) == 'function' && (sp).indexOf('xbDebug_orig') == -1)
293     {
294       classref.prototype[sp] = xbDebugCreateMethodWrapper(contextname, classname, sp, xbDebugTraceBefore, xbDebugTraceAfter);
295     }
296   }
297 }
298
299 function xbDebugDumpProfile()
300 {
301   var p;
302   var execprofile;
303   var avg;
304
305   for (p in xbDEBUG.execprofile)
306   {
307     execprofile = xbDEBUG.execprofile[p];
308     avg = Math.round ( 100 * execprofile.time/execprofile.count) /100;
309     xbDEBUG.dump('Execution profile ' + p + ' called ' + execprofile.count + ' times. Total time=' + execprofile.time + 'ms. Avg Time=' + avg + 'ms.');
310   }
311 }