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

feat(es/minifier): switches #4260

Merged
merged 28 commits into from Apr 21, 2022
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -11,7 +11,6 @@ const reducer = (op, args)=>{
break;
case "concat":
console.log(args.firstArr.concat(args.secondArr));
break;
}
};
reducer("add", {
Expand Down
Expand Up @@ -12,7 +12,6 @@ var reducer = function(op, args) {
break;
case "concat":
console.log(args.firstArr.concat(args.secondArr));
break;
}
};
reducer("add", {
Expand Down
Expand Up @@ -77,7 +77,6 @@ var TypeScript;
context.skipNextFuncDeclForClass ? context.skipNextFuncDeclForClass = !1 : (context.scopeGetter = function() {
return funcDecl.isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod) && ast.type && ast.type.enclosingType ? ast.type.enclosingType.constructorScope : funcDecl.scopeType ? funcDecl.scopeType.containedScope : funcDecl.type ? funcDecl.type.containedScope : null;
}, context.scopeStartAST = ast);
break;
}
walker.options.goChildren = !0;
} else walker.options.goChildren = !1;
Expand Down
Expand Up @@ -42,7 +42,6 @@ import * as swcHelpers from "@swc/helpers";
context.skipNextFuncDeclForClass ? context.skipNextFuncDeclForClass = !1 : (context.scopeGetter = function() {
return funcDecl.isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod) && ast.type && ast.type.enclosingType ? ast.type.enclosingType.constructorScope : funcDecl.scopeType ? funcDecl.scopeType.containedScope : funcDecl.type ? funcDecl.type.containedScope : null;
}, context.scopeStartAST = ast);
break;
}
walker.options.goChildren = !0;
} else walker.options.goChildren = !1;
Expand Down
Expand Up @@ -246,7 +246,6 @@ var Formatting;
break;
case AuthorTokenKind.atkLBrack:
updateStartOffset = node.AuthorNode.Details.Kind == AuthorParseNodeKind.apnkArray;
break;
}
updateStartOffset && ParseNodeExtensions.SetNodeSpan(node, token.Span.startPosition(), node.AuthorNode.Details.EndOffset);
}
Expand Down
Expand Up @@ -219,7 +219,6 @@ import * as swcHelpers from "@swc/helpers";
break;
case AuthorTokenKind.atkLBrack:
updateStartOffset = node.AuthorNode.Details.Kind == AuthorParseNodeKind.apnkArray;
break;
}
updateStartOffset && ParseNodeExtensions.SetNodeSpan(node, token.Span.startPosition(), node.AuthorNode.Details.EndOffset);
}
Expand Down
Expand Up @@ -5,5 +5,4 @@ switch(foo){
break;
default:
foo = foo[0];
break;
}
Expand Up @@ -5,5 +5,4 @@ switch(foo){
break;
default:
foo = foo[0];
break;
}
@@ -0,0 +1,6 @@
'';
ONE: '';
TWO: THREE: '';
FOUR: '';
'';
SEVEN: '';
@@ -0,0 +1,6 @@
"";
ONE: "";
TWO: THREE: "";
FOUR: "";
"";
SEVEN: "";
Expand Up @@ -5,4 +5,5 @@ var M;
}
M1.fn = fn;
}(M || (M = {})), new class {
}(), new Object();
}(), new Object(), (x)=>''
;
@@ -1,11 +1 @@
var y;
switch(y){
case 'a':
throw y;
default:
throw y;
}
for(;;)throw 0;
for(;;)throw 0;
for(var idx in {})throw idx;
for(;;)throw null;
throw void 0;
@@ -1,20 +1,3 @@
var y;
import * as swcHelpers from "@swc/helpers";
switch(y){
case "a":
throw y;
default:
throw y;
}
for(;;)throw 0;
for(;;)throw 0;
for(var idx in {})throw idx;
for(;;)throw null;
var y, C = function() {
"use strict";
function C() {
throw swcHelpers.classCallCheck(this, C), this;
}
return C.prototype.biz = function() {
throw this.value;
}, C;
}();
throw y;
@@ -1 +1 @@
isString1(0, ""), isString1(0, ""), isString2("");
isString1(0, ""), isString2(""), isString1(0, ""), isString2("");
@@ -1 +1 @@
isString1(0, ""), isString1(0, ""), isString2("");
isString1(0, ""), isString2(""), isString1(0, ""), isString2("");
10 changes: 10 additions & 0 deletions crates/swc_ecma_ast/src/stmt.rs
Expand Up @@ -345,6 +345,16 @@ pub struct SwitchCase {
pub cons: Vec<Stmt>,
}

