swc_plugin_proxy/comments/
plugin_comments_proxy.rs

1#[cfg(feature = "__plugin_mode")]
2use swc_common::{
3    comments::{Comment, Comments},
4    BytePos,
5};
6#[cfg(feature = "__plugin_mode")]
7use swc_trace_macro::swc_trace;
8
9#[cfg(all(feature = "__rkyv", feature = "__plugin_mode", target_arch = "wasm32"))]
10use crate::memory_interop::read_returned_result_from_host;
11
12#[cfg(target_arch = "wasm32")]
13extern "C" {
14    fn __copy_comment_to_host_env(bytes_ptr: u32, bytes_ptr_len: u32);
15    fn __add_leading_comment_proxy(byte_pos: u32);
16    fn __add_leading_comments_proxy(byte_pos: u32);
17    fn __has_leading_comments_proxy(byte_pos: u32) -> u32;
18    fn __move_leading_comments_proxy(from_byte_pos: u32, to_byte_pos: u32);
19    fn __take_leading_comments_proxy(byte_pos: u32, allocated_ret_ptr: u32) -> u32;
20    fn __get_leading_comments_proxy(byte_pos: u32, allocated_ret_ptr: u32) -> u32;
21    fn __add_trailing_comment_proxy(byte_pos: u32);
22    fn __add_trailing_comments_proxy(byte_pos: u32);
23    fn __has_trailing_comments_proxy(byte_pos: u32) -> u32;
24    fn __move_trailing_comments_proxy(from_byte_pos: u32, to_byte_pos: u32);
25    fn __take_trailing_comments_proxy(byte_pos: u32, allocated_ret_ptr: u32) -> u32;
26    fn __get_trailing_comments_proxy(byte_pos: u32, allocated_ret_ptr: u32) -> u32;
27    fn __add_pure_comment_proxy(byte_pos: u32);
28}
29
30/// A struct implements `swc_common::comments::Comments` for the plugin.
31/// This is a proxy to the host's comments reference while plugin transform
32/// runs, does not contain actual data but lazily requests to the host for each
33/// interfaces.
34///
35/// This _does not_ derives serialization / deserialization for the
36/// Serialized::de/serialize interface. Instead, swc_plugin_macro injects an
37/// instance in plugin's runtime directly.
38#[cfg(feature = "__plugin_mode")]
39#[derive(Debug, Copy, Clone)]
40pub struct PluginCommentsProxy;
41
42#[cfg(feature = "__plugin_mode")]
43#[swc_trace]
44impl PluginCommentsProxy {
45    /// Copy guest memory's struct into host via CommentHostEnvironment's
46    /// comment_buffer as serialized to pass param from guest to the host for
47    /// the fn like add_leading*.
48    #[cfg_attr(not(target_arch = "wasm32"), allow(unused))]
49    fn allocate_comments_buffer_to_host<T>(&self, value: T)
50    where
51        T: for<'a> rkyv::Serialize<
52            rancor::Strategy<
53                rkyv::ser::Serializer<
54                    rkyv::util::AlignedVec,
55                    rkyv::ser::allocator::ArenaHandle<'a>,
56                    rkyv::ser::sharing::Share,
57                >,
58                rancor::Error,
59            >,
60        >,
61    {
62        #[cfg(target_arch = "wasm32")]
63        {
64            let serialized = swc_common::plugin::serialized::PluginSerializedBytes::try_serialize(
65                &swc_common::plugin::serialized::VersionedSerializable::new(value),
66            )
67            .expect("Should able to serialize value");
68            let (serialized_comment_ptr, serialized_comment_ptr_len) = serialized.as_ptr();
69            unsafe {
70                // We need to copy PluginCommentProxy's param for add_leading (Comment, or
71                // Vec<Comment>) to the host, before calling proxy to the host. This'll fill in
72                // CommentHostEnvironment's buffer, subsequent proxy call will read &
73                // deserialize it.
74                __copy_comment_to_host_env(
75                    serialized_comment_ptr as u32,
76                    serialized_comment_ptr_len
77                        .try_into()
78                        .expect("Should able to convert ptr length"),
79                );
80            }
81        }
82    }
83}
84
85#[cfg(all(feature = "__plugin_mode", not(target_arch = "wasm32")))]
86#[swc_trace]
87impl Comments for PluginCommentsProxy {
88    fn add_leading(&self, pos: BytePos, cmt: Comment) {
89        swc_common::comments::COMMENTS.with(|c| {
90            c.add_leading(pos, cmt);
91        });
92    }
93
94    fn add_leading_comments(&self, pos: BytePos, comments: Vec<Comment>) {
95        swc_common::comments::COMMENTS.with(|c| {
96            c.add_leading_comments(pos, comments);
97        });
98    }
99
100    fn has_leading(&self, pos: BytePos) -> bool {
101        swc_common::comments::COMMENTS.with(|c| c.has_leading(pos))
102    }
103
104    fn move_leading(&self, from: BytePos, to: BytePos) {
105        swc_common::comments::COMMENTS.with(|c| {
106            c.move_leading(from, to);
107        });
108    }
109
110    fn take_leading(&self, pos: BytePos) -> Option<Vec<Comment>> {
111        swc_common::comments::COMMENTS.with(|c| c.take_leading(pos))
112    }
113
114    fn get_leading(&self, pos: BytePos) -> Option<Vec<Comment>> {
115        swc_common::comments::COMMENTS.with(|c| c.get_leading(pos))
116    }
117
118    fn add_trailing(&self, pos: BytePos, cmt: Comment) {
119        swc_common::comments::COMMENTS.with(|c| {
120            c.add_trailing(pos, cmt);
121        });
122    }
123
124    fn add_trailing_comments(&self, pos: BytePos, comments: Vec<Comment>) {
125        swc_common::comments::COMMENTS.with(|c| {
126            c.add_trailing_comments(pos, comments);
127        });
128    }
129
130    fn has_trailing(&self, pos: BytePos) -> bool {
131        swc_common::comments::COMMENTS.with(|c| c.has_trailing(pos))
132    }
133
134    fn move_trailing(&self, from: BytePos, to: BytePos) {
135        swc_common::comments::COMMENTS.with(|c| {
136            c.move_trailing(from, to);
137        });
138    }
139
140    fn take_trailing(&self, pos: BytePos) -> Option<Vec<Comment>> {
141        swc_common::comments::COMMENTS.with(|c| c.take_trailing(pos))
142    }
143
144    fn get_trailing(&self, pos: BytePos) -> Option<Vec<Comment>> {
145        swc_common::comments::COMMENTS.with(|c| c.get_trailing(pos))
146    }
147
148    fn add_pure_comment(&self, pos: BytePos) {
149        swc_common::comments::COMMENTS.with(|c| {
150            c.add_pure_comment(pos);
151        });
152    }
153}
154
155#[cfg(all(feature = "__plugin_mode", target_arch = "wasm32"))]
156#[cfg_attr(not(target_arch = "wasm32"), allow(unused))]
157#[swc_trace]
158impl Comments for PluginCommentsProxy {
159    fn add_leading(&self, pos: BytePos, cmt: Comment) {
160        self.allocate_comments_buffer_to_host(cmt);
161        #[cfg(target_arch = "wasm32")]
162        unsafe {
163            __add_leading_comment_proxy(pos.0);
164        }
165    }
166
167    fn add_leading_comments(&self, pos: BytePos, comments: Vec<Comment>) {
168        self.allocate_comments_buffer_to_host(comments);
169        #[cfg(target_arch = "wasm32")]
170        unsafe {
171            __add_leading_comments_proxy(pos.0);
172        }
173    }
174
175    fn has_leading(&self, pos: BytePos) -> bool {
176        #[cfg(target_arch = "wasm32")]
177        {
178            if unsafe { __has_leading_comments_proxy(pos.0) } == 0 {
179                false
180            } else {
181                true
182            }
183        }
184        #[cfg(not(target_arch = "wasm32"))]
185        false
186    }
187
188    fn move_leading(&self, from: BytePos, to: BytePos) {
189        #[cfg(target_arch = "wasm32")]
190        unsafe {
191            __move_leading_comments_proxy(from.0, to.0)
192        }
193    }
194
195    fn take_leading(&self, pos: BytePos) -> Option<Vec<Comment>> {
196        #[cfg(target_arch = "wasm32")]
197        return read_returned_result_from_host(|serialized_ptr| unsafe {
198            __take_leading_comments_proxy(pos.0, serialized_ptr)
199        });
200
201        #[cfg(not(target_arch = "wasm32"))]
202        None
203    }
204
205    fn get_leading(&self, pos: BytePos) -> Option<Vec<Comment>> {
206        #[cfg(target_arch = "wasm32")]
207        return read_returned_result_from_host(|serialized_ptr| unsafe {
208            __get_leading_comments_proxy(pos.0, serialized_ptr)
209        });
210
211        #[cfg(not(target_arch = "wasm32"))]
212        None
213    }
214
215    fn add_trailing(&self, pos: BytePos, cmt: Comment) {
216        self.allocate_comments_buffer_to_host(cmt);
217        #[cfg(target_arch = "wasm32")]
218        unsafe {
219            __add_trailing_comment_proxy(pos.0);
220        }
221    }
222
223    fn add_trailing_comments(&self, pos: BytePos, comments: Vec<Comment>) {
224        self.allocate_comments_buffer_to_host(comments);
225        #[cfg(target_arch = "wasm32")]
226        unsafe {
227            __add_trailing_comments_proxy(pos.0);
228        }
229    }
230
231    fn has_trailing(&self, pos: BytePos) -> bool {
232        #[cfg(target_arch = "wasm32")]
233        {
234            if unsafe { __has_trailing_comments_proxy(pos.0) } == 0 {
235                false
236            } else {
237                true
238            }
239        }
240        #[cfg(not(target_arch = "wasm32"))]
241        false
242    }
243
244    fn move_trailing(&self, from: BytePos, to: BytePos) {
245        #[cfg(target_arch = "wasm32")]
246        unsafe {
247            __move_trailing_comments_proxy(from.0, to.0)
248        }
249    }
250
251    fn take_trailing(&self, pos: BytePos) -> Option<Vec<Comment>> {
252        #[cfg(target_arch = "wasm32")]
253        return read_returned_result_from_host(|serialized_ptr| unsafe {
254            __take_trailing_comments_proxy(pos.0, serialized_ptr)
255        });
256
257        #[cfg(not(target_arch = "wasm32"))]
258        None
259    }
260
261    fn get_trailing(&self, pos: BytePos) -> Option<Vec<Comment>> {
262        #[cfg(target_arch = "wasm32")]
263        return read_returned_result_from_host(|serialized_ptr| unsafe {
264            __get_trailing_comments_proxy(pos.0, serialized_ptr)
265        });
266
267        #[cfg(not(target_arch = "wasm32"))]
268        None
269    }
270
271    fn add_pure_comment(&self, pos: BytePos) {
272        #[cfg(target_arch = "wasm32")]
273        {
274            unsafe {
275                __add_pure_comment_proxy(pos.0);
276            }
277        }
278    }
279}