stackframe.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. (function(root, factory) {
  2. 'use strict';
  3. // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, Rhino, and browsers.
  4. /* istanbul ignore next */
  5. if (typeof define === 'function' && define.amd) {
  6. define('stackframe', [], factory);
  7. } else if (typeof exports === 'object') {
  8. module.exports = factory();
  9. } else {
  10. root.StackFrame = factory();
  11. }
  12. }(this, function() {
  13. 'use strict';
  14. function _isNumber(n) {
  15. return !isNaN(parseFloat(n)) && isFinite(n);
  16. }
  17. function _capitalize(str) {
  18. return str.charAt(0).toUpperCase() + str.substring(1);
  19. }
  20. function _getter(p) {
  21. return function() {
  22. return this[p];
  23. };
  24. }
  25. var booleanProps = ['isConstructor', 'isEval', 'isNative', 'isToplevel'];
  26. var numericProps = ['columnNumber', 'lineNumber'];
  27. var stringProps = ['fileName', 'functionName', 'source'];
  28. var arrayProps = ['args'];
  29. var objectProps = ['evalOrigin'];
  30. var props = booleanProps.concat(numericProps, stringProps, arrayProps, objectProps);
  31. function StackFrame(obj) {
  32. if (!obj) return;
  33. for (var i = 0; i < props.length; i++) {
  34. if (obj[props[i]] !== undefined) {
  35. this['set' + _capitalize(props[i])](obj[props[i]]);
  36. }
  37. }
  38. }
  39. StackFrame.prototype = {
  40. getArgs: function() {
  41. return this.args;
  42. },
  43. setArgs: function(v) {
  44. if (Object.prototype.toString.call(v) !== '[object Array]') {
  45. throw new TypeError('Args must be an Array');
  46. }
  47. this.args = v;
  48. },
  49. getEvalOrigin: function() {
  50. return this.evalOrigin;
  51. },
  52. setEvalOrigin: function(v) {
  53. if (v instanceof StackFrame) {
  54. this.evalOrigin = v;
  55. } else if (v instanceof Object) {
  56. this.evalOrigin = new StackFrame(v);
  57. } else {
  58. throw new TypeError('Eval Origin must be an Object or StackFrame');
  59. }
  60. },
  61. toString: function() {
  62. var fileName = this.getFileName() || '';
  63. var lineNumber = this.getLineNumber() || '';
  64. var columnNumber = this.getColumnNumber() || '';
  65. var functionName = this.getFunctionName() || '';
  66. if (this.getIsEval()) {
  67. if (fileName) {
  68. return '[eval] (' + fileName + ':' + lineNumber + ':' + columnNumber + ')';
  69. }
  70. return '[eval]:' + lineNumber + ':' + columnNumber;
  71. }
  72. if (functionName) {
  73. return functionName + ' (' + fileName + ':' + lineNumber + ':' + columnNumber + ')';
  74. }
  75. return fileName + ':' + lineNumber + ':' + columnNumber;
  76. }
  77. };
  78. StackFrame.fromString = function StackFrame$$fromString(str) {
  79. var argsStartIndex = str.indexOf('(');
  80. var argsEndIndex = str.lastIndexOf(')');
  81. var functionName = str.substring(0, argsStartIndex);
  82. var args = str.substring(argsStartIndex + 1, argsEndIndex).split(',');
  83. var locationString = str.substring(argsEndIndex + 1);
  84. if (locationString.indexOf('@') === 0) {
  85. var parts = /@(.+?)(?::(\d+))?(?::(\d+))?$/.exec(locationString, '');
  86. var fileName = parts[1];
  87. var lineNumber = parts[2];
  88. var columnNumber = parts[3];
  89. }
  90. return new StackFrame({
  91. functionName: functionName,
  92. args: args || undefined,
  93. fileName: fileName,
  94. lineNumber: lineNumber || undefined,
  95. columnNumber: columnNumber || undefined
  96. });
  97. };
  98. for (var i = 0; i < booleanProps.length; i++) {
  99. StackFrame.prototype['get' + _capitalize(booleanProps[i])] = _getter(booleanProps[i]);
  100. StackFrame.prototype['set' + _capitalize(booleanProps[i])] = (function(p) {
  101. return function(v) {
  102. this[p] = Boolean(v);
  103. };
  104. })(booleanProps[i]);
  105. }
  106. for (var j = 0; j < numericProps.length; j++) {
  107. StackFrame.prototype['get' + _capitalize(numericProps[j])] = _getter(numericProps[j]);
  108. StackFrame.prototype['set' + _capitalize(numericProps[j])] = (function(p) {
  109. return function(v) {
  110. if (!_isNumber(v)) {
  111. throw new TypeError(p + ' must be a Number');
  112. }
  113. this[p] = Number(v);
  114. };
  115. })(numericProps[j]);
  116. }
  117. for (var k = 0; k < stringProps.length; k++) {
  118. StackFrame.prototype['get' + _capitalize(stringProps[k])] = _getter(stringProps[k]);
  119. StackFrame.prototype['set' + _capitalize(stringProps[k])] = (function(p) {
  120. return function(v) {
  121. this[p] = String(v);
  122. };
  123. })(stringProps[k]);
  124. }
  125. return StackFrame;
  126. }));