fix(es/minifier): Respect dead_code (#4328)

This commit is contained in:
Donny/강동윤 2022-04-14 15:00:43 +09:00 committed by GitHub
parent 62b021b5b2
commit 8886a4b572
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 59 additions and 32 deletions

View File

@ -1,15 +1,14 @@
#![deny(warnings)]
#![cfg(feature = "node")] #![cfg(feature = "node")]
use std::{ use std::{
collections::HashMap,
env::{current_dir, set_current_dir}, env::{current_dir, set_current_dir},
path::PathBuf, path::PathBuf,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use anyhow::{anyhow, Error};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use swc_common::{collections::AHashMap, FileName}; use swc_common::FileName;
extern crate swc_ecma_loader; extern crate swc_ecma_loader;
use swc_ecma_loader::{resolve::Resolve, resolvers::node::NodeModulesResolver, TargetEnv}; use swc_ecma_loader::{resolve::Resolve, resolvers::node::NodeModulesResolver, TargetEnv};
@ -37,7 +36,7 @@ fn basic_import() {
// When // When
let resolved = node_resolver let resolved = node_resolver
.resolve(&FileName::Real(PathBuf::from(&"jquery")), &"jquery") .resolve(&FileName::Real(PathBuf::from("jquery")), "jquery")
.expect("should resolve"); .expect("should resolve");
// Expect // Expect
@ -56,7 +55,7 @@ fn hoisting() {
// When // When
let resolved = node_resolver let resolved = node_resolver
.resolve(&FileName::Real(PathBuf::from(&"jquery")), &"jquery") .resolve(&FileName::Real(PathBuf::from("jquery")), "jquery")
.expect("should resolve"); .expect("should resolve");
// Expect // Expect

View File

@ -2652,10 +2652,7 @@ where
return; return;
} }
let ctx = Ctx { let ctx = Ctx { ..self.ctx };
top_level: false,
..self.ctx
};
self.with_ctx(ctx).inject_else(stmts); self.with_ctx(ctx).inject_else(stmts);

View File

@ -64,9 +64,11 @@ where
T: StmtLike, T: StmtLike,
{ {
if !self.options.sequences() { if !self.options.sequences() {
log_abort!("sequences: make_sequence for statements is disabled");
return; return;
} }
if self.ctx.in_asm { if self.ctx.in_asm {
log_abort!("sequences: asm.js is not supported");
return; return;
} }
@ -718,6 +720,7 @@ where
}; };
if !self.options.sequences() && !e.span.has_mark(self.marks.synthesized_seq) { if !self.options.sequences() && !e.span.has_mark(self.marks.synthesized_seq) {
log_abort!("sequences: Disabled && no mark");
return; return;
} }

View File

@ -33,6 +33,26 @@ where
return; return;
} }
if !self.options.top_level()
&& (self.ctx.is_top_level_for_block_level_vars() || self.ctx.in_top_level())
&& !var.span.has_mark(self.marks.non_top_level)
{
match self.ctx.var_kind {
Some(VarDeclKind::Const) | Some(VarDeclKind::Let) => {
if self.ctx.is_top_level_for_block_level_vars() {
log_abort!("unused: Top-level (block level)");
return;
}
}
_ => {
if self.ctx.in_top_level() {
log_abort!("unused: Top-level");
return;
}
}
}
}
let had_init = var.init.is_some(); let had_init = var.init.is_some();
match &mut var.init { match &mut var.init {
@ -94,7 +114,7 @@ where
} }
} }
self.take_pat_if_unused(DUMMY_SP, pat, None) self.take_pat_if_unused(DUMMY_SP, pat, None, false)
} }
#[cfg_attr(feature = "debug", tracing::instrument(skip_all))] #[cfg_attr(feature = "debug", tracing::instrument(skip_all))]
@ -163,13 +183,13 @@ where
return; return;
} }
self.take_pat_if_unused(var_declarator_span, name, init); self.take_pat_if_unused(var_declarator_span, name, init, true);
} }
#[cfg_attr(feature = "debug", tracing::instrument(skip_all))] #[cfg_attr(feature = "debug", tracing::instrument(skip_all))]
pub(super) fn drop_unused_params(&mut self, params: &mut Vec<Param>) { pub(super) fn drop_unused_params(&mut self, params: &mut Vec<Param>) {
for param in params.iter_mut().rev() { for param in params.iter_mut().rev() {
self.take_pat_if_unused(DUMMY_SP, &mut param.pat, None); self.take_pat_if_unused(DUMMY_SP, &mut param.pat, None, false);
if !param.pat.is_invalid() { if !param.pat.is_invalid() {
return; return;
@ -312,6 +332,7 @@ where
parent_span: Span, parent_span: Span,
name: &mut Pat, name: &mut Pat,
mut init: Option<&mut Expr>, mut init: Option<&mut Expr>,
is_var_decl: bool,
) { ) {
if self.ctx.is_exported { if self.ctx.is_exported {
return; return;
@ -360,7 +381,7 @@ where
.as_mut() .as_mut()
.and_then(|expr| self.access_numeric_property(expr, idx)); .and_then(|expr| self.access_numeric_property(expr, idx));
self.take_pat_if_unused(parent_span, p, elem); self.take_pat_if_unused(parent_span, p, elem, is_var_decl);
} }
None => {} None => {}
} }
@ -387,7 +408,7 @@ where
continue; continue;
} }
self.take_pat_if_unused(parent_span, &mut p.value, None); self.take_pat_if_unused(parent_span, &mut p.value, None, is_var_decl);
} }
ObjectPatProp::Assign(AssignPatProp { ObjectPatProp::Assign(AssignPatProp {
key, value: None, .. key, value: None, ..

View File

@ -254,6 +254,10 @@ impl VisitMut for Pure<'_> {
} }
fn visit_mut_expr(&mut self, e: &mut Expr) { fn visit_mut_expr(&mut self, e: &mut Expr) {
if let Expr::Paren(p) = e {
*e = *p.expr.take();
}
{ {
let ctx = Ctx { let ctx = Ctx {
in_first_expr: false, in_first_expr: false,

View File

@ -118,9 +118,6 @@ dead_code/dead_code_2_should_warn/input.js
dead_code/dead_code_2_should_warn_strict/input.js dead_code/dead_code_2_should_warn_strict/input.js
dead_code/dead_code_const_annotation/input.js dead_code/dead_code_const_annotation/input.js
dead_code/dead_code_const_annotation_complex_scope/input.js dead_code/dead_code_const_annotation_complex_scope/input.js
dead_code/dead_code_const_declaration/input.js
dead_code/dead_code_constant_boolean_should_warn_more/input.js
dead_code/dead_code_constant_boolean_should_warn_more_strict/input.js
dead_code/global_fns/input.js dead_code/global_fns/input.js
dead_code/issue_2749/input.js dead_code/issue_2749/input.js
dead_code/issue_2860_2/input.js dead_code/issue_2860_2/input.js

View File

@ -279,6 +279,9 @@ dead_code/collapse_vars_misc1/input.js
dead_code/dead_code_1/input.js dead_code/dead_code_1/input.js
dead_code/dead_code_block_decls_die/input.js dead_code/dead_code_block_decls_die/input.js
dead_code/dead_code_const_annotation_regex/input.js dead_code/dead_code_const_annotation_regex/input.js
dead_code/dead_code_const_declaration/input.js
dead_code/dead_code_constant_boolean_should_warn_more/input.js
dead_code/dead_code_constant_boolean_should_warn_more_strict/input.js
dead_code/global_timeout_and_interval_symbols/input.js dead_code/global_timeout_and_interval_symbols/input.js
dead_code/issue_2233_1/input.js dead_code/issue_2233_1/input.js
dead_code/issue_2233_2/input.js dead_code/issue_2233_2/input.js

View File

@ -1,7 +1,7 @@
var unused; var unused;
var CONST_FOO_ANN = false; /** @const */ var CONST_FOO_ANN = false;
if (CONST_FOO_ANN) { if (CONST_FOO_ANN) {
console.log("unreachable"); console.log("unreachable");
var moo; var moo;
function bar() {} function bar() { }
} }

View File

@ -1,15 +1,16 @@
var unused_var; var unused_var;
var test = "test"; /** @const */ var test = "test";
// @const
var CONST_FOO_ANN = false; var CONST_FOO_ANN = false;
var unused_var_2; var unused_var_2;
if (CONST_FOO_ANN) { if (CONST_FOO_ANN) {
console.log("unreachable"); console.log("unreachable");
var moo; var moo;
function bar() {} function bar() { }
} }
if (test === "test") { if (test === "test") {
var beef = "good"; var beef = "good";
var meat = "beef"; /** @const */ var meat = "beef";
var pork = "bad"; var pork = "bad";
if (meat === "pork") { if (meat === "pork") {
console.log("also unreachable"); console.log("also unreachable");

View File

@ -1,4 +1,3 @@
var unused; var unused;
const CONST_FOO = !1; const CONST_FOO = !1;
var moo; var moo, bar;
var bar;

View File

@ -1,6 +1,4 @@
var foo; var foo, bar;
var bar; var x = 10, y;
var moo; var moo;
var x = 10,
y;
bar(); bar();

View File

@ -1,6 +1,5 @@
"use strict"; "use strict";
var foo; var foo;
var x = 10, y;
var moo; var moo;
var x = 10,
y;
bar(); bar();

View File

@ -412,14 +412,20 @@ pub struct Hoister {
impl Visit for Hoister { impl Visit for Hoister {
noop_visit_type!(); noop_visit_type!();
fn visit_assign_expr(&mut self, node: &AssignExpr) {
node.right.visit_children_with(self);
}
fn visit_assign_pat_prop(&mut self, node: &AssignPatProp) { fn visit_assign_pat_prop(&mut self, node: &AssignPatProp) {
node.value.visit_with(self); node.value.visit_with(self);
self.vars.push(node.key.clone()); self.vars.push(node.key.clone());
} }
fn visit_assign_expr(&mut self, node: &AssignExpr) { fn visit_fn_decl(&mut self, f: &FnDecl) {
node.right.visit_children_with(self); self.vars.push(f.ident.clone());
f.visit_children_with(self)
} }
fn visit_pat(&mut self, p: &Pat) { fn visit_pat(&mut self, p: &Pat) {