1 /* See license.txt for terms of usage */ 2 3 var FirebugReps = FBL.ns(function() { with (FBL) { 4 5 // ************************************************************************************************ 6 // Constants 7 8 const Cc = Components.classes; 9 const Ci = Components.interfaces; 10 const jsdIStackFrame = Ci.jsdIStackFrame; 11 const jsdIScript = Ci.jsdIScript; 12 13 const fbs = Cc["@joehewitt.com/firebug;1"].getService().wrappedJSObject; 14 15 // ************************************************************************************************ 16 // Common Tags 17 18 var OBJECTBOX = this.OBJECTBOX = 19 SPAN({"class": "objectBox objectBox-$className", role : "presentation"}); 20 21 var OBJECTBLOCK = this.OBJECTBLOCK = 22 DIV({"class": "objectBox objectBox-$className focusRow subLogRow", role : "listitem"}); 23 24 var OBJECTLINK = this.OBJECTLINK = 25 A({ 26 "class": "objectLink objectLink-$className a11yFocus", 27 _repObject: "$object" 28 }); 29 30 // ************************************************************************************************ 31 32 this.Undefined = domplate(Firebug.Rep, 33 { 34 tag: OBJECTBOX("undefined"), 35 36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 37 38 className: "undefined", 39 40 supportsObject: function(object, type) 41 { 42 return type == "undefined"; 43 } 44 }); 45 46 // ************************************************************************************************ 47 48 this.Null = domplate(Firebug.Rep, 49 { 50 tag: OBJECTBOX("null"), 51 52 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 53 54 className: "null", 55 56 supportsObject: function(object, type) 57 { 58 return object == null; 59 } 60 }); 61 62 // ************************************************************************************************ 63 64 this.Nada = domplate(Firebug.Rep, 65 { 66 tag: SPAN(""), 67 68 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 69 70 className: "nada" 71 }); 72 73 // ************************************************************************************************ 74 75 this.Number = domplate(Firebug.Rep, 76 { 77 tag: OBJECTBOX("$object"), 78 79 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 80 81 className: "number", 82 83 supportsObject: function(object, type) 84 { 85 return type == "boolean" || type == "number"; 86 } 87 }); 88 89 // ************************************************************************************************ 90 91 this.String = domplate(Firebug.Rep, 92 { 93 tag: OBJECTBOX(""$object""), 94 95 shortTag: OBJECTBOX(""$object|cropMultipleLines""), 96 97 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 98 99 className: "string", 100 101 supportsObject: function(object, type) 102 { 103 return type == "string"; 104 } 105 }); 106 107 // ************************************************************************************************ 108 109 this.XML = domplate(Firebug.Rep, 110 { 111 tag: OBJECTBOX("$object|asString"), 112 113 shortTag: OBJECTBOX("$object|asShortString"), 114 115 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 116 117 className: "xml", 118 119 supportsObject: function(object, type) 120 { 121 return type == "xml"; 122 }, 123 124 asString: function(object) 125 { 126 return object.toXMLString(); 127 }, 128 129 asShortString: function(object) 130 { 131 return cropMultipleLines(this.asString(object)); 132 }, 133 }); 134 135 // ************************************************************************************************ 136 137 this.Text = domplate(Firebug.Rep, 138 { 139 tag: OBJECTBOX("$object"), 140 141 shortTag: OBJECTBOX("$object|cropMultipleLines"), 142 143 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 144 145 className: "text" 146 }); 147 148 // ************************************************************************************************ 149 150 this.Caption = domplate(Firebug.Rep, 151 { 152 tag: SPAN({"class": "caption"}, "$object") 153 }); 154 155 // ************************************************************************************************ 156 157 this.Warning = domplate(Firebug.Rep, 158 { 159 tag: DIV({"class": "warning focusRow", role : 'listitem'}, "$object|STR") 160 }); 161 162 // ************************************************************************************************ 163 164 this.Func = domplate(Firebug.Rep, 165 { 166 tag: 167 OBJECTLINK("$object|summarizeFunction"), 168 169 summarizeFunction: function(fn) 170 { 171 var fnRegex = /function ([^(]+\([^)]*\)) \{/; 172 var fnText = safeToString(fn); 173 174 var m = fnRegex.exec(fnText); 175 return m ? m[1] : "function()"; 176 }, 177 178 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 179 180 copySource: function(fn) 181 { 182 copyToClipboard(safeToString(fn)); 183 }, 184 185 monitor: function(fn, script, monitored) 186 { 187 if (monitored) 188 Firebug.Debugger.unmonitorScript(fn, script, "monitor"); 189 else 190 Firebug.Debugger.monitorScript(fn, script, "monitor"); 191 }, 192 193 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 194 195 className: "function", 196 197 supportsObject: function(object, type) 198 { 199 return type == "function"; 200 }, 201 202 inspectObject: function(fn, context) 203 { 204 var sourceLink = findSourceForFunction(fn, context); 205 if (sourceLink) 206 Firebug.chrome.select(sourceLink); 207 if (FBTrace.DBG_FUNCTION_NAME) 208 FBTrace.sysout("reps.function.inspectObject selected sourceLink is ", sourceLink); 209 }, 210 211 getTooltip: function(fn, context) 212 { 213 /* XXjjb I think this is very expensive... 214 var script = findScriptForFunctionInContext(context, fn); 215 if (script) 216 return $STRF("Line", [normalizeURL(script.fileName), script.baseLineNumber]); 217 else 218 */ 219 if (fn.toString) 220 return fn.toString(); 221 }, 222 223 getTitle: function(fn, context) 224 { 225 var name = fn.name ? fn.name : "function"; 226 return name + "()"; 227 }, 228 229 getContextMenuItems: function(fn, target, context, script) 230 { 231 if (!script) 232 script = findScriptForFunctionInContext(context, fn); 233 if (!script) 234 return; 235 236 var scriptInfo = Firebug.SourceFile.getSourceFileAndLineByScript(context, script); 237 var monitored = scriptInfo ? fbs.isMonitored(scriptInfo.sourceFile.href, scriptInfo.lineNo) : false; 238 239 var name = script ? getFunctionName(script, context) : fn.name; 240 return [ 241 {label: "CopySource", command: bindFixed(this.copySource, this, fn) }, 242 "-", 243 {label: $STRF("ShowCallsInConsole", [name]), nol10n: true, 244 type: "checkbox", checked: monitored, 245 command: bindFixed(this.monitor, this, fn, script, monitored) } 246 ]; 247 } 248 }); 249 250 // ************************************************************************************************ 251 252 this.jsdScript = domplate(Firebug.Rep, 253 { 254 copySource: function(script) 255 { 256 var fn = unwrapIValue(script.functionObject); 257 return FirebugReps.Func.copySource(fn); 258 }, 259 260 monitor: function(fn, script, monitored) 261 { 262 fn = unwrapIValue(script.functionObject); 263 return FirebugReps.Func.monitor(fn, script, monitored); 264 }, 265 266 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 267 268 className: "jsdScript", 269 inspectable: false, 270 271 supportsObject: function(object, type) 272 { 273 return object instanceof jsdIScript; 274 }, 275 276 inspectObject: function(script, context) 277 { 278 var sourceLink = getSourceLinkForScript(script, context); 279 if (sourceLink) 280 Firebug.chrome.select(sourceLink); 281 }, 282 283 getRealObject: function(script, context) 284 { 285 return script; 286 }, 287 288 getTooltip: function(script) 289 { 290 return $STRF("jsdIScript", [script.tag]); 291 }, 292 293 getTitle: function(script, context) 294 { 295 var fn = unwrapIValue(script.functionObject); 296 return FirebugReps.Func.getTitle(fn, context); 297 }, 298 299 getContextMenuItems: function(script, target, context) 300 { 301 var fn = unwrapIValue(script.functionObject); 302 303 var scriptInfo = Firebug.SourceFile.getSourceFileAndLineByScript(context, script); 304 var monitored = scriptInfo ? fbs.isMonitored(scriptInfo.sourceFile.href, scriptInfo.lineNo) : false; 305 306 var name = getFunctionName(script, context); 307 308 return [ 309 {label: "CopySource", command: bindFixed(this.copySource, this, script) }, 310 "-", 311 {label: $STRF("ShowCallsInConsole", [name]), nol10n: true, 312 type: "checkbox", checked: monitored, 313 command: bindFixed(this.monitor, this, fn, script, monitored) } 314 ]; 315 } 316 }); 317 318 //************************************************************************************************ 319 320 this.Obj = domplate(Firebug.Rep, 321 { 322 tag: 323 OBJECTLINK( 324 SPAN({"class": "objectTitle"}, "$object|getTitle "), 325 SPAN({"class": "objectLeftBrace", role: "presentation"}, "{"), 326 FOR("prop", "$object|shortPropIterator", 327 " $prop.name", 328 SPAN({"class": "objectEqual", role: "presentation"}, "$prop.equal"), 329 TAG("$prop.tag", {object: "$prop.object"}), 330 SPAN({"class": "objectComma", role: "presentation"}, "$prop.delim") 331 ), 332 SPAN({"class": "objectRightBrace"}, "}") 333 ), 334 335 shortTag: 336 OBJECTLINK( 337 SPAN({"class": "objectTitle"}, "$object|getTitle "), 338 SPAN({"class": "objectLeftBrace", role: "presentation"}, "{"), 339 FOR("prop", "$object|shortPropIterator", 340 " $prop.name", 341 SPAN({"class": "objectEqual", role: "presentation"}, "$prop.equal"), 342 TAG("$prop.tag", {object: "$prop.object"}), 343 SPAN({"class": "objectComma", role: "presentation"}, "$prop.delim") 344 ), 345 SPAN({"class": "objectRightBrace"}, "}") 346 ), 347 348 titleTag: 349 SPAN({"class": "objectTitle"}, "$object|getTitle"), 350 351 longPropIterator: function (object) 352 { 353 return this.propIterator(object,100); 354 }, 355 356 shortPropIterator: function (object) 357 { 358 return this.propIterator(object,1); 359 }, 360 361 propIterator: function (object, max) 362 { 363 max = max || 3; 364 if (!object) 365 return []; 366 367 var props = []; 368 var len = 0, count = 0; 369 370 try 371 { 372 for (var name in object) 373 { 374 var value; 375 try 376 { 377 value = object[name]; 378 } 379 catch (exc) 380 { 381 continue; 382 } 383 384 var t = typeof(value); 385 if (t == "boolean" || t == "number" || (t == "string" && value) 386 || (t == "object" && value && value.toString)) 387 { 388 var rep = Firebug.getRep(value); 389 var tag = rep.shortTag || rep.tag; 390 if (t == "object") 391 { 392 value = rep.getTitle(value); 393 tag = rep.titleTag; 394 } 395 count++; 396 if (count <= max) 397 props.push({tag: tag, name: name, object: value, equal: "=", delim: ", "}); 398 else 399 break; 400 } 401 } 402 if (count > max) 403 { 404 props[Math.max(1,max-1)] = { 405 object: "more...", //xxxHonza localization 406 tag: FirebugReps.Caption.tag, 407 name: "", 408 equal:"", 409 delim:"" 410 }; 411 } 412 else if (props.length > 0) 413 { 414 props[props.length-1].delim = ''; 415 } 416 } 417 catch (exc) 418 { 419 // Sometimes we get exceptions when trying to read from certain objects, like 420 // StorageList, but don't let that gum up the works 421 // XXXjjb also History.previous fails because object is a web-page object which does not have 422 // permission to read the history 423 } 424 return props; 425 }, 426 427 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 428 429 className: "object", 430 431 supportsObject: function(object, type) 432 { 433 return true; 434 } 435 }); 436 437 // ************************************************************************************************ 438 439 this.Arr = domplate(Firebug.Rep, 440 { 441 tag: 442 OBJECTBOX({_repObject: "$object", 443 $hasTwisty: "$object|hasSpecialProperties", 444 onclick: "$onToggleProperties"}, 445 SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["), 446 FOR("item", "$object|longArrayIterator", 447 TAG("$item.tag", {object: "$item.object"}), 448 SPAN({"class": "arrayComma", role: "presentation"}, "$item.delim") 449 ), 450 SPAN({"class": "arrayRightBracket", role: "presentation"}, "]"), 451 SPAN({"class": "arrayProperties", role: "group"}) 452 ), 453 454 shortTag: 455 OBJECTBOX({_repObject: "$object", 456 $hasTwisty: "$object|hasSpecialProperties", 457 onclick: "$onToggleProperties"}, 458 SPAN({"class": "arrayLeftBracket", role: "presentation"}, "["), 459 FOR("item", "$object|shortArrayIterator", 460 TAG("$item.tag", {object: "$item.object"}), 461 SPAN({"class": "arrayComma", role: "presentation"}, "$item.delim") 462 ), 463 SPAN({"class": "arrayRightBracket"}, "]"), 464 SPAN({"class": "arrayProperties", role: "group"}) 465 ), 466 467 longArrayIterator: function(array) 468 { 469 return this.arrayIterator(array,300); 470 }, 471 472 shortArrayIterator: function(array) 473 { 474 return this.arrayIterator(array,3); 475 }, 476 477 arrayIterator: function(array, max) 478 { 479 var items = []; 480 for (var i = 0; i < array.length && i <= max; ++i) 481 { 482 var value = array[i]; 483 var rep = Firebug.getRep(value); 484 var tag = rep.shortTag || rep.tag; 485 var delim = (i == array.length-1 ? "" : ", "); 486 487 items.push({object: value, tag: tag, delim: delim}); 488 } 489 490 if (array.length > max + 1) 491 { 492 items[max] = { 493 object: (array.length-max) + " more...", //xxxHonza localization 494 tag: FirebugReps.Caption.tag, 495 delim: "" 496 }; 497 } 498 499 return items; 500 }, 501 502 toggles: {}, 503 504 getItemIndex: function(child) 505 { 506 var arrayIndex = 0; 507 for (child = child.previousSibling; child; child = child.previousSibling) 508 { 509 if (child.repObject) 510 ++arrayIndex; 511 } 512 return arrayIndex; 513 }, 514 515 hasSpecialProperties: function(array) 516 { 517 return (array.length != array.__count__) && hasProperties(array); 518 }, 519 520 onToggleProperties: function(event) 521 { 522 var target = event.originalTarget; 523 if (hasClass(target, "objectBox-array")) 524 { 525 toggleClass(target, "opened"); 526 527 var propBox = target.getElementsByClassName("arrayProperties").item(0); 528 if (hasClass(target, "opened")) 529 Firebug.DOMPanel.DirTable.tag.replace( 530 {object: target.repObject, toggles: this.toggles}, propBox); 531 else 532 clearNode(propBox); 533 } 534 }, 535 536 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 537 538 className: "array", 539 540 supportsObject: function(object) 541 { 542 return this.isArray(object); 543 }, 544 545 // http://code.google.com/p/fbug/issues/detail?id=874 546 // BEGIN Yahoo BSD Source (modified here) YAHOO.lang.isArray, YUI 2.2.2 June 2007 547 isArray: function(obj) { 548 try { 549 if (!obj) 550 return false; 551 else if (obj instanceof Ci.nsIDOMHistory) // do this first to avoid security 1000 errors 552 return false; 553 else if (obj instanceof StorageList) // do this first to avoid security 1000 errors 554 return false; 555 else if (isFinite(obj.length) && typeof obj.splice === 'function') 556 return true; 557 else if (isFinite(obj.length) && typeof obj.callee === 'function') // arguments 558 return true; 559 else if (obj instanceof HTMLCollection) 560 return true; 561 else if (obj instanceof NodeList) 562 return true; 563 else 564 return false; 565 } 566 catch(exc) 567 { 568 if (FBTrace.DBG_ERRORS) 569 { 570 FBTrace.sysout("isArray FAILS:", exc); /* Something weird: without the try/catch, OOM, with no exception?? */ 571 FBTrace.sysout("isArray Fails on obj "+obj); 572 } 573 } 574 575 return false; 576 }, 577 // END Yahoo BSD SOURCE See license below. 578 579 getTitle: function(object, context) 580 { 581 return "[" + object.length + "]"; 582 } 583 }); 584 585 // ************************************************************************************************ 586 587 this.Property = domplate(Firebug.Rep, 588 { 589 supportsObject: function(object) 590 { 591 return object instanceof Property; 592 }, 593 594 getRealObject: function(prop, context) 595 { 596 return prop.object[prop.name]; 597 }, 598 599 getTitle: function(prop, context) 600 { 601 return prop.name; 602 } 603 }); 604 605 // ************************************************************************************************ 606 607 this.NetFile = domplate(this.Obj, 608 { 609 supportsObject: function(object) 610 { 611 return object instanceof Firebug.NetFile; 612 }, 613 614 browseObject: function(file, context) 615 { 616 openNewTab(file.href); 617 return true; 618 }, 619 620 getRealObject: function(file, context) 621 { 622 return null; 623 } 624 }); 625 626 // ************************************************************************************************ 627 628 this.Except = domplate(Firebug.Rep, 629 { 630 tag: 631 OBJECTBOX({_repObject: "$object"}, "$object.message"), 632 633 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 634 635 className: "exception", 636 637 supportsObject: function(object) 638 { 639 return object instanceof ErrorCopy; 640 } 641 }); 642 643 644 // ************************************************************************************************ 645 646 this.Element = domplate(Firebug.Rep, 647 { 648 tag: 649 OBJECTLINK( 650 "<", 651 SPAN({"class": "nodeTag"}, "$object.localName|toLowerCase"), 652 FOR("attr", "$object|attrIterator", 653 " $attr.localName="", SPAN({"class": "nodeValue"}, "$attr.nodeValue"), """ 654 ), 655 ">" 656 ), 657 658 shortTag: 659 OBJECTLINK( 660 SPAN({"class": "$object|getVisible"}, 661 SPAN({"class": "selectorTag"}, "$object|getSelectorTag"), 662 SPAN({"class": "selectorId"}, "$object|getSelectorId"), 663 SPAN({"class": "selectorClass"}, "$object|getSelectorClass"), 664 SPAN({"class": "selectorValue"}, "$object|getValue") 665 ) 666 ), 667 668 getVisible: function(elt) 669 { 670 return isVisible(elt) ? "" : "selectorHidden"; 671 }, 672 673 getSelectorTag: function(elt) 674 { 675 return elt.localName.toLowerCase(); 676 }, 677 678 getSelectorId: function(elt) 679 { 680 return elt.id ? ("#" + elt.id) : ""; 681 }, 682 683 getSelectorClass: function(elt) 684 { 685 return elt.getAttribute("class") 686 ? ("." + elt.getAttribute("class").split(" ")[0]) 687 : ""; 688 }, 689 690 getValue: function(elt) 691 { 692 var value; 693 694 if (elt instanceof HTMLImageElement) 695 value = getFileName(elt.getAttribute("src")); 696 else if (elt instanceof HTMLAnchorElement) 697 value = getFileName(elt.getAttribute("href")); 698 else if (elt instanceof HTMLInputElement) 699 value = elt.getAttribute("value"); 700 else if (elt instanceof HTMLFormElement) 701 value = getFileName(elt.getAttribute("action")); 702 else if (elt instanceof HTMLScriptElement) 703 value = getFileName(elt.getAttribute("src")); 704 705 return value ? " " + cropMultipleLines(value, 20) : ""; 706 }, 707 708 attrIterator: function(elt) 709 { 710 var attrs = []; 711 var idAttr, classAttr; 712 if (elt.attributes) 713 { 714 for (var i = 0; i < elt.attributes.length; ++i) 715 { 716 var attr = elt.attributes[i]; 717 if (attr.localName.indexOf("-moz-math") != -1) 718 continue; 719 if (attr.localName.indexOf("firebug-") != -1) 720 continue; 721 else if (attr.localName == "id") 722 idAttr = attr; 723 else if (attr.localName == "class") 724 classAttr = attr; 725 else 726 attrs.push(attr); 727 } 728 } 729 if (classAttr) 730 attrs.splice(0, 0, classAttr); 731 if (idAttr) 732 attrs.splice(0, 0, idAttr); 733 return attrs; 734 }, 735 736 shortAttrIterator: function(elt) 737 { 738 var attrs = []; 739 if (elt.attributes) 740 { 741 for (var i = 0; i < elt.attributes.length; ++i) 742 { 743 var attr = elt.attributes[i]; 744 if (attr.localName == "id" || attr.localName == "class") 745 attrs.push(attr); 746 } 747 } 748 749 return attrs; 750 }, 751 752 getHidden: function(elt) 753 { 754 return isVisible(elt) ? "" : "nodeHidden"; 755 }, 756 757 getXPath: function(elt) 758 { 759 return getElementTreeXPath(elt); 760 }, 761 762 getNodeTextGroups: function(element) 763 { 764 var text = element.textContent; 765 if (!Firebug.showFullTextNodes) 766 { 767 text=cropString(text,50); 768 } 769 770 var escapeGroups=[]; 771 772 if (Firebug.showTextNodesWithWhitespace) 773 escapeGroups.push({ 774 'group': 'whitespace', 775 'class': 'nodeWhiteSpace', 776 'extra': { 777 '\t': '_Tab', 778 '\n': '_Para', 779 ' ' : '_Space' 780 } 781 }); 782 if (Firebug.showTextNodesWithEntities) 783 escapeGroups.push({ 784 'group':'text', 785 'class':'nodeTextEntity', 786 'extra':{} 787 }); 788 789 if (escapeGroups.length) 790 return escapeGroupsForEntities(text, escapeGroups); 791 else 792 return [{str:text,'class':'',extra:''}]; 793 }, 794 795 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 796 797 copyHTML: function(elt) 798 { 799 var html = getElementHTML(elt); 800 copyToClipboard(html); 801 }, 802 803 copyInnerHTML: function(elt) 804 { 805 copyToClipboard(elt.innerHTML); 806 }, 807 808 copyXPath: function(elt) 809 { 810 var xpath = getElementXPath(elt); 811 copyToClipboard(xpath); 812 }, 813 814 persistor: function(context, xpath) 815 { 816 var elts = xpath 817 ? getElementsByXPath(context.window.document, xpath) 818 : null; 819 820 return elts && elts.length ? elts[0] : null; 821 }, 822 823 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 824 825 className: "element", 826 827 supportsObject: function(object) 828 { 829 return object instanceof Element; 830 }, 831 832 browseObject: function(elt, context) 833 { 834 var tag = elt.localName.toLowerCase(); 835 if (tag == "script") 836 openNewTab(elt.src); 837 else if (tag == "link") 838 openNewTab(elt.href); 839 else if (tag == "a") 840 openNewTab(elt.href); 841 else if (tag == "img") 842 openNewTab(elt.src); 843 844 return true; 845 }, 846 847 persistObject: function(elt, context) 848 { 849 var xpath = getElementXPath(elt); 850 851 return bind(this.persistor, top, xpath); 852 }, 853 854 getTitle: function(element, context) 855 { 856 return getElementCSSSelector(element); 857 }, 858 859 getTooltip: function(elt) 860 { 861 return this.getXPath(elt); 862 }, 863 864 getContextMenuItems: function(elt, target, context) 865 { 866 var monitored = areEventsMonitored(elt, null, context); 867 var CopyElement = "CopyHTML"; 868 if (isElementSVG(elt)) 869 CopyElement = "CopySVG"; 870 if (isElementMathML(elt)) 871 CopyElement = "CopyMathML"; 872 873 var items=[{label: CopyElement, command: bindFixed(this.copyHTML, this, elt)}]; 874 if (!isElementSVG(elt) && !isElementMathML(elt)) 875 items.push({label: "CopyInnerHTML", command: bindFixed(this.copyInnerHTML, this, elt) }); 876 877 return items.concat([ 878 {label: "CopyXPath", command: bindFixed(this.copyXPath, this, elt) }, 879 "-", 880 {label: "ShowEventsInConsole", type: "checkbox", checked: monitored, 881 command: bindFixed(toggleMonitorEvents, FBL, elt, null, monitored, context) }, 882 "-", 883 {label: "ScrollIntoView", command: bindFixed(elt.scrollIntoView, elt) } 884 ]); 885 } 886 }); 887 888 // ************************************************************************************************ 889 890 this.TextNode = domplate(Firebug.Rep, 891 { 892 tag: 893 OBJECTLINK( 894 "<", 895 SPAN({"class": "nodeTag"}, "TextNode"), 896 " textContent="", SPAN({"class": "nodeValue"}, "$object.textContent|cropMultipleLines"), """, 897 ">" 898 ), 899 900 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 901 902 className: "textNode", 903 904 inspectObject: function(node, context) 905 { 906 // Text nodes have two displays in HTML panel, inline and distinct 907 // node. We need to examine which case we are dealing with in order to 908 // select the proper object. 909 if (Firebug.HTMLLib.hasNoElementChildren(node.parentNode)) 910 { 911 node = node.parentNode; 912 } 913 914 Firebug.chrome.select(node, "html", "domSide"); 915 }, 916 917 supportsObject: function(object) 918 { 919 return object instanceof Text; 920 }, 921 922 getTitle: function(win, context) 923 { 924 return "textNode"; 925 } 926 }); 927 928 929 // ************************************************************************************************ 930 931 var regexpConstructorRE = /RegExp/; 932 this.RegExp = domplate(Firebug.Rep, 933 { 934 tag: 935 OBJECTLINK( 936 SPAN({"class": "objectTitle"}, "$object|getTitle") 937 ), 938 939 className: "regexp", 940 941 supportsObject: function(object, type) 942 { 943 return type == "object" && object && object.constructor && object.constructor.toString && regexpConstructorRE.test(object.constructor.toString()); 944 } 945 }); 946 947 948 // ************************************************************************************************ 949 950 this.Document = domplate(Firebug.Rep, 951 { 952 tag: 953 OBJECTLINK("Document ", SPAN({"class": "objectPropValue"}, "$object|getLocation")), 954 955 getLocation: function(doc) 956 { 957 return doc.location ? getFileName(doc.location.href) : ""; 958 }, 959 960 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 961 962 className: "object", 963 964 supportsObject: function(object) 965 { 966 return object instanceof Document || object instanceof XMLDocument; 967 }, 968 969 browseObject: function(doc, context) 970 { 971 openNewTab(doc.location.href); 972 return true; 973 }, 974 975 persistObject: function(doc, context) 976 { 977 return this.persistor; 978 }, 979 980 persistor: function(context) 981 { 982 return context.window.document; 983 }, 984 985 getTitle: function(win, context) 986 { 987 return "document"; 988 }, 989 990 getTooltip: function(doc) 991 { 992 return doc.location.href; 993 } 994 }); 995 996 // ************************************************************************************************ 997 998 this.StyleSheet = domplate(Firebug.Rep, 999 { 1000 tag: 1001 OBJECTLINK("StyleSheet ", SPAN({"class": "objectPropValue"}, "$object|getLocation")), 1002 1003 getLocation: function(styleSheet) 1004 { 1005 return getFileName(styleSheet.href); 1006 }, 1007 1008 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1009 1010 copyURL: function(styleSheet) 1011 { 1012 copyToClipboard(styleSheet.href); 1013 }, 1014 1015 openInTab: function(styleSheet) 1016 { 1017 openNewTab(styleSheet.href); 1018 }, 1019 1020 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1021 1022 className: "object", 1023 1024 supportsObject: function(object) 1025 { 1026 return object instanceof CSSStyleSheet; 1027 }, 1028 1029 browseObject: function(styleSheet, context) 1030 { 1031 openNewTab(styleSheet.href); 1032 return true; 1033 }, 1034 1035 persistObject: function(styleSheet, context) 1036 { 1037 return bind(this.persistor, top, styleSheet.href); 1038 }, 1039 1040 getTooltip: function(styleSheet) 1041 { 1042 return styleSheet.href; 1043 }, 1044 1045 getContextMenuItems: function(styleSheet, target, context) 1046 { 1047 return [ 1048 {label: "CopyLocation", command: bindFixed(this.copyURL, this, styleSheet) }, 1049 "-", 1050 {label: "OpenInTab", command: bindFixed(this.openInTab, this, styleSheet) } 1051 ]; 1052 }, 1053 1054 persistor: function(context, href) 1055 { 1056 return getStyleSheetByHref(href, context); 1057 } 1058 }); 1059 1060 // ************************************************************************************************ 1061 1062 this.Window = domplate(Firebug.Rep, 1063 { 1064 tag: 1065 OBJECTLINK("Window ", SPAN({"class": "objectPropValue"}, "$object|getLocation")), 1066 1067 getLocation: function(win) 1068 { 1069 try 1070 { 1071 return (win && win.location && !win.closed) ? getFileName(win.location.href) : ""; 1072 } 1073 catch (exc) 1074 { 1075 if (FBTrace.DBG_ERRORS) 1076 FBTrace.sysout("reps.Window window closed?"); 1077 } 1078 }, 1079 1080 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1081 1082 className: "object", 1083 1084 supportsObject: function(object) 1085 { 1086 return object instanceof Window; 1087 }, 1088 1089 browseObject: function(win, context) 1090 { 1091 openNewTab(win.location.href); 1092 return true; 1093 }, 1094 1095 persistObject: function(win, context) 1096 { 1097 return this.persistor; 1098 }, 1099 1100 persistor: function(context) 1101 { 1102 return context.window; 1103 }, 1104 1105 getTitle: function(win, context) 1106 { 1107 return "window"; 1108 }, 1109 1110 getTooltip: function(win) 1111 { 1112 if (win && !win.closed) 1113 return win.location.href; 1114 } 1115 }); 1116 1117 // ************************************************************************************************ 1118 1119 this.Event = domplate(Firebug.Rep, 1120 { 1121 tag: TAG("$copyEventTag", {object: "$object|copyEvent"}), 1122 1123 copyEventTag: 1124 OBJECTLINK("$object|summarizeEvent"), 1125 1126 summarizeEvent: function(event) 1127 { 1128 var info = [event.type, ' ']; 1129 1130 var eventFamily = getEventFamily(event.type); 1131 if (eventFamily == "mouse") 1132 info.push("clientX=", event.clientX, ", clientY=", event.clientY); 1133 else if (eventFamily == "key") 1134 info.push("charCode=", event.charCode, ", keyCode=", event.keyCode); 1135 1136 return info.join(""); 1137 }, 1138 1139 copyEvent: function(event) 1140 { 1141 return new EventCopy(event); 1142 }, 1143 1144 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1145 1146 className: "object", 1147 1148 supportsObject: function(object) 1149 { 1150 return object instanceof Event || object instanceof EventCopy; 1151 }, 1152 1153 getTitle: function(event, context) 1154 { 1155 return "Event " + event.type; 1156 } 1157 }); 1158 1159 // ************************************************************************************************ 1160 1161 this.SourceLink = domplate(Firebug.Rep, 1162 { 1163 tag: 1164 OBJECTLINK( 1165 {$collapsed: "$object|hideSourceLink"}, 1166 DIV("$object|getSourceLinkTitle"), 1167 DIV({$systemLink: "$object|isSystemLink"}, "$object|getSystemFlagTitle")), 1168 1169 isSystemLink: function(sourceLink) 1170 { 1171 return sourceLink && isSystemURL(sourceLink.href); 1172 }, 1173 1174 hideSourceLink: function(sourceLink) 1175 { 1176 try 1177 { 1178 return (sourceLink && sourceLink.href && sourceLink.href.indexOf) ? 1179 (sourceLink.href.indexOf("XPCSafeJSObjectWrapper") != -1) : true; 1180 } 1181 catch (e) 1182 { 1183 // xxxHonza: I see "Security error" code: "1000" nsresult: "0x805303e8 (NS_ERROR_DOM_SECURITY_ERR)" 1184 // when accessing globalStorage property of a page. 1185 if (FBTrace.DBG_ERRORS) 1186 FBTrace.sysout("reps.hideSourceLink; EXCEPTION " + sourceLink + ", " + e, e); 1187 } 1188 1189 return true; 1190 }, 1191 1192 getSourceLinkTitle: function(sourceLink) 1193 { 1194 if (!sourceLink) 1195 return ""; 1196 1197 try 1198 { 1199 var fileName = getFileName(sourceLink.href); 1200 fileName = decodeURIComponent(fileName); 1201 } 1202 catch(exc) 1203 { 1204 if (FBTrace.DBG_ERRORS) 1205 FBTrace.sysout("reps.getSourceLinkTitle decodeURIComponent fails for \'"+fileName+"\': "+exc, exc); 1206 fileName = sourceLink.href; 1207 } 1208 1209 var maxWidth = Firebug.sourceLinkLabelWidth; 1210 if (maxWidth > 0) 1211 fileName = cropString(fileName, maxWidth); 1212 1213 if (sourceLink.instance) 1214 return $STRF("InstanceLine", [fileName, sourceLink.instance+1, sourceLink.line]); 1215 else if (sourceLink.line) 1216 return $STRF("Line", [fileName, sourceLink.line]); 1217 else 1218 return fileName; 1219 }, 1220 1221 getSystemFlagTitle: function(sourceLink) 1222 { 1223 if (this.isSystemLink(sourceLink)) 1224 return $STRF("SystemItem", [""]); 1225 else 1226 return ""; 1227 }, 1228 1229 copyLink: function(sourceLink) 1230 { 1231 copyToClipboard(sourceLink.href); 1232 }, 1233 1234 openInTab: function(sourceLink) 1235 { 1236 openNewTab(sourceLink.href); 1237 }, 1238 1239 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1240 1241 className: "sourceLink", 1242 1243 supportsObject: function(object) 1244 { 1245 return object instanceof SourceLink; 1246 }, 1247 1248 getTooltip: function(sourceLink) 1249 { 1250 var text; 1251 try 1252 { 1253 text = decodeURI(sourceLink.href); 1254 } 1255 catch(exc) 1256 { 1257 if (FBTrace.DBG_ERRORS) 1258 FBTrace.sysout("reps.getTooltip decodeURI fails for " + sourceLink.href, exc); 1259 } 1260 1261 text = unescape(sourceLink.href); 1262 1263 var lines = splitLines(text); 1264 if (lines.length < 10) 1265 return text; 1266 1267 lines.splice(10); 1268 return lines.join("") + "..."; 1269 }, 1270 1271 inspectObject: function(sourceLink, context) 1272 { 1273 if (sourceLink.type == "js") 1274 { 1275 var scriptFile = getSourceFileByHref(sourceLink.href, context); 1276 if (scriptFile) 1277 return Firebug.chrome.select(sourceLink); 1278 } 1279 else if (sourceLink.type == "css") 1280 { 1281 // If an object is defined, treat it as the highest priority for 1282 // inspect actions 1283 if (sourceLink.object) { 1284 Firebug.chrome.select(sourceLink.object); 1285 return; 1286 } 1287 1288 var stylesheet = getStyleSheetByHref(sourceLink.href, context); 1289 if (stylesheet) 1290 { 1291 var ownerNode = stylesheet.ownerNode; 1292 if (ownerNode) 1293 { 1294 Firebug.chrome.select(sourceLink, "html"); 1295 return; 1296 } 1297 1298 var panel = context.getPanel("stylesheet"); 1299 if (panel && panel.getRuleByLine(stylesheet, sourceLink.line)) 1300 return Firebug.chrome.select(sourceLink); 1301 } 1302 } 1303 else if (sourceLink.type == "net") 1304 { 1305 return Firebug.chrome.select(sourceLink); 1306 } 1307 1308 // Fallback is to just open the view-source window on the file 1309 viewSource(sourceLink.href, sourceLink.line); 1310 }, 1311 1312 browseObject: function(sourceLink, context) 1313 { 1314 openNewTab(sourceLink.href); 1315 return true; 1316 }, 1317 1318 getContextMenuItems: function(sourceLink, target, context) 1319 { 1320 return [ 1321 {label: "CopyLocation", command: bindFixed(this.copyLink, this, sourceLink) }, 1322 "-", 1323 {label: "OpenInTab", command: bindFixed(this.openInTab, this, sourceLink) } 1324 ]; 1325 } 1326 }); 1327 1328 // ************************************************************************************************ 1329 1330 this.SourceFile = domplate(this.SourceLink, 1331 { 1332 tag: 1333 OBJECTLINK({$collapsed: "$object|hideSourceLink"}, "$object|getSourceLinkTitle"), 1334 1335 persistor: function(context, href) 1336 { 1337 return getSourceFileByHref(href, context); 1338 }, 1339 1340 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1341 1342 className: "sourceFile", 1343 1344 supportsObject: function(object) 1345 { 1346 return object instanceof Firebug.SourceFile; 1347 }, 1348 1349 persistObject: function(sourceFile) 1350 { 1351 return bind(this.persistor, top, sourceFile.href); 1352 }, 1353 1354 browseObject: function(sourceLink, context) 1355 { 1356 }, 1357 1358 getTooltip: function(sourceFile) 1359 { 1360 return sourceFile.href; 1361 } 1362 }); 1363 1364 // ************************************************************************************************ 1365 1366 this.StackFrame = domplate(Firebug.Rep, // XXXjjb Since the repObject is fn the stack does not have correct line numbers 1367 { 1368 tag: 1369 OBJECTBLOCK( 1370 A({"class": "objectLink a11yFocus", _repObject: "$object"}, "$object|getCallName"), 1371 SPAN("("), 1372 FOR("arg", "$object|argIterator", 1373 TAG("$arg.tag", {object: "$arg.value"}), 1374 SPAN({"class": "arrayComma"}, "$arg.delim") 1375 ), 1376 SPAN(")"), 1377 SPAN({"class": "objectLink-sourceLink objectLink a11yFocus", 1378 _repObject: "$object|getSourceLink", 1379 role: "link"}, 1380 "$object|getSourceLinkTitle") 1381 ), 1382 1383 getCallName: function(frame) 1384 { 1385 if (frame.fn && frame.fn != "anonymous") 1386 return frame.fn; 1387 return getFunctionName(frame.script, frame.context, null, true); 1388 }, 1389 1390 getSourceLinkTitle: function(frame) 1391 { 1392 var fileName = cropString(getFileName(frame.href), 17); 1393 return $STRF("Line", [fileName, frame.line]); 1394 }, 1395 1396 argIterator: function(frame) 1397 { 1398 if (!frame.args) 1399 return []; 1400 1401 var items = []; 1402 1403 for (var i = 0; i < frame.args.length; ++i) 1404 { 1405 var arg = frame.args[i]; 1406 1407 if (!arg) 1408 break; 1409 1410 if (arg.value) // then we got these from jsd 1411 { 1412 var rep = Firebug.getRep(arg.value); 1413 var tag = rep.shortTag ? rep.shortTag : rep.tag; 1414 1415 var delim = (i == frame.args.length-1 ? "" : ", "); 1416 1417 items.push({name: arg.name, value: arg.value, tag: tag, delim: delim}); 1418 } 1419 else // eg from Error object 1420 { 1421 var delim = (i == frame.args.length-1 ? "" : ", "); 1422 var rep = Firebug.getRep(arg); 1423 var tag = rep.shortTag ? rep.shortTag : rep.tag; 1424 1425 items.push({value: arg, tag: tag, delim: delim}); 1426 } 1427 } 1428 1429 return items; 1430 }, 1431 1432 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1433 1434 className: "stackFrame", 1435 1436 supportsObject: function(object) 1437 { 1438 return object instanceof StackFrame; 1439 }, 1440 1441 inspectObject: function(stackFrame, context) 1442 { 1443 Firebug.chrome.select(this.getSourceLink(stackFrame)); 1444 }, 1445 1446 getTooltip: function(stackFrame, context) 1447 { 1448 return $STRF("Line", [stackFrame.href, stackFrame.line]); 1449 }, 1450 1451 getSourceLink: function(stackFrame) 1452 { 1453 var sourceLink = new SourceLink(stackFrame.href, stackFrame.line, "js"); 1454 return sourceLink; 1455 }, 1456 }); 1457 1458 // ************************************************************************************************ 1459 1460 this.StackTrace = domplate(Firebug.Rep, 1461 { 1462 tag: 1463 DIV({role : "group", 'aria-label' : $STR('aria.labels.stack trace')}, 1464 FOR("frame", "$object.frames", 1465 TAG(this.StackFrame.tag, {object: "$frame"}) 1466 ) 1467 ), 1468 1469 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1470 1471 className: "stackTrace", 1472 1473 supportsObject: function(object) 1474 { 1475 return object instanceof StackTrace; 1476 } 1477 }); 1478 1479 // ************************************************************************************************ 1480 1481 this.jsdStackFrame = domplate(Firebug.Rep, 1482 { 1483 inspectable: false, 1484 1485 className: "jsdIStactFrame", 1486 1487 supportsObject: function(object) 1488 { 1489 return (object instanceof jsdIStackFrame); 1490 }, 1491 1492 getTitle: function(frame, context) 1493 { 1494 if (!frame.isValid) return "(invalid frame)"; // XXXjjb avoid frame.script == null 1495 return getFunctionName(frame.script, context); 1496 }, 1497 1498 getTooltip: function(frame, context) 1499 { 1500 if (!frame.isValid) return "(invalid frame; did Firebug suspend?)"; // XXXjjb avoid frame.script == null 1501 var sourceInfo = Firebug.SourceFile.getSourceFileAndLineByScript(context, frame.script, frame); 1502 if (sourceInfo) 1503 return $STRF("Line", [sourceInfo.sourceFile.href, sourceInfo.lineNo]); 1504 else 1505 return $STRF("Line", [frame.script.fileName, frame.line]); 1506 }, 1507 1508 getContextMenuItems: function(frame, target, context) 1509 { 1510 var fn = unwrapIValue(frame.script.functionObject); 1511 return FirebugReps.Func.getContextMenuItems(fn, target, context, frame.script); 1512 } 1513 }); 1514 1515 // ************************************************************************************************ 1516 1517 this.ErrorMessage = domplate(Firebug.Rep, 1518 { 1519 tag: 1520 OBJECTBOX({ 1521 $hasTwisty: "$object|hasStackTrace", 1522 $hasBreakSwitch: "$object|hasBreakSwitch", 1523 $breakForError: "$object|hasErrorBreak", 1524 _repObject: "$object", 1525 _stackTrace: "$object|getLastErrorStackTrace", 1526 onclick: "$onToggleError"}, 1527 1528 DIV({"class": "errorTitle focusRow subLogRow", role : 'listitem'}, 1529 SPAN({"class": "errorDuplication"}, "$object.msgId|getDuplication"), 1530 "$object.message|getMessage" 1531 ), 1532 DIV({"class": "errorTrace", role : 'presentation'}), 1533 DIV({"class": "errorSourceBox errorSource-$object|getSourceType focusRow subLogRow", role : "listitem"}, 1534 IMG({"class": "errorBreak a11yFocus", src:"blank.gif", role : 'checkbox', 'aria-checked':"$object|hasErrorBreak", title: "Break on this error"}), 1535 A({"class": "errorSource a11yFocus"}, "$object|getLine"), 1536 TAG(this.SourceLink.tag, {object: "$object|getSourceLink"}) 1537 ) 1538 ), 1539 1540 getLastErrorStackTrace: function(error) 1541 { 1542 return error.trace; 1543 }, 1544 1545 hasStackTrace: function(error) 1546 { 1547 var url = error.href.toString(); 1548 var fromCommandLine = (url.indexOf("XPCSafeJSObjectWrapper") != -1); 1549 return !fromCommandLine && error.trace; 1550 }, 1551 1552 hasBreakSwitch: function(error) 1553 { 1554 return error.href && error.lineNo > 0; 1555 }, 1556 1557 hasErrorBreak: function(error) 1558 { 1559 return fbs.hasErrorBreakpoint(normalizeURL(error.href), error.lineNo); 1560 }, 1561 1562 getMessage: function(message) 1563 { 1564 var re = /\[Exception... "(.*?)" nsresult:/; 1565 var m = re.exec(message); 1566 return m ? m[1] : message; 1567 }, 1568 1569 getDuplication: function(msgId) 1570 { 1571 return ""; // filled in later 1572 }, 1573 1574 getLine: function(error) 1575 { 1576 if (error.source) 1577 return cropMultipleLines(error.source, 80); 1578 if (error.category == "js" && error.href && error.href.indexOf("XPCSafeJSObjectWrapper") != -1) 1579 return ""; 1580 var source = error.getSourceLine(); 1581 if (source) 1582 return cropString(source, 80); 1583 return ""; 1584 }, 1585 1586 getSourceLink: function(error) 1587 { 1588 var ext = error.category == "css" ? "css" : "js"; 1589 return error.lineNo ? new SourceLink(error.href, error.lineNo, ext) : null; 1590 }, 1591 1592 getSourceType: function(error) 1593 { 1594 // Errors occurring inside of HTML event handlers look like "foo.html (line 1)" 1595 // so let's try to skip those 1596 if (error.source) 1597 return "syntax"; 1598 else if (error.lineNo == 1 && getFileExtension(error.href) != "js") 1599 return "none"; 1600 else if (error.category == "css") 1601 return "show"; 1602 else if (!error.href || !error.lineNo) 1603 return "none"; 1604 else 1605 return "show"; 1606 }, 1607 1608 onToggleError: function(event) 1609 { 1610 var target = event.currentTarget; 1611 if (hasClass(event.target, "errorBreak")) 1612 { 1613 var panel = Firebug.getElementPanel(event.target); 1614 this.breakOnThisError(target.repObject, panel.context); 1615 } 1616 else if (hasClass(event.target, "errorSource")) 1617 { 1618 var panel = Firebug.getElementPanel(event.target); 1619 this.inspectObject(target.repObject, panel.context); 1620 } 1621 else if (hasClass(event.target, "errorTitle")) 1622 { 1623 var traceBox = target.childNodes[1]; 1624 toggleClass(target, "opened"); 1625 event.target.setAttribute('aria-expanded', hasClass(target, "opened")); 1626 if (hasClass(target, "opened")) 1627 { 1628 if (target.stackTrace) 1629 var node = FirebugReps.StackTrace.tag.append({object: target.stackTrace}, traceBox); 1630 if (Firebug.A11yModel.enabled) 1631 { 1632 var panel = Firebug.getElementPanel(event.target); 1633 dispatch([Firebug.A11yModel], "modifyLogRow", [panel , traceBox]); 1634 } 1635 } 1636 else 1637 clearNode(traceBox); 1638 } 1639 }, 1640 1641 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1642 1643 copyError: function(error) 1644 { 1645 var message = [ 1646 this.getMessage(error.message), 1647 error.href, 1648 "Line " + error.lineNo 1649 ]; 1650 copyToClipboard(message.join("\n")); 1651 }, 1652 1653 breakOnThisError: function(error, context) 1654 { 1655 1656 var sourceFile = context.sourceFileMap[normalizeURL(error.href)]; 1657 if (!sourceFile) 1658 { 1659 Firebug.Console.logFormatted(["reps.breakOnThisError has not source file for error.href: "+error.href, error], context, 'error', true); 1660 return; 1661 } 1662 1663 if (this.hasErrorBreak(error)) 1664 Firebug.Debugger.clearErrorBreakpoint(sourceFile, error.lineNo); 1665 else 1666 Firebug.Debugger.setErrorBreakpoint(sourceFile, error.lineNo); 1667 }, 1668 1669 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1670 1671 className: "errorMessage", 1672 inspectable: false, 1673 1674 supportsObject: function(object) 1675 { 1676 return object instanceof ErrorMessage; 1677 }, 1678 1679 inspectObject: function(error, context) 1680 { 1681 var sourceLink = this.getSourceLink(error); 1682 FirebugReps.SourceLink.inspectObject(sourceLink, context); 1683 }, 1684 1685 getContextMenuItems: function(error, target, context) 1686 { 1687 var breakOnThisError = this.hasErrorBreak(error); 1688 1689 var items = [ 1690 {label: "CopyError", command: bindFixed(this.copyError, this, error) } 1691 ]; 1692 1693 if (error.category == "css") 1694 { 1695 items.push( 1696 "-", 1697 {label: "BreakOnThisError", type: "checkbox", checked: breakOnThisError, 1698 command: bindFixed(this.breakOnThisError, this, error) }, 1699 1700 optionMenu("BreakOnAllErrors", "breakOnErrors") 1701 ); 1702 } 1703 1704 return items; 1705 } 1706 }); 1707 1708 // ************************************************************************************************ 1709 1710 this.Assert = domplate(Firebug.Rep, 1711 { 1712 tag: 1713 DIV( 1714 DIV({"class": "errorTitle"}), 1715 DIV({"class": "assertDescription"}) 1716 ), 1717 1718 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1719 1720 className: "assert", 1721 1722 inspectObject: function(error, context) 1723 { 1724 var sourceLink = this.getSourceLink(error); 1725 Firebug.chrome.select(sourceLink); 1726 }, 1727 1728 getContextMenuItems: function(error, target, context) 1729 { 1730 var breakOnThisError = this.hasErrorBreak(error); 1731 1732 return [ 1733 {label: "CopyError", command: bindFixed(this.copyError, this, error) }, 1734 "-", 1735 {label: "BreakOnThisError", type: "checkbox", checked: breakOnThisError, 1736 command: bindFixed(this.breakOnThisError, this, error) }, 1737 {label: "BreakOnAllErrors", type: "checkbox", checked: Firebug.breakOnErrors, 1738 command: bindFixed(this.breakOnAllErrors, this, error) } 1739 ]; 1740 } 1741 }); 1742 1743 // ************************************************************************************************ 1744 1745 this.SourceText = domplate(Firebug.Rep, 1746 { 1747 tag: 1748 DIV( 1749 FOR("line", "$object|lineIterator", 1750 DIV({"class": "sourceRow", role : "presentation"}, 1751 SPAN({"class": "sourceLine", role : "presentation"}, "$line.lineNo"), 1752 SPAN({"class": "sourceRowText", role : "presentation"}, "$line.text") 1753 ) 1754 ) 1755 ), 1756 1757 lineIterator: function(sourceText) 1758 { 1759 var maxLineNoChars = (sourceText.lines.length + "").length; 1760 var list = []; 1761 1762 for (var i = 0; i < sourceText.lines.length; ++i) 1763 { 1764 // Make sure all line numbers are the same width (with a fixed-width font) 1765 var lineNo = (i+1) + ""; 1766 while (lineNo.length < maxLineNoChars) 1767 lineNo = " " + lineNo; 1768 1769 list.push({lineNo: lineNo, text: sourceText.lines[i]}); 1770 } 1771 1772 return list; 1773 }, 1774 1775 getHTML: function(sourceText) 1776 { 1777 return getSourceLineRange(sourceText, 1, sourceText.lines.length); 1778 } 1779 }); 1780 1781 //************************************************************************************************ 1782 1783 this.nsIDOMHistory = domplate(Firebug.Rep, 1784 { 1785 tag:OBJECTBOX({onclick: "$showHistory"}, 1786 OBJECTLINK("$object|summarizeHistory") 1787 ), 1788 1789 className: "nsIDOMHistory", 1790 1791 summarizeHistory: function(history) 1792 { 1793 try 1794 { 1795 var items = history.length; 1796 return items + " history entries"; 1797 } 1798 catch(exc) 1799 { 1800 return "object does not support history (nsIDOMHistory)"; 1801 } 1802 }, 1803 1804 showHistory: function(history) 1805 { 1806 try 1807 { 1808 var items = history.length; // if this throws, then unsupported 1809 Firebug.chrome.select(history); 1810 } 1811 catch (exc) 1812 { 1813 } 1814 }, 1815 1816 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1817 1818 supportsObject: function(object, type) 1819 { 1820 return (object instanceof Ci.nsIDOMHistory); 1821 } 1822 }); 1823 1824 // ************************************************************************************************ 1825 1826 this.ApplicationCache = domplate(Firebug.Rep, 1827 { 1828 tag:OBJECTBOX({onclick: "$showApplicationCache"}, 1829 OBJECTLINK("$object|summarizeCache") 1830 ), 1831 1832 summarizeCache: function(applicationCache) 1833 { 1834 try 1835 { 1836 return applicationCache.length + " items in offline cache"; 1837 } 1838 catch(exc) 1839 { 1840 return "https://bugzilla.mozilla.org/show_bug.cgi?id=422264"; 1841 } 1842 }, 1843 1844 showApplicationCache: function(event) 1845 { 1846 openNewTab("https://bugzilla.mozilla.org/show_bug.cgi?id=422264"); 1847 }, 1848 1849 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1850 1851 className: "applicationCache", 1852 1853 supportsObject: function(object, type) 1854 { 1855 if (Ci.nsIDOMOfflineResourceList) 1856 return (object instanceof Ci.nsIDOMOfflineResourceList); 1857 } 1858 1859 }); 1860 1861 this.Storage = domplate(Firebug.Rep, 1862 { 1863 tag: OBJECTBOX({onclick: "$show"}, OBJECTLINK("$object|summarize")), 1864 1865 summarize: function(storage) 1866 { 1867 return storage.length +" items in Storage"; 1868 }, 1869 show: function(storage) 1870 { 1871 openNewTab("http://dev.w3.org/html5/webstorage/#storage-0"); 1872 }, 1873 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1874 1875 className: "Storage", 1876 1877 supportsObject: function(object, type) 1878 { 1879 return (object instanceof Storage); 1880 } 1881 1882 }); 1883 1884 // ************************************************************************************************ 1885 1886 Firebug.registerRep( 1887 this.nsIDOMHistory, // make this early to avoid exceptions 1888 this.Undefined, 1889 this.Null, 1890 this.Number, 1891 this.RegExp, 1892 this.String, 1893 this.Window, 1894 this.ApplicationCache, // must come before Arr (array) else exceptions. 1895 this.ErrorMessage, 1896 this.Element, 1897 this.TextNode, 1898 this.Document, 1899 this.StyleSheet, 1900 this.Event, 1901 this.SourceLink, 1902 this.SourceFile, 1903 this.StackTrace, 1904 this.StackFrame, 1905 this.jsdStackFrame, 1906 this.jsdScript, 1907 this.NetFile, 1908 this.Property, 1909 this.Except, 1910 this.XML, 1911 this.Arr 1912 ); 1913 1914 Firebug.setDefaultReps(this.Func, this.Obj); 1915 1916 }}); 1917 1918 // ************************************************************************************************ 1919 /* 1920 * The following is http://developer.yahoo.com/yui/license.txt and applies to only code labeled "Yahoo BSD Source" 1921 * in only this file reps.js. John J. Barton June 2007. 1922 * 1923 Software License Agreement (BSD License) 1924 1925 Copyright (c) 2006, Yahoo! Inc. 1926 All rights reserved. 1927 1928 Redistribution and use of this software in source and binary forms, with or without modification, are 1929 permitted provided that the following conditions are met: 1930 1931 * Redistributions of source code must retain the above 1932 copyright notice, this list of conditions and the 1933 following disclaimer. 1934 1935 * Redistributions in binary form must reproduce the above 1936 copyright notice, this list of conditions and the 1937 following disclaimer in the documentation and/or other 1938 materials provided with the distribution. 1939 1940 * Neither the name of Yahoo! Inc. nor the names of its 1941 contributors may be used to endorse or promote products 1942 derived from this software without specific prior 1943 written permission of Yahoo! Inc. 1944 1945 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 1946 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 1947 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 1948 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1949 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1950 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 1951 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 1952 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1953 * / 1954 */ 1955