traceback.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. "use strict";
  5. module.metadata = {
  6. "stability": "experimental"
  7. };
  8. const { Cc, Ci, components } = require("chrome");
  9. const { parseStack, sourceURI } = require("toolkit/loader");
  10. const { readURISync } = require("../net/url");
  11. exports.sourceURI = sourceURI
  12. function safeGetFileLine(path, line) {
  13. try {
  14. var scheme = require("../url").URL(path).scheme;
  15. // TODO: There should be an easier, more accurate way to figure out
  16. // what's the case here.
  17. if (!(scheme == "http" || scheme == "https"))
  18. return readURISync(path).split("\n")[line - 1];
  19. } catch (e) {}
  20. return null;
  21. }
  22. function nsIStackFramesToJSON(frame) {
  23. var stack = [];
  24. while (frame) {
  25. if (frame.filename) {
  26. stack.unshift({
  27. fileName: sourceURI(frame.filename),
  28. lineNumber: frame.lineNumber,
  29. name: frame.name
  30. });
  31. }
  32. frame = frame.caller;
  33. }
  34. return stack;
  35. };
  36. var fromException = exports.fromException = function fromException(e) {
  37. if (e instanceof Ci.nsIException)
  38. return nsIStackFramesToJSON(e.location);
  39. if (e.stack && e.stack.length)
  40. return parseStack(e.stack);
  41. if (e.fileName && typeof(e.lineNumber == "number"))
  42. return [{fileName: sourceURI(e.fileName),
  43. lineNumber: e.lineNumber,
  44. name: null}];
  45. return [];
  46. };
  47. var get = exports.get = function get() {
  48. return nsIStackFramesToJSON(components.stack.caller);
  49. };
  50. var format = exports.format = function format(tbOrException) {
  51. if (tbOrException === undefined) {
  52. tbOrException = get();
  53. tbOrException.pop();
  54. }
  55. var tb;
  56. if (typeof(tbOrException) == "object" &&
  57. tbOrException.constructor.name == "Array")
  58. tb = tbOrException;
  59. else
  60. tb = fromException(tbOrException);
  61. var lines = ["Traceback (most recent call last):"];
  62. tb.forEach(
  63. function(frame) {
  64. if (!(frame.fileName || frame.lineNumber || frame.name))
  65. return;
  66. lines.push(' File "' + frame.fileName + '", line ' +
  67. frame.lineNumber + ', in ' + frame.name);
  68. var sourceLine = safeGetFileLine(frame.fileName, frame.lineNumber);
  69. if (sourceLine)
  70. lines.push(' ' + sourceLine.trim());
  71. });
  72. return lines.join("\n");
  73. };