Skip to content

Commit 585ff17

Browse files
devjiwonchoibgw
andcommitted
Update Turbopack code
Co-authored-by: Benjamin Woodruff <benjamin.woodruff@vercel.com>
1 parent deada72 commit 585ff17

File tree

1 file changed

+75
-25
lines changed

1 file changed

+75
-25
lines changed

crates/next-core/src/middleware.rs

Lines changed: 75 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
use anyhow::{Result, bail};
1+
use std::path::Path;
2+
3+
use anyhow::Result;
24
use turbo_rcstr::{RcStr, rcstr};
35
use turbo_tasks::{ResolvedVc, Vc, fxindexmap};
46
use turbo_tasks_fs::FileSystemPath;
5-
use turbopack_core::{context::AssetContext, module::Module, reference_type::ReferenceType};
7+
use turbopack_core::{
8+
context::AssetContext,
9+
issue::{Issue, IssueExt, IssueSeverity, IssueStage, OptionStyledString, StyledString},
10+
module::Module,
11+
reference_type::ReferenceType,
12+
};
613
use turbopack_ecmascript::chunk::{EcmascriptChunkPlaceable, EcmascriptExports};
714

815
use crate::util::load_next_js_template;
@@ -33,7 +40,11 @@ pub async fn get_middleware_module(
3340
// Determine if this is a proxy file by checking the module path
3441
let userland_path = userland_module.ident().path().await?;
3542
let is_proxy = userland_path.file_stem() == Some("proxy");
36-
let page_path = if is_proxy { "/proxy" } else { "/middleware" };
43+
let (file_type, function_name, page_path) = if is_proxy {
44+
("Proxy", "proxy", "/proxy")
45+
} else {
46+
("Middleware", "middleware", "/middleware")
47+
};
3748

3849
// Validate that the module has the required exports
3950
if let Some(ecma_module) =
@@ -46,13 +57,9 @@ pub async fn get_middleware_module(
4657
// ESM modules - check for named or default export
4758
EcmascriptExports::EsmExports(esm_exports) => {
4859
let esm_exports = esm_exports.await?;
49-
let has_default = esm_exports.exports.contains_key(&rcstr!("default"));
50-
let expected_named = if is_proxy {
51-
rcstr!("proxy")
52-
} else {
53-
rcstr!("middleware")
54-
};
55-
let has_named = esm_exports.exports.contains_key(&expected_named);
60+
let has_default = esm_exports.exports.contains_key("default");
61+
let expected_named = function_name;
62+
let has_named = esm_exports.exports.contains_key(expected_named);
5663
has_default || has_named
5764
}
5865
// CommonJS modules are valid (they can have module.exports or exports.default)
@@ -66,21 +73,16 @@ pub async fn get_middleware_module(
6673
};
6774

6875
if !has_valid_export {
69-
let file_type = if is_proxy { "Proxy" } else { "Middleware" };
70-
let function_name = if is_proxy { "proxy" } else { "middleware" };
71-
// Extract just the filename for the error message
72-
let file_name = userland_path
73-
.path
74-
.split('/')
75-
.next_back()
76-
.unwrap_or(&userland_path.path);
77-
// Use the same error message format as the runtime check
78-
bail!(
79-
"The {} file \"./{}\" must export a function named `{}` or a default function.",
80-
file_type,
81-
file_name,
82-
function_name
83-
);
76+
MiddlewareMissingExportIssue {
77+
file_type: file_type.into(),
78+
function_name: function_name.into(),
79+
file_path: (*userland_path).clone(),
80+
}
81+
.resolved_cell()
82+
.emit();
83+
84+
// Continue execution instead of bailing - let the module be processed anyway
85+
// The runtime template will still catch this at runtime
8486
}
8587
}
8688
// If we can't cast to EcmascriptChunkPlaceable, continue without validation
@@ -113,3 +115,51 @@ pub async fn get_middleware_module(
113115

114116
Ok(module)
115117
}
118+
119+
#[turbo_tasks::value]
120+
struct MiddlewareMissingExportIssue {
121+
file_type: RcStr, // "Proxy" or "Middleware"
122+
function_name: RcStr, // "proxy" or "middleware"
123+
file_path: FileSystemPath,
124+
}
125+
126+
#[turbo_tasks::value_impl]
127+
impl Issue for MiddlewareMissingExportIssue {
128+
#[turbo_tasks::function]
129+
fn stage(&self) -> Vc<IssueStage> {
130+
IssueStage::Transform.into()
131+
}
132+
133+
fn severity(&self) -> IssueSeverity {
134+
IssueSeverity::Error
135+
}
136+
137+
#[turbo_tasks::function]
138+
fn file_path(&self) -> Vc<FileSystemPath> {
139+
self.file_path.clone().cell()
140+
}
141+
142+
#[turbo_tasks::function]
143+
fn title(&self) -> Vc<StyledString> {
144+
let file_name = Path::new(&self.file_path.path)
145+
.file_name()
146+
.and_then(|n| n.to_str())
147+
.unwrap_or(&self.file_path.path);
148+
149+
StyledString::Line(vec![
150+
StyledString::Text(rcstr!("The ")),
151+
StyledString::Code(self.file_type.clone()),
152+
StyledString::Text(rcstr!(" file \"")),
153+
StyledString::Code(format!("./{}", file_name).into()),
154+
StyledString::Text(rcstr!("\" must export a function named ")),
155+
StyledString::Code(format!("`{}`", self.function_name).into()),
156+
StyledString::Text(rcstr!(" or a default function.")),
157+
])
158+
.cell()
159+
}
160+
161+
#[turbo_tasks::function]
162+
fn description(&self) -> Vc<OptionStyledString> {
163+
Vc::cell(None)
164+
}
165+
}

0 commit comments

Comments
 (0)