#![deny(warnings)] extern crate swc_malloc; use std::{env, fs, path::PathBuf, time::Instant}; use anyhow::Result; use rayon::prelude::*; use swc_common::{errors::HANDLER, sync::Lrc, Mark, SourceMap, GLOBALS}; use swc_ecma_codegen::text_writer::JsWriter; use swc_ecma_minifier::{ optimize, option::{ExtraOptions, MangleOptions, MinifyOptions}, }; use swc_ecma_parser::parse_file_as_module; use swc_ecma_transforms_base::{ fixer::{fixer, paren_remover}, resolver, }; use swc_ecma_visit::FoldWith; use walkdir::WalkDir; fn main() { let dirs = env::args().skip(1).collect::>(); let files = expand_dirs(dirs); eprintln!("Using {} files", files.len()); let start = Instant::now(); testing::run_test2(false, |cm, handler| { GLOBALS.with(|globals| { HANDLER.set(&handler, || { let _ = files .into_iter() .map(|path| -> Result<_> { GLOBALS.set(globals, || { let fm = cm.load_file(&path).expect("failed to load file"); let unresolved_mark = Mark::new(); let top_level_mark = Mark::new(); let program = parse_file_as_module( &fm, Default::default(), Default::default(), None, &mut vec![], ) .map_err(|err| { err.into_diagnostic(&handler).emit(); }) .map(|module| { module.fold_with(&mut resolver( unresolved_mark, top_level_mark, false, )) }) .map(|module| module.fold_with(&mut paren_remover(None))) .unwrap(); let output = optimize( program.into(), cm.clone(), None, None, &MinifyOptions { compress: Some(Default::default()), mangle: Some(MangleOptions { top_level: Some(true), ..Default::default() }), ..Default::default() }, &ExtraOptions { unresolved_mark, top_level_mark, }, ) .expect_module(); let output = output.fold_with(&mut fixer(None)); let code = print(cm.clone(), &[output], true); fs::write("output.js", code.as_bytes()) .expect("failed to write output"); Ok(()) }) }) .collect::>(); Ok(()) }) }) }) .unwrap(); eprintln!("Took {:?}", start.elapsed()); } /// Return the whole input files as abolute path. fn expand_dirs(dirs: Vec) -> Vec { dirs.into_par_iter() .map(PathBuf::from) .map(|dir| dir.canonicalize().unwrap()) .flat_map(|dir| { WalkDir::new(dir) .into_iter() .filter_map(Result::ok) .filter_map(|entry| { if entry.metadata().map(|v| v.is_file()).unwrap_or(false) { Some(entry.into_path()) } else { None } }) .filter(|path| path.extension().map(|ext| ext == "js").unwrap_or(false)) .collect::>() }) .collect() } fn print(cm: Lrc, nodes: &[N], minify: bool) -> String { let mut buf = vec![]; { let mut emitter = swc_ecma_codegen::Emitter { cfg: swc_ecma_codegen::Config::default().with_minify(minify), cm: cm.clone(), comments: None, wr: Box::new(JsWriter::new(cm, "\n", &mut buf, None)), }; for n in nodes { n.emit_with(&mut emitter).unwrap(); } } String::from_utf8(buf).unwrap() }