Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(dbg-swc): Cleanup and document reducer #6647

Merged
merged 17 commits into from Dec 14, 2022
Expand Up @@ -16,21 +16,22 @@ use tracing::info;

use crate::{bundle::bundle, util::print_js};

/// Execute a javascript file after performing some preprocessing.
/// [Experimental] Execute a javascript file after performing some
/// preprocessing.
#[derive(Debug, Subcommand)]
pub enum TestCommand {
pub enum ExecForTestingCommand {
MinifiedBundle(TestMinifiedBundleCommand),
}

impl TestCommand {
impl ExecForTestingCommand {
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),
ExecForTestingCommand::MinifiedBundle(cmd) => cmd.run(cm),
}?
};

Expand Down
Expand Up @@ -10,7 +10,8 @@ use crate::util::{
print_js,
};

/// Opens vscode for diffing output of swc minifier and terser/esbuild
/// [Experimental] Opens vscode for diffing output of swc minifier and
/// terser/esbuild
#[derive(Debug, Args)]
pub struct CompareCommand {
pub path: PathBuf,
Expand Down
Expand Up @@ -18,7 +18,8 @@ use crate::util::{
print_js, wrap_task,
};

/// Ensure that we are performing better than other minification tools.
/// [Experimental] Ensure that we are performing better than other minification
/// tools.
#[derive(Debug, Args)]
pub struct EnsureSize {
#[clap(long)]
Expand Down
35 changes: 35 additions & 0 deletions crates/dbg-swc/src/es/minifier/mod.rs
@@ -0,0 +1,35 @@
use std::sync::Arc;

use anyhow::Result;
use clap::Subcommand;
use swc_common::SourceMap;

use self::{
compare::CompareCommand, ensure_size::EnsureSize, next::NextCommand, reduce::ReduceCommand,
};

mod compare;
mod ensure_size;
mod next;
mod reduce;

/// Debug the ECMAScript Minifier.
#[derive(Debug, Subcommand)]
pub enum MinifierCommand {
#[clap(subcommand)]
Next(NextCommand),
Reduce(ReduceCommand),
Compare(CompareCommand),
EnsureSize(EnsureSize),
}

impl MinifierCommand {
pub fn run(self, cm: Arc<SourceMap>) -> Result<()> {
match self {
MinifierCommand::Next(cmd) => cmd.run(cm),
MinifierCommand::Reduce(cmd) => cmd.run(cm),
MinifierCommand::EnsureSize(cmd) => cmd.run(cm),
MinifierCommand::Compare(cmd) => cmd.run(cm),
}
}
}
Expand Up @@ -8,7 +8,7 @@ use self::check_size::CheckSizeCommand;

mod check_size;

/// Debug the minifier issue related to next.js application.
/// [Experimental] Debug the minifier issue related to next.js application.
#[derive(Debug, Subcommand)]
pub enum NextCommand {
CheckSize(CheckSizeCommand),
Expand Down
Expand Up @@ -18,14 +18,32 @@ use crate::{
CREDUCE_INPUT_ENV_VAR, CREDUCE_MODE_ENV_VAR,
};

/// Reduce input files to minimal reproduction cases
///
/// This command requires `creduce` and `terser` in PATH.
/// See https://embed.cs.utah.edu/creduce/ for more information.
///
/// For `terser`, this command uses `npx terser` to invoke `terser` for
/// comparison.
///
/// After reducing, the reduced file will be moved to `.swc-reduce` directory.
#[derive(Debug, Args)]
pub struct ReduceCommand {
/// The path to the input file. You can specify a directory if you want to
/// reduce every '.js' file within a directory, in a recursive manner.
pub path: PathBuf,

/// In 'size' mode, this command tries to find the minimal input file where
/// the size of the output file of swc minifier is larger than the one from
/// terser.
///
/// In 'semantics' mode, this command tries to reduce the input file to a
/// minimal reproduction case which triggers the bug.
#[clap(long, arg_enum)]
pub mode: ReduceMode,

/// If true, the input file will be removed after the reduction.
/// If true, the input file will be removed after the reduction. This can be
/// used for pausing and resuming the process of reducing.
#[clap(long)]
pub remove: bool,
}
Expand Down Expand Up @@ -115,9 +133,9 @@ fn move_to_data_dir(input_path: &Path) -> Result<PathBuf> {
let result = hasher.finalize();
let hash_str = format!("{:x}", result);

create_dir_all(format!("data/{}", hash_str)).context("failed to create `.data`")?;
create_dir_all(format!(".swc-reduce/{}", hash_str)).context("failed to create `.data`")?;

let to = PathBuf::from(format!("data/{}/input.js", hash_str));
let to = PathBuf::from(format!(".swc-reduce/{}/input.js", hash_str));
fs::write(&to, src.as_bytes()).context("failed to write")?;

Ok(to)
Expand Down
28 changes: 28 additions & 0 deletions crates/dbg-swc/src/es/mod.rs
@@ -0,0 +1,28 @@
use std::sync::Arc;

use anyhow::Result;
use clap::Subcommand;
use swc_common::SourceMap;

use self::{exec_test::ExecForTestingCommand, minifier::MinifierCommand};

mod exec_test;
mod minifier;

/// Debug modules related to ECMAScript
#[derive(Debug, Subcommand)]
pub(crate) enum EsCommand {
#[clap(subcommand)]
Minifier(MinifierCommand),
#[clap(subcommand)]
ExecForTesting(ExecForTestingCommand),
}

impl EsCommand {
pub fn run(self, cm: Arc<SourceMap>) -> Result<()> {
match self {
Self::Minifier(cmd) => cmd.run(cm),
Self::ExecForTesting(cmd) => cmd.run(cm),
}
}
}
35 changes: 5 additions & 30 deletions crates/dbg-swc/src/main.rs
Expand Up @@ -2,23 +2,19 @@ use std::{env, path::PathBuf, str::FromStr, sync::Arc};

use anyhow::{bail, Result};
use clap::{StructOpt, Subcommand};
use es::EsCommand;
use swc_common::{
errors::{ColorConfig, HANDLER},
Globals, SourceMap, GLOBALS,
};
use swc_error_reporters::handler::{try_with_handler, HandlerOpts};
use tracing_subscriber::EnvFilter;

use self::{
minify::MinifyCommand,
test::TestCommand,
util::{minifier::get_esbuild_output, print_js},
};
use self::util::print_js;
use crate::util::minifier::{get_minified, get_terser_output};

mod bundle;
mod minify;
mod test;
mod es;
mod util;

const CREDUCE_INPUT_ENV_VAR: &str = "CREDUCE_INPUT";
Expand All @@ -34,9 +30,7 @@ struct AppArgs {
#[derive(Debug, Subcommand)]
enum Cmd {
#[clap(subcommand)]
Minify(MinifyCommand),
#[clap(subcommand)]
Test(TestCommand),
Es(EsCommand),
}

fn init() -> Result<()> {
Expand Down Expand Up @@ -89,24 +83,6 @@ fn main() -> Result<()> {
return Ok(());
}

// We only care about length, so we can replace it.
//
// We target es5, but esbuild does not support it
let swc_output = swc_output.replace("\\n", "_");

let esbuild_output = get_esbuild_output(&input, true)?;

if swc_output.len() > esbuild_output.len() {
// It's interesting, as our output is larger than esbuild's.
return Ok(());
}

println!(
"swc size = {}, esbuild size = {}",
swc_output.len(),
esbuild_output.len()
);

bail!("We don't care about this file")
} else if mode == "SEMANTICS" {
let m = get_minified(cm.clone(), &input, true, false)?;
Expand Down Expand Up @@ -142,8 +118,7 @@ fn main() -> Result<()> {
|handler| {
GLOBALS.set(&Globals::default(), || {
HANDLER.set(handler, || match args.cmd {
Cmd::Minify(cmd) => cmd.run(cm),
Cmd::Test(cmd) => cmd.run(cm),
Cmd::Es(cmd) => cmd.run(cm),
})
})
},
Expand Down
124 changes: 0 additions & 124 deletions crates/dbg-swc/src/minify/diff_options.rs

This file was deleted.