Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions bench/app-router-server/app/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import(`@/${globalThis.type}/${globalThis.processedSlugPath}`)

// globalThis.docs = 'docs'
// console.trace(require(`@/${globalThis.docs}/foo`))

// globalThis.foo = 'foo'
// console.trace(require(`@/docs/${globalThis.foo}`))

export default function page() {
return <div>hello</div>
}
5 changes: 0 additions & 5 deletions bench/app-router-server/app/rsc/page.js

This file was deleted.

Empty file.
1 change: 1 addition & 0 deletions bench/app-router-server/docs/foo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'docs'
1 change: 1 addition & 0 deletions bench/app-router-server/docs2/foo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'docs2'
6 changes: 6 additions & 0 deletions bench/app-router-server/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import './.next/types/routes.d.ts'

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
9 changes: 0 additions & 9 deletions bench/app-router-server/pages/index.js

This file was deleted.

37 changes: 37 additions & 0 deletions bench/app-router-server/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"],
"@/docs/*": ["./docs2/*"]
},
"strictNullChecks": true
},
"include": [
"**/*.mts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
"next-env.d.ts",
"next.config.mjs",
".next/dev/types/**/*.ts"
],
"exclude": ["node_modules", "**/*.test.ts", "**/*.test.tsx"]
}
33 changes: 28 additions & 5 deletions turbopack/crates/turbopack-core/src/resolve/alias_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,12 @@ where
}
}
AliasKey::Wildcard { suffix } => {
println!(
"AliasKey::Wildcard {} {}*{}",
self.request.describe_as_string(),
prefix,
suffix
);
// This is quite messy as we'd have to match against the FS to do this
// properly. For now, try to support as many cases as possible (and as are
// actually used).
Expand All @@ -570,6 +576,7 @@ where
// The request is a constant string, so the PatriciaMap lookup already
// ensured that the prefix is matching the request.
let remaining = &request[prefix.len()..];
println!("1");
remaining.ends_with(&**suffix)
} else if let Pattern::Concatenation(req) = self.request
&& let [
Expand All @@ -582,6 +589,7 @@ where

// The request might be more specific than the mapping, e.g. for
// `require('@/foo/' + dyn)` into a `@/*` mapping
println!("2");
req_prefix.starts_with(&**prefix)
} else if let Pattern::Concatenation(req) = self.request
&& let [
Expand All @@ -590,12 +598,16 @@ where
Pattern::Constant(req_suffix),
] = req.as_slice()
{
println!("3");
req_prefix.starts_with(&**prefix) && req_suffix.ends_with(&**suffix)
} else if !self.request.could_match(prefix) {
// There's no way it could match if the prefix can't match.
// If the whole of the prefix doesn't match, then it can't possibly
// match.
println!("4");
false
} else if suffix.is_empty() {
// Prefix matches the request, and suffix is empty.
// Prefix could match the request, and suffix is empty.
println!("5");
true
} else {
// It may or may not match, throw an error.
Expand All @@ -607,13 +619,24 @@ where
suffix,
)));
};
println!(
"AliasKey::Wildcard {} {}*{}, {}",
self.request.describe_as_string(),
prefix,
suffix,
is_match
);

