[extra] Import Firefox 3.0 beta 5 tarball
[mozilla-extra.git] / extensions / venkman / resources / content / venkman-static.js
blob1e031cce099fbfc39be1d843ccfc8418f488b886
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * ***** BEGIN LICENSE BLOCK *****
4  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5  *
6  * The contents of this file are subject to the Mozilla Public License Version
7  * 1.1 (the "License"); you may not use this file except in compliance with
8  * the License. You may obtain a copy of the License at
9  * http://www.mozilla.org/MPL/
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is The JavaScript Debugger.
17  *
18  * The Initial Developer of the Original Code is
19  * Netscape Communications Corporation.
20  * Portions created by the Initial Developer are Copyright (C) 1998
21  * the Initial Developer. All Rights Reserved.
22  *
23  * Contributor(s):
24  *   Robert Ginda, <rginda@netscape.com>, original author
25  *
26  * Alternatively, the contents of this file may be used under the terms of
27  * either the GNU General Public License Version 2 or later (the "GPL"), or
28  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29  * in which case the provisions of the GPL or the LGPL are applicable instead
30  * of those above. If you wish to allow use of your version of this file only
31  * under the terms of either the GPL or the LGPL, and not to allow others to
32  * use your version of this file under the terms of the MPL, indicate your
33  * decision by deleting the provisions above and replace them with the notice
34  * and other provisions required by the GPL or the LGPL. If you do not delete
35  * the provisions above, a recipient may use your version of this file under
36  * the terms of any one of the MPL, the GPL or the LGPL.
37  *
38  * ***** END LICENSE BLOCK ***** */
40 #filter substitution
42 const __vnk_version        = "@VENKMAN_VERSION@";
43 const __vnk_requiredLocale = "0.9.87.3";
44 var   __vnk_versionSuffix  = "";
46 const __vnk_counter_url = 
47 "http://www.hacksrus.com/~ginda/venkman/launch-counter/next-sequence.cgi"
49 /* dd is declared first in venkman-utils.js */
50 var warn;
51 var ASSERT;
53 if (DEBUG)
55     _dd_pfx = "vnk: ";
56     warn = function (msg) { dumpln ("** WARNING " + msg + " **"); }
57     ASSERT = function (expr, msg) {
58                  if (!expr) {
59                      dump ("** ASSERTION FAILED: " + msg + " **\n" + 
60                            getStackTrace() + "\n"); 
61                      return false;
62                  } else {
63                      return true;
64                  }
65              }
66 }    
67 else
68     dd = warn = ASSERT = function (){};
71 const MAX_WORD_LEN = 20; /* number of characters to display before forcing a 
72                           * potential word break point (in the console.) */
74 const LINE_BREAKABLE = 0x01;
75 const LINE_BREAK     = 0x02;
76 const LINE_FBREAK    = 0x04;
78 var console = new Object();
80 console.initialized = false;
82 /* |this|less functions */
84 function setStopState(state)
86     var tb = console.ui["stop-button"];
87     if (state)
88     {
89         console.jsds.interruptHook = console.executionHook;
90         tb.setAttribute("willStop", "true");
91     }
92     else
93     {
94         console.jsds.interruptHook = null;
95         tb.removeAttribute("willStop");
96     }
99 function setProfileState(state)
101     var tb = console.ui["profile-button"];
102     if (state)
103     {
104         console.profiler.enabled = true;
105         tb.setAttribute("profile", "true");
106     }
107     else
108     {
109         console.profiler.enabled = false;
110         tb.removeAttribute("profile");
111     }
114 function enableDebugCommands()
116     var cmds = console.commandManager.list ("", CMD_NEED_STACK);
117     for (var i in cmds)
118         cmds[i].enabled = true;
119     
120     cmds = console.commandManager.list ("", CMD_NO_STACK);
121     for (i in cmds)
122         cmds[i].enabled = false;
125 function disableDebugCommands()
127     var cmds = console.commandManager.list ("", CMD_NEED_STACK);
128     for (var i in cmds)
129         cmds[i].enabled = false;
130     
131     cmds = console.commandManager.list ("", CMD_NO_STACK);
132     for (i in cmds)
133         cmds[i].enabled = true;
137 function isDOMIInstalled()
139     const IOSERVICE_CTRID = "@mozilla.org/network/io-service;1";
140     const nsIIOService    = Components.interfaces.nsIIOService;
141     const CHROMEREG_CTRID = "@mozilla.org/chrome/chrome-registry;1";
142     const nsIChromeReg    = Components.interfaces.nsIChromeRegistry;
144     var iosvc = Components.classes[IOSERVICE_CTRID].getService(nsIIOService);
145     var uri = iosvc.newURI("chrome://inspector/content/inspector.xul",
146                            null, null);
147     // Evil hack: check if the chrome registry knows about Inspector.
148     // If it does, it's installed, otherwise it isn't.
149     try
150     {
151         var cr = Components.classes[CHROMEREG_CTRID].getService(nsIChromeReg);
152         var realURI = cr.convertChromeURL(uri);
153     }
154     catch (ex)
155     {
156         return false;
157     }
158     return true;
161 function isDOMThing(o)
163     const nsIDOMNode     = Components.interfaces.nsIDOMNode;
164     const nsIDOMDocument = Components.interfaces.nsIDOMDocument;
165     return isinstance(o, nsIDOMNode);
168 function isURLVenkman (url)
170     return (url.search (/^chrome:\/\/venkman/) == 0 &&
171             url.search (/test/) == -1);
174 function isURLFiltered (url)
176     return (!url ||
177             (console.prefs["enableChromeFilter"] &&
178              (url.search(/^chrome:/) == 0 ||
179               ("componentPath" in console &&
180                url.indexOf(console.componentPath) == 0))) ||
181             (url.search (/^chrome:\/\/venkman/) == 0 &&
182              url.search (/test/) == -1));
185 function toUnicode (msg, charset)
187     try
188     {
189         console.ucConverter.charset = charset;
190         return console.ucConverter.ConvertToUnicode(msg);
191     }
192     catch (ex)
193     {
194         dd ("caught " + ex + " converting to unicode");
195         return msg;
196     }
199 function fromUnicode (msg, charset)
201     try
202     {
203         console.ucConverter.charset = charset;
204         return console.ucConverter.ConvertFromUnicode(msg);
205     }
206     catch (ex)
207     {
208         dd ("caught " + ex + " converting from unicode");
209         return msg;
210     }
213 function displayUsageError (e, details)
215     if (!("isInteractive" in e) || !e.isInteractive)
216     {
217         var caller = Components.stack.caller.caller;
218         if (caller.name == "dispatch")
219             caller = caller.caller;
220         var error = new Error (details);
221         error.fileName = caller.filename;
222         error.lineNumber = caller.lineNumber;
223         error.name = caller.name;
224         display (formatException(error), MT_ERROR);
225     }
226     else
227     {
228         display (details, MT_ERROR);
229     }
230     
231     display (getMsg(MSN_FMT_USAGE, [e.command.name, e.command.usage]), MT_USAGE);
234 function dispatch (text, e, flags)
236     if (!e)
237         e = new Object();
239     if (!("inputData" in e))
240         e.inputData = "";
241     
242     /* split command from arguments */
243     var ary = text.match (/(\S+) ?(.*)/);
244     e.commandText = ary[1];
245     e.inputData =  ary[2] ? stringTrim(ary[2]) : "";
246     
247     /* list matching commands */
248     ary = console.commandManager.list (e.commandText, flags);
249     var rv = null;
250     var i;
251     
252     switch (ary.length)
253     {            
254         case 0:
255             /* no match, try again */
256             display (getMsg(MSN_NO_CMDMATCH, e.commandText), MT_ERROR);
257             break;
258             
259         case 1:
260             /* one match, good for you */
261             var ex;
262             try
263             {
264                 rv = dispatchCommand(ary[0], e, flags);
265             }
266             catch (ex)
267             {
268                 display (getMsg(MSN_ERR_INTERNAL_DISPATCH, ary[0].name),
269                          MT_ERROR);
270                 display (formatException(ex), MT_ERROR);
271                 dd (formatException(ex), MT_ERROR);
272                 if (typeof ex == "object" && "stack" in ex)
273                     dd (ex.stack);
274             }
275             break;
276             
277         default:
278             /* more than one match, show the list */
279             var str = "";
280             for (i in ary)
281                 str += (str) ? MSG_COMMASP + ary[i].name : ary[i].name;
282             display (getMsg (MSN_ERR_AMBIGCOMMAND,
283                              [e.commandText, ary.length, str]), MT_ERROR);
284     }
286     return rv;
289 function dispatchCommand (command, e, flags)
291     function callHooks (command, isBefore)
292     {
293         var names, hooks;
294         
295         if (isBefore)
296             hooks = command.beforeHooks;
297         else
298             hooks = command.afterHooks;
300         for (var h in hooks)
301         {
302             if ("dbgDispatch" in console && console.dbgDispatch)
303             {
304                 dd ("calling " + (isBefore ? "before" : "after") + 
305                     " hook " + h);
306             }
307             try
308             {
309                 hooks[h](e);
310             }
311             catch (ex)
312             {
313                 if (e.command.name != "hook-session-display")
314                 {
315                     display (getMsg(MSN_ERR_INTERNAL_HOOK, h), MT_ERROR);
316                     display (formatException(ex), MT_ERROR);
317                 }
318                 else
319                 {
320                     dd (getMsg(MSN_ERR_INTERNAL_HOOK, h));
321                 }
323                 dd ("Caught exception calling " +
324                     (isBefore ? "before" : "after") + " hook " + h);
325                 dd (formatException(ex));
326                 if (typeof ex == "object" && "stack" in ex)
327                     dd (ex.stack);
328                 else
329                     dd (getStackTrace());
330             }
331         }
332     };
333     
334     e.command = command;
336     if ((e.command.flags & CMD_NEED_STACK) &&
337         (!("frames" in console)))
338     {
339         /* doc, it hurts when I do /this/... */
340         display (MSG_ERR_NO_STACK, MT_ERROR);
341         return null;
342     }
343     
344     if (!e.command.enabled)
345     {
346         /* disabled command */
347         display (getMsg(MSN_ERR_DISABLED, e.command.name),
348                  MT_ERROR);
349         return null;
350     }
351     
352     var h, i;
353     
354     if ("beforeHooks" in e.command)
355         callHooks (e.command, true);
356     
357     if (typeof e.command.func == "function")
358     {
359         /* dispatch a real function */
360         if (e.command.usage)
361             console.commandManager.parseArguments (e);
362         if ("parseError" in e)
363         {
364             displayUsageError (e, e.parseError);
365         }
366         else
367         {
368             if ("dbgDispatch" in console && console.dbgDispatch)
369             {
370                 var str = "";
371                 for (i = 0; i < e.command.argNames.length; ++i)
372                 {
373                     var name = e.command.argNames[i];
374                     if (name in e)
375                         str += " " + name + ": " + e[name];
376                     else if (name != ":")
377                         str += " ?" + name;
378                 }
379                 dd (">>> " + e.command.name + str + " <<<");
380                 e.returnValue = e.command.func(e);
381                 /* set console.lastEvent *after* dispatching, so the dispatched
382                  * function actually get's a chance to see the last event. */
383                 console.lastEvent = e;
384             }
385             else
386             {
387                 e.returnValue = e.command.func(e);
388             }
390         }
391     }
392     else if (typeof e.command.func == "string")
393     {
394         /* dispatch an alias (semicolon delimited list of subcommands) */
395         var commandList = e.command.func.split(";");
396         for (i = 0; i < commandList.length; ++i)
397         {
398             var newEvent = Clone (e);
399             delete newEvent.command;            
400             commandList[i] = stringTrim(commandList[i]);
401             dispatch (commandList[i], newEvent, flags);
402         }
403     }
404     else
405     {
406         display (getMsg(MSN_ERR_NOTIMPLEMENTED, e.command.name),
407                  MT_ERROR);
408         return null;
409     }
411     if ("afterHooks" in e.command)
412         callHooks (e.command, false);
414     return ("returnValue" in e) ? e.returnValue : null;
417 function feedback(e, message, msgtype)
419     if ("isInteractive" in e && e.isInteractive)
420         display (message, msgtype);
423 function display(message, msgtype)
425     if (typeof message == "undefined")
426         throw new RequiredParam ("message");
428     if (typeof message != "string" &&
429         !(message instanceof Components.interfaces.nsIDOMHTMLElement))
430         throw new InvalidParam ("message", message);
432     if ("capturedMsgs" in console)
433         console.capturedMsgs.push ([message, msgtype]);
434         
435     dispatchCommand(console.coDisplayHook, 
436                     { message: message, msgtype: msgtype });
439 function evalInDebuggerScope (script, rethrow)
441     try
442     {
443         return console.doEval (script);
444     }
445     catch (ex)
446     {
447         if (rethrow)
448             throw ex;
450         display (formatEvalException(ex), MT_ERROR);
451         return null;
452     }
455 function evalInTargetScope (script, rethrow)
457     if (!console.frames)
458     {
459         display (MSG_ERR_NO_STACK, MT_ERROR);
460         return null;
461     }
462     
463     var rval = new Object();
464     
465     if (!getCurrentFrame().eval (script, MSG_VAL_CONSOLE, 1, rval))
466     {
467         if (rethrow)
468             throw rval.value;
469         
470         //dd ("exception: " + dumpObjectTree(rval.value));
471         display (formatEvalException (rval.value), MT_ERROR);
472         return null;
473     }
475     return ("value" in rval) ? rval.value : null;
478 function formatException (ex)
480     if (ex instanceof BadMojo)
481         return getMsg (MSN_FMT_BADMOJO,
482                        [ex.errno, ex.message, ex.fileName, ex.lineNumber, 
483                         ex.functionName]);
485     if (ex instanceof Error)
486         return getMsg (MSN_FMT_JSEXCEPTION, [ex.name, ex.message, ex.fileName, 
487                                              ex.lineNumber]);
489     return String(ex);
492 function formatEvalException (ex)
494     if (ex instanceof BadMojo || ex instanceof Error)
495         return formatException (ex);
496     else if (ex instanceof jsdIValue)
497         ex = ex.stringValue;
498     
499     return getMsg (MSN_EVAL_THREW,  String(ex));
502 function init()
504     dd ("init {");
505     
506     var i;
507     const WW_CTRID = "@mozilla.org/embedcomp/window-watcher;1";
508     const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
510     console.windowWatcher =
511         Components.classes[WW_CTRID].getService(nsIWindowWatcher);
513     const UC_CTRID = "@mozilla.org/intl/scriptableunicodeconverter";
514     const nsIUnicodeConverter = 
515         Components.interfaces.nsIScriptableUnicodeConverter;
516     console.ucConverter =
517         Components.classes[UC_CTRID].getService(nsIUnicodeConverter);
519     console.baseWindow = getBaseWindowFromWindow(window);
520     console.mainWindow = window;
521     console.dnd = nsDragAndDrop;
522     console.currentEvalObject = console;
523     
524     console.files = new Object();
525     console.pluginState = new Object();
527     console._statusStack = new Array();
528     console._lastStackDepth = -1;
530     initMsgs();
531     initPrefs();
532     initCommands();
533     initJSDURL();
534     
535     /* Some commonly used commands, cached now, for use with dispatchCommand. */
536     var cm = console.commandManager;
537     console.coManagerCreated    = cm.commands["hook-script-manager-created"];
538     console.coManagerDestroyed  = cm.commands["hook-script-manager-destroyed"];
539     console.coInstanceCreated   = cm.commands["hook-script-instance-created"];
540     console.coInstanceSealed    = cm.commands["hook-script-instance-sealed"];
541     console.coInstanceDestroyed = cm.commands["hook-script-instance-destroyed"];
542     console.coDisplayHook       = cm.commands["hook-session-display"];
543     console.coFindScript        = cm.commands["find-script"];
545     console.commandManager.addHooks (console.hooks);
547     initMenus();
549     console.capturedMsgs = new Array();
550     var ary = console.prefs["initialScripts"].split(/\s*;\s*/);
551     for (i = 0; i < ary.length; ++i)
552     {
553         var url = stringTrim(ary[i]);
554         if (url)
555             dispatch ("loadd", { url: ary[i] });
556     }
558     dispatch ("hook-venkman-started");
560     initViews();
561     initRecords();
562     initHandlers(); // handlers may notice windows, which need views and records
564     createMainMenu(document);
565     createMainToolbar(document);
567     // Must be done after menus are "here", since it corrects them for the host.
568     initApplicationCompatibility();
570     console.ui = {
571         "status-text": document.getElementById ("status-text"),
572         "profile-button": document.getElementById ("maintoolbar:profile-tb"),
573         "stop-button": document.getElementById ("maintoolbar:stop")
574     };    
576     disableDebugCommands();
578     initDebugger();
579     initProfiler();
581     // read prefs that have not been explicitly created, such as the layout prefs
582     console.prefManager.readPrefs();
583     
584     fetchLaunchCount();
585     
586     console.sourceText = new HelpText();
588     console.pushStatus(MSG_STATUS_DEFAULT);
590     dispatch ("restore-layout default");
592     var startupMsgs = console.capturedMsgs;
593     delete console.capturedMsgs;
594     
595     dispatch ("version");
597     for (i = 0; i < startupMsgs.length; ++i)
598         display (startupMsgs[i][0], startupMsgs[i][1]);
600     display (getMsg(MSN_TIP1_HELP, 
601                     console.prefs["sessionView.requireSlash"] ? "/" : ""));
602     display (MSG_TIP2_HELP);
603     if (console.prefs["sessionView.requireSlash"])
604         display (MSG_TIP3_HELP);
606     if (console.prefs["rememberPrettyprint"])
607         dispatch ("pprint", { toggle: console.prefs["prettyprint"] });
608     else
609         dispatch ("pprint", { toggle: false });
611     if (MSG_LOCALE_VERSION != __vnk_requiredLocale)
612     {
613         display (getMsg(MSN_BAD_LOCALE,
614                         [__vnk_requiredLocale, MSG_LOCALE_VERSION]),
615                  MT_WARN);
616     }
618     // Delay being "done" until the window is up.
619     setTimeout(initPost, 100);
621     if (console.prefs["saveSettingsOnExit"])
622     {
623         dispatch ("restore-settings",
624                   {settingsFile: console.prefs["settingsFile"]});
625     }
627     dispatch ("hook-venkman-started");
629     dd ("}");
632 function initApplicationCompatibility()
634     // This function does nothing more than tweak the UI based on the host
635     // application.
637     // Set up simple host and platform information.
638     console.host = "Unknown";
639     console.haveBrowser = false;
641     var app = getService("@mozilla.org/xre/app-info;1", "nsIXULAppInfo");
642     // nsIXULAppInfo wasn't implemented before 1.8...
643     if (app)
644     {
645         // Use the XULAppInfo.ID to find out what host we run on.
646         switch (app.ID)
647         {
648             case "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}":
649                 console.host = "Firefox";
650                 console.haveBrowser = true;
651                 break;
652             case "{3550f703-e582-4d05-9a08-453d09bdfdc6}": // Thunderbird
653                 console.host = "Thunderbird";
654                 break;
655             case "{a463f10c-3994-11da-9945-000d60ca027b}": // Flock
656                 console.host = "Flock";
657                 console.haveBrowser = true;
658                 break;
659             case "{718e30fb-e89b-41dd-9da7-e25a45638b28}": // Sunbird
660                 console.host = "Sunbird";
661                 break;
662             case "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}": // SeaMonkey
663                 console.host = "Mozilla";
664                 console.haveBrowser = true;
665                 break;
666             default:
667                 console.unknownAppUID = app.ID;
668                 console.host = "ToolkitApp"; // Unknown host, platform install
669         }
670     }
671     else if ("getBrowserURL" in window)
672     {
673         var url = getBrowserURL();
674         if (url == "chrome://navigator/content/navigator.xul")
675         {
676             console.host = "Mozilla";
677             console.haveBrowser = true;
678         }
679         else if (url == "chrome://browser/content/browser.xul")
680         {
681             console.host = "Firefox";
682             console.haveBrowser = true;
683         }
684         else
685         {
686             console.unknownAppUID = url;
687         }
688     }
690     console.platform = "Unknown";
691     if (navigator.platform.search(/mac/i) > -1)
692         console.platform = "Mac";
693     if (navigator.platform.search(/win/i) > -1)
694         console.platform = "Windows";
695     if (navigator.platform.search(/linux/i) > -1)
696         console.platform = "Linux";
697     if (navigator.platform.search(/os\/2/i) > -1)
698         console.platform = "OS/2";
700     console.hostPlatform = console.host + console.platform;
702     // The menus and the component bar need to be hidden on some hosts.
703     var winMenu   = document.getElementById("windowMenu");
704     var tasksMenu = document.getElementById("tasksMenu");
705     //var toolsMenu = document.getElementById("mainmenu:tools");
706     var comBar    = document.getElementById("component-bar");
708     if (console.host != "Mozilla") {
709         tasksMenu.parentNode.removeChild(tasksMenu);
710         winMenu.parentNode.removeChild(winMenu);
711         comBar.collapsed = true;
712     }
715 function initPost()
717     console.initialized = true;
720 function destroy ()
722     if (console.prefs["saveLayoutOnExit"])
723         dispatch ("save-layout default");
725     if (console.prefs["saveSettingsOnExit"])
726     {
727         dispatch ("save-settings",
728                   {settingsFile: console.prefs["settingsFile"]});
729     }
731     delete console.currentEvalObject;
732     delete console.jsdConsole;
734     destroyViews();
735     destroyHandlers();
736     destroyPrefs();
737     detachDebugger();
740 function paintHack (i)
742     /* when stopping at a timeout, we don't repaint correctly.
743      * by jamming a character into this hidden text box, we can force
744      * a repaint.
745      */
746     for (var w in console.viewManager.windows)
747     {
748         var window = console.viewManager.windows[w];
749         var textbox = window.document.getElementById("paint-hack");
750         if (textbox)
751         {
752             textbox.value = " ";
753             textbox.value = "";
754         }
755     }
756     
757     if (!i)
758         i = 0;
759     
760     if (i < 4)
761         setTimeout (paintHack, 250, i + 1);
762 }   
764 function fetchLaunchCount()
766     ++console.prefs["startupCount"];
768     if (!toBool(console.prefs["permitStartupHit"]))
769         return;
771     function onLoad ()
772     {
773         var ary = String(r.responseText).match(/(\d+)/);
774         if (ary)
775         {
776             display (getMsg(MSN_LAUNCH_COUNT,
777                             [console.prefs["startupCount"], ary[1]]));
778         }
779     };
780     
781     try
782     {
783         var r = new XMLHttpRequest();
784         r.onload = onLoad;
785         r.open ("GET",
786                 __vnk_counter_url + "?local=" + console.prefs["startupCount"] +
787                 "&version=" + __vnk_version);
788         r.send (null);
789     }
790     catch (ex)
791     {
792         // Oops. Probably missing the xmlextras extension, can't really do 
793         // much about that.
794         display(getMsg(MSN_LAUNCH_COUNT,
795                        [console.prefs["startupCount"], MSG_VAL_UNKNOWN]));
796     }
799 function getCommandEnabled(command)
801     try {
802         var dispatcher = top.document.commandDispatcher;
803         var controller = dispatcher.getControllerForCommand(command);
804         
805         return controller.isCommandEnabled(command);
806     }
807     catch (e)
808     {
809         return false;
810     }
813 function doCommand(command)
815     try {
816         var dispatcher = top.document.commandDispatcher;
817         var controller = dispatcher.getControllerForCommand(command);
818         if (controller && controller.isCommandEnabled(command))
819             controller.doCommand(command);
820     }
821     catch (e)
822     {
823     }
826 console.__defineGetter__ ("userAgent", con_ua);
827 function con_ua ()
829     var ary = navigator.userAgent.match (/;\s*([^;\s]+\s*)\).*\/(\d+)/);
830     if (ary)
831     {
832         return ("Venkman " + __vnk_version + __vnk_versionSuffix + 
833                 " [Mozilla " + ary[1] + "/" + ary[2] + "]");
834     }
836     return ("Venkman " + __vnk_version + __vnk_versionSuffix + " [" + 
837             navigator.userAgent + "]");
840 console.hooks = new Object();
842 console.hooks["hook-script-instance-sealed"] =
843 function hookScriptSealed (e)
845     var url = e.scriptInstance.url;
846     if (!("componentPath" in console))
847     {
848         const VNK_SVC = "venkman-service.js";
849         if (url.substr(-VNK_SVC.length) == VNK_SVC)
850         {
851             if (!console.prefs["enableChromeFilter"])
852             {
853                 dispatch ("debug-instance-on",
854                           { scriptInstance: e.scriptInstance });
855             }
856             console.componentPath = url.substr(0, url.length - VNK_SVC.length);
857         }
858     }
860     for (var fbp in console.fbreaks)
861     {
862         if (console.fbreaks[fbp].enabled &&
863             url.indexOf(console.fbreaks[fbp].url) != -1)
864         {
865             e.scriptInstance.setBreakpoint(console.fbreaks[fbp].lineNumber,
866                                            console.fbreaks[fbp]);
867         }
868     }
871 console.hooks["hook-debug-stop"] =
872 function hookDebugStop (e)
874     var jsdFrame = setCurrentFrameByIndex(0);
875     var type = console.trapType;
877     //var frameRec = console.stackView.stack.childData[0];
878     //console.pushStatus (getMsg(MSN_STATUS_STOPPED, [frameRec.functionName,
879     //                                                frameRec.location]));
880     var showHeader = (type != jsdIExecutionHook.TYPE_INTERRUPTED ||
881                       console._lastStackDepth != console.frames.length);
882     var sourceContext = (type == jsdIExecutionHook.TYPE_INTERRUPTED) ? 0 : 2
883         
884     displayFrame (jsdFrame, 0, showHeader, sourceContext);    
886     var scriptWrapper = getScriptWrapper(jsdFrame.script);
887     if (scriptWrapper)
888     {
889         dispatchCommand (console.coFindScript,
890                          { scriptWrapper: scriptWrapper, targetPc: jsdFrame.pc })
891     }
893     console._lastStackDepth = console.frames.length;
895     enableDebugCommands();
897     //XXX
898     //paintHack();
901 console.hooks["hook-venkman-query-exit"] =
902 function hookQueryExit (e)
904     if ("frames" in console)
905     {
906         if (confirm(MSG_QUERY_CLOSE))
907         {
908             dispatch ("cont");
909             console.__exitAfterContinue__ = true;
910         }
911         e.returnValue = false;
912     }
915 console.hooks["eval"] =
916 function hookEval()
918     for (var i = 0; i < $.length; ++i)
919         $[i].refresh();
921     
922 /* exceptions */
924 /* keep this list in sync with exceptionMsgNames in venkman-msg.js */
925 const ERR_NOT_IMPLEMENTED = 0;
926 const ERR_REQUIRED_PARAM  = 1;
927 const ERR_INVALID_PARAM   = 2;
928 const ERR_SUBSCRIPT_LOAD  = 3;
929 const ERR_NO_DEBUGGER     = 4;
930 const ERR_FAILURE         = 5;
931 const ERR_NO_STACK        = 6;
933 /* venkman exception class */
934 function BadMojo (errno, params)
936     var msg = getMsg(exceptionMsgNames[errno], params);
937     
938     dd ("new BadMojo (" + errno + ": " + msg + ") from\n" + getStackTrace());
939     this.message = msg;
940     this.errno = errno;
941     this.fileName = Components.stack.caller.filename;
942     this.lineNumber = Components.stack.caller.lineNumber;
943     this.functionName = Components.stack.caller.name;
946 BadMojo.prototype.toString =
947 function bm_tostring ()
949     return formatException (this);
952 function Failure (reason)
954     if (typeof reason == "undefined")
955         reason = MSG_ERR_DEFAULT_REASON;
957     var obj = new BadMojo(ERR_FAILURE, [reason]);
958     obj.fileName = Components.stack.caller.filename;
959     obj.lineNumber = Components.stack.caller.lineNumber;
960     obj.functionName = Components.stack.caller.name;
961     
962     return obj;
965 function InvalidParam (name, value)
967     var obj = new BadMojo(ERR_INVALID_PARAM, [name, String(value)]);
968     obj.fileName = Components.stack.caller.filename;
969     obj.lineNumber = Components.stack.caller.lineNumber;
970     obj.functionName = Components.stack.caller.name;
971     return obj;
974 function RequiredParam (name)
976     var obj = new BadMojo(ERR_REQUIRED_PARAM, name);
977     obj.fileName = Components.stack.caller.filename;
978     obj.lineNumber = Components.stack.caller.lineNumber;
979     obj.functionName = Components.stack.caller.name;
980     return obj;
983 /* console object */
985 console.display = display;
986 console.dispatch = dispatch;
987 console.dispatchCommand = dispatchCommand;
989 console.evalCount = 1;
991 console.metaDirectives = new Object();
993 console.metaDirectives["JSD_LOG"] =
994 console.metaDirectives["JSD_BREAK"] =
995 console.metaDirectives["JSD_EVAL"] =
996 function metaBreak (scriptInstance, line, matchResult)
998     var scriptWrapper = scriptInstance.getScriptWrapperAtLine(line);
999     if (!scriptWrapper)
1000     {
1001         display (getMsg(MSN_ERR_NO_FUNCTION, [line, scriptInstance.url]),
1002                  MT_ERROR);
1003         return;
1004     }
1005                         
1006     var pc = scriptWrapper.jsdScript.lineToPc(line, PCMAP_SOURCETEXT);
1007     if (scriptWrapper.getBreakpoint(pc))
1008         return;
1010     var sourceLine = scriptWrapper.jsdScript.pcToLine(pc, PCMAP_SOURCETEXT);
1011     var breakpoint = setFutureBreakpoint (scriptWrapper.jsdScript.fileName,
1012                                           sourceLine);
1013     scriptWrapper.setBreakpoint (pc, breakpoint);
1014     matchResult[2] = stringTrim(matchResult[2]);
1015     
1016     switch (matchResult[1])
1017     {
1018         case "JSD_LOG":
1019             breakpoint.conditionEnabled = true;
1020             breakpoint.condition = "return eval(" + matchResult[2].quote() + ")";
1021             breakpoint.resultAction = BREAKPOINT_STOPNEVER;
1022             breakpoint.logResult = true;
1023             break;
1025         case "JSD_BREAK":
1026             if (matchResult[2])
1027             {
1028                 breakpoint.conditionEnabled = true;
1029                 breakpoint.condition = "return eval(" + matchResult[2].quote() +
1030                     ")";
1031                 breakpoint.resultAction = BREAKPOINT_STOPTRUE;
1032             }
1033             else
1034             {
1035                 breakpoint.resultAction = BREAKPOINT_STOPALWAYS;
1036             }
1037             break;
1038             
1039         case "JSD_EVAL":
1040             breakpoint.conditionEnabled = true;
1041             breakpoint.condition = "return eval(" + matchResult[2].quote() + ")";
1042             breakpoint.resultAction = BREAKPOINT_STOPNEVER;
1043             break;
1044     }
1047 console.__defineGetter__ ("status", con_getstatus);
1048 function con_getstatus ()
1050     return console.ui["status-text"].getAttribute ("label");
1053 console.__defineSetter__ ("status", con_setstatus);
1054 function con_setstatus (msg)
1056     var topMsg = console._statusStack[console._statusStack.length - 1];
1058     if (msg)
1059     {        
1060         if ("_statusTimeout" in console)
1061         {
1062             clearTimeout (console._statusTimeout);
1063             delete console._statusTimeout;
1064         }
1065         if (msg != topMsg)
1066         {
1067             console._statusTimeout = setTimeout (con_setstatus,
1068                                                  console.prefs["statusDuration"],
1069                                                  null);
1070         }
1071     }
1072     else
1073     {
1074         msg = topMsg;
1075     }
1077     console.ui["status-text"].setAttribute ("label", msg);
1080 console.__defineGetter__ ("pp_stopLine", con_getppline);
1081 function con_getppline ()
1083     if (!("frames" in console))
1084         return (void 0);
1085     
1086     if (!("_pp_stopLine" in this))
1087     {
1088         var frame = getCurrentFrame();
1089         this._pp_stopLine = frame.script.pcToLine(frame.pc, PCMAP_PRETTYPRINT);
1090     }
1091     return this._pp_stopLine;
1094 console.pushStatus =
1095 function con_pushstatus (msg)
1097     console._statusStack.push (msg);
1098     console.status = msg;
1101 console.popStatus =
1102 function con_popstatus ()
1104     console._statusStack.pop();
1105     console.status = console._statusStack[console._statusStack.length - 1];
1108 function SourceText (scriptInstance)
1110     this.lines = new Array();
1111     this.tabWidth = console.prefs["tabWidth"];
1112     if (scriptInstance instanceof ScriptInstance)
1113     {
1114         this.scriptInstance = scriptInstance;
1115         this.url = scriptInstance.url;
1116         this.jsdURL = JSD_URL_SCHEME + "source?location=" + 
1117             encodeURIComponent(this.url) +
1118             "&instance=" + scriptInstance.sequence;
1119     }
1120     else
1121     {
1122         /* assume scriptInstance is a string containing the filename */
1123         this.url = scriptInstance;
1124         this.jsdURL = JSD_URL_SCHEME + "source?location=" + 
1125                       encodeURIComponent(this.url);
1126     }
1128     this.shortName = abbreviateWord(getFileFromPath (this.url), 30);
1131 SourceText.prototype.noteFutureBreakpoint =
1132 function st_notefbreak(line, state)
1134     if (!ASSERT(!("scriptInstance" in this),
1135                 "Don't call noteFutureBreakpoint on a SourceText with a " +
1136                 "scriptInstance, use the scriptManager instead."))
1137     {
1138         return;
1139     }
1140     
1141     if (state)
1142         arrayOrFlag (this.lineMap, line - 1, LINE_FBREAK);
1143     else
1144         arrayAndFlag (this.lineMap, line - 1, ~LINE_FBREAK);
1147 SourceText.prototype.onMarginClick =
1148 function st_marginclick (e, line)
1150     //dd ("onMarginClick");
1151     
1152     if (!("scriptInstance" in this))
1153     {
1154         if (getFutureBreakpoint(this.url, line))
1155         {
1156             clearFutureBreakpoint(this.url, line);
1157         }
1158         else
1159         {
1160             setFutureBreakpoint(this.url, line);
1161             //dispatch ("fbreak", { urlPattern: this.url, lineNumber: line });
1162         }
1163     }
1164     else
1165     {
1166         var parentBP = getFutureBreakpoint(this.url, line);
1167         if (parentBP)
1168         {
1169             if (this.scriptInstance.hasBreakpoint(line))
1170                 this.scriptInstance.clearBreakpoint(line);
1171             else
1172                 clearFutureBreakpoint(this.url, line);
1173         }
1174         else
1175         {
1176             if (this.scriptInstance.hasBreakpoint(line))
1177             {
1178                 this.scriptInstance.clearBreakpoint(line);
1179             }
1180             else
1181             {
1182                 parentBP = setFutureBreakpoint(this.url, line);
1183                 this.scriptInstance.setBreakpoint (line, parentBP);
1184             }
1185         }
1186     }
1189 SourceText.prototype.isLoaded = false;
1191 SourceText.prototype.reloadSource =
1192 function st_reloadsrc (cb)
1194     function reloadCB (status)
1195     {
1196         if (typeof cb == "function")
1197             cb(status);
1198     }
1200     this.isLoaded = false;
1201     this.lines = new Array();
1202     delete this.markup;
1203     delete this.charset;
1204     this.loadSource(reloadCB);
1207 SourceText.prototype.onSourceLoaded =
1208 function st_oncomplete (data, url, status)
1210     //dd ("source loaded " + url + ", " + status);
1211     
1212     var sourceText = this;
1213     
1214     function callall (status)
1215     {
1216         while (sourceText.loadCallbacks.length)
1217         {
1218             var cb = sourceText.loadCallbacks.pop();
1219             cb (status);
1220         }
1221         delete sourceText.loadCallbacks;
1222     };
1223             
1224     delete this.isLoading;
1225     
1226     if (status != Components.results.NS_OK)
1227     {
1228         dd ("loadSource failed with status " + status + ", " + url);
1229         callall (status);
1230         return;
1231     }
1233     if (!ASSERT(data, "loadSource succeeded but got no data"))
1234         data = "";
1236     var matchResult;
1237     
1238     // search for xml charset
1239     if (data.substring(0, 5) == "<?xml" && !("charset" in this))
1240     {
1241         var s = data.substring(6, data.indexOf("?>"));
1242         matchResult = s.match(/encoding\s*=\s*([\"\'])([^\"\'\s]+)\1/i);
1243         if (matchResult)
1244             this.charset = matchResult[2];
1245     }
1247     // kill control characters, except \t, \r, and \n
1248     data = data.replace(/[\x00-\x08]|[\x0B\x0C]|[\x0E-\x1F]/g, "?");
1250     // check for a html style charset declaration
1251     if (!("charset" in this))
1252     {
1253         matchResult =
1254             data.match(/meta\s+http-equiv.*content-type.*charset\s*=\s*([^\;\"\'\s]+)/i);
1255         if (matchResult)
1256             this.charset = matchResult[1];
1257     }
1259     // look for an emacs mode line
1260     matchResult = data.match (/-\*-.*tab-width\:\s*(\d+).*-\*-/);
1261     if (matchResult)
1262         this.tabWidth = matchResult[1];
1264     // replace tabs
1265     data = data.replace(/\x09/g, leftPadString ("", this.tabWidth, " "));
1266     
1267     var ary = data.split(/\r\n|\n|\r/m);        
1269     if (0)
1270     {
1271         for (var i = 0; i < ary.length; ++i)
1272         {
1273             /*
1274              * The replace() strips control characters, we leave the tabs in
1275              * so we can expand them to a per-file width before actually
1276              * displaying them.
1277              */
1278             ary[i] = ary[i].replace(/[\x00-\x08]|[\x0A-\x1F]/g, "?");
1279             if (!("charset" in this))
1280             {
1281                 matchResult = ary[i].match(charsetRE);
1282                 if (matchResult)
1283                     this.charset = matchResult[1];
1284             }
1285         }
1286     }
1287     
1288     this.lines = ary;
1290     if ("scriptInstance" in this)
1291     {
1292         this.scriptInstance.guessFunctionNames(sourceText);
1293         this.lineMap = this.scriptInstance.lineMap;
1294     }
1295     else
1296     {
1297         this.lineMap = new Array();
1298         for (var fbp in console.fbreaks)
1299         {
1300             var fbreak = console.fbreaks[fbp];
1301             if (fbreak.url == this.url)
1302                 arrayOrFlag (this.lineMap, fbreak.lineNumber - 1, LINE_FBREAK);
1303         }
1304     }
1306     this.isLoaded = true;
1307     dispatch ("hook-source-load-complete",
1308               { sourceText: sourceText, status: status });
1309     callall(status);
1313 SourceText.prototype.loadSource =
1314 function st_loadsrc (cb)
1316     var sourceText = this;
1317     
1318     function onComplete (data, url, status)
1319     {
1320         //dd ("loaded " + url + " with status " + status + "\n" + data);
1321         sourceText.onSourceLoaded (data, url, status);
1322     };
1324     if (this.isLoaded)
1325     {
1326         /* if we're loaded, callback right now, and return. */
1327         cb (Components.results.NS_OK);
1328         return;
1329     }
1331     if ("isLoading" in this)
1332     {
1333         /* if we're in the process of loading, make a note of the callback, and
1334          * return. */
1335         if (typeof cb == "function")
1336             this.loadCallbacks.push (cb);
1337         return;
1338     }
1339     else
1340         this.loadCallbacks = new Array();
1342     if (typeof cb == "function")
1343         this.loadCallbacks.push (cb);
1344     this.isLoading = true;    
1345     
1346     var ex;
1347     var src;
1348     var url = this.url;
1349     if (url.search (/^javascript:/i) == 0)
1350     {
1351         src = url;
1352         delete this.isLoading;
1353     }
1354     else
1355     {
1356         try
1357         {
1358             loadURLAsync (url, { onComplete: onComplete });
1359             return;
1360         }
1361         catch (ex)
1362         {
1363             display (getMsg(MSN_ERR_SOURCE_LOAD_FAILED, [url, ex]), MT_ERROR);
1364             onComplete (src, url, Components.results.NS_ERROR_FAILURE);
1365             return;
1366         }
1367     }
1369     onComplete (src, url, Components.results.NS_OK);
1372 function PPSourceText (scriptWrapper)
1374     this.scriptWrapper = scriptWrapper;
1375     this.reloadSource();
1376     this.shortName = scriptWrapper.functionName;
1377     this.jsdURL = JSD_URL_SCHEME + "pprint?scriptWrapper=" + scriptWrapper.tag;
1380 PPSourceText.prototype.isLoaded = true;
1382 PPSourceText.prototype.reloadSource =
1383 function ppst_reload (cb)
1385     try
1386     {
1387         var jsdScript = this.scriptWrapper.jsdScript;
1388         this.tabWidth = console.prefs["tabWidth"];
1389         this.url = jsdScript.fileName;
1390         var lines = String(jsdScript.functionSource).split("\n");
1391         var lineMap = new Array();
1392         var len = lines.length;
1393         for (var i = 0; i < len; ++i)
1394         {
1395             if (jsdScript.isLineExecutable(i + 1, PCMAP_PRETTYPRINT))
1396                 lineMap[i] = LINE_BREAKABLE;
1397         }
1398         
1399         for (var b in this.scriptWrapper.breaks)
1400         {
1401             var line = jsdScript.pcToLine(this.scriptWrapper.breaks[b].pc,
1402                                           PCMAP_PRETTYPRINT);
1403             arrayOrFlag (lineMap, line - 1, LINE_BREAK);
1404         }
1405         
1406         this.lines = lines;
1407         this.lineMap = lineMap;
1408         delete this.markup;
1409         
1410         if (typeof cb == "function")
1411             cb (Components.results.NS_OK);
1412     }
1413     catch (ex)
1414     {
1415         ASSERT(0, "caught exception reloading pretty printed source " + ex);
1416         if (typeof cb == "function")
1417             cb (Components.results.NS_ERROR_FAILURE);
1418         this.lines = [String(MSG_CANT_PPRINT)];
1419         this.lineMap = [0];
1420     }           
1423 PPSourceText.prototype.onMarginClick =
1424 function ppst_marginclick (e, line)
1426     try
1427     {
1428         var jsdScript = this.scriptWrapper.jsdScript;
1429         var pc = jsdScript.lineToPc(line, PCMAP_PRETTYPRINT);
1430         if (this.scriptWrapper.hasBreakpoint(pc))
1431             this.scriptWrapper.clearBreakpoint(pc);
1432         else
1433             this.scriptWrapper.setBreakpoint(pc);
1434     }
1435     catch (ex)
1436     {
1437         ASSERT(0, "onMarginClick caught exception " + ex);
1438     }
1441 function HelpText ()
1443     this.tabWidth = console.prefs["tabWidth"];
1444     this.jsdURL = this.url = JSD_URL_SCHEME + "help";
1445     this.shortName = this.url;
1446     this.reloadSource();
1449 HelpText.prototype.isLoaded = true;
1451 HelpText.prototype.reloadSource =
1452 function ht_reload (cb)
1454     var ary = console.commandManager.list();
1455     var str = "";
1456     for (var c in ary)
1457     {
1458         str += "\n                                        ===\n"
1459             + ary[c].getDocumentation(formatCommandFlags);
1460     }
1461     
1462     this.lines = str.split("\n");
1463     if (typeof cb == "function")
1464         cb (Components.results.NS_OK);