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_error_expr(request: &str, message: &str) -> Expr {
29 let message = format!("Cannot find module '{request}': {message}");
30 quote!(
31 "(() => { const e = new Error($message); e.code = 'MODULE_NOT_FOUND'; throw e; })()"
32 as Expr,
33 message: Expr = message.into()
34 )
35}
36
37#[turbo_tasks::function]
38pub async fn request_to_string(request: Vc<Request>) -> Result<Vc<RcStr>> {
39 Ok(Vc::cell(
40 request
41 .await?
42 .request()
43 .unwrap_or(rcstr!("unknown")),
45 ))
46}
47
48const TOO_MANY_MATCHES_LIMIT: usize = 10000;
50
51pub async fn check_and_emit_too_many_matches_warning(
52 result: Vc<ModuleResolveResult>,
53 issue_source: IssueSource,
54 context_dir: FileSystemPath,
55 pattern: ResolvedVc<Pattern>,
56) -> Result<()> {
57 let num_matches = result.await?.primary.len();
58 if num_matches > TOO_MANY_MATCHES_LIMIT {
59 TooManyMatchesWarning {
60 source: issue_source,
61 context_dir,
62 num_matches,
63 pattern,
64 }
65 .resolved_cell()
66 .emit();
67 }
68 Ok(())
69}
70
71#[turbo_tasks::value(shared)]
72struct TooManyMatchesWarning {
73 source: IssueSource,
74 context_dir: FileSystemPath,
75 num_matches: usize,
76 pattern: ResolvedVc<Pattern>,
77}
78
79#[turbo_tasks::value_impl]
80impl Issue for TooManyMatchesWarning {
81 #[turbo_tasks::function]
82 async fn title(&self) -> Result<Vc<StyledString>> {
83 Ok(StyledString::Text(
84 format!(
85 "The file pattern {pattern} matches {num_matches} files in {context_dir}",
86 pattern = self.pattern.to_string().await?,
87 context_dir = self.context_dir.value_to_string().await?,
88 num_matches = self.num_matches
89 )
90 .into(),
91 )
92 .cell())
93 }
94
95 #[turbo_tasks::function]
96 fn description(&self) -> Vc<OptionStyledString> {
97 Vc::cell(Some(
98 StyledString::Text(rcstr!(
99 "Overly broad patterns can lead to build performance issues and over bundling."
100 ))
101 .resolved_cell(),
102 ))
103 }
104
105 #[turbo_tasks::function]
106 async fn file_path(&self) -> Vc<FileSystemPath> {
107 self.source.file_path()
108 }
109
110 #[turbo_tasks::function]
111 fn stage(&self) -> Vc<IssueStage> {
112 IssueStage::Resolve.cell()
113 }
114
115 fn severity(&self) -> IssueSeverity {
116 IssueSeverity::Warning
117 }
118
119 #[turbo_tasks::function]
120 fn source(&self) -> Vc<OptionIssueSource> {
121 Vc::cell(Some(self.source))
122 }
123}