fix(es/minifier): Apply new SyntaxContext to inlined Arrow (#8301)

**Related issue:**

 - Closes #8288
This commit is contained in:
Austaras 2023-11-18 08:01:27 +08:00 committed by GitHub
parent ba9d2f56cc
commit c18a959e3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 28 deletions

View File

@ -509,12 +509,11 @@ impl Optimizer<'_> {
//
// For arrow expressions this is required because we copy simple arrow
// expressions.
let mut remap = HashMap::default();
let new_ctxt = SyntaxContext::empty().apply_mark(Mark::fresh(Mark::root()));
for p in param_ids.iter() {
remap.insert(p.to_id(), new_ctxt);
}
let new_ctxt = SyntaxContext::empty().apply_mark(Mark::new());
let remap = param_ids
.iter()
.map(|p| (p.to_id(), new_ctxt))
.collect::<FxHashMap<_, _>>();
{
let vars = param_ids
@ -843,7 +842,7 @@ impl Optimizer<'_> {
// We remap variables.
let mut remap = HashMap::default();
let new_ctxt = SyntaxContext::empty().apply_mark(Mark::fresh(Mark::root()));
let new_ctxt = SyntaxContext::empty().apply_mark(Mark::new());
let params = orig_params
.iter()
@ -857,27 +856,25 @@ impl Optimizer<'_> {
})
.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 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()));
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);
// [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);
}
}
}

View File

@ -1,8 +1,9 @@
use swc_common::{util::take::Take, EqIgnoreSpan, Spanned};
use rustc_hash::FxHashMap;
use swc_common::{collections::AHashSet, util::take::Take, EqIgnoreSpan, Mark, Spanned};
use swc_ecma_ast::*;
use swc_ecma_transforms_optimization::simplify::expr_simplifier;
use swc_ecma_usage_analyzer::alias::{collect_infects_from, AliasConfig};
use swc_ecma_utils::{class_has_side_effect, find_pat_ids, ExprExt};
use swc_ecma_utils::{class_has_side_effect, collect_decls, find_pat_ids, ExprExt, Remapper};
use swc_ecma_visit::VisitMutWith;
use super::Optimizer;
@ -808,7 +809,7 @@ impl Optimizer<'_> {
}
Expr::Ident(i) => {
let id = i.to_id();
if let Some(value) = self
if let Some(mut value) = self
.vars
.lits
.get(&id)
@ -827,6 +828,25 @@ impl Optimizer<'_> {
return;
}
// currently renamer relies on the fact no distinct var has same ctxt, we need
// to remap all new bindings.
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 remapper = Remapper::new(&remap);
value.visit_mut_with(&mut remapper);
self.changed = true;
report_change!("inline: Replacing a variable `{}` with cheap expression", i);

View File

@ -0,0 +1,30 @@
function memoizeWithArgs(fnWithArgs, options) {
const fn = proxyMemoize((args) => fnWithArgs(...args), options);
return (...args) => fn(args);
}
function makeSelector(selector, selectorTransformer) {
return (state) => selectorTransformer(selector(state));
}
export function createSelectorHook(selector) {
const useSelectorHook = (selectorTransformer, deps) => {
const memoSelector = useMemo(
() =>
selectorTransformer && deps
? makeSelector(
selector,
memoizeWithArgs(selectorTransformer)
)
: undefined,
deps
);
const finalSelector = memoSelector
? memoSelector
: selectorTransformer
? makeSelector(selector, selectorTransformer)
: selector;
return useSelector(finalSelector);
};
return useSelectorHook;
}

View File

@ -0,0 +1 @@
export function createSelectorHook(e){return(o,r)=>{const t=useMemo(()=>{var t;return o&&r?(t=function(e,o){const r=proxyMemoize(o=>e(...o),void 0);return(...e)=>r(e)}(o),o=>t(e(o))):void 0},r)||(o?r=>o(e(r)):e);return useSelector(t)}}