1 /* See license.txt for terms of usage */ 2 3 define([ 4 "firebug/lib/object", 5 "firebug/lib/array", 6 "firebug/firebug", 7 "firebug/lib/domplate", 8 "firebug/chrome/firefox", 9 "firebug/lib/xpcom", 10 "firebug/lib/locale", 11 "firebug/html/htmlLib", 12 "firebug/lib/events", 13 "firebug/lib/wrapper", 14 "firebug/lib/options", 15 "firebug/lib/url", 16 "firebug/js/sourceLink", 17 "firebug/js/stackFrame", 18 "firebug/lib/css", 19 "firebug/lib/dom", 20 "firebug/chrome/window", 21 "firebug/lib/system", 22 "firebug/lib/xpath", 23 "firebug/lib/string", 24 "firebug/lib/xml", 25 "firebug/dom/toggleBranch", 26 "firebug/console/eventMonitor", 27 "firebug/chrome/menu", 28 "arch/compilationunit", 29 ], 30 function(Obj, Arr, Firebug, Domplate, Firefox, Xpcom, Locale, HTMLLib, Events, Wrapper, Options, 31 Url, SourceLink, StackFrame, Css, Dom, Win, System, Xpath, Str, Xml, ToggleBranch, 32 EventMonitor, Menu, CompilationUnit) { 33 34 with (Domplate) { 35 36 // ********************************************************************************************* // 37 // Constants 38 39 const Cc = Components.classes; 40 const Ci = Components.interfaces; 41 42 // xxxHonza: the only global should be Firebug object. 43 var FirebugReps = window.FirebugReps = {}; 44 45 try 46 { 47 // xxxHonza: RJS 48 var FBS = {}; 49 Components.utils["import"]("resource://firebug/firebug-service.js", FBS); 50 var jsd = Cc["@mozilla.org/js/jsd/debugger-service;1"].getService(Ci.jsdIDebuggerService); 51 } 52 catch (err) 53 { 54 } 55 56 // ********************************************************************************************* // 57 // Common Tags 58 59 // use pre here to keep line breaks while copying multiline strings 60 var OBJECTBOX = FirebugReps.OBJECTBOX = 61 PRE({"class": "objectBox inline objectBox-$className", role : "presentation"}); 62 63 var OBJECTBLOCK = FirebugReps.OBJECTBLOCK = 64 DIV({"class": "objectBox objectBox-$className focusRow subLogRow", role : "listitem"}); 65 66 var OBJECTLINK = FirebugReps.OBJECTLINK = 67 A({ 68 "class": "objectLink objectLink-$className a11yFocus", 69 _repObject: "$object" 70 }); 71 72 // ********************************************************************************************* // 73 74 FirebugReps.Undefined = domplate(Firebug.Rep, 75 { 76 tag: OBJECTBOX("undefined"), 77 78 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 79 80 className: "undefined", 81 82 supportsObject: function(object, type) 83 { 84 return type == "undefined"; 85 } 86 }); 87 88 // ********************************************************************************************* // 89 90 FirebugReps.Null = domplate(Firebug.Rep, 91 { 92 tag: OBJECTBOX("null"), 93 94 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 95 96 className: "null", 97 98 supportsObject: function(object, type) 99 { 100 return object == null; 101 } 102 }); 103 104 // ********************************************************************************************* // 105 106 FirebugReps.Hint = domplate(Firebug.Rep, 107 { 108 tag: OBJECTBOX("$object"), 109 110 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 111 112 className: "hint", 113 }); 114 115 // ********************************************************************************************* // 116 117 FirebugReps.Nada = domplate(Firebug.Rep, 118 { 119 tag: SPAN(""), 120 121 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 122 123 className: "nada" 124 }); 125 126 // ********************************************************************************************* // 127 128 FirebugReps.Number = domplate(Firebug.Rep, 129 { 130 tag: OBJECTBOX("$object"), 131 132 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 133 134 className: "number", 135 136 supportsObject: function(object, type) 137 { 138 return type == "boolean" || type == "number"; 139 } 140 }); 141 142 // ********************************************************************************************* // 143 144 FirebugReps.String = domplate(Firebug.Rep, 145 { 146 tag: OBJECTBOX(""$object""), 147 148 shortTag: OBJECTBOX(""$object|cropMultipleLines""), 149 150 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 151 152 className: "string", 153 154 supportsObject: function(object, type) 155 { 156 return type == "string"; 157 } 158 }); 159 160 // ********************************************************************************************* // 161 162 FirebugReps.XML = domplate(Firebug.Rep, 163 { 164 tag: OBJECTBOX("$object|asString"), 165 166 shortTag: OBJECTBOX("$object|asShortString"), 167 168 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 169 170 className: "xml", 171 172 supportsObject: function(object, type) 173 { 174 return type == "xml"; 175 }, 176 177 asString: function(object) 178 { 179 return object.toXMLString(); 180 }, 181 182 asShortString: function(object) 183 { 184 return cropMultipleLines(this.asString(object)); 185 }, 186 }); 187 188 // ********************************************************************************************* // 189 190 FirebugReps.Text = domplate(Firebug.Rep, 191 { 192 tag: OBJECTBOX("$object"), 193 194 shortTag: OBJECTBOX("$object|cropMultipleLines"), 195 196 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 197 198 className: "text" 199 }); 200 201 // ********************************************************************************************* // 202 203 FirebugReps.Caption = domplate(Firebug.Rep, 204 { 205 tag: SPAN({"class": "caption"}, "$object") 206 }); 207 208 // ********************************************************************************************* // 209 210 FirebugReps.Warning = domplate(Firebug.Rep, 211 { 212 tag: DIV({"class": "warning focusRow", role : 'listitem'}, "$object|STR") 213 }); 214 215 // ********************************************************************************************* // 216 217 FirebugReps.Func = domplate(Firebug.Rep, 218 { 219 tag: 220 OBJECTLINK("$object|summarizeFunction"), 221 222 summarizeFunction: function(fn) 223 { 224 var fnText = Str.safeToString(fn); 225 var namedFn = /^function ([^(]+\([^)]*\)) \{/.exec(fnText); 226 var anonFn = /^function \(/.test(fnText); 227 var displayName = fn.displayName; 228 229 return namedFn ? namedFn[1] : (displayName ? displayName + "()" : 230 (anonFn ? "function()" : fnText)); 231 }, 232 233 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 234 235 copySource: function(fn) 236 { 237 if (fn && typeof (fn['toSource']) == 'function') 238 System.copyToClipboard(fn.toSource()); 239 }, 240 241 monitor: function(fn, monitored) 242 { 243 if (monitored) 244 Firebug.Debugger.unmonitorFunction(fn, "monitor"); 245 else 246 Firebug.Debugger.monitorFunction(fn, "monitor"); 247 }, 248 249 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 250 251 className: "function", 252 253 supportsObject: function(object, type) 254 { 255 return type == "function"; 256 }, 257 258 inspectObject: function(fn, context) 259 { 260 var sourceLink = Firebug.SourceFile.findSourceForFunction(fn, context); 261 if (sourceLink) 262 Firebug.chrome.select(sourceLink); 263 if (FBTrace.DBG_FUNCTION_NAME) 264 FBTrace.sysout("reps.function.inspectObject selected sourceLink is ", sourceLink); 265 }, 266 267 getTooltip: function(fn, context) 268 { 269 var script = Firebug.SourceFile.findScriptForFunctionInContext(context, fn); 270 if (script) 271 { 272 return Locale.$STRF("Line", [Url.normalizeURL(script.fileName), 273 script.baseLineNumber]); 274 } 275 else 276 { 277 if (fn.toString) 278 return fn.toString(); 279 } 280 }, 281 282 getTitle: function(fn, context) 283 { 284 var name = fn.name ? fn.name : "function"; 285 return name + "()"; 286 }, 287 288 getContextMenuItems: function(fn, target, context, script) 289 { 290 if (!script) 291 script = Firebug.SourceFile.findScriptForFunctionInContext(context, fn); 292 if (!script) 293 return; 294 295 var scriptInfo = Firebug.SourceFile.getSourceFileAndLineByScript(context, script); 296 var monitored = scriptInfo ? FBS.fbs.isMonitored(scriptInfo.sourceFile.href, 297 scriptInfo.lineNo) : false; 298 299 var self = this; 300 var name = script ? StackFrame.getFunctionName(script, context) : fn.name; 301 return [ 302 { 303 label: Locale.$STRF("ShowCallsInConsole", [name]), 304 tooltiptext: Locale.$STRF("dom.tip.Log_Calls_To_Function", [name]), 305 nol10n: true, 306 type: "checkbox", 307 checked: monitored, 308 command: function() 309 { 310 var checked = this.hasAttribute("checked"); 311 self.monitor(fn, !checked); 312 } 313 }, 314 "-", 315 { 316 label: "CopySource", 317 tooltiptext: "dom.tip.Copy_Source", 318 command: Obj.bindFixed(this.copySource, this, fn) 319 } 320 ]; 321 } 322 }); 323 324 // ********************************************************************************************* // 325 326 FirebugReps.Obj = domplate(Firebug.Rep, 327 { 328 tag: 329 OBJECTLINK( 330 SPAN({"class": "objectTitle"}, "$object|getTitle "), 331 SPAN({"class": "objectLeftBrace", role: "presentation"}, "{"), 332 FOR("prop", "$object|shortPropIterator", 333 " $prop.name", 334 SPAN({"class": "objectEqual", role: "presentation"}, "$prop.equal"), 335 TAG("$prop.tag", {object: "$prop.object"}), 336 SPAN({"class": "objectComma", role: "presentation"}, "$prop.delim") 337 ), 338 SPAN({"class": "objectRightBrace"}, "}") 339 ), 340 341 shortTag: 342 OBJECTLINK( 343 SPAN({"class": "objectTitle"}, "$object|getTitle "), 344 SPAN({"class": "objectLeftBrace", role: "presentation"}, "{"), 345 FOR("prop", "$object|shortPropIterator", 346 " $prop.name", 347 SPAN({"class": "objectEqual", role: "presentation"}, "$prop.equal"), 348 TAG("$prop.tag", {object: "$prop.object"}), 349 SPAN({"class": "objectComma", role: "presentation"}, "$prop.delim") 350 ), 351 SPAN({"class": "objectRightBrace"}, "}") 352 ), 353 354 titleTag: 355 SPAN({"class": "objectTitle"}, "$object|getTitleTag"), 356 357 getTitleTag: function(object) 358 { 359 var title; 360 if (typeof(object) == "string") 361 title = object; 362 else 363 title = this.getTitle(object); 364 365 if (title == "Object") 366 title = "{...}"; 367 368 return title; 369 }, 370 371 longPropIterator: function (object) 372 { 373 return this.propIterator(object, 100); 374 }, 375 376 shortPropIterator: function (object) 377 { 378 return this.propIterator(object, Options.get("ObjectShortIteratorMax")); 379 }, 380 381 propIterator: function (object, max) 382 { 383 var props = []; 384 385 // Object members with non-empty values are preferred since it gives the 386 // user a better overview of the object. 387 this.getProps(props, object, max, function(t, value) 388 { 389 return (t == "boolean" || t == "number" || (t == "string" && value) || 390 (t == "object" && value && value.toString)); 391 }); 392 393 if (props.length+1 <= max) 394 { 395 // There is not enough props yet, let's display also empty members and functions. 396 this.getProps(props, object, max, function(t, value) 397 { 398 return ((t == "string" && !value) || (t == "object" && !value) || 399 (t == "function")); 400 }); 401 } 402 403 if (props.length > max) 404 { 405 props[props.length-1] = { 406 object: Locale.$STR("firebug.reps.more") + "...", 407 tag: FirebugReps.Caption.tag, 408 name: "", 409 equal: "", 410 delim: "" 411 }; 412 } 413 else if (props.length > 0) 414 { 415 props[props.length-1].delim = ''; 416 } 417 418 return props; 419 }, 420 421 getProps: function (props, object, max, filter) 422 { 423 max = max || 3; 424 if (!object) 425 return []; 426 427 var len = 0; 428 429 try 430 { 431 for (var name in object) 432 { 433 var value; 434 try 435 { 436 value = object[name]; 437 } 438 catch (exc) 439 { 440 continue; 441 } 442 443 var t = typeof(value); 444 if (filter(t, value)) 445 { 446 var rep = Firebug.getRep(value); 447 var tag = rep.shortTag || rep.tag; 448 if ((t == "object" || t == "function") && value) 449 { 450 value = rep.getTitle(value); 451 if (rep.titleTag) 452 tag = rep.titleTag; 453 else 454 tag = FirebugReps.Obj.titleTag; 455 } 456 457 if (props.length <= max) 458 props.push({tag: tag, name: name, object: value, equal: "=", delim: ", "}); 459 else 460 break; 461 } 462 } 463 } 464 catch (exc) 465 { 466 // Sometimes we get exceptions when trying to read from certain objects, like 467 // StorageList, but don't let that gum up the works 468 // XXXjjb also History.previous fails because object is a web-page object 469 // which does not have permission to read the history 470 } 471 }, 472 473 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 474 475 className: "object", 476 477 supportsObject: function(object, type) 478 { 479 return true; 480 } 481 }); 482 483 // ********************************************************************************************* // 484 // Reference 485 486 /** 487 * A placeholder used instead of cycle reference within arrays. 488 * @param {Object} target The original referenced object 489 */ 490 FirebugReps.ReferenceObj = function(target) 491 { 492 this.target = target; 493 } 494 495 /** 496 * Rep for cycle reference in an array. 497 */ 498 FirebugReps.Reference = domplate(Firebug.Rep, 499 { 500 tag: 501 OBJECTLINK({_repObject: "$object"}, 502 SPAN({title: "$object|getTooltip"}, 503 "[...]") 504 ), 505 506 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 507 508 className: "Reference", 509 510 supportsObject: function(object, type) 511 { 512 return (object instanceof FirebugReps.ReferenceObj); 513 }, 514 515 getTooltip: function(object) 516 { 517 return Locale.$STR("firebug.reps.reference"); 518 }, 519 520 getRealObject: function(object) 521 { 522 return object.target; 523 }, 524 }); 525 526 // ********************************************************************************************* // 527 528 FirebugReps.ArrBase = domplate(FirebugReps.Obj, 529 { 530 className: "array", 531 toggles: new ToggleBranch.ToggleBranch(), 532 533 titleTag: 534 SPAN({"class": "objectTitle"}, "$object|getTitleTag"), 535 536 getTitle: function(object, context) 537 { 538 return "[" + object.length + "]"; 539 }, 540 541 supportsObject: function(object, type) 542 { 543 return this.isArray(object); 544 }, 545 546 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 547 548 longArrayIterator: function(array) 549 { 550 return this.arrayIterator(array, 300); 551 }, 552 553 shortArrayIterator: function(array) 554 { 555 return this.arrayIterator(array, Options.get("ObjectShortIteratorMax")); 556 }, 557 558 arrayIterator: function(array, max) 559 { 560 var items = []; 561 for (var i = 0; i < array.length && i <= max; ++i) 562 { 563 try 564 { 565 var delim = (i == array.length-1 ? "" : ", "); 566 var value = array[i]; 567 568 // Cycle detected 569 if (value === array) 570 value = new FirebugReps.ReferenceObj(value); 571 572 var rep = Firebug.getRep(value); 573 var tag = rep.shortTag || rep.tag; 574 items.push({object: value, tag: tag, delim: delim}); 575 } 576 catch (exc) 577 { 578 var rep = Firebug.getRep(exc); 579 var tag = rep.shortTag || rep.tag; 580 581 items.push({object: exc, tag: tag, delim: delim}); 582 } 583 } 584 585 if (array.length > max + 1) 586 { 587 items[max] = { 588 object: (array.length-max) + " " + Locale.$STR("firebug.reps.more") + "...", 589 tag: FirebugReps.Caption.tag, 590 delim: "" 591 }; 592 } 593 594 return items; 595 }, 596 597 getItemIndex: function(child) 598 { 599 var arrayIndex = 0; 600 for (child = child.previousSibling; child; child = child.previousSibling) 601 { 602 if (child.repObject) 603 ++arrayIndex; 604 } 605 return arrayIndex; 606 }, 607 608 /** 609 * Returns true if the passed object is an array with additional (custom) properties, 610 * otherwise returns false. Custom properties should be displayed in extra expandable 611 * section. 612 * 613 * Example array with a custom property. 614 * var arr = [0, 1]; 615 * arr.myProp = "Hello"; 616 * 617 * @param {Array} array The array object. 618 */ 619 hasSpecialProperties: function(array) 620 { 621 function isInteger(x) 622 { 623 var y = parseInt(x, 10); 624 if (isNaN(y)) 625 return false; 626 return x === y.toString(); 627 } 628 629 var n = 0; 630 var props = Object.getOwnPropertyNames(array); 631 for (var i=0; i<props.length; i++) 632 { 633 var p = props[i]; 634 635 // Valid indexes are skipped 636 if (isInteger(p)) 637 continue; 638 639 // Ignore standard 'length' property, anything else is custom. 640 if (p != "length") 641 return true; 642 } 643 644 return false; 645 }, 646 647 onToggleProperties: function(event) 648 { 649 var target = event.originalTarget; 650 if (Css.hasClass(target, "objectBox-array")) 651 { 652 Events.cancelEvent(event); 653 654 Css.toggleClass(target, "opened"); 655 656 var propBox = target.getElementsByClassName("arrayProperties").item(0); 657 if (Css.hasClass(target, "opened")) 658 { 659 Firebug.DOMPanel.DirTable.tag.replace( 660 {object: target.repObject, toggles: this.toggles}, propBox); 661 } 662 else 663 { 664 Dom.clearNode(propBox); 665 } 666 } 667 }, 668 669 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 670 671 highlightObject: function(object, context, target) 672 { 673 // Highlighting huge amount of elements on the page can cause serious performance 674 // problems (see issue 4736). So, avoid highlighting if the number of elements in 675 // the array exceeds specified limit. 676 var arr = this.getRealObject(object, context); 677 var limit = Options.get("multiHighlightLimit"); 678 if (!arr || (limit > 0 && arr.length > limit)) 679 { 680 if (Css.hasClass(target, "arrayLeftBracket") || 681 Css.hasClass(target, "arrayRightBracket")) 682 { 683 var tooltip = Locale.$STRF("console.multiHighlightLimitExceeded", [limit]); 684 target.setAttribute("title", tooltip); 685 } 686 687 // Do not highlight, a tooltip will be displayed instead. 688 return; 689 } 690 691 target.removeAttribute("title"); 692 693 // Highlight multiple elements on the page. 694 Firebug.Inspector.highlightObject(arr, context); 695 }, 696 697 isArray: function(obj) 698 { 699 return false; 700 } 701 }); 702 703 // ********************************************************************************************* // 704 705 FirebugReps.Arr = domplate(FirebugReps.ArrBase, 706 { 707 tag: 708 OBJECTBOX({_repObject: "$object", 709 $hasTwisty: "$object|hasSpecialProperties", 710 onclick: "$onToggleProperties"}, 711 SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["), 712 FOR("item", "$object|longArrayIterator", 713 TAG("$item.tag", {object: "$item.object"}), 714 SPAN({"class": "arrayComma", role: "presentation"}, "$item.delim") 715 ), 716 SPAN({"class": "arrayRightBracket", role: "presentation"}, "]"), 717 SPAN({"class": "arrayProperties", role: "group"}) 718 ), 719 720 shortTag: 721 OBJECTBOX({_repObject: "$object", 722 $hasTwisty: "$object|hasSpecialProperties", 723 onclick: "$onToggleProperties"}, 724 SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["), 725 FOR("item", "$object|shortArrayIterator", 726 TAG("$item.tag", {object: "$item.object"}), 727 SPAN({"class": "arrayComma", role: "presentation"}, "$item.delim") 728 ), 729 SPAN({"class": "arrayRightBracket"}, "]"), 730 SPAN({"class": "arrayProperties", role: "group"}) 731 ), 732 733 // http://code.google.com/p/fbug/issues/detail?id=874 734 isArray: function(obj) 735 { 736 try 737 { 738 if (Arr.isArray(obj)) 739 return true; 740 else if (isFinite(obj.length) && typeof obj.callee === "function") // arguments 741 return true; 742 } 743 catch (exc) {} 744 return false; 745 } 746 }); 747 748 // ********************************************************************************************* // 749 750 /** 751 * Any arrayish object that is not directly Array type (e.g. HTMLCollection, NodeList, etc.) 752 */ 753 FirebugReps.ArrayLikeObject = domplate(FirebugReps.ArrBase, 754 { 755 tag: 756 OBJECTBOX({_repObject: "$object", 757 $hasTwisty: "$object|hasSpecialProperties", 758 onclick: "$onToggleProperties"}, 759 A({"class": "objectTitle objectLink", onclick: "$onClickTitle"}, 760 "$object|getTitle" 761 ), 762 SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["), 763 FOR("item", "$object|longArrayIterator", 764 TAG("$item.tag", {object: "$item.object"}), 765 SPAN({"class": "arrayComma", role: "presentation"}, "$item.delim") 766 ), 767 SPAN({"class": "arrayRightBracket", role: "presentation"}, "]"), 768 SPAN({"class": "arrayProperties", role: "group"}) 769 ), 770 771 shortTag: 772 OBJECTBOX({_repObject: "$object", 773 $hasTwisty: "$object|hasSpecialProperties", 774 onclick: "$onToggleProperties"}, 775 A({"class": "objectTitle objectLink", onclick: "$onClickTitle"}, 776 "$object|getTitle" 777 ), 778 SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["), 779 FOR("item", "$object|shortArrayIterator", 780 TAG("$item.tag", {object: "$item.object"}), 781 SPAN({"class": "arrayComma", role: "presentation"}, "$item.delim") 782 ), 783 SPAN({"class": "arrayRightBracket"}, "]"), 784 SPAN({"class": "arrayProperties", role: "group"}) 785 ), 786 787 onClickTitle: function(event) 788 { 789 var obj = Firebug.getRepObject(event.target); 790 Firebug.chrome.select(obj); 791 }, 792 793 getTitle: function(obj, context) 794 { 795 var arr = Wrapper.unwrapObject(obj); 796 const re =/\[object ([^\]]*)/; 797 var label = Str.safeToString(arr); 798 var m = re.exec(label); 799 if (m) 800 return m[1] || label; 801 802 if ((arr instanceof Ci.nsIDOMDOMTokenList) || (this.isTokenList_Fx19(obj))) 803 return "DOMTokenList"; 804 805 return ""; 806 }, 807 808 isArray: function(obj) 809 { 810 if (this.isArrayLike_Fx19(obj)) 811 return true; 812 813 return Arr.isArrayLike(obj); 814 }, 815 816 /** 817 * Hack for Firefox 19 where obj instanceof Ci.nsIDOMDOMTokenList doesn't work. 818 */ 819 isTokenList_Fx19: function(obj) 820 { 821 var context = Firebug.currentContext; 822 if (!context) 823 return false; 824 825 var view = Wrapper.getContentView(context.window); 826 if (!view) 827 return false; 828 829 obj = Wrapper.unwrapObject(obj); 830 return (obj instanceof view.DOMTokenList); 831 }, 832 833 /** 834 * Hack for Firefox 19 where obj instanceof Ci.nsIDOMDOMTokenList, 835 * Ci.nsIDOMHTMLCollection and nsIDOMNodeList doesn't work. 836 */ 837 isArrayLike_Fx19: function(obj) 838 { 839 var context = Firebug.currentContext; 840 if (!context) 841 return false; 842 843 var view = Wrapper.getContentView(context.window); 844 if (!view) 845 return false; 846 847 obj = Wrapper.unwrapObject(obj); 848 return (obj instanceof view.DOMTokenList) || (obj instanceof view.HTMLCollection) || 849 (obj instanceof view.NodeList); 850 }, 851 }); 852 853 // ********************************************************************************************* // 854 855 FirebugReps.Property = domplate(Firebug.Rep, 856 { 857 supportsObject: function(object, type) 858 { 859 return object instanceof FirebugReps.PropertyObj; 860 }, 861 862 getRealObject: function(prop, context) 863 { 864 return prop.object[prop.name]; 865 }, 866 867 getTitle: function(prop, context) 868 { 869 return prop.name; 870 } 871 }); 872 873 // ********************************************************************************************* // 874 875 FirebugReps.PropertyObj = function(object, name) 876 { 877 this.object = object; 878 this.name = name; 879 880 this.getObject = function() 881 { 882 return object[name]; 883 }; 884 }; 885 886 // ********************************************************************************************* // 887 888 FirebugReps.NetFile = domplate(FirebugReps.Obj, 889 { 890 supportsObject: function(object, type) 891 { 892 if (typeof(Firebug.NetFile) == "undefined") 893 return false; 894 895 return object instanceof Firebug.NetFile; 896 }, 897 898 browseObject: function(file, context) 899 { 900 Win.openNewTab(file.href); 901 return true; 902 }, 903 904 getRealObject: function(file, context) 905 { 906 return null; 907 } 908 }); 909 910 // ********************************************************************************************* // 911 912 function instanceOf(object, Klass) 913 { 914 while (object != null) 915 { 916 if (object == Klass.prototype) 917 return true; 918 919 if ( typeof(object) === 'xml') 920 return (Klass.prototype === Xml.prototype); 921 922 object = object.__proto__; 923 } 924 return false; 925 } 926 927 928 929 // ********************************************************************************************* // 930 931 FirebugReps.Element = domplate(Firebug.Rep, 932 { 933 tag: 934 OBJECTLINK( 935 "<", 936 SPAN({"class": "nodeTag"}, "$object|getLocalName"), 937 FOR("attr", "$object|attrIterator", 938 " $attr.localName="", 939 SPAN({"class": "nodeValue"}, "$attr|getAttrValue"), 940 """ 941 ), 942 ">" 943 ), 944 945 shortTag: 946 OBJECTLINK( 947 SPAN({"class": "$object|getVisible"}, 948 SPAN({"class": "selectorTag"}, "$object|getSelectorTag"), 949 SPAN({"class": "selectorId"}, "$object|getSelectorId"), 950 SPAN({"class": "selectorClass"}, "$object|getSelectorClass"), 951 SPAN({"class": "selectorValue"}, "$object|getValue") 952 ) 953 ), 954 955 getLocalName: function(object) 956 { 957 try 958 { 959 return Xml.getLocalName(object); 960 } 961 catch (err) 962 { 963 return ""; 964 } 965 }, 966 967 getNodeName: function(object) 968 { 969 try 970 { 971 return Xml.getNodeName(object); 972 } 973 catch (err) 974 { 975 return ""; 976 } 977 }, 978 979 getAttrValue: function(attr) 980 { 981 var limit = Firebug.displayedAttributeValueLimit; 982 return (limit > 0) ? Str.cropString(attr.value, limit) : attr.value; 983 }, 984 985 getVisible: function(elt) 986 { 987 return Xml.isVisible(elt) ? "" : "selectorHidden"; 988 }, 989 990 getSelectorTag: function(elt) 991 { 992 return this.getLocalName(elt); 993 }, 994 995 getSelectorId: function(elt) 996 { 997 try 998 { 999 return elt.id ? ("#" + elt.id) : ""; 1000 } 1001 catch (e) 1002 { 1003 return ""; 1004 } 1005 }, 1006 1007 getSelectorClass: function(elt) 1008 { 1009 try 1010 { 1011 return elt.classList.length > 0 ? ("." + elt.classList[0]) : ""; 1012 } 1013 catch (err) 1014 { 1015 return ""; 1016 } 1017 }, 1018 1019 getValue: function(elt) 1020 { 1021 var value; 1022 1023 if (elt instanceof window.HTMLImageElement) 1024 value = Url.getFileName(elt.getAttribute("src")); 1025 else if (elt instanceof window.HTMLAnchorElement) 1026 value = Url.getFileName(elt.getAttribute("href")); 1027 else if (elt instanceof window.HTMLInputElement) 1028 value = elt.getAttribute("value"); 1029 else if (elt instanceof window.HTMLFormElement) 1030 value = Url.getFileName(elt.getAttribute("action")); 1031 else if (elt instanceof window.HTMLScriptElement) 1032 value = Url.getFileName(elt.getAttribute("src")); 1033 1034 return value ? " " + Str.cropMultipleLines(value, 20) : ""; 1035 }, 1036 1037 attrIterator: function(elt) 1038 { 1039 var attrs = []; 1040 var idAttr, classAttr; 1041 if (elt.attributes) 1042 { 1043 for (var i = 0; i < elt.attributes.length; ++i) 1044 { 1045 var attr = elt.attributes[i]; 1046 if (attr.localName.indexOf("-moz-math") != -1) 1047 continue; 1048 if (attr.localName.indexOf("firebug-") != -1) 1049 continue; 1050 else if (attr.localName == "id") 1051 idAttr = attr; 1052 else if (attr.localName == "class") 1053 classAttr = attr; 1054 else 1055 attrs.push(attr); 1056 } 1057 } 1058 1059 // Make sure 'id' and 'class' attributes are displayed first. 1060 if (classAttr) 1061 attrs.splice(0, 0, classAttr); 1062 if (idAttr) 1063 attrs.splice(0, 0, idAttr); 1064 1065 return attrs; 1066 }, 1067 1068 shortAttrIterator: function(elt) 1069 { 1070 // Short version returns only 'id' and 'class' attributes. 1071 var attrs = []; 1072 if (elt.attributes) 1073 { 1074 for (var i = 0; i < elt.attributes.length; ++i) 1075 { 1076 var attr = elt.attributes[i]; 1077 if (attr.localName == "id" || attr.localName == "class") 1078 attrs.push(attr); 1079 } 1080 } 1081 return attrs; 1082 }, 1083 1084 getHidden: function(elt) 1085 { 1086 return Xml.isVisible(elt) ? "" : "nodeHidden"; 1087 }, 1088 1089 getXPath: function(elt) 1090 { 1091 return Xpath.getElementTreeXPath(elt); 1092 }, 1093 1094 getNodeTextGroups: function(element) 1095 { 1096 var text = element.textContent; 1097 if (!Firebug.showFullTextNodes) 1098 { 1099 text = Str.cropString(text,50); 1100 } 1101 1102 var escapeGroups=[]; 1103 1104 if (Firebug.showTextNodesWithWhitespace) 1105 escapeGroups.push({ 1106 "group": "whitespace", 1107 "class": "nodeWhiteSpace", 1108 "extra": { 1109 "\t": "_Tab", 1110 "\n": "_Para", 1111 " " : "_Space" 1112 } 1113 }); 1114 1115 if (Firebug.entityDisplay != "symbols") 1116 escapeGroups.push({ 1117 "group": "text", 1118 "class": "nodeTextEntity", 1119 "extra": {} 1120 }); 1121 1122 if (escapeGroups.length) 1123 return Str.escapeGroupsForEntities(text, escapeGroups, Options.get("entityDisplay")); 1124 else 1125 return [{str:text, "class": "", extra: ""}]; 1126 }, 1127 1128 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1129 1130 copyHTML: function(elt) 1131 { 1132 var html = Xml.getElementHTML(elt); 1133 System.copyToClipboard(html); 1134 }, 1135 1136 copyInnerHTML: function(elt) 1137 { 1138 System.copyToClipboard(elt.innerHTML); 1139 }, 1140 1141 copyXPath: function(elt) 1142 { 1143 var xpath = Xpath.getElementXPath(elt); 1144 System.copyToClipboard(xpath); 1145 }, 1146 1147 copyCSSPath: function(elt) 1148 { 1149 var csspath = Css.getElementCSSPath(elt); 1150 System.copyToClipboard(csspath); 1151 }, 1152 1153 paste: function(elt, clipboardContent, mode) 1154 { 1155 if (elt instanceof window.HTMLElement) 1156 return this.pasteHTML.apply(this, arguments); 1157 else 1158 return this.pasteXML.apply(this, arguments); 1159 }, 1160 1161 pasteHTML: function(elt, clipboardContent, mode) 1162 { 1163 if (mode === "replaceInner") 1164 elt.innerHTML = clipboardContent; 1165 else if (mode === "replaceOuter") 1166 elt.outerHTML = clipboardContent; 1167 else 1168 elt.insertAdjacentHTML(mode, clipboardContent); 1169 }, 1170 1171 pasteXML: function(elt, clipboardContent, mode) 1172 { 1173 var contextNode, parentNode = elt.parentNode; 1174 if (["beforeBegin", "afterEnd", "replaceOuter"].indexOf(mode) >= 0) 1175 contextNode = parentNode; 1176 else 1177 contextNode = elt; 1178 1179 var pastedElements = Dom.markupToDocFragment(clipboardContent, contextNode); 1180 switch (mode) 1181 { 1182 case "beforeBegin": 1183 parentNode.insertBefore(pastedElements, elt); 1184 break; 1185 case "afterBegin": 1186 elt.insertBefore(pastedElements, elt.firstChild); 1187 break; 1188 case "beforeEnd": 1189 elt.appendChild(pastedElements); 1190 break; 1191 case "afterEnd": 1192 Dom.insertAfter(pastedElements, elt); 1193 break; 1194 case "replaceInner": 1195 Dom.eraseNode(elt); 1196 elt.appendChild(pastedElements); 1197 break; 1198 case "replaceOuter": 1199 parentNode.replaceChild(pastedElements, elt); 1200 break; 1201 } 1202 }, 1203 1204 persistor: function(context, xpath) 1205 { 1206 var elts = xpath 1207 ? Xpath.getElementsByXPath(context.window.document, xpath) 1208 : null; 1209 1210 return elts && elts.length ? elts[0] : null; 1211 }, 1212 1213 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1214 1215 className: "element", 1216 1217 supportsObject: function(object, type) 1218 { 1219 return object instanceof window.Element; 1220 }, 1221 1222 browseObject: function(elt, context) 1223 { 1224 var tag = elt.localName.toLowerCase(); 1225 if (tag == "script") 1226 Win.openNewTab(elt.src); 1227 else if (tag == "link") 1228 Win.openNewTab(elt.href); 1229 else if (tag == "a") 1230 Win.openNewTab(elt.href); 1231 else if (tag == "img") 1232 Win.openNewTab(elt.src); 1233 1234 return true; 1235 }, 1236 1237 persistObject: function(elt, context) 1238 { 1239 var xpath = Xpath.getElementXPath(elt); 1240 1241 return Obj.bind(this.persistor, window.top, xpath); 1242 }, 1243 1244 getTitle: function(element, context) 1245 { 1246 return Css.getElementCSSSelector(element); 1247 }, 1248 1249 getTooltip: function(elt) 1250 { 1251 var tooltip = this.getXPath(elt); 1252 1253 if (elt.namespaceURI) 1254 tooltip += " (" + elt.namespaceURI + ")"; 1255 1256 return tooltip; 1257 }, 1258 1259 getContextMenuItems: function(elt, target, context) 1260 { 1261 // XXX: Temporary fix for issue 5577. 1262 if (Dom.getAncestorByClass(target, "cssElementRuleContainer")) 1263 return; 1264 1265 var type; 1266 var items = []; 1267 var clipboardContent = System.getStringDataFromClipboard(); 1268 var isEltRoot = (elt === elt.ownerDocument.documentElement); 1269 1270 if (Xml.isElementHTML(elt) || Xml.isElementXHTML(elt)) 1271 type = "HTML"; 1272 else if (Xml.isElementMathML(elt)) 1273 type = "MathML"; 1274 else if (Xml.isElementSVG(elt)) 1275 type = "SVG"; 1276 else if (Xml.isElementXUL(elt)) 1277 type = "XUL"; 1278 else 1279 type = "XML"; 1280 1281 items.push( 1282 { 1283 label: Locale.$STRF("html.Copy_Node", [type]), 1284 tooltiptext: Locale.$STRF("html.tip.Copy_Node", [type]), 1285 command: Obj.bindFixed(this.copyHTML, this, elt) 1286 }); 1287 1288 if (Xml.isElementHTML(elt) || Xml.isElementXHTML(elt)) 1289 { 1290 items.push( 1291 { 1292 label: "CopyInnerHTML", 1293 tooltiptext: "html.tip.Copy_innerHTML", 1294 command: Obj.bindFixed(this.copyInnerHTML, this, elt) 1295 }); 1296 } 1297 1298 items = items.concat([ 1299 { 1300 label: "CopyXPath", 1301 tooltiptext: "html.tip.Copy_XPath", 1302 id: "fbCopyXPath", 1303 command: Obj.bindFixed(this.copyXPath, this, elt) 1304 }, 1305 { 1306 label: "Copy_CSS_Path", 1307 tooltiptext: "html.tip.Copy_CSS_Path", 1308 id: "fbCopyCSSPath", 1309 command: Obj.bindFixed(this.copyCSSPath, this, elt) 1310 }, 1311 { 1312 label: Locale.$STRF("html.menu.Paste", [type]), 1313 tooltiptext: Locale.$STRF("html.tip.Paste", [type]), 1314 disabled: !clipboardContent, 1315 id: "fbPaste", 1316 items: [ 1317 { 1318 label: "html.menu.Paste_Replace_Content", 1319 tooltiptext: "html.tip.Paste_Replace_Content", 1320 id: "fbPasteReplaceInner", 1321 command: Obj.bindFixed(this.paste, this, elt, clipboardContent, 1322 "replaceInner") 1323 }, 1324 { 1325 label: "html.menu.Paste_Replace_Node", 1326 tooltiptext: "html.tip.Paste_Replace_Node", 1327 id: "fbPasteReplaceOuter", 1328 disabled: isEltRoot, 1329 command: Obj.bindFixed(this.paste, this, elt, clipboardContent, 1330 "replaceOuter") 1331 }, 1332 { 1333 label: "html.menu.Paste_AsFirstChild", 1334 tooltiptext: "html.tip.Paste_AsFirstChild", 1335 id: "fbPasteFirstChild", 1336 command: Obj.bindFixed(this.paste, this, elt, clipboardContent, 1337 "afterBegin") 1338 }, 1339 { 1340 label: "html.menu.Paste_AsLastChild", 1341 tooltiptext: "html.tip.Paste_AsLastChild", 1342 id: "fbPasteLastChild", 1343 command: Obj.bindFixed(this.paste, this, elt, clipboardContent, "beforeEnd") 1344 }, 1345 { 1346 label: "html.menu.Paste_Before", 1347 tooltiptext: "html.tip.Paste_Before", 1348 id: "fbPasteBefore", 1349 disabled: isEltRoot, 1350 command: Obj.bindFixed(this.paste, this, elt, clipboardContent, 1351 "beforeBegin") 1352 }, 1353 { 1354 label: "html.menu.Paste_After", 1355 tooltiptext: "html.tip.Paste_After", 1356 id: "fbPasteAfter", 1357 disabled: isEltRoot, 1358 command: Obj.bindFixed(this.paste, this, elt, clipboardContent, "afterEnd") 1359 } 1360 ] 1361 } 1362 ]); 1363 1364 var tag = elt.localName.toLowerCase(); 1365 if (tag == "script" || tag == "link" || tag == "a" || tag == "img") 1366 { 1367 items = items.concat([ 1368 "-", 1369 { 1370 label: "OpenInTab", 1371 tooltiptext: "firebug.tip.Open_In_Tab", 1372 command: Obj.bindFixed(this.browseObject, this, elt, context) 1373 } 1374 ]); 1375 } 1376 1377 items = items.concat([ 1378 "-", 1379 { 1380 label: "ShowEventsInConsole", 1381 tooltiptext: "html.tip.Show_Events_In_Console", 1382 id: "fbShowEventsInConsole", 1383 type: "checkbox", 1384 checked: EventMonitor.areEventsMonitored(elt, null, context), 1385 command: function() 1386 { 1387 var checked = this.hasAttribute("checked"); 1388 EventMonitor.toggleMonitorEvents(elt, null, !checked, context); 1389 } 1390 }, 1391 "-", 1392 { 1393 label: "ScrollIntoView", 1394 tooltiptext: "html.tip.Scroll_Into_View", 1395 id: "fbScrollIntoView", 1396 command: Obj.bindFixed(elt.scrollIntoView, elt) 1397 } 1398 ]); 1399 1400 return items; 1401 } 1402 }); 1403 1404 // ********************************************************************************************* // 1405 1406 FirebugReps.TextNode = domplate(Firebug.Rep, 1407 { 1408 tag: 1409 OBJECTLINK( 1410 "<", 1411 SPAN({"class": "nodeTag"}, "TextNode"), 1412 " textContent="", 1413 SPAN({"class": "nodeValue"}, "$object.textContent|cropMultipleLines"), 1414 """, 1415 ">" 1416 ), 1417 1418 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1419 1420 className: "textNode", 1421 1422 inspectObject: function(node, context) 1423 { 1424 // Text nodes have two displays in HTML panel, inline and distinct 1425 // node. We need to examine which case we are dealing with in order to 1426 // select the proper object. 1427 if (HTMLLib.hasNoElementChildren(node.parentNode)) 1428 { 1429 node = node.parentNode; 1430 } 1431 1432 Firebug.chrome.select(node, "html", "domSide"); 1433 }, 1434 1435 supportsObject: function(object, type) 1436 { 1437 return object instanceof window.Text; 1438 }, 1439 1440 getTitle: function(win, context) 1441 { 1442 return "textNode"; 1443 } 1444 }); 1445 1446 // ********************************************************************************************* // 1447 1448 FirebugReps.RegExp = domplate(Firebug.Rep, 1449 { 1450 tag: 1451 OBJECTLINK( 1452 SPAN({"class": "objectTitle"}, "$object|getTitle"), 1453 SPAN(" "), 1454 SPAN({"class": "regexpSource"}, "$object|getSource") 1455 ), 1456 1457 className: "regexp", 1458 1459 supportsObject: function(object, type) 1460 { 1461 try 1462 { 1463 return type == "object" && Object.prototype.toString.call(object) === "[object RegExp]"; 1464 } 1465 catch (err) 1466 { 1467 if (FBTrace.DBG_ERRORS) 1468 FBTrace.sysout("reps.RegExp.supportsObject; EXCEPTION " + err, err) 1469 } 1470 }, 1471 1472 getSource: function(object) 1473 { 1474 var source = "/" + object.source + "/"; 1475 source += object.ignoreCase ? "i" : ""; 1476 source += object.global ? "g" : ""; 1477 source += object.multiline ? "m" : ""; 1478 return source; 1479 } 1480 }); 1481 1482 // ********************************************************************************************* // 1483 1484 FirebugReps.Document = domplate(Firebug.Rep, 1485 { 1486 tag: 1487 OBJECTLINK("Document ", SPAN({"class": "objectPropValue"}, "$object|getLocation")), 1488 1489 getLocation: function(doc) 1490 { 1491 return doc.location ? Url.getFileName(doc.location.href) : ""; 1492 }, 1493 1494 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1495 1496 className: "object", 1497 1498 supportsObject: function(object, type) 1499 { 1500 return object instanceof window.Document || object instanceof window.XMLDocument; 1501 }, 1502 1503 browseObject: function(doc, context) 1504 { 1505 Win.openNewTab(doc.location.href); 1506 return true; 1507 }, 1508 1509 persistObject: function(doc, context) 1510 { 1511 return this.persistor; 1512 }, 1513 1514 persistor: function(context) 1515 { 1516 return context.window.document; 1517 }, 1518 1519 getTitle: function(win, context) 1520 { 1521 return "document"; 1522 }, 1523 1524 getTooltip: function(doc) 1525 { 1526 return doc.location.href; 1527 } 1528 }); 1529 1530 // ********************************************************************************************* // 1531 1532 FirebugReps.StyleSheet = domplate(Firebug.Rep, 1533 { 1534 tag: 1535 OBJECTLINK("StyleSheet ", SPAN({"class": "objectPropValue"}, "$object|getLocation")), 1536 1537 getLocation: function(styleSheet) 1538 { 1539 return Url.getFileName(styleSheet.href); 1540 }, 1541 1542 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1543 1544 copyURL: function(styleSheet) 1545 { 1546 var url = Css.getURLForStyleSheet(styleSheet); 1547 if (url) 1548 System.copyToClipboard(url); 1549 1550 if (FBTrace.DBG_ERRORS && !url) 1551 FBTrace.sysout("reps.StyleSheet.copyURL; ERROR no URL", styleSheet); 1552 }, 1553 1554 openInTab: function(styleSheet) 1555 { 1556 var url = Css.getURLForStyleSheet(styleSheet); 1557 if (url) 1558 Win.openNewTab(url); 1559 1560 if (FBTrace.DBG_ERRORS && !url) 1561 FBTrace.sysout("reps.StyleSheet.openInTab; ERROR no URL", styleSheet); 1562 }, 1563 1564 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1565 1566 className: "object", 1567 1568 supportsObject: function(object, type) 1569 { 1570 return object instanceof window.CSSStyleSheet; 1571 }, 1572 1573 browseObject: function(styleSheet, context) 1574 { 1575 Win.openNewTab(styleSheet.href); 1576 return true; 1577 }, 1578 1579 persistObject: function(styleSheet, context) 1580 { 1581 return Obj.bind(this.persistor, top, styleSheet.href); 1582 }, 1583 1584 getTooltip: function(styleSheet) 1585 { 1586 return styleSheet.href; 1587 }, 1588 1589 getContextMenuItems: function(styleSheet, target, context) 1590 { 1591 return [ 1592 { 1593 label: "CopyLocation", 1594 tooltiptext: "clipboard.tip.Copy_Location", 1595 command: Obj.bindFixed(this.copyURL, this, styleSheet) 1596 }, 1597 "-", 1598 { 1599 label: "OpenInTab", 1600 tooltiptext: "firebug.tip.Open_In_Tab", 1601 command: Obj.bindFixed(this.openInTab, this, styleSheet) 1602 } 1603 ]; 1604 }, 1605 1606 persistor: function(context, href) 1607 { 1608 return Css.getStyleSheetByHref(href, context); 1609 } 1610 }); 1611 1612 //********************************************************************************************* // 1613 1614 FirebugReps.CSSRule = domplate(Firebug.Rep, 1615 { 1616 tag: 1617 OBJECTLINK("$object|getType ", SPAN({"class": "objectPropValue"}, "$object|getDescription")), 1618 1619 getType: function(rule) 1620 { 1621 if (rule instanceof window.CSSStyleRule) 1622 { 1623 return "CSSStyleRule"; 1624 } 1625 else if (rule instanceof window.CSSFontFaceRule) 1626 { 1627 return "CSSFontFaceRule"; 1628 } 1629 else if (rule instanceof window.CSSImportRule) 1630 { 1631 return "CSSImportRule"; 1632 } 1633 else if (rule instanceof window.CSSMediaRule) 1634 { 1635 return "CSSMediaRule"; 1636 } 1637 else if (rule instanceof window.CSSCharsetRule) 1638 { 1639 return "CSSCharsetRule"; 1640 } 1641 else if ((window.CSSKeyframesRule && rule instanceof window.CSSKeyframesRule) || 1642 rule instanceof window.MozCSSKeyframesRule) 1643 { 1644 return "CSSKeyframesRule"; 1645 } 1646 else if ((window.CSSKeyframeRule && rule instanceof window.CSSKeyframeRule) || 1647 rule instanceof window.MozCSSKeyframeRule) 1648 { 1649 return "CSSKeyframeRule"; 1650 } 1651 else if (rule instanceof window.CSSNameSpaceRule) 1652 { 1653 return "CSSNameSpaceRule"; 1654 } 1655 1656 return "CSSRule"; 1657 }, 1658 1659 getDescription: function(rule) 1660 { 1661 if (rule instanceof window.CSSStyleRule) 1662 { 1663 return rule.selectorText; 1664 } 1665 else if (rule instanceof window.CSSFontFaceRule) 1666 { 1667 return rule.style.getPropertyValue("font-family"); 1668 } 1669 else if (rule instanceof window.CSSImportRule) 1670 { 1671 return Url.getFileName(rule.href); 1672 } 1673 else if (rule instanceof window.CSSMediaRule) 1674 { 1675 return rule.media.mediaText; 1676 } 1677 else if (rule instanceof window.CSSCharsetRule) 1678 { 1679 return rule.encoding; 1680 } 1681 else if ((window.CSSKeyframesRule && rule instanceof window.CSSKeyframesRule) || 1682 rule instanceof window.MozCSSKeyframesRule) 1683 { 1684 return rule.name; 1685 } 1686 else if ((window.CSSKeyframeRule && rule instanceof window.CSSKeyframeRule) || 1687 rule instanceof window.MozCSSKeyframeRule) 1688 { 1689 return rule.keyText; 1690 } 1691 else if (rule instanceof window.CSSNameSpaceRule) 1692 { 1693 var reNamespace = /^@namespace (.+ )?url\("(.*?)"\);$/; 1694 var namespace = rule.cssText.match(reNamespace); 1695 var prefix = namespace[1] || ""; 1696 var name = namespace[2]; 1697 return prefix + name; 1698 } 1699 1700 return ""; 1701 }, 1702 1703 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1704 1705 className: "object", 1706 1707 supportsObject: function(object, type) 1708 { 1709 return object instanceof window.CSSRule; 1710 }, 1711 1712 getTooltip: function(rule) 1713 { 1714 if (rule instanceof CSSFontFaceRule) 1715 return Css.extractURLs(rule.style.getPropertyValue("src")).join(", "); 1716 else if (rule instanceof window.CSSImportRule) 1717 return rule.href; 1718 1719 return ""; 1720 } 1721 }); 1722 1723 // ********************************************************************************************* // 1724 1725 FirebugReps.Window = domplate(Firebug.Rep, 1726 { 1727 tag: 1728 OBJECTLINK("$object|getWindowTitle ", 1729 SPAN({"class": "objectPropValue"}, 1730 "$object|getLocation" 1731 ) 1732 ), 1733 1734 getLocation: function(win) 1735 { 1736 try 1737 { 1738 return (win && win.location && !win.closed) ? Url.getFileName(win.location.href) : ""; 1739 } 1740 catch (exc) 1741 { 1742 if (FBTrace.DBG_ERRORS) 1743 FBTrace.sysout("reps.Window window closed? "+exc, exc); 1744 } 1745 }, 1746 1747 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1748 1749 className: "object", 1750 1751 supportsObject: function(object, type) 1752 { 1753 return object instanceof window.Window; 1754 }, 1755 1756 browseObject: function(win, context) 1757 { 1758 Win.openNewTab(win.location.href); 1759 return true; 1760 }, 1761 1762 persistObject: function(win, context) 1763 { 1764 return this.persistor; 1765 }, 1766 1767 persistor: function(context) 1768 { 1769 return context.window; 1770 }, 1771 1772 getTitle: function(win, context) 1773 { 1774 return "window"; 1775 }, 1776 1777 getWindowTitle: function(win) 1778 { 1779 if (Firebug.viewChrome) 1780 { 1781 if (win.toString().indexOf('XrayWrapper') !== -1) 1782 return "XrayWrapper[Window]"; 1783 } 1784 return "Window"; 1785 }, 1786 1787 getTooltip: function(win) 1788 { 1789 if (win && !win.closed) 1790 return win.location.href; 1791 } 1792 }); 1793 1794 // ********************************************************************************************* // 1795 1796 FirebugReps.Event = domplate(Firebug.Rep, 1797 { 1798 className: "event", 1799 1800 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1801 1802 tag: 1803 TAG("$copyEventTag", {object: "$object|copyEvent"}), 1804 1805 copyEventTag: 1806 OBJECTLINK("$object|summarizeEvent"), 1807 1808 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1809 1810 summarizeEvent: function(event) 1811 { 1812 var info = [event.type, " "]; 1813 1814 var eventFamily = Events.getEventFamily(event.type); 1815 if (eventFamily == "mouse") 1816 info.push("clientX=", event.clientX, ", clientY=", event.clientY); 1817 else if (eventFamily == "key") 1818 info.push("charCode=", event.charCode, ", keyCode=", event.keyCode); 1819 else if (event.type == "message") 1820 info.push("origin=", event.origin, ", data=", event.data); 1821 1822 return info.join(""); 1823 }, 1824 1825 copyEvent: function(event) 1826 { 1827 return new Dom.EventCopy(event); 1828 }, 1829 1830 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1831 1832 supportsObject: function(object, type) 1833 { 1834 return object instanceof window.Event || object instanceof Dom.EventCopy; 1835 }, 1836 1837 getTitle: function(event, context) 1838 { 1839 return "Event " + event.type; 1840 } 1841 }); 1842 1843 // ********************************************************************************************* // 1844 1845 FirebugReps.EventLog = domplate(FirebugReps.Event, 1846 { 1847 className: "eventLog", 1848 1849 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1850 1851 tag: 1852 TAG("$copyEventTag", {object: "$object|copyEvent"}), 1853 1854 copyEventTag: 1855 SPAN( 1856 OBJECTLINK("$object|summarizeEvent"), 1857 SPAN(" "), 1858 SPAN("»"), 1859 SPAN(" "), 1860 TAG("$object|getTargetTag", {object: "$object|getTarget"}) 1861 ), 1862 1863 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1864 1865 copyEvent: function(log) 1866 { 1867 return new Dom.EventCopy(log.event); 1868 }, 1869 1870 getTarget: function(event) 1871 { 1872 return event.target; 1873 }, 1874 1875 getTargetTag: function(event) 1876 { 1877 var rep = Firebug.getRep(event.target); 1878 return rep.shortTag ? rep.shortTag : rep.tag; 1879 }, 1880 1881 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1882 1883 supportsObject: function(object, type) 1884 { 1885 return object instanceof EventMonitor.EventLog; 1886 }, 1887 }); 1888 1889 // ********************************************************************************************* // 1890 1891 FirebugReps.SourceLink = domplate(Firebug.Rep, 1892 { 1893 tag: 1894 OBJECTLINK( 1895 {$collapsed: "$object|hideSourceLink"}, 1896 DIV("$object|getSourceLinkTitle"), 1897 DIV({$systemLink: "$object|isSystemLink"}, "$object|getSystemFlagTitle")), 1898 1899 isSystemLink: function(sourceLink) 1900 { 1901 return sourceLink && Url.isSystemURL(sourceLink.href); 1902 }, 1903 1904 hideSourceLink: function(sourceLink) 1905 { 1906 try 1907 { 1908 return (sourceLink && sourceLink.href && sourceLink.href.indexOf) ? 1909 (sourceLink.href.indexOf("XPCSafeJSObjectWrapper") != -1) : true; 1910 } 1911 catch (e) 1912 { 1913 // xxxHonza: I see "Security error" code: "1000" nsresult: 1914 // "0x805303e8 (NS_ERROR_DOM_SECURITY_ERR)" 1915 // when accessing globalStorage property of a page. 1916 if (FBTrace.DBG_ERRORS) 1917 FBTrace.sysout("reps.hideSourceLink; EXCEPTION " + sourceLink + ", " + e, e); 1918 } 1919 1920 return true; 1921 }, 1922 1923 getSourceLinkTitle: function(sourceLink) 1924 { 1925 if (!sourceLink || !sourceLink.href || typeof(sourceLink.href) !== 'string') 1926 return ""; 1927 1928 try 1929 { 1930 var fileName = Url.getFileName(sourceLink.href); 1931 fileName = decodeURIComponent(fileName); 1932 } 1933 catch(exc) 1934 { 1935 if (FBTrace.DBG_ERRORS) 1936 FBTrace.sysout("reps.getSourceLinkTitle decodeURIComponent fails for \'" + 1937 sourceLink.href + "\': " + exc, exc); 1938 1939 fileName = sourceLink.href; 1940 } 1941 1942 var maxWidth = Firebug.sourceLinkLabelWidth; 1943 if (maxWidth > 0) 1944 fileName = Str.cropString(fileName, maxWidth); 1945 1946 if (sourceLink.instance) 1947 { 1948 return Locale.$STRF("InstanceLine", [fileName, sourceLink.instance + 1, 1949 sourceLink.line]); 1950 } 1951 else if (sourceLink.line && typeof(sourceLink.col) != "undefined") 1952 { 1953 return Locale.$STRF("LineAndCol", [fileName, sourceLink.line, sourceLink.col]); 1954 } 1955 else if (sourceLink.line) 1956 { 1957 return Locale.$STRF("Line", [fileName, sourceLink.line]); 1958 } 1959 else 1960 { 1961 return fileName; 1962 } 1963 }, 1964 1965 getSystemFlagTitle: function(sourceLink) 1966 { 1967 if (this.isSystemLink(sourceLink)) 1968 return Locale.$STRF("SystemItem", [""]); 1969 else 1970 return ""; 1971 }, 1972 1973 copyLink: function(sourceLink) 1974 { 1975 System.copyToClipboard(sourceLink.href); 1976 }, 1977 1978 openInTab: function(sourceLink) 1979 { 1980 Win.openNewTab(sourceLink.href); 1981 }, 1982 1983 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 1984 1985 className: "sourceLink", 1986 1987 supportsObject: function(object, type) 1988 { 1989 return object instanceof SourceLink.SourceLink; 1990 }, 1991 1992 getTooltip: function(sourceLink) 1993 { 1994 var text; 1995 try 1996 { 1997 text = decodeURI(sourceLink.href); 1998 } 1999 catch(exc) 2000 { 2001 if (FBTrace.DBG_ERRORS) 2002 FBTrace.sysout("reps.getTooltip decodeURI fails for " + sourceLink.href, exc); 2003 } 2004 2005 text = unescape(sourceLink.href); 2006 2007 var lines = Str.splitLines(text); 2008 if (lines.length < 10) 2009 return text; 2010 2011 lines.splice(10); 2012 return lines.join("") + "..."; 2013 }, 2014 2015 inspectObject: function(sourceLink, context) 2016 { 2017 if (sourceLink.type == "js") 2018 { 2019 var scriptFile = Firebug.SourceFile.getSourceFileByHref(sourceLink.href, context); 2020 if (scriptFile) 2021 return Firebug.chrome.select(sourceLink); 2022 } 2023 else if (sourceLink.type == "css") 2024 { 2025 // If an object is defined, treat it as the highest priority for 2026 // inspect actions 2027 if (sourceLink.object) { 2028 Firebug.chrome.select(sourceLink.object); 2029 return; 2030 } 2031 2032 var stylesheet = Css.getStyleSheetByHref(sourceLink.href, context); 2033 if (stylesheet) 2034 { 2035 var ownerNode = stylesheet.ownerNode; 2036 if (ownerNode) 2037 { 2038 Firebug.chrome.select(sourceLink, "html"); 2039 return; 2040 } 2041 2042 var panel = context.getPanel("stylesheet"); 2043 if (panel && panel.getRuleByLine(stylesheet, sourceLink.line)) 2044 return Firebug.chrome.select(sourceLink); 2045 } 2046 } 2047 else if (sourceLink.type == "net") 2048 { 2049 return Firebug.chrome.select(sourceLink); 2050 } 2051 2052 // Fallback is to just open the view-source window on the file 2053 Firefox.viewSource(sourceLink.href, sourceLink.line); 2054 }, 2055 2056 browseObject: function(sourceLink, context) 2057 { 2058 Win.openNewTab(sourceLink.href); 2059 return true; 2060 }, 2061 2062 getContextMenuItems: function(sourceLink, target, context) 2063 { 2064 return [ 2065 { 2066 label: "CopyLocation", 2067 tooltiptext: "clipboard.tip.Copy_Location", 2068 command: Obj.bindFixed(this.copyLink, this, sourceLink) 2069 }, 2070 "-", 2071 { 2072 label: "OpenInTab", 2073 tooltiptext: "firebug.tip.Open_In_Tab", 2074 command: Obj.bindFixed(this.openInTab, this, sourceLink) 2075 } 2076 ]; 2077 } 2078 }); 2079 2080 // ********************************************************************************************* // 2081 2082 FirebugReps.CompilationUnit = domplate(FirebugReps.SourceLink, 2083 { 2084 tag: 2085 OBJECTLINK({$collapsed: "$object|hideSourceLink"}, "$object|getSourceLinkTitle"), 2086 2087 persistor: function(context, href) 2088 { 2089 return context.getCompilationUnit(href); 2090 }, 2091 2092 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 2093 2094 className: "CompilationUnit", 2095 2096 supportsObject: function(object, type) 2097 { 2098 return (object instanceof CompilationUnit) ? 2 : 0; 2099 }, 2100 2101 persistObject: function(compilationUnit) 2102 { 2103 var href = compilationUnit.getURL(); 2104 return Obj.bind(this.persistor, top, href); 2105 }, 2106 2107 browseObject: function(sourceLink, context) 2108 { 2109 }, 2110 2111 getTooltip: function(compilationUnit) 2112 { 2113 return compilationUnit.getURL(); 2114 } 2115 }); 2116 2117 // ********************************************************************************************* // 2118 2119 // XXXjjb Since the repObject is fn the stack does not have correct line numbers 2120 FirebugReps.StackFrame = domplate(Firebug.Rep, 2121 { 2122 tag: 2123 OBJECTBLOCK({$hasTwisty: "$object|hasArguments", _repObject: "$object", 2124 onclick: "$onToggleArguments"}, 2125 SPAN({"class":"stackFrameMarker"}, ""), 2126 A({"class": "objectLink a11yFocus", _repObject: "$object"}, "$object|getCallName"), 2127 SPAN("("), 2128 SPAN({"class": "arguments"}, 2129 FOR("arg", "$object|argIterator", 2130 SPAN({"class": "argName"}, "$arg.name"), 2131 SPAN("="), 2132 TAG("$arg.tag", {object: "$arg.value"}), 2133 SPAN({"class": "arrayComma"}, "$arg.delim") 2134 ) 2135 ), 2136 SPAN(")"), 2137 SPAN({"class": "objectLink-sourceLink objectLink a11yFocus", 2138 _repObject: "$object|getSourceLink", 2139 role: "link"}, 2140 "$object|getSourceLinkTitle"), 2141 DIV({"class": "argList"}) 2142 ), 2143 2144 argList: 2145 DIV({"class": "argListBox", onclick: "$onSelectFrame"}, 2146 FOR("arg", "$object|argIterator", 2147 DIV({"class": "argBox"}, 2148 SPAN({"class": "argName"}, "$arg.name"), 2149 SPAN(" = "), 2150 TAG("$arg.tag", {object: "$arg.value"}) 2151 ) 2152 ) 2153 ), 2154 2155 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 2156 2157 getTitle: function(frame) 2158 { 2159 return frame.getFunctionName(); 2160 }, 2161 2162 hasArguments: function(frame) 2163 { 2164 return frame.args.length; 2165 }, 2166 2167 getCallName: function(frame) 2168 { 2169 return frame.getFunctionName(); 2170 }, 2171 2172 getSourceLinkTitle: function(frame) 2173 { 2174 var fileName = Url.getFileName(frame.href); 2175 2176 var maxWidth = Firebug.sourceLinkLabelWidth; 2177 if (maxWidth > 0) 2178 var fileName = Str.cropString(fileName, maxWidth); 2179 2180 return Locale.$STRF("Line", [fileName, frame.line]); 2181 }, 2182 2183 argIterator: function(frame) 2184 { 2185 if (!frame.args) 2186 return []; 2187 2188 var items = []; 2189 2190 for (var i = 0; i < frame.args.length; ++i) 2191 { 2192 var arg = frame.args[i]; 2193 2194 if (!arg) 2195 break; 2196 2197 if (arg.hasOwnProperty('value')) // then we got these from jsd 2198 { 2199 var rep = Firebug.getRep(arg.value); 2200 var tag = rep.shortTag ? rep.shortTag : rep.tag; 2201 2202 var delim = (i == frame.args.length-1 ? "" : ", "); 2203 2204 items.push({name: arg.name, value: arg.value, tag: tag, delim: delim}); 2205 } 2206 else if (arg.hasOwnProperty('name')) 2207 { 2208 items.push({name: arg.name, delim: delim}); 2209 } 2210 else // eg from Error object 2211 { 2212 var delim = (i == frame.args.length-1 ? "" : ", "); 2213 var rep = Firebug.getRep(arg); 2214 var tag = rep.shortTag ? rep.shortTag : rep.tag; 2215 2216 items.push({value: arg, tag: tag, delim: delim}); 2217 } 2218 2219 if (FBTrace.DBG_DOMPLATE) 2220 FBTrace.sysout("reps.stackframe args[" + i + "]: " + arg.name + " = " + 2221 arg.value, {arg: arg, item: items[items.length - 1]}); 2222 } 2223 2224 return items; 2225 }, 2226 2227 getSourceLink: function(stackFrame) 2228 { 2229 var sourceLink = new SourceLink.SourceLink(stackFrame.href, stackFrame.line, "js"); 2230 return sourceLink; 2231 }, 2232 2233 onToggleArguments: function(event) 2234 { 2235 this.toggleArguments(event.originalTarget); 2236 }, 2237 2238 toggleArguments: function(target) 2239 { 2240 if (Css.hasClass(target, "objectBox-stackFrame")) 2241 { 2242 if (Css.hasClass(target, "opened")) 2243 this.collapseArguments(target); 2244 else 2245 this.expandArguments(target); 2246 } 2247 }, 2248 2249 collapseArguments: function(target) 2250 { 2251 if (!Css.hasClass(target, "opened")) 2252 return; 2253 2254 Css.toggleClass(target, "opened"); 2255 2256 var argList = target.getElementsByClassName("argList").item(0); 2257 Dom.clearNode(argList); 2258 }, 2259 2260 expandArguments: function(target) 2261 { 2262 if (Css.hasClass(target, "opened")) 2263 return; 2264 2265 var frame = target.repObject; 2266 if (!this.hasArguments(frame)) 2267 return; 2268 2269 Css.toggleClass(target, "opened"); 2270 2271 var argList = target.getElementsByClassName("argList").item(0); 2272 this.argList.replace({object: frame}, argList); 2273 }, 2274 2275 onSelectFrame: function(event) 2276 { 2277 var target = event.currentTarget; 2278 if (Css.hasClass(target, "argListBox")) 2279 { 2280 var stackFrame = Dom.getAncestorByClass(target, "objectBox-stackFrame"); 2281 var panel = Firebug.getElementPanel(target); 2282 this.inspectObject(stackFrame.repObject, panel.context); 2283 Events.cancelEvent(event); 2284 } 2285 }, 2286 2287 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 2288 // Rep 2289 2290 className: "stackFrame", 2291 2292 supportsObject: function(object, type) 2293 { 2294 return object instanceof StackFrame.StackFrame; 2295 }, 2296 2297 inspectObject: function(stackFrame, context) 2298 { 2299 if (context.stopped) 2300 Firebug.chrome.select(stackFrame); 2301 else 2302 Firebug.chrome.select(this.getSourceLink(stackFrame)); 2303 }, 2304 2305 getTooltip: function(stackFrame, context) 2306 { 2307 return Locale.$STRF("Line", [stackFrame.href, stackFrame.line]); 2308 } 2309 }); 2310 2311 // ********************************************************************************************* // 2312 2313 FirebugReps.StackTrace = domplate(Firebug.Rep, 2314 { 2315 tag: 2316 DIV({role : "group", "aria-label" : Locale.$STR("aria.labels.stack trace")}, 2317 FOR("frame", "$object.frames|frameIterator", 2318 TAG(FirebugReps.StackFrame.tag, {object: "$frame"}) 2319 ) 2320 ), 2321 2322 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 2323 2324 className: "stackTrace", 2325 2326 supportsObject: function(object, type) 2327 { 2328 return object instanceof StackFrame.StackTrace; 2329 }, 2330 2331 frameIterator: function(frames) 2332 { 2333 // Skip Firebug internal frames. 2334 // xxxHonza: this is anoter place where stack frame is peeling off. 2335 var result = []; 2336 for (var i=0; frames && i<frames.length; i++) 2337 { 2338 var frame = frames[i]; 2339 var sf = frame.sourceFile; 2340 if ((sf && sf.href && Str.hasPrefix(sf.href, "chrome")) || 2341 (frame.fn == "_firebugRerun") || 2342 (frame.fn == "jsdbug_NoScriptFunctionName")) 2343 { 2344 continue; 2345 } 2346 2347 result.push(frames[i]); 2348 } 2349 return result; 2350 } 2351 }); 2352 2353 // ********************************************************************************************* // 2354 2355 FirebugReps.ErrorMessage = domplate(Firebug.Rep, 2356 { 2357 sourceLimit: 80, 2358 alterText: "...", 2359 2360 tag: 2361 OBJECTBOX({ 2362 $hasTwisty: "$object|hasStackTrace", 2363 $hasBreakSwitch: "$object|hasBreakSwitch", 2364 $breakForError: "$object|hasErrorBreak", 2365 _repObject: "$object", 2366 _stackTrace: "$object|getLastErrorStackTrace", 2367 onclick: "$onToggleError"}, 2368 DIV({"class": "errorTitle focusRow subLogRow", role: "listitem"}, 2369 SPAN({"class": "errorDuplication"}, "$object.msgId|getDuplication"), 2370 SPAN({"class": "errorMessage"}, 2371 "$object.message" 2372 ) 2373 ), 2374 DIV({"class": "errorTrace", role: "presentation"}), 2375 TAG("$object|getObjectsTag", {object: "$object.objects"}), 2376 DIV({"class": "errorSourceBox errorSource-$object|getSourceType focusRow subLogRow", 2377 role : "listitem"}, 2378 TABLE({cellspacing: 0, cellpadding: 0}, 2379 TBODY( 2380 TR( 2381 TD( 2382 IMG({"class": "$object|isBreakableError a11yFocus", 2383 src:"blank.gif", role: "checkbox", 2384 "aria-checked": "$object|hasErrorBreak", 2385 title: Locale.$STR("console.Break On This Error")}) 2386 ), 2387 TD( 2388 A({"class": "errorSource a11yFocus"}, 2389 PRE({"class": "errorSourceCode", 2390 title: "$object|getSourceTitle"}, "$object|getSource") 2391 ), 2392 TAG(FirebugReps.SourceLink.tag, {object: "$object|getSourceLink"}) 2393 ) 2394 ), 2395 TR({$collapsed: "$object|hideErrorCaret"}, 2396 TD(), 2397 TD( 2398 DIV({"class": "errorColPosition"}, 2399 "$object|getColumnPosition" 2400 ), 2401 DIV({"class": "errorColCaret"}) 2402 ) 2403 ) 2404 ) 2405 ) 2406 ) 2407 ), 2408 2409 getObjectsTag: function(error) 2410 { 2411 return error.objects ? FirebugReps.Arr.tag : SPAN(); 2412 }, 2413 2414 getLastErrorStackTrace: function(error) 2415 { 2416 return error.trace; 2417 }, 2418 2419 hasStackTrace: function(error) 2420 { 2421 return error && error.trace; 2422 }, 2423 2424 hasBreakSwitch: function(error) 2425 { 2426 return error.href && error.lineNo > 0; 2427 }, 2428 2429 isBreakableError: function(error) 2430 { 2431 return (error.category === "js") ? "errorBreak" : "errorUnbreakable"; 2432 }, 2433 2434 hasErrorBreak: function(error) 2435 { 2436 return FBS.fbs.hasErrorBreakpoint(Url.normalizeURL(error.href), error.lineNo); 2437 }, 2438 2439 getDuplication: function(msgId) 2440 { 2441 return ""; // filled in later 2442 }, 2443 2444 getSource: function(error, noCrop) 2445 { 2446 if (error.source && noCrop) 2447 { 2448 return error.source; 2449 } 2450 else if (error.source) 2451 { 2452 return Str.cropStringEx(Str.trim(error.source), this.sourceLimit, 2453 this.alterText, error.colNumber); 2454 } 2455 2456 if (error.category == "js" && error.href && 2457 error.href.indexOf("XPCSafeJSObjectWrapper") != -1) 2458 { 2459 return ""; 2460 } 2461 2462 var source = error.getSourceLine(); 2463 if (source && noCrop) 2464 { 2465 return source; 2466 } 2467 else if (source) 2468 { 2469 return Str.cropStringEx(Str.trim(source), this.sourceLimit, 2470 this.alterText, error.colNumber); 2471 } 2472 2473 return ""; 2474 }, 2475 2476 hideErrorCaret: function(error) 2477 { 2478 var source = this.getSource(error); 2479 if (!source) 2480 return true; 2481 2482 if (typeof(error.colNumber) == "undefined") 2483 return true; 2484 2485 return false; 2486 }, 2487 2488 getColumnPosition: function(error) 2489 { 2490 if (this.hideErrorCaret(error)) 2491 return ""; 2492 2493 var colNumber = error.colNumber; 2494 var originalLength = error.source.length; 2495 var trimmedLength = Str.trimLeft(error.source).length; 2496 2497 // The source line is displayed without starting whitespaces. 2498 colNumber -= (originalLength - trimmedLength); 2499 2500 var source = this.getSource(error, true); 2501 if (!source) 2502 return ""; 2503 2504 source = Str.trim(source); 2505 2506 // Count how much the pivot needs to be adjusted (based on Str.cropStringEx) 2507 var halfLimit = this.sourceLimit/2; 2508 var pivot = error.colNumber; 2509 if (pivot < halfLimit) 2510 pivot = halfLimit; 2511 2512 if (pivot > source.length - halfLimit) 2513 pivot = source.length - halfLimit; 2514 2515 // Subtract some columns if the text has been cropped at the beginning. 2516 var begin = Math.max(0, pivot - halfLimit); 2517 colNumber -= begin; 2518 2519 // Add come cols because there is an alterText at the beginning now. 2520 if (begin > 0) 2521 colNumber += this.alterText.length; 2522 2523 var text = ""; 2524 for (var i=0; i<colNumber; i++) 2525 text += "-"; 2526 2527 return text; 2528 }, 2529 2530 getSourceTitle: function(error) 2531 { 2532 var source = this.getSource(error, true); 2533 return source ? Str.trim(source) : ""; 2534 }, 2535 2536 getSourceLink: function(error) 2537 { 2538 var ext = error.category == "css" ? "css" : "js"; 2539 return error.lineNo ? new SourceLink.SourceLink(error.href, error.lineNo, ext, 2540 null, null, error.colNumber) : null; 2541 }, 2542 2543 getSourceType: function(error) 2544 { 2545 // Errors occurring inside of HTML event handlers look like "foo.html (line 1)" 2546 // so let's try to skip those 2547 if (error.source) 2548 return "syntax"; 2549 else if (error.category == "css") 2550 return "show"; 2551 else if (!error.href || !error.lineNo) 2552 return "none"; 2553 // Why do we have that at all? 2554 else if (error.lineNo == 1 && Url.getFileExtension(error.href) != "js") 2555 return "none"; 2556 else 2557 return "show"; 2558 }, 2559 2560 onToggleError: function(event) 2561 { 2562 var target = event.currentTarget; 2563 if (Css.hasClass(event.target, "errorBreak")) 2564 { 2565 var panel = Firebug.getElementPanel(event.target); 2566 this.breakOnThisError(target.repObject, panel.context); 2567 return; 2568 } 2569 else if (Css.hasClass(event.target, "errorSourceCode")) 2570 { 2571 var panel = Firebug.getElementPanel(event.target); 2572 this.inspectObject(target.repObject, panel.context); 2573 return; 2574 } 2575 2576 var errorTitle = Dom.getAncestorByClass(event.target, "errorTitle"); 2577 if (errorTitle) 2578 { 2579 var traceBox = target.childNodes[1]; 2580 Css.toggleClass(target, "opened"); 2581 event.target.setAttribute('aria-expanded', Css.hasClass(target, "opened")); 2582 2583 if (Css.hasClass(target, "opened")) 2584 { 2585 if (target.stackTrace) 2586 FirebugReps.StackTrace.tag.append({object: target.stackTrace}, traceBox); 2587 2588 if (Firebug.A11yModel.enabled) 2589 { 2590 var panel = Firebug.getElementPanel(event.target); 2591 Events.dispatch(panel.fbListeners, "modifyLogRow", [panel, traceBox]); 2592 } 2593 } 2594 else 2595 { 2596 Dom.clearNode(traceBox); 2597 } 2598 } 2599 }, 2600 2601 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 2602 2603 copyError: function(error) 2604 { 2605 var message = [ 2606 error.message, 2607 error.href, 2608 "Line " + error.lineNo 2609 ]; 2610 System.copyToClipboard(message.join(Str.lineBreak())); 2611 }, 2612 2613 breakOnThisError: function(error, context) 2614 { 2615 var compilationUnit = context.getCompilationUnit(Url.normalizeURL(error.href)); 2616 if (!compilationUnit) 2617 { 2618 if (FBTrace.DBG_ERRORS) 2619 FBTrace.sysout("reps.breakOnThisError has no source file for error.href: " + 2620 error.href + " error:" + error, context); 2621 return; 2622 } 2623 2624 if (this.hasErrorBreak(error)) 2625 Firebug.Debugger.clearErrorBreakpoint(compilationUnit, error.lineNo); 2626 else 2627 Firebug.Debugger.setErrorBreakpoint(compilationUnit, error.lineNo); 2628 }, 2629 2630 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 2631 2632 className: "errorMessage", 2633 inspectable: false, 2634 2635 supportsObject: function(object, type) 2636 { 2637 return object instanceof FirebugReps.ErrorMessageObj; 2638 }, 2639 2640 inspectObject: function(error, context) 2641 { 2642 var sourceLink = this.getSourceLink(error); 2643 FirebugReps.SourceLink.inspectObject(sourceLink, context); 2644 }, 2645 2646 getContextMenuItems: function(error, target, context) 2647 { 2648 var breakOnThisError = this.hasErrorBreak(error); 2649 2650 var items = [ 2651 { 2652 label: "CopyError", 2653 tooltiptext: "console.menu.tip.Copy_Error", 2654 command: Obj.bindFixed(this.copyError, this, error) 2655 } 2656 ]; 2657 2658 if (error.category != "css") 2659 { 2660 items.push( 2661 "-", 2662 { 2663 label: "BreakOnThisError", 2664 tooltiptext: "console.menu.tip.Break_On_This_Error", 2665 type: "checkbox", 2666 checked: breakOnThisError, 2667 command: Obj.bindFixed(this.breakOnThisError, this, error, context) 2668 }, 2669 Menu.optionMenu("BreakOnAllErrors", "breakOnErrors", 2670 "console.menu.tip.Break_On_All_Errors") 2671 ); 2672 } 2673 2674 return items; 2675 } 2676 }); 2677 2678 // ********************************************************************************************* // 2679 2680 FirebugReps.Except = domplate(Firebug.Rep, 2681 { 2682 tag: 2683 TAG(FirebugReps.ErrorMessage.tag, {object: "$object|getErrorMessage"}), 2684 2685 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 2686 2687 className: "exception", 2688 2689 getTitle: function(object) 2690 { 2691 if (object.name) 2692 return object.name + (object.message ? ": " + object.message : ""); 2693 2694 if (object.message) 2695 return object.message; 2696 2697 return "Exception"; 2698 }, 2699 2700 getErrorMessage: function(object) 2701 { 2702 var context = Firebug.currentContext; 2703 var win = context ? context.window : null; 2704 2705 var url = object.fileName ? object.fileName : (win ? win.location.href : ""); 2706 var lineNo = object.lineNumber ? object.lineNumber : 0; 2707 var message = this.getTitle(object); 2708 2709 var trace; 2710 if (object.stack) 2711 { 2712 trace = StackFrame.parseToStackTrace(object.stack, context); 2713 trace = StackFrame.cleanStackTraceOfFirebug(trace); 2714 2715 if (!trace) 2716 lineNo = 0; 2717 } 2718 2719 var errorObject = new FirebugReps.ErrorMessageObj(message, url, lineNo, "", "js", 2720 context, trace); 2721 2722 if (trace && trace.frames && trace.frames[0]) 2723 errorObject.correctWithStackTrace(trace); 2724 2725 errorObject.resetSource(); 2726 return errorObject; 2727 }, 2728 2729 supportsObject: function(object, type) 2730 { 2731 return (object instanceof FirebugReps.ErrorCopy) || Obj.XW_instanceof(object, Error); 2732 } 2733 }); 2734 2735 // ********************************************************************************************* // 2736 2737 // xxxsz: Is this code still in use? 2738 FirebugReps.Assert = domplate(Firebug.Rep, 2739 { 2740 tag: 2741 DIV( 2742 DIV({"class": "errorTitle"}), 2743 DIV({"class": "assertDescription"}) 2744 ), 2745 2746 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 2747 2748 className: "assert", 2749 2750 inspectObject: function(error, context) 2751 { 2752 var sourceLink = this.getSourceLink(error); 2753 Firebug.chrome.select(sourceLink); 2754 }, 2755 2756 getContextMenuItems: function(error, target, context) 2757 { 2758 var breakOnThisError = this.hasErrorBreak(error); 2759 2760 return [ 2761 { 2762 label: "CopyError", 2763 tooltiptext: "console.tip.Copy_Error", 2764 command: Obj.bindFixed(this.copyError, this, error) 2765 }, 2766 "-", 2767 { 2768 label: "BreakOnThisError", 2769 tooltiptext: "console.menu.tip.Break_On_This_Error", 2770 type: "checkbox", 2771 checked: breakOnThisError, 2772 command: Obj.bindFixed(this.breakOnThisError, this, error, context) 2773 }, 2774 Menu.optionMenu("BreakOnAllErrors", "breakOnErrors", 2775 "console.menu.tip.Break_On_All_Errors") 2776 ]; 2777 } 2778 }); 2779 2780 // ********************************************************************************************* // 2781 2782 FirebugReps.SourceText = domplate(Firebug.Rep, 2783 { 2784 tag: 2785 DIV( 2786 FOR("line", "$object|lineIterator", 2787 DIV({"class": "sourceRow", role : "presentation"}, 2788 SPAN({"class": "sourceLine", role : "presentation"}, "$line.lineNo"), 2789 SPAN({"class": "sourceRowText", role : "presentation"}, "$line.text") 2790 ) 2791 ) 2792 ), 2793 2794 lineIterator: function(sourceText) 2795 { 2796 var maxLineNoChars = (sourceText.lines.length + "").length; 2797 var list = []; 2798 2799 for (var i = 0; i < sourceText.lines.length; ++i) 2800 { 2801 // Make sure all line numbers are the same width (with a fixed-width font) 2802 var lineNo = (i+1) + ""; 2803 while (lineNo.length < maxLineNoChars) 2804 lineNo = " " + lineNo; 2805 2806 list.push({lineNo: lineNo, text: sourceText.lines[i]}); 2807 } 2808 2809 return list; 2810 }, 2811 2812 getHTML: function(sourceText) 2813 { 2814 return getSourceLineRange(sourceText, 1, sourceText.lines.length); 2815 } 2816 }); 2817 2818 //********************************************************************************************** // 2819 2820 FirebugReps.nsIDOMHistory = domplate(Firebug.Rep, 2821 { 2822 tag: 2823 OBJECTBOX({onclick: "$showHistory", _repObject: "$object"}, 2824 OBJECTLINK("$object|summarizeHistory") 2825 ), 2826 2827 className: "nsIDOMHistory", 2828 2829 summarizeHistory: function(history) 2830 { 2831 try 2832 { 2833 var items = history.length; 2834 return Locale.$STRP("firebug.reps.historyEntries", [items]); 2835 } 2836 catch (exc) 2837 { 2838 return "object does not support history (nsIDOMHistory)"; 2839 } 2840 }, 2841 2842 showHistory: function(event) 2843 { 2844 try 2845 { 2846 var history = event.currentTarget.repObject; 2847 history.length; // if this throws, then unsupported 2848 Firebug.chrome.select(history); 2849 } 2850 catch (exc) 2851 { 2852 } 2853 }, 2854 2855 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 2856 2857 supportsObject: function(object, type) 2858 { 2859 return (object instanceof Ci.nsIDOMHistory); 2860 } 2861 }); 2862 2863 // ********************************************************************************************* // 2864 2865 FirebugReps.ApplicationCache = domplate(Firebug.Rep, 2866 { 2867 tag: 2868 OBJECTLINK("$object|summarizeCache"), 2869 2870 summarizeCache: function(applicationCache) 2871 { 2872 try 2873 { 2874 return applicationCache.mozItems.length + " items in offline cache"; 2875 } 2876 catch(exc) 2877 { 2878 return "https://bugzilla.mozilla.org/show_bug.cgi?id=422264"; 2879 } 2880 }, 2881 2882 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 2883 2884 className: "applicationCache", 2885 2886 supportsObject: function(object, type) 2887 { 2888 if (Ci.nsIDOMOfflineResourceList) 2889 return (object instanceof Ci.nsIDOMOfflineResourceList); 2890 } 2891 }); 2892 2893 // ********************************************************************************************* // 2894 2895 FirebugReps.Storage = domplate(Firebug.Rep, 2896 { 2897 tag: 2898 OBJECTLINK( 2899 SPAN({"class": "storageTitle"}, "$object|summarize "), 2900 FOR("prop", "$object|longPropIterator", 2901 "$prop.name", 2902 SPAN({"class": "objectEqual", role: "presentation"}, "$prop.equal"), 2903 TAG("$prop.tag", {object: "$prop.object"}), 2904 SPAN({"class": "objectComma", role: "presentation"}, "$prop.delim") 2905 ) 2906 ), 2907 2908 shortTag: 2909 OBJECTLINK( 2910 SPAN({"class": "storageTitle"}, "$object|summarize "), 2911 FOR("prop", "$object|shortPropIterator", 2912 "$prop.name", 2913 SPAN({"class": "objectEqual", role: "presentation"}, "$prop.equal"), 2914 TAG("$prop.tag", {object: "$prop.object"}), 2915 SPAN({"class": "objectComma", role: "presentation"}, "$prop.delim") 2916 ) 2917 ), 2918 2919 summarize: function(storage) 2920 { 2921 var object = this.objectView(storage); 2922 return Locale.$STRP("firebug.storage.totalItems", [Object.keys(object).length]); 2923 }, 2924 2925 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 2926 2927 className: "Storage", 2928 2929 supportsObject: function(object, type) 2930 { 2931 return (object instanceof window.Storage); 2932 }, 2933 2934 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 2935 // Iterator 2936 2937 longPropIterator: function(object) 2938 { 2939 return this.propIterator(object, 100); 2940 }, 2941 2942 shortPropIterator: function(object) 2943 { 2944 return this.propIterator(object, Options.get("ObjectShortIteratorMax")); 2945 }, 2946 2947 propIterator: function(storage, max) 2948 { 2949 var object = this.objectView(storage); 2950 return FirebugReps.Obj.propIterator(object, max); 2951 }, 2952 2953 objectView: function(storage) 2954 { 2955 var object = this.makeObject(storage); 2956 for (var any in object) 2957 return object; 2958 2959 // We might have hit upon an https site (bug 709238). 2960 // As a hack, we'll check if the current context's window 2961 // contains the object as localStorage or sessionStorage. 2962 try { 2963 var context = Firebug.currentContext; 2964 var win = context && context.window; 2965 if (win && win.location.protocol === "https:") 2966 { 2967 var names = ["localStorage", "sessionStorage"], done = false; 2968 for (var i = 0; i < 2; ++i) 2969 { 2970 if (win[names[i]] !== storage) 2971 continue; 2972 Firebug.CommandLine.evaluate( 2973 "((" + this.makeObject + ")(" + names[i] + "))", 2974 context, 2975 null, null, 2976 function(result) { 2977 object = result; 2978 done = true; 2979 }, 2980 function() {}, 2981 true 2982 ); 2983 if (done) 2984 break; 2985 } 2986 } 2987 } 2988 catch(e) 2989 { 2990 if (FBTrace.DBG_ERRORS) 2991 FBTrace.sysout("reps.Storage.objectView; EXCEPTION " + e, e); 2992 } 2993 2994 return object; 2995 }, 2996 2997 makeObject: function(storage) 2998 { 2999 // Create a raw object, free from getItem etc., from a storage. 3000 // May be serialized and run in page scope. 3001 var object = {}; 3002 try 3003 { 3004 for (var name in storage) 3005 { 3006 var value = storage.getItem(name); 3007 Object.defineProperty(object, name, {value: value, enumerable: true}); 3008 } 3009 } 3010 catch(e) 3011 { 3012 // We can't log an error in page scope. 3013 } 3014 return object; 3015 } 3016 }); 3017 3018 // ********************************************************************************************* // 3019 3020 FirebugReps.XPathResult = domplate(FirebugReps.Arr, 3021 { 3022 className: "array xPathResult", 3023 toggles: new ToggleBranch.ToggleBranch(), 3024 3025 tag: 3026 SPAN(FirebugReps.Arr.tag), 3027 3028 shortTag: 3029 SPAN(FirebugReps.Arr.shortTag), 3030 3031 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 3032 3033 supportsObject: function(xpathresult, type) 3034 { 3035 return (xpathresult instanceof window.XPathResult); 3036 }, 3037 3038 arrayIterator: function(xpathresult, max) 3039 { 3040 var items = []; 3041 for (var i=0; i<xpathresult.snapshotLength && i<=max; i++) 3042 { 3043 var value = xpathresult.snapshotItem(i); 3044 var rep = Firebug.getRep(value); 3045 var tag = rep.shortTag || rep.tag; 3046 var delim = (i == xpathresult.snapshotLength-1 ? "" : ", "); 3047 3048 items.push({object: value, tag: tag, delim: delim}); 3049 } 3050 3051 if (xpathresult.snapshotLength > max + 1) 3052 { 3053 items[max] = { 3054 object: (xpathresult.snapshotLength-max) + " " + 3055 Locale.$STR("firebug.reps.more") + "...", 3056 tag: FirebugReps.Caption.tag, 3057 delim: "" 3058 }; 3059 } 3060 3061 return items; 3062 }, 3063 }); 3064 3065 // ********************************************************************************************* // 3066 3067 FirebugReps.Description = domplate(Firebug.Rep, 3068 { 3069 className: "Description", 3070 3071 tag: 3072 DIV({onclick: "$onClickLink"}), 3073 3074 render: function(text, parentNode, listener) 3075 { 3076 var params = {}; 3077 if (listener) 3078 { 3079 params.onClickLink = function(event) 3080 { 3081 // Only clicks on links are passed to the original listener. 3082 var localName = event.target.localName; 3083 if (listener && localName && localName.toLowerCase() == "a") 3084 listener(event); 3085 }; 3086 } 3087 3088 var rootNode = this.tag.replace(params, parentNode, this); 3089 3090 var parser = Xpcom.CCIN("@mozilla.org/xmlextras/domparser;1", "nsIDOMParser"); 3091 var doc = parser.parseFromString("<div>" + text + "</div>", "text/xml"); 3092 var root = doc.documentElement; 3093 3094 // Error handling 3095 var nsURI = "http://www.mozilla.org/newlayout/xml/parsererror.xml"; 3096 if (root.namespaceURI == nsURI && root.nodeName == "parsererror") 3097 { 3098 FBTrace.sysout("reps.Description; parse ERROR " + root.firstChild.nodeValue, root); 3099 3100 return FirebugReps.Warning.tag.replace({object: "css.EmptyElementCSS"}, 3101 parentNode, FirebugReps.Warning); 3102 } 3103 3104 // Nodes from external documents need to be imported. 3105 root = rootNode.ownerDocument.importNode(root, true); 3106 3107 rootNode.appendChild(root); 3108 return rootNode; 3109 } 3110 }); 3111 3112 // ********************************************************************************************* // 3113 3114 FirebugReps.Attr = domplate(Firebug.Rep, 3115 { 3116 tag: 3117 OBJECTLINK( 3118 SPAN( 3119 SPAN({"class": "attrTitle"}, "$object|getTitle"), 3120 SPAN({"class": "attrEqual"}, "="), 3121 TAG("$object|getValueTag", {object: "$object.value"}) 3122 ) 3123 ), 3124 3125 getTitle: function(attr) 3126 { 3127 return attr.name; 3128 }, 3129 3130 getValueTag: function(object) 3131 { 3132 return Firebug.getRep(object.value).tag; 3133 }, 3134 3135 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 3136 3137 className: "Attr", 3138 3139 supportsObject: function(object, type) 3140 { 3141 return (object instanceof window.Attr); 3142 }, 3143 }); 3144 3145 // ********************************************************************************************* // 3146 3147 FirebugReps.Date = domplate(Firebug.Rep, 3148 { 3149 tag: 3150 OBJECTLINK( 3151 SPAN({"class": "objectTitle"}, "$object|getTitle "), 3152 SPAN({"class": "objectLeftBrace", role: "presentation"}, "{"), 3153 SPAN({"class": "attrEqual"}, "$object|getValue"), 3154 SPAN({"class": "objectRightBrace"}, "}") 3155 ), 3156 3157 getValue: function(object) 3158 { 3159 return object.toString(); 3160 }, 3161 3162 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 3163 3164 className: "Date", 3165 3166 supportsObject: function(object, type) 3167 { 3168 return object && object.constructor && object.constructor.name == "Date"; 3169 }, 3170 }); 3171 3172 // ********************************************************************************************* // 3173 3174 FirebugReps.NamedNodeMap = domplate(Firebug.Rep, 3175 { 3176 tag: 3177 OBJECTLINK( 3178 SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["), 3179 FOR("prop", "$object|longPropIterator", 3180 SPAN({"class": "nodeName"}, "$prop.name"), 3181 SPAN({"class": "objectEqual", role: "presentation"}, "$prop.equal"), 3182 TAG("$prop.tag", {object: "$prop.object"}), 3183 SPAN({"class": "objectComma", role: "presentation"}, "$prop.delim") 3184 ), 3185 SPAN({"class": "arrayRightBracket", role: "presentation"}, "]") 3186 ), 3187 3188 shortTag: 3189 OBJECTLINK( 3190 SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["), 3191 FOR("prop", "$object|shortPropIterator", 3192 SPAN({"class": "nodeName"}, "$prop.name"), 3193 SPAN({"class": "objectEqual", role: "presentation"}, "$prop.equal"), 3194 TAG("$prop.tag", {object: "$prop.object"}), 3195 SPAN({"class": "objectComma", role: "presentation"}, "$prop.delim") 3196 ), 3197 SPAN({"class": "arrayRightBracket", role: "presentation"}, "]") 3198 ), 3199 3200 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 3201 3202 className: "NamedNodeMap", 3203 3204 supportsObject: function(object, type) 3205 { 3206 return (object instanceof window.NamedNodeMap); 3207 }, 3208 3209 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 3210 // Iterator 3211 3212 longPropIterator: function(object) 3213 { 3214 return this.propIterator(object, 100); 3215 }, 3216 3217 shortPropIterator: function(object) 3218 { 3219 return this.propIterator(object, Options.get("ObjectShortIteratorMax")); 3220 }, 3221 3222 propIterator: function (object, max) 3223 { 3224 max = max || 3; 3225 if (!object) 3226 return []; 3227 3228 var props = []; 3229 for (var i=0; i<object.length && i<max; i++) 3230 { 3231 var item = object.item(i); 3232 var name = item.name; 3233 var value = item.value; 3234 3235 var rep = Firebug.getRep(value); 3236 var tag = rep.tag; 3237 3238 props.push({tag: tag, name: name, object: value, equal: "=", delim: ", "}); 3239 } 3240 3241 if (object.length > max) 3242 { 3243 props[Math.max(1,max-1)] = { 3244 object: (object.length-max) + " " + Locale.$STR("firebug.reps.more") + "...", 3245 tag: FirebugReps.Caption.tag, 3246 name: "", 3247 equal:"", 3248 delim:"" 3249 }; 3250 } 3251 else if (props.length > 0) 3252 { 3253 props[props.length-1].delim = ''; 3254 } 3255 3256 return props; 3257 }, 3258 }); 3259 3260 // ********************************************************************************************* // 3261 // Error Message 3262 3263 FirebugReps.ErrorMessageObj = function(message, href, lineNo, source, category, context, 3264 trace, msgId, colNumber) 3265 { 3266 this.message = message; 3267 this.href = href; 3268 this.lineNo = lineNo; 3269 this.source = source; 3270 this.category = category; 3271 this.context = context; 3272 this.trace = trace; 3273 this.msgId = msgId; 3274 this.colNumber = colNumber; 3275 }; 3276 3277 FirebugReps.ErrorMessageObj.prototype = 3278 { 3279 getSourceLine: function() 3280 { 3281 if (!this.context.sourceCache) 3282 { 3283 if (FBTrace.DBG_ERRORS) 3284 FBTrace.sysout("reps.ErrorMessageObj.getSourceLine; ERROR no source cache!") 3285 return; 3286 } 3287 3288 return this.context.sourceCache.getLine(this.href, this.lineNo); 3289 }, 3290 3291 resetSource: function() 3292 { 3293 if (this.href && this.lineNo) 3294 this.source = this.getSourceLine(); 3295 }, 3296 3297 correctWithStackTrace: function(trace) 3298 { 3299 var frame = trace.frames[0]; 3300 if (frame) 3301 { 3302 this.href = frame.href; 3303 this.lineNo = frame.line; 3304 this.trace = trace; 3305 } 3306 }, 3307 3308 correctSourcePoint: function(sourceName, lineNumber) 3309 { 3310 this.href = sourceName; 3311 this.lineNo = lineNumber; 3312 }, 3313 }; 3314 3315 // ********************************************************************************************* // 3316 3317 FirebugReps.ErrorCopy = function(message) 3318 { 3319 this.message = message; 3320 }; 3321 3322 // ********************************************************************************************* // 3323 // Registration 3324 3325 Firebug.registerRep( 3326 FirebugReps.Undefined, 3327 FirebugReps.Null, 3328 FirebugReps.Number, 3329 FirebugReps.String, 3330 FirebugReps.nsIDOMHistory, // make this early to avoid exceptions 3331 FirebugReps.ApplicationCache, // this also 3332 FirebugReps.RegExp, 3333 FirebugReps.Window, 3334 FirebugReps.ErrorMessage, 3335 FirebugReps.Element, 3336 FirebugReps.TextNode, 3337 FirebugReps.Document, 3338 FirebugReps.StyleSheet, 3339 FirebugReps.CSSRule, 3340 FirebugReps.Event, 3341 FirebugReps.SourceLink, 3342 FirebugReps.CompilationUnit, 3343 FirebugReps.StackTrace, 3344 FirebugReps.StackFrame, 3345 FirebugReps.NetFile, 3346 FirebugReps.Property, 3347 FirebugReps.Except, 3348 FirebugReps.XML, 3349 FirebugReps.Arr, 3350 FirebugReps.ArrayLikeObject, 3351 FirebugReps.XPathResult, 3352 FirebugReps.Storage, 3353 FirebugReps.Attr, 3354 FirebugReps.Date, 3355 FirebugReps.NamedNodeMap, 3356 FirebugReps.Reference, 3357 FirebugReps.EventLog 3358 ); 3359 3360 Firebug.setDefaultReps(FirebugReps.Func, FirebugReps.Obj); 3361 3362 return Firebug.Reps = FirebugReps; 3363 3364 // ********************************************************************************************* // 3365 }}); 3366