if is_match {
let mut remaining = self.request.clone();
if let Err(e) = remaining.strip_prefix_len(prefix.len()) {
return Some(Err(e.context(self.request.describe_as_string())));
if let Err(e) = remaining.strip_constant_prefix_len(prefix.len()) {
return Some(Err(e.context(format!(
"{}.strip_constant_prefix_len({:?}.len())",
self.request.describe_as_string(),
prefix
))));
}
remaining.strip_suffix_len(suffix.len());
remaining.strip_constant_suffix_len(suffix.len());

let output = template.replace(&remaining);
return Some(Ok(AliasMatch {
Expand Down
40 changes: 18 additions & 22 deletions turbopack/crates/turbopack-core/src/resolve/pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,18 +227,18 @@ impl Pattern {
longest_common_suffix(&strings)
}

pub fn strip_prefix(&self, prefix: &str) -> Result<Option<Self>> {
pub fn strip_constant_prefix(&self, prefix: &str) -> Result<Option<Self>> {
if self.must_match(prefix) {
let mut pat = self.clone();
pat.strip_prefix_len(prefix.len())?;
pat.strip_constant_prefix_len(prefix.len())?;
Ok(Some(pat))
} else {
Ok(None)
}
}

pub fn strip_prefix_len(&mut self, len: usize) -> Result<()> {
fn strip_prefix_internal(pattern: &mut Pattern, chars_to_strip: &mut usize) -> Result<()> {
pub fn strip_constant_prefix_len(&mut self, len: usize) -> Result<()> {
fn strip_internal(pattern: &mut Pattern, chars_to_strip: &mut usize) -> Result<()> {
match pattern {
Pattern::Constant(c) => {
let c_len = c.len();
Expand All @@ -252,15 +252,15 @@ impl Pattern {
Pattern::Concatenation(list) => {
for c in list {
if *chars_to_strip > 0 {
strip_prefix_internal(c, chars_to_strip)?;
strip_internal(c, chars_to_strip)?;
}
}
}
Pattern::Alternatives(_) => {
bail!("strip_prefix pattern must be normalized");
bail!("strip_constant_prefix_len pattern must be normalized");
}
Pattern::Dynamic | Pattern::DynamicNoSlash => {
bail!("strip_prefix prefix is too long");
bail!("strip_constant_prefix_len prefix is too long");
}
}
Ok(())
Expand All @@ -269,21 +269,17 @@ impl Pattern {
match &mut *self {
c @ Pattern::Constant(_) | c @ Pattern::Concatenation(_) => {
let mut len_local = len;
strip_prefix_internal(c, &mut len_local)?;
strip_internal(c, &mut len_local)?;
}
Pattern::Alternatives(list) => {
for c in list {
let mut len_local = len;
strip_prefix_internal(c, &mut len_local)?;
strip_internal(c, &mut len_local)?;
}
}
Pattern::Dynamic | Pattern::DynamicNoSlash => {
if len > 0 {
bail!(
"strip_prefix prefix ({}) is too long: {}",
len,
self.describe_as_string()
);
bail!("strip_constant_prefix_len prefix is too long",);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bail!("strip_constant_prefix_len prefix is too long",);
bail!(
"strip_constant_prefix_len prefix ({}) is too long: {}",
len,
self.describe_as_string()
);

An error message has been simplified, losing valuable diagnostic information that was in the original code.

View Details

Analysis

Error message loses diagnostic information in Pattern::strip_constant_prefix_len()

What fails: The error message at line 282 in turbopack/crates/turbopack-core/src/resolve/pattern.rs when calling strip_constant_prefix_len() on a Dynamic or DynamicNoSlash pattern no longer includes the len value or the pattern description.

How to trigger it:

// In typescript.rs or any caller
let mut pattern = Pattern::Dynamic;
pattern.strip_constant_prefix_len(5)?;  // This will error with generic message

Result: Error message: "strip_constant_prefix_len prefix is too long" (generic, no context about the length or pattern)

Expected: Error message should include diagnostic details like in commit c6a6c73 (#84882):

"strip_constant_prefix_len prefix (5) is too long: <dynamic>"

This provides developers with the actual len value that exceeded the limit and the pattern description, which are valuable for debugging path resolution failures. The enhanced error message was intentionally added in commit c6a6c73 ("Turbopack: better errors for strip_prefix_len") with the message "To help debugging", but was removed in a subsequent WIP commit.

While some callers (in alias_map.rs) wrap the error with additional context, not all callers do (e.g., typescript.rs), so the function should include these diagnostic details in its own error message for complete debugging information across all call sites.

}
}
};
Expand All @@ -293,8 +289,8 @@ impl Pattern {
Ok(())
}

pub fn strip_suffix_len(&mut self, len: usize) {
fn strip_suffix_internal(pattern: &mut Pattern, chars_to_strip: &mut usize) {
pub fn strip_constant_suffix_len(&mut self, len: usize) {
fn strip_internal(pattern: &mut Pattern, chars_to_strip: &mut usize) {
match pattern {
Pattern::Constant(c) => {
let c_len = c.len();
Expand All @@ -308,7 +304,7 @@ impl Pattern {
Pattern::Concatenation(list) => {
for c in list.iter_mut().rev() {
if *chars_to_strip > 0 {
strip_suffix_internal(c, chars_to_strip);
strip_internal(c, chars_to_strip);
}
}
}
Expand All @@ -324,12 +320,12 @@ impl Pattern {
match &mut *self {
c @ Pattern::Constant(_) | c @ Pattern::Concatenation(_) => {
let mut len_local = len;
strip_suffix_internal(c, &mut len_local);
strip_internal(c, &mut len_local);
}
Pattern::Alternatives(list) => {
for c in list {
let mut len_local = len;
strip_suffix_internal(c, &mut len_local);
strip_internal(c, &mut len_local);
}
}
Pattern::Dynamic | Pattern::DynamicNoSlash => {
Expand Down Expand Up @@ -2169,9 +2165,9 @@ mod tests {
}

#[test]
fn strip_prefix() {
fn strip_constant_prefix() {
fn strip(mut pat: Pattern, n: usize) -> Pattern {
pat.strip_prefix_len(n).unwrap();
pat.strip_constant_prefix_len(n).unwrap();
pat
}

Expand Down Expand Up @@ -2212,7 +2208,7 @@ mod tests {
#[test]
fn strip_suffix() {
fn strip(mut pat: Pattern, n: usize) -> Pattern {
pat.strip_suffix_len(n);
pat.strip_constant_suffix_len(n);
pat
}

Expand Down
2 changes: 1 addition & 1 deletion turbopack/crates/turbopack-resolve/src/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ pub async fn type_resolve(
fragment: _,
} = &*request.await?
{
let mut m = if let Some(mut stripped) = m.strip_prefix("@")? {
let mut m = if let Some(mut stripped) = m.strip_constant_prefix("@")? {
stripped.replace_constants(&|c| Some(Pattern::Constant(c.replace("/", "__").into())));
stripped
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import { loadSub, loadSubNested, loadSubFallback } from './src/foo'
import {
load,
loadComplex,
loadSub,
loadSubNested,
loadSubFallback,
} from './src/foo'

it('should support dynamic requests with tsconfig.paths', () => {
expect(loadSub('file2.js').default).toBe('file2')
expect(load('sub/file2.js').default).toBe('file2')
expect(loadSub('file2.js').default).toBe('file2-override')
expect(loadComplex('sub', 'file2', 'js').default).toBe('file2')
})

it('should support dynamic requests with tsconfig.paths and without extension', () => {
expect(loadSub('file2').default).toBe('file2')
expect(loadSub('file2').default).toBe('file2-override')
})

it('should support dynamic requests with tsconfig.paths and multiple dynamic parts', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
export function load(v: string) {
return require(`@/${v}`)
}

export function loadComplex(dir: string, name: string, ext: string) {
return require(`@/${dir}/${name}/${ext}`)
}

export function loadSub(v: string) {
return require(`@/sub/${v}`)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'file1-override'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'file2-override'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'file3-override'
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"compilerOptions": {
"paths": {
"@/*": ["./*"],
"@/sub/*": ["./sub-override/*"],
"@sub/*": ["./sub/*", "./sub-fallback/*"]
}
}
Expand Down
Loading