source_map_mappings_wasm_api/
lib.rs1#![deny(missing_docs)]
25
26extern crate source_map_mappings;
27
28use source_map_mappings::{Bias, Error, Mapping, Mappings};
29use std::mem;
30use std::ptr;
31use std::process;
32use std::slice;
33
34#[cfg(feature = "profiling")]
35mod observer {
36 use source_map_mappings;
37
38 macro_rules! define_raii_observer {
39 ( $name:ident , $ctor:ident , $dtor:ident ) => {
40 #[derive(Debug)]
41 pub struct $name;
42
43 impl Default for $name {
44 #[inline]
45 fn default() -> $name {
46 extern "C" {
47 fn $ctor();
48 }
49 unsafe {
50 $ctor();
51 }
52 $name
53 }
54 }
55
56 impl Drop for $name {
57 #[inline]
58 fn drop(&mut self) {
59 extern "C" {
60 fn $dtor();
61 }
62 unsafe {
63 $dtor();
64 }
65 }
66 }
67 }
68 }
69
70 define_raii_observer!(ParseMappings, start_parse_mappings, end_parse_mappings);
71 define_raii_observer!(
72 SortByOriginalLocation,
73 start_sort_by_original_location,
74 end_sort_by_original_location
75 );
76 define_raii_observer!(
77 SortByGeneratedLocation,
78 start_sort_by_generated_location,
79 end_sort_by_generated_location
80 );
81 define_raii_observer!(
82 ComputeColumnSpans,
83 start_compute_column_spans,
84 end_compute_column_spans
85 );
86 define_raii_observer!(
87 OriginalLocationFor,
88 start_original_location_for,
89 end_original_location_for
90 );
91 define_raii_observer!(
92 GeneratedLocationFor,
93 start_generated_location_for,
94 end_generated_location_for
95 );
96 define_raii_observer!(
97 AllGeneratedLocationsFor,
98 start_all_generated_locations_for,
99 end_all_generated_locations_for
100 );
101
102 #[derive(Debug, Default)]
103 pub struct Observer;
104
105 impl source_map_mappings::Observer for Observer {
106 type ParseMappings = ParseMappings;
107 type SortByOriginalLocation = SortByOriginalLocation;
108 type SortByGeneratedLocation = SortByGeneratedLocation;
109 type ComputeColumnSpans = ComputeColumnSpans;
110 type OriginalLocationFor = OriginalLocationFor;
111 type GeneratedLocationFor = GeneratedLocationFor;
112 type AllGeneratedLocationsFor = AllGeneratedLocationsFor;
113 }
114}
115
116#[cfg(not(feature = "profiling"))]
117mod observer {
118 pub type Observer = ();
119}
120
121use observer::Observer;
122
123static mut LAST_ERROR: Option<Error> = None;
124
125#[no_mangle]
129pub extern "C" fn get_last_error() -> u32 {
130 unsafe {
131 match LAST_ERROR {
132 None => 0,
133 Some(e) => e as u32,
134 }
135 }
136}
137
138#[inline]
139fn assert_pointer_is_word_aligned(p: *mut u8) {
140 debug_assert_eq!(p as usize & (mem::size_of::<usize>() - 1), 0);
141}
142
143#[no_mangle]
149pub extern "C" fn allocate_mappings(size: usize) -> *mut u8 {
150 let size_in_units_of_usize = (size + mem::size_of::<usize>() - 1) / mem::size_of::<usize>();
152
153 let mut vec: Vec<usize> = Vec::with_capacity(size_in_units_of_usize + 2);
156
157 let capacity = vec.capacity();
159 vec.push(capacity);
160 vec.push(size);
161
162 let ptr = vec.as_mut_ptr();
164 debug_assert!(!ptr.is_null());
165 mem::forget(vec);
166
167 let ptr = ptr.wrapping_offset(2) as *mut u8;
170 assert_pointer_is_word_aligned(ptr);
171 ptr
172}
173
174#[inline]
175fn constrain<'a, T>(_scope: &'a (), reference: &'a T) -> &'a T
176where
177 T: ?Sized,
178{
179 reference
180}
181
182#[no_mangle]
195pub extern "C" fn parse_mappings(mappings: *mut u8) -> *mut Mappings<Observer> {
196 assert_pointer_is_word_aligned(mappings);
197 let mappings = mappings as *mut usize;
198
199 let capacity_ptr = mappings.wrapping_offset(-2);
202 debug_assert!(!capacity_ptr.is_null());
203 let capacity = unsafe { *capacity_ptr };
204
205 let size_ptr = mappings.wrapping_offset(-1);
206 debug_assert!(!size_ptr.is_null());
207 let size = unsafe { *size_ptr };
208
209 let result = unsafe {
211 let input = slice::from_raw_parts(mappings as *const u8, size);
212 let this_scope = ();
213 let input = constrain(&this_scope, input);
214 source_map_mappings::parse_mappings(input)
215 };
216
217 let size_in_usizes = (size + mem::size_of::<usize>() - 1) / mem::size_of::<usize>();
219 unsafe {
220 Vec::<usize>::from_raw_parts(capacity_ptr, size_in_usizes + 2, capacity);
221 }
222
223 match result {
226 Ok(mappings) => Box::into_raw(Box::new(mappings)),
227 Err(e) => {
228 unsafe {
229 LAST_ERROR = Some(e);
230 }
231 ptr::null_mut()
232 }
233 }
234}
235
236#[no_mangle]
240pub extern "C" fn free_mappings(mappings: *mut Mappings<Observer>) {
241 unsafe {
242 Box::from_raw(mappings);
243 }
244}
245
246#[inline]
247unsafe fn mappings_mut<'a>(
248 _scope: &'a (),
249 mappings: *mut Mappings<Observer>,
250) -> &'a mut Mappings<Observer> {
251 mappings.as_mut().unwrap()
252}
253
254extern "C" {
255 fn mapping_callback(
256 generated_line: u32,
258 generated_column: u32,
259
260 has_last_generated_column: bool,
263 last_generated_column: u32,
264
265 has_original: bool,
268 source: u32,
269 original_line: u32,
270 original_column: u32,
271
272 has_name: bool,
274 name: u32,
275 );
276}
277
278#[inline]
279unsafe fn invoke_mapping_callback(mapping: &Mapping) {
280 let generated_line = mapping.generated_line;
281 let generated_column = mapping.generated_column;
282
283 let (has_last_generated_column, last_generated_column) =
284 if let Some(last_generated_column) = mapping.last_generated_column {
285 (true, last_generated_column)
286 } else {
287 (false, 0)
288 };
289
290 let (has_original, source, original_line, original_column, has_name, name) =
291 if let Some(original) = mapping.original.as_ref() {
292 let (has_name, name) = if let Some(name) = original.name {
293 (true, name)
294 } else {
295 (false, 0)
296 };
297
298 (
299 true,
300 original.source,
301 original.original_line,
302 original.original_column,
303 has_name,
304 name,
305 )
306 } else {
307 (false, 0, 0, 0, false, 0)
308 };
309
310 mapping_callback(
311 generated_line,
312 generated_column,
313 has_last_generated_column,
314 last_generated_column,
315 has_original,
316 source,
317 original_line,
318 original_column,
319 has_name,
320 name,
321 );
322}
323
324#[no_mangle]
327pub extern "C" fn by_generated_location(mappings: *mut Mappings<Observer>) {
328 let this_scope = ();
329 let mappings = unsafe { mappings_mut(&this_scope, mappings) };
330
331 mappings
332 .by_generated_location()
333 .iter()
334 .for_each(|m| unsafe {
335 invoke_mapping_callback(m);
336 });
337}
338
339#[no_mangle]
341pub extern "C" fn compute_column_spans(mappings: *mut Mappings<Observer>) {
342 let this_scope = ();
343 let mappings = unsafe { mappings_mut(&this_scope, mappings) };
344
345 mappings.compute_column_spans();
346}
347
348#[no_mangle]
352pub extern "C" fn by_original_location(mappings: *mut Mappings<Observer>) {
353 let this_scope = ();
354 let mappings = unsafe { mappings_mut(&this_scope, mappings) };
355
356 mappings.by_original_location().for_each(|m| unsafe {
357 invoke_mapping_callback(m);
358 });
359}
360
361#[inline]
362fn u32_to_bias(bias: u32) -> Bias {
363 match bias {
364 1 => Bias::GreatestLowerBound,
365 2 => Bias::LeastUpperBound,
366 otherwise => if cfg!(debug_assertions) {
367 panic!(
368 "Invalid `Bias = {}`; must be `Bias::GreatestLowerBound = {}` or \
369 `Bias::LeastUpperBound = {}`",
370 otherwise,
371 Bias::GreatestLowerBound as u32,
372 Bias::LeastUpperBound as u32,
373 )
374 } else {
375 process::abort()
376 },
377 }
378}
379
380#[no_mangle]
385pub extern "C" fn original_location_for(
386 mappings: *mut Mappings<Observer>,
387 generated_line: u32,
388 generated_column: u32,
389 bias: u32,
390) {
391 let this_scope = ();
392 let mappings = unsafe { mappings_mut(&this_scope, mappings) };
393 let bias = u32_to_bias(bias);
394
395 if let Some(m) = mappings.original_location_for(generated_line, generated_column, bias) {
396 unsafe {
397 invoke_mapping_callback(m);
398 }
399 }
400}
401
402#[no_mangle]
407pub extern "C" fn generated_location_for(
408 mappings: *mut Mappings<Observer>,
409 source: u32,
410 original_line: u32,
411 original_column: u32,
412 bias: u32,
413) {
414 let this_scope = ();
415 let mappings = unsafe { mappings_mut(&this_scope, mappings) };
416 let bias = u32_to_bias(bias);
417
418 if let Some(m) = mappings.generated_location_for(source, original_line, original_column, bias) {
419 unsafe {
420 invoke_mapping_callback(m);
421 }
422 }
423}
424
425#[no_mangle]
435pub extern "C" fn all_generated_locations_for(
436 mappings: *mut Mappings<Observer>,
437 source: u32,
438 original_line: u32,
439 has_original_column: bool,
440 original_column: u32,
441) {
442 let this_scope = ();
443 let mappings = unsafe { mappings_mut(&this_scope, mappings) };
444
445 let original_column = if has_original_column {
446 Some(original_column)
447 } else {
448 None
449 };
450
451 for m in mappings.all_generated_locations_for(source, original_line, original_column) {
452 unsafe {
453 invoke_mapping_callback(m);
454 }
455 }
456}