-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
fix: expose GlobalPassOption.build #10968
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
fix: expose GlobalPassOption.build #10968
Conversation
|
7d44c39
to
278b1a8
Compare
CodSpeed Performance ReportMerging #10968 will not alter performanceComparing Summary
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I intentionally hide this to reduce maintenance burden.
Is copying the source code of the function acceptable? It's a wrapper for a visitor creator function so I think it's trivial enough, and Wasm plugin should not depend on the swc
crate
use dashmap::DashMap;
use once_cell::sync::Lazy;
use rustc_hash::{FxBuildHasher, FxHashMap};
use std::{collections::HashMap, env, sync::Arc};
use swc_core::{
atoms::Atom,
base::config::{GlobalInliningPassEnvs, GlobalPassOption},
common::{errors::Handler, FileName, Mark, SourceMap},
ecma::{
ast::*,
parser::{parse_file_as_expr, Syntax},
transforms::optimization::{inline_globals, GlobalExprMap},
utils::NodeIgnoringSpan,
},
};
pub fn opts_build(
global_pass_option: GlobalPassOption,
cm: &SourceMap,
handler: &Handler,
unresolved_mark: Mark,
) -> impl 'static + Pass {
type ValuesMap = Arc<FxHashMap<Atom, Expr>>;
fn expr(cm: &SourceMap, handler: &Handler, src: String) -> Box<Expr> {
let fm = cm.new_source_file(FileName::Anon.into(), src);
let mut errors = Vec::new();
let expr = parse_file_as_expr(
&fm,
Syntax::Es(Default::default()),
Default::default(),
None,
&mut errors,
);
for e in errors {
e.into_diagnostic(handler).emit()
}
match expr {
Ok(v) => v,
_ => panic!("{} is not a valid expression", fm.src),
}
}
fn mk_map(
cm: &SourceMap,
handler: &Handler,
values: impl Iterator<Item = (Atom, Atom)>,
is_env: bool,
) -> ValuesMap {
let mut m = HashMap::default();
for (k, v) in values {
let v = if is_env {
format!("'{v}'")
} else {
(*v).into()
};
let v_str = v.clone();
let e = expr(cm, handler, v_str);
m.insert((*k).into(), *e);
}
Arc::new(m)
}
let env_map = if cfg!(target_arch = "wasm32") {
Arc::new(Default::default())
} else {
match &global_pass_option.envs {
GlobalInliningPassEnvs::List(env_list) => {
static CACHE: Lazy<DashMap<Vec<String>, ValuesMap, FxBuildHasher>> =
Lazy::new(Default::default);
let cache_key = env_list.iter().cloned().collect::<Vec<_>>();
if let Some(v) = CACHE.get(&cache_key).as_deref().cloned() {
v
} else {
let map = mk_map(
cm,
handler,
env::vars()
.filter(|(k, _)| env_list.contains(k))
.map(|(k, v)| (k.into(), v.into())),
true,
);
CACHE.insert(cache_key, map.clone());
map
}
}
GlobalInliningPassEnvs::Map(map) => {
static CACHE: Lazy<DashMap<Vec<(Atom, Atom)>, ValuesMap, FxBuildHasher>> =
Lazy::new(Default::default);
let cache_key = global_pass_option
.vars
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect::<Vec<_>>();
if let Some(v) = CACHE.get(&cache_key) {
(*v).clone()
} else {
let map = mk_map(
cm,
handler,
map.iter().map(|(k, v)| (k.clone(), v.clone())),
false,
);
CACHE.insert(cache_key, map.clone());
map
}
}
}
};
let global_exprs = {
static CACHE: Lazy<DashMap<Vec<(Atom, Atom)>, GlobalExprMap, FxBuildHasher>> =
Lazy::new(Default::default);
let cache_key = global_pass_option
.vars
.iter()
.filter(|(k, _)| k.contains('.'))
.map(|(k, v)| (k.clone(), v.clone()))
.collect::<Vec<_>>();
if let Some(v) = CACHE.get(&cache_key) {
(*v).clone()
} else {
let map = global_pass_option
.vars
.iter()
.filter(|(k, _)| k.contains('.'))
.map(|(k, v)| {
(
NodeIgnoringSpan::owned(*expr(cm, handler, k.to_string())),
*expr(cm, handler, v.to_string()),
)
})
.collect::<FxHashMap<_, _>>();
let map = Arc::new(map);
CACHE.insert(cache_key, map.clone());
map
}
};
let global_map = {
static CACHE: Lazy<DashMap<Vec<(Atom, Atom)>, ValuesMap, FxBuildHasher>> =
Lazy::new(Default::default);
let cache_key = global_pass_option
.vars
.iter()
.filter(|(k, _)| !k.contains('.'))
.map(|(k, v)| (k.clone(), v.clone()))
.collect::<Vec<_>>();
if let Some(v) = CACHE.get(&cache_key) {
(*v).clone()
} else {
let map = mk_map(
cm,
handler,
global_pass_option
.vars
.into_iter()
.filter(|(k, _)| !k.contains('.')),
false,
);
CACHE.insert(cache_key, map.clone());
map
}
};
inline_globals(
unresolved_mark,
env_map,
global_map,
global_exprs,
Arc::new(global_pass_option.typeofs),
)
} I attempted to copy the source code into our codebase and implement it as shown below, but it's not working as expected. Could you help me find a better implementation approach, or simply expose let define_dce_plugin = {
let opts = GlobalPassOption {
vars: match &options.define_dce {
Either::A(_) => Default::default(),
Either::B(config) => {
let mut map = indexmap::IndexMap::<_, _, FxBuildHasher>::default();
for (key, value) in &config.define {
map.insert(key.as_str().into(), value.as_str().into());
}
map
}
},
envs: Default::default(),
typeofs: Default::default(),
};
HANDLER.with(|handler| {
Optional::new(
opts_build(opts, &cm, handler, unresolved_mark),
matches!(options.define_dce, Either::B(_)),
)
})
}; |
This PR #10449 changed
GlobalPassOption.build
topub(crate)
, but ReactLynx's WASM plugin depends on it (see https://github.com/lynx-family/lynx-stack/blob/main/packages/react/transform/src/lib.rs#L412).When upgrading
swc_core
, we encountered a crash due to this change. This PR aims to restoreGlobalPassOption.build
topub
.