dbg_swc/
main.rs

1use std::{env, path::PathBuf, str::FromStr, sync::Arc};
2
3use anyhow::{bail, Error, Result};
4use clap::{StructOpt, Subcommand};
5use es::EsCommand;
6use swc_common::{
7    errors::{ColorConfig, HANDLER},
8    Globals, SourceMap, GLOBALS,
9};
10use swc_error_reporters::handler::{try_with_handler, HandlerOpts};
11use tracing_subscriber::EnvFilter;
12
13use self::util::print_js;
14use crate::util::minifier::{get_minified, get_terser_output};
15
16mod bundle;
17mod es;
18mod util;
19
20const CREDUCE_INPUT_ENV_VAR: &str = "CREDUCE_INPUT";
21
22const CREDUCE_MODE_ENV_VAR: &str = "CREDUCE_COMPARE";
23
24#[derive(Debug, clap::Parser)]
25struct AppArgs {
26    #[clap(subcommand)]
27    cmd: Cmd,
28}
29
30#[derive(Debug, Subcommand)]
31enum Cmd {
32    #[clap(subcommand)]
33    Es(EsCommand),
34}
35
36fn init() -> Result<()> {
37    let log_env =
38        env::var("RUST_LOG").unwrap_or_else(|_| "info,swc_ecma_minifier=warn,swc_timer=off".into());
39
40    let logger = tracing_subscriber::FmtSubscriber::builder()
41        .without_time()
42        .with_target(false)
43        .with_ansi(true)
44        .with_env_filter(EnvFilter::from_str(&log_env).unwrap())
45        .with_writer(std::io::stderr)
46        .pretty()
47        .finish();
48
49    tracing::subscriber::set_global_default(logger)?;
50
51    Ok(())
52}
53
54fn main() -> Result<(), Error> {
55    init()?;
56
57    let cm = Arc::new(SourceMap::default());
58
59    if let Ok(mode) = env::var(CREDUCE_MODE_ENV_VAR) {
60        return try_with_handler(
61            cm.clone(),
62            HandlerOpts {
63                color: ColorConfig::Always,
64                skip_filename: false,
65            },
66            |handler| {
67                GLOBALS.set(&Globals::default(), || {
68                    HANDLER.set(handler, || {
69                        //
70                        let input = PathBuf::from(
71                            env::var(CREDUCE_INPUT_ENV_VAR)
72                                .expect("creduce is invoked without the name of input file"),
73                        );
74
75                        if mode == "SIZE" {
76                            let m = get_minified(cm.clone(), &input, true, true)?;
77
78                            let swc_output = print_js(cm.clone(), &m.module, true)?;
79
80                            let terser_output = get_terser_output(&input, true, true)?;
81                            if swc_output.trim().len() > terser_output.trim().len() {
82                                // It's interesting, as our output is larger than terser's.
83                                return Ok(());
84                            }
85
86                            bail!("We don't care about this file")
87                        } else if mode == "SEMANTICS" {
88                            let m = get_minified(cm.clone(), &input, true, false)?;
89
90                            let swc_output = print_js(cm.clone(), &m.module, true)?;
91
92                            let terser_output = get_terser_output(&input, true, false)?;
93
94                            if swc_output.trim() == terser_output.trim() {
95                                bail!("We don't care about this file")
96                            }
97
98                            // It's interesting, as our output may have a bug
99
100                            Ok(())
101                        } else {
102                            unreachable!("Unknown mode `{}`", mode)
103                        }
104                    })
105                })
106            },
107        )
108        .map_err(|e| e.to_pretty_error());
109    }
110
111    let args = AppArgs::parse();
112
113    try_with_handler(
114        cm.clone(),
115        HandlerOpts {
116            color: ColorConfig::Always,
117            skip_filename: false,
118        },
119        |handler| {
120            GLOBALS.set(&Globals::default(), || {
121                HANDLER.set(handler, || match args.cmd {
122                    Cmd::Es(cmd) => cmd.run(cm.clone()),
123                })
124            })
125        },
126    )
127    .map_err(|e| e.to_pretty_error())
128}