Import 3.0 beta 3 tarball
[mozilla-extra.git] / extensions / venkman / resources / content / venkman-records.js
blob0ac7570c15f0913ecdd1d9bd0335ef7a3659678a
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
14 * License.
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.
23 * Contributor(s):
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 function initRecords()
42 var cmdary =
43 [/* "real" commands */
44 ["show-functions", cmdShowFunctions, CMD_CONSOLE],
45 ["show-ecmas", cmdShowECMAs, CMD_CONSOLE],
46 ["show-constants", cmdShowConstants, CMD_CONSOLE],
48 /* aliases */
49 ["toggle-functions", "show-functions toggle", 0],
50 ["toggle-ecmas", "show-ecma toggle", 0],
51 ["toggle-constants", "show-constants toggle", 0]
54 console.commandManager.defineCommands (cmdary);
56 var atomsvc = console.atomService;
58 WindowRecord.prototype.property = atomsvc.getAtom("item-window");
60 FileContainerRecord.prototype.property = atomsvc.getAtom("item-files");
62 FileRecord.prototype.property = atomsvc.getAtom("item-file");
64 FrameRecord.prototype.property = atomsvc.getAtom("item-frame");
65 FrameRecord.prototype.atomCurrent = atomsvc.getAtom("current-frame-flag");
67 ScriptInstanceRecord.prototype.atomUnknown = atomsvc.getAtom("item-unk");
68 ScriptInstanceRecord.prototype.atomHTML = atomsvc.getAtom("item-html");
69 ScriptInstanceRecord.prototype.atomJS = atomsvc.getAtom("item-js");
70 ScriptInstanceRecord.prototype.atomXUL = atomsvc.getAtom("item-xul");
71 ScriptInstanceRecord.prototype.atomXML = atomsvc.getAtom("item-xml");
72 ScriptInstanceRecord.prototype.atomDisabled =
73 atomsvc.getAtom("script-disabled");
75 ScriptRecord.prototype.atomFunction = atomsvc.getAtom("file-function");
76 ScriptRecord.prototype.atomBreakpoint = atomsvc.getAtom("item-has-bp");
77 ScriptRecord.prototype.atomDisabled = atomsvc.getAtom("script-disabled");
79 var prefs =
81 ["valueRecord.showFunctions", false],
82 ["valueRecord.showECMAProps", false],
83 ["valueRecord.showConstants", false],
84 ["valueRecord.brokenObjects", "^JavaPackage$"]
87 console.prefManager.addPrefs(prefs);
89 try
91 ValueRecord.prototype.brokenObjects =
92 new RegExp (console.prefs["valueRecord.brokenObjects"]);
94 catch (ex)
96 display (MSN_ERR_INVALID_PREF,
97 ["valueRecord.brokenObjects",
98 console.prefs["valueRecord.brokenObjects"]], MT_ERROR);
99 display (formatException(ex), MT_ERROR);
100 ValueRecord.prototype.brokenObjects = /^JavaPackage$/;
103 ValueRecord.prototype.atomVoid = atomsvc.getAtom("item-void");
104 ValueRecord.prototype.atomNull = atomsvc.getAtom("item-null");
105 ValueRecord.prototype.atomBool = atomsvc.getAtom("item-bool");
106 ValueRecord.prototype.atomInt = atomsvc.getAtom("item-int");
107 ValueRecord.prototype.atomDouble = atomsvc.getAtom("item-double");
108 ValueRecord.prototype.atomString = atomsvc.getAtom("item-string");
109 ValueRecord.prototype.atomFunction = atomsvc.getAtom("item-function");
110 ValueRecord.prototype.atomObject = atomsvc.getAtom("item-object");
111 ValueRecord.prototype.atomError = atomsvc.getAtom("item-error");
112 ValueRecord.prototype.atomException = atomsvc.getAtom("item-exception");
113 ValueRecord.prototype.atomHinted = atomsvc.getAtom("item-hinted");
116 /*******************************************************************************
117 * Breakpoint Record.
118 * One prototype for all breakpoint types, works only in the Breakpoints View.
119 *******************************************************************************/
121 function BPRecord (breakWrapper)
123 this.setColumnPropertyName ("col-0", "name");
124 this.setColumnPropertyName ("col-1", "line");
126 this.breakWrapper = breakWrapper;
128 if ("pc" in breakWrapper)
130 this.type = "instance";
131 this.name = breakWrapper.scriptWrapper.functionName;
132 this.line = getMsg(MSN_FMT_PC, String(breakWrapper.pc));
134 else if (breakWrapper instanceof FutureBreakpoint)
136 this.type = "future";
137 var ary = breakWrapper.url.match(/\/([^\/?]+)(\?|$)/);
138 if (ary)
139 this.name = ary[1];
140 else
141 this.name = breakWrapper.url;
143 this.line = breakWrapper.lineNumber;
147 BPRecord.prototype = new XULTreeViewRecord(console.views.breaks.share);
149 /*******************************************************************************
150 * Stack Frame Record.
151 * Represents a jsdIStackFrame, for use in the Stack View only.
152 *******************************************************************************/
154 function FrameRecord (jsdFrame)
156 if (!(jsdFrame instanceof jsdIStackFrame))
157 throw new BadMojo (ERR_INVALID_PARAM, "value");
159 this.setColumnPropertyName ("col-0", "functionName");
160 this.setColumnPropertyName ("col-1", "location");
162 this.functionName = jsdFrame.functionName;
163 if (!jsdFrame.isNative)
165 this.scriptWrapper = getScriptWrapper(jsdFrame.script);
166 this.location = getMsg(MSN_FMT_FRAME_LOCATION,
167 [getFileFromPath(jsdFrame.script.fileName),
168 jsdFrame.line, jsdFrame.pc]);
169 this.functionName = this.scriptWrapper.functionName;
171 else
173 this.scriptWrapper = null;
174 this.location = MSG_URL_NATIVE;
177 this.jsdFrame = jsdFrame;
180 FrameRecord.prototype = new XULTreeViewRecord (console.views.stack.share);
182 /*******************************************************************************
183 * Window Record.
184 * Represents a DOM window with files and child windows. For use in the
185 * Windows View.
186 *******************************************************************************/
188 function WindowRecord (win, baseURL)
190 function none() { return ""; };
191 this.setColumnPropertyName ("col-0", "displayName");
193 this.window = win;
194 this.url = win.location.href;
195 if (this.url.search(/^\w+:/) == -1)
197 if (this.url[0] == "/")
199 this.url = win.location.protocol + "//" + win.location.host +
200 this.url;
202 else
204 this.url = baseURL + this.url;
206 this.baseURL = baseURL;
208 else
210 this.baseURL = getPathFromURL(this.url);
211 if (this.baseURL.indexOf("file:///") == 0)
212 this.baseURL = "file:/" + this.baseURL.substr(8)
215 this.reserveChildren(true);
216 this.shortName = getFileFromPath (this.url);
217 if (console.prefs["enableChromeFilter"] && this.shortName == "navigator.xul")
219 this.displayName = MSG_NAVIGATOR_XUL;
221 else if (console.prefs["enableChromeFilter"] && this.shortName == "browser.xul")
223 this.displayName = MSG_BROWSER_XUL;
225 else
227 this.filesRecord = new FileContainerRecord(this);
228 this.displayName = this.shortName;
233 WindowRecord.prototype = new XULTreeViewRecord(console.views.windows.share);
235 WindowRecord.prototype.onPreOpen =
236 function wr_preopen()
238 this.childData = new Array();
240 if ("filesRecord" in this)
241 this.appendChild(this.filesRecord);
243 var framesLength = this.window.frames.length;
244 for (var i = 0; i < framesLength; ++i)
246 this.appendChild(new WindowRecord(this.window.frames[i].window,
247 this.baseURL));
251 /*******************************************************************************
252 * "File Container" Record.
253 * List of script tags found in the parent record's |window.document| property.
254 * For use in the Windows View, as a child of a WindowRecord.
255 *******************************************************************************/
257 function FileContainerRecord (windowRecord)
259 function files() { return MSG_FILES_REC; }
260 function none() { return ""; }
261 this.setColumnPropertyName ("col-0", files);
262 this.windowRecord = windowRecord;
263 this.reserveChildren(true);
266 FileContainerRecord.prototype =
267 new XULTreeViewRecord(console.views.windows.share);
269 FileContainerRecord.prototype.onPreOpen =
270 function fcr_getkids ()
272 if (!("parentRecord" in this))
273 return;
275 this.childData = new Array();
276 var doc = this.windowRecord.window.document;
277 var loc = this.windowRecord.window.location;
278 var nodeList = doc.getElementsByTagName("script");
280 for (var i = 0; i < nodeList.length; ++i)
282 var url = nodeList.item(i).getAttribute("src");
283 if (url)
285 if (url.search(/^\w+:/) == -1)
287 if (url[0] == "/")
288 url = loc.protocol + "//" + loc.host + url;
289 else
290 url = this.windowRecord.baseURL + url;
292 else
294 this.baseURL = getPathFromURL(url);
297 this.appendChild(new FileRecord(url));
302 /*******************************************************************************
303 * File Record
304 * Represents a URL, for use in the Windows View only.
305 *******************************************************************************/
307 function FileRecord (url)
309 function none() { return ""; }
310 this.setColumnPropertyName ("col-0", "shortName");
311 this.url = url;
312 this.shortName = getFileFromPath(url);
315 FileRecord.prototype = new XULTreeViewRecord(console.views.windows.share);
317 /*******************************************************************************
318 * Script Instance Record.
319 * Represents a ScriptInstance, for use in the Scripts View only.
320 *******************************************************************************/
322 function ScriptInstanceRecord(scriptInstance)
324 if (!ASSERT(scriptInstance.isSealed,
325 "Attempt to create ScriptInstanceRecord for unsealed instance"))
327 return null;
330 this.setColumnPropertyName ("col-0", "displayName");
331 this.setColumnPropertyValue ("col-1", "");
332 this.setColumnPropertyValue ("col-2", "");
333 this.reserveChildren(true);
334 this.url = scriptInstance.url;
335 var sv = console.views.scripts;
336 this.fileType = this.atomUnknown;
337 this.shortName = this.url;
338 this.group = 4;
339 this.scriptInstance = scriptInstance;
340 this.lastScriptCount = 0;
341 this.sequence = scriptInstance.sequence;
343 this.shortName = getFileFromPath(this.url);
344 var ary = this.shortName.match (/\.(js|html|xul|xml)$/i);
345 if (ary)
347 switch (ary[1].toLowerCase())
349 case "js":
350 this.fileType = this.atomJS;
351 this.group = 0;
352 break;
354 case "html":
355 this.group = 1;
356 this.fileType = this.atomHTML;
357 break;
359 case "xul":
360 this.group = 2;
361 this.fileType = this.atomXUL;
362 break;
364 case "xml":
365 this.group = 3;
366 this.fileType = this.atomXML;
367 break;
371 this.displayName = this.shortName;
372 this.sortName = this.shortName.toLowerCase();
373 return this;
376 ScriptInstanceRecord.prototype =
377 new XULTreeViewRecord(console.views.scripts.share);
379 ScriptInstanceRecord.prototype.onDragStart =
380 function scr_dragstart (e, transferData, dragAction)
382 transferData.data = new TransferData();
383 transferData.data.addDataForFlavour("text/x-venkman-file", this.fileName);
384 transferData.data.addDataForFlavour("text/x-moz-url", this.fileName);
385 transferData.data.addDataForFlavour("text/unicode", this.fileName);
386 transferData.data.addDataForFlavour("text/html",
387 "<a href='" + this.fileName +
388 "'>" + this.fileName + "</a>");
389 return true;
392 ScriptInstanceRecord.prototype.getProperties =
393 function scr_getprops (properties)
395 properties.AppendElement(this.fileType);
397 if (this.scriptInstance.disabledScripts > 0)
398 properties.AppendElement (this.atomDisabled);
401 ScriptInstanceRecord.prototype.super_resort = XTRootRecord.prototype.resort;
403 ScriptInstanceRecord.prototype.resort =
404 function scr_resort ()
406 console._groupFiles = console.prefs["scriptsView.groupFiles"];
407 this.super_resort();
408 delete console._groupFiles;
411 ScriptInstanceRecord.prototype.sortCompare =
412 function scr_compare (a, b)
414 if (0)
416 if (a.group < b.group)
417 return -1;
419 if (a.group > b.group)
420 return 1;
423 if (a.sortName < b.sortName)
424 return -1;
426 if (a.sortName > b.sortName)
427 return 1;
429 if (a.sequence < b.sequence)
430 return -1;
432 if (a.sequence > b.sequence)
433 return 1;
435 dd ("ack, all equal?");
436 return 0;
439 ScriptInstanceRecord.prototype.onPreOpen =
440 function scr_preopen ()
442 if (!this.scriptInstance.sourceText.isLoaded)
443 this.scriptInstance.sourceText.loadSource();
445 if (this.lastScriptCount != this.scriptInstance.scriptCount)
447 var sr;
449 console.views.scripts.freeze();
450 this.childData = new Array();
451 var scriptWrapper = this.scriptInstance.topLevel;
452 if (scriptWrapper)
454 sr = new ScriptRecord(scriptWrapper);
455 scriptWrapper.scriptRecord = sr;
456 this.appendChild(sr);
459 var functions = this.scriptInstance.functions;
460 for (var f in functions)
462 if (functions[f].jsdScript.isValid)
464 sr = new ScriptRecord(functions[f]);
465 functions[f].scriptRecord = sr;
466 this.appendChild(sr);
469 console.views.scripts.thaw();
470 this.lastScriptCount = this.scriptInstance.scriptCount;
474 /*******************************************************************************
475 * Script Record.
476 * Represents a ScriptWrapper, for use in the Scripts View only.
477 *******************************************************************************/
479 function ScriptRecord(scriptWrapper)
481 this.setColumnPropertyName ("col-0", "functionName");
482 this.setColumnPropertyName ("col-1", "baseLineNumber");
483 this.setColumnPropertyName ("col-2", "lineExtent");
485 this.functionName = scriptWrapper.functionName
486 this.baseLineNumber = scriptWrapper.jsdScript.baseLineNumber;
487 this.lineExtent = scriptWrapper.jsdScript.lineExtent;
488 this.scriptWrapper = scriptWrapper;
490 this.jsdurl = "jsd:sourcetext?url=" +
491 encodeURIComponent(this.scriptWrapper.jsdScript.fileName) +
492 "&base=" + this.baseLineNumber + "&extent=" + this.lineExtent +
493 "&name=" + this.functionName;
496 ScriptRecord.prototype = new XULTreeViewRecord(console.views.scripts.share);
498 ScriptRecord.prototype.onDragStart =
499 function sr_dragstart (e, transferData, dragAction)
501 var fileName = this.script.fileName;
502 transferData.data = new TransferData();
503 transferData.data.addDataForFlavour("text/x-jsd-url", this.jsdurl);
504 transferData.data.addDataForFlavour("text/x-moz-url", fileName);
505 transferData.data.addDataForFlavour("text/unicode", fileName);
506 transferData.data.addDataForFlavour("text/html",
507 "<a href='" + fileName +
508 "'>" + fileName + "</a>");
509 return true;
512 ScriptRecord.prototype.getProperties =
513 function sr_getprops (properties)
515 properties.AppendElement (this.atomFunction);
517 if (this.scriptWrapper.breakpointCount)
518 properties.AppendElement (this.atomBreakpoint);
520 if (this.scriptWrapper.jsdScript.isValid &&
521 this.scriptWrapper.jsdScript.flags & SCRIPT_NODEBUG)
523 properties.AppendElement (this.atomDisabled);
527 /*******************************************************************************
528 * Value Record.
529 * Use this to show a jsdIValue in any tree.
530 *******************************************************************************/
532 function cmdShowFunctions (e)
534 if (e.toggle != null)
536 e.toggle = getToggle(e.toggle, ValueRecord.prototype.showFunctions);
537 ValueRecord.prototype.showFunctions = e.toggle;
538 console.prefs["valueRecord.showFunctions"] = e.toggle;
541 if ("isInteractive" in e && e.isInteractive)
542 dispatch("pref valueRecord.showFunctions", { isInteractive: true });
545 function cmdShowECMAs (e)
547 if (e.toggle != null)
549 e.toggle = getToggle(e.toggle, ValueRecord.prototype.showECMAProps);
550 ValueRecord.prototype.showECMAProps = e.toggle;
551 console.prefs["valueRecord.showECMAProps"] = e.toggle;
554 if ("isInteractive" in e && e.isInteractive)
555 dispatch("pref valueRecord.showECMAProps", { isInteractive: true });
558 function cmdShowConstants (e)
560 if (e.toggle != null)
562 e.toggle = getToggle(e.toggle, ValueRecord.prototype.showConstants);
563 ValueRecord.prototype.showConstants = e.toggle;
564 console.prefs["valueRecord.showConstants"] = e.toggle;
567 if ("isInteractive" in e && e.isInteractive)
568 dispatch("pref valueRecord.showConstants", { isInteractive: true });
571 function ValueRecord (value, name, flags, jsdFrame)
573 if (!(value instanceof jsdIValue))
574 throw new BadMojo (ERR_INVALID_PARAM, "value", String(value));
576 this.setColumnPropertyName ("col-0", "displayName");
577 this.setColumnPropertyName ("col-1", "displayType");
578 this.setColumnPropertyName ("col-2", "displayValue");
579 this.setColumnPropertyName ("col-3", "displayFlags");
580 this.displayName = name;
581 this.displayFlags = formatFlags(flags);
582 this.name = name;
583 this.flags = flags;
584 this.value = value;
585 this.jsdFrame = jsdFrame;
586 this.jsType = null;
587 this.onPreRefresh = false;
588 this.refresh();
589 delete this.onPreRefresh;
592 ValueRecord.prototype = new XULTreeViewRecord (null);
594 ValueRecord.prototype.__defineGetter__("_share", vr_getshare);
595 function vr_getshare()
597 if ("__share" in this)
598 return this.__share;
600 if ("parentRecord" in this)
601 return this.__share = this.parentRecord._share;
603 ASSERT (0, "ValueRecord cannot be the root of a visible tree.");
604 return null;
607 ValueRecord.prototype.__defineGetter__("expression", vr_getexpressionl);
608 function vr_getexpressionl()
610 return this.getExpression();
613 ValueRecord.prototype.getExpression =
614 function vr_getexpression(extra)
616 var items = [this.displayName];
618 if ("value" in this.parentRecord)
620 var cur = this.parentRecord;
621 while (!("isRootRecord" in cur) || !cur.isRootRecord)
623 if ("isECMAProto" in cur)
624 items.unshift("__proto__");
625 else if ("isECMAParent" in cur)
626 items.unshift("__parent__");
627 else
628 items.unshift(cur.displayName);
629 cur = cur.parentRecord;
633 if (typeof extra == "string")
634 items.push(extra);
636 return makeExpression(items);
639 ValueRecord.prototype.evalString =
640 function vr_evalstring(string)
642 //dd("ValueRecord(" + this.displayName + ").evalString(" + string + ")");
643 var rval = new Object();
644 if (this.jsdFrame.eval(string, JSD_URL_SCHEME + "value-record", 1, rval))
645 return rval.value;
646 return undefined;
649 ValueRecord.prototype.showFunctions = false;
650 ValueRecord.prototype.showECMAProps = false;
651 ValueRecord.prototype.showConstants = false;
653 ValueRecord.prototype.getProperties =
654 function vr_getprops (properties)
656 if ("valueIsException" in this || this.flags & PROP_EXCEPTION)
657 properties.AppendElement (this.atomException);
659 if (this.flags & PROP_ERROR)
660 properties.AppendElement (this.atomError);
662 if (this.flags & PROP_HINTED)
663 properties.AppendElement (this.atomHinted);
665 properties.AppendElement (this.property);
668 ValueRecord.prototype.onPreRefresh =
669 function vr_prerefresh ()
671 if (!ASSERT("parentRecord" in this, "onPreRefresh with no parent"))
672 return;
674 if ("isECMAProto" in this)
676 if (this.parentRecord.value.jsPrototype)
677 this.value = this.parentRecord.value.jsPrototype;
678 else
679 this.value = console.jsds.wrapValue(null);
681 else if ("isECMAParent" in this)
683 if (this.parentRecord.value.jsParent)
684 this.value = this.parentRecord.value.jsParent;
685 else
686 this.value = console.jsds.wrapValue(null);
688 else
690 var value = this.parentRecord.value;
691 var prop = value.getProperty (this.name);
692 if (prop)
694 this.flags = prop.flags;
695 this.value = prop.value;
697 else
699 ASSERT(this.jsdFrame, "ValueRecord(" + this.displayName +
700 ").onPreRefresh: no jsdIStackFrame to safely eval on!");
702 this.value = this.evalString(this.expression);
703 this.flags = PROP_ENUMERATE | PROP_HINTED;
708 ValueRecord.prototype.refresh =
709 function vr_refresh ()
711 if (this.onPreRefresh)
715 this.onPreRefresh();
716 delete this.valueIsException;
718 catch (ex)
721 dd ("caught exception refreshing " + this.displayName);
722 if (typeof ex == "object")
723 dd (dumpObjectTree(ex));
724 else
725 dd(ex);
727 if (!(ex instanceof jsdIValue))
728 ex = console.jsds.wrapValue(ex);
730 this.value = ex;
731 this.valueIsException = true;
735 this.jsType = this.value.jsType;
736 delete this.alwaysHasChildren;
738 var strval;
740 switch (this.jsType)
742 case TYPE_VOID:
743 this.displayValue = MSG_TYPE_VOID
744 this.displayType = MSG_TYPE_VOID;
745 this.property = this.atomVoid;
746 break;
747 case TYPE_NULL:
748 this.displayValue = MSG_TYPE_NULL;
749 this.displayType = MSG_TYPE_NULL;
750 this.property = this.atomNull;
751 break;
752 case TYPE_BOOLEAN:
753 this.displayValue = this.value.stringValue;
754 this.displayType = MSG_TYPE_BOOLEAN;
755 this.property = this.atomBool;
756 break;
757 case TYPE_INT:
758 this.displayValue = this.value.intValue;
759 this.displayType = MSG_TYPE_INT;
760 this.property = this.atomInt;
761 break;
762 case TYPE_DOUBLE:
763 this.displayValue = this.value.doubleValue;
764 this.displayType = MSG_TYPE_DOUBLE;
765 this.property = this.atomDouble;
766 break;
767 case TYPE_STRING:
768 strval = this.value.stringValue;
769 if (strval.length > console.prefs["maxStringLength"])
770 strval = getMsg(MSN_FMT_LONGSTR, strval.length);
771 else
772 strval = strval.quote();
773 this.displayValue = strval;
774 this.displayType = MSG_TYPE_STRING;
775 this.property = this.atomString;
776 break;
777 case TYPE_FUNCTION:
778 case TYPE_OBJECT:
779 this.displayType = MSG_TYPE_OBJECT;
780 this.property = this.atomObject;
782 this.alwaysHasChildren = true;
783 this.value.refresh();
785 var ctor = this.value.jsClassName;
786 strval = null;
788 switch (ctor)
790 case "Function":
791 this.displayType = MSG_TYPE_FUNCTION;
792 ctor = (this.value.isNative ? MSG_CLASS_NATIVE_FUN :
793 MSG_CLASS_SCRIPT_FUN);
794 this.property = this.atomFunction;
795 break;
797 case "Object":
798 if (this.value.jsConstructor)
799 ctor = this.value.jsConstructor.jsFunctionName;
800 break;
802 case "XPCWrappedNative_NoHelper":
803 ctor = MSG_CLASS_CONST_XPCOBJ;
804 break;
806 case "XPC_WN_ModsAllowed_Proto_JSClass":
807 ctor = MSG_CLASS_XPCOBJ;
808 break;
810 case "String":
811 strval = this.value.stringValue;
812 if (strval.length > console.prefs["maxStringLength"])
813 strval = getMsg(MSN_FMT_LONGSTR, strval.length);
814 else
815 strval = strval.quote();
816 break;
818 case "Number":
819 case "Boolean":
820 strval = this.value.stringValue;
821 break;
824 if (strval != null)
826 this.displayValue = strval;
828 else
830 if (0) {
831 /* too slow... */
832 var propCount;
833 if (this.brokenObjects.test(ctor))
835 /* XXX these objects do Bad Things when you enumerate
836 * over them. */
837 propCount = 0;
839 else
841 propCount = this.countProperties();
844 this.displayValue = getMsg (MSN_FMT_OBJECT_VALUE,
845 [ctor, propCount]);
847 else
849 this.displayValue = "{" + ctor + "}";
853 /* if we have children, refresh them. */
854 if ("childData" in this && this.childData.length > 0)
856 if (!this.refreshChildren())
858 dd ("refreshChilren failed for " + this.displayName);
859 delete this.childData;
860 this.close();
863 break;
865 default:
866 ASSERT (0, "invalid value");
870 ValueRecord.prototype.countProperties =
871 function vr_countprops ()
873 ASSERT(this.jsdFrame, "ValueRecord(" + this.displayName +
874 ").countProperties: no jsdIStackFrame to safely eval on!");
876 // Note: uses an inline function to avoid polluting the frame's scope.
877 var code = "(function(obj){" +
878 " var count = 0;" +
879 " for (var prop in obj)" +
880 " ++count;" +
881 " return count;" +
882 "})(" + this.expression + ")";
884 // rv is undefined if an exception occured.
885 var rv = this.evalString(code);
886 if (typeof rv == "undefined")
887 return 0;
889 return rv.intValue;
892 ValueRecord.prototype.listProperties =
893 function vr_listprops ()
895 function charEscapeReplace(s, c)
897 return String.fromCharCode(parseInt(c, 16));
900 // the ":" prefix for keys in the propMap avoid collisions with "real"
901 // pseudo-properties, such as __proto__. If we were to actually assign
902 // to those we would introduce bad side affects.
904 //dd ("listProperties {");
905 var i, jsval;
906 var propMap = new Object();
908 /* get the enumerable properties */
910 ASSERT(this.jsdFrame, "ValueRecord(" + this.displayName +
911 ").listProperties: no jsdIStackFrame to safely eval on!");
913 var propList = new Array();
915 // quote() puts double-quotes at either end of the string,
916 // backspash-escapes double-quotes in the string, and (quite
917 // importantly) uses \xXX and \uXXXX escapes for non-ASCII
918 // characters.
920 // Note: uses an inline function to avoid polluting the frame's scope.
921 var code = "(function(obj){" +
922 " var string = '';" +
923 " for (var prop in obj) {" +
924 " if (string)" +
925 " string += ',';" +
926 " string += prop.quote();" +
927 " }" +
928 " return string;" +
929 "})(" + this.expression + ")";
931 // list is undefined if an exception occured.
932 var list = this.evalString(code);
933 if (typeof list != "undefined") {
934 list = list.stringValue;
935 //dd("ValueRecord(" + this.displayName +
936 // ").listProperties: list: " + list);
937 if (list) {
938 list = ('",' + list + ',"').split('","');
940 for (i = 0; i < list.length; i++)
942 if (!list[i])
943 continue;
945 var prop = list[i];
946 prop = prop.replace(/\\x([0-9a-f]{2})/i, charEscapeReplace);
947 prop = prop.replace(/\\u([0-9a-f]{4})/i, charEscapeReplace);
948 prop = prop.replace(/\\(.)/, "$1");
949 propList.push(prop);
950 //dd("ValueRecord(" + this.displayName +
951 // ").listProperties: prop: " + prop);
956 for (i = 0; i < propList.length; i++)
958 var p = propList[i];
959 var value;
962 value = this.evalString(this.getExpression(p));
964 if (this.showFunctions || value.jsType != TYPE_FUNCTION)
966 propMap[":" + p] = { name: p, value: value,
967 flags: PROP_ENUMERATE | PROP_HINTED };
969 else
971 //dd ("not including function " + name);
972 propMap[":" + p] = null;
975 catch (ex)
977 propMap[":" + p] = { name: p, value: console.jsds.wrapValue(ex),
978 flags: PROP_EXCEPTION };
981 //dd ("jsval props: adding " + p + ", " + propMap[":" + p]);
985 /* get the local properties, may or may not be enumerable */
986 var localProps = new Object()
987 this.value.getProperties(localProps, {});
988 localProps = localProps.value;
989 var len = localProps.length;
990 for (i = 0; i < len; ++i)
992 var prop = localProps[i];
993 var name = prop.name.stringValue;
995 if (!((":" + name) in propMap))
997 if ((this.showFunctions || prop.value.jsType != TYPE_FUNCTION) &&
998 (this.showConstants || !(prop.flags & PROP_READONLY)))
1000 //dd ("localProps: adding " + name + ", " + prop);
1001 propMap[":" + name] = { name: name, value: prop.value,
1002 flags: prop.flags };
1004 else
1006 //dd ("not including function " + name);
1007 propMap[":" + name] = null;
1010 else
1012 if (!this.showConstants && (prop.flags & PROP_READONLY))
1013 propMap[":" + name] = null;
1014 if (propMap[":" + name])
1015 propMap[":" + name].flags = prop.flags;
1019 /* sort the property list */
1020 var nameList = keys(propMap);
1021 //dd ("nameList is " + nameList);
1023 nameList.sort();
1024 var propertyList = new Array();
1025 for (i = 0; i < nameList.length; ++i)
1027 name = nameList[i];
1028 if (propMap[name])
1029 propertyList.push (propMap[name]);
1032 //dd ("} " + propertyList.length + " properties");
1034 return propertyList;
1037 ValueRecord.prototype.refreshChildren =
1038 function vr_refreshkids ()
1040 var leadingProps = 0;
1042 this.propertyList = this.listProperties();
1044 for (var i = 0; i < this.childData.length; ++i)
1046 if ("isECMAParent" in this.childData[i] ||
1047 "isECMAProto" in this.childData[i])
1049 ++leadingProps;
1051 else if (this.childData.length - leadingProps !=
1052 this.propertyList.length)
1054 dd ("refreshChildren: property length mismatch");
1055 return false;
1057 else if (this.childData[i]._colValues["col-0"] !=
1058 this.propertyList[i - leadingProps].name)
1060 dd ("refreshChildren: " +
1061 this.childData[i]._colValues["col-0"] + " != " +
1062 this.propertyList[i - leadingProps].name);
1063 return false;
1066 this.childData[i].refresh();
1069 if (this.childData.length - leadingProps !=
1070 this.propertyList.length)
1072 dd ("refreshChildren: property length mismatch");
1073 return false;
1075 return true;
1078 ValueRecord.prototype.onPreOpen =
1079 function vr_preopen()
1083 if (!ASSERT(this.value.jsType == TYPE_OBJECT ||
1084 this.value.jsType == TYPE_FUNCTION,
1085 "onPreOpen called for non object?"))
1087 return;
1090 this.childData = new Array();
1091 this.propertyList = this.listProperties();
1093 if (this.showECMAProps)
1095 var rec;
1096 if (this.value.jsPrototype)
1098 rec = new ValueRecord(this.value.jsPrototype,
1099 MSG_VAL_PROTO, "", this.jsdFrame);
1100 rec.isECMAProto = true;
1101 this.appendChild (rec);
1104 if (this.value.jsParent)
1106 rec = new ValueRecord(this.value.jsParent,
1107 MSG_VAL_PARENT, "", this.jsdFrame);
1108 rec.isECMAParent = true;
1109 this.appendChild (rec);
1113 if (!this.childData.length && !this.propertyList.length)
1115 rec = new XTLabelRecord ("col-0", MSG_VAL_NONE,
1116 ["col-1", "col-2", "col-3"]);
1117 this.appendChild(rec);
1118 return;
1121 for (var i = 0; i < this.propertyList.length; ++i)
1123 var prop = this.propertyList[i];
1124 this.appendChild(new ValueRecord(prop.value,
1125 prop.name,
1126 prop.flags,
1127 this.jsdFrame));
1130 catch (ex)
1132 display (getMsg (MSN_ERR_FAILURE, ex), MT_ERROR);
1136 ValueRecord.prototype.onPostClose =
1137 function vr_destroy()
1139 this.childData = new Array();
1140 delete this.propertyList;