turbopack_core/resolve/
plugin.rs1use anyhow::Result;
2use rustc_hash::FxHashSet;
3use turbo_rcstr::RcStr;
4use turbo_tasks::{ResolvedVc, Vc};
5use turbo_tasks_fs::{FileSystemPath, glob::Glob};
6
7use crate::{
8 reference_type::ReferenceType,
9 resolve::{ResolveResultOption, parse::Request},
10};
11
12#[turbo_tasks::value(shared)]
14pub enum AfterResolvePluginCondition {
15 Glob {
16 root: FileSystemPath,
17 glob: ResolvedVc<Glob>,
18 },
19 Always,
20 Never,
21}
22
23#[turbo_tasks::value_impl]
24impl AfterResolvePluginCondition {
25 #[turbo_tasks::function]
26 pub fn new_with_glob(root: FileSystemPath, glob: ResolvedVc<Glob>) -> Vc<Self> {
27 AfterResolvePluginCondition::Glob { root, glob }.cell()
28 }
29}
30
31#[turbo_tasks::value_impl]
32impl AfterResolvePluginCondition {
33 #[turbo_tasks::function]
34 pub async fn matches(&self, fs_path: FileSystemPath) -> Result<Vc<bool>> {
35 match self {
36 AfterResolvePluginCondition::Glob { root, glob } => {
37 let path = fs_path;
38
39 if let Some(path) = root.get_path_to(&path)
40 && glob.await?.matches(path)
41 {
42 return Ok(Vc::cell(true));
43 }
44
45 Ok(Vc::cell(false))
46 }
47 AfterResolvePluginCondition::Always => Ok(Vc::cell(true)),
48 AfterResolvePluginCondition::Never => Ok(Vc::cell(false)),
49 }
50 }
51}
52
53#[turbo_tasks::value(shared)]
55pub enum BeforeResolvePluginCondition {
56 Request(ResolvedVc<Glob>),
57 Modules(FxHashSet<RcStr>),
58 Always,
59 Never,
60}
61
62#[turbo_tasks::value_impl]
63impl BeforeResolvePluginCondition {
64 #[turbo_tasks::function]
65 pub async fn from_modules(modules: ResolvedVc<Vec<RcStr>>) -> Result<Vc<Self>> {
66 Ok(BeforeResolvePluginCondition::Modules(modules.await?.iter().cloned().collect()).cell())
67 }
68
69 #[turbo_tasks::function]
70 pub fn from_request_glob(glob: ResolvedVc<Glob>) -> Vc<Self> {
71 BeforeResolvePluginCondition::Request(glob).cell()
72 }
73}
74
75#[turbo_tasks::value_impl]
76impl BeforeResolvePluginCondition {
77 #[turbo_tasks::function]
78 pub async fn matches(&self, request: Vc<Request>) -> Result<Vc<bool>> {
79 Ok(Vc::cell(match self {
80 BeforeResolvePluginCondition::Request(glob) => match request.await?.request() {
81 Some(request) => glob.await?.matches(request.as_str()),
82 None => false,
83 },
84 BeforeResolvePluginCondition::Modules(modules) => {
85 if let Request::Module { module, .. } = &*request.await? {
86 modules.iter().any(|m| module.is_match(m))
87 } else {
88 false
89 }
90 }
91 BeforeResolvePluginCondition::Always => true,
92 BeforeResolvePluginCondition::Never => false,
93 }))
94 }
95}
96
97#[turbo_tasks::value_trait]
98pub trait BeforeResolvePlugin {
99 #[turbo_tasks::function]
100 fn before_resolve_condition(self: Vc<Self>) -> Vc<BeforeResolvePluginCondition>;
101
102 #[turbo_tasks::function]
103 fn before_resolve(
104 self: Vc<Self>,
105 lookup_path: FileSystemPath,
106 reference_type: ReferenceType,
107 request: Vc<Request>,
108 ) -> Vc<ResolveResultOption>;
109}
110
111#[turbo_tasks::value_trait]
112pub trait AfterResolvePlugin {
113 #[turbo_tasks::function]
115 fn after_resolve_condition(self: Vc<Self>) -> Vc<AfterResolvePluginCondition>;
116
117 #[turbo_tasks::function]
121 fn after_resolve(
122 self: Vc<Self>,
123 fs_path: FileSystemPath,
124 lookup_path: FileSystemPath,
125 reference_type: ReferenceType,
126 request: Vc<Request>,
127 ) -> Vc<ResolveResultOption>;
128}