impl Take for SwitchCase {
fn dummy() -> Self {
Self {
span: DUMMY_SP,
test: None,
cons: Vec::new(),
}
}
}

#[ast_node("CatchClause")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
Expand Down
11 changes: 4 additions & 7 deletions crates/swc_ecma_minifier/src/compress/optimize/conditionals.rs
Expand Up @@ -3,14 +3,11 @@ use std::mem::swap;
use swc_common::{util::take::Take, EqIgnoreSpan, Spanned, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_transforms_base::ext::ExprRefExt;
use swc_ecma_utils::{ident::IdentLike, ExprExt, ExprFactory, StmtLike};
use swc_ecma_utils::{ident::IdentLike, ExprExt, ExprFactory, StmtExt, StmtLike};

use super::Optimizer;
use crate::{
compress::{
optimize::Ctx,
util::{always_terminates, negate_cost},
},
compress::{optimize::Ctx, util::negate_cost},
mode::Mode,
DISABLE_BUGGY_PASSES,
};
Expand Down Expand Up @@ -701,7 +698,7 @@ where
cons,
alt: Some(..),
..
})) => always_terminates(cons),
})) => cons.terminates(),
_ => false,
});
if !need_work {
Expand All @@ -720,7 +717,7 @@ where
cons,
alt: Some(alt),
..
}) if always_terminates(&cons) => {
}) if cons.terminates() => {
new_stmts.push(T::from_stmt(Stmt::If(IfStmt {
span,
test,
Expand Down
11 changes: 3 additions & 8 deletions crates/swc_ecma_minifier/src/compress/optimize/if_return.rs
@@ -1,15 +1,10 @@
use swc_common::{util::take::Take, Spanned, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_utils::{prepend, undefined, StmtLike};
use swc_ecma_utils::{prepend, undefined, StmtExt, StmtLike};
use swc_ecma_visit::{noop_visit_type, Visit, VisitWith};

use super::Optimizer;
use crate::{
compress::util::{always_terminates, is_pure_undefined},
debug::dump,
mode::Mode,
util::ExprOptExt,
};
use crate::{compress::util::is_pure_undefined, debug::dump, mode::Mode, util::ExprOptExt};

/// Methods related to the option `if_return`. All methods are noop if
/// `if_return` is false.
Expand Down Expand Up @@ -587,7 +582,7 @@ fn always_terminates_with_return_arg(s: &Stmt) -> bool {
fn can_merge_as_if_return(s: &Stmt) -> bool {
fn cost(s: &Stmt) -> Option<isize> {
if let Stmt::Block(..) = s {
if !always_terminates(s) {
if !s.terminates() {
return None;
}
}
Expand Down
97 changes: 77 additions & 20 deletions crates/swc_ecma_minifier/src/compress/optimize/mod.rs
Expand Up @@ -12,8 +12,8 @@ use swc_common::{
};
use swc_ecma_ast::*;
use swc_ecma_utils::{
ident::IdentLike, prepend_stmts, undefined, ExprExt, ExprFactory, Id, IsEmpty, ModuleItemLike,
StmtLike, Type, Value,
extract_var_ids, ident::IdentLike, prepend_stmts, undefined, ExprExt, ExprFactory, Id, IsEmpty,
ModuleItemLike, StmtLike, Type, Value,
};
use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith, VisitWith};
use tracing::{debug, span, Level};
Expand Down Expand Up @@ -133,8 +133,6 @@ struct Ctx {
/// `true` while handling `expr` of `!expr`
in_bang_arg: bool,
in_var_decl_of_for_in_or_of_loop: bool,
/// `true` while handling inner statements of a labelled statement.
stmt_labelled: bool,

dont_use_negated_iife: bool,

Expand Down Expand Up @@ -1551,7 +1549,6 @@ where
#[cfg_attr(feature = "debug", tracing::instrument(skip_all))]
fn visit_mut_block_stmt(&mut self, n: &mut BlockStmt) {
let ctx = Ctx {
stmt_labelled: false,
top_level: false,
in_block: true,
scope: n.span.ctxt,
Expand Down Expand Up @@ -1957,13 +1954,7 @@ where

#[cfg_attr(feature = "debug", tracing::instrument(skip_all))]
fn visit_mut_function(&mut self, n: &mut Function) {
{
let ctx = Ctx {
stmt_labelled: false,
..self.ctx
};
n.decorators.visit_mut_with(&mut *self.with_ctx(ctx));
}
n.decorators.visit_mut_with(self);

let is_standalone = n.span.has_mark(self.marks.standalone);

Expand All @@ -1978,7 +1969,6 @@ where
{
let ctx = Ctx {
skip_standalone: self.ctx.skip_standalone || is_standalone,
stmt_labelled: false,
in_fn_like: true,
scope: n.span.ctxt,
can_inline_arguments: true,
Expand Down Expand Up @@ -2044,13 +2034,9 @@ where

#[cfg_attr(feature = "debug", tracing::instrument(skip_all))]
fn visit_mut_labeled_stmt(&mut self, n: &mut LabeledStmt) {
let ctx = Ctx {
stmt_labelled: true,
..self.ctx
};
let old_label = self.label.take();
self.label = Some(n.label.to_id());
n.visit_mut_children_with(&mut *self.with_ctx(ctx));
n.visit_mut_children_with(self);

if self.label.is_none() {
report_change!("Removing label `{}`", n.label);
Expand Down Expand Up @@ -2511,6 +2497,79 @@ where
if cfg!(debug_assertions) {
stmts.visit_with(&mut AssertValid);
}

if self.options.dead_code {
// copy from [Remover]
// TODO: make it better
let orig_len = stmts.len();

let mut new_stmts = Vec::with_capacity(stmts.len());

let mut iter = stmts.take().into_iter();
while let Some(stmt) = iter.next() {
let stmt = match stmt {
// Remove empty statements.
Stmt::Empty(..) => continue,

// Control flow
Stmt::Throw(..)
| Stmt::Return { .. }
| Stmt::Continue { .. }
| Stmt::Break { .. } => {
// Hoist function and `var` declarations above return.
let mut decls = vec![];
let mut hoisted_fns = vec![];
for t in iter {
match t.try_into_stmt() {
Ok(Stmt::Decl(Decl::Fn(f))) => {
hoisted_fns.push(Stmt::Decl(Decl::Fn(f)));
}
Ok(t) => {
let ids =
extract_var_ids(&t).into_iter().map(|i| VarDeclarator {
span: i.span,
name: i.into(),
init: None,
definite: false,
});
decls.extend(ids);
}
Err(item) => new_stmts.push(item),
}
}

if !decls.is_empty() {
new_stmts.push(Stmt::Decl(Decl::Var(VarDecl {
span: DUMMY_SP,
kind: VarDeclKind::Var,
decls,
declare: false,
})));
}

new_stmts.push(stmt);
new_stmts.extend(hoisted_fns);

*stmts = new_stmts;
if stmts.len() != orig_len {
self.changed = true;

if cfg!(feature = "debug") {
debug!("Dropping statements after a control keyword");
Austaras marked this conversation as resolved.
Show resolved Hide resolved
}
}

return;
}

_ => stmt,
};

new_stmts.push(stmt);
}

*stmts = new_stmts;
}
kdy1 marked this conversation as resolved.
Show resolved Hide resolved
}

fn visit_mut_str(&mut self, s: &mut Str) {
Expand Down Expand Up @@ -2540,8 +2599,6 @@ where
fn visit_mut_switch_stmt(&mut self, n: &mut SwitchStmt) {
n.discriminant.visit_mut_with(self);

self.drop_unreachable_cases(n);

n.cases.visit_mut_with(self);
}

Expand Down