Skip to content

Commit

Permalink
feat(es/minifier): Implement more rules (#2183)
Browse files Browse the repository at this point in the history
swc_ecma_codegen:
 - Don't panic on `Pat::Invalid`.
 - Fix codegen of unary minus. (#2213)

swc_ecma_minifier:
 - Remove identifier of function expressions if a variable with same name exists.
 - `sequences`: Merge into the argument of a throw statement.
 - Use `ignore_return_value` for `void` expressions.
 - Improve inlining.
 - Drop last `return` if the return value is not used.
 - `sequences`: Merge `c++; use(c)` as `use(++c)`.
 - `sequences`: Merge assignments with an operator.
 - `comparisons`: Optimize the comparison operator if type is equivalent.
 - Fix `negate_cost`.
 - `unused`: Fix order or variable initalizer when variables are dropped.
 - Fix `top_retain` option.
 - `if_return`: Don't merge nested if it's wrong to do so. (#2214)
 - Fix negation of `if_return`.
  • Loading branch information
kdy1 authored Sep 8, 2021
1 parent d8ae4c4 commit c8b46bf
Show file tree
Hide file tree
Showing 45 changed files with 4,435 additions and 3,339 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion ecmascript/codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"]
license = "Apache-2.0/MIT"
name = "swc_ecma_codegen"
repository = "https://github.com/swc-project/swc.git"
version = "0.70.0"
version = "0.70.1"

[dependencies]
bitflags = "1"
Expand Down
16 changes: 8 additions & 8 deletions ecmascript/codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,12 @@ impl<'a> Emitter<'a> {
) => false,

(_, Expr::Update(UpdateExpr { prefix: true, .. }) | Expr::Unary(..)) => true,

(_, Expr::Bin(BinExpr { left, .. })) => match &**left {
Expr::Update(UpdateExpr { prefix: true, .. }) | Expr::Unary(..) => true,
_ => false,
},

_ => false,
}
}
Expand Down Expand Up @@ -1950,14 +1956,14 @@ impl<'a> Emitter<'a> {

#[emitter]
fn emit_pat(&mut self, node: &Pat) -> Result {
match *node {
match node {
Pat::Array(ref n) => emit!(n),
Pat::Assign(ref n) => emit!(n),
Pat::Expr(ref n) => emit!(n),
Pat::Ident(ref n) => emit!(n),
Pat::Object(ref n) => emit!(n),
Pat::Rest(ref n) => emit!(n),
Pat::Invalid(..) => invalid_pat(),
Pat::Invalid(n) => emit!(n),
}

self.emit_trailing_comments_of_pos(node.span().hi, true, true)?;
Expand Down Expand Up @@ -3102,9 +3108,3 @@ fn handle_invalid_unicodes(s: &str) -> Cow<str> {

Cow::Owned(s.replace("\\\0", "\\"))
}

#[cold]
#[inline(never)]
fn invalid_pat() -> ! {
unimplemented!("emit Pat::Invalid")
}
5 changes: 5 additions & 0 deletions ecmascript/codegen/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -652,3 +652,8 @@ impl Write for Buf {
self.0.write().unwrap().flush()
}
}

#[test]
fn issue_2213() {
assert_min("a - -b * c", "a- -b*c")
}
2 changes: 1 addition & 1 deletion ecmascript/minifier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "src/lists/*.json"]
license = "Apache-2.0/MIT"
name = "swc_ecma_minifier"
repository = "https://github.com/swc-project/swc.git"
version = "0.27.0"
version = "0.27.1"

[features]
debug = []
Expand Down
13 changes: 6 additions & 7 deletions ecmascript/minifier/scripts/apply.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ set -eux

export RUST_BACKTRACE=1
export RUST_LOG=swc_ecma_minifier=trace
touch tests/compress.rs

UPDATE=1 cargo test --test compress files__projects --all-features || true
UPDATE=1 cargo test -q --test compress projects__files --all-features || true

# Make it easier to compare
prettier --write tests/projects/output
yarn run eslint --fix ./tests/projects/output/
# # Make it easier to compare
# prettier --write tests/projects/output
# yarn run eslint --fix ./tests/projects/output/

ls -al ./tests/projects/output
ls -al ./tests/projects/refs
# ls -al ./tests/projects/output
# ls -al ./tests/projects/refs
4 changes: 2 additions & 2 deletions ecmascript/minifier/scripts/base.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -eu
set -eux

export RUST_LOG=swc_ecma_minifier=trace

# To prevent regression, we run base test before real tests.
cargo test --test compress ${1-base_exec} -q --all-features
cargo test --test compress -q --all-features ${1-base_exec}
4 changes: 3 additions & 1 deletion ecmascript/minifier/scripts/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# For second invokation, arguments are passed to cargo test so the user can
# filter tests.
#
set -eu
set -eux

export RUST_LOG=swc_ecma_minifier=trace

Expand All @@ -21,10 +21,12 @@ if [ -z "$@" ]; then
./scripts/sort.sh

SWC_RUN=0 GOLDEN_ONLY=1 cargo test -q --test compress --all-features fixture_tests__terser__compress__
SWC_RUN=0 GOLDEN_ONLY=1 UPDATE=1 cargo test -q --test compress --all-features fixture_tests__compress
fi

# To prevent regression, we run base test before real tests.
UPDATE=1 ./scripts/base.sh base_fixture
./scripts/base.sh base_exec

SKIP_GOLDEN=1 cargo test --test compress --all-features ${1:-fixture_tests__terser__compress__}
SKIP_GOLDEN=1 UPDATE=1 cargo test --test compress --all-features ${1:-fixture_tests__compress__}
69 changes: 43 additions & 26 deletions ecmascript/minifier/src/analyzer/ctx.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use super::UsageAnalyzer;
use super::{storage::Storage, UsageAnalyzer};
use std::ops::{Deref, DerefMut};
use swc_ecma_ast::VarDeclKind;

impl UsageAnalyzer {
pub(super) fn with_ctx(&mut self, ctx: Ctx) -> WithCtx {
impl<S> UsageAnalyzer<S>
where
S: Storage,
{
pub(super) fn with_ctx(&mut self, ctx: Ctx) -> WithCtx<S> {
let orig_ctx = self.ctx;
self.ctx = ctx;
WithCtx {
Expand All @@ -14,59 +17,73 @@ impl UsageAnalyzer {
}

#[derive(Debug, Default, Clone, Copy)]
pub(super) struct Ctx {
pub(crate) struct Ctx {
/// See [crate::marks::Marks]
pub skip_standalone: bool,
pub(super) skip_standalone: bool,

pub var_decl_kind_of_pat: Option<VarDeclKind>,
pub(super) var_decl_kind_of_pat: Option<VarDeclKind>,

pub in_var_decl_with_no_side_effect_for_member_access: bool,
pub(super) in_var_decl_with_no_side_effect_for_member_access: bool,

pub in_pat_of_var_decl: bool,
pub in_pat_of_var_decl_with_init: bool,
pub in_pat_of_param: bool,
pub in_catch_param: bool,
pub(super) in_pat_of_var_decl: bool,
pub(super) in_pat_of_var_decl_with_init: bool,
pub(super) in_pat_of_param: bool,
pub(super) in_catch_param: bool,
/// `true` for `foo.bar` and `false` for `foo` in `foo.bar++`
pub is_exact_reassignment: bool,
pub(super) is_exact_reassignment: bool,

/// `true` for arugments of [swc_ecma_ast::Expr::Call] or
/// [swc_ecma_ast::Expr::New]
pub in_call_arg: bool,
pub(super) in_call_arg: bool,

/// `false` for `array` in `array.length.
pub is_exact_arg: bool,
pub(super) is_exact_arg: bool,

pub in_left_of_for_loop: bool,
pub(super) in_await_arg: bool,

pub in_loop: bool,
pub(super) in_left_of_for_loop: bool,

pub(super) in_loop: bool,
/// Are we handling argument of an update exprssion.
pub in_update_arg: bool,
pub in_assign_lhs: bool,
pub in_cond: bool,
pub(super) in_update_arg: bool,
pub(super) in_assign_lhs: bool,
pub(super) in_cond: bool,

pub inline_prevented: bool,
pub(super) inline_prevented: bool,
}

pub(super) struct WithCtx<'a> {
analyzer: &'a mut UsageAnalyzer,
pub(super) struct WithCtx<'a, S>
where
S: Storage,
{
analyzer: &'a mut UsageAnalyzer<S>,
orig_ctx: Ctx,
}

impl Deref for WithCtx<'_> {
type Target = UsageAnalyzer;
impl<S> Deref for WithCtx<'_, S>
where
S: Storage,
{
type Target = UsageAnalyzer<S>;

fn deref(&self) -> &Self::Target {
&self.analyzer
}
}

impl DerefMut for WithCtx<'_> {
impl<S> DerefMut for WithCtx<'_, S>
where
S: Storage,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.analyzer
}
}

impl Drop for WithCtx<'_> {
impl<S> Drop for WithCtx<'_, S>
where
S: Storage,
{
fn drop(&mut self) {
self.analyzer.ctx = self.orig_ctx;
}
Expand Down
Loading

0 comments on commit c8b46bf

Please sign in to comment.