swc_transform_common/
output.rs

1//! (Experimental) Output capturing.
2//!
3//! This module provides a way to emit metadata to the JS caller.
4
5use std::cell::RefCell;
6
7use better_scoped_tls::scoped_tls;
8use rustc_hash::FxHashMap;
9
10scoped_tls!(static OUTPUT: RefCell<FxHashMap<String, String>>);
11
12/// (Experimental) Captures output.
13///
14/// This is not stable and may be removed in the future.
15pub fn capture<Ret>(f: impl FnOnce() -> Ret) -> (Ret, FxHashMap<String, String>) {
16    let output = RefCell::new(Default::default());
17
18    let ret = OUTPUT.set(&output, f);
19
20    (ret, output.into_inner())
21}
22
23#[cfg(all(feature = "plugin-mode", target_arch = "wasm32"))]
24extern "C" {
25    fn __emit_output(output_ptr: u32, output_len: u32);
26}
27
28/// (Experimental) Emits a value to the JS caller.
29///
30/// This is not stable and may be removed in the future.
31#[cfg(all(feature = "plugin-mode", target_arch = "wasm32"))]
32pub fn experimental_emit(key: String, value: String) {
33    let output = (key, value);
34
35    let diag = swc_common::plugin::serialized::PluginSerializedBytes::try_serialize(
36        &swc_common::plugin::serialized::VersionedSerializable::new(output),
37    )
38    .expect("Should able to serialize String");
39    let (ptr, len) = diag.as_ptr();
40
41    unsafe {
42        __emit_output(ptr as u32, len as u32);
43    }
44}
45
46/// (Experimental) Emits a value to the JS caller.
47///
48/// This is not stable and may be removed in the future.
49#[cfg(not(all(feature = "plugin-mode", target_arch = "wasm32")))]
50pub fn experimental_emit(key: String, value: String) {
51    OUTPUT.with(|output| {
52        let previous = output.borrow_mut().insert(key, value);
53
54        if let Some(previous) = previous {
55            panic!("Key already set. Previous value: {previous:?}");
56        }
57    });
58}