1 /* See license.txt for terms of usage */ 2 3 define([ 4 "firebug/lib/object", 5 "firebug/firebug", 6 "firebug/chrome/reps", 7 "firebug/lib/xpcom", 8 "firebug/console/console", 9 "firebug/lib/css", 10 "firebug/chrome/window", 11 "firebug/lib/array", 12 "firebug/lib/string" 13 ], 14 function(Obj, Firebug, FirebugReps, Xpcom, Console, Css, Win, Arr, Str) { 15 16 // ********************************************************************************************* // 17 // Constants 18 19 const Cc = Components.classes; 20 const Ci = Components.interfaces; 21 const nsIScriptError = Ci.nsIScriptError; 22 const nsIConsoleMessage = Ci.nsIConsoleMessage; 23 24 const WARNING_FLAG = nsIScriptError.warningFlag; 25 26 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 27 28 const urlRe = new RegExp("([^:]*):(//)?([^/]*)"); 29 const reUncaught = /uncaught exception/; 30 // regular expessions for parsing uncaught exceptions 31 // see http://lxr.mozilla.org/mozilla/source/js/src/xpconnect/src/xpcexception.cpp#347 32 // and http://lxr.mozilla.org/mozilla/source/js/src/xpconnect/src/xpcstack.cpp#318 33 // and http://lxr.mozilla.org/mozilla/source/dom/src/base/nsDOMException.cpp#351 34 const reException1 = /^(?:uncaught exception: )?\[Exception... "(?!<no message>)([\s\S]+)" nsresult: "0x\S+ \((.+)\)" location: "(?:(?:JS|native) frame :: (?!<unknown filename>)(.+) :: .+ :: line (\d+)|<unknown>)" data: (?:yes|no)\]$/ 35 const reException2 = /^(?:uncaught exception: )?\[Exception... "(?!<no message>)([\s\S]+)" code: "\d+" nsresult: "0x\S+ \((.+)\)" location: "(?:(.+) Line: (\d+)|<unknown>)"\]$/ 36 const pointlessErrors = 37 { 38 "uncaught exception: Permission denied to call method Location.toString": 1, 39 "uncaught exception: Permission denied to get property Window.writeDebug": 1, 40 "uncaught exception: Permission denied to get property XULElement.accessKey": 1, 41 "this.docShell has no properties": 1, 42 "aDocShell.QueryInterface(Components.interfaces.nsIWebNavigation).currentURI has no properties": 1, 43 "Deprecated property window.title used. Please use document.title instead.": 1, 44 "Key event not available on GTK2:": 1 45 }; 46 47 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 48 49 Components.utils["import"]("resource://firebug/firebug-service.js"); 50 51 const consoleService = Xpcom.CCSV("@mozilla.org/consoleservice;1", "nsIConsoleService"); 52 const domWindowUtils = window.QueryInterface(Ci.nsIInterfaceRequestor) 53 .getInterface(Ci.nsIDOMWindowUtils); 54 55 // ********************************************************************************************* // 56 57 var Errors = Firebug.Errors = Obj.extend(Firebug.Module, 58 { 59 dispatchName: "errors", 60 61 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 62 // extends Module 63 64 shutdown: function() 65 { 66 // Make sure the error obsever is removed. 67 this.stopObserving(); 68 69 Firebug.Module.shutdown.apply(this, arguments); 70 }, 71 72 initContext: function(context) 73 { 74 this.clear(context); 75 }, 76 77 showContext: function(browser, context) 78 { 79 this.showCount(context ? context.errorCount : 0); 80 }, 81 82 // called for top window and frames. 83 unwatchWindow: function(context, win) 84 { 85 // If we ever get errors by window from Firefox we can cache by window. 86 this.clear(context); 87 }, 88 89 destroyContext: function(context, persistedState) 90 { 91 this.showCount(0); 92 93 if (FBTrace.DBG_ERRORLOG && FBTrace.DBG_CSS && "initTime" in this) 94 { 95 var deltaT = new Date().getTime() - this.initTime.getTime(); 96 97 FBTrace.sysout("errors.destroyContext sheets: " + Css.totalSheets + " rules: " + 98 Css.totalRules + " time: " + deltaT); 99 } 100 }, 101 102 updateOption: function(name, value) 103 { 104 this.checkEnabled(); 105 106 if (name == "showErrorCount") 107 this.toggleShowErrorCount(); 108 }, 109 110 toggleShowErrorCount: function() 111 { 112 this.showContext(null, Firebug.currentContext); 113 }, 114 115 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 116 117 clear: function(context) 118 { 119 // reset the UI counter 120 this.setCount(context, 0); 121 122 // clear the counts of dropped errors 123 delete context.droppedErrors; 124 }, 125 126 increaseCount: function(context) 127 { 128 this.setCount(context, context.errorCount + 1) 129 }, 130 131 setCount: function(context, count) 132 { 133 context.errorCount = count; 134 135 if (context == Firebug.currentContext) 136 this.showCount(context.errorCount); 137 }, 138 139 showCount: function(errorCount) 140 { 141 Firebug.StartButton.showCount(errorCount); 142 }, 143 144 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 145 // Called by Console 146 147 startObserving: function() 148 { 149 if (this.isObserving) 150 return; 151 152 if (FBTrace.DBG_ERRORLOG) 153 FBTrace.sysout("Errors.startObserving"); 154 155 if (consoleService) 156 consoleService.registerListener(this); 157 158 this.isObserving = true; 159 }, 160 161 stopObserving: function() 162 { 163 if (!this.isObserving) 164 return; 165 166 if (FBTrace.DBG_ERRORLOG) 167 FBTrace.sysout("Errors.stopObserving"); 168 169 if (consoleService) 170 consoleService.unregisterListener(this); 171 172 this.isObserving = false; 173 }, 174 175 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 176 // extends consoleListener 177 178 observe: function(object) 179 { 180 // Make sure the argument is an error object. 'instanceof' also 181 // queries the object so e.g. outerWindowID (nsIScriptError2) is available. 182 // nsIScriptError2 was merged with nsIScriptError, see 183 // https://bugzilla.mozilla.org/show_bug.cgi?id=711721 184 if (!(object instanceof Ci.nsIScriptError) || 185 (Ci.nsIScriptError2 && !(object instanceof Ci.nsIScriptError2))) 186 { 187 return; 188 } 189 190 try 191 { 192 if (window.closed) 193 this.stopObserving(); 194 195 if (typeof FBTrace == "undefined") 196 return; 197 198 if (!FBTrace) 199 return; 200 } 201 catch (exc) 202 { 203 return; 204 } 205 206 try 207 { 208 this.onConsoleLog(object); 209 } 210 catch (exc) 211 { 212 // Errors prior to console init will come out here, eg error message 213 // from Firefox startup jjb. 214 if (FBTrace.DBG_ERRORLOG) 215 { 216 FBTrace.sysout("errors.observe FAILS " + exc, exc); 217 FBTrace.sysout("errors.observe object " + object, object); 218 } 219 } 220 }, 221 222 onConsoleLog: function(object) 223 { 224 var ScriptError = object instanceof nsIScriptError; 225 var ConsoleMessage = object instanceof nsIConsoleMessage; 226 227 // This cannot be pulled in front of the instanceof 228 var isWarning = object && object.flags & WARNING_FLAG; 229 var CSSParser = object && object.category == "CSS Parser"; 230 var XPConnect = object && object.category && 231 object.category.split(' ').indexOf("XPConnect") != -1; 232 233 // Some categories say "content javascript" even if they come from chrome space. 234 var sourceName = (object && object.sourceName) ? object.sourceName : ""; 235 if (Str.hasPrefix(sourceName, "chrome:") || Str.hasPrefix(sourceName, "resource:")) 236 XPConnect = true; 237 238 if (FBTrace.DBG_ERRORLOG) 239 FBTrace.sysout("errors.observe; ScriptError: " + ScriptError + 240 ", XPConnect: " + XPConnect + ", sourceName: " + sourceName); 241 242 if (ScriptError && !XPConnect) // all branches should trace 'object' 243 { 244 if (FBTrace.DBG_ERRORLOG) 245 { 246 FBTrace.sysout("errors.observe nsIScriptError: " + object.errorMessage, 247 object); 248 } 249 250 // after instanceof 251 var context = this.getErrorContext(object); 252 if (context) 253 return this.logScriptError(context, object, isWarning); 254 255 if (FBTrace.DBG_ERRORLOG) 256 { 257 FBTrace.sysout("errors.observe nsIScriptError no context! " + 258 object.errorMessage, object); 259 } 260 } 261 else 262 { 263 if (Firebug.showChromeMessages) 264 { 265 if (ConsoleMessage) 266 { 267 if (FBTrace.DBG_ERRORLOG) 268 { 269 FBTrace.sysout("errors.observe nsIConsoleMessage: " + 270 object.message, object); 271 } 272 273 var context = this.getErrorContext(object); // after instanceof 274 if (!context) 275 context = Firebug.currentContext; 276 277 var msgId = lessTalkMoreAction(context, object, isWarning); 278 if (!msgId) 279 return; 280 281 if (context) 282 { 283 // Even chrome errors can be nicely formatted in the Console panel 284 this.logScriptError(context, object, isWarning); 285 //Console.log(object.message, context, "consoleMessage", 286 //FirebugReps.Text); 287 } 288 } 289 else if (object.message) 290 { 291 if (FBTrace.DBG_ERRORLOG) 292 FBTrace.sysout("errors.observe object.message:", object); 293 294 var context = this.getErrorContext(object); 295 296 if (!context) 297 context = Firebug.currentContext; 298 299 if (context) 300 { 301 // Even chrome errors can be nicely formatted in the Console panel 302 this.logScriptError(context, object, isWarning); 303 //Console.log(object.message, context, "consoleMessage", 304 //FirebugReps.Text); 305 } 306 else 307 { 308 FBTrace.sysout("errors.observe, no context for message", object); 309 } 310 } 311 else 312 { 313 FBTrace.sysout("errors.observe, no message in object", object); 314 } 315 } 316 else 317 { 318 if (FBTrace.DBG_ERRORLOG) 319 FBTrace.sysout("errors.observe showChromeMessages off, dropped:", object); 320 return; 321 } 322 } 323 324 if (FBTrace.DBG_ERRORLOG) 325 { 326 if (context) 327 { 328 if (context.window) 329 { 330 FBTrace.sysout((isWarning?"warning":"error") + " logged to " + 331 context.getName()); 332 } 333 else 334 { 335 FBTrace.sysout("errors.observe, context with no window, " + 336 (isWarning?"warning":"error")+" object:", object); 337 338 FBTrace.sysout("errors.observe, context with no window, context:", 339 context); 340 } 341 } 342 else 343 { 344 FBTrace.sysout("errors.observe, no context!"); 345 } 346 } 347 }, 348 349 logScriptError: function(context, object, isWarning) 350 { 351 if (!context) 352 return; 353 354 if (FBTrace.DBG_ERRORLOG) 355 { 356 FBTrace.sysout("errors.observe logScriptError " + 357 (Firebug.errorStackTrace ? "have " : "NO ") + 358 (Firebug.showStackTrace ? "show stack trace" : "do not show stack trace ") + 359 "errorStackTrace error object:", 360 {object: object, errorStackTrace: Firebug.errorStackTrace}); 361 } 362 363 var category = getBaseCategory(object.category); 364 var isJSError = category == "js" && !isWarning; 365 366 // the sourceLine will cause the source to be loaded. 367 var error = new FirebugReps.ErrorMessageObj(object.errorMessage, object.sourceName, 368 object.lineNumber, object.sourceLine, category, context, null, msgId); 369 370 // Display column info only if it isn't zero. 371 if (object.columnNumber > 0) 372 error.colNumber = object.columnNumber; 373 374 if (checkForException(context, object)) 375 { 376 context = getExceptionContext(context, object); 377 correctLineNumbersOnExceptions(object, error); 378 } 379 380 if (Firebug.errorStackTrace) 381 { 382 error.correctWithStackTrace(Firebug.errorStackTrace); 383 if (!Firebug.showStackTrace) 384 error.trace = null; 385 } 386 387 var msgId = lessTalkMoreAction(context, object, isWarning); 388 if (!msgId) 389 return null; 390 391 // clear global: either we copied it or we don't use it. 392 Firebug.errorStackTrace = null; 393 394 if (!isWarning) 395 this.increaseCount(context); 396 397 var className = isWarning ? "warningMessage" : "errorMessage"; 398 399 if (FBTrace.DBG_ERRORLOG) 400 FBTrace.sysout("errors.observe delayed log to " + context.getName()); 401 402 // report later to avoid loading sourceS 403 context.throttle(this.delayedLogging, this, [msgId, context, error, context, className, 404 false, true], true); 405 }, 406 407 delayedLogging: function() 408 { 409 var args = Arr.cloneArray(arguments); 410 var msgId = args.shift(); 411 var context = args.shift(); 412 var row = Console.log.apply(Console, args); 413 return row; 414 }, 415 416 getErrorContext: function(object) 417 { 418 var url = object.sourceName; 419 420 // If window is not associated bail out to avoid reporting errors that are not 421 // page related (issue 4991). 422 if (!url && !object.outerWindowID) 423 { 424 if (FBTrace.DBG_ERRORLOG) 425 FBTrace.sysout("errors.getErrorContext; No URL & no outer-window. " + 426 "url: " + url + ", outerWindowID: " + object.outerWindowID, object); 427 return null; 428 } 429 430 // eg some XPCOM messages 431 // xxxHonza: this could cause appearing error messages in wrong tabs. 432 // Is this still necessary? 433 if (!url) 434 return Firebug.currentContext; 435 436 if (url && url.indexOf("://chromebug/") > 0) 437 return Firebug.currentContext; // no context for self 438 439 // Correct the error routing in the case that the new window id will work (R10860). 440 // Don't pass the current context (issue 4504) 441 var errorContext = getExceptionContext(null, object); 442 if (errorContext) 443 return errorContext; 444 445 var errorContext = null; 446 Firebug.connection.eachContext( 447 function findContextByURL(context) 448 { 449 if (FBTrace.DBG_ERRORLOG && FBTrace.DBG_CSS) 450 FBTrace.sysout("findContextByURL " + context.getName()); 451 452 if (!context.window || !context.getWindowLocation()) 453 return false; 454 455 // If the error's parent window is available, check if it 456 // corresponds to the context.window. If not bail out to avoid 457 // error reporting in a wrong window. 458 var errorWindow = getErrorWindow(object); 459 if (errorWindow && errorWindow != context.window) 460 return false; 461 462 if (FBTrace.DBG_ERRORLOG) 463 { 464 FBTrace.sysout("findContextByURL seeking " + url + " in " + 465 (context.loaded ? "loaded" : "not loaded") + 466 " window location: " + context.getWindowLocation().toString()); 467 } 468 469 if (context.getWindowLocation().toString() == url) 470 { 471 if (FBTrace.DBG_ERRORLOG && FBTrace.DBG_CSS) 472 FBTrace.sysout("findContextByURL found match to context window location"); 473 474 return errorContext = context; 475 } 476 else 477 { 478 if (context.sourceFileMap && context.sourceFileMap[url]) 479 { 480 if (FBTrace.DBG_ERRORLOG && FBTrace.DBG_CSS) 481 FBTrace.sysout("findContextByURL found match in sourceFileMap"); 482 return errorContext = context; 483 } 484 } 485 486 if (context.loaded) 487 { 488 if (Css.getStyleSheetByHref(url, context)) 489 { 490 if (FBTrace.DBG_ERRORLOG && FBTrace.DBG_CSS) 491 { 492 FBTrace.sysout("findContextByURL found match to in loaded " + 493 "styleSheetMap"); 494 } 495 496 return errorContext = context; 497 } 498 else 499 { 500 return false; 501 } 502 } 503 else // then new stylesheets are still coming in. 504 { 505 if (context.getCompilationUnit(url)) 506 { 507 if (FBTrace.DBG_EERRORLOG) 508 FBTrace.sysout("findContextByURL found match in compilationUnits"); 509 510 return errorContext = context; 511 } 512 513 if (Css.getStyleSheetByHref(url, context)) 514 { 515 if (FBTrace.DBG_ERRORLOG && FBTrace.DBG_CSS) 516 { 517 FBTrace.sysout("findContextByURL found match to in non-loaded " + 518 "styleSheetMap"); 519 } 520 521 // but we already have this one. 522 errorContext = context; 523 } 524 525 // clear the cache for next time. 526 delete context.styleSheetMap; 527 } 528 }); 529 530 if (FBTrace.DBG_ERRORLOG && FBTrace.DBG_CSS && "initTime" in this) 531 { 532 var deltaT = new Date().getTime() - this.initTime.getTime(); 533 FBTrace.sysout("errors.getErrorContext sheets: " + Css.totalSheets + 534 " rules: " + Css.totalRules + " time: " + deltaT); 535 } 536 537 if (!errorContext) 538 { 539 if (FBTrace.DBG_ERRORLOG) 540 FBTrace.sysout("errors.getErrorContext no context from error filename:"+ 541 url, object); 542 } 543 544 // Use nsIScriptError/nsIScriptError2 to compare the parent window 545 // guessed by Firebug with the window found through outerWindowID 546 if (FBTrace.DBG_ERRORLOG) 547 { 548 var win1 = getErrorWindow(object); 549 var win2 = errorContext ? errorContext.window : null; 550 551 win1 = Win.getRootWindow(win1); 552 win2 = Win.getRootWindow(win2); 553 554 var id1 = Win.getWindowProxyIdForWindow(win1); 555 var id2 = Win.getWindowProxyIdForWindow(win2); 556 557 if (win1 && id1 != id2 && errorContext) 558 { 559 var win1Name = Win.safeGetWindowLocation(win1); 560 var win2Name = Win.safeGetWindowLocation(win2); 561 var moreInfo = {object: object, fromError2: win1, fromFirebug: win2}; 562 563 FBTrace.sysout("errors.getErrorContext; ERROR wrong parent window? " + 564 win1Name + " !== " + win2Name, moreInfo); 565 } 566 } 567 568 // we looked everywhere... 569 return errorContext; 570 }, 571 572 toggleWatchForErrors: function(watchForErrors) 573 { 574 var previous = this.watchForErrors; 575 this.watchForErrors = watchForErrors; 576 this.checkEnabled(); 577 578 return (previous !== this.watchForErrors); 579 }, 580 581 checkEnabled: function() 582 { 583 var beEnabled = this.watchForErrors && this.mustBeEnabled(); 584 if (beEnabled) 585 { 586 if (!this.isObserving) 587 this.startObserving(); 588 // else we must be and we are observing 589 } 590 else 591 { 592 if (this.isObserving) 593 this.stopObserving(); 594 // else we must not be and we are not 595 } 596 597 if (FBTrace.DBG_ERRORLOG) 598 FBTrace.sysout("errors.checkEnabled mustBeEnabled: " + this.mustBeEnabled() + 599 " Console.isAlwaysEnabled " + Console.isAlwaysEnabled() + 600 " isObserving:" + this.isObserving); 601 }, 602 603 mustBeEnabled: function() 604 { 605 var optionMap = 606 { 607 showJSErrors:1, 608 showJSWarnings:1, 609 showCSSErrors:1, 610 showXMLErrors: 1, 611 showChromeErrors: 1, 612 showChromeMessages: 1, 613 showXMLHttpRequests: 1, 614 showStackTrace: 1 615 }; 616 617 for (var p in optionMap) 618 { 619 if (Firebug[p]) 620 return true; 621 } 622 623 return false; 624 }, 625 626 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 627 628 reparseXPC: function(errorMessage, context) 629 { 630 var reXPCError = /JavaScript Error:\s*\"([^\"]*)\"/; 631 var reFile = /file:\s*\"([^\"]*)\"/; 632 var reLine = /line:\s*(\d*)/; 633 var m = reXPCError.exec(errorMessage); 634 if (!m) 635 return null; 636 637 var msg = m[1]; 638 var sourceFile = null; 639 m = reFile.exec(errorMessage); 640 if (m) 641 sourceFile = m[1]; 642 643 var sourceLineNo = 0; 644 m = reLine.exec(errorMessage); 645 if (m) 646 sourceLineNo = m[1]; 647 648 var sourceLine = null; 649 if (sourceFile && sourceLineNo && sourceLineNo != 0) 650 { 651 if (context.sourceCache) 652 { 653 sourceLine = context.sourceCache.getLine(sourceFile, sourceLineNo); 654 } 655 else if (FBTrace.DBG_ERRORS) 656 { 657 FBTrace.sysout("errors.reparseXPC; ERROR, NULL context.sourceCache, " + 658 sourceFile + ", " + sourceLineNo); 659 } 660 } 661 662 var error = new FirebugReps.ErrorMessageObj(msg, sourceFile, 663 sourceLineNo, sourceLine, "error", context, null); 664 return error; 665 } 666 }); 667 668 // ********************************************************************************************* // 669 // Local Helpers 670 671 const categoryMap = 672 { 673 "javascript": "js", 674 "JavaScript": "js", 675 "DOM": "js", 676 "Events": "js", 677 "CSS": "css", 678 "HTML": "xml", 679 "XML": "xml", 680 "malformed-xml": "xml" 681 }; 682 683 function getBaseCategory(categories) 684 { 685 var categoryList = categories.split(" "); 686 for (var i=0; i<categoryList.length; ++i) 687 { 688 var category = categoryList[i]; 689 if (categoryMap.hasOwnProperty(category)) 690 return categoryMap[category]; 691 } 692 } 693 694 function whyNotShown(url, categoryList, isWarning) 695 { 696 var m = urlRe.exec(url); 697 var errorScheme = m ? m[1] : ""; 698 if (errorScheme == "javascript") 699 return null; 700 701 var isChrome = false; 702 703 if (!categoryList) 704 { 705 return Firebug.showChromeErrors ? null : 706 "no category, assume chrome, showChromeErrors false"; 707 } 708 709 var categories = categoryList.split(" "); 710 for (var i=0; i<categories.length; ++i) 711 { 712 var category = categories[i]; 713 if (category == "CSS" && !Firebug.showCSSErrors) 714 { 715 return "showCSSErrors"; 716 } 717 else if ((category == "HTML" || category == "XML" || category == "malformed-xml" ) && 718 !Firebug.showXMLErrors) 719 { 720 return "showXMLErrors"; 721 } 722 else if ((category == "javascript" || category == "JavaScript" || category == "DOM") 723 && !isWarning && !Firebug.showJSErrors) 724 { 725 return "showJSErrors"; 726 } 727 else if ((category == "javascript" || category == "JavaScript" || category == "DOM") 728 && isWarning && !Firebug.showJSWarnings) 729 { 730 return "showJSWarnings"; 731 } 732 else if (errorScheme == "chrome" || category == "XUL" || category == "chrome" || 733 category == "XBL" || category == "component") 734 { 735 isChrome = true; 736 } 737 } 738 739 if (isChrome && !Firebug.showChromeErrors) 740 return "showChromeErrors"; 741 742 return null; 743 } 744 745 function lessTalkMoreAction(context, object, isWarning) 746 { 747 if (!context) 748 { 749 if (FBTrace.DBG_ERRORLOG) 750 FBTrace.sysout("errors.observe dropping " + object.category + " no context"); 751 return false; 752 } 753 754 var enabled = Console.isAlwaysEnabled(); 755 if (!enabled) 756 return null; 757 758 var why = whyNotShown(object.sourceName, object.category, isWarning); 759 if (why) 760 { 761 if (FBTrace.DBG_ERRORLOG) 762 FBTrace.sysout("errors.observe dropping " + object.category + " because: " + why); 763 764 context.droppedErrors = context.droppedErrors || {}; 765 766 if (!context.droppedErrors[object.category]) 767 context.droppedErrors[object.category] = 1; 768 else 769 context.droppedErrors[object.category] += 1; 770 771 return null; 772 } 773 774 // nsIScriptError 775 var incoming_message = object.errorMessage; 776 777 // nsIConsoleMessage 778 if (!incoming_message) 779 incoming_message = object.message; 780 781 if (Firebug.suppressPointlessErrors) 782 { 783 for (var msg in pointlessErrors) 784 { 785 if (msg.charAt(0) == incoming_message.charAt(0)) 786 { 787 if (Str.hasPrefix(incoming_message, msg)) 788 { 789 if (FBTrace.DBG_ERRORLOG) 790 FBTrace.sysout("errors.observe dropping pointlessError: " + msg); 791 return null; 792 } 793 } 794 } 795 } 796 797 var msgId = [incoming_message, object.sourceName, object.lineNumber].join("/"); 798 return msgId; 799 } 800 801 function checkForException(context, object) 802 { 803 if (object.flags & object.exceptionFlag) 804 { 805 if (FBTrace.DBG_ERRORLOG) 806 FBTrace.sysout("errors.observe is exception"); 807 808 if (context.thrownStackTrace) 809 { 810 Firebug.errorStackTrace = context.thrownStackTrace; 811 812 if (FBTrace.DBG_ERRORLOG) 813 FBTrace.sysout("errors.observe trace.frames", context.thrownStackTrace.frames); 814 815 delete context.thrownStackTrace; 816 } 817 else 818 { 819 if (FBTrace.DBG_ERRORLOG) 820 FBTrace.sysout("errors.observe NO context.thrownStackTrace"); 821 } 822 return true; 823 } 824 825 delete context.thrownStackTrace; 826 return false; 827 } 828 829 /** 830 * Returns a parent window (outer window) for given error object (an object 831 * that is passed into a consoleListener). 832 * This method should be the primary way how to find the parent window for any 833 * error object. 834 * 835 * @param {Object} object Error object (implementing nsIScriptError2 or nsIScriptError) 836 */ 837 function getErrorWindow(object) 838 { 839 try 840 { 841 // nsIScriptError2 is merged into nsIScriptError in Firefox 12 (bug 842 // 711721), so check for the one that is relevant. 843 var why; 844 if (object instanceof (Ci["nsIScriptError2"] || Ci["nsIScriptError"])) 845 { 846 if (object.outerWindowID) 847 { 848 var win = domWindowUtils.getOuterWindowWithId(object.outerWindowID); 849 if (win) 850 return win; 851 else 852 why = "no getOuterWindowWithId"; 853 } 854 else 855 { 856 why = "no outerWindowID"; 857 } 858 } 859 else 860 { 861 why = "not an nsIScriptError"; 862 } 863 864 if (FBTrace.DBG_ERRORS) 865 FBTrace.sysout("errors.getErrorWindow failed " + why, object); 866 } 867 catch (err) 868 { 869 if (FBTrace.DBG_ERRORS) 870 FBTrace.sysout("errors.getErrorWindow; EXCEPTION" + err, err); 871 } 872 873 return null; 874 } 875 876 function getExceptionContext(context, object) 877 { 878 var errorWin = getErrorWindow(object); 879 if (errorWin) 880 { 881 var errorContext = Firebug.connection.getContextByWindow(errorWin); 882 if (FBTrace.DBG_ERRORLOG) 883 { 884 FBTrace.sysout("errors.observe exception context: " + 885 (errorContext ? errorContext.getName() : "none") + " errorWin: " + 886 Win.safeGetWindowLocation(errorWin)); 887 } 888 889 if (errorContext) 890 return errorContext; 891 } 892 893 return context; 894 } 895 896 function correctLineNumbersOnExceptions(object, error) 897 { 898 var m = reException1.exec(object.errorMessage) || reException2.exec(object.errorMessage); 899 if (m) 900 { 901 var exception = m[1]; 902 if (exception) 903 error.message = exception; 904 var sourceName = m[3]; 905 var lineNumber = parseInt(m[4]); 906 907 error.correctSourcePoint(sourceName, lineNumber); 908 909 if (FBTrace.DBG_ERRORLOG) 910 { 911 FBTrace.sysout("errors.correctLineNumbersOnExceptions corrected message " + 912 "with sourceName: "+ sourceName + "@" + lineNumber); 913 } 914 } 915 } 916 917 // ********************************************************************************************* // 918 // Registration 919 920 Firebug.registerModule(Errors); 921 922 return Firebug.Errors; 923 924 // ********************************************************************************************* // 925 }); 926