Skip to content

Commit

Permalink
fix(es/minifier): Make AST compressor respect toplevel (#6775)
Browse files Browse the repository at this point in the history
**Related issue:**

 - Closes #4386.
  • Loading branch information
kdy1 committed Jan 11, 2023
1 parent 267d256 commit 06770cf
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 2 deletions.
5 changes: 4 additions & 1 deletion crates/swc_ecma_minifier/src/compress/optimize/inline.rs
Expand Up @@ -29,7 +29,7 @@ where
&mut self,
ident: &mut Ident,
init: &mut Expr,
should_preserve: bool,
mut should_preserve: bool,
can_drop: bool,
) {
trace_op!(
Expand Down Expand Up @@ -58,6 +58,7 @@ where
if !usage.var_initialized {
return;
}

if self.data.top.used_arguments && usage.declared_as_fn_param {
return;
}
Expand Down Expand Up @@ -95,6 +96,8 @@ where
let is_inline_enabled =
self.options.reduce_vars || self.options.collapse_vars || self.options.inline != 0;

should_preserve |= !self.options.top_level() && usage.is_top_level;

self.vars.inline_with_multi_replacer(init);

// We inline arrays partially if it's pure (all elements are literal), and not
Expand Down
5 changes: 5 additions & 0 deletions crates/swc_ecma_minifier/src/program_data.rs
Expand Up @@ -121,6 +121,9 @@ pub(crate) struct VarUsageInfo {

pub(crate) pure_fn: bool,

/// Is the variable declared in top level?
pub(crate) is_top_level: bool,

/// `infects_to`. This should be renamed, but it will be done with another
/// PR. (because it's hard to review)
infects: Vec<Access>,
Expand Down Expand Up @@ -168,6 +171,7 @@ impl Default for VarUsageInfo {
used_in_non_child_fn: Default::default(),
accessed_props: Default::default(),
used_recursively: Default::default(),
is_top_level: Default::default(),
}
}
}
Expand Down Expand Up @@ -346,6 +350,7 @@ impl Storage for ProgramData {
// }

let v = self.vars.entry(i.to_id()).or_default();
v.is_top_level |= ctx.is_top_level;

if has_init && (v.declared || v.var_initialized) {
#[cfg(feature = "debug")]
Expand Down
@@ -0,0 +1,4 @@
{
"defaults": true,
"toplevel": false
}
24 changes: 24 additions & 0 deletions crates/swc_ecma_minifier/tests/fixture/issues/4386/1/input.js
@@ -0,0 +1,24 @@
var application;
(() => {
var __webpack_require__ = {};
(() => {
__webpack_require__.d = (exports, definition) => {
};
})();
(() => {
__webpack_require__.o = (obj, prop) => { };
})();
(() => {
__webpack_require__.r = (exports) => {
};
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
"bootstrap": () => (bootstrap)
});
function bootstrap() {
alert();
}
application = __webpack_exports__;
})();
12 changes: 12 additions & 0 deletions crates/swc_ecma_minifier/tests/fixture/issues/4386/1/output.js
@@ -0,0 +1,12 @@
var application;
(()=>{
var __webpack_require__ = {};
__webpack_require__.d = (exports, definition)=>{}, __webpack_require__.o = (obj, prop)=>{}, __webpack_require__.r = (exports)=>{};
var __webpack_exports__ = {};
function bootstrap() {
alert();
}
__webpack_require__.r(__webpack_exports__), __webpack_require__.d(__webpack_exports__, {
bootstrap: ()=>bootstrap
}), application = __webpack_exports__;
})();
@@ -0,0 +1,4 @@
{
"defaults": true,
"toplevel": true
}
24 changes: 24 additions & 0 deletions crates/swc_ecma_minifier/tests/fixture/issues/4386/2/input.js
@@ -0,0 +1,24 @@
var application;
(() => {
var __webpack_require__ = {};
(() => {
__webpack_require__.d = (exports, definition) => {
};
})();
(() => {
__webpack_require__.o = (obj, prop) => { };
})();
(() => {
__webpack_require__.r = (exports) => {
};
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
"bootstrap": () => (bootstrap)
});
function bootstrap() {
alert();
}
application = __webpack_exports__;
})();
11 changes: 11 additions & 0 deletions crates/swc_ecma_minifier/tests/fixture/issues/4386/2/output.js
@@ -0,0 +1,11 @@
(()=>{
var __webpack_require__ = {};
__webpack_require__.d = (exports, definition)=>{}, __webpack_require__.o = (obj, prop)=>{}, __webpack_require__.r = (exports)=>{};
var __webpack_exports__ = {};
function bootstrap() {
alert();
}
__webpack_require__.r(__webpack_exports__), __webpack_require__.d(__webpack_exports__, {
bootstrap: ()=>bootstrap
});
})();
@@ -0,0 +1,4 @@
{
"defaults": true,
"toplevel": true
}
Expand Up @@ -633,6 +633,14 @@ impl TreeShaker {
} else if !self.in_block_stmt {
return false;
}

// Abort if the variable is declared on top level scope.
let ix = self.data.graph_ix.get_index_of(&name);
if let Some(ix) = ix {
if self.data.entries.contains(&(ix as u32)) {
return false;
}
}
}

if self.config.top_retain.contains(&name.0) {
Expand Down
3 changes: 3 additions & 0 deletions crates/swc_ecma_usage_analyzer/src/analyzer/ctx.rs
Expand Up @@ -21,6 +21,7 @@ where
}

#[derive(Debug, Default, Clone, Copy)]
#[non_exhaustive]
pub struct Ctx {
/// See [crate::marks::Marks]
pub skip_standalone: bool,
Expand Down Expand Up @@ -60,6 +61,8 @@ pub struct Ctx {
pub inline_prevented: bool,

pub is_op_assign: bool,

pub is_top_level: bool,
}

pub(super) struct WithCtx<'a, S>
Expand Down
7 changes: 6 additions & 1 deletion crates/swc_ecma_usage_analyzer/src/analyzer/mod.rs
Expand Up @@ -79,7 +79,10 @@ where
let mut child = UsageAnalyzer {
data: Default::default(),
marks: self.marks,
ctx: self.ctx,
ctx: Ctx {
is_top_level: false,
..self.ctx
},
scope: Default::default(),
used_recursively: self.used_recursively.clone(),
};
Expand Down Expand Up @@ -849,6 +852,7 @@ where
fn visit_module(&mut self, n: &Module) {
let ctx = Ctx {
skip_standalone: true,
is_top_level: true,
..self.ctx
};
n.visit_children_with(&mut *self.with_ctx(ctx))
Expand All @@ -857,6 +861,7 @@ where
fn visit_script(&mut self, n: &Script) {
let ctx = Ctx {
skip_standalone: true,
is_top_level: true,
..self.ctx
};
n.visit_children_with(&mut *self.with_ctx(ctx))
Expand Down

0 comments on commit 06770cf

Please sign in to comment.