{"version":3,"sources":["../../../../../src/server/dev/browser-logs/source-map.ts"],"sourcesContent":["import { getOriginalStackFrames as getOriginalStackFramesWebpack } from '../middleware-webpack'\nimport { getOriginalStackFrames as getOriginalStackFramesTurbopack } from '../middleware-turbopack'\nimport type { Project } from '../../../build/swc/types'\nimport { dim } from '../../../lib/picocolors'\nimport { parseStack, type StackFrame } from '../../lib/parse-stack'\nimport path from 'path'\nimport { LRUCache } from '../../lib/lru-cache'\n\ntype WebpackMappingContext = {\n  bundler: 'webpack'\n  isServer: boolean\n  isEdgeServer: boolean\n  isAppDirectory: boolean\n  clientStats: () => any\n  serverStats: () => any\n  edgeServerStats: () => any\n  rootDirectory: string\n}\n\ntype TurbopackMappingContext = {\n  bundler: 'turbopack'\n  isServer: boolean\n  isEdgeServer: boolean\n  isAppDirectory: boolean\n  project: Project\n  projectPath: string\n}\n\nexport type MappingContext = WebpackMappingContext | TurbopackMappingContext\n\n// TODO: handle server vs browser error source mapping correctly\nexport async function mapFramesUsingBundler(\n  frames: StackFrame[],\n  ctx: MappingContext\n) {\n  switch (ctx.bundler) {\n    case 'webpack': {\n      const {\n        isServer,\n        isEdgeServer,\n        isAppDirectory,\n        clientStats,\n        serverStats,\n        edgeServerStats,\n        rootDirectory,\n      } = ctx\n      const res = await getOriginalStackFramesWebpack({\n        isServer,\n        isEdgeServer,\n        isAppDirectory,\n        frames,\n        clientStats,\n        serverStats,\n        edgeServerStats,\n        rootDirectory,\n      })\n      return res\n    }\n    case 'turbopack': {\n      const { project, projectPath, isServer, isEdgeServer, isAppDirectory } =\n        ctx\n      const res = await getOriginalStackFramesTurbopack({\n        project,\n        projectPath,\n        frames,\n        isServer,\n        isEdgeServer,\n        isAppDirectory,\n      })\n\n      return res\n    }\n    default: {\n      return null!\n    }\n  }\n}\n\n// converts _next/static/chunks/... to file:///.next/static/chunks/... for parseStack\n// todo: where does next dev overlay handle this case and re-use that logic\nfunction preprocessStackTrace(stackTrace: string, distDir?: string): string {\n  return stackTrace\n    .split('\\n')\n    .map((line) => {\n      const match = line.match(/^(\\s*at\\s+.*?)\\s+\\(([^)]+)\\)$/)\n      if (match) {\n        const [, prefix, location] = match\n\n        if (location.startsWith('_next/static/') && distDir) {\n          const normalizedDistDir = distDir\n            .replace(/\\\\/g, '/')\n            .replace(/\\/$/, '')\n\n          const absolutePath =\n            normalizedDistDir + '/' + location.slice('_next/'.length)\n          const fileUrl = `file://${path.resolve(absolutePath)}`\n\n          return `${prefix} (${fileUrl})`\n        }\n      }\n\n      return line\n    })\n    .join('\\n')\n}\n\nconst cache = new LRUCache<\n  Awaited<ReturnType<typeof getSourceMappedStackFramesInternal>>\n>(25)\nasync function getSourceMappedStackFramesInternal(\n  stackTrace: string,\n  ctx: MappingContext,\n  distDir: string,\n  ignore = true\n) {\n  try {\n    const normalizedStack = preprocessStackTrace(stackTrace, distDir)\n    const frames = parseStack(normalizedStack, distDir)\n\n    if (frames.length === 0) {\n      return {\n        kind: 'stack' as const,\n        stack: stackTrace,\n      }\n    }\n\n    const mappingResults = await mapFramesUsingBundler(frames, ctx)\n\n    const processedFrames = mappingResults\n      .map((result, index) => ({\n        result,\n        originalFrame: frames[index],\n      }))\n      .map(({ result, originalFrame }) => {\n        if (result.status === 'rejected') {\n          return {\n            kind: 'rejected' as const,\n            frameText: formatStackFrame(originalFrame),\n            codeFrame: null,\n          }\n        }\n\n        const { originalStackFrame, originalCodeFrame } = result.value\n        if (originalStackFrame?.ignored && ignore) {\n          return {\n            kind: 'ignored' as const,\n          }\n        }\n\n        // should we apply this generally to dev overlay (dev overlay does not ignore chrome-extension://)\n        if (originalStackFrame?.file?.startsWith('chrome-extension://')) {\n          return {\n            kind: 'ignored' as const,\n          }\n        }\n\n        return {\n          kind: 'success' as const,\n          // invariant: if result is not rejected and not ignored, then original stack frame exists\n          // verifiable by tracing `getOriginalStackFrame`. The invariant exists because of bad types\n          frameText: formatStackFrame(originalStackFrame!),\n          codeFrame: originalCodeFrame,\n        }\n      })\n\n    const allIgnored = processedFrames.every(\n      (frame) => frame.kind === 'ignored'\n    )\n\n    // we want to handle **all** ignored vs all/some rejected differently\n    // if all are ignored we should show no frames\n    // if all are rejected, we want to fallback to showing original stack frames\n    if (allIgnored) {\n      return {\n        kind: 'all-ignored' as const,\n      }\n    }\n\n    const filteredFrames = processedFrames.filter(\n      (frame) => frame.kind !== 'ignored'\n    )\n\n    if (filteredFrames.length === 0) {\n      return {\n        kind: 'stack' as const,\n        stack: stackTrace,\n      }\n    }\n\n    const stackOutput = filteredFrames\n      .map((frame) => frame.frameText)\n      .join('\\n')\n    const firstFrameCode = filteredFrames.find(\n      (frame) => frame.codeFrame\n    )?.codeFrame\n\n    if (firstFrameCode) {\n      return {\n        kind: 'with-frame-code' as const,\n        frameCode: firstFrameCode,\n        stack: stackOutput,\n        frames: filteredFrames,\n      }\n    }\n    // i don't think this a real case, but good for exhaustion\n    return {\n      kind: 'mapped-stack' as const,\n      stack: stackOutput,\n      frames: filteredFrames,\n    }\n  } catch (error) {\n    return {\n      kind: 'stack' as const,\n      stack: stackTrace,\n    }\n  }\n}\n\n// todo: cache the actual async call, not the wrapper with post processing\nexport async function getSourceMappedStackFrames(\n  stackTrace: string,\n  ctx: MappingContext,\n  distDir: string,\n  ignore = true\n) {\n  const cacheKey = `sm_${stackTrace}-${ctx.bundler}-${ctx.isAppDirectory}-${ctx.isEdgeServer}-${ctx.isServer}-${distDir}-${ignore}`\n\n  const cacheItem = cache.get(cacheKey)\n  if (cacheItem) {\n    return cacheItem\n  }\n\n  const result = await getSourceMappedStackFramesInternal(\n    stackTrace,\n    ctx,\n    distDir,\n    ignore\n  )\n  cache.set(cacheKey, result)\n  return result\n}\n\nfunction formatStackFrame(frame: StackFrame): string {\n  const functionName = frame.methodName || '<anonymous>'\n  const location =\n    frame.file && frame.line1\n      ? `${frame.file}:${frame.line1}${frame.column1 ? `:${frame.column1}` : ''}`\n      : frame.file || '<unknown>'\n\n  return `    at ${functionName} (${location})`\n}\n\n// appends the source mapped location of the console method\nexport const withLocation = async (\n  {\n    original,\n    stack,\n  }: {\n    original: Array<any>\n    stack: string | null\n  },\n  ctx: MappingContext,\n  distDir: string,\n  _config: boolean | 'error' | 'warn'\n) => {\n  if (!stack) {\n    return original\n  }\n\n  const res = await getSourceMappedStackFrames(stack, ctx, distDir)\n  const location = getConsoleLocation(res)\n\n  if (!location) {\n    return original\n  }\n\n  return [...original, dim(`(${location})`)]\n}\n\nexport const getConsoleLocation = (\n  mapped: Awaited<ReturnType<typeof getSourceMappedStackFrames>>\n) => {\n  if (mapped.kind !== 'mapped-stack' && mapped.kind !== 'with-frame-code') {\n    return null\n  }\n\n  const first = mapped.frames.at(0)\n\n  if (!first) {\n    return null\n  }\n\n  // we don't want to show the name of parent function (at <fn> thing in stack), just source location for minimal noise\n  const match = first.frameText.match(/\\(([^)]+)\\)/)\n  const locationText = match ? match[1] : first.frameText\n  return locationText\n}\n"],"names":["getOriginalStackFrames","getOriginalStackFramesWebpack","getOriginalStackFramesTurbopack","dim","parseStack","path","LRUCache","mapFramesUsingBundler","frames","ctx","bundler","isServer","isEdgeServer","isAppDirectory","clientStats","serverStats","edgeServerStats","rootDirectory","res","project","projectPath","preprocessStackTrace","stackTrace","distDir","split","map","line","match","prefix","location","startsWith","normalizedDistDir","replace","absolutePath","slice","length","fileUrl","resolve","join","cache","getSourceMappedStackFramesInternal","ignore","filteredFrames","normalizedStack","kind","stack","mappingResults","processedFrames","result","index","originalFrame","originalStackFrame","status","frameText","formatStackFrame","codeFrame","originalCodeFrame","value","ignored","file","allIgnored","every","frame","filter","stackOutput","firstFrameCode","find","frameCode","error","getSourceMappedStackFrames","cacheKey","cacheItem","get","set","functionName","methodName","line1","column1","withLocation","original","_config","getConsoleLocation","mapped","first","at","locationText"],"mappings":"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","ignoreList":[0]}