char/avril

(wip) why'd you have to go and make things so complicaaaaated?

git clone https://git.t4t.associates/char/avril

Charlotte Somcore: use current error messages in stack tracese0f52fe

main
2.2 KiB68 linesraw
1import {
2  Error,
3  ErrorGetStack,
4  ObjectDefineProperty,
5  ObjectGetPrototypeOf,
6  ReflectApply,
7  String,
8  StringPrototypeSlice,
9  uncurryThis,
10} from "ext:core/primordials";
11import { mapSourceLocation } from "ext:core/source_map";
12const lastIndexOf = uncurryThis(String.prototype.lastIndexOf);
13
14ObjectDefineProperty(Error, "prepareStackTrace", {
15  value: (_, frames) => frames,
16  writable: true,
17  configurable: true,
18});
19const prototype = ObjectGetPrototypeOf(ErrorGetStack(new Error())[0]);
20const fileName = uncurryThis(prototype.getFileName);
21const lineNumber = uncurryThis(prototype.getLineNumber);
22const columnNumber = uncurryThis(prototype.getColumnNumber);
23const frameToString = uncurryThis(prototype.toString);
24const errorToString = uncurryThis(Error.prototype.toString);
25
26delete Error.prepareStackTrace;
27export function formatStackTrace(error, frames) {
28  const custom = Error.prepareStackTrace;
29  if (typeof custom === "function") {
30    return ReflectApply(custom, Error, [error, frames]);
31  }
32  let stack;
33  try {
34    stack = errorToString(error);
35    for (let index = 0; index < frames.length; index++) {
36      stack += `\n    at ${frameToString(frames[index])}`;
37    }
38  } catch {
39    // V8's reentrant fallback preserves the original message and guards hostile getters.
40    stack = ErrorGetStack(error);
41  }
42  let end = stack.length;
43  for (let index = frames.length - 1; index >= 0; index--) {
44    const frame = frames[index];
45    const name = fileName(frame);
46    const line = lineNumber(frame);
47    const column = columnNumber(frame);
48    const mapped = name && line && column &&
49      mapSourceLocation(name, line, column);
50    if (!mapped) continue;
51    let text;
52    try {
53      text = `\n    at ${frameToString(frame)}`;
54    } catch {
55      continue;
56    }
57    const generated = `${name}:${line}:${column}`;
58    const frameAt = lastIndexOf(stack, text, end);
59    const locationAt = lastIndexOf(text, generated);
60    if (frameAt === -1 || locationAt === -1) continue;
61    end = frameAt - 1;
62    const at = frameAt + locationAt;
63    stack = StringPrototypeSlice(stack, 0, at) +
64      `${mapped[0]}:${mapped[1]}:${mapped[2]}` +
65      StringPrototypeSlice(stack, at + generated.length);
66  }
67  return stack;
68}