vue_compiler_core/transformer/
pass.rs1use super::{BaseInfo, BaseTransformer, BaseVNode, ConvertInfo, CoreTransformer, IRRoot, Js, C};
2use crate::Name;
3use rustc_hash::FxHashMap;
4
5pub trait CorePass<T: ConvertInfo> {
6 fn enter_root(&mut self, _: &mut IRRoot<T>) {}
7 fn exit_root(&mut self, _: &mut IRRoot<T>) {}
8 fn enter_text(&mut self, _: &mut C::TextIR<T>) {}
9 fn exit_text(&mut self, _: &mut C::TextIR<T>) {}
10 fn enter_if(&mut self, _: &mut C::IfNodeIR<T>) {}
11 fn exit_if(&mut self, _: &mut C::IfNodeIR<T>) {}
12 fn enter_for(&mut self, _: &mut C::ForNodeIR<T>) {}
13 fn exit_for(&mut self, _: &mut C::ForNodeIR<T>) {}
14 fn enter_vnode(&mut self, _: &mut C::VNodeIR<T>) {}
15 fn exit_vnode(&mut self, _: &mut C::VNodeIR<T>) {}
16 fn enter_slot_outlet(&mut self, _: &mut C::RenderSlotIR<T>) {}
17 fn exit_slot_outlet(&mut self, _: &mut C::RenderSlotIR<T>) {}
18 fn enter_v_slot(&mut self, _: &mut C::VSlotIR<T>) {}
19 fn exit_v_slot(&mut self, _: &mut C::VSlotIR<T>) {}
20 fn enter_slot_fn(&mut self, _: &mut C::Slot<T>) {}
21 fn exit_slot_fn(&mut self, _: &mut C::Slot<T>) {}
22 fn enter_js_expr(&mut self, _: &mut T::JsExpression) {}
23 fn exit_js_expr(&mut self, _: &mut T::JsExpression) {}
24 fn enter_fn_param(&mut self, _: &mut T::JsExpression) {}
26 fn exit_fn_param(&mut self, _: &mut T::JsExpression) {}
28 fn enter_comment(&mut self, _: &mut T::CommentType) {}
29 fn exit_comment(&mut self, _: &mut T::CommentType) {}
30}
31
32pub struct MergedPass<'b, P> {
34 passes: &'b mut [P],
35}
36
37impl<'b, P> MergedPass<'b, P> {
38 pub fn new(passes: &'b mut [P]) -> Self {
39 Self { passes }
40 }
41 fn enter<F>(&mut self, mut f: F)
42 where
43 F: FnMut(&mut P),
44 {
45 for p in &mut self.passes.iter_mut() {
46 f(p)
47 }
48 }
49 fn exit<F>(&mut self, mut f: F)
50 where
51 F: FnMut(&mut P),
52 {
53 for p in self.passes.iter_mut().rev() {
54 f(p)
55 }
56 }
57}
58
59impl<'b, T> CorePass<T> for MergedPass<'b, &'b mut dyn CorePass<T>>
60where
61 T: ConvertInfo,
62{
63 fn enter_root(&mut self, r: &mut IRRoot<T>) {
64 self.enter(|p| p.enter_root(r))
65 }
66 fn exit_root(&mut self, r: &mut IRRoot<T>) {
67 self.exit(|p| p.exit_root(r))
68 }
69 fn enter_text(&mut self, t: &mut C::TextIR<T>) {
70 self.enter(|p| p.enter_text(t))
71 }
72 fn exit_text(&mut self, t: &mut C::TextIR<T>) {
73 self.exit(|p| p.exit_text(t))
74 }
75 fn enter_if(&mut self, i: &mut C::IfNodeIR<T>) {
76 self.enter(|p| p.enter_if(i))
77 }
78 fn exit_if(&mut self, i: &mut C::IfNodeIR<T>) {
79 self.exit(|p| p.exit_if(i))
80 }
81 fn enter_for(&mut self, f: &mut C::ForNodeIR<T>) {
82 self.enter(|p| p.enter_for(f))
83 }
84 fn exit_for(&mut self, f: &mut C::ForNodeIR<T>) {
85 self.exit(|p| p.exit_for(f))
86 }
87 fn enter_vnode(&mut self, v: &mut C::VNodeIR<T>) {
88 self.enter(|p| p.enter_vnode(v))
89 }
90 fn exit_vnode(&mut self, v: &mut C::VNodeIR<T>) {
91 self.exit(|p| p.exit_vnode(v))
92 }
93 fn enter_slot_outlet(&mut self, r: &mut C::RenderSlotIR<T>) {
94 self.enter(|p| p.enter_slot_outlet(r))
95 }
96 fn exit_slot_outlet(&mut self, r: &mut C::RenderSlotIR<T>) {
97 self.exit(|p| p.exit_slot_outlet(r))
98 }
99 fn enter_v_slot(&mut self, s: &mut C::VSlotIR<T>) {
100 self.enter(|p| p.enter_v_slot(s))
101 }
102 fn exit_v_slot(&mut self, s: &mut C::VSlotIR<T>) {
103 self.exit(|p| p.exit_v_slot(s))
104 }
105 fn enter_slot_fn(&mut self, s: &mut C::Slot<T>) {
106 self.enter(|p| p.enter_slot_fn(s))
107 }
108 fn exit_slot_fn(&mut self, s: &mut C::Slot<T>) {
109 self.exit(|p| p.exit_slot_fn(s))
110 }
111 fn enter_js_expr(&mut self, e: &mut T::JsExpression) {
112 self.enter(|p| p.enter_js_expr(e))
113 }
114 fn exit_js_expr(&mut self, e: &mut T::JsExpression) {
115 self.exit(|p| p.exit_js_expr(e))
116 }
117 fn enter_fn_param(&mut self, m: &mut T::JsExpression) {
118 self.enter(|p| p.enter_fn_param(m))
119 }
120 fn exit_fn_param(&mut self, m: &mut T::JsExpression) {
121 self.exit(|p| p.exit_fn_param(m))
122 }
123 fn enter_comment(&mut self, c: &mut T::CommentType) {
124 self.enter(|p| p.enter_comment(c))
125 }
126 fn exit_comment(&mut self, c: &mut T::CommentType) {
127 self.exit(|p| p.exit_comment(c))
128 }
129}
130
131pub trait CorePassExt<T: ConvertInfo, Shared> {
132 fn enter_js_expr(&mut self, _: &mut T::JsExpression, _: &mut Shared) {}
133 fn exit_js_expr(&mut self, _: &mut T::JsExpression, _: &mut Shared) {}
134 fn enter_fn_param(&mut self, _: &mut T::JsExpression, _: &mut Shared) {}
135 fn exit_fn_param(&mut self, _: &mut T::JsExpression, _: &mut Shared) {}
136
137 fn enter_vnode(&mut self, _: &mut C::VNodeIR<T>, _: &mut Shared) {}
138 fn exit_vnode(&mut self, _: &mut C::VNodeIR<T>, _: &mut Shared) {}
139}
140
141type Identifiers<'a> = FxHashMap<Name<'a>, usize>;
142#[derive(Default)]
143pub struct Scope<'a> {
144 pub identifiers: Identifiers<'a>,
145}
146
147impl<'a> Scope<'a> {
154 pub fn has_identifier(&self, id: Name<'a>) -> bool {
155 self.identifiers.contains_key(id)
156 }
157 pub fn add_identifier(&mut self, id: Name<'a>) {
158 *self.identifiers.entry(id).or_default() += 1;
159 }
160 pub fn remove_identifier(&mut self, id: Name<'a>) {
161 *self.identifiers.entry(id).or_default() -= 1;
162 }
163 pub fn has_ref_in_vnode(&self, node: &mut BaseVNode<'a>) -> bool {
164 if self.identifiers.is_empty() {
165 return false;
166 }
167 let mut ref_finder = RefFinder(&self.identifiers, false);
168 BaseTransformer::transform_vnode(node, &mut ref_finder);
169 ref_finder.1
170 }
171}
172struct RefFinder<'a, 'b>(&'b Identifiers<'a>, bool);
173impl<'a, 'b> CorePass<BaseInfo<'a>> for RefFinder<'a, 'b> {
180 fn enter_js_expr(&mut self, e: &mut Js<'a>) {
181 if let Js::Simple(e, _) = e {
182 if self.0.contains_key(e.raw) {
183 self.1 = true;
184 }
185 }
186 }
187}
188
189pub struct SharedInfoPasses<'b, Pass, Shared> {
190 pub passes: MergedPass<'b, Pass>,
191 pub shared_info: Shared,
192}
193impl<'b, T, Shared> CorePass<T> for SharedInfoPasses<'b, &'b mut dyn CorePassExt<T, Shared>, Shared>
195where
196 T: ConvertInfo,
197{
198 fn enter_js_expr(&mut self, e: &mut T::JsExpression) {
199 let shared = &mut self.shared_info;
200 self.passes.enter(|p| p.enter_js_expr(e, shared));
201 }
202 fn exit_js_expr(&mut self, e: &mut T::JsExpression) {
203 let shared = &mut self.shared_info;
204 self.passes.exit(|p| p.exit_js_expr(e, shared));
205 }
206 fn enter_fn_param(&mut self, prm: &mut T::JsExpression) {
207 let shared = &mut self.shared_info;
208 self.passes.enter(|p| p.enter_fn_param(prm, shared));
209 }
210 fn exit_fn_param(&mut self, prm: &mut T::JsExpression) {
211 let shared = &mut self.shared_info;
212 self.passes.exit(|p| p.exit_fn_param(prm, shared));
213 }
214 fn enter_vnode(&mut self, v: &mut C::VNodeIR<T>) {
215 let shared = &mut self.shared_info;
216 self.passes.enter(|p| p.enter_vnode(v, shared))
217 }
218 fn exit_vnode(&mut self, v: &mut C::VNodeIR<T>) {
219 let shared = &mut self.shared_info;
220 self.passes.exit(|p| p.exit_vnode(v, shared))
221 }
222}