index.js 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. const IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[a-z]:[/\\]/i;
  2. const LINE_RE = /^\s+at (?:(?<function>[^)]+) \()?(?<source>[^)]+)\)?$/u;
  3. const SOURCE_RE = /^(?<source>.+):(?<line>\d+):(?<column>\d+)$/u;
  4. function captureRawStackTrace() {
  5. if (!Error.captureStackTrace) {
  6. return;
  7. }
  8. const stack = new Error();
  9. Error.captureStackTrace(stack);
  10. return stack.stack;
  11. }
  12. function captureStackTrace() {
  13. const stack = captureRawStackTrace();
  14. return stack ? parseRawStackTrace(stack) : [];
  15. }
  16. function parseRawStackTrace(stacktrace) {
  17. const trace = [];
  18. for (const line of stacktrace.split("\n")) {
  19. const parsed = LINE_RE.exec(line)?.groups;
  20. if (!parsed) {
  21. continue;
  22. }
  23. if (!parsed.source) {
  24. continue;
  25. }
  26. const parsedSource = SOURCE_RE.exec(parsed.source)?.groups;
  27. if (parsedSource) {
  28. Object.assign(parsed, parsedSource);
  29. }
  30. if (IS_ABSOLUTE_RE.test(parsed.source)) {
  31. parsed.source = `file://${parsed.source}`;
  32. }
  33. if (parsed.source === import.meta.url) {
  34. continue;
  35. }
  36. for (const key of ["line", "column"]) {
  37. if (parsed[key]) {
  38. parsed[key] = Number(parsed[key]);
  39. }
  40. }
  41. trace.push(parsed);
  42. }
  43. return trace;
  44. }
  45. export { captureRawStackTrace, captureStackTrace, parseRawStackTrace };