lite.cjs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. 'use strict';
  2. const FIREFOX_SAFARI_STACK_REGEXP = /(^|@)\S+:\d+/;
  3. const CHROME_IE_STACK_REGEXP = /^\s*at .*(\S+:\d+|\(native\))/m;
  4. const SAFARI_NATIVE_CODE_REGEXP = /^(eval@)?(\[native code\])?$/;
  5. function parse(error, options) {
  6. if (typeof error.stacktrace !== "undefined" || typeof error["opera#sourceloc"] !== "undefined")
  7. return parseOpera(error, options);
  8. else if (error.stack && error.stack.match(CHROME_IE_STACK_REGEXP))
  9. return parseV8OrIE(error, options);
  10. else if (error.stack)
  11. return parseFFOrSafari(error, options);
  12. else if (options?.allowEmpty)
  13. return [];
  14. else
  15. throw new Error("Cannot parse given Error object");
  16. }
  17. function parseStack(stackString, options) {
  18. if (stackString.match(CHROME_IE_STACK_REGEXP))
  19. return parseV8OrIeString(stackString, options);
  20. else
  21. return parseFFOrSafariString(stackString, options);
  22. }
  23. function extractLocation(urlLike) {
  24. if (!urlLike.includes(":"))
  25. return [urlLike, void 0, void 0];
  26. const regExp = /(.+?)(?::(\d+))?(?::(\d+))?$/;
  27. const parts = regExp.exec(urlLike.replace(/[()]/g, ""));
  28. return [parts[1], parts[2] || void 0, parts[3] || void 0];
  29. }
  30. function applySlice(lines, options) {
  31. if (options && options.slice != null) {
  32. if (Array.isArray(options.slice))
  33. return lines.slice(options.slice[0], options.slice[1]);
  34. return lines.slice(0, options.slice);
  35. }
  36. return lines;
  37. }
  38. function parseV8OrIE(error, options) {
  39. return parseV8OrIeString(error.stack, options);
  40. }
  41. function parseV8OrIeString(stack, options) {
  42. const filtered = applySlice(
  43. stack.split("\n").filter((line) => {
  44. return !!line.match(CHROME_IE_STACK_REGEXP);
  45. }),
  46. options
  47. );
  48. return filtered.map((line) => {
  49. if (line.includes("(eval ")) {
  50. line = line.replace(/eval code/g, "eval").replace(/(\(eval at [^()]*)|(,.*$)/g, "");
  51. }
  52. let sanitizedLine = line.replace(/^\s+/, "").replace(/\(eval code/g, "(").replace(/^.*?\s+/, "");
  53. const location = sanitizedLine.match(/ (\(.+\)$)/);
  54. sanitizedLine = location ? sanitizedLine.replace(location[0], "") : sanitizedLine;
  55. const locationParts = extractLocation(location ? location[1] : sanitizedLine);
  56. const functionName = location && sanitizedLine || void 0;
  57. const fileName = ["eval", "<anonymous>"].includes(locationParts[0]) ? void 0 : locationParts[0];
  58. return {
  59. function: functionName,
  60. file: fileName,
  61. line: locationParts[1] ? +locationParts[1] : void 0,
  62. col: locationParts[2] ? +locationParts[2] : void 0,
  63. raw: line
  64. };
  65. });
  66. }
  67. function parseFFOrSafari(error, options) {
  68. return parseFFOrSafariString(error.stack, options);
  69. }
  70. function parseFFOrSafariString(stack, options) {
  71. const filtered = applySlice(
  72. stack.split("\n").filter((line) => {
  73. return !line.match(SAFARI_NATIVE_CODE_REGEXP);
  74. }),
  75. options
  76. );
  77. return filtered.map((line) => {
  78. if (line.includes(" > eval"))
  79. line = line.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g, ":$1");
  80. if (!line.includes("@") && !line.includes(":")) {
  81. return {
  82. function: line
  83. };
  84. } else {
  85. const functionNameRegex = /(([^\n\r"\u2028\u2029]*".[^\n\r"\u2028\u2029]*"[^\n\r@\u2028\u2029]*(?:@[^\n\r"\u2028\u2029]*"[^\n\r@\u2028\u2029]*)*(?:[\n\r\u2028\u2029][^@]*)?)?[^@]*)@/;
  86. const matches = line.match(functionNameRegex);
  87. const functionName = matches && matches[1] ? matches[1] : void 0;
  88. const locationParts = extractLocation(line.replace(functionNameRegex, ""));
  89. return {
  90. function: functionName,
  91. file: locationParts[0],
  92. line: locationParts[1] ? +locationParts[1] : void 0,
  93. col: locationParts[2] ? +locationParts[2] : void 0,
  94. raw: line
  95. };
  96. }
  97. });
  98. }
  99. function parseOpera(e, options) {
  100. if (!e.stacktrace || e.message.includes("\n") && e.message.split("\n").length > e.stacktrace.split("\n").length)
  101. return parseOpera9(e);
  102. else if (!e.stack)
  103. return parseOpera10(e);
  104. else
  105. return parseOpera11(e, options);
  106. }
  107. function parseOpera9(e, options) {
  108. const lineRE = /Line (\d+).*script (?:in )?(\S+)/i;
  109. const lines = e.message.split("\n");
  110. const result = [];
  111. for (let i = 2, len = lines.length; i < len; i += 2) {
  112. const match = lineRE.exec(lines[i]);
  113. if (match) {
  114. result.push({
  115. file: match[2],
  116. line: +match[1],
  117. raw: lines[i]
  118. });
  119. }
  120. }
  121. return applySlice(result, options);
  122. }
  123. function parseOpera10(e, options) {
  124. const lineRE = /Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i;
  125. const lines = e.stacktrace.split("\n");
  126. const result = [];
  127. for (let i = 0, len = lines.length; i < len; i += 2) {
  128. const match = lineRE.exec(lines[i]);
  129. if (match) {
  130. result.push({
  131. function: match[3] || void 0,
  132. file: match[2],
  133. line: match[1] ? +match[1] : void 0,
  134. raw: lines[i]
  135. });
  136. }
  137. }
  138. return applySlice(result, options);
  139. }
  140. function parseOpera11(error, options) {
  141. const filtered = applySlice(
  142. // @ts-expect-error missing stack property
  143. error.stack.split("\n").filter((line) => {
  144. return !!line.match(FIREFOX_SAFARI_STACK_REGEXP) && !line.match(/^Error created at/);
  145. }),
  146. options
  147. );
  148. return filtered.map((line) => {
  149. const tokens = line.split("@");
  150. const locationParts = extractLocation(tokens.pop());
  151. const functionCall = tokens.shift() || "";
  152. const functionName = functionCall.replace(/<anonymous function(: (\w+))?>/, "$2").replace(/\([^)]*\)/g, "") || void 0;
  153. let argsRaw;
  154. if (functionCall.match(/\(([^)]*)\)/))
  155. argsRaw = functionCall.replace(/^[^(]+\(([^)]*)\)$/, "$1");
  156. const args = argsRaw === void 0 || argsRaw === "[arguments not available]" ? void 0 : argsRaw.split(",");
  157. return {
  158. function: functionName,
  159. args,
  160. file: locationParts[0],
  161. line: locationParts[1] ? +locationParts[1] : void 0,
  162. col: locationParts[2] ? +locationParts[2] : void 0,
  163. raw: line
  164. };
  165. });
  166. }
  167. exports.extractLocation = extractLocation;
  168. exports.parse = parse;
  169. exports.parseFFOrSafari = parseFFOrSafari;
  170. exports.parseFFOrSafariString = parseFFOrSafariString;
  171. exports.parseOpera = parseOpera;
  172. exports.parseOpera10 = parseOpera10;
  173. exports.parseOpera11 = parseOpera11;
  174. exports.parseOpera9 = parseOpera9;
  175. exports.parseStack = parseStack;
  176. exports.parseV8OrIE = parseV8OrIE;
  177. exports.parseV8OrIeString = parseV8OrIeString;