Skip to content

Commit

Permalink
fix(es/minifier): Apply new SyntaxContext to inlined Arrow correc…
Browse files Browse the repository at this point in the history
…tly (#8312)
  • Loading branch information
Austaras authored Nov 19, 2023
1 parent a004842 commit 572ad63
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 270 deletions.
130 changes: 36 additions & 94 deletions crates/swc_ecma_minifier/src/compress/optimize/iife.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use std::{collections::HashMap, mem::swap};

use rustc_hash::FxHashMap;
use swc_common::{pass::Either, util::take::Take, Mark, Spanned, SyntaxContext, DUMMY_SP};
use swc_common::{pass::Either, util::take::Take, Spanned, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_utils::{
contains_arguments, contains_this_expr, find_pat_ids, undefined, ExprFactory, Remapper,
contains_arguments, contains_this_expr, find_pat_ids, undefined, ExprFactory,
};
use swc_ecma_visit::VisitMutWith;

Expand Down Expand Up @@ -505,42 +505,26 @@ impl Optimizer<'_> {

self.changed = true;

// We remap variables.
//
// For arrow expressions this is required because we copy simple arrow
// expressions.
let new_ctxt = SyntaxContext::empty().apply_mark(Mark::new());
let remap = param_ids
let vars = param_ids
.iter()
.map(|p| (p.to_id(), new_ctxt))
.collect::<FxHashMap<_, _>>();

{
let vars = param_ids
.iter()
.map(|name| VarDeclarator {
.map(|name| VarDeclarator {
span: DUMMY_SP,
name: name.clone().into(),
init: Default::default(),
definite: Default::default(),
})
.collect::<Vec<_>>();

if !vars.is_empty() {
self.prepend_stmts.push(
VarDecl {
span: DUMMY_SP,
name: Ident::new(
name.sym.clone(),
name.span.with_ctxt(new_ctxt),
)
.into(),
init: Default::default(),
definite: Default::default(),
})
.collect::<Vec<_>>();

if !vars.is_empty() {
self.prepend_stmts.push(
VarDecl {
span: DUMMY_SP,
kind: VarDeclKind::Var,
declare: Default::default(),
decls: vars,
}
.into(),
);
}
kind: VarDeclKind::Var,
declare: Default::default(),
decls: vars,
}
.into(),
)
}

let mut exprs = vec![Box::new(make_number(DUMMY_SP, 0.0))];
Expand All @@ -549,13 +533,7 @@ impl Optimizer<'_> {
exprs.push(Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: PatOrExpr::Pat(
Ident::new(
param.sym.clone(),
param.span.with_ctxt(new_ctxt),
)
.into(),
),
left: PatOrExpr::Pat(param.clone().into()),
right: arg.expr.take(),
})));
}
Expand All @@ -569,7 +547,6 @@ impl Optimizer<'_> {
if self.vars.inline_with_multi_replacer(body) {
self.changed = true;
}
body.visit_mut_with(&mut Remapper::new(&remap));
exprs.push(body.take());

report_change!("inline: Inlining a call to an arrow function");
Expand Down Expand Up @@ -832,71 +809,29 @@ impl Optimizer<'_> {

