Repository: vercel/next.js
Pull request: [devtools] Stop sending codeframes for ignored frames

Codeframes for ignored stackframes are not used by the Redbox at the moment and impact performance of the sourcemapping request noticeably (the more ignore-listed frames, the worse).
In `test/development/app-dir/ssr-only-error/` the sourcemapping request went down to 600ms from 1.8s for both Webpack and Turbopack. On larger stacks that may be even more noticably.

I believe this should reduce flakiness of the `test/development/app-dir/ssr-only-error/ssr-only-error.test.ts` test since we currently block the Redbox on the sourcemapping request (which I also want to change later).

As a follow-up, we'll only send the codeframe for the first non-ignored frame to save even more I/O and CPU.

We'll add a dedicated endpoint to fetch codeframes on demand to allow switching codeframes for https://github.com/vercel/next.js/pull/88867/



Changed files:
filename: packages/next/src/build/webpack/plugins/wellknown-errors-plugin/parseNotFoundError.ts
patch: @@ -4,6 +4,7 @@ import {
   createOriginalStackFrame,
   getIgnoredSources,
 } from '../../../../server/dev/middleware-webpack'
+import isInternal from '../../../../shared/lib/is-internal'
 import type { webpack } from 'next/dist/compiled/webpack/webpack'
 import type { RawSourceMap } from 'next/dist/compiled/source-map08'
 
@@ -89,10 +90,22 @@ async function getSourceFrame(
         },
       })
 
+      if (result === null || result.originalStackFrame === null) {
+        return {
+          column1: '',
+          frame: '',
+          line1: '',
+        }
+      }
+
+      const originalStackFrame = result.originalStackFrame
       return {
-        frame: result?.originalCodeFrame ?? '',
-        line1: result?.originalStackFrame?.line1?.toString() ?? '',
-        column1: result?.originalStackFrame?.column1?.toString() ?? '',
+        frame:
+          (!isInternal(originalStackFrame.file)
+            ? result.originalCodeFrame
+            : null) ?? '',
+        line1: originalStackFrame.line1?.toString() ?? '',
+        column1: originalStackFrame.column1?.toString() ?? '',
       }
     }
   } catch {}

filename: packages/next/src/next-devtools/server/shared.ts
patch: @@ -1,5 +1,4 @@
 import { codeFrameColumns } from 'next/dist/compiled/babel/code-frame'
-import isInternal from '../../shared/lib/is-internal'
 import type { StackFrame } from '../../server/lib/parse-stack'
 import { ignoreListAnonymousStackFramesIfSandwiched as ignoreListAnonymousStackFramesIfSandwichedGeneric } from '../../server/lib/source-maps'
 
@@ -68,7 +67,7 @@ export function getOriginalCodeFrame(
   source: string | null,
   colors: boolean = process.stdout.isTTY
 ): string | null {
-  if (!source || isInternal(frame.file)) {
+  if (!source) {
     return null
   }
 

filename: packages/next/src/server/dev/middleware-turbopack.ts
patch: @@ -307,16 +307,25 @@ async function createOriginalStackFrame(
     )
   }
 
+  /** undefined = not yet computed */
+  let originalCodeFrame: string | null | undefined
+
+  const tracedFrame = traced.frame
   return {
     originalStackFrame: {
-      arguments: traced.frame.arguments,
+      arguments: tracedFrame.arguments,
       file: normalizedStackFrameLocation,
-      line1: traced.frame.line1,
-      column1: traced.frame.column1,
-      ignored: traced.frame.ignored,
-      methodName: traced.frame.methodName,
+      line1: tracedFrame.line1,
+      column1: tracedFrame.column1,
+      ignored: tracedFrame.ignored,
+      methodName: tracedFrame.methodName,
+    },
+    get originalCodeFrame() {
+      if (originalCodeFrame === undefined) {
+        originalCodeFrame = getOriginalCodeFrame(tracedFrame, traced.source)
+      }
+      return originalCodeFrame
     },
-    originalCodeFrame: getOriginalCodeFrame(traced.frame, traced.source),
   }
 }
 
@@ -507,7 +516,18 @@ export async function getOriginalStackFrames({
             reason: 'Failed to create original stack frame',
           }
         }
-        return { status: 'fulfilled', value: stackFrame }
+        const originalStackFrame = stackFrame.originalStackFrame
+        return {
+          status: 'fulfilled',
+          value: {
+            originalStackFrame,
+            originalCodeFrame:
+              (originalStackFrame?.ignored ?? true)
+                ? null
+                : // TODO: Don't get all codeframes of non-ignored frames eagerly.
+                  stackFrame.originalCodeFrame,
+          },
+        }
       } catch (error) {
         return {
           status: 'rejected',

filename: packages/next/src/server/dev/middleware-webpack.ts
patch: @@ -254,9 +254,17 @@ export async function createOriginalStackFrame({
     ignored,
   }
 
+  /** undefined = not yet computed */
+  let originalCodeFrame: string | null | undefined
+
   return {
     originalStackFrame: traced,
-    originalCodeFrame: getOriginalCodeFrame(traced, sourceContent),
+    get originalCodeFrame() {
+      if (originalCodeFrame === undefined) {
+        originalCodeFrame = getOriginalCodeFrame(traced, sourceContent)
+      }
+      return originalCodeFrame
+    },
   }
 }
 
@@ -530,7 +538,15 @@ async function getOriginalStackFrame({
     }
   }
 
-  return originalStackFrameResponse
+  const originalStackFrame = originalStackFrameResponse.originalStackFrame
+  return {
+    originalStackFrame,
+    originalCodeFrame:
+      (originalStackFrame?.ignored ?? true)
+        ? null
+        : // TODO: Don't get all codeframes of non-ignored frames eagerly.
+          originalStackFrameResponse.originalCodeFrame,
+  }
 }
 
 export function getOverlayMiddleware(options: {

filename: packages/next/src/server/patch-error-inspect.ts
patch: @@ -303,33 +303,27 @@ function getSourcemappedFrameIfPossible(
     ignored,
   }
 
-  /** undefined = not yet computed*/
+  /** undefined = not yet computed */
   let codeFrame: string | null | undefined
 
-  return Object.defineProperty(
-    {
-      stack: originalFrame,
-      code: null,
+  return {
+    stack: originalFrame,
+    get code() {
+      if (codeFrame === undefined) {
+        const sourceContent: string | null =
+          sourceMapConsumer.sourceContentFor(
+            sourcePosition.source,
+            /* returnNullOnMissing */ true
+          ) ?? null
+        codeFrame = getOriginalCodeFrame(
+          originalFrame,
+          sourceContent,
+          inspectOptions.colors
+        )
+      }
+      return codeFrame
     },
-    'code',
-    {
-      get: () => {
-        if (codeFrame === undefined) {
-          const sourceContent: string | null =
-            sourceMapConsumer.sourceContentFor(
-              sourcePosition.source,
-              /* returnNullOnMissing */ true
-            ) ?? null
-          codeFrame = getOriginalCodeFrame(
-            originalFrame,
-            sourceContent,
-            inspectOptions.colors
-          )
-        }
-        return codeFrame
-      },
-    }
-  )
+  }
 }
 
 function parseAndSourceMap(