Skip to content

Commit

Permalink
built-in sourcemap support
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed Jan 14, 2025
1 parent e31435c commit 2fb1520
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 7 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@
"semver": "^7.6.3",
"serve-placeholder": "^2.0.2",
"serve-static": "^1.16.2",
"source-map": "^0.7.4",
"std-env": "^3.8.0",
"ufo": "^1.5.4",
"uncrypto": "^0.1.3",
Expand All @@ -165,7 +166,8 @@
"unstorage": "^1.14.4",
"untyped": "^1.5.2",
"unwasm": "^0.3.9",
"youch": "4.1.0-beta.4"
"youch": "4.1.0-beta.4",
"youch-core": "^0.3.1"
},
"devDependencies": {
"@azure/functions": "^3.5.1",
Expand Down
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 63 additions & 5 deletions src/runtime/internal/error/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import {
getRequestURL,
getResponseHeader,
} from "h3";

import { readFile } from "node:fs/promises";
import { resolve, dirname } from "node:path";
import consola from "consola";
import { ErrorParser } from "youch-core";
import { Youch } from "youch";

import { SourceMapConsumer } from "source-map";
import { defineNitroErrorHandler, setSecurityHeaders } from "./utils";

export default defineNitroErrorHandler(
Expand All @@ -20,19 +22,22 @@ export default defineNitroErrorHandler(
// prettier-ignore
const url = getRequestURL(event, { xForwardedHost: true, xForwardedProto: true }).toString();

const youch = new Youch();
// Load stack trace with source maps
await loadStackTrace(error);

// Console output
if (error.unhandled || error.fatal) {
// prettier-ignore
const tags = [error.unhandled && "[unhandled]", error.fatal && "[fatal]"].filter(Boolean).join(" ")
// const ansiError = await youch.toANSI(error);
consola.error(
`[nitro] [request error] ${tags} [${event.method}] ${url}\n`,
`[nitro] [request error] ${tags} [${event.method}] ${url}\n\n`,
error
);
}

// https://github.com/poppinss/youch
const youch = new Youch();

// Send response
setResponseStatus(event, statusCode, statusMessage);
setSecurityHeaders(event, true /* allow js */);
Expand Down Expand Up @@ -70,3 +75,56 @@ export default defineNitroErrorHandler(
);
}
);

// ---- Source Map support ----

type SourceLoader = Parameters<ErrorParser["defineSourceLoader"]>[0];
type StackFrame = Parameters<SourceLoader>[0];
async function sourceLoader(frame: StackFrame) {
if (!frame.fileName || frame.fileType !== "fs" || frame.type === "native") {
return;
}

if (frame.type === "app") {
// prettier-ignore
const rawSourceMap = await readFile(`${frame.fileName}.map`, "utf8").catch(() => {});
if (rawSourceMap) {
const consumer = await new SourceMapConsumer(rawSourceMap);
// prettier-ignore
const originalPosition = consumer.originalPositionFor({ line: frame.lineNumber!, column: frame.columnNumber! });
if (originalPosition.source && originalPosition.line) {
// prettier-ignore
frame.fileName = resolve(dirname(frame.fileName), originalPosition.source);
frame.lineNumber = originalPosition.line;
frame.columnNumber = originalPosition.column || 0;
}
}
}

const contents = await readFile(frame.fileName, "utf8").catch(() => {});

return contents ? { contents } : undefined;
}

async function loadStackTrace(error: any) {
const parsed = await new ErrorParser()
.defineSourceLoader(sourceLoader)
.parse(error);

const stack =
error.message +
"\n" +
parsed.frames
.map((frame) => {
return frame.type === "app" || !frame.raw
? `at ${frame.functionName || ""} (${frame.fileName}:${frame.lineNumber}:${frame.columnNumber})`
: frame.raw;
})
.join("\n");

Object.defineProperty(error, "stack", { value: stack });

if (error.cause) {
await loadStackTrace(error.cause);
}
}
1 change: 0 additions & 1 deletion src/runtime/internal/error/prod.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
getRequestHeader,
getRequestURL,
getResponseHeader,
send,
Expand Down

0 comments on commit 2fb1520

Please sign in to comment.