fn inline_fn_like(
&mut self,
orig_params: &[Ident],
params: &[Ident],
body: &mut BlockStmt,
args: &mut [ExprOrSpread],
) -> Option<Expr> {
if !self.can_inline_fn_like(orig_params, &*body) {
if !self.can_inline_fn_like(params, &*body) {
return None;
}

// We remap variables.
let mut remap = HashMap::default();
let new_ctxt = SyntaxContext::empty().apply_mark(Mark::new());

let params = orig_params
.iter()
.map(|i| {
// As the result of this function comes from `params` and `body`, we only need
// to remap those.

let new = Ident::new(i.sym.clone(), i.span.with_ctxt(new_ctxt));
remap.insert(i.to_id(), new_ctxt);
new
})
.collect::<Vec<_>>();

for stmt in &body.stmts {
if let Stmt::Decl(Decl::Var(var)) = stmt {
for decl in &var.decls {
let ids: Vec<Id> = find_pat_ids(&decl.name);

for id in ids {
let ctx = remap
.entry(id.clone())
.or_insert_with(|| SyntaxContext::empty().apply_mark(Mark::new()));

// [is_skippable_for_seq] would check fn scope
if let Some(usage) = self.data.vars.get(&id) {
let mut usage = usage.clone();
// as we turn var declaration into assignment
// we need to maintain correct var usage
if decl.init.is_some() {
usage.ref_count += 1;
}
self.data.vars.insert((id.0, *ctx), usage);
}
}
}
}
}

if self.vars.inline_with_multi_replacer(body) {
self.changed = true;
}
body.visit_mut_with(&mut Remapper::new(&remap));

let mut vars = Vec::new();
let mut exprs = Vec::new();
let param_len = params.len();

for (idx, param) in params.into_iter().enumerate() {
for (idx, param) in params.iter().enumerate() {
let arg = args.get_mut(idx).map(|arg| arg.expr.take());

let no_arg = arg.is_none();

if let Some(arg) = arg {
if let Some(usage) = self.data.vars.get(&orig_params[idx].to_id()) {
if let Some(usage) = self.data.vars.get(&params[idx].to_id()) {
if usage.ref_count == 1
&& !usage.reassigned
&& usage.property_mutation_count == 0
Expand All @@ -911,9 +846,6 @@ impl Optimizer<'_> {
self.vars.vars_for_inlining.insert(param.to_id(), arg);
continue;
}

let usage = usage.clone();
self.data.vars.insert(param.to_id(), usage);
}

exprs.push(
Expand All @@ -929,7 +861,7 @@ impl Optimizer<'_> {

vars.push(VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(param.into()),
name: Pat::Ident(param.clone().into()),
init: if self.ctx.executed_multiple_time && no_arg {
Some(undefined(DUMMY_SP))
} else {
Expand Down Expand Up @@ -964,6 +896,16 @@ impl Optimizer<'_> {
Stmt::Decl(Decl::Var(ref mut var)) => {
for decl in &mut var.decls {
if decl.init.is_some() {
let ids = find_pat_ids(decl);

for id in ids {
if let Some(usage) = self.data.vars.get_mut(&id) {
// as we turn var declaration into assignment
// we need to maintain correct var usage
usage.ref_count += 1;
}
}

exprs.push(Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
op: op!("="),
Expand Down
32 changes: 20 additions & 12 deletions crates/swc_ecma_minifier/src/compress/optimize/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -833,19 +833,27 @@ impl Optimizer<'_> {
let bindings: AHashSet<Id> = collect_decls(&*value);
let new_mark = Mark::new();
let mut cache = FxHashMap::default();
let remap: FxHashMap<_, _> = bindings
.into_iter()
.map(|id| {
let value = cache
.entry(id.1)
.or_insert_with(|| id.1.apply_mark(new_mark));

(id, *value)
})
.collect();
let mut remap = FxHashMap::default();

for id in bindings {
let new_ctxt = cache
.entry(id.1)
.or_insert_with(|| id.1.apply_mark(new_mark));

let new_ctxt = *new_ctxt;

if let Some(usage) = self.data.vars.get(&id).cloned() {
let new_id = (id.0.clone(), new_ctxt);
self.data.vars.insert(new_id, usage);
}

remap.insert(id, new_ctxt);
}

let mut remapper = Remapper::new(&remap);
value.visit_mut_with(&mut remapper);
if !remap.is_empty() {
let mut remapper = Remapper::new(&remap);
value.visit_mut_with(&mut remapper);
}

self.changed = true;
report_change!("inline: Replacing a variable `{}` with cheap expression", i);
Expand Down
30 changes: 27 additions & 3 deletions crates/swc_ecma_minifier/src/compress/optimize/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use std::{

use rustc_hash::{FxHashMap, FxHashSet};
use swc_atoms::JsWord;
use swc_common::{util::take::Take, Span, DUMMY_SP};
use swc_common::{collections::AHashSet, util::take::Take, Mark, Span, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_transforms_base::perf::{Parallel, ParallelExt};
use swc_ecma_utils::{ExprCtx, ExprExt};
use swc_ecma_utils::{collect_decls, ExprCtx, ExprExt, Remapper};
use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};
use tracing::debug;

Expand Down Expand Up @@ -243,7 +243,31 @@ impl Parallel for Finalizer<'_> {
impl<'a> Finalizer<'a> {
fn var(&mut self, i: &Id, mode: FinalizerMode) -> Option<Box<Expr>> {
let mut e = match mode {
FinalizerMode::Callee => self.simple_functions.get(i).cloned()?,
FinalizerMode::Callee => {
let mut value = self.simple_functions.get(i).cloned()?;
let mut cache = FxHashMap::default();
let mut remap = FxHashMap::default();
let bindings: AHashSet<Id> = collect_decls(&*value);
let new_mark = Mark::new();

// at this point, var usage no longer matter
for id in bindings {
let new_ctxt = cache
.entry(id.1)
.or_insert_with(|| id.1.apply_mark(new_mark));

let new_ctxt = *new_ctxt;

remap.insert(id, new_ctxt);
}

if !remap.is_empty() {
let mut remapper = Remapper::new(&remap);
value.visit_mut_with(&mut remapper);
}

value
}
FinalizerMode::ComparisonWithLit => self.lits_for_cmp.get(i).cloned()?,
FinalizerMode::MemberAccess => self.lits_for_array_access.get(i).cloned()?,
};
Expand Down
10 changes: 5 additions & 5 deletions crates/swc_ecma_minifier/tests/benches-full/echarts.js
Original file line number Diff line number Diff line change
Expand Up @@ -15071,7 +15071,7 @@
var splitNumber1, result, span, interval, precision, extent = this._extent, span1 = extent[1] - extent[0];
if (isFinite(span1)) {
span1 < 0 && (span1 = -span1, extent.reverse());
var interval1, niceTickExtent, result1 = (splitNumber1 = splitNumber, result = {}, span = extent[1] - extent[0], interval = result.interval = nice(span / splitNumber1, !0), null != minInterval && interval < minInterval && (interval = result.interval = minInterval), null != maxInterval && interval > maxInterval && (interval = result.interval = maxInterval), precision = result.intervalPrecision = getPrecisionSafe(interval) + 2, isFinite((niceTickExtent = result.niceTickExtent = [
var niceTickExtent, result1 = (splitNumber1 = splitNumber, result = {}, span = extent[1] - extent[0], interval = result.interval = nice(span / splitNumber1, !0), null != minInterval && interval < minInterval && (interval = result.interval = minInterval), null != maxInterval && interval > maxInterval && (interval = result.interval = maxInterval), precision = result.intervalPrecision = getPrecisionSafe(interval) + 2, isFinite((niceTickExtent = result.niceTickExtent = [
round(Math.ceil(extent[0] / interval) * interval, precision),
round(Math.floor(extent[1] / interval) * interval, precision)
])[0]) || (niceTickExtent[0] = extent[0]), isFinite(niceTickExtent[1]) || (niceTickExtent[1] = extent[1]), clamp(niceTickExtent, 0, extent), clamp(niceTickExtent, 1, extent), niceTickExtent[0] > niceTickExtent[1] && (niceTickExtent[0] = niceTickExtent[1]), result);
Expand Down Expand Up @@ -15578,16 +15578,16 @@
return __extends(LogScale, _super), LogScale.prototype.getTicks = function(expandToNicedExtent) {
var originalScale = this._originalScale, extent = this._extent, originalExtent = originalScale.getExtent();
return map(intervalScaleProto.getTicks.call(this, expandToNicedExtent), function(tick) {
var val, originalVal, val1, originalVal1, val2 = tick.value, powVal = round(mathPow$1(this.base, val2));
return powVal = val2 === extent[0] && this._fixMin ? round(powVal, getPrecisionSafe(originalExtent[0])) : powVal, {
value: powVal = val2 === extent[1] && this._fixMax ? round(powVal, getPrecisionSafe(originalExtent[1])) : powVal
var val = tick.value, powVal = round(mathPow$1(this.base, val));
return powVal = val === extent[0] && this._fixMin ? round(powVal, getPrecisionSafe(originalExtent[0])) : powVal, {
value: powVal = val === extent[1] && this._fixMax ? round(powVal, getPrecisionSafe(originalExtent[1])) : powVal
};
}, this);
}, LogScale.prototype.setExtent = function(start, end) {
var base = this.base;
start = mathLog(start) / mathLog(base), end = mathLog(end) / mathLog(base), intervalScaleProto.setExtent.call(this, start, end);
}, LogScale.prototype.getExtent = function() {
var originalVal, originalVal1, base = this.base, extent = scaleProto.getExtent.call(this);
var base = this.base, extent = scaleProto.getExtent.call(this);
extent[0] = mathPow$1(base, extent[0]), extent[1] = mathPow$1(base, extent[1]);
var originalExtent = this._originalScale.getExtent();
return this._fixMin && (extent[0] = round(extent[0], getPrecisionSafe(originalExtent[0]))), this._fixMax && (extent[1] = round(extent[1], getPrecisionSafe(originalExtent[1]))), extent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
}
function delimit(type) {
var begin, end;
return begin = position - 1, end = function delimiter(type) {
return (begin = position - 1, end = function delimiter(type) {
for(; next();)switch(character){
case type:
return position;
Expand All @@ -133,7 +133,7 @@
next();
}
return position;
}(91 === type ? type + 2 : 40 === type ? type + 1 : type), Utility_substr(characters, begin, end).trim();
}(91 === type ? type + 2 : 40 === type ? type + 1 : type), Utility_substr(characters, begin, end)).trim();
}
var MS = "-ms-", MOZ = "-moz-", WEBKIT = "-webkit-", COMMENT = "comm", Enum_RULESET = "rule", DECLARATION = "decl";
function serialize(children, callback) {
Expand Down Expand Up @@ -485,7 +485,7 @@
};
Object.prototype.hasOwnProperty;
var EmotionCacheContext = (0, react.createContext)("undefined" != typeof HTMLElement ? function(options) {
var callback, container, currentSheet, collection, length, key = options.key;
var collection, length, callback, container, currentSheet, key = options.key;
if ("css" === key) {
var ssrStyles = document.querySelectorAll("style[data-emotion]:not([data-s])");
Array.prototype.forEach.call(ssrStyles, function(node) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4110,8 +4110,8 @@
}
}
function cc(t, e, n) {
var t1;
if (t.isPrimaryClient && 0 === n || !t.isPrimaryClient && 1 === n) {
var t1;
let s;
const t2 = [];
t.Oo.forEach((n, s)=>{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
var i = 0, l = (c)=>"checkbox" === c.type;
var k = (c, o)=>{
var f;
return c.has((f = o, f.substring(0, f.search(/\.\d+(\.|$)/)) || f));
return c.has((f = o).substring(0, f.search(/\.\d+(\.|$)/)) || f);
}, v = ()=>{};
function b(c, o, f) {}
var g = (c)=>"radio" === c.type;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26421,8 +26421,8 @@
do try {
!function() {
for(; null !== nj;){
var e, t = nj.effectTag;
0 != (256 & t) && function(e, t) {
var e, t, r = nj.effectTag;
0 != (256 & r) && function(e, t) {
switch(t.tag){
case 0:
case 11:
Expand All @@ -26444,9 +26444,9 @@
default:
throw Error(d(163));
}
}(nj.alternate, nj), 0 == (512 & t) || nL || (nL = !0, e = function() {
}(nj.alternate, nj), 0 == (512 & r) || nL || (nL = !0, e = 97, t = function() {
return it(), null;
}, eK(ta(97), e, void 0)), nj = nj.nextEffect;
}, eK(e = ta(e), t, void 0)), nj = nj.nextEffect;
}
}();
} catch (e) {
Expand Down
Loading

0 comments on commit 572ad63

Please sign in to comment.