1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
16 * The Original Code is The JavaScript Debugger.
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.
24 * Robert Ginda, <rginda@netscape.com>, original author
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.
38 * ***** END LICENSE BLOCK ***** */
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 */
56 warn = function (msg) { dumpln ("** WARNING " + msg + " **"); }
57 ASSERT = function (expr, msg) {
59 dump ("** ASSERTION FAILED: " + msg + " **\n" +
60 getStackTrace() + "\n");
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"];
89 console.jsds.interruptHook = console.executionHook;
90 tb.setAttribute("willStop", "true");
94 console.jsds.interruptHook = null;
95 tb.removeAttribute("willStop");
99 function setProfileState(state)
101 var tb = console.ui["profile-button"];
104 console.profiler.enabled = true;
105 tb.setAttribute("profile", "true");
109 console.profiler.enabled = false;
110 tb.removeAttribute("profile");
114 function enableDebugCommands()
116 var cmds = console.commandManager.list ("", CMD_NEED_STACK);
118 cmds[i].enabled = true;
120 cmds = console.commandManager.list ("", CMD_NO_STACK);
122 cmds[i].enabled = false;
125 function disableDebugCommands()
127 var cmds = console.commandManager.list ("", CMD_NEED_STACK);
129 cmds[i].enabled = false;
131 cmds = console.commandManager.list ("", CMD_NO_STACK);
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",
147 // Evil hack: check if the chrome registry knows about Inspector.
148 // If it does, it's installed, otherwise it isn't.
151 var cr = Components.classes[CHROMEREG_CTRID].getService(nsIChromeReg);
152 var realURI = cr.convertChromeURL(uri);
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)
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)
189 console.ucConverter.charset = charset;
190 return console.ucConverter.ConvertToUnicode(msg);
194 dd ("caught " + ex + " converting to unicode");
199 function fromUnicode (msg, charset)
203 console.ucConverter.charset = charset;
204 return console.ucConverter.ConvertFromUnicode(msg);
208 dd ("caught " + ex + " converting from unicode");
213 function displayUsageError (e, details)
215 if (!("isInteractive" in e) || !e.isInteractive)
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);
228 display (details, MT_ERROR);
231 display (getMsg(MSN_FMT_USAGE, [e.command.name, e.command.usage]), MT_USAGE);
234 function dispatch (text, e, flags)
239 if (!("inputData" in e))
242 /* split command from arguments */
243 var ary = text.match (/(\S+) ?(.*)/);
244 e.commandText = ary[1];
245 e.inputData = ary[2] ? stringTrim(ary[2]) : "";
247 /* list matching commands */
248 ary = console.commandManager.list (e.commandText, flags);
255 /* no match, try again */
256 display (getMsg(MSN_NO_CMDMATCH, e.commandText), MT_ERROR);
260 /* one match, good for you */
264 rv = dispatchCommand(ary[0], e, flags);
268 display (getMsg(MSN_ERR_INTERNAL_DISPATCH, ary[0].name),
270 display (formatException(ex), MT_ERROR);
271 dd (formatException(ex), MT_ERROR);
272 if (typeof ex == "object" && "stack" in ex)
278 /* more than one match, show the list */
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);
289 function dispatchCommand (command, e, flags)
291 function callHooks (command, isBefore)
296 hooks = command.beforeHooks;
298 hooks = command.afterHooks;
302 if ("dbgDispatch" in console && console.dbgDispatch)
304 dd ("calling " + (isBefore ? "before" : "after") +
313 if (e.command.name != "hook-session-display")
315 display (getMsg(MSN_ERR_INTERNAL_HOOK, h), MT_ERROR);
316 display (formatException(ex), MT_ERROR);
320 dd (getMsg(MSN_ERR_INTERNAL_HOOK, h));
323 dd ("Caught exception calling " +
324 (isBefore ? "before" : "after") + " hook " + h);
325 dd (formatException(ex));
326 if (typeof ex == "object" && "stack" in ex)
329 dd (getStackTrace());
336 if ((e.command.flags & CMD_NEED_STACK) &&
337 (!("frames" in console)))
339 /* doc, it hurts when I do /this/... */
340 display (MSG_ERR_NO_STACK, MT_ERROR);
344 if (!e.command.enabled)
346 /* disabled command */
347 display (getMsg(MSN_ERR_DISABLED, e.command.name),
354 if ("beforeHooks" in e.command)
355 callHooks (e.command, true);
357 if (typeof e.command.func == "function")
359 /* dispatch a real function */
361 console.commandManager.parseArguments (e);
362 if ("parseError" in e)
364 displayUsageError (e, e.parseError);
368 if ("dbgDispatch" in console && console.dbgDispatch)
371 for (i = 0; i < e.command.argNames.length; ++i)
373 var name = e.command.argNames[i];
375 str += " " + name + ": " + e[name];
376 else if (name != ":")
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;
387 e.returnValue = e.command.func(e);
392 else if (typeof e.command.func == "string")
394 /* dispatch an alias (semicolon delimited list of subcommands) */
395 var commandList = e.command.func.split(";");
396 for (i = 0; i < commandList.length; ++i)
398 var newEvent = Clone (e);
399 delete newEvent.command;
400 commandList[i] = stringTrim(commandList[i]);
401 dispatch (commandList[i], newEvent, flags);
406 display (getMsg(MSN_ERR_NOTIMPLEMENTED, e.command.name),
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]);
435 dispatchCommand(console.coDisplayHook,
436 { message: message, msgtype: msgtype });
439 function evalInDebuggerScope (script, rethrow)
443 return console.doEval (script);
450 display (formatEvalException(ex), MT_ERROR);
455 function evalInTargetScope (script, rethrow)
459 display (MSG_ERR_NO_STACK, MT_ERROR);
463 var rval = new Object();
465 if (!getCurrentFrame().eval (script, MSG_VAL_CONSOLE, 1, rval))
470 //dd ("exception: " + dumpObjectTree(rval.value));
471 display (formatEvalException (rval.value), MT_ERROR);
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,
485 if (ex instanceof Error)
486 return getMsg (MSN_FMT_JSEXCEPTION, [ex.name, ex.message, ex.fileName,
492 function formatEvalException (ex)
494 if (ex instanceof BadMojo || ex instanceof Error)
495 return formatException (ex);
496 else if (ex instanceof jsdIValue)
499 return getMsg (MSN_EVAL_THREW, String(ex));
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;
524 console.files = new Object();
525 console.pluginState = new Object();
527 console._statusStack = new Array();
528 console._lastStackDepth = -1;
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);
549 console.capturedMsgs = new Array();
550 var ary = console.prefs["initialScripts"].split(/\s*;\s*/);
551 for (i = 0; i < ary.length; ++i)
553 var url = stringTrim(ary[i]);
555 dispatch ("loadd", { url: ary[i] });
558 dispatch ("hook-venkman-started");
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();
571 "status-text": document.getElementById ("status-text"),
572 "profile-button": document.getElementById ("maintoolbar:profile-tb"),
573 "stop-button": document.getElementById ("maintoolbar:stop")
576 disableDebugCommands();
581 // read prefs that have not been explicitly created, such as the layout prefs
582 console.prefManager.readPrefs();
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;
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"] });
609 dispatch ("pprint", { toggle: false });
611 if (MSG_LOCALE_VERSION != __vnk_requiredLocale)
613 display (getMsg(MSN_BAD_LOCALE,
614 [__vnk_requiredLocale, MSG_LOCALE_VERSION]),
618 // Delay being "done" until the window is up.
619 setTimeout(initPost, 100);
621 if (console.prefs["saveSettingsOnExit"])
623 dispatch ("restore-settings",
624 {settingsFile: console.prefs["settingsFile"]});
627 dispatch ("hook-venkman-started");
632 function initApplicationCompatibility()
634 // This function does nothing more than tweak the UI based on the host
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...
645 // Use the XULAppInfo.ID to find out what host we run on.
648 case "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}":
649 console.host = "Firefox";
650 console.haveBrowser = true;
652 case "{3550f703-e582-4d05-9a08-453d09bdfdc6}": // Thunderbird
653 console.host = "Thunderbird";
655 case "{a463f10c-3994-11da-9945-000d60ca027b}": // Flock
656 console.host = "Flock";
657 console.haveBrowser = true;
659 case "{718e30fb-e89b-41dd-9da7-e25a45638b28}": // Sunbird
660 console.host = "Sunbird";
662 case "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}": // SeaMonkey
663 console.host = "Mozilla";
664 console.haveBrowser = true;
667 console.unknownAppUID = app.ID;
668 console.host = "ToolkitApp"; // Unknown host, platform install
671 else if ("getBrowserURL" in window)
673 var url = getBrowserURL();
674 if (url == "chrome://navigator/content/navigator.xul")
676 console.host = "Mozilla";
677 console.haveBrowser = true;
679 else if (url == "chrome://browser/content/browser.xul")
681 console.host = "Firefox";
682 console.haveBrowser = true;
686 console.unknownAppUID = url;
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;
717 console.initialized = true;
722 if (console.prefs["saveLayoutOnExit"])
723 dispatch ("save-layout default");
725 if (console.prefs["saveSettingsOnExit"])
727 dispatch ("save-settings",
728 {settingsFile: console.prefs["settingsFile"]});
731 delete console.currentEvalObject;
732 delete console.jsdConsole;
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
746 for (var w in console.viewManager.windows)
748 var window = console.viewManager.windows[w];
749 var textbox = window.document.getElementById("paint-hack");
761 setTimeout (paintHack, 250, i + 1);
764 function fetchLaunchCount()
766 ++console.prefs["startupCount"];
768 if (!toBool(console.prefs["permitStartupHit"]))
773 var ary = String(r.responseText).match(/(\d+)/);
776 display (getMsg(MSN_LAUNCH_COUNT,
777 [console.prefs["startupCount"], ary[1]]));
783 var r = new XMLHttpRequest();
786 __vnk_counter_url + "?local=" + console.prefs["startupCount"] +
787 "&version=" + __vnk_version);
792 // Oops. Probably missing the xmlextras extension, can't really do
794 display(getMsg(MSN_LAUNCH_COUNT,
795 [console.prefs["startupCount"], MSG_VAL_UNKNOWN]));
799 function getCommandEnabled(command)
802 var dispatcher = top.document.commandDispatcher;
803 var controller = dispatcher.getControllerForCommand(command);
805 return controller.isCommandEnabled(command);
813 function doCommand(command)
816 var dispatcher = top.document.commandDispatcher;
817 var controller = dispatcher.getControllerForCommand(command);
818 if (controller && controller.isCommandEnabled(command))
819 controller.doCommand(command);
826 console.__defineGetter__ ("userAgent", con_ua);
829 var ary = navigator.userAgent.match (/;\s*([^;\s]+\s*)\).*\/(\d+)/);
832 return ("Venkman " + __vnk_version + __vnk_versionSuffix +
833 " [Mozilla " + ary[1] + "/" + ary[2] + "]");
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))
848 const VNK_SVC = "venkman-service.js";
849 if (url.substr(-VNK_SVC.length) == VNK_SVC)
851 if (!console.prefs["enableChromeFilter"])
853 dispatch ("debug-instance-on",
854 { scriptInstance: e.scriptInstance });
856 console.componentPath = url.substr(0, url.length - VNK_SVC.length);
860 for (var fbp in console.fbreaks)
862 if (console.fbreaks[fbp].enabled &&
863 url.indexOf(console.fbreaks[fbp].url) != -1)
865 e.scriptInstance.setBreakpoint(console.fbreaks[fbp].lineNumber,
866 console.fbreaks[fbp]);
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
884 displayFrame (jsdFrame, 0, showHeader, sourceContext);
886 var scriptWrapper = getScriptWrapper(jsdFrame.script);
889 dispatchCommand (console.coFindScript,
890 { scriptWrapper: scriptWrapper, targetPc: jsdFrame.pc })
893 console._lastStackDepth = console.frames.length;
895 enableDebugCommands();
901 console.hooks["hook-venkman-query-exit"] =
902 function hookQueryExit (e)
904 if ("frames" in console)
906 if (confirm(MSG_QUERY_CLOSE))
909 console.__exitAfterContinue__ = true;
911 e.returnValue = false;
915 console.hooks["eval"] =
918 for (var i = 0; i < $.length; ++i)
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);
938 dd ("new BadMojo (" + errno + ": " + msg + ") from\n" + getStackTrace());
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;
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;
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;
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);
1001 display (getMsg(MSN_ERR_NO_FUNCTION, [line, scriptInstance.url]),
1006 var pc = scriptWrapper.jsdScript.lineToPc(line, PCMAP_SOURCETEXT);
1007 if (scriptWrapper.getBreakpoint(pc))
1010 var sourceLine = scriptWrapper.jsdScript.pcToLine(pc, PCMAP_SOURCETEXT);
1011 var breakpoint = setFutureBreakpoint (scriptWrapper.jsdScript.fileName,
1013 scriptWrapper.setBreakpoint (pc, breakpoint);
1014 matchResult[2] = stringTrim(matchResult[2]);
1016 switch (matchResult[1])
1019 breakpoint.conditionEnabled = true;
1020 breakpoint.condition = "return eval(" + matchResult[2].quote() + ")";
1021 breakpoint.resultAction = BREAKPOINT_STOPNEVER;
1022 breakpoint.logResult = true;
1028 breakpoint.conditionEnabled = true;
1029 breakpoint.condition = "return eval(" + matchResult[2].quote() +
1031 breakpoint.resultAction = BREAKPOINT_STOPTRUE;
1035 breakpoint.resultAction = BREAKPOINT_STOPALWAYS;
1040 breakpoint.conditionEnabled = true;
1041 breakpoint.condition = "return eval(" + matchResult[2].quote() + ")";
1042 breakpoint.resultAction = BREAKPOINT_STOPNEVER;
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];
1060 if ("_statusTimeout" in console)
1062 clearTimeout (console._statusTimeout);
1063 delete console._statusTimeout;
1067 console._statusTimeout = setTimeout (con_setstatus,
1068 console.prefs["statusDuration"],
1077 console.ui["status-text"].setAttribute ("label", msg);
1080 console.__defineGetter__ ("pp_stopLine", con_getppline);
1081 function con_getppline ()
1083 if (!("frames" in console))
1086 if (!("_pp_stopLine" in this))
1088 var frame = getCurrentFrame();
1089 this._pp_stopLine = frame.script.pcToLine(frame.pc, PCMAP_PRETTYPRINT);
1091 return this._pp_stopLine;
1094 console.pushStatus =
1095 function con_pushstatus (msg)
1097 console._statusStack.push (msg);
1098 console.status = msg;
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)
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;
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);
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."))
1142 arrayOrFlag (this.lineMap, line - 1, LINE_FBREAK);
1144 arrayAndFlag (this.lineMap, line - 1, ~LINE_FBREAK);
1147 SourceText.prototype.onMarginClick =
1148 function st_marginclick (e, line)
1150 //dd ("onMarginClick");
1152 if (!("scriptInstance" in this))
1154 if (getFutureBreakpoint(this.url, line))
1156 clearFutureBreakpoint(this.url, line);
1160 setFutureBreakpoint(this.url, line);
1161 //dispatch ("fbreak", { urlPattern: this.url, lineNumber: line });
1166 var parentBP = getFutureBreakpoint(this.url, line);
1169 if (this.scriptInstance.hasBreakpoint(line))
1170 this.scriptInstance.clearBreakpoint(line);
1172 clearFutureBreakpoint(this.url, line);
1176 if (this.scriptInstance.hasBreakpoint(line))
1178 this.scriptInstance.clearBreakpoint(line);
1182 parentBP = setFutureBreakpoint(this.url, line);
1183 this.scriptInstance.setBreakpoint (line, parentBP);
1189 SourceText.prototype.isLoaded = false;
1191 SourceText.prototype.reloadSource =
1192 function st_reloadsrc (cb)
1194 function reloadCB (status)
1196 if (typeof cb == "function")
1200 this.isLoaded = false;
1201 this.lines = new Array();
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);
1212 var sourceText = this;
1214 function callall (status)
1216 while (sourceText.loadCallbacks.length)
1218 var cb = sourceText.loadCallbacks.pop();
1221 delete sourceText.loadCallbacks;
1224 delete this.isLoading;
1226 if (status != Components.results.NS_OK)
1228 dd ("loadSource failed with status " + status + ", " + url);
1233 if (!ASSERT(data, "loadSource succeeded but got no data"))
1238 // search for xml charset
1239 if (data.substring(0, 5) == "<?xml" && !("charset" in this))
1241 var s = data.substring(6, data.indexOf("?>"));
1242 matchResult = s.match(/encoding\s*=\s*([\"\'])([^\"\'\s]+)\1/i);
1244 this.charset = matchResult[2];
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))
1254 data.match(/meta\s+http-equiv.*content-type.*charset\s*=\s*([^\;\"\'\s]+)/i);
1256 this.charset = matchResult[1];
1259 // look for an emacs mode line
1260 matchResult = data.match (/-\*-.*tab-width\:\s*(\d+).*-\*-/);
1262 this.tabWidth = matchResult[1];
1265 data = data.replace(/\x09/g, leftPadString ("", this.tabWidth, " "));
1267 var ary = data.split(/\r\n|\n|\r/m);
1271 for (var i = 0; i < ary.length; ++i)
1274 * The replace() strips control characters, we leave the tabs in
1275 * so we can expand them to a per-file width before actually
1278 ary[i] = ary[i].replace(/[\x00-\x08]|[\x0A-\x1F]/g, "?");
1279 if (!("charset" in this))
1281 matchResult = ary[i].match(charsetRE);
1283 this.charset = matchResult[1];
1290 if ("scriptInstance" in this)
1292 this.scriptInstance.guessFunctionNames(sourceText);
1293 this.lineMap = this.scriptInstance.lineMap;
1297 this.lineMap = new Array();
1298 for (var fbp in console.fbreaks)
1300 var fbreak = console.fbreaks[fbp];
1301 if (fbreak.url == this.url)
1302 arrayOrFlag (this.lineMap, fbreak.lineNumber - 1, LINE_FBREAK);
1306 this.isLoaded = true;
1307 dispatch ("hook-source-load-complete",
1308 { sourceText: sourceText, status: status });
1313 SourceText.prototype.loadSource =
1314 function st_loadsrc (cb)
1316 var sourceText = this;
1318 function onComplete (data, url, status)
1320 //dd ("loaded " + url + " with status " + status + "\n" + data);
1321 sourceText.onSourceLoaded (data, url, status);
1326 /* if we're loaded, callback right now, and return. */
1327 cb (Components.results.NS_OK);
1331 if ("isLoading" in this)
1333 /* if we're in the process of loading, make a note of the callback, and
1335 if (typeof cb == "function")
1336 this.loadCallbacks.push (cb);
1340 this.loadCallbacks = new Array();
1342 if (typeof cb == "function")
1343 this.loadCallbacks.push (cb);
1344 this.isLoading = true;
1349 if (url.search (/^javascript:/i) == 0)
1352 delete this.isLoading;
1358 loadURLAsync (url, { onComplete: onComplete });
1363 display (getMsg(MSN_ERR_SOURCE_LOAD_FAILED, [url, ex]), MT_ERROR);
1364 onComplete (src, url, Components.results.NS_ERROR_FAILURE);
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)
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)
1395 if (jsdScript.isLineExecutable(i + 1, PCMAP_PRETTYPRINT))
1396 lineMap[i] = LINE_BREAKABLE;
1399 for (var b in this.scriptWrapper.breaks)
1401 var line = jsdScript.pcToLine(this.scriptWrapper.breaks[b].pc,
1403 arrayOrFlag (lineMap, line - 1, LINE_BREAK);
1407 this.lineMap = lineMap;
1410 if (typeof cb == "function")
1411 cb (Components.results.NS_OK);
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)];
1423 PPSourceText.prototype.onMarginClick =
1424 function ppst_marginclick (e, line)
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);
1433 this.scriptWrapper.setBreakpoint(pc);
1437 ASSERT(0, "onMarginClick caught exception " + ex);
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();
1459 + ary[c].getDocumentation(formatCommandFlags);
1462 this.lines = str.split("\n");
1463 if (typeof cb == "function")
1464 cb (Components.results.NS_OK);