1

I'm trying to compile js/ts inside the Rust code [with SWC][1].

I'm using the following code, but I get an error (see below):

use std::{path::Path, sync::Arc};
use swc::{self, config::Options};
use swc_common::{
    GLOBALS,
    errors::{ColorConfig, Handler},
    SourceMap,
};

fn main(){
    let cm = Arc::::default();
    let handler = Handler::with_tty_emitter(
        ColorConfig::Auto,
        true,
        false,
        Some(cm.clone(),
    ));
    let compiler = swc::Compiler::new(cm.clone());

    let fm = cm
        // filepath that actually exists relative to the binary
        .load_file(Path::new("./script/some.js"))
        .expect("failed to load file");
    
    let result:Result = compiler.process_js_file(
        fm,
        &handler,
        &Options {
            ..Default::default()
        }
    )
    .expect("failed to process file");

}

Error:
thread 'main' panicked at 'swc_common::GLOBALS is required for this operation', /usr/local/cargo/git/checkouts/swc-594f88c93b4170b2/bed73c1/crates/swc/src/lib.rs:255:9
note: with 'RUST_BACKTRACE=1' environment variable set

thread 'main' panicked at '`swc_common::GLOBALS` is required for this operation', /usr/local/cargo/git/checkouts/swc-594f88c93b4170b2/bed73c1/crates/swc/src/lib.rs:255:9
stack backtrace:
   0:     0xaaaaeb751154 - std::backtrace_rs::backtrace::libunwind::trace::h29e1f4605719d2e4
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1:     0xaaaaeb751154 - std::backtrace_rs::backtrace::trace_unsynchronized::he71b8ad01d0d570d
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:     0xaaaaeb751154 - std::sys_common::backtrace::_print_fmt::h1a25e796dd9d10de
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/sys_common/backtrace.rs:65:5
   3:     0xaaaaeb751154 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h74e43b24d2f03798
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/sys_common/backtrace.rs:44:22
   4:     0xaaaaeb77c0d8 - core::fmt::rt::Argument::fmt::h7a0f275fe1c35953
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/core/src/fmt/rt.rs:138:9
   5:     0xaaaaeb77c0d8 - core::fmt::write::h1f6ba7d2fae50706
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/core/src/fmt/mod.rs:1094:21
   6:     0xaaaaeb74cbd0 - std::io::Write::write_fmt::h70da0dc2053df60e
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/io/mod.rs:1714:15
   7:     0xaaaaeb750fa4 - std::sys_common::backtrace::_print::h2f20f17fc8b14ff4
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/sys_common/backtrace.rs:47:5
   8:     0xaaaaeb750fa4 - std::sys_common::backtrace::print::h5aae444a666c7efa
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/sys_common/backtrace.rs:34:9
   9:     0xaaaaeb752758 - std::panicking::default_hook::{{closure}}::h7f5928c2248ec2b7
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/panicking.rs:269:22
  10:     0xaaaaeb7524e8 - std::panicking::default_hook::hc9afdbb6b5bcbac6
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/panicking.rs:288:9
  11:     0xaaaaeb752cfc - std::panicking::rust_panic_with_hook::h3589895b27dd44f6
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/panicking.rs:705:13
  12:     0xaaaaeb752b84 - std::panicking::begin_panic_handler::{{closure}}::h6287b145800f0df5
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/panicking.rs:595:13
  13:     0xaaaaeb751588 - std::sys_common::backtrace::__rust_end_short_backtrace::ha0f549176d54f50e
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/sys_common/backtrace.rs:151:18
  14:     0xaaaaeb752920 - rust_begin_unwind
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/panicking.rs:593:5
  15:     0xaaaae915296c - core::panicking::panic_fmt::h494f82afdbccfc22
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/core/src/panicking.rs:67:14
  16:     0xaaaae943f900 - swc::Compiler::run::h9f8ae82ddb3dcfe7
                               at /usr/local/cargo/git/checkouts/swc-594f88c93b4170b2/bed73c1/crates/swc/src/lib.rs:255:9
  17:     0xaaaae94499ec - swc::Compiler::process_js_with_custom_pass::h0f5b9487eedbe44a
                               at /usr/local/cargo/git/checkouts/swc-594f88c93b4170b2/bed73c1/crates/swc/src/lib.rs:937:9
  18:     0xaaaae944b328 - swc::Compiler::process_js_file::h27e13817755ed776
                               at /usr/local/cargo/git/checkouts/swc-594f88c93b4170b2/bed73c1/crates/swc/src/lib.rs:994:9
  19:     0xaaaae91e9958 - actx::cool::hfc87a8c80d596f3c
                               at /home/rusty/dev/actx/src/main.rs:53:5
  20:     0xaaaae9154eb0 - actx::main::{{closure}}::h6eb56977136ad246
                               at /home/rusty/dev/actx/src/main.rs:17:5
  21:     0xaaaae91f09dc - <tokio::task::local::RunUntil<T> as core::future::future::Future>::poll::{{closure}}::hb5f2ee51996c96c0
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/task/local.rs:923:42
  22:     0xaaaae91f05d8 - tokio::task::local::LocalSet::with::{{closure}}::h45772191bd97e518
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/task/local.rs:684:13
  23:     0xaaaae91811f8 - std::thread::local::LocalKey<T>::try_with::h26b72b0500288f5e
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/thread/local.rs:270:16
  24:     0xaaaae9180f60 - std::thread::local::LocalKey<T>::with::h012313c542aff9c9
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/thread/local.rs:246:9
  25:     0xaaaae91f0524 - tokio::task::local::LocalSet::with::h917340a9373dc68b
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/task/local.rs:667:9
  26:     0xaaaae91f095c - <tokio::task::local::RunUntil<T> as core::future::future::Future>::poll::h319708c12c7eae4b
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/task/local.rs:913:9
  27:     0xaaaae91f0850 - tokio::task::local::LocalSet::run_until::{{closure}}::h70941f34694f16b9
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/task/local.rs:573:19
  28:     0xaaaae91ede10 - <core::pin::Pin<P> as core::future::future::Future>::poll::h5a85f6430aa8058c
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/core/src/future/future.rs:125:9
  29:     0xaaaae916ab1c - tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::{{closure}}::{{closure}}::h493f3f02a215fcf1
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/scheduler/current_thread.rs:651:57
  30:     0xaaaae916aa54 - tokio::runtime::coop::with_budget::h67fe7f48c974afc1
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/coop.rs:107:5
  31:     0xaaaae916aa54 - tokio::runtime::coop::budget::h434a9208d3e3b849
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/coop.rs:73:5
  32:     0xaaaae916aa54 - tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::{{closure}}::h23259697b079583d
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/scheduler/current_thread.rs:651:25
  33:     0xaaaae91699d8 - tokio::runtime::scheduler::current_thread::Context::enter::hd85249b93d1dae5c
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/scheduler/current_thread.rs:410:19
  34:     0xaaaae916a340 - tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::h3c9cb6042a7958f0
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/scheduler/current_thread.rs:650:36
  35:     0xaaaae916a114 - tokio::runtime::scheduler::current_thread::CoreGuard::enter::{{closure}}::hec9ca8a44a59cb61
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/scheduler/current_thread.rs:729:68
  36:     0xaaaae920b3d0 - tokio::runtime::context::scoped::Scoped<T>::set::h89d76d991c6391b5
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/context/scoped.rs:40:9
  37:     0xaaaae91e1f1c - tokio::runtime::context::set_scheduler::{{closure}}::hd22cb414275e29c7
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/context.rs:176:26
  38:     0xaaaae9181518 - std::thread::local::LocalKey<T>::try_with::h33249708ce3a18a2
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/thread/local.rs:270:16
  39:     0xaaaae9180fa8 - std::thread::local::LocalKey<T>::with::h247897245c4f8c12
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/thread/local.rs:246:9
  40:     0xaaaae91e1ee0 - tokio::runtime::context::set_scheduler::hc4d03946207a8e0c
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/context.rs:176:9
  41:     0xaaaae9169f3c - tokio::runtime::scheduler::current_thread::CoreGuard::enter::hcc6d2ab1d6af840b
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/scheduler/current_thread.rs:729:27
  42:     0xaaaae916a140 - tokio::runtime::scheduler::current_thread::CoreGuard::block_on::h7ea3793b6e6609da
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/scheduler/current_thread.rs:638:19
  43:     0xaaaae91692e4 - tokio::runtime::scheduler::current_thread::CurrentThread::block_on::{{closure}}::hae52c2bb8cb038c7
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/scheduler/current_thread.rs:175:28
  44:     0xaaaae91e4990 - tokio::runtime::context::runtime::enter_runtime::hbae7837926e42665
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/context/runtime.rs:65:16
  45:     0xaaaae9169208 - tokio::runtime::scheduler::current_thread::CurrentThread::block_on::h012e33ed4477a2e7
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/scheduler/current_thread.rs:167:9
  46:     0xaaaae918b468 - tokio::runtime::runtime::Runtime::block_on::h60fc904760608829
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/runtime.rs:311:47
  47:     0xaaaae91f0678 - tokio::task::local::LocalSet::block_on::hc5eb9e67084d7546
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/task/local.rs:534:9
  48:     0xaaaae91fe170 - actix_rt::runtime::Runtime::block_on::hc63313777b87480e
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/actix-rt-2.8.0/src/runtime.rs:82:9
  49:     0xaaaae91fdcd4 - actix_rt::system::SystemRunner::block_on::h57d1045222987161
                               at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/actix-rt-2.8.0/src/system.rs:210:9
  50:     0xaaaae91e9a28 - actx::main::hb0c2e21478aff8fd
                               at /home/rusty/dev/actx/src/main.rs:14:1
  51:     0xaaaae919eb5c - core::ops::function::FnOnce::call_once::hb2a4b021445f755c
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/core/src/ops/function.rs:250:5
  52:     0xaaaae91c4d20 - std::sys_common::backtrace::__rust_begin_short_backtrace::h4ae0bb585e86fa4d
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/sys_common/backtrace.rs:135:18
  53:     0xaaaae91f5ed0 - std::rt::lang_start::{{closure}}::ha1f987e326c57bf0
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/rt.rs:166:18
  54:     0xaaaaeb743e54 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::hdc7e7cd29b9502aa
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/core/src/ops/function.rs:284:13
  55:     0xaaaaeb743e54 - std::panicking::try::do_call::h03ba75425057198b
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/panicking.rs:500:40
  56:     0xaaaaeb743e54 - std::panicking::try::h855a5f887203d91d
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/panicking.rs:464:19
  57:     0xaaaaeb743e54 - std::panic::catch_unwind::h332d9138399b1db1
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/panic.rs:142:14
  58:     0xaaaaeb743e54 - std::rt::lang_start_internal::{{closure}}::h5eb351882112c211
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/rt.rs:148:48
  59:     0xaaaaeb743e54 - std::panicking::try::do_call::hf5d1a2f53e99b086
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/panicking.rs:500:40
  60:     0xaaaaeb743e54 - std::panicking::try::h1702a70632694473
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/panicking.rs:464:19
  61:     0xaaaaeb743e54 - std::panic::catch_unwind::hca4d61db01aa86a4
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/panic.rs:142:14
  62:     0xaaaaeb743e54 - std::rt::lang_start_internal::h0ce084e83a02d16d
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/rt.rs:148:20
  63:     0xaaaae91f5ea0 - std::rt::lang_start::hfcc787e7b0b10d0a
                               at /rustc/ad963232d9b987d66a6f8e6ec4141f672b8b9900/library/std/src/rt.rs:165:17
  64:     0xaaaae91e9aa4 - main
  65:     0xffffb1428e18 - __libc_start_main
  66:     0xaaaae9152fc4 - <unknown>

