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 ***** */
40 const JSD_CTRID = "@mozilla.org/js/jsd/debugger-service;1";
41 const jsdIDebuggerService = Components.interfaces.jsdIDebuggerService;
42 const jsdIExecutionHook = Components.interfaces.jsdIExecutionHook;
43 const jsdIErrorHook = Components.interfaces.jsdIErrorHook;
44 const jsdICallHook = Components.interfaces.jsdICallHook;
45 const jsdIValue = Components.interfaces.jsdIValue;
46 const jsdIProperty = Components.interfaces.jsdIProperty;
47 const jsdIScript = Components.interfaces.jsdIScript;
48 const jsdIStackFrame = Components.interfaces.jsdIStackFrame;
50 const TYPE_VOID = jsdIValue.TYPE_VOID;
51 const TYPE_NULL = jsdIValue.TYPE_NULL;
52 const TYPE_BOOLEAN = jsdIValue.TYPE_BOOLEAN;
53 const TYPE_INT = jsdIValue.TYPE_INT;
54 const TYPE_DOUBLE = jsdIValue.TYPE_DOUBLE;
55 const TYPE_STRING = jsdIValue.TYPE_STRING;
56 const TYPE_FUNCTION = jsdIValue.TYPE_FUNCTION;
57 const TYPE_OBJECT = jsdIValue.TYPE_OBJECT;
59 const PROP_ENUMERATE = jsdIProperty.FLAG_ENUMERATE;
60 const PROP_READONLY = jsdIProperty.FLAG_READONLY;
61 const PROP_PERMANENT = jsdIProperty.FLAG_PERMANENT;
62 const PROP_ALIAS = jsdIProperty.FLAG_ALIAS;
63 const PROP_ARGUMENT = jsdIProperty.FLAG_ARGUMENT;
64 const PROP_VARIABLE = jsdIProperty.FLAG_VARIABLE;
65 const PROP_EXCEPTION = jsdIProperty.FLAG_EXCEPTION;
66 const PROP_ERROR = jsdIProperty.FLAG_ERROR;
67 const PROP_HINTED = jsdIProperty.FLAG_HINTED;
69 const SCRIPT_NODEBUG = jsdIScript.FLAG_DEBUG;
70 const SCRIPT_NOPROFILE = jsdIScript.FLAG_PROFILE;
72 const COLLECT_PROFILE_DATA = jsdIDebuggerService.COLLECT_PROFILE_DATA;
74 const PCMAP_SOURCETEXT = jsdIScript.PCMAP_SOURCETEXT;
75 const PCMAP_PRETTYPRINT = jsdIScript.PCMAP_PRETTYPRINT;
77 const RETURN_CONTINUE = jsdIExecutionHook.RETURN_CONTINUE;
78 const RETURN_CONT_THROW = jsdIExecutionHook.RETURN_CONTINUE_THROW;
79 const RETURN_VALUE = jsdIExecutionHook.RETURN_RET_WITH_VAL;
80 const RETURN_THROW = jsdIExecutionHook.RETURN_THROW_WITH_VAL;
83 const FTYPE_SUMMARY = 1;
84 const FTYPE_ARRAY = 2;
86 const BREAKPOINT_STOPNEVER = 0;
87 const BREAKPOINT_STOPALWAYS = 1;
88 const BREAKPOINT_STOPTRUE = 2;
89 const BREAKPOINT_EARLYRETURN = 3;
91 var $ = new Array(); /* array to store results from evals in debug frames */
93 function compareVersion(maj, min)
95 if (console.jsds.implementationMajor < maj)
98 if (console.jsds.implementationMajor > maj)
101 if (console.jsds.implementationMinor < min)
104 if (console.jsds.implementationMinor > min)
110 function initDebugger()
112 dd ("initDebugger {");
114 console.instanceSequence = 0;
115 console._continueCodeStack = new Array(); /* top of stack is the default */
116 /* return code for the most */
117 /* recent debugTrap(). */
118 console.scriptWrappers = new Object();
119 console.scriptManagers = new Object();
120 console.breaks = new Object();
121 console.fbreaks = new Object();
122 console.sbreaks = new Object();
124 /* create the debugger instance */
125 if (!(JSD_CTRID in Components.classes))
126 throw new BadMojo (ERR_NO_DEBUGGER);
129 Components.classes[JSD_CTRID].getService(jsdIDebuggerService);
132 if (compareVersion(1, 2) >= 0)
133 console.jsds.flags = jsdIDebuggerService.DISABLE_OBJECT_TRACE;
135 console.executionHook = { onExecute: jsdExecutionHook };
136 console.errorHook = { onError: jsdErrorHook };
137 console.callHook = { onCall: jsdCallHook };
139 console.jsdConsole = console.jsds.wrapValue(console);
141 dispatch ("tmode", {mode: console.prefs["lastThrowMode"]});
142 dispatch ("emode", {mode: console.prefs["lastErrorMode"]});
144 console.enumeratingScripts = true;
145 var enumer = { enumerateScript: console.scriptHook.onScriptCreated };
146 console.jsds.scriptHook = console.scriptHook;
147 console.jsds.enumerateScripts(enumer);
148 delete console.enumeratingScripts;
150 console.jsds.breakpointHook = console.executionHook;
151 console.jsds.debuggerHook = console.executionHook;
152 console.jsds.debugHook = console.executionHook;
153 console.jsds.errorHook = console.errorHook;
155 console.jsds.flags = jsdIDebuggerService.ENABLE_NATIVE_FRAMES;
157 dd ("} initDebugger");
160 function detachDebugger()
162 if ("frames" in console)
163 console.jsds.exitNestedEventLoop();
166 for (b in console.breaks)
167 console.breaks[b].clearBreakpoint();
168 for (b in console.fbreaks)
169 console.fbreaks[b].clearFutureBreakpoint();
171 console.jsds.topLevelHook = null;
172 console.jsds.functionHook = null;
173 console.jsds.breakpointHook = null;
174 console.jsds.debuggerHook = null;
175 console.jsds.debugHook = null;
176 console.jsds.errorHook = null;
177 console.jsds.scriptHook = null;
178 console.jsds.interruptHook = null;
179 console.jsds.throwHook = null;
180 console.jsds.clearAllBreakpoints();
184 if (!console.jsds.initAtStartup)
188 console.scriptHook = new Object();
190 console.scriptHook.onScriptCreated =
191 function sh_created (jsdScript)
195 jsdScriptCreated(jsdScript);
199 dd ("caught " + dumpObjectTree(ex) + " while creating script.");
203 console.scriptHook.onScriptDestroyed =
204 function sh_destroyed (jsdScript)
208 jsdScriptDestroyed(jsdScript);
212 dd ("caught " + dumpObjectTree(ex) + " while destroying script.");
216 function jsdScriptCreated (jsdScript)
218 var url = jsdScript.fileName;
221 if (!(url in console.scriptManagers))
223 manager = console.scriptManagers[url] = new ScriptManager(url);
224 //dispatchCommand (console.coManagerCreated, { scriptManager: manager });
228 manager = console.scriptManagers[url];
231 manager.onScriptCreated(jsdScript);
234 function jsdScriptDestroyed (jsdScript)
236 if (!(jsdScript.tag in console.scriptWrappers))
239 var scriptWrapper = console.scriptWrappers[jsdScript.tag];
240 scriptWrapper.scriptManager.onScriptInvalidated(scriptWrapper);
242 if (scriptWrapper.scriptManager.instances.length == 0 &&
243 scriptWrapper.scriptManager.transientCount == 0)
245 delete console.scriptManagers[scriptWrapper.scriptManager.url];
246 //dispatchCommand (console.coManagerDestroyed,
247 // { scriptManager: scriptWrapper.scriptManager });
251 function jsdExecutionHook (frame, type, rv)
253 dd ("execution hook: " + formatFrame(frame));
255 var hookReturn = jsdIExecutionHook.RETURN_CONTINUE;
257 if (!console.initialized)
261 if (!ASSERT(!("frames" in console),
262 "Execution hook called while stopped") ||
264 !ASSERT(frame.script, "Execution hook called with no script") ||
265 frame.script.fileName == MSG_VAL_CONSOLE ||
266 !ASSERT(!(frame.script.flags & SCRIPT_NODEBUG),
267 "Stopped in a script marked as don't debug") ||
268 !ASSERT(isURLVenkman(frame.script.fileName) ||
269 !isURLFiltered(frame.script.fileName),
270 "stopped in a filtered URL"))
275 var frames = new Array();
276 var prevFrame = frame;
277 var hasDisabledFrame = false;
281 frames.push(prevFrame);
282 prevFrame = prevFrame.callingFrame;
285 var targetWindow = null;
286 var wasModal = false;
291 cx = frame.executionContext;
299 var targetWasEnabled = true;
300 var debuggerWasEnabled = console.baseWindow.enabled;
301 console.baseWindow.enabled = true;
303 if (!ASSERT(cx, "no cx in execution hook"))
306 var glob = cx.globalObject;
307 if (!ASSERT(glob, "no glob in execution hook"))
310 console.targetWindow = getBaseWindowFromWindow(glob.getWrappedValue());
311 targetWasEnabled = console.targetWindow.enabled;
312 if (console.targetWindow != console.baseWindow)
314 cx.scriptsEnabled = false;
315 console.targetWindow.enabled = false;
320 //dd ("debug trap " + formatFrame(frame));
321 hookReturn = debugTrap(frames, type, rv);
322 //dd ("debug trap returned " + hookReturn);
326 display (MSG_ERR_INTERNAL_BPT, MT_ERROR);
327 display (formatException(ex), MT_ERROR);
332 if (console.targetWindow && console.targetWindow != console.baseWindow)
334 console.targetWindow.enabled = targetWasEnabled;
335 cx.scriptsEnabled = true;
338 console.baseWindow.enabled = debuggerWasEnabled;
339 delete console.frames;
340 delete console.targetWindow;
341 if ("__exitAfterContinue__" in console)
347 function jsdCallHook (frame, type)
349 if (!console.initialized)
352 if (type == jsdICallHook.TYPE_FUNCTION_CALL)
355 //dd ("Calling: " + frame.functionName);
357 else if (type == jsdICallHook.TYPE_FUNCTION_RETURN)
359 // we're called *before* the returning frame is popped from the
360 // stack, so we want our depth calculation to be off by one.
362 var prevFrame = frame;
367 prevFrame = prevFrame.callingFrame;
371 //dd ("Returning: " + frame.functionName +
372 // ", target depth: " + console._stepOverDepth +
373 // ", current depth: " + depth);
375 if (depth <= console._stepOverDepth)
377 //dd ("step over at target depth of " + depth);
379 console.jsds.functionHook = null;
380 delete console._stepOverDepth;
385 function jsdErrorHook (message, fileName, line, pos, flags, exception)
387 if (!console.initialized || isURLFiltered (fileName))
393 flagstr = (flags & jsdIErrorHook.REPORT_EXCEPTION) ? "x" : "-";
394 flagstr += (flags & jsdIErrorHook.REPORT_STRICT) ? "s" : "-";
396 //dd ("===\n" + message + "\n" + fileName + "@" +
397 // line + ":" + pos + "; " + flagstr);
398 var msn = (flags & jsdIErrorHook.REPORT_WARNING) ?
399 MSN_ERPT_WARN : MSN_ERPT_ERROR;
401 if (console.errorMode != EMODE_IGNORE)
402 display (getMsg(msn, [message, flagstr, fileName,
403 line, pos]), MT_ETRACE);
405 if (console.errorMode == EMODE_BREAK)
412 dd ("error in error hook: " + ex);
417 function ScriptManager (url)
420 this.instances = new Array();
421 this.transients = new Object();
422 this.transientCount = 0;
423 this.disableTransients = isURLFiltered(url);
426 ScriptManager.prototype.onScriptCreated =
427 function smgr_created (jsdScript)
431 if (!ASSERT(jsdScript.isValid, "invalid script created!"))
434 if (this.instances.length != 0)
435 instance = this.instances[this.instances.length - 1];
437 if (!instance || (instance.isSealed && jsdScript.functionName))
439 //dd ("instance created for " + jsdScript.fileName);
440 instance = new ScriptInstance(this);
441 instance.sequence = console.instanceSequence++;
442 this.instances.push(instance);
443 dispatchCommand (console.coInstanceCreated,
444 { scriptInstance: instance });
447 if ("_lastScriptWrapper" in console)
449 if ((console._lastScriptWrapper.scriptManager != this ||
450 console._lastScriptWrapper.scriptInstance != instance) &&
451 console._lastScriptWrapper.scriptInstance.scriptCount &&
452 !console._lastScriptWrapper.scriptInstance.isSealed)
454 console._lastScriptWrapper.scriptInstance.seal();
458 var scriptWrapper = new ScriptWrapper(jsdScript);
459 console._lastScriptWrapper = scriptWrapper;
460 scriptWrapper.scriptManager = this;
461 console.scriptWrappers[jsdScript.tag] = scriptWrapper;
462 scriptWrapper.scriptInstance = instance;
464 if (!instance.isSealed)
466 //dd ("function created " + formatScript(jsdScript));
467 instance.onScriptCreated (scriptWrapper);
471 //dd ("transient created " + formatScript(jsdScript));
472 ++this.transientCount;
473 if (this.disableTransients)
474 jsdScript.flags |= SCRIPT_NODEBUG | SCRIPT_NOPROFILE;
476 this.transients[jsdScript.tag] = scriptWrapper;
477 scriptWrapper.functionName = MSG_VAL_EVSCRIPT;
478 //dispatch ("hook-transient-script", { scriptWrapper: scriptWrapper });
482 ScriptManager.prototype.onScriptInvalidated =
483 function smgr_invalidated (scriptWrapper)
485 //dd ("script invalidated");
487 delete console.scriptWrappers[scriptWrapper.tag];
488 if (scriptWrapper.tag in this.transients)
490 //dd ("transient destroyed " + formatScript(scriptWrapper.jsdScript));
491 --this.transientCount;
492 delete this.transients[scriptWrapper.tag];
493 //dispatch ("hook-script-invalidated", { scriptWrapper: scriptWrapper });
497 //dd ("function destroyed " + formatScript(scriptWrapper.jsdScript));
498 scriptWrapper.scriptInstance.onScriptInvalidated(scriptWrapper);
499 //dispatch ("hook-script-invalidated", { scriptWrapper: scriptWrapper });
501 if (scriptWrapper.scriptInstance.scriptCount == 0)
503 var i = arrayIndexOf(this.instances, scriptWrapper.scriptInstance);
504 arrayRemoveAt(this.instances, i);
505 dispatchCommand (console.coInstanceDestroyed,
506 { scriptInstance: scriptWrapper.scriptInstance });
511 ScriptManager.prototype.__defineGetter__ ("sourceText", smgr_sourcetext);
512 function smgr_sourcetext()
514 return this.instances[this.instances.length - 1].sourceText;
517 ScriptManager.prototype.__defineGetter__ ("lineMap", smgr_linemap);
518 function smgr_linemap()
520 return this.instances[this.instances.length - 1].lineMap;
523 ScriptManager.prototype.getInstanceBySequence =
524 function smgr_bysequence (seq)
526 for (var i = 0; i < this.instances.length; ++i)
528 if (this.instances[i].sequence == seq)
529 return this.instances[i];
535 ScriptManager.prototype.isLineExecutable =
536 function smgr_isexe (line)
538 for (var i in this.instances)
540 if (this.instances[i].isLineExecutable(line))
547 ScriptManager.prototype.hasBreakpoint =
548 function smgr_hasbp (line)
550 for (var i in this.instances)
552 if (this.instances[i].hasBreakpoint(line))
559 ScriptManager.prototype.setBreakpoint =
560 function smgr_break (line, parentBP, props)
564 for (var i in this.instances)
565 found |= this.instances[i].setBreakpoint(line, parentBP, props);
570 ScriptManager.prototype.clearBreakpoint =
571 function smgr_break (line)
575 for (var i in this.instances)
576 found |= this.instances[i].clearBreakpoint(line);
581 ScriptManager.prototype.hasFutureBreakpoint =
582 function smgr_hasbp (line)
584 var key = this.url + "#" + line;
585 return (key in console.fbreaks);
588 ScriptManager.prototype.getFutureBreakpoint =
589 function smgr_getfbp (line)
591 return getFutureBreakpoint (this.url, line);
594 ScriptManager.prototype.noteFutureBreakpoint =
595 function smgr_fbreak (line, state)
597 for (var i in this.instances)
599 if (this.instances[i]._lineMapInited)
603 arrayOrFlag (this.instances[i]._lineMap, line - 1, LINE_FBREAK);
607 arrayAndFlag (this.instances[i]._lineMap, line - 1,
614 function ScriptInstance (manager)
616 this.scriptManager = manager;
617 this.url = manager.url;
618 this.creationDate = new Date();
619 this.topLevel = null;
620 this.functions = new Object();
622 this.isSealed = false;
623 this.scriptCount = 0;
624 this.breakpointCount = 0;
625 this.disabledScripts = 0;
626 this._lineMap = new Array();
627 this._lineMapInited = false;
630 ScriptInstance.prototype.scanForMetaComments =
631 function si_scan (start)
633 const CHUNK_SIZE = 500;
634 const CHUNK_DELAY = 100;
636 var scriptInstance = this;
637 var sourceText = this.sourceText;
639 function onSourceLoaded(result)
641 if (result == Components.results.NS_OK)
642 scriptInstance.scanForMetaComments();
645 if (!sourceText.isLoaded)
647 sourceText.loadSource(onSourceLoaded);
651 if (typeof start == "undefined")
654 var end = Math.min (sourceText.lines.length, start + CHUNK_SIZE);
655 var obj = new Object();
657 for (var i = start; i < end; ++i)
659 var ary = sourceText.lines[i].match (/\/\/@(\S+)(.*)/);
660 if (ary && ary[1] in console.metaDirectives && !(ary[1] in obj))
664 console.metaDirectives[ary[1]](scriptInstance, i + 1, ary);
668 display (getMsg(MSN_ERR_META_FAILED, [ary[1], this.url, i + 1]),
670 display (formatException (ex), MT_ERROR);
675 if (i != sourceText.lines.length)
676 setTimeout (this.scanForMetaComments, CHUNK_DELAY, i);
679 ScriptInstance.prototype.seal =
682 this.sealDate = new Date();
683 this.isSealed = true;
685 if (isURLFiltered(this.url))
687 this.disabledScripts = 1;
688 var nada = SCRIPT_NODEBUG | SCRIPT_NOPROFILE;
689 if (this.topLevel && this.topLevel.isValid)
690 this.topLevel.jsdScript.flags |= nada;
692 for (var f in this.functions)
694 if (this.functions[f].jsdScript.isValid)
695 this.functions[f].jsdScript.flags |= nada;
696 ++this.disabledScripts;
700 dispatch ("hook-script-instance-sealed", { scriptInstance: this });
703 ScriptInstance.prototype.onScriptCreated =
704 function si_created (scriptWrapper)
706 var tag = scriptWrapper.jsdScript.tag;
708 if (scriptWrapper.functionName)
710 this.functions[tag] = scriptWrapper;
714 this.topLevel = scriptWrapper;
715 scriptWrapper.functionName = MSG_VAL_TLSCRIPT;
716 scriptWrapper.addToLineMap(this._lineMap);
717 //var dummy = scriptWrapper.sourceText;
724 ScriptInstance.prototype.onScriptInvalidated =
725 function si_invalidated (scriptWrapper)
727 //dd ("script invalidated");
728 scriptWrapper.clearBreakpoints();
732 ScriptInstance.prototype.__defineGetter__ ("sourceText", si_gettext);
733 function si_gettext ()
735 if (!("_sourceText" in this))
736 this._sourceText = new SourceText (this);
738 return this._sourceText;
741 ScriptInstance.prototype.__defineGetter__ ("lineMap", si_linemap);
742 function si_linemap()
744 if (!this._lineMapInited)
746 if (this.topLevel && this.topLevel.jsdScript.isValid)
747 this.topLevel.addToLineMap(this._lineMap);
749 for (var i in this.functions)
751 if (this.functions[i].jsdScript.isValid)
752 this.functions[i].addToLineMap(this._lineMap);
755 for (var fbp in console.fbreaks)
757 var fbreak = console.fbreaks[fbp];
758 if (fbreak.url == this.url)
759 arrayOrFlag (this._lineMap, fbreak.lineNumber - 1, LINE_FBREAK);
762 this._lineMapInited = true;
765 return this._lineMap;
768 ScriptInstance.prototype.isLineExecutable =
769 function si_isexe (line)
771 if (this.topLevel && this.topLevel.jsdScript.isValid &&
772 this.topLevel.jsdScript.isLineExecutable (line, PCMAP_SOURCETEXT))
777 for (var f in this.functions)
779 var jsdScript = this.functions[f].jsdScript;
780 if (line >= jsdScript.baseLineNumber &&
781 line <= jsdScript.baseLineNumber + jsdScript.lineExtent &&
782 jsdScript.isLineExecutable (line, PCMAP_SOURCETEXT))
791 ScriptInstance.prototype.hasBreakpoint =
792 function si_hasbp (line)
794 return Boolean (this.getBreakpoint(line));
797 ScriptInstance.prototype.getBreakpoint =
798 function si_getbp (line)
800 for (var b in console.breaks)
802 if (console.breaks[b].scriptWrapper.scriptInstance == this)
804 if (typeof line == "undefined")
807 var jsdScript = console.breaks[b].scriptWrapper.jsdScript;
808 if (jsdScript.pcToLine(console.breaks[b].pc, PCMAP_SOURCETEXT) ==
811 return console.breaks[b];
819 ScriptInstance.prototype.setBreakpoint =
820 function si_setbp (line, parentBP, props)
822 function setBP (scriptWrapper)
824 if (!scriptWrapper.jsdScript.isValid)
827 var jsdScript = scriptWrapper.jsdScript;
829 if (line >= jsdScript.baseLineNumber &&
830 line <= jsdScript.baseLineNumber + jsdScript.lineExtent &&
831 (jsdScript.isLineExecutable (line, PCMAP_SOURCETEXT) ||
832 jsdScript.baseLineNumber == line))
834 var pc = jsdScript.lineToPc(line, PCMAP_SOURCETEXT);
835 scriptWrapper.setBreakpoint(pc, parentBP, props);
844 found = setBP (this.topLevel);
845 for (var f in this.functions)
846 found |= setBP (this.functions[f]);
848 if (this._lineMapInited && found)
849 arrayOrFlag(this._lineMap, line - 1, LINE_BREAK);
854 ScriptInstance.prototype.clearBreakpoint =
855 function si_setbp (line)
859 function clearBP (scriptWrapper)
861 var jsdScript = scriptWrapper.jsdScript;
862 if (!jsdScript.isValid)
865 var pc = jsdScript.lineToPc(line, PCMAP_SOURCETEXT);
866 if (line >= jsdScript.baseLineNumber &&
867 line <= jsdScript.baseLineNumber + jsdScript.lineExtent &&
868 scriptWrapper.hasBreakpoint(pc))
870 found |= scriptWrapper.clearBreakpoint(pc);
874 if (this._lineMapInited)
875 arrayAndFlag(this._lineMap, line - 1, ~LINE_BREAK);
878 clearBP (this.topLevel);
880 for (var f in this.functions)
881 clearBP (this.functions[f]);
886 ScriptInstance.prototype.getScriptWrapperAtLine =
887 function si_getscript (line)
889 var targetScript = null;
894 scriptWrapper = this.topLevel;
895 if (line >= scriptWrapper.jsdScript.baseLineNumber &&
896 line <= scriptWrapper.jsdScript.baseLineNumber +
897 scriptWrapper.jsdScript.lineExtent)
899 targetScript = scriptWrapper;
903 for (var f in this.functions)
905 scriptWrapper = this.functions[f];
906 if ((line >= scriptWrapper.jsdScript.baseLineNumber &&
907 line <= scriptWrapper.jsdScript.baseLineNumber +
908 scriptWrapper.jsdScript.lineExtent) &&
910 scriptWrapper.jsdScript.lineExtent <
911 targetScript.jsdScript.lineExtent))
913 targetScript = scriptWrapper;
920 ScriptInstance.prototype.containsScriptTag =
921 function si_contains (tag)
923 return ((this.topLevel && this.topLevel.tag == tag) ||
924 (tag in this.functions));
927 ScriptInstance.prototype.guessFunctionNames =
928 function si_guessnames ()
930 var sourceLines = this._sourceText.lines;
931 var context = console.prefs["guessContext"];
932 var pattern = new RegExp (console.prefs["guessPattern"]);
935 function getSourceContext (end)
937 var startLine = end - context;
943 for (i = startLine; i <= targetLine; ++i)
944 text += String(sourceLines[i]);
946 var pos = text.lastIndexOf ("function");
948 text = text.substring(0, pos);
953 for (var i in this.functions)
955 var scriptWrapper = this.functions[i];
956 if (scriptWrapper.jsdScript.functionName != "anonymous")
959 var targetLine = scriptWrapper.jsdScript.baseLineNumber;
960 if (targetLine > sourceLines.length)
962 dd ("not enough source to guess function at line " + targetLine);
966 scanText = getSourceContext(targetLine);
967 var ary = scanText.match (pattern);
970 if ("charset" in this._sourceText)
971 ary[1] = toUnicode(ary[1], this._sourceText.charset);
973 scriptWrapper.functionName = getMsg(MSN_FMT_GUESSEDNAME, ary[1]);
977 if ("guessFallback" in console)
979 var name = console.guessFallback(scriptWrapper, scanText);
982 scriptWrapper.functionName = getMsg(MSN_FMT_GUESSEDNAME,
989 dispatch ("hook-guess-complete", { scriptInstance: this });
992 function ScriptWrapper (jsdScript)
994 this.jsdScript = jsdScript;
995 this.tag = jsdScript.tag;
996 this.functionName = jsdScript.functionName;
997 this.breakpointCount = 0;
998 this._lineMap = null;
999 this.breaks = new Object();
1002 ScriptWrapper.prototype.__defineGetter__ ("sourceText", sw_getsource);
1003 function sw_getsource ()
1005 if (!("_sourceText" in this))
1007 if (!this.jsdScript.isValid)
1009 this._sourceText = new PPSourceText(this);
1012 return this._sourceText;
1015 ScriptWrapper.prototype.__defineGetter__ ("lineMap", sw_linemap);
1016 function sw_linemap ()
1019 this.addToLineMap(this._lineMap);
1021 return this._lineMap;
1024 ScriptWrapper.prototype.hasBreakpoint =
1025 function sw_hasbp (pc)
1027 var key = this.jsdScript.tag + ":" + pc;
1028 return key in console.breaks;
1031 ScriptWrapper.prototype.getBreakpoint =
1032 function sw_hasbp (pc)
1034 var key = this.jsdScript.tag + ":" + pc;
1035 if (key in console.breaks)
1036 return console.breaks[key];
1041 ScriptWrapper.prototype.setBreakpoint =
1042 function sw_setbp (pc, parentBP, props)
1044 var key = this.jsdScript.tag + ":" + pc;
1046 //dd ("setting breakpoint in " + this.functionName + " " + key);
1048 if (key in console.breaks)
1051 var brk = new BreakInstance (parentBP, this, pc);
1053 brk.setProperties(props);
1055 console.breaks[key] = brk;
1056 this.breaks[key] = brk;
1060 parentBP.childrenBP[key] = brk;
1061 brk.lineNumber = parentBP.lineNumber;
1062 brk.url = parentBP.url;
1065 if ("_sourceText" in this)
1067 var line = this.jsdScript.pcToLine(brk.pc, PCMAP_PRETTYPRINT);
1068 arrayOrFlag (this._sourceText.lineMap, line - 1, LINE_BREAK);
1071 ++this.scriptInstance.breakpointCount;
1072 ++this.breakpointCount;
1074 if (this.scriptInstance._lineMapInited)
1076 line = this.jsdScript.pcToLine (pc, PCMAP_SOURCETEXT);
1077 arrayOrFlag (this.scriptInstance._lineMap, line - 1, LINE_BREAK);
1080 dispatch ("hook-break-set", { breakWrapper: brk });
1085 ScriptWrapper.prototype.clearBreakpoints =
1086 function sw_clearbps ()
1090 for (b in this.breaks)
1091 found |= this.clearBreakpoint(this.breaks[b].pc);
1096 ScriptWrapper.prototype.clearBreakpoint =
1097 function sw_clearbp (pc)
1099 var key = this.jsdScript.tag + ":" + pc;
1100 if (!(key in console.breaks))
1103 var brk = console.breaks[key];
1105 if ("propsWindow" in brk)
1106 brk.propsWindow.close();
1108 delete console.breaks[key];
1109 delete this.breaks[key];
1112 delete brk.parentBP.childrenBP[key];
1116 if ("_sourceText" in this && this.jsdScript.isValid)
1118 line = this.jsdScript.pcToLine(brk.pc, PCMAP_PRETTYPRINT);
1119 this._sourceText.lineMap[line - 1] &= ~LINE_BREAK;
1122 --this.scriptInstance.breakpointCount;
1123 --this.breakpointCount;
1125 if (this.scriptInstance._lineMapInited)
1127 if (this.jsdScript.isValid)
1129 line = this.jsdScript.pcToLine (pc, PCMAP_SOURCETEXT);
1130 if (!this.scriptInstance.hasBreakpoint(line))
1131 this.scriptInstance._lineMap[line - 1] &= ~LINE_BREAK;
1135 /* script is gone, no way to find out where the break actually
1136 * was, so we have to redo the whole map. */
1137 this.scriptInstance._lineMapInited = false;
1138 this.scriptInstance._lineMap.length = 0;
1139 var dummy = this.scriptInstance.lineMap;
1143 dispatch ("hook-break-clear", { breakWrapper: brk });
1145 if (this.jsdScript.isValid)
1146 this.jsdScript.clearBreakpoint (pc);
1151 ScriptWrapper.prototype.addToLineMap =
1152 function sw_addmap (lineMap)
1154 var jsdScript = this.jsdScript;
1155 var end = jsdScript.baseLineNumber + jsdScript.lineExtent;
1156 if (!("enumeratingScripts" in console))
1158 for (var i = jsdScript.baseLineNumber; i < end; ++i)
1160 if (jsdScript.isLineExecutable(i, PCMAP_SOURCETEXT))
1161 arrayOrFlag (lineMap, i - 1, LINE_BREAKABLE);
1165 for (i in this.breaks)
1167 var line = jsdScript.pcToLine(this.breaks[i].pc, PCMAP_SOURCETEXT);
1168 arrayOrFlag (lineMap, line - 1, LINE_BREAK);
1172 function getScriptWrapper(jsdScript)
1174 if (!ASSERT(jsdScript, "getScriptWrapper: null jsdScript"))
1177 var tag = jsdScript.tag;
1178 if (tag in console.scriptWrappers)
1179 return console.scriptWrappers[tag];
1181 dd ("Can't find a wrapper for " + formatScript(jsdScript));
1185 function BreakInstance (parentBP, scriptWrapper, pc)
1187 this._enabled = true;
1188 this.parentBP = parentBP;
1189 this.scriptWrapper = scriptWrapper;
1191 this.url = scriptWrapper.jsdScript.fileName;
1192 this.lineNumber = scriptWrapper.jsdScript.pcToLine (pc, PCMAP_SOURCETEXT);
1193 this.oneTime = false;
1194 this.triggerCount = 0;
1196 scriptWrapper.jsdScript.setBreakpoint (pc);
1199 BreakInstance.prototype.__defineGetter__ ("jsdURL", bi_getURL);
1200 function bi_getURL ()
1202 return ("x-jsd:break?url=" + encodeURIComponent(this.url) +
1203 "&lineNumber=" + this.lineNumber +
1204 "&conditionEnabled=" + this.conditionEnabled +
1205 "&condition=" + encodeURIComponent(this.condition) +
1206 "&passExceptions=" + this.passExceptions +
1207 "&logResult=" + this.logResult +
1208 "&resultAction=" + this.resultAction +
1209 "&enabled=" + this.enabled);
1212 BreakInstance.prototype.getProperties =
1213 function bi_getprops()
1215 var rv = new Object();
1217 rv.enabled = this._enabled;
1218 if ("_conditionEnabled" in this)
1219 rv.conditionEnabled = this._conditionEnabled;
1220 if ("_condition" in this)
1221 rv.condition = this._condition;
1222 if ("_passExceptions" in this)
1223 rv.passExceptions = this._passExceptions;
1224 if ("_logResult" in this)
1225 rv.logResult = this._logResult;
1226 if ("_resultAction" in this)
1227 rv.resultAction = this._resultAction;
1232 BreakInstance.prototype.setProperties =
1233 function bi_setprops(obj)
1237 if (p.search(/pc|url|lineNumber/) == -1)
1241 if ("propsWindow" in this)
1242 this.propsWindow.populateFromBreakpoint();
1245 BreakInstance.prototype.clearBreakpoint =
1248 this.scriptWrapper.clearBreakpoint(this.pc);
1251 BreakInstance.prototype.__defineGetter__ ("enabled", bi_getEnabled);
1252 function bi_getEnabled ()
1254 return this._enabled;
1257 BreakInstance.prototype.__defineSetter__ ("enabled", bi_setEnabled);
1258 function bi_setEnabled (state)
1260 if (state != this._enabled)
1262 this._enabled = state;
1264 this.scriptWrapper.jsdScript.setBreakpoint(this.pc);
1266 this.scriptWrapper.jsdScript.clearBreakpoint(this.pc);
1272 BreakInstance.prototype.__defineGetter__ ("conditionEnabled", bi_getCondEnabled);
1273 function bi_getCondEnabled ()
1275 if ("_conditionEnabled" in this)
1276 return this._conditionEnabled;
1279 return this.parentBP.conditionEnabled;
1284 BreakInstance.prototype.__defineSetter__ ("conditionEnabled", bi_setCondEnabled);
1285 function bi_setCondEnabled (state)
1288 return this.parentBP.conditionEnabled = state;
1290 return this._conditionEnabled = state;
1293 BreakInstance.prototype.__defineGetter__ ("condition", bi_getCondition);
1294 function bi_getCondition ()
1296 if ("_condition" in this)
1297 return this._condition;
1300 return this.parentBP.condition;
1305 BreakInstance.prototype.__defineSetter__ ("condition", bi_setCondition);
1306 function bi_setCondition (value)
1309 return this.parentBP.condition = value;
1311 return this._condition = value;
1315 BreakInstance.prototype.__defineGetter__ ("passExceptions", bi_getException);
1316 function bi_getException ()
1318 if ("_passExceptions" in this)
1319 return this._passExceptions;
1322 return this.parentBP.passExceptions;
1327 BreakInstance.prototype.__defineSetter__ ("passExceptions", bi_setException);
1328 function bi_setException (state)
1331 return this.parentBP.passExceptions = state;
1333 return this._passExceptions = state;
1337 BreakInstance.prototype.__defineGetter__ ("logResult", bi_getLogResult);
1338 function bi_getLogResult ()
1340 if ("_logResult" in this)
1341 return this._logResult;
1344 return this.parentBP.logResult;
1349 BreakInstance.prototype.__defineSetter__ ("logResult", bi_setLogResult);
1350 function bi_setLogResult (state)
1353 return this.parentBP.logResult = state;
1355 return this._logResult = state;
1359 BreakInstance.prototype.__defineGetter__ ("resultAction", bi_getResultAction);
1360 function bi_getResultAction ()
1362 if ("_resultAction" in this)
1363 return this._resultAction;
1366 return this.parentBP.resultAction;
1368 return BREAKPOINT_STOPALWAYS;
1371 BreakInstance.prototype.__defineSetter__ ("resultAction", bi_setResultAction);
1372 function bi_setResultAction (state)
1375 return this.parentBP.resultAction = state;
1377 return this._resultAction = state;
1380 function FutureBreakpoint (url, lineNumber)
1383 this.lineNumber = lineNumber;
1384 this.enabled = true;
1385 this.childrenBP = new Object();
1386 this.conditionEnabled = false;
1387 this.condition = "";
1388 this.passExceptions = false;
1389 this.logResult = false;
1390 this.resultAction = BREAKPOINT_STOPALWAYS;
1393 FutureBreakpoint.prototype.__defineGetter__ ("jsdURL", fb_getURL);
1394 function fb_getURL ()
1396 return ("x-jsd:fbreak?url=" + encodeURIComponent(this.url) +
1397 "&lineNumber=" + this.lineNumber +
1398 "&conditionEnabled=" + this.conditionEnabled +
1399 "&condition=" + encodeURIComponent(this.condition) +
1400 "&passExceptions=" + this.passExceptions +
1401 "&logResult=" + this.logResult +
1402 "&resultAction=" + this.resultAction +
1403 "&enabled=" + this.enabled);
1407 FutureBreakpoint.prototype.getProperties =
1408 function fb_getprops()
1410 var rv = new Object();
1412 rv.conditionEnabled = this.conditionEnabled;
1413 rv.condition = this.condition;
1414 rv.passExceptions = this.passExceptions;
1415 rv.logResult = this.logResult;
1416 rv.resultAction = this.resultAction;
1421 FutureBreakpoint.prototype.setProperties =
1422 function fb_setprops(obj)
1426 if (p.search(/url|lineNumber|childrenBP/) == -1)
1430 if ("propsWindow" in this)
1431 this.propsWindow.populateFromBreakpoint();
1434 FutureBreakpoint.prototype.clearFutureBreakpoint =
1435 function fb_clear ()
1437 clearFutureBreakpoint (this.url, this.lineNumber);
1440 FutureBreakpoint.prototype.resetInstances =
1441 function fb_reseti ()
1443 for (var url in console.scriptManagers)
1445 if (url.indexOf(this.url) != -1)
1446 console.scriptManagers[url].setBreakpoint(this.lineNumber);
1450 FutureBreakpoint.prototype.clearInstances =
1451 function fb_cleari ()
1453 for (var url in console.scriptManagers)
1455 if (url.indexOf(this.url) != -1)
1456 console.scriptManagers[url].clearBreakpoint(this.lineNumber);
1460 function testBreakpoint(currentFrame, rv)
1462 var tag = currentFrame.script.tag;
1463 if (!(tag in console.scriptWrappers))
1466 var scriptWrapper = console.scriptWrappers[tag];
1467 var breakpoint = scriptWrapper.getBreakpoint(currentFrame.pc);
1468 if (!ASSERT(breakpoint, "can't find breakpoint for " +
1469 formatFrame(currentFrame)))
1474 if (!ASSERT(breakpoint.enabled, "stopped at a disabled breakpoint?"))
1475 return RETURN_CONTINUE;
1477 ++breakpoint.triggerCount;
1478 if ("propsWindow" in breakpoint)
1479 breakpoint.propsWindow.onBreakpointTriggered();
1481 if (breakpoint.oneTime)
1482 scriptWrapper.clearBreakpoint(currentFrame.pc);
1484 if (breakpoint.conditionEnabled && breakpoint.condition)
1486 var result = new Object();
1487 var script = "var __trigger__ = function (__count__) {" +
1488 breakpoint.condition + "}; __trigger__.apply(this, [" +
1489 breakpoint.triggerCount + "]);";
1490 if (!currentFrame.eval (script,
1491 JSD_URL_SCHEME + "breakpoint-condition",
1494 /* condition raised an exception */
1495 if (breakpoint.passExceptions)
1497 rv.value = result.value;
1498 return RETURN_THROW;
1501 display (MSG_ERR_CONDITION_FAILED, MT_ERROR);
1502 display (formatException(result.value.getWrappedValue()), MT_ERROR);
1506 /* condition executed ok */
1507 if (breakpoint.logResult)
1509 display (result.value.stringValue, MT_LOG);
1512 if (breakpoint.resultAction == BREAKPOINT_EARLYRETURN)
1514 rv.value = result.value;
1515 return RETURN_VALUE;
1518 if (breakpoint.resultAction == BREAKPOINT_STOPNEVER ||
1519 (breakpoint.resultAction == BREAKPOINT_STOPTRUE &&
1520 !result.value.booleanValue))
1522 return RETURN_CONTINUE;
1530 const EMODE_IGNORE = 0;
1531 const EMODE_TRACE = 1;
1532 const EMODE_BREAK = 2;
1534 const TMODE_IGNORE = 0;
1535 const TMODE_TRACE = 1;
1536 const TMODE_BREAK = 2;
1538 function debugTrap (frames, type, rv)
1541 var retcode = jsdIExecutionHook.RETURN_CONTINUE;
1545 var frame = frames[0];
1551 case jsdIExecutionHook.TYPE_BREAKPOINT:
1552 var bpResult = testBreakpoint(frame, rv);
1555 tn = MSG_VAL_BREAKPOINT;
1557 case jsdIExecutionHook.TYPE_DEBUG_REQUESTED:
1560 case jsdIExecutionHook.TYPE_DEBUGGER_KEYWORD:
1561 tn = MSG_VAL_DEBUGGER;
1563 case jsdIExecutionHook.TYPE_THROW:
1564 dd (dumpObjectTree(rv));
1565 display (getMsg(MSN_EXCEPTION_TRACE,
1566 [rv.value.stringValue, formatFrame(frame)]),
1568 if (rv.value.jsClassName == "Error")
1569 display (formatProperty(rv.value.getProperty("message")),
1572 if (console.throwMode != TMODE_BREAK)
1573 return jsdIExecutionHook.RETURN_CONTINUE_THROW;
1575 console.currentException = rv.value;
1576 retcode = jsdIExecutionHook.RETURN_CONTINUE_THROW;
1580 case jsdIExecutionHook.TYPE_INTERRUPTED:
1582 if (!frame.script.functionName &&
1583 isURLFiltered(frame.script.fileName))
1585 //dd ("filtered url: " + frame.script.fileName);
1586 frame.script.flags |= SCRIPT_NOPROFILE | SCRIPT_NODEBUG;
1591 if (console.prefs["prettyprint"])
1592 line = frame.script.pcToLine (frame.pc, PCMAP_PRETTYPRINT);
1595 if (console._stepPast ==
1596 frames.length + frame.script.fileName + line)
1598 //dd("stepPast: " + console._stepPast);
1602 delete console._stepPast;
1603 setStopState(false);
1606 /* don't print stop/cont messages for other types */
1609 console.jsds.functionHook = null;
1611 /* set our default return value */
1612 console._continueCodeStack.push (retcode);
1615 display (getMsg(MSN_STOP, tn), MT_STOP);
1617 /* build an array of frames */
1618 console.frames = frames;
1620 console.trapType = type;
1624 console.jsds.enterNestedEventLoop({onNest: eventLoopNested});
1628 dd ("caught " + ex + " while nested");
1631 /* execution pauses here until someone calls exitNestedEventLoop() */
1633 clearCurrentFrame();
1634 rv.value = ("currentException" in console) ? console.currentException : null;
1636 delete console.frames;
1637 delete console.trapType;
1638 delete console.currentException;
1641 dispatch ("hook-debug-continue");
1644 display (getMsg(MSN_CONT, tn), MT_CONT);
1646 return console._continueCodeStack.pop();
1649 function eventLoopNested ()
1652 window.getAttention();
1654 dispatch ("hook-debug-stop");
1657 function getCurrentFrame()
1659 if ("frames" in console)
1660 return console.frames[console._currentFrameIndex];
1665 function getCurrentFrameIndex()
1667 if (typeof console._currentFrameIndex == "undefined")
1670 return console._currentFrameIndex;
1673 function setCurrentFrameByIndex (index)
1675 if (!console.frames)
1676 throw new BadMojo (ERR_NO_STACK);
1678 ASSERT (index >= 0 && index < console.frames.length, "index out of range");
1680 console._currentFrameIndex = index;
1681 var cf = console.frames[console._currentFrameIndex];
1682 dispatch ("set-eval-obj", { jsdValue: cf });
1683 console.stopFile = (cf.isNative) ? MSG_URL_NATIVE : cf.script.fileName;
1684 console.stopLine = cf.line;
1685 delete console._pp_stopLine;
1689 function clearCurrentFrame ()
1691 if (!console.frames)
1692 throw new BadMojo (ERR_NO_STACK);
1694 if (console.currentEvalObject instanceof jsdIStackFrame)
1695 dispatch ("set-eval-obj", { jsdValue: console.jsdConsole });
1697 delete console.stopLine;
1698 delete console._pp_stopLine;
1699 delete console.stopFile;
1700 delete console._currentFrameIndex;
1703 function formatArguments (v)
1708 var ary = new Array();
1709 var p = new Object();
1710 v.getProperties (p, {});
1712 for (var i = 0; i < p.length; ++i)
1714 if (p[i].flags & jsdIProperty.FLAG_ARGUMENT)
1715 ary.push (getMsg(MSN_FMT_ARGUMENT,
1716 [p[i].name.stringValue,
1717 formatValue(p[i].value, FTYPE_SUMMARY)]));
1720 return ary.join (MSG_COMMASP);
1723 function formatFlags (flags)
1727 if (flags & PROP_ENUMERATE)
1728 s += MSG_VF_ENUMERABLE;
1729 if (flags & PROP_READONLY)
1730 s += MSG_VF_READONLY;
1731 if (flags & PROP_PERMANENT)
1732 s += MSG_VF_PERMANENT;
1733 if (flags & PROP_ALIAS)
1735 if (flags & PROP_ARGUMENT)
1736 s += MSG_VF_ARGUMENT;
1737 if (flags & PROP_VARIABLE)
1738 s += MSG_VF_VARIABLE;
1739 if (flags & PROP_ERROR)
1741 if (flags & PROP_EXCEPTION)
1742 s += MSG_VF_EXCEPTION;
1743 if (flags & PROP_HINTED)
1749 function formatProperty (p, formatType)
1752 throw new BadMojo (ERR_REQUIRED_PARAM, "p");
1754 var s = formatFlags (p.flags);
1756 if (formatType == FTYPE_ARRAY)
1758 var rv = formatValue (p.value, FTYPE_ARRAY);
1759 return [p.name.stringValue, rv[1] ? rv[1] : rv[0], rv[2], s];
1762 return getMsg(MSN_FMT_PROPERTY, [s, p.name.stringValue,
1763 formatValue(p.value)]);
1766 function formatScript (script)
1769 throw new BadMojo (ERR_REQUIRED_PARAM, "script");
1772 if (script.tag in console.scriptWrappers)
1773 functionName = console.scriptWrappers[script.tag].functionName;
1775 functionName = script.functionName;
1776 return getMsg (MSN_FMT_SCRIPT, [functionName, script.fileName]);
1779 function formatFrame (f)
1782 throw new BadMojo (ERR_REQUIRED_PARAM, "f");
1783 var url = (f.isNative) ? MSG_URL_NATIVE : f.script.fileName;
1784 return getMsg (MSN_FMT_FRAME,
1785 [f.functionName, formatArguments(f.scope), url, f.line]);
1788 function formatValue (v, formatType)
1791 throw new BadMojo (ERR_REQUIRED_PARAM, "v");
1793 if (!(v instanceof jsdIValue))
1794 throw new BadMojo (ERR_INVALID_PARAM, "v", String(v));
1801 case jsdIValue.TYPE_BOOLEAN:
1802 type = MSG_TYPE_BOOLEAN;
1803 value = String(v.booleanValue);
1805 case jsdIValue.TYPE_DOUBLE:
1806 type = MSG_TYPE_DOUBLE;
1807 value = v.doubleValue;
1809 case jsdIValue.TYPE_INT:
1810 type = MSG_TYPE_INT;
1813 case jsdIValue.TYPE_FUNCTION:
1814 type = MSG_TYPE_FUNCTION;
1815 value = v.jsFunctionName;
1817 case jsdIValue.TYPE_NULL:
1818 type = MSG_TYPE_NULL;
1819 value = MSG_TYPE_NULL;
1821 case jsdIValue.TYPE_OBJECT:
1822 if (formatType == FTYPE_STD)
1824 type = MSG_TYPE_OBJECT;
1825 value = getMsg(MSN_FMT_OBJECT, String(v.propertyCount));
1830 if (v.jsClassName == "XPCWrappedNative_NoHelper")
1831 type = MSG_CLASS_XPCOBJ;
1833 type = v.jsClassName;
1835 type = MSG_TYPE_OBJECT;
1836 value = "{" + String(v.propertyCount) + "}";
1839 case jsdIValue.TYPE_STRING:
1840 type = MSG_TYPE_STRING;
1841 var strval = v.stringValue;
1842 if (strval.length > console.prefs["maxStringLength"])
1843 strval = getMsg(MSN_FMT_LONGSTR, strval.length);
1845 strval = strval.quote()
1848 case jsdIValue.TYPE_VOID:
1849 type = MSG_TYPE_VOID;
1850 value = MSG_TYPE_VOID;
1853 type = MSG_TYPE_UNKNOWN;
1854 value = MSG_TYPE_UNKNOWN;
1858 if (formatType == FTYPE_SUMMARY)
1859 return getMsg (MSN_FMT_VALUE_SHORT, [type, value]);
1863 if (v.jsClassName == "XPCWrappedNative_NoHelper")
1864 /* translate this long, unintuitive, and common class name into
1865 * something more palatable. */
1866 className = MSG_CLASS_XPCOBJ;
1868 className = v.jsClassName;
1870 if (formatType == FTYPE_ARRAY)
1871 return [type, className, value];
1874 return getMsg (MSN_FMT_VALUE_LONG, [type, v.jsClassName, value]);
1876 return getMsg (MSN_FMT_VALUE_MED, [type, value]);
1880 function displayCallStack ()
1882 for (var i = 0; i < console.frames.length; ++i)
1883 displayFrame (console.frames[i], i);
1886 function displayProperties (v)
1889 throw new BadMojo (ERR_REQUIRED_PARAM, "v");
1891 if (!(v instanceof jsdIValue))
1892 throw new BadMojo (ERR_INVALID_PARAM, "v", String(v));
1894 var p = new Object();
1895 v.getProperties (p, {});
1896 for (var i in p.value) display(formatProperty (p.value[i]), MT_EVAL_OUT);
1899 function displaySourceContext (sourceText, line, contextLines)
1901 function onSourceLoaded (status)
1903 if (status == Components.results.NS_OK)
1904 displaySourceContext (sourceText, line, contextLines);
1907 if (sourceText.isLoaded)
1909 for (var i = line - contextLines; i <= line + contextLines; ++i)
1911 if (i > 0 && i < sourceText.lines.length)
1914 if ("charset" in sourceText)
1916 sourceLine = toUnicode(sourceText.lines[i - 1],
1917 sourceText.charset);
1921 sourceLine = sourceText.lines[i - 1];
1924 display (getMsg(MSN_SOURCE_LINE, [zeroPad (i, 3), sourceLine]),
1925 i == line ? MT_STEP : MT_SOURCE);
1931 sourceText.loadSource (onSourceLoaded);
1935 function displayFrame (jsdFrame, idx, showHeader, sourceContext)
1937 if (typeof idx == "undefined")
1939 for (idx = 0; idx < console.frames.length; ++idx)
1940 if (jsdFrame == console.frames[idx])
1943 if (idx >= console.frames.length)
1944 idx = MSG_VAL_UNKNOWN;
1947 if (typeof showHeader == "undefined")
1950 if (typeof sourceContext == "undefined")
1951 sourceContext = null;
1953 display(getMsg(MSN_FMT_FRAME_LINE, [idx, formatFrame(jsdFrame)]), MT_OUTPUT);
1955 if (!jsdFrame.isNative && sourceContext != null)
1957 var jsdScript = jsdFrame.script;
1958 var scriptWrapper = getScriptWrapper(jsdScript);
1960 if (!ASSERT(scriptWrapper, "Couldn't get a script wrapper"))
1962 if (console.prefs["prettyprint"] && jsdScript.isValid)
1964 displaySourceContext (scriptWrapper.sourceText,
1965 jsdScript.pcToLine(jsdFrame.pc,
1971 displaySourceContext (scriptWrapper.scriptInstance.sourceText,
1972 jsdFrame.line, sourceContext);
1977 function getFutureBreakpoint (urlPattern, lineNumber)
1979 var key = urlPattern + "#" + lineNumber;
1980 if (key in console.fbreaks)
1981 return console.fbreaks[key];
1986 function setFutureBreakpoint (urlPattern, lineNumber, props)
1988 var key = urlPattern + "#" + lineNumber;
1990 if (key in console.fbreaks)
1995 for (url in console.scriptManagers)
1997 if (url == urlPattern)
1998 console.scriptManagers[url].noteFutureBreakpoint(lineNumber, true);
2001 for (url in console.files)
2003 if (url == urlPattern)
2004 console.files[url].noteFutureBreakpoint(lineNumber, true);
2007 var fbreak = new FutureBreakpoint (urlPattern, lineNumber);
2009 fbreak.setProperties(props);
2010 console.fbreaks[key] = fbreak;
2012 dispatch ("hook-fbreak-set", { fbreak: fbreak });
2017 function clearFutureBreakpoint (urlPattern, lineNumber)
2019 var key = urlPattern + "#" + lineNumber;
2020 if (!(key in console.fbreaks))
2024 var fbreak = console.fbreaks[key];
2025 if ("propsWindow" in fbreak)
2026 fbreak.propsWindow.close();
2028 delete console.fbreaks[key];
2030 for (i in fbreak.childrenBP)
2031 fbreak.childrenBP[i].parentBP = null;
2035 for (url in console.scriptManagers)
2037 if (url.indexOf(urlPattern) != -1)
2038 console.scriptManagers[url].noteFutureBreakpoint(lineNumber, false);
2041 for (url in console.files)
2043 if (url == urlPattern)
2044 console.files[url].noteFutureBreakpoint(lineNumber, false);
2047 dispatch ("hook-fbreak-clear", { fbreak: fbreak });