mirror of
https://github.com/swc-project/swc.git
synced 2024-12-22 21:21:31 +03:00
feat(debug): Inline dbg-swc
(#4651)
This commit is contained in:
parent
f0639c9de4
commit
b393773373
39
Cargo.lock
generated
39
Cargo.lock
generated
@ -784,6 +784,28 @@ dependencies = [
|
||||
"parking_lot",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dbg-swc"
|
||||
version = "0.12.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 3.1.0",
|
||||
"rayon",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_codegen",
|
||||
"swc_ecma_minifier",
|
||||
"swc_ecma_parser",
|
||||
"swc_ecma_transforms_base",
|
||||
"swc_ecma_visit",
|
||||
"swc_error_reporters",
|
||||
"swc_timer",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "debug_unreachable"
|
||||
version = "0.1.1"
|
||||
@ -2260,9 +2282,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.5.1"
|
||||
version = "1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
|
||||
checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"crossbeam-deque",
|
||||
@ -2272,14 +2294,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.9.1"
|
||||
version = "1.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
|
||||
checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
@ -4379,9 +4400,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.32"
|
||||
version = "0.1.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f"
|
||||
checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"log",
|
||||
@ -4445,9 +4466,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.9"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e0ab7bdc962035a87fba73f3acca9b8a8d0034c2e6f60b84aeaaddddc155dce"
|
||||
checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"lazy_static",
|
||||
|
@ -1,5 +1,6 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"crates/dbg-swc",
|
||||
"crates/jsdoc",
|
||||
"crates/binding_core_node",
|
||||
"crates/binding_core_wasm",
|
||||
@ -44,5 +45,5 @@ opt-level = 3
|
||||
opt-level = 3
|
||||
|
||||
[patch.crates-io]
|
||||
cranelift-codegen = { git = "https://github.com/kdy1/wasmtime", branch = "tls" }
|
||||
cranelift-entity = { git = "https://github.com/kdy1/wasmtime", branch = "tls" }
|
||||
cranelift-codegen = {git = "https://github.com/kdy1/wasmtime", branch = "tls"}
|
||||
cranelift-entity = {git = "https://github.com/kdy1/wasmtime", branch = "tls"}
|
||||
|
26
crates/dbg-swc/Cargo.toml
Normal file
26
crates/dbg-swc/Cargo.toml
Normal file
@ -0,0 +1,26 @@
|
||||
[package]
|
||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||
description = "Debug utilities"
|
||||
edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
name = "dbg-swc"
|
||||
repository = "https://github.com/kdy1/dbg-swc.git"
|
||||
version = "0.12.0"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.57"
|
||||
clap = {version = "3", features = ["derive"]}
|
||||
rayon = "1.5.2"
|
||||
swc_atoms = { version = "0.2.11", path = "../swc_atoms" }
|
||||
swc_common = { version = "0.18.0", features = ["concurrent"], path = "../swc_common" }
|
||||
swc_ecma_ast = { version = "0.78.0", path = "../swc_ecma_ast" }
|
||||
swc_ecma_codegen = { version = "0.107.0", path = "../swc_ecma_codegen" }
|
||||
swc_ecma_minifier = { version = "0.113.1", path = "../swc_ecma_minifier" }
|
||||
swc_ecma_parser = { version = "0.104.0", path = "../swc_ecma_parser" }
|
||||
swc_ecma_transforms_base = { version = "0.84.0", path = "../swc_ecma_transforms_base" }
|
||||
swc_ecma_visit = { version = "0.64.0", path = "../swc_ecma_visit" }
|
||||
swc_error_reporters = { version = "0.2.0", path = "../swc_error_reporters" }
|
||||
swc_timer = { version = "0.6.0", path = "../swc_timer" }
|
||||
tracing = "0.1.34"
|
||||
tracing-subscriber = {version = "0.3.11", features = ["fmt"]}
|
||||
url = "2"
|
39
crates/dbg-swc/src/bundle.rs
Normal file
39
crates/dbg-swc/src/bundle.rs
Normal file
@ -0,0 +1,39 @@
|
||||
use std::{
|
||||
process::{Command, Stdio},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use clap::Subcommand;
|
||||
use swc_common::{FileName, SourceMap};
|
||||
use swc_timer::timer;
|
||||
|
||||
use crate::util::{parse_js, wrap_task, ModuleRecord};
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum BundleCommand {}
|
||||
|
||||
pub fn bundle(cm: Arc<SourceMap>, entry_url: &str) -> Result<ModuleRecord> {
|
||||
wrap_task(|| {
|
||||
let _timer = timer!("bundle");
|
||||
|
||||
let mut cmd = Command::new("deno");
|
||||
cmd.arg("bundle");
|
||||
cmd.arg(entry_url);
|
||||
|
||||
cmd.stderr(Stdio::inherit());
|
||||
|
||||
let output = cmd.output().context("failed to invoke `deno bundle`")?;
|
||||
|
||||
if !output.status.success() {
|
||||
bail!("`deno bundle` failed with status code {}", output.status);
|
||||
}
|
||||
|
||||
let code =
|
||||
String::from_utf8(output.stdout).context("deno bundle emitted non-utf8 output")?;
|
||||
|
||||
let fm = cm.new_source_file(FileName::Anon, code);
|
||||
parse_js(fm).context("failed to parse js filed emitted by `deno bundle`")
|
||||
})
|
||||
.with_context(|| format!("failed to bundle `{}`", entry_url))
|
||||
}
|
57
crates/dbg-swc/src/main.rs
Normal file
57
crates/dbg-swc/src/main.rs
Normal file
@ -0,0 +1,57 @@
|
||||
#![feature(box_syntax)]
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::{StructOpt, Subcommand};
|
||||
use swc_common::{
|
||||
errors::{ColorConfig, HANDLER},
|
||||
Globals, SourceMap, GLOBALS,
|
||||
};
|
||||
use swc_error_reporters::handler::{try_with_handler, HandlerOpts};
|
||||
|
||||
use self::{bundle::BundleCommand, minify::MinifyCommand, test::TestCommand};
|
||||
|
||||
mod bundle;
|
||||
mod minify;
|
||||
mod test;
|
||||
mod util;
|
||||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
struct AppArgs {
|
||||
#[clap(subcommand)]
|
||||
cmd: Cmd,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
enum Cmd {
|
||||
#[clap(subcommand)]
|
||||
Bundle(BundleCommand),
|
||||
#[clap(subcommand)]
|
||||
Minify(MinifyCommand),
|
||||
#[clap(subcommand)]
|
||||
Test(TestCommand),
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let args = AppArgs::parse();
|
||||
|
||||
let cm = Arc::new(SourceMap::default());
|
||||
|
||||
try_with_handler(
|
||||
cm.clone(),
|
||||
HandlerOpts {
|
||||
color: ColorConfig::Always,
|
||||
skip_filename: false,
|
||||
},
|
||||
|handler| {
|
||||
GLOBALS.set(&Globals::default(), || {
|
||||
HANDLER.set(handler, || match args.cmd {
|
||||
Cmd::Bundle(_) => todo!(),
|
||||
Cmd::Minify(_) => todo!(),
|
||||
Cmd::Test(cmd) => cmd.run(cm),
|
||||
})
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
5
crates/dbg-swc/src/minify.rs
Normal file
5
crates/dbg-swc/src/minify.rs
Normal file
@ -0,0 +1,5 @@
|
||||
use clap::Subcommand;
|
||||
|
||||
/// Minify a javascript file.
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum MinifyCommand {}
|
129
crates/dbg-swc/src/test.rs
Normal file
129
crates/dbg-swc/src/test.rs
Normal file
@ -0,0 +1,129 @@
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
process::{Command, Stdio},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use clap::{Args, Subcommand};
|
||||
use swc_common::SourceMap;
|
||||
use swc_ecma_minifier::option::MinifyOptions;
|
||||
use swc_ecma_transforms_base::fixer::fixer;
|
||||
use swc_ecma_visit::VisitMutWith;
|
||||
use swc_timer::timer;
|
||||
use tracing::info;
|
||||
|
||||
use crate::{bundle::bundle, util::print_js};
|
||||
|
||||
/// Execute a javascript file after performing some preprocessing.
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum TestCommand {
|
||||
MinifiedBundle(TestMinifiedBundleCommand),
|
||||
}
|
||||
|
||||
impl TestCommand {
|
||||
pub fn run(self, cm: Arc<SourceMap>) -> Result<()> {
|
||||
let _timer = timer!("test");
|
||||
|
||||
let output = {
|
||||
let _timer = timer!("process");
|
||||
|
||||
match self {
|
||||
TestCommand::MinifiedBundle(cmd) => cmd.run(cm),
|
||||
}?
|
||||
};
|
||||
|
||||
{
|
||||
let _timer = timer!("run");
|
||||
let stdout = output
|
||||
.runtime
|
||||
.execute(&output.path)
|
||||
.context("failed to execute generated code")?;
|
||||
|
||||
info!("----- Stdout -----\n{}", stdout);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
pub struct TestMinifiedBundleCommand {
|
||||
entry: String,
|
||||
}
|
||||
|
||||
impl TestMinifiedBundleCommand {
|
||||
fn run(self, cm: Arc<SourceMap>) -> Result<Output> {
|
||||
let bundle = bundle(cm.clone(), &self.entry)?;
|
||||
|
||||
let mut minified = {
|
||||
let _timer = timer!("minify");
|
||||
swc_ecma_minifier::optimize(
|
||||
bundle.module,
|
||||
cm.clone(),
|
||||
None,
|
||||
None,
|
||||
&MinifyOptions {
|
||||
compress: Some(Default::default()),
|
||||
mangle: Some(Default::default()),
|
||||
..Default::default()
|
||||
},
|
||||
&swc_ecma_minifier::option::ExtraOptions {
|
||||
unresolved_mark: bundle.unresolved_mark,
|
||||
top_level_mark: bundle.top_level_mark,
|
||||
},
|
||||
)
|
||||
};
|
||||
|
||||
minified.visit_mut_with(&mut fixer(None));
|
||||
|
||||
let code = print_js(cm, &minified, true).context("failed to convert ast to code")?;
|
||||
|
||||
let path = Path::new("output.js").to_path_buf();
|
||||
fs::write(&path, code.as_bytes()).context("failed to write code as file")?;
|
||||
|
||||
Ok(Output {
|
||||
path,
|
||||
runtime: JsRuntime::Deno,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Output {
|
||||
pub path: PathBuf,
|
||||
pub runtime: JsRuntime,
|
||||
}
|
||||
|
||||
pub enum JsRuntime {
|
||||
// Node,
|
||||
Deno,
|
||||
}
|
||||
|
||||
impl JsRuntime {
|
||||
pub fn execute(&self, path: &Path) -> Result<String> {
|
||||
match self {
|
||||
// JsRuntime::Node => todo!("node.execute"),
|
||||
JsRuntime::Deno => {
|
||||
let mut cmd = Command::new("deno");
|
||||
cmd.arg("run").arg("--no-check");
|
||||
|
||||
cmd.arg(path);
|
||||
|
||||
cmd.stderr(Stdio::inherit());
|
||||
|
||||
let output = cmd.output().context("failed to get output from deno")?;
|
||||
|
||||
if !output.status.success() {
|
||||
bail!("deno exited with status {}", output.status);
|
||||
}
|
||||
|
||||
Ok(
|
||||
(String::from_utf8(output.stdout).context("deno emitted non-utf8 string")?)
|
||||
.trim()
|
||||
.to_string(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
78
crates/dbg-swc/src/util/mod.rs
Normal file
78
crates/dbg-swc/src/util/mod.rs
Normal file
@ -0,0 +1,78 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use swc_common::{errors::HANDLER, Mark, SourceFile, SourceMap};
|
||||
use swc_ecma_ast::{EsVersion, Module};
|
||||
use swc_ecma_codegen::text_writer::{omit_trailing_semi, JsWriter, WriteJs};
|
||||
use swc_ecma_parser::{parse_file_as_module, Syntax};
|
||||
use swc_ecma_transforms_base::resolver;
|
||||
use swc_ecma_visit::VisitMutWith;
|
||||
|
||||
/// Type annotation
|
||||
pub fn wrap_task<T, F>(op: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce() -> Result<T>,
|
||||
{
|
||||
op()
|
||||
}
|
||||
|
||||
pub fn parse_js(fm: Arc<SourceFile>) -> Result<ModuleRecord> {
|
||||
let unresolved_mark = Mark::new();
|
||||
let top_level_mark = Mark::new();
|
||||
|
||||
let mut errors = vec![];
|
||||
let res = parse_file_as_module(
|
||||
&fm,
|
||||
Syntax::Es(Default::default()),
|
||||
EsVersion::latest(),
|
||||
None,
|
||||
&mut errors,
|
||||
)
|
||||
.map_err(|err| HANDLER.with(|handler| err.into_diagnostic(handler).emit()));
|
||||
|
||||
for err in errors {
|
||||
HANDLER.with(|handler| err.into_diagnostic(handler).emit());
|
||||
}
|
||||
|
||||
let mut m = match res {
|
||||
Ok(v) => v,
|
||||
Err(()) => bail!("failed to parse a js file as a module"),
|
||||
};
|
||||
|
||||
m.visit_mut_with(&mut resolver(unresolved_mark, top_level_mark, false));
|
||||
|
||||
Ok(ModuleRecord {
|
||||
module: m,
|
||||
top_level_mark,
|
||||
unresolved_mark,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn print_js(cm: Arc<SourceMap>, m: &Module, minify: bool) -> Result<String> {
|
||||
let mut buf = vec![];
|
||||
|
||||
{
|
||||
let mut wr = box JsWriter::new(cm.clone(), "\n", &mut buf, None) as Box<dyn WriteJs>;
|
||||
if minify {
|
||||
wr = box omit_trailing_semi(wr);
|
||||
}
|
||||
|
||||
let mut e = swc_ecma_codegen::Emitter {
|
||||
cfg: swc_ecma_codegen::Config { minify },
|
||||
cm,
|
||||
comments: None,
|
||||
wr,
|
||||
};
|
||||
|
||||
e.emit_module(m).unwrap();
|
||||
}
|
||||
|
||||
String::from_utf8(buf).context("swc emitted non-utf8 output")
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ModuleRecord {
|
||||
pub module: Module,
|
||||
pub top_level_mark: Mark,
|
||||
pub unresolved_mark: Mark,
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
extern crate swc_node_base;
|
||||
|
||||
use std::{env, fs, path::PathBuf};
|
||||
use std::{env, fs, path::PathBuf, time::Instant};
|
||||
|
||||
use anyhow::Result;
|
||||
use rayon::prelude::*;
|
||||
@ -20,7 +20,9 @@ use walkdir::WalkDir;
|
||||
fn main() {
|
||||
let dirs = env::args().skip(1).collect::<Vec<_>>();
|
||||
let files = expand_dirs(dirs);
|
||||
eprintln!("Using {} files", files.len());
|
||||
|
||||
let start = Instant::now();
|
||||
testing::run_test2(false, |cm, handler| {
|
||||
GLOBALS.with(|globals| {
|
||||
let _ = files
|
||||
@ -81,6 +83,8 @@ fn main() {
|
||||
})
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
eprintln!("Took {:?}", start.elapsed());
|
||||
}
|
||||
|
||||
/// Return the whole input files as abolute path.
|
||||
|
Loading…
Reference in New Issue
Block a user