swc_plugin_proxy/source_map/
plugin_source_map_proxy.rs1#![allow(unused_imports)]
2#![allow(unused_variables)]
3#[cfg(feature = "__plugin_mode")]
4use swc_common::{
5 source_map::{
6 DistinctSources, FileLinesResult, MalformedSourceMapPositions, PartialFileLinesResult,
7 PartialLoc, SmallPos, SpanSnippetError,
8 },
9 sync::Lrc,
10 BytePos, FileName, Loc, SourceFileAndBytePos, SourceMapper, Span,
11};
12use swc_common::{sync::OnceCell, CharPos, FileLines, SourceFile};
13#[cfg(feature = "__plugin_mode")]
14use swc_ecma_ast::SourceMapperExt;
15use swc_trace_macro::swc_trace;
16
17#[cfg(all(feature = "__rkyv", feature = "__plugin_mode", target_arch = "wasm32"))]
18use crate::memory_interop::read_returned_result_from_host;
19
20#[cfg(target_arch = "wasm32")]
21extern "C" {
22 fn __lookup_char_pos_source_map_proxy(
23 byte_pos: u32,
24 should_include_source_file: i32,
25 allocated_ret_ptr: u32,
26 ) -> u32;
27 fn __doctest_offset_line_proxy(orig: u32) -> u32;
28 fn __merge_spans_proxy(
29 lhs_lo: u32,
30 lhs_hi: u32,
31 rhs_lo: u32,
32 rhs_hi: u32,
33 allocated_ptr: u32,
34 ) -> u32;
35 fn __span_to_string_proxy(span_lo: u32, span_hi: u32, allocated_ret_ptr: u32) -> u32;
36 fn __span_to_filename_proxy(span_lo: u32, span_hi: u32, allocated_ret_ptr: u32) -> u32;
37 fn __span_to_source_proxy(span_lo: u32, span_hi: u32, allocated_ret_ptr: u32) -> u32;
38 fn __span_to_lines_proxy(
39 span_lo: u32,
40 span_hi: u32,
41 should_request_source_file: i32,
42 allocated_ret_ptr: u32,
43 ) -> u32;
44 fn __lookup_byte_offset_proxy(byte_pos: u32, allocated_ret_ptr: u32) -> u32;
45}
46
47#[cfg(feature = "__plugin_mode")]
48#[derive(Debug, Clone)]
49pub struct PluginSourceMapProxy {
50 pub source_file: OnceCell<swc_common::sync::Lrc<SourceFile>>,
54}
55
56#[cfg(all(feature = "__rkyv", feature = "__plugin_mode", target_arch = "wasm32"))]
57#[swc_trace]
58impl PluginSourceMapProxy {
59 pub fn span_to_source<F, Ret>(
60 &self,
61 sp: Span,
62 extract_source: F,
63 ) -> Result<Ret, Box<SpanSnippetError>>
64 where
65 F: FnOnce(&str, usize, usize) -> Ret,
66 {
67 #[cfg(target_arch = "wasm32")]
68 {
69 let src: Result<String, Box<SpanSnippetError>> =
70 read_returned_result_from_host(|serialized_ptr| unsafe {
71 __span_to_source_proxy(sp.lo.0, sp.hi.0, serialized_ptr)
72 })
73 .expect("Host should return source code");
74
75 let src = src?;
76 return Ok(extract_source(&src, 0, src.len()));
77 }
78
79 #[cfg(not(target_arch = "wasm32"))]
80 unimplemented!("Sourcemap proxy cannot be called in this context")
81 }
82}
83
84#[cfg(feature = "__plugin_mode")]
87impl SourceMapper for PluginSourceMapProxy {
88 #[cfg_attr(not(target_arch = "wasm32"), allow(unused))]
89 fn lookup_char_pos(&self, pos: BytePos) -> Loc {
90 #[cfg(target_arch = "wasm32")]
91 {
92 let should_request_source_file = if self.source_file.get().is_none() {
93 1
94 } else {
95 0
96 };
97 let partial_loc: PartialLoc = read_returned_result_from_host(|serialized_ptr| unsafe {
98 __lookup_char_pos_source_map_proxy(
99 pos.0,
100 should_request_source_file,
101 serialized_ptr,
102 )
103 })
104 .expect("Host should return PartialLoc");
105
106 if self.source_file.get().is_none() {
107 if let Some(source_file) = partial_loc.source_file {
108 self.source_file
109 .set(source_file)
110 .expect("Should able to set source file");
111 }
112 }
113
114 return Loc {
115 file: self
116 .source_file
117 .get()
118 .expect("SourceFile should exist")
119 .clone(),
120 line: partial_loc.line,
121 col: CharPos(partial_loc.col),
122 col_display: partial_loc.col_display,
123 };
124 }
125
126 #[cfg(not(target_arch = "wasm32"))]
127 unimplemented!("Sourcemap proxy cannot be called in this context")
128 }
129
130 fn span_to_lines(&self, sp: Span) -> FileLinesResult {
131 #[cfg(target_arch = "wasm32")]
132 {
133 let should_request_source_file = if self.source_file.get().is_none() {
134 1
135 } else {
136 0
137 };
138 let partial_files: PartialFileLinesResult =
139 read_returned_result_from_host(|serialized_ptr| unsafe {
140 __span_to_lines_proxy(
141 sp.lo.0,
142 sp.hi.0,
143 should_request_source_file,
144 serialized_ptr,
145 )
146 })
147 .expect("Host should return PartialFileLinesResult");
148
149 if self.source_file.get().is_none() {
150 if let Ok(p) = &partial_files {
151 if let Some(source_file) = &p.file {
152 self.source_file
153 .set(source_file.clone())
154 .expect("Should able to set source file");
155 }
156 }
157 }
158
159 return partial_files.map(|files| FileLines {
160 file: self
161 .source_file
162 .get()
163 .expect("SourceFile should exist")
164 .clone(),
165 lines: files.lines,
166 });
167 }
168
169 #[cfg(not(target_arch = "wasm32"))]
170 unimplemented!("Sourcemap proxy cannot be called in this context")
171 }
172
173 fn span_to_string(&self, sp: Span) -> String {
174 #[cfg(target_arch = "wasm32")]
175 return read_returned_result_from_host(|serialized_ptr| unsafe {
176 __span_to_string_proxy(sp.lo.0, sp.hi.0, serialized_ptr)
177 })
178 .expect("Host should return String");
179
180 #[cfg(not(target_arch = "wasm32"))]
181 unimplemented!("Sourcemap proxy cannot be called in this context")
182 }
183
184 fn span_to_filename(&self, sp: Span) -> Lrc<FileName> {
185 #[cfg(target_arch = "wasm32")]
186 return Lrc::new(
187 read_returned_result_from_host(|serialized_ptr| unsafe {
188 __span_to_filename_proxy(sp.lo.0, sp.hi.0, serialized_ptr)
189 })
190 .expect("Host should return Filename"),
191 );
192
193 #[cfg(not(target_arch = "wasm32"))]
194 unimplemented!("Sourcemap proxy cannot be called in this context")
195 }
196
197 fn span_to_snippet(&self, sp: Span) -> Result<String, Box<SpanSnippetError>> {
198 #[cfg(target_arch = "wasm32")]
199 return self.span_to_source(sp, |src, start_index, end_index| {
200 src[start_index..end_index].to_string()
201 });
202
203 #[cfg(not(target_arch = "wasm32"))]
204 unimplemented!("Sourcemap proxy cannot be called in this context")
205 }
206
207 fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span> {
208 #[cfg(target_arch = "wasm32")]
209 unsafe {
210 let span = Span {
212 lo: BytePos(0),
213 hi: BytePos(0),
214 };
215
216 let serialized = swc_common::plugin::serialized::PluginSerializedBytes::try_serialize(
217 &swc_common::plugin::serialized::VersionedSerializable::new(span),
218 )
219 .expect("Should be serializable");
220 let (ptr, len) = serialized.as_ptr();
221
222 let ret =
223 __merge_spans_proxy(sp_lhs.lo.0, sp_lhs.hi.0, sp_rhs.lo.0, sp_rhs.hi.0, ptr as _);
224
225 return if ret == 1 { Some(span) } else { None };
226 };
227
228 #[cfg(not(target_arch = "wasm32"))]
229 unimplemented!("Sourcemap proxy cannot be called in this context")
230 }
231
232 fn call_span_if_macro(&self, sp: Span) -> Span {
233 sp
236 }
237
238 fn doctest_offset_line(&self, line: usize) -> usize {
239 #[cfg(target_arch = "wasm32")]
240 unsafe {
241 return __doctest_offset_line_proxy(line as u32) as usize;
242 };
243
244 #[cfg(not(target_arch = "wasm32"))]
245 unimplemented!("Sourcemap proxy cannot be called in this context")
246 }
247}
248
249#[cfg(feature = "__plugin_mode")]
250impl SourceMapperExt for PluginSourceMapProxy {
251 fn get_code_map(&self) -> &dyn SourceMapper {
252 self
253 }
254}