1 Answers1

0

You need to run your code inside a closure passed to GLOBALS.set().

Ex.

let result = GLOBALS.set(&Default::default(), || {
    compiler.process_js_file(
        fm,
        &handler,
        &Options {
            ..Default::default()
        }
    )
    .expect("failed to process file")
});

Here's a full an example of TypeScript to JavaScript transformation using the SWC high level APIs

use std::io;

use swc::{
    config::{IsModule, SourceMapsConfig},
    Compiler,
};
use swc_common::{errors::Handler, source_map::SourceMap, sync::Lrc, Mark, GLOBALS};
use swc_ecma_ast::EsVersion;
use swc_ecma_parser::Syntax;
use swc_ecma_transforms_typescript::strip;
use swc_ecma_visit::FoldWith;

/// Transforms typescript to javascript. Returns tuple (js string, source map)
fn ts_to_js(filename: &str, ts_code: &str) -> (String, String) {
    let cm = Lrc::new(SourceMap::new(swc_common::FilePathMapping::empty()));

    let compiler = Compiler::new(cm.clone());

    let source = cm.new_source_file(
        swc_common::FileName::Custom(filename.into()),
        ts_code.to_string(),
    );

    let handler = Handler::with_emitter_writer(Box::new(io::stderr()), Some(compiler.cm.clone()));

    return GLOBALS.set(&Default::default(), || {
        let res = compiler
            .parse_js(
                source,
                &handler,
                EsVersion::Es5,
                Syntax::Typescript(Default::default()),
                IsModule::Bool(true),
                Some(compiler.comments()),
            )
            .expect("parse_js failed");

        let module = res.module().unwrap();

        // Add TypeScript type stripping transform
        let top_level_mark = Mark::new();
        let module = module.fold_with(&mut strip(top_level_mark));

        // https://rustdoc.swc.rs/swc/struct.Compiler.html#method.print
        let ret = compiler
            .print(
                &module,                      // ast to print
                None,                         // source file name
                None,                         // output path
                false,                        // inline sources content
                EsVersion::EsNext,            // target ES version
                SourceMapsConfig::Bool(true), // source map config
                &Default::default(),          // source map names
                None,                         // original source map
                false,                        // minify
                Some(compiler.comments()),    // comments
                false,                        // emit source map columns
                false,                        // ascii only
                "",                           // preable
            )
            .expect("print failed");

        return (ret.code, ret.map.expect("no source map"));
    });
}

Usage

fn main() {
    let (js, sourcemap) = ts_to_js(
        "hello.ts",
        r#"

        interface Args {
            name: string;
         }

        function hello(param: Args) {
            // comment
            console.log(`Hello ${param.name}!`);
        }
        "#,
    );

    println!("{}", js);
    println!("{}", sourcemap);
}

Which prints

function hello(param) {
    // comment
    console.log(`Hello ${param.name}!`);
}

{"version":3,"sources":["hello.ts"],"names":[],"mappings":"AAMQ,SAAS,MAAM,KAAW;IACtB,UAAU;IACV,QAAQ,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC;AACtC"}

There is also an example in the swc github repo:

https://github.com/swc-project/swc/blob/875a7a7393c23774453e89549e92ac412ddc2e9a/crates/swc_ecma_transforms_typescript/examples/ts_to_js.rs

esamatti
  • 18,293
  • 11
  • 75
  • 82