1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/// **Don't use this**
#[doc(hidden)]
pub extern crate abi_stable;
/// **Don't use this**
#[doc(hidden)]
pub extern crate swc_common;
/// **Don't use this**
#[doc(hidden)]
pub extern crate swc_ecma_plugin_ast;
/// Fix malloc.
extern crate swc_node_base;

use abi_stable::std_types::{RResult, RStr, RString};
use anyhow::Context;
use rplugin::StableAst;
use serde::de::DeserializeOwned;
/// Reexported for convenience.
pub use swc_plugin_js_api::*;

#[doc(hidden)]
pub fn invoke_js_plugin<C, F>(
    rt: swc_common::plugin::Runtime,
    op: fn(C) -> F,
    config_json: RStr,
    ast: swc_ecma_plugin_ast::Program,
) -> RResult<swc_ecma_plugin_ast::Program, RString>
where
    C: DeserializeOwned,
    F: swc_ecma_visit::Fold,
{
    use swc_ecma_visit::FoldWith;

    let config = serde_json::from_str(config_json.as_str())
        .context("failed to deserialize config string as json");
    let config: C = match config {
        Ok(v) => v,
        Err(err) => return RResult::RErr(format!("{:?}", err).into()),
    };

    swc_common::plugin::with_runtime(&rt, || {
        let ast = ast.into_unstable();

        let mut tr = op(config);

        let ast = ast.fold_with(&mut tr);

        let res = StableAst::from_unstable(ast);

        RResult::ROk(res)
    })
}

#[macro_export]
macro_rules! define_js_plugin {
    ($fn_name:ident) => {
        #[abi_stable::export_root_module]
        pub fn swc_library() -> $crate::SwcJsPluginRef {
            extern "C" fn swc_js_plugin(
                rt: $crate::swc_common::plugin::Runtime,
                config_json: $crate::abi_stable::std_types::RStr,
                ast: $crate::swc_ecma_plugin_ast::Program,
            ) -> $crate::abi_stable::std_types::RResult<
                $crate::swc_ecma_plugin_ast::Program,
                $crate::abi_stable::std_types::RString,
            > {
                $crate::invoke_js_plugin(rt, $fn_name, config_json, ast)
            }
            use $crate::abi_stable::prefix_type::PrefixTypeTrait;

            $crate::SwcJsPlugin {
                process_js: Some(swc_js_plugin),
            }
            .leak_into_prefix()
        }
    };
}