Skip to content

Commit 692085d

Browse files
committed
add ./ to relative paths to make it easier to understand
1 parent 251e6bd commit 692085d

File tree

6 files changed

+85
-76
lines changed

6 files changed

+85
-76
lines changed

crates/napi/src/next_api/project.rs

+30-37
Original file line numberDiff line numberDiff line change
@@ -1213,44 +1213,37 @@ pub async fn project_trace_source(
12131213

12141214
let project_root_uri =
12151215
uri_from_file(project.container.project().project_root_path(), None).await? + "/";
1216-
let (file, original_file, is_internal) = if let Some(source_file) =
1217-
original_file.strip_prefix(&project_root_uri)
1218-
{
1219-
// Client code uses file://
1220-
(
1221-
get_relative_path_to(&current_directory_file_url, &original_file)
1222-
// TODO(sokra) remove this to include a ./ here to make it a relative path
1223-
.trim_start_matches("./")
1224-
.to_string(),
1225-
Some(source_file.to_string()),
1226-
false,
1227-
)
1228-
} else if let Some(source_file) =
1229-
original_file.strip_prefix(&*SOURCE_MAP_PREFIX_PROJECT)
1230-
{
1231-
// Server code uses turbopack://[project]
1232-
// TODO should this also be file://?
1233-
(
1234-
get_relative_path_to(
1235-
&current_directory_file_url,
1236-
&format!("{}{}", project_root_uri, source_file),
1216+
let (file, original_file, is_internal) =
1217+
if let Some(source_file) = original_file.strip_prefix(&project_root_uri) {
1218+
// Client code uses file://
1219+
(
1220+
get_relative_path_to(&current_directory_file_url, &original_file),
1221+
Some(source_file.to_string()),
1222+
false,
12371223
)
1238-
// TODO(sokra) remove this to include a ./ here to make it a relative path
1239-
.trim_start_matches("./")
1240-
.to_string(),
1241-
Some(source_file.to_string()),
1242-
false,
1243-
)
1244-
} else if let Some(source_file) = original_file.strip_prefix(SOURCE_MAP_PREFIX) {
1245-
// All other code like turbopack://[turbopack] is internal code
1246-
(source_file.to_string(), None, true)
1247-
} else {
1248-
bail!(
1249-
"Original file ({}) outside project ({})",
1250-
original_file,
1251-
project_root_uri
1252-
)
1253-
};
1224+
} else if let Some(source_file) =
1225+
original_file.strip_prefix(&*SOURCE_MAP_PREFIX_PROJECT)
1226+
{
1227+
// Server code uses turbopack://[project]
1228+
// TODO should this also be file://?
1229+
(
1230+
get_relative_path_to(
1231+
&current_directory_file_url,
1232+
&format!("{}{}", project_root_uri, source_file),
1233+
),
1234+
Some(source_file.to_string()),
1235+
false,
1236+
)
1237+
} else if let Some(source_file) = original_file.strip_prefix(SOURCE_MAP_PREFIX) {
1238+
// All other code like turbopack://[turbopack] is internal code
1239+
(source_file.to_string(), None, true)
1240+
} else {
1241+
bail!(
1242+
"Original file ({}) outside project ({})",
1243+
original_file,
1244+
project_root_uri
1245+
)
1246+
};
12541247

12551248
Ok(Some(StackFrame {
12561249
file,

packages/next/src/client/components/react-dev-overlay/server/middleware-turbopack.ts

+2-9
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import type { Project, TurbopackStackFrame } from '../../../../build/swc/types'
1919
import { getSourceMapFromFile } from '../internal/helpers/get-source-map-from-file'
2020
import { findSourceMap, type SourceMapPayload } from 'node:module'
2121
import { pathToFileURL } from 'node:url'
22+
import { relativeToCwd } from '../../../../server/lib/stack-trace-utils'
2223

2324
function shouldIgnorePath(modulePath: string): boolean {
2425
return (
@@ -262,9 +263,7 @@ async function nativeTraceSource(
262263
?.replace('__WEBPACK_DEFAULT_EXPORT__', 'default')
263264
?.replace('__webpack_exports__.', '') || '<unknown>',
264265
column: (originalPosition.column ?? 0) + 1,
265-
file: originalPosition.source?.startsWith('file://')
266-
? relativeToCwd(originalPosition.source)
267-
: originalPosition.source,
266+
file: relativeToCwd(originalPosition.source),
268267
lineNumber: originalPosition.line ?? 0,
269268
// TODO: c&p from async createOriginalStackFrame but why not frame.arguments?
270269
arguments: [],
@@ -281,12 +280,6 @@ async function nativeTraceSource(
281280
return undefined
282281
}
283282

284-
function relativeToCwd(file: string): string {
285-
const relPath = path.relative(process.cwd(), url.fileURLToPath(file))
286-
// TODO(sokra) include a ./ here to make it a relative path
287-
return relPath
288-
}
289-
290283
async function createOriginalStackFrame(
291284
project: Project,
292285
frame: TurbopackStackFrame
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { relative, isAbsolute } from 'path'
2+
import { fileURLToPath } from 'url'
3+
4+
// Formats a file url or absolute path as relative path relative to the current working directory.
5+
// It will start with ./ or ../ if it's a relative path.
6+
// It might be an absolute path if it's on a different drive on windows.
7+
// When the argument is not a file url or a absolute path, it will return the argument as is.
8+
export function relativeToCwd(file: string): string
9+
export function relativeToCwd(file: null): null
10+
export function relativeToCwd(file: string | null): string | null
11+
export function relativeToCwd(file: string | null): string | null {
12+
if (!file) {
13+
return file
14+
}
15+
if (file.startsWith('file://')) {
16+
file = fileURLToPath(file)
17+
} else if (!isAbsolute(file)) {
18+
return file
19+
}
20+
const relPath = relative(process.cwd(), file)
21+
if (isAbsolute(relPath)) {
22+
return relPath
23+
}
24+
if (relPath.startsWith('../')) {
25+
return relPath
26+
}
27+
return './' + relPath
28+
}

packages/next/src/server/patch-error-inspect.ts

+6-17
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import {
22
findSourceMap as nativeFindSourceMap,
33
type SourceMapPayload,
44
} from 'module'
5-
import * as path from 'path'
65
import * as url from 'url'
76
import type * as util from 'util'
87
import { SourceMapConsumer as SyncSourceMapConsumer } from 'next/dist/compiled/source-map'
@@ -11,6 +10,7 @@ import { parseStack } from '../client/components/react-dev-overlay/server/middle
1110
import { getOriginalCodeFrame } from '../client/components/react-dev-overlay/server/shared'
1211
import { workUnitAsyncStorage } from './app-render/work-unit-async-storage.external'
1312
import { dim } from '../lib/picocolors'
13+
import { relativeToCwd } from './lib/stack-trace-utils'
1414

1515
type FindSourceMapPayload = (
1616
sourceURL: string
@@ -66,22 +66,11 @@ function frameToString(frame: StackFrame): string {
6666
sourceLocation += `:${frame.column}`
6767
}
6868

69-
let fileLocation: string | null
70-
if (
71-
frame.file !== null &&
72-
frame.file.startsWith('file://') &&
73-
URL.canParse(frame.file)
74-
) {
75-
// If not relative to CWD, the path is ambiguous to IDEs and clicking will prompt to select the file first.
76-
// In a multi-app repo, this leads to potentially larger file names but will make clicking snappy.
77-
// There's no tradeoff for the cases where `dir` in `next dev [dir]` is omitted
78-
// since relative to cwd is both the shortest and snappiest.
79-
fileLocation = path.relative(process.cwd(), url.fileURLToPath(frame.file))
80-
} else if (frame.file !== null && frame.file.startsWith('/')) {
81-
fileLocation = path.relative(process.cwd(), frame.file)
82-
} else {
83-
fileLocation = frame.file
84-
}
69+
// If not relative to CWD, the path is ambiguous to IDEs and clicking will prompt to select the file first.
70+
// In a multi-app repo, this leads to potentially larger file names but will make clicking snappy.
71+
// There's no tradeoff for the cases where `dir` in `next dev [dir]` is omitted
72+
// since relative to cwd is both the shortest and snappiest.
73+
let fileLocation = relativeToCwd(frame.file)
8574

8675
return frame.methodName
8776
? ` at ${frame.methodName} (${fileLocation}${sourceLocation})`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Hide the method name when showing a stack trace in the error overlay or when displaying a stack trace in the console.
2+
export function isHiddenMethodName(methodName: string) {
3+
return /^(?:Object\.|Module\.)?(?:<anonymous>|eval|__TURBOPACK__module__evaluation__)$/.test(
4+
methodName
5+
)
6+
}

test/e2e/app-dir/non-root-project-monorepo/non-root-project-monorepo.test.ts

+13-13
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ describe('non-root-project-monorepo', () => {
9898
if (isTurbopack) {
9999
// TODO the function name should be hidden
100100
expect(await getRedboxSource(browser)).toMatchInlineSnapshot(`
101-
"app/source-maps-rsc/page.tsx (13:28) @ innerArrowFunction
101+
"./app/source-maps-rsc/page.tsx (13:28) @ innerArrowFunction
102102
103103
11 | }
104104
12 |
@@ -120,9 +120,9 @@ describe('non-root-project-monorepo', () => {
120120
innerArrowFunction
121121
app/source-maps-rsc/page.tsx (13:28)
122122
innerFunction
123-
app/source-maps-rsc/page.tsx (10:3)
123+
./app/source-maps-rsc/page.tsx (10:3)
124124
Page
125-
app/source-maps-rsc/page.tsx (4:5)"
125+
./app/source-maps-rsc/page.tsx (4:5)"
126126
`)
127127
} else {
128128
// TODO the function name is incorrect
@@ -160,7 +160,7 @@ describe('non-root-project-monorepo', () => {
160160
if (isTurbopack) {
161161
// TODO the function name should be hidden
162162
expect(await getRedboxSource(browser)).toMatchInlineSnapshot(`
163-
"app/separate-file.ts (1:7) @ [project]/apps/web/app/separate-file.ts [app-client] (ecmascript)
163+
"./app/separate-file.ts (1:7) @ [project]/apps/web/app/separate-file.ts [app-client] (ecmascript)
164164
165165
> 1 | throw new Error('Expected error')
166166
| ^
@@ -169,13 +169,13 @@ describe('non-root-project-monorepo', () => {
169169
expect(normalizeStackTrace(await getRedboxCallStack(browser)))
170170
.toMatchInlineSnapshot(`
171171
"[project]/apps/web/app/separate-file.ts [app-client] (ecmascript)
172-
app/separate-file.ts (1:7)
172+
./app/separate-file.ts (1:7)
173173
innerArrowFunction
174-
app/source-maps-ssr/page.tsx (15:28)
174+
./app/source-maps-ssr/page.tsx (15:28)
175175
innerFunction
176-
app/source-maps-ssr/page.tsx (12:3)
176+
./app/source-maps-ssr/page.tsx (12:3)
177177
Page
178-
app/source-maps-ssr/page.tsx (6:5)"
178+
./app/source-maps-ssr/page.tsx (6:5)"
179179
`)
180180
} else {
181181
// TODO the function name should be hidden
@@ -217,7 +217,7 @@ describe('non-root-project-monorepo', () => {
217217
if (isTurbopack) {
218218
// TODO the function name should be hidden
219219
expect(await getRedboxSource(browser)).toMatchInlineSnapshot(`
220-
"app/separate-file.ts (1:7) @ [project]/apps/web/app/separate-file.ts [app-client] (ecmascript)
220+
"./app/separate-file.ts (1:7) @ [project]/apps/web/app/separate-file.ts [app-client] (ecmascript)
221221
222222
> 1 | throw new Error('Expected error')
223223
| ^
@@ -226,13 +226,13 @@ describe('non-root-project-monorepo', () => {
226226
expect(normalizeStackTrace(await getRedboxCallStack(browser)))
227227
.toMatchInlineSnapshot(`
228228
"[project]/apps/web/app/separate-file.ts [app-client] (ecmascript)
229-
app/separate-file.ts (1:7)
229+
./app/separate-file.ts (1:7)
230230
innerArrowFunction
231-
app/source-maps-client/page.tsx (16:28)
231+
./app/source-maps-client/page.tsx (16:28)
232232
innerFunction
233-
app/source-maps-client/page.tsx (13:3)
233+
./app/source-maps-client/page.tsx (13:3)
234234
effectCallback
235-
app/source-maps-client/page.tsx (7:5)"
235+
./app/source-maps-client/page.tsx (7:5)"
236236
`)
237237
} else {
238238
// TODO the function name should be hidden

0 commit comments

Comments
 (0)