Skip to content

Commit

Permalink
feat(es/minifier): Enable conditionals by default (#4687)
Browse files Browse the repository at this point in the history
  • Loading branch information
kdy1 committed May 17, 2022
1 parent b467432 commit c01476d
Show file tree
Hide file tree
Showing 40 changed files with 454 additions and 398 deletions.
3 changes: 3 additions & 0 deletions crates/dbg-swc/.gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
/*.output.js
/input.js
*.orig
input.new.js
input.orig.js

*.txt

/.input
/.compare

# creduce
creduce_bug*
23 changes: 3 additions & 20 deletions crates/dbg-swc/src/minify/compare.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
use std::{
path::{Path, PathBuf},
process::{Command, Stdio},
sync::Arc,
};
use std::{path::PathBuf, process::Command, sync::Arc};

use anyhow::{bail, Context, Result};
use anyhow::{Context, Result};
use clap::Args;
use swc_common::SourceMap;

use crate::util::{
make_pretty,
minifier::{get_esbuild_output, get_minified},
print_js,
};
Expand Down Expand Up @@ -54,17 +51,3 @@ impl CompareCommand {
Ok(())
}
}

fn make_pretty(f: &Path) -> Result<()> {
let mut c = Command::new("npx");
c.stderr(Stdio::inherit());
c.arg("js-beautify").arg("--replace").arg(f);

let output = c.output().context("failed to run prettier")?;

if !output.status.success() {
bail!("prettier failed");
}

Ok(())
}
122 changes: 122 additions & 0 deletions crates/dbg-swc/src/minify/diff_options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
use std::{
fs,
path::{Path, PathBuf},
process::Command,
sync::Arc,
};

use anyhow::{Context, Result};
use clap::Args;
use rayon::prelude::*;
use swc_common::{SourceMap, GLOBALS};
use swc_ecma_minifier::option::{CompressOptions, MinifyOptions};
use swc_ecma_transforms_base::fixer::fixer;
use swc_ecma_visit::VisitMutWith;
use tracing::info;

use crate::util::{all_js_files, make_pretty, parse_js, print_js};

/// Useful for checking if the minifier is working correctly, even with the new
/// option.
#[derive(Debug, Args)]
pub struct DiffOptionCommand {
pub path: PathBuf,

#[clap(long)]
pub open: bool,
}

impl DiffOptionCommand {
pub fn run(self, cm: Arc<SourceMap>) -> Result<()> {
let js_files = all_js_files(&self.path)?;

let inputs = js_files
.into_iter()
.filter(|p| p.file_name() == Some("input.js".as_ref()))
.collect::<Vec<_>>();

let files = GLOBALS.with(|globals| {
inputs
.into_par_iter()
.map(|f| GLOBALS.set(globals, || self.process_file(cm.clone(), &f)))
.collect::<Result<Vec<_>>>()
})?;

for (orig_path, new_path) in files.into_iter().flatten() {
if self.open {
let mut c = Command::new("code");
c.arg("--diff").arg("--wait");
c.arg(&orig_path);
c.arg(&new_path);
c.output().context("failed to run vscode")?;
}
}

Ok(())
}

fn process_file(&self, cm: Arc<SourceMap>, f: &Path) -> Result<Option<(PathBuf, PathBuf)>> {
info!("Processing `{}`", f.display());

let fm = cm.load_file(f)?;
let m = parse_js(fm)?;

let orig = {
let m = m.clone();
let mut m = swc_ecma_minifier::optimize(
m.module,
cm.clone(),
Some(&m.comments),
None,
&MinifyOptions {
compress: Some(Default::default()),
mangle: None,
..Default::default()
},
&swc_ecma_minifier::option::ExtraOptions {
unresolved_mark: m.unresolved_mark,
top_level_mark: m.top_level_mark,
},
);
m.visit_mut_with(&mut fixer(None));
print_js(cm.clone(), &m, false)?
};

let new = {
let mut m = swc_ecma_minifier::optimize(
m.module,
cm.clone(),
Some(&m.comments),
None,
&MinifyOptions {
compress: Some(CompressOptions {
conditionals: true,
..Default::default()
}),
mangle: None,
..Default::default()
},
&swc_ecma_minifier::option::ExtraOptions {
unresolved_mark: m.unresolved_mark,
top_level_mark: m.top_level_mark,
},
);
m.visit_mut_with(&mut fixer(None));
print_js(cm, &m, false)?
};

if orig == new {
fs::remove_file(f)?;
return Ok(None);
}

let orig_path = f.with_extension("orig.js");
fs::write(&orig_path, orig)?;
make_pretty(&orig_path)?;
let new_path = f.with_extension("new.js");
fs::write(&new_path, new)?;
make_pretty(&new_path)?;

Ok(Some((orig_path, new_path)))
}
}
8 changes: 7 additions & 1 deletion crates/dbg-swc/src/minify/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ use anyhow::Result;
use clap::Subcommand;
use swc_common::SourceMap;

use self::{compare::CompareCommand, ensure_size::EnsureSize, reduce::ReduceCommand};
use self::{
compare::CompareCommand, diff_options::DiffOptionCommand, ensure_size::EnsureSize,
reduce::ReduceCommand,
};

mod compare;
mod diff_options;
mod ensure_size;
mod reduce;

Expand All @@ -15,6 +19,7 @@ mod reduce;
pub enum MinifyCommand {
Reduce(ReduceCommand),
Compare(CompareCommand),
DiffOption(DiffOptionCommand),
EnsureSize(EnsureSize),
}

Expand All @@ -24,6 +29,7 @@ impl MinifyCommand {
MinifyCommand::Reduce(cmd) => cmd.run(cm),
MinifyCommand::EnsureSize(cmd) => cmd.run(cm),
MinifyCommand::Compare(cmd) => cmd.run(cm),
MinifyCommand::DiffOption(cmd) => cmd.run(cm),
}
}
}
17 changes: 16 additions & 1 deletion crates/dbg-swc/src/util/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{
path::{Path, PathBuf},
process::{Command, Stdio},
sync::Arc,
};

Expand All @@ -21,6 +22,20 @@ where
op()
}

pub fn make_pretty(f: &Path) -> Result<()> {
let mut c = Command::new("npx");
c.stderr(Stdio::inherit());
c.arg("js-beautify").arg("--replace").arg(f);

let output = c.output().context("failed to run prettier")?;

if !output.status.success() {
bail!("prettier failed");
}

Ok(())
}

pub fn parse_js(fm: Arc<SourceFile>) -> Result<ModuleRecord> {
let unresolved_mark = Mark::new();
let top_level_mark = Mark::new();
Expand Down Expand Up @@ -80,7 +95,7 @@ pub fn print_js(cm: Arc<SourceMap>, m: &Module, minify: bool) -> Result<String>
String::from_utf8(buf).context("swc emitted non-utf8 output")
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct ModuleRecord {
pub module: Module,
pub comments: SingleThreadedComments,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
foo({
bar: function(data, baz) {
!(!(baz ? data.quxA : data.quxB) && !(baz ? data.corgeA : data.corgeB) && (baz ? data.get("waldo") : data.waldo)) ? (baz ? data.quxA : data.quxB) || (baz ? data.get("waldo") : data.waldo) || (baz ? !data.corgeA : !data.corgeB) || pass() : pass();
!(!(baz ? data.quxA : data.quxB) && !(baz ? data.corgeA : data.corgeB) && (baz ? data.get("waldo") : data.waldo)) && ((baz ? data.quxA : data.quxB) || (baz ? data.get("waldo") : data.waldo) || (baz ? !data.corgeA : !data.corgeB)) || pass();
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ var Formatting;
}
GetIndentationEditsWorker(token, nextToken, node, sameLineIndent) {
var result = new List_TextEditInfo(), indentationInfo = null;
if (this.AdjustStartOffsetIfNeeded(token, node), this.scriptBlockBeginLineNumber == token.lineNumber()) return result;
if (!sameLineIndent && this.IsMultiLineString(token)) return result;
if (this.AdjustStartOffsetIfNeeded(token, node), this.scriptBlockBeginLineNumber == token.lineNumber() || !sameLineIndent && this.IsMultiLineString(token)) return result;
if (null == (indentationInfo = this.GetSpecialCaseIndentation(token, node))) {
for(; !node.CanIndent() && null != node.Parent && token.Span.span.start() == node.Parent.AuthorNode.Details.StartOffset;)node = node.Parent;
indentationInfo = node.CanIndent() && token.Span.span.start() == node.AuthorNode.Details.StartOffset ? node.GetEffectiveIndentation(this) : token.Token == AuthorTokenKind.atkIdentifier && null != nextToken && nextToken.Token == AuthorTokenKind.atkColon ? node.GetEffectiveChildrenIndentation(this) : this.ApplyIndentationDeltaFromParent(token, node);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ import * as swcHelpers from "@swc/helpers";
return result;
}, _proto.GetIndentationEditsWorker = function(token, nextToken, node, sameLineIndent) {
var result = new List_TextEditInfo(), indentationInfo = null;
if (this.AdjustStartOffsetIfNeeded(token, node), this.scriptBlockBeginLineNumber == token.lineNumber()) return result;
if (!sameLineIndent && this.IsMultiLineString(token)) return result;
if (this.AdjustStartOffsetIfNeeded(token, node), this.scriptBlockBeginLineNumber == token.lineNumber() || !sameLineIndent && this.IsMultiLineString(token)) return result;
if (null == (indentationInfo = this.GetSpecialCaseIndentation(token, node))) {
for(; !node.CanIndent() && null != node.Parent && token.Span.span.start() == node.Parent.AuthorNode.Details.StartOffset;)node = node.Parent;
indentationInfo = node.CanIndent() && token.Span.span.start() == node.AuthorNode.Details.StartOffset ? node.GetEffectiveIndentation(this) : token.Token == AuthorTokenKind.atkIdentifier && null != nextToken && nextToken.Token == AuthorTokenKind.atkColon ? node.GetEffectiveChildrenIndentation(this) : this.ApplyIndentationDeltaFromParent(token, node);
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ var ItemsList = function(_Component) {
var Derived, Constructor1, protoProps, staticProps, _super = (Derived = ItemsList1, function() {
var self, call, result, Super = _getPrototypeOf(Derived);
if (function() {
if ("undefined" == typeof Reflect || !Reflect.construct) return !1;
if (Reflect.construct.sham) return !1;
if ("undefined" == typeof Reflect || !Reflect.construct || Reflect.construct.sham) return !1;
if ("function" == typeof Proxy) return !0;
try {
return Date.prototype.toString.call(Reflect.construct(Date, [], function() {})), !0;
Expand Down
Loading

1 comment on commit c01476d

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: c01476d Previous: b56f3b7 Ratio
es/full/minify/libraries/antd 2486276202 ns/iter (± 38932727) 2551286039 ns/iter (± 44008653) 0.97
es/full/minify/libraries/d3 809098180 ns/iter (± 10280469) 832354710 ns/iter (± 19444260) 0.97
es/full/minify/libraries/echarts 5123759512 ns/iter (± 78734500) 5190265639 ns/iter (± 36434341) 0.99
es/full/minify/libraries/jquery 126790155 ns/iter (± 2344981) 133526450 ns/iter (± 1449325) 0.95
es/full/minify/libraries/lodash 203205236 ns/iter (± 3422489) 208813964 ns/iter (± 2650426) 0.97
es/full/minify/libraries/moment 74996608 ns/iter (± 250651) 76908023 ns/iter (± 574234) 0.98
es/full/minify/libraries/react 23542459 ns/iter (± 406032) 23776073 ns/iter (± 176646) 0.99
es/full/minify/libraries/terser 589474826 ns/iter (± 9330612) 608335834 ns/iter (± 7926606) 0.97
es/full/minify/libraries/three 804049009 ns/iter (± 11266478) 926811652 ns/iter (± 16880900) 0.87
es/full/minify/libraries/typescript 6752645881 ns/iter (± 42588506) 7011257573 ns/iter (± 34107361) 0.96
es/full/minify/libraries/victory 988436202 ns/iter (± 23282483) 1075313439 ns/iter (± 14748155) 0.92
es/full/minify/libraries/vue 202579114 ns/iter (± 841494) 203196352 ns/iter (± 3054174) 1.00
es/full/codegen/es3 38381 ns/iter (± 482) 37749 ns/iter (± 522) 1.02
es/full/codegen/es5 38564 ns/iter (± 174) 37676 ns/iter (± 1202) 1.02
es/full/codegen/es2015 38532 ns/iter (± 220) 37126 ns/iter (± 617) 1.04
es/full/codegen/es2016 38436 ns/iter (± 259) 37884 ns/iter (± 243) 1.01
es/full/codegen/es2017 38516 ns/iter (± 190) 37879 ns/iter (± 317) 1.02
es/full/codegen/es2018 38445 ns/iter (± 290) 37616 ns/iter (± 618) 1.02
es/full/codegen/es2019 38445 ns/iter (± 219) 37202 ns/iter (± 670) 1.03
es/full/codegen/es2020 38561 ns/iter (± 199) 37545 ns/iter (± 579) 1.03
es/full/all/es3 241003624 ns/iter (± 5726783) 235370181 ns/iter (± 2200007) 1.02
es/full/all/es5 224570544 ns/iter (± 4666950) 224277941 ns/iter (± 4730444) 1.00
es/full/all/es2015 178014121 ns/iter (± 5030391) 176681686 ns/iter (± 5454013) 1.01
es/full/all/es2016 177579022 ns/iter (± 4736524) 173172683 ns/iter (± 2911662) 1.03
es/full/all/es2017 175012763 ns/iter (± 5979231) 172621706 ns/iter (± 3656000) 1.01
es/full/all/es2018 171645799 ns/iter (± 6248211) 171523709 ns/iter (± 2577599) 1.00
es/full/all/es2019 170847270 ns/iter (± 4950822) 168351712 ns/iter (± 3197115) 1.01
es/full/all/es2020 163627474 ns/iter (± 1954442) 162341438 ns/iter (± 5184088) 1.01
es/full/parser 755415 ns/iter (± 9611) 731062 ns/iter (± 24974) 1.03
es/full/base/fixer 49996 ns/iter (± 1144) 48704 ns/iter (± 1704) 1.03
es/full/base/resolver_and_hygiene 190467 ns/iter (± 1447) 179085 ns/iter (± 6828) 1.06
serialization of ast node 215 ns/iter (± 7) 203 ns/iter (± 7) 1.06
serialization of serde 213 ns/iter (± 0) 201 ns/iter (± 6) 1.06

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.