{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { originalPositionFor, TraceMap } from '@jridgewell/trace-mapping';\nimport type { ErrorPayload, ModuleGraph, Plugin, WebSocketClient } from 'vite';\n\nconst packageName = 'runtime-error-plugin';\n\nexport default function viteRuntimeErrorOverlayPlugin(options?: {\n filter?: (error: Error) => boolean;\n}): Plugin {\n return {\n name: packageName,\n\n apply(config, env) {\n return env.command === 'serve' && !config.ssr;\n },\n\n transformIndexHtml() {\n return [\n {\n tag: 'script',\n attrs: { type: 'module' },\n children: CLIENT_SCRIPT,\n },\n ];\n },\n\n configureServer(server) {\n server.ws.on(MESSAGE_TYPE, (data: unknown, client: WebSocketClient) => {\n const error = Object.assign(new Error(), data);\n if (!error.stack) {\n return;\n }\n\n if (options?.filter && !options.filter(error)) {\n return;\n }\n\n const { stack, loc } = rewriteStacktrace(\n error.stack,\n server.moduleGraph,\n );\n\n const err: ErrorPayload['err'] = {\n name: error.name,\n message: error.message,\n stack,\n loc,\n plugin: packageName,\n };\n\n if (loc?.file) {\n err.id = loc?.file;\n const source = readFileSync(loc.file, 'utf-8');\n err.frame = generateCodeFrame(source, {\n line: loc.line,\n column: loc.column - 1,\n });\n }\n\n client.send({\n type: 'error',\n err,\n });\n });\n },\n };\n}\n\nconst MESSAGE_TYPE = `${packageName}:error`;\nconst CLIENT_SCRIPT = `\nimport { createHotContext } from \"/@vite/client\";\nconst hot = createHotContext(\"/__dummy__${packageName}\");\n\nfunction sendError(error) {\n if (!(error instanceof Error)) {\n error = new Error(\"(unknown runtime error)\");\n }\n const serialized = {\n message: error.message,\n stack: error.stack,\n };\n hot.send(\"${MESSAGE_TYPE}\", serialized);\n}\n\nwindow.addEventListener(\"error\", (evt) => {\n sendError(evt.error);\n});\n\nwindow.addEventListener(\"unhandledrejection\", (evt) => {\n sendError(evt.reason);\n});\n`;\n\nfunction cleanStack(stack: string) {\n return stack\n .split(/\\n/g)\n .filter((l) => /^\\s*at/.test(l))\n .join('\\n');\n}\n\nfunction rewriteStacktrace(\n stack: string,\n moduleGraph: ModuleGraph,\n): {\n stack: string;\n loc?: Pos & { file: string };\n} {\n let loc: (Pos & { file: string }) | undefined = undefined;\n const rewrittenStack = cleanStack(stack)\n .split('\\n')\n .map((line) => {\n return line.replace(\n /^ {4}at (?:(\\S+?) )?\\(?(?:https|http):\\/\\/[^\\/]+(\\/[^\\s?]+).*:(\\d+):(\\d+)\\)?$/,\n (input, varName, url, line, column) => {\n if (!url) {\n return input;\n }\n\n const module = moduleGraph.urlToModuleMap.get(url);\n if (!module) {\n return '';\n }\n\n const rawSourceMap = module?.transformResult?.map;\n\n if (rawSourceMap) {\n const traced = new TraceMap(rawSourceMap as any);\n const pos = originalPositionFor(traced, {\n line: Number(line),\n // stacktrace's column is 1-indexed, but sourcemap's one is 0-indexed\n column: Number(column) - 1,\n });\n\n if (pos.source && pos.line >= 0 && pos.column >= 0) {\n line = pos.line;\n column = pos.column + 1;\n }\n }\n\n const trimmedVarName = varName?.trim();\n const sourceFile = module.file;\n const source = `${module.file}:${line}:${column}`;\n\n if (sourceFile) {\n loc ??= {\n line: Number(line),\n column: Number(column),\n file: sourceFile,\n };\n }\n\n if (!trimmedVarName || trimmedVarName === 'eval') {\n return ` at ${source}`;\n } else {\n return ` at ${trimmedVarName} ${source}`;\n }\n },\n );\n })\n .join('\\n');\n\n return {\n stack: rewrittenStack,\n loc,\n };\n}\n\ntype Pos = {\n /** 1-based */\n line: number;\n /** 0-based */\n column: number;\n};\n\nconst splitRE = /\\r?\\n/g;\nconst range: number = 2;\n\nfunction posToNumber(source: string, pos: number | Pos): number {\n if (typeof pos === 'number') {\n return pos;\n }\n\n const lines = source.split(splitRE);\n const { line, column } = pos;\n let start = 0;\n for (let i = 0; i < line - 1 && i < lines.length; i++) {\n start += lines[i].length + 1;\n }\n\n return start + column;\n}\n\nfunction generateCodeFrame(\n source: string,\n start: number | Pos = 0,\n end?: number | Pos,\n): string {\n start = Math.max(posToNumber(source, start), 0);\n end = Math.min(\n end !== undefined ? posToNumber(source, end) : start,\n source.length,\n );\n const lines = source.split(splitRE);\n let count = 0;\n const res: Array = [];\n for (let i = 0; i < lines.length; i++) {\n count += lines[i].length;\n if (count >= start) {\n for (let j = i - range; j <= i + range || end > count; j++) {\n if (j < 0 || j >= lines.length) {\n continue;\n }\n\n const line = j + 1;\n res.push(\n `${line}${' '.repeat(Math.max(3 - String(line).length, 0))}| ${\n lines[j]\n }`,\n );\n const lineLength = lines[j].length;\n if (j === i) {\n const pad = Math.max(start - (count - lineLength), 0);\n const length = Math.max(\n 1,\n end > count ? lineLength - pad : end - start,\n );\n res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length));\n } else if (j > i) {\n if (end > count) {\n const length = Math.max(Math.min(end - count, lineLength), 1);\n res.push(` | ` + '^'.repeat(length));\n }\n\n count += lineLength + 1;\n }\n }\n\n break;\n }\n\n count++;\n }\n\n return res.join('\\n');\n}\n"],"mappings":"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","names":["line"]}