turbopack_ecmascript/references/
util.rs1use anyhow::Result;
2use swc_core::{ecma::ast::Expr, quote};
3use turbo_rcstr::{RcStr, rcstr};
4use turbo_tasks::{ResolvedVc, ValueToString, Vc};
5use turbo_tasks_fs::FileSystemPath;
6use turbopack_core::{
7 self,
8 issue::{
9 Issue, IssueExt, IssueSeverity, IssueSource, IssueStage, OptionIssueSource,
10 OptionStyledString, StyledString,
11 },
12 resolve::{ModuleResolveResult, parse::Request, pattern::Pattern},
13};
14
15pub fn throw_module_not_found_expr(request: &str) -> Expr {
18 let message = format!("Cannot find module '{request}'");
19 quote!(
20 "(() => { const e = new Error($message); e.code = 'MODULE_NOT_FOUND'; throw e; })()"
21 as Expr,
22 message: Expr = message.into()
23 )
24}
25
26pub fn throw_module_not_found_expr_async(request: &str) -> Expr {
29 let message = format!("Cannot find module '{request}'");
30 quote!(
31 "Promise.resolve().then(() => { const e = new Error($message); e.code = 'MODULE_NOT_FOUND'; throw e; })"
32 as Expr,
33 message: Expr = message.into()
34 )
35}
36
37pub fn throw_module_not_found_error_expr(request: &str, message: &str) -> Expr {
40 let message = format!("Cannot find module '{request}': {message}");
41 quote!(
42 "(() => { const e = new Error($message); e.code = 'MODULE_NOT_FOUND'; throw e; })()"
43 as Expr,
44 message: Expr = message.into()
45 )
46}
47
48#[turbo_tasks::function]
49pub async fn request_to_string(request: Vc<Request>) -> Result<Vc<RcStr>> {
50 Ok(Vc::cell(
51 request
52 .await?
53 .request()
54 .unwrap_or(rcstr!("unknown")),
56 ))
57}
58
59const TOO_MANY_MATCHES_LIMIT: usize = 10000;
61
62pub async fn check_and_emit_too_many_matches_warning(
63 result: Vc<ModuleResolveResult>,
64 issue_source: IssueSource,
65 context_dir: FileSystemPath,
66 pattern: ResolvedVc<Pattern>,
67) -> Result<()> {
68 let num_matches = result.await?.primary.len();
69 if num_matches > TOO_MANY_MATCHES_LIMIT {
70 TooManyMatchesWarning {
71 source: issue_source,
72 context_dir,
73 num_matches,
74 pattern,
75 }
76 .resolved_cell()
77 .emit();
78 }
79 Ok(())
80}
81
82#[turbo_tasks::value(shared)]
83struct TooManyMatchesWarning {
84 source: IssueSource,
85 context_dir: FileSystemPath,
86 num_matches: usize,
87 pattern: ResolvedVc<Pattern>,
88}
89
90#[turbo_tasks::value_impl]
91impl Issue for TooManyMatchesWarning {
92 #[turbo_tasks::function]
93 async fn title(&self) -> Result<Vc<StyledString>> {
94 Ok(StyledString::Text(
95 format!(
96 "The file pattern {pattern} matches {num_matches} files in {context_dir}",
97 pattern = self.pattern.to_string().await?,
98 context_dir = self.context_dir.value_to_string().await?,
99 num_matches = self.num_matches
100 )
101 .into(),
102 )
103 .cell())
104 }
105
106 #[turbo_tasks::function]
107 fn description(&self) -> Vc<OptionStyledString> {
108 Vc::cell(Some(
109 StyledString::Text(rcstr!(
110 "Overly broad patterns can lead to build performance issues and over bundling."
111 ))
112 .resolved_cell(),
113 ))
114 }
115
116 #[turbo_tasks::function]
117 async fn file_path(&self) -> Vc<FileSystemPath> {
118 self.source.file_path()
119 }
120
121 #[turbo_tasks::function]
122 fn stage(&self) -> Vc<IssueStage> {
123 IssueStage::Resolve.cell()
124 }
125
126 fn severity(&self) -> IssueSeverity {
127 IssueSeverity::Warning
128 }
129
130 #[turbo_tasks::function]
131 fn source(&self) -> Vc<OptionIssueSource> {
132 Vc::cell(Some(self.source))
133 }
134}