mirror of
https://github.com/swc-project/swc.git
synced 2024-12-01 09:52:57 +03:00
perf(es/transforms): Reduce usage of #[fast_path]
(#2439)
swc_ecma_transforms_compat: - Remove `#[fast_path]` from passes. - Migrate some passes to `VisitMut`.
This commit is contained in:
parent
d045244089
commit
e722bd4887
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -2815,7 +2815,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_compat"
|
||||
version = "0.43.0"
|
||||
version = "0.43.1"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"arrayvec",
|
||||
@ -3156,7 +3156,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "swc_visit"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
dependencies = [
|
||||
"either",
|
||||
"swc_visit_macros",
|
||||
|
@ -56,6 +56,8 @@ macro_rules! mark_nested {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl<'a> Fold for SuperFieldAccessFolder<'a> {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -6,7 +6,7 @@ edition = "2018"
|
||||
license = "Apache-2.0/MIT"
|
||||
name = "swc_ecma_transforms_compat"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
version = "0.43.0"
|
||||
version = "0.43.1"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
|
@ -18,6 +18,7 @@ struct AsyncArrowsInClass {
|
||||
vars: Vec<VarDeclarator>,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for AsyncArrowsInClass {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -13,6 +13,7 @@ struct EdgeDefaultParam {
|
||||
in_arrow: bool,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for EdgeDefaultParam {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -55,6 +55,7 @@ impl TemplateLiteralCaching {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for TemplateLiteralCaching {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -67,6 +67,7 @@ struct Arrow {
|
||||
vars: Vec<VarDeclarator>,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
#[fast_path(ArrowVisitor)]
|
||||
impl Fold for Arrow {
|
||||
noop_fold_type!();
|
||||
@ -238,6 +239,7 @@ struct ArgumentsReplacer {
|
||||
found: bool,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for ArgumentsReplacer {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -12,6 +12,7 @@ pub fn block_scoped_functions() -> impl Fold {
|
||||
#[derive(Clone, Copy)]
|
||||
struct BlockScopedFns;
|
||||
|
||||
/// TODO: VisitMut
|
||||
#[fast_path(BlockScopedFnFinder)]
|
||||
impl Fold for BlockScopedFns {
|
||||
noop_fold_type!();
|
||||
|
@ -418,6 +418,7 @@ impl BlockScoping {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for BlockScoping {
|
||||
noop_fold_type!();
|
||||
|
||||
@ -761,6 +762,7 @@ impl<'a> FlowHelper<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for FlowHelper<'_> {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -180,6 +180,7 @@ pub(super) enum SuperFoldingMode {
|
||||
Var,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for ConstructorFolder<'_> {
|
||||
noop_fold_type!();
|
||||
fold_only_key!();
|
||||
@ -425,6 +426,7 @@ pub(super) fn replace_this_in_constructor(mark: Mark, c: Constructor) -> (Constr
|
||||
in_injected_define_property_call: bool,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for Replacer {
|
||||
noop_fold_type!();
|
||||
|
||||
@ -543,6 +545,7 @@ pub(super) struct VarRenamer<'a> {
|
||||
pub class_name: &'a JsWord,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl<'a> Fold for VarRenamer<'a> {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -179,6 +179,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
#[fast_path(ClassFinder)]
|
||||
impl<C> Fold for Classes<C>
|
||||
where
|
||||
|
@ -47,6 +47,7 @@ struct ObjectLitFolder {
|
||||
used_define_enum_props: bool,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for ObjectLitFolder {
|
||||
noop_fold_type!();
|
||||
|
||||
@ -288,6 +289,7 @@ impl Visit for ComplexVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for ComputedProps {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -448,6 +448,7 @@ impl AssignFolder {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
#[fast_path(DestructuringVisitor)]
|
||||
impl Fold for Destructuring {
|
||||
noop_fold_type!();
|
||||
@ -522,6 +523,7 @@ struct AssignFolder {
|
||||
ignore_return_value: Option<()>,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
#[fast_path(DestructuringVisitor)]
|
||||
impl Fold for AssignFolder {
|
||||
noop_fold_type!();
|
||||
|
@ -398,6 +398,7 @@ impl Actual {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for Actual {
|
||||
noop_fold_type!();
|
||||
|
||||
@ -503,6 +504,7 @@ fn make_finally_block(
|
||||
})
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for ForOf {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use swc_common::util::take::Take;
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::{helper, perf::Check};
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_transforms_base::helper;
|
||||
use swc_ecma_utils::ExprFactory;
|
||||
use swc_ecma_visit::{noop_fold_type, noop_visit_type, Fold, FoldWith, Node, Visit, VisitWith};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
|
||||
/// `@babel/plugin-transform-instanceof`
|
||||
///
|
||||
@ -29,17 +29,16 @@ use swc_ecma_visit::{noop_fold_type, noop_visit_type, Fold, FoldWith, Node, Visi
|
||||
///
|
||||
/// _instanceof(foo, Bar);
|
||||
/// ```
|
||||
pub fn instance_of() -> impl Fold {
|
||||
InstanceOf
|
||||
pub fn instance_of() -> impl Fold + VisitMut {
|
||||
as_folder(InstanceOf)
|
||||
}
|
||||
struct InstanceOf;
|
||||
|
||||
#[fast_path(InstnaceOfFinder)]
|
||||
impl Fold for InstanceOf {
|
||||
noop_fold_type!();
|
||||
impl VisitMut for InstanceOf {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn fold_expr(&mut self, expr: Expr) -> Expr {
|
||||
let expr = expr.fold_children_with(self);
|
||||
fn visit_mut_expr(&mut self, expr: &mut Expr) {
|
||||
expr.visit_mut_children_with(self);
|
||||
|
||||
match expr {
|
||||
Expr::Bin(BinExpr {
|
||||
@ -47,36 +46,15 @@ impl Fold for InstanceOf {
|
||||
left,
|
||||
op: op!("instanceof"),
|
||||
right,
|
||||
}) => Expr::Call(CallExpr {
|
||||
span,
|
||||
callee: helper!(span, instanceof, "instanceof"),
|
||||
args: vec![left.as_arg(), right.as_arg()],
|
||||
type_args: Default::default(),
|
||||
}),
|
||||
_ => expr,
|
||||
}) => {
|
||||
*expr = Expr::Call(CallExpr {
|
||||
span: *span,
|
||||
callee: helper!(*span, instanceof, "instanceof"),
|
||||
args: vec![left.take().as_arg(), right.take().as_arg()],
|
||||
type_args: Default::default(),
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct InstnaceOfFinder {
|
||||
found: bool,
|
||||
}
|
||||
|
||||
impl Visit for InstnaceOfFinder {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_bin_expr(&mut self, e: &BinExpr, _: &dyn Node) {
|
||||
e.visit_children_with(self);
|
||||
|
||||
if e.op == op!("instanceof") {
|
||||
self.found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Check for InstnaceOfFinder {
|
||||
fn should_handle(&self) -> bool {
|
||||
self.found
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,7 @@ use std::borrow::Cow;
|
||||
use swc_atoms::js_word;
|
||||
use swc_common::{pass::CompilerPass, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Check;
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_transforms_base::perf::{should_work, Check};
|
||||
use swc_ecma_utils::{prepend, private_ident, quote_ident, undefined, ExprFactory};
|
||||
use swc_ecma_visit::{
|
||||
as_folder, noop_visit_mut_type, noop_visit_type, Fold, Node, Visit, VisitMut, VisitMutWith,
|
||||
@ -25,12 +24,14 @@ struct NewTarget {
|
||||
var: Option<VarDeclarator>,
|
||||
}
|
||||
|
||||
#[fast_path(ShouldWork)]
|
||||
impl VisitMut for NewTarget {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn visit_mut_arrow_expr(&mut self, e: &mut ArrowExpr) {
|
||||
// #[fast_path] ensures that `e` contains new.target
|
||||
// Ensure that `e` contains new.target
|
||||
if !should_work::<ShouldWork, _>(&*e) {
|
||||
return;
|
||||
}
|
||||
|
||||
let old = self.in_arrow_expr;
|
||||
if self.var.is_none() {
|
||||
@ -143,7 +144,10 @@ impl VisitMut for NewTarget {
|
||||
}
|
||||
|
||||
fn visit_mut_fn_decl(&mut self, f: &mut FnDecl) {
|
||||
// #[fast_path] ensures that `f` contains `new.target`.
|
||||
// Ensure that `f` contains `new.target`.
|
||||
if !should_work::<ShouldWork, _>(&*f) {
|
||||
return;
|
||||
}
|
||||
|
||||
let old = self.cur.take();
|
||||
self.cur = Some(f.ident.clone());
|
||||
@ -154,7 +158,10 @@ impl VisitMut for NewTarget {
|
||||
}
|
||||
|
||||
fn visit_mut_fn_expr(&mut self, f: &mut FnExpr) {
|
||||
// #[fast_path] ensures that `f` contains `new.target`.
|
||||
// Ensure that `f` contains `new.target`.
|
||||
if !should_work::<ShouldWork, _>(&*f) {
|
||||
return;
|
||||
}
|
||||
|
||||
let i = f
|
||||
.ident
|
||||
|
@ -253,6 +253,7 @@ impl Params {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for Params {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -1532,6 +1532,7 @@ struct UnmarkedInvalidHandler {
|
||||
case_id: usize,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for UnmarkedInvalidHandler {
|
||||
noop_fold_type!();
|
||||
|
||||
@ -1553,6 +1554,8 @@ struct InvalidToLit<'a> {
|
||||
// Map from loc-id to stmt index
|
||||
map: &'a [Loc],
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for InvalidToLit<'_> {
|
||||
noop_fold_type!();
|
||||
|
||||
@ -1585,6 +1588,7 @@ struct CatchParamHandler<'a> {
|
||||
param: Option<&'a Pat>,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for CatchParamHandler<'_> {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -56,6 +56,7 @@ impl Hoister {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for Hoister {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -82,6 +82,7 @@ impl Regenerator {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for Regenerator {
|
||||
noop_fold_type!();
|
||||
|
||||
@ -500,6 +501,7 @@ struct FnSentVisitor {
|
||||
ctx: Ident,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for FnSentVisitor {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
use swc_common::util::take::Take;
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Check;
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_utils::quote_ident;
|
||||
use swc_ecma_visit::{noop_fold_type, noop_visit_type, Fold, FoldWith, Node, Visit, VisitWith};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
|
||||
/// Compile ES2015 shorthand properties to ES5
|
||||
///
|
||||
@ -38,58 +37,40 @@ use swc_ecma_visit::{noop_fold_type, noop_visit_type, Fold, FoldWith, Node, Visi
|
||||
/// }
|
||||
/// };
|
||||
/// ```
|
||||
pub fn shorthand() -> impl 'static + Fold {
|
||||
Shorthand
|
||||
pub fn shorthand() -> impl 'static + Fold + VisitMut {
|
||||
as_folder(Shorthand)
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Shorthand;
|
||||
|
||||
#[fast_path(ShorthandFinder)]
|
||||
impl Fold for Shorthand {
|
||||
noop_fold_type!();
|
||||
impl VisitMut for Shorthand {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn fold_prop(&mut self, prop: Prop) -> Prop {
|
||||
let prop = prop.fold_children_with(self);
|
||||
fn visit_mut_prop(&mut self, prop: &mut Prop) {
|
||||
prop.visit_mut_children_with(self);
|
||||
|
||||
match prop {
|
||||
Prop::Shorthand(Ident { sym, span, .. }) => Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!(span, sym.clone())),
|
||||
value: Box::new(quote_ident!(span, sym).into()),
|
||||
}),
|
||||
Prop::Method(MethodProp { key, function }) => Prop::KeyValue(KeyValueProp {
|
||||
key,
|
||||
value: Box::new(Expr::Fn(FnExpr {
|
||||
ident: None,
|
||||
function,
|
||||
})),
|
||||
}),
|
||||
_ => prop,
|
||||
Prop::Shorthand(Ident { sym, span, .. }) => {
|
||||
*prop = Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!(*span, sym.clone())),
|
||||
value: Box::new(quote_ident!(*span, sym.clone()).into()),
|
||||
});
|
||||
}
|
||||
Prop::Method(MethodProp { key, function }) => {
|
||||
*prop = Prop::KeyValue(KeyValueProp {
|
||||
key: key.take(),
|
||||
value: Box::new(Expr::Fn(FnExpr {
|
||||
ident: None,
|
||||
function: function.take(),
|
||||
})),
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ShorthandFinder {
|
||||
found: bool,
|
||||
}
|
||||
|
||||
impl Visit for ShorthandFinder {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_prop(&mut self, n: &Prop, _: &dyn Node) {
|
||||
n.visit_children_with(self);
|
||||
|
||||
self.found |= n.is_shorthand() || n.is_method();
|
||||
}
|
||||
}
|
||||
|
||||
impl Check for ShorthandFinder {
|
||||
fn should_handle(&self) -> bool {
|
||||
self.found
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -97,7 +78,7 @@ mod tests {
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| Shorthand,
|
||||
|_| shorthand(),
|
||||
babel_method_plain,
|
||||
"var obj = {
|
||||
method() {
|
||||
@ -113,7 +94,7 @@ mod tests {
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| Shorthand,
|
||||
|_| shorthand(),
|
||||
babel_comments,
|
||||
"var A = 'a';
|
||||
var o = {
|
||||
@ -128,7 +109,7 @@ var o = {
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| Shorthand,
|
||||
|_| shorthand(),
|
||||
babel_mixed,
|
||||
"var coords = { x, y, foo: 'bar' };",
|
||||
"var coords = {
|
||||
@ -140,7 +121,7 @@ var o = {
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| Shorthand,
|
||||
|_| shorthand(),
|
||||
babel_multiple,
|
||||
"var coords = { x, y };",
|
||||
"var coords = {
|
||||
@ -151,7 +132,7 @@ var o = {
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| Shorthand,
|
||||
|_| shorthand(),
|
||||
babel_single,
|
||||
"var coords = { x };",
|
||||
"var coords = {
|
||||
|
@ -1,18 +1,20 @@
|
||||
use serde::Deserialize;
|
||||
use std::mem;
|
||||
use swc_atoms::js_word;
|
||||
use swc_common::{util::move_map::MoveMap, Span, Spanned, DUMMY_SP};
|
||||
use swc_common::{util::take::Take, Span, Spanned, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::{ext::ExprRefExt, helper, perf::Check};
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_transforms_base::{ext::ExprRefExt, helper};
|
||||
use swc_ecma_utils::{
|
||||
alias_ident_for, is_literal, member_expr, prepend, quote_ident, undefined, ExprFactory,
|
||||
StmtLike,
|
||||
};
|
||||
use swc_ecma_visit::{noop_fold_type, noop_visit_type, Fold, FoldWith, Node, Visit, VisitWith};
|
||||
use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
|
||||
|
||||
pub fn spread(c: Config) -> impl Fold {
|
||||
Spread { c }
|
||||
Spread {
|
||||
c,
|
||||
vars: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default, Deserialize)]
|
||||
@ -25,15 +27,10 @@ pub struct Config {
|
||||
#[derive(Default)]
|
||||
struct Spread {
|
||||
c: Config,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ActualFolder {
|
||||
c: Config,
|
||||
vars: Vec<VarDeclarator>,
|
||||
}
|
||||
|
||||
#[fast_path(SpreadFinder)]
|
||||
/// TODO: VisitMut
|
||||
impl Fold for Spread {
|
||||
noop_fold_type!();
|
||||
|
||||
@ -44,37 +41,6 @@ impl Fold for Spread {
|
||||
fn fold_stmts(&mut self, n: Vec<Stmt>) -> Vec<Stmt> {
|
||||
self.fold_stmt_like(n)
|
||||
}
|
||||
}
|
||||
|
||||
impl Spread {
|
||||
fn fold_stmt_like<T>(&mut self, items: Vec<T>) -> Vec<T>
|
||||
where
|
||||
T: StmtLike + FoldWith<ActualFolder> + FoldWith<Self>,
|
||||
{
|
||||
let mut folder = ActualFolder {
|
||||
c: self.c,
|
||||
vars: vec![],
|
||||
};
|
||||
let mut items = items.move_map(|item| item.fold_with(&mut folder));
|
||||
if !folder.vars.is_empty() {
|
||||
prepend(
|
||||
&mut items,
|
||||
T::from_stmt(Stmt::Decl(Decl::Var(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
declare: false,
|
||||
decls: mem::replace(&mut folder.vars, vec![]),
|
||||
}))),
|
||||
);
|
||||
}
|
||||
|
||||
items
|
||||
}
|
||||
}
|
||||
|
||||
#[fast_path(SpreadFinder)]
|
||||
impl Fold for ActualFolder {
|
||||
noop_fold_type!();
|
||||
|
||||
fn fold_expr(&mut self, e: Expr) -> Expr {
|
||||
let e = e.fold_children_with(self);
|
||||
@ -230,7 +196,34 @@ impl Fold for ActualFolder {
|
||||
}
|
||||
}
|
||||
|
||||
impl ActualFolder {
|
||||
impl Spread {
|
||||
fn fold_stmt_like<T>(&mut self, items: Vec<T>) -> Vec<T>
|
||||
where
|
||||
T: StmtLike,
|
||||
Vec<T>: FoldWith<Self>,
|
||||
{
|
||||
let orig = self.vars.take();
|
||||
|
||||
let mut items = items.fold_children_with(self);
|
||||
if !self.vars.is_empty() {
|
||||
prepend(
|
||||
&mut items,
|
||||
T::from_stmt(Stmt::Decl(Decl::Var(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
declare: false,
|
||||
decls: self.vars.take(),
|
||||
}))),
|
||||
);
|
||||
}
|
||||
|
||||
self.vars = orig;
|
||||
|
||||
items
|
||||
}
|
||||
}
|
||||
|
||||
impl Spread {
|
||||
fn concat_args(
|
||||
&self,
|
||||
span: Span,
|
||||
@ -453,24 +446,3 @@ fn expand_literal_args(
|
||||
expand(&mut buf, args);
|
||||
buf
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct SpreadFinder {
|
||||
found: bool,
|
||||
}
|
||||
|
||||
impl Visit for SpreadFinder {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_expr_or_spread(&mut self, n: &ExprOrSpread, _: &dyn Node) {
|
||||
n.visit_children_with(self);
|
||||
|
||||
self.found |= n.spread.is_some();
|
||||
}
|
||||
}
|
||||
|
||||
impl Check for SpreadFinder {
|
||||
fn should_handle(&self) -> bool {
|
||||
self.found
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,8 @@
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::DUMMY_SP;
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Check;
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_utils::{quote_ident, ExprFactory};
|
||||
use swc_ecma_visit::{noop_fold_type, noop_visit_type, Fold, FoldWith, Node, Visit};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
|
||||
/// Compile ES2015 sticky regex to an ES5 RegExp constructor
|
||||
///
|
||||
@ -20,19 +18,18 @@ use swc_ecma_visit::{noop_fold_type, noop_visit_type, Fold, FoldWith, Node, Visi
|
||||
/// ```js
|
||||
/// new RegExp("o+", "y")
|
||||
/// ```
|
||||
pub fn sticky_regex() -> impl 'static + Fold {
|
||||
StickyRegex
|
||||
pub fn sticky_regex() -> impl 'static + Fold + VisitMut {
|
||||
as_folder(StickyRegex)
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct StickyRegex;
|
||||
|
||||
#[fast_path(StickyRegexVisitor)]
|
||||
impl Fold for StickyRegex {
|
||||
noop_fold_type!();
|
||||
impl VisitMut for StickyRegex {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn fold_expr(&mut self, e: Expr) -> Expr {
|
||||
let e = e.fold_children_with(self);
|
||||
fn visit_mut_expr(&mut self, e: &mut Expr) {
|
||||
e.visit_mut_children_with(self);
|
||||
|
||||
match e {
|
||||
Expr::Lit(Lit::Regex(Regex { exp, flags, span })) => {
|
||||
@ -48,40 +45,22 @@ impl Fold for StickyRegex {
|
||||
})))
|
||||
};
|
||||
|
||||
Expr::New(NewExpr {
|
||||
span,
|
||||
callee: Box::new(quote_ident!(span, "RegExp").into()),
|
||||
args: Some(vec![str_lit(exp).as_arg(), str_lit(flags).as_arg()]),
|
||||
*e = Expr::New(NewExpr {
|
||||
span: *span,
|
||||
callee: Box::new(quote_ident!(*span, "RegExp").into()),
|
||||
args: Some(vec![
|
||||
str_lit(exp.clone()).as_arg(),
|
||||
str_lit(flags.clone()).as_arg(),
|
||||
]),
|
||||
type_args: Default::default(),
|
||||
})
|
||||
} else {
|
||||
Expr::Lit(Lit::Regex(Regex { exp, flags, span }))
|
||||
}
|
||||
}
|
||||
_ => e,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct StickyRegexVisitor {
|
||||
found: bool,
|
||||
}
|
||||
|
||||
impl Visit for StickyRegexVisitor {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_regex(&mut self, n: &Regex, _: &dyn Node) {
|
||||
self.found |= n.flags.contains('y');
|
||||
}
|
||||
}
|
||||
|
||||
impl Check for StickyRegexVisitor {
|
||||
fn should_handle(&self) -> bool {
|
||||
self.found
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -89,7 +68,7 @@ mod tests {
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| StickyRegex,
|
||||
|_| sticky_regex(),
|
||||
babel_basic,
|
||||
"var re = /o+/y;",
|
||||
"var re = new RegExp('o+', 'y');"
|
||||
@ -97,7 +76,7 @@ mod tests {
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| StickyRegex,
|
||||
|_| sticky_regex(),
|
||||
babel_ignore_non_sticky,
|
||||
"var re = /o+/;",
|
||||
"var re = /o+/;"
|
||||
|
@ -1,13 +1,9 @@
|
||||
use swc_atoms::js_word;
|
||||
use swc_common::{util::take::Take, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::{helper, perf::Check};
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_transforms_base::helper;
|
||||
use swc_ecma_utils::{quote_str, ExprFactory};
|
||||
use swc_ecma_visit::{
|
||||
as_folder, noop_visit_mut_type, noop_visit_type, Fold, Node, Visit, VisitMut, VisitMutWith,
|
||||
VisitWith,
|
||||
};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
|
||||
pub fn typeof_symbol() -> impl VisitMut + Fold {
|
||||
as_folder(TypeOfSymbol)
|
||||
@ -16,7 +12,6 @@ pub fn typeof_symbol() -> impl VisitMut + Fold {
|
||||
#[derive(Clone)]
|
||||
struct TypeOfSymbol;
|
||||
|
||||
#[fast_path(TypeOfFinder)]
|
||||
impl VisitMut for TypeOfSymbol {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
@ -109,29 +104,6 @@ impl VisitMut for TypeOfSymbol {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct TypeOfFinder {
|
||||
found: bool,
|
||||
}
|
||||
|
||||
impl Visit for TypeOfFinder {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_unary_expr(&mut self, e: &UnaryExpr, _: &dyn Node) {
|
||||
e.visit_children_with(self);
|
||||
|
||||
if e.op == op!("typeof") {
|
||||
self.found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Check for TypeOfFinder {
|
||||
fn should_handle(&self) -> bool {
|
||||
self.found
|
||||
}
|
||||
}
|
||||
|
||||
fn is_non_symbol_literal(e: &Expr) -> bool {
|
||||
match *e {
|
||||
Expr::Lit(Lit::Str(Str {
|
||||
|
@ -1,9 +1,8 @@
|
||||
use swc_common::{Span, Spanned, DUMMY_SP};
|
||||
use swc_common::{util::take::Take, Span, Spanned, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::{ext::PatOrExprExt, perf::Check};
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_transforms_base::ext::PatOrExprExt;
|
||||
use swc_ecma_utils::{member_expr, private_ident, ExprFactory, StmtLike};
|
||||
use swc_ecma_visit::{noop_fold_type, noop_visit_type, Fold, FoldWith, Node, Visit, VisitWith};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
|
||||
/// `@babel/plugin-transform-exponentiation-operator`
|
||||
///
|
||||
@ -24,30 +23,34 @@ use swc_ecma_visit::{noop_fold_type, noop_visit_type, Fold, FoldWith, Node, Visi
|
||||
///
|
||||
/// x = Math.pow(x, 3);
|
||||
/// ```
|
||||
pub fn exponentation() -> impl Fold {
|
||||
Exponentation
|
||||
pub fn exponentation() -> impl Fold + VisitMut {
|
||||
as_folder(Exponentation::default())
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Exponentation;
|
||||
|
||||
#[derive(Default)]
|
||||
struct AssignFolder {
|
||||
struct Exponentation {
|
||||
vars: Vec<VarDeclarator>,
|
||||
}
|
||||
|
||||
#[fast_path(ShouldFold)]
|
||||
impl Fold for AssignFolder {
|
||||
noop_fold_type!();
|
||||
impl VisitMut for Exponentation {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn fold_expr(&mut self, e: Expr) -> Expr {
|
||||
let e = e.fold_children_with(self);
|
||||
fn visit_mut_module_items(&mut self, n: &mut Vec<ModuleItem>) {
|
||||
self.visit_mut_stmt_like(n)
|
||||
}
|
||||
|
||||
fn visit_mut_stmts(&mut self, n: &mut Vec<Stmt>) {
|
||||
self.visit_mut_stmt_like(n)
|
||||
}
|
||||
|
||||
fn visit_mut_expr(&mut self, e: &mut Expr) {
|
||||
e.visit_mut_children_with(self);
|
||||
|
||||
match e {
|
||||
Expr::Assign(AssignExpr {
|
||||
span,
|
||||
left,
|
||||
op: op!("**="),
|
||||
op: op @ op!("**="),
|
||||
right,
|
||||
}) => {
|
||||
let lhs: Ident = match left {
|
||||
@ -67,79 +70,62 @@ impl Fold for AssignFolder {
|
||||
}
|
||||
|
||||
left => {
|
||||
return Expr::Assign(AssignExpr {
|
||||
span,
|
||||
left,
|
||||
*e = Expr::Assign(AssignExpr {
|
||||
span: *span,
|
||||
left: left.take(),
|
||||
op: op!("="),
|
||||
right,
|
||||
right: right.take(),
|
||||
});
|
||||
return;
|
||||
}
|
||||
};
|
||||
Expr::Assign(AssignExpr {
|
||||
span,
|
||||
left,
|
||||
op: op!("="),
|
||||
right: Box::new(mk_call(span, Box::new(lhs.into()), right)),
|
||||
})
|
||||
|
||||
*op = op!("=");
|
||||
*right = Box::new(mk_call(*span, Box::new(lhs.into()), right.take()));
|
||||
}
|
||||
Expr::Bin(BinExpr {
|
||||
span,
|
||||
left,
|
||||
op: op!("**"),
|
||||
right,
|
||||
}) => mk_call(span, left, right),
|
||||
_ => e,
|
||||
}) => {
|
||||
*e = mk_call(*span, left.take(), right.take());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[fast_path(ShouldFold)]
|
||||
impl Fold for Exponentation {
|
||||
noop_fold_type!();
|
||||
|
||||
fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> {
|
||||
self.fold_stmt_like(n)
|
||||
}
|
||||
|
||||
fn fold_stmts(&mut self, n: Vec<Stmt>) -> Vec<Stmt> {
|
||||
self.fold_stmt_like(n)
|
||||
}
|
||||
}
|
||||
|
||||
impl Exponentation {
|
||||
fn fold_stmt_like<T>(&mut self, stmts: Vec<T>) -> Vec<T>
|
||||
fn visit_mut_stmt_like<T>(&mut self, stmts: &mut Vec<T>)
|
||||
where
|
||||
T: StmtLike + VisitWith<ShouldFold>,
|
||||
Vec<T>: FoldWith<Self> + VisitWith<ShouldFold>,
|
||||
T: StmtLike + VisitMutWith<Self>,
|
||||
Vec<T>: VisitMutWith<Self>,
|
||||
{
|
||||
let stmts = stmts.fold_children_with(self);
|
||||
let orig = self.vars.take();
|
||||
|
||||
let mut buf = vec![];
|
||||
let mut buf = Vec::with_capacity(stmts.len());
|
||||
|
||||
for stmt in stmts {
|
||||
match stmt.try_into_stmt() {
|
||||
Err(module_item) => buf.push(module_item),
|
||||
Ok(stmt) => {
|
||||
let mut folder = AssignFolder::default();
|
||||
let stmt = stmt.fold_with(&mut folder);
|
||||
for mut stmt in stmts.take() {
|
||||
stmt.visit_mut_with(self);
|
||||
|
||||
// Add variable declaration
|
||||
// e.g. var ref
|
||||
if !folder.vars.is_empty() {
|
||||
buf.push(T::from_stmt(Stmt::Decl(Decl::Var(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
decls: folder.vars,
|
||||
declare: false,
|
||||
}))));
|
||||
}
|
||||
|
||||
buf.push(T::from_stmt(stmt));
|
||||
}
|
||||
// Add variable declaration
|
||||
// e.g. var ref
|
||||
if !self.vars.is_empty() {
|
||||
buf.push(T::from_stmt(Stmt::Decl(Decl::Var(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
decls: self.vars.take(),
|
||||
declare: false,
|
||||
}))));
|
||||
}
|
||||
|
||||
buf.push(stmt);
|
||||
}
|
||||
|
||||
buf
|
||||
self.vars = orig;
|
||||
|
||||
*stmts = buf
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,37 +140,6 @@ fn mk_call(span: Span, left: Box<Expr>, right: Box<Expr>) -> Expr {
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ShouldFold {
|
||||
found: bool,
|
||||
}
|
||||
impl Visit for ShouldFold {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_bin_expr(&mut self, e: &BinExpr, _: &dyn Node) {
|
||||
if e.op == op!("**") {
|
||||
self.found = true;
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_assign_expr(&mut self, e: &AssignExpr, _: &dyn Node) {
|
||||
if e.op == op!("**=") {
|
||||
self.found = true;
|
||||
}
|
||||
|
||||
if !self.found {
|
||||
e.left.visit_with(e as _, self);
|
||||
e.right.visit_with(e as _, self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Check for ShouldFold {
|
||||
fn should_handle(&self) -> bool {
|
||||
self.found
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -192,7 +147,7 @@ mod tests {
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| Exponentation,
|
||||
|_| exponentation(),
|
||||
babel_binary,
|
||||
"2 ** 2",
|
||||
"Math.pow(2, 2)"
|
||||
@ -201,7 +156,7 @@ mod tests {
|
||||
test_exec!(
|
||||
ignore,
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| Exponentation,
|
||||
|_| exponentation(),
|
||||
babel_comprehensive,
|
||||
r#"expect(2 ** 3).toBe(8);
|
||||
expect(3 * 2 ** 3).toBe(24);
|
||||
@ -230,7 +185,7 @@ expect(2 ** 3 ** 2).toBe(512);"#
|
||||
// FIXME
|
||||
ignore,
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| Exponentation,
|
||||
|_| exponentation(),
|
||||
babel_memoize_object,
|
||||
r#"var counters = 0;
|
||||
Object.defineProperty(global, "reader", {
|
||||
@ -246,7 +201,7 @@ expect(counters).toBe(1);"#
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| Exponentation,
|
||||
|_| exponentation(),
|
||||
assign,
|
||||
r#"x **= 3"#,
|
||||
r#"x = Math.pow(x, 3)"#,
|
||||
@ -254,7 +209,7 @@ expect(counters).toBe(1);"#
|
||||
);
|
||||
|
||||
// test!(::swc_ecma_parser::Syntax::default(),
|
||||
// |_| Exponentation,
|
||||
// |_| exponentation(),
|
||||
// babel_4403,
|
||||
// "var a, b;
|
||||
// a[`${b++}`] **= 1;",
|
||||
@ -266,7 +221,7 @@ expect(counters).toBe(1);"#
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| Exponentation,
|
||||
|_| exponentation(),
|
||||
issue_740,
|
||||
"self.a = 10 ** 2",
|
||||
"self.a = Math.pow(10, 2)",
|
||||
@ -277,7 +232,7 @@ expect(counters).toBe(1);"#
|
||||
// bu JakeChampion
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| Exponentation,
|
||||
|_| exponentation(),
|
||||
babel_binary_member_assignment_expression,
|
||||
"var x = {}; x.a = 2 ** 2",
|
||||
"var x = {}; x.a = Math.pow(2, 2)"
|
||||
@ -285,7 +240,7 @@ expect(counters).toBe(1);"#
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| Exponentation,
|
||||
|_| exponentation(),
|
||||
assign_to_object_property,
|
||||
r#"var self = {}; self.x **= 3"#,
|
||||
r#"var self = {}; var ref = self.x; self.x = Math.pow(ref, 3);"#,
|
||||
|
@ -40,6 +40,7 @@ struct Actual {
|
||||
extra_stmts: Vec<Stmt>,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
#[fast_path(ShouldWork)]
|
||||
impl Fold for AsyncToGenerator {
|
||||
noop_fold_type!();
|
||||
@ -78,6 +79,7 @@ impl AsyncToGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
#[fast_path(ShouldWork)]
|
||||
impl Fold for Actual {
|
||||
noop_fold_type!();
|
||||
@ -497,6 +499,7 @@ impl MethodFolder {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for MethodFolder {
|
||||
noop_fold_type!();
|
||||
|
||||
@ -910,6 +913,7 @@ macro_rules! noop {
|
||||
};
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for AsyncFnBodyHandler {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -1,17 +1,23 @@
|
||||
use std::{iter, mem};
|
||||
use swc_common::{chain, util::move_map::MoveMap, Mark, Spanned, DUMMY_SP};
|
||||
use swc_common::{
|
||||
chain,
|
||||
util::{move_map::MoveMap, take::Take},
|
||||
Mark, Spanned, DUMMY_SP,
|
||||
};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::{helper, helper_expr, perf::Check};
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_transforms_base::{helper, helper_expr};
|
||||
use swc_ecma_utils::{
|
||||
alias_ident_for, alias_if_required, is_literal, private_ident, quote_ident, var::VarCollector,
|
||||
ExprFactory, StmtLike,
|
||||
};
|
||||
use swc_ecma_visit::{noop_fold_type, noop_visit_type, Fold, FoldWith, Node, Visit, VisitWith};
|
||||
use swc_ecma_visit::{
|
||||
as_folder, noop_fold_type, noop_visit_mut_type, noop_visit_type, Fold, FoldWith, Node, Visit,
|
||||
VisitMut, VisitMutWith, VisitWith,
|
||||
};
|
||||
|
||||
/// `@babel/plugin-proposal-object-rest-spread`
|
||||
pub fn object_rest_spread() -> impl Fold {
|
||||
chain!(ObjectRest, ObjectSpread)
|
||||
chain!(ObjectRest, as_folder(ObjectSpread))
|
||||
}
|
||||
|
||||
struct ObjectRest;
|
||||
@ -141,6 +147,7 @@ macro_rules! impl_for_for_stmt {
|
||||
};
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for RestFolder {
|
||||
noop_fold_type!();
|
||||
|
||||
@ -403,6 +410,7 @@ where
|
||||
v.found
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for ObjectRest {
|
||||
noop_fold_type!();
|
||||
fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> {
|
||||
@ -1050,6 +1058,8 @@ fn excluded_props(props: &[ObjectPatProp]) -> Vec<Option<ExprOrSpread>> {
|
||||
/// - `{ x4: {} }` -> `{}`
|
||||
fn simplify_pat(pat: Pat) -> Pat {
|
||||
struct PatSimplifier;
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for PatSimplifier {
|
||||
noop_fold_type!();
|
||||
|
||||
@ -1092,12 +1102,11 @@ fn simplify_pat(pat: Pat) -> Pat {
|
||||
|
||||
struct ObjectSpread;
|
||||
|
||||
#[fast_path(SpreadVisitor)]
|
||||
impl Fold for ObjectSpread {
|
||||
noop_fold_type!();
|
||||
impl VisitMut for ObjectSpread {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn fold_expr(&mut self, expr: Expr) -> Expr {
|
||||
let expr = expr.fold_children_with(self);
|
||||
fn visit_mut_expr(&mut self, expr: &mut Expr) {
|
||||
expr.visit_mut_children_with(self);
|
||||
|
||||
match expr {
|
||||
Expr::Object(ObjectLit { span, props }) => {
|
||||
@ -1106,7 +1115,7 @@ impl Fold for ObjectSpread {
|
||||
_ => false,
|
||||
});
|
||||
if !has_spread {
|
||||
return Expr::Object(ObjectLit { span, props });
|
||||
return;
|
||||
}
|
||||
|
||||
let mut first = true;
|
||||
@ -1118,7 +1127,7 @@ impl Fold for ObjectSpread {
|
||||
span: DUMMY_SP,
|
||||
props: vec![],
|
||||
};
|
||||
for prop in props {
|
||||
for prop in props.take() {
|
||||
match prop {
|
||||
PropOrSpread::Prop(..) => obj.props.push(prop),
|
||||
PropOrSpread::Spread(SpreadElement { expr, .. }) => {
|
||||
@ -1147,32 +1156,14 @@ impl Fold for ObjectSpread {
|
||||
buf
|
||||
};
|
||||
|
||||
Expr::Call(CallExpr {
|
||||
span,
|
||||
*expr = Expr::Call(CallExpr {
|
||||
span: *span,
|
||||
callee: helper!(object_spread, "objectSpread"),
|
||||
args,
|
||||
type_args: Default::default(),
|
||||
})
|
||||
});
|
||||
}
|
||||
_ => expr,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Default)]
|
||||
struct SpreadVisitor {
|
||||
found: bool,
|
||||
}
|
||||
|
||||
impl Visit for SpreadVisitor {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_spread_element(&mut self, _: &SpreadElement, _: &dyn Node) {
|
||||
self.found = true;
|
||||
}
|
||||
}
|
||||
|
||||
impl Check for SpreadVisitor {
|
||||
fn should_handle(&self) -> bool {
|
||||
self.found
|
||||
}
|
||||
}
|
||||
|
@ -1,52 +1,23 @@
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Check;
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_utils::private_ident;
|
||||
use swc_ecma_visit::{noop_fold_type, noop_visit_type, Fold, FoldWith, Node, Visit, VisitWith};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
|
||||
struct OptionalCatchBinding;
|
||||
|
||||
pub fn optional_catch_binding() -> impl Fold {
|
||||
OptionalCatchBinding
|
||||
pub fn optional_catch_binding() -> impl Fold + VisitMut {
|
||||
as_folder(OptionalCatchBinding)
|
||||
}
|
||||
|
||||
#[fast_path(ShouldWork)]
|
||||
impl Fold for OptionalCatchBinding {
|
||||
noop_fold_type!();
|
||||
impl VisitMut for OptionalCatchBinding {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn fold_catch_clause(&mut self, mut cc: CatchClause) -> CatchClause {
|
||||
cc = cc.fold_children_with(self);
|
||||
fn visit_mut_catch_clause(&mut self, cc: &mut CatchClause) {
|
||||
cc.visit_mut_children_with(self);
|
||||
|
||||
if cc.param.is_some() {
|
||||
return cc;
|
||||
}
|
||||
|
||||
CatchClause {
|
||||
param: Some(private_ident!("e").into()),
|
||||
..cc
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Default)]
|
||||
struct ShouldWork {
|
||||
found: bool,
|
||||
}
|
||||
|
||||
impl Visit for ShouldWork {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_catch_clause(&mut self, n: &CatchClause, _: &dyn Node) {
|
||||
if n.param.is_none() {
|
||||
self.found = true;
|
||||
return;
|
||||
}
|
||||
n.visit_children_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Check for ShouldWork {
|
||||
fn should_handle(&self) -> bool {
|
||||
self.found
|
||||
cc.param = Some(private_ident!("e").into());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ pub(super) struct ClassNameTdzFolder<'a> {
|
||||
pub class_name: &'a Ident,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl<'a> Fold for ClassNameTdzFolder<'a> {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -52,6 +52,7 @@ struct ClassProperties {
|
||||
method_mark: Mark,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
#[fast_path(ShouldWork)]
|
||||
impl Fold for ClassProperties {
|
||||
noop_fold_type!();
|
||||
|
@ -129,6 +129,7 @@ macro_rules! take_vars {
|
||||
};
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl<'a> Fold for FieldAccessFolder<'a> {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -5,6 +5,7 @@ pub(super) struct ThisInStaticFolder {
|
||||
pub ident: Ident,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for ThisInStaticFolder {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -9,6 +9,7 @@ pub fn export_namespace_from() -> impl Fold {
|
||||
|
||||
struct ExportNamespaceFrom;
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for ExportNamespaceFrom {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -44,6 +44,7 @@ impl NullishCoalescing {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
#[fast_path(ShouldWork)]
|
||||
impl Fold for NullishCoalescing {
|
||||
noop_fold_type!();
|
||||
|
@ -16,6 +16,7 @@ struct OptChaining {
|
||||
vars_with_init: Vec<VarDeclarator>,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
#[fast_path(ShouldWork)]
|
||||
impl Fold for OptChaining {
|
||||
noop_fold_type!();
|
||||
@ -76,8 +77,8 @@ impl OptChaining {
|
||||
Vec<T>: FoldWith<Self>,
|
||||
{
|
||||
// This is to support nested block statements
|
||||
let old_no_init = mem::replace(&mut self.vars_without_init, vec![]);
|
||||
let old_init = mem::replace(&mut self.vars_with_init, vec![]);
|
||||
let old_no_init = mem::take(&mut self.vars_without_init);
|
||||
let old_init = mem::take(&mut self.vars_with_init);
|
||||
|
||||
let mut new: Vec<T> = vec![];
|
||||
|
||||
|
@ -1,11 +1,7 @@
|
||||
use swc_common::{util::take::Take, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Check;
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_utils::{alias_ident_for, prepend, ExprFactory};
|
||||
use swc_ecma_visit::{
|
||||
as_folder, noop_visit_mut_type, noop_visit_type, Fold, Node, Visit, VisitMut, VisitMutWith,
|
||||
};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
|
||||
pub fn logical_assignments() -> impl Fold + VisitMut {
|
||||
as_folder(Operators::default())
|
||||
@ -16,7 +12,6 @@ struct Operators {
|
||||
vars: Vec<VarDeclarator>,
|
||||
}
|
||||
|
||||
#[fast_path(OperatorFinder)]
|
||||
impl VisitMut for Operators {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
@ -159,22 +154,3 @@ impl VisitMut for Operators {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct OperatorFinder {
|
||||
found: bool,
|
||||
}
|
||||
|
||||
impl Visit for OperatorFinder {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_assign_op(&mut self, n: &AssignOp, _: &dyn Node) {
|
||||
self.found |= *n == op!("||=") || *n == op!("??=");
|
||||
}
|
||||
}
|
||||
|
||||
impl Check for OperatorFinder {
|
||||
fn should_handle(&self) -> bool {
|
||||
self.found
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ pub fn member_expression_literals() -> impl Fold {
|
||||
#[derive(Default, Clone, Copy)]
|
||||
struct MemberExprLit;
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for MemberExprLit {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -35,6 +35,7 @@ pub fn property_literals() -> impl Fold {
|
||||
|
||||
struct PropertyLiteral;
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for PropertyLiteral {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -25,6 +25,7 @@ struct ReservedWord {
|
||||
pub preserve_import: bool,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for ReservedWord {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -1,10 +1,6 @@
|
||||
use swc_atoms::{js_word, JsWord};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Check;
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_visit::{
|
||||
as_folder, noop_visit_mut_type, noop_visit_type, Fold, Node, Visit, VisitMut, VisitMutWith,
|
||||
};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
|
||||
pub fn reserved_words() -> impl 'static + Fold + VisitMut {
|
||||
as_folder(EsReservedWord)
|
||||
@ -12,17 +8,11 @@ pub fn reserved_words() -> impl 'static + Fold + VisitMut {
|
||||
|
||||
struct EsReservedWord;
|
||||
|
||||
#[fast_path(ShouldWork)]
|
||||
impl VisitMut for EsReservedWord {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn visit_mut_export_specifier(&mut self, _n: &mut ExportSpecifier) {}
|
||||
|
||||
/// For #[fast_path]
|
||||
fn visit_mut_expr(&mut self, e: &mut Expr) {
|
||||
e.visit_mut_children_with(self);
|
||||
}
|
||||
|
||||
fn visit_mut_ident(&mut self, i: &mut Ident) {
|
||||
rename_ident(&mut i.sym, true);
|
||||
}
|
||||
@ -56,11 +46,6 @@ impl VisitMut for EsReservedWord {
|
||||
fn visit_mut_meta_prop_expr(&mut self, _n: &mut MetaPropExpr) {}
|
||||
|
||||
fn visit_mut_prop_name(&mut self, _n: &mut PropName) {}
|
||||
|
||||
/// For #[fast_path]
|
||||
fn visit_mut_stmt(&mut self, s: &mut Stmt) {
|
||||
s.visit_mut_children_with(self);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_reserved(sym: &JsWord) -> bool {
|
||||
@ -117,24 +102,3 @@ fn rename_ident(sym: &mut JsWord, _strict: bool) {
|
||||
*sym = s;
|
||||
}
|
||||
}
|
||||
#[derive(Default)]
|
||||
struct ShouldWork {
|
||||
found: bool,
|
||||
}
|
||||
|
||||
impl Visit for ShouldWork {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_ident(&mut self, i: &Ident, _: &dyn Node) {
|
||||
if is_reserved(&i.sym) {
|
||||
self.found = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Check for ShouldWork {
|
||||
fn should_handle(&self) -> bool {
|
||||
self.found
|
||||
}
|
||||
}
|
||||
|
@ -235,7 +235,6 @@ switch (true){
|
||||
|
||||
"#,
|
||||
r#"
|
||||
var _obj;
|
||||
|
||||
function fn() {}
|
||||
|
||||
@ -248,6 +247,7 @@ var obj = {
|
||||
|
||||
switch (true) {
|
||||
case true:
|
||||
var _obj;
|
||||
(_obj = obj.obj).fn.apply(_obj, _toConsumableArray(args));
|
||||
|
||||
break;
|
||||
|
@ -67,6 +67,7 @@ pub struct Config {
|
||||
pub config: util::Config,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl<R> Fold for Amd<R>
|
||||
where
|
||||
R: ImportResolver,
|
||||
|
@ -66,6 +66,7 @@ where
|
||||
resolver: Option<(P, FileName)>,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl<P> Fold for CommonJs<P>
|
||||
where
|
||||
P: ImportResolver,
|
||||
|
@ -13,7 +13,10 @@ pub fn import_analyzer(scope: Rc<RefCell<Scope>>) -> ImportAnalyzer {
|
||||
pub struct ImportAnalyzer {
|
||||
scope: Rc<RefCell<Scope>>,
|
||||
}
|
||||
|
||||
/// Inject required helpers methods **for** module transform passes.
|
||||
///
|
||||
/// TODO: VisitMut
|
||||
impl Fold for ImportAnalyzer {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -70,6 +70,7 @@ where
|
||||
resolver: Option<(R, FileName)>,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl<R> Fold for Umd<R>
|
||||
where
|
||||
R: ImportResolver,
|
||||
|
@ -79,6 +79,7 @@ struct Scope {
|
||||
imported: HashMap<JsWord, Arc<Expr>>,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for ConstModules {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -41,6 +41,7 @@ impl Default for JsonParse {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for JsonParse {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -82,6 +82,7 @@ struct Decorators {
|
||||
vars: Vec<VarDeclarator>,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for Decorators {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -81,6 +81,7 @@ impl Visit for Legacy {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for Legacy {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -8,6 +8,7 @@ use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
|
||||
/// https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata/blob/master/src/parameter/parameterVisitor.ts
|
||||
pub(super) struct ParamMetadata;
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for ParamMetadata {
|
||||
noop_fold_type!();
|
||||
|
||||
@ -125,6 +126,7 @@ pub(super) struct Metadata<'a> {
|
||||
pub(super) class_name: Option<&'a Ident>,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for Metadata<'_> {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -10,6 +10,7 @@ pub fn export_default_from() -> impl Fold {
|
||||
|
||||
struct ExportDefaultFrom;
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for ExportDefaultFrom {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -7,8 +7,7 @@ use swc_common::{
|
||||
collections::AHashSet, pass::CompilerPass, util::take::Take, Mark, Spanned, DUMMY_SP,
|
||||
};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::{pass::JsPass, perf::Check};
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_transforms_base::pass::JsPass;
|
||||
use swc_ecma_utils::{
|
||||
default_constructor, ident::IdentLike, prepend, private_ident, quote_ident, ExprFactory, Id,
|
||||
};
|
||||
@ -126,7 +125,6 @@ impl PrivateInObject {
|
||||
}
|
||||
}
|
||||
|
||||
#[fast_path(ShouldWork)]
|
||||
impl VisitMut for PrivateInObject {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
@ -513,35 +511,3 @@ impl Visit for ClassAnalyzer<'_> {
|
||||
n.visit_children_with(self);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ShouldWork {
|
||||
found: bool,
|
||||
}
|
||||
|
||||
impl Check for ShouldWork {
|
||||
fn should_handle(&self) -> bool {
|
||||
self.found
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for ShouldWork {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_bin_expr(&mut self, e: &BinExpr, _: &dyn Node) {
|
||||
if e.op == op!("in") && e.left.is_private_name() {
|
||||
self.found = true;
|
||||
return;
|
||||
}
|
||||
|
||||
e.visit_children_with(self);
|
||||
}
|
||||
|
||||
fn visit_private_method(&mut self, _: &PrivateMethod, _: &dyn Node) {
|
||||
self.found = true;
|
||||
}
|
||||
|
||||
fn visit_private_prop(&mut self, _: &PrivateProp, _: &dyn Node) {
|
||||
self.found = true;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ struct JsxSelf {
|
||||
dev: bool,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for JsxSelf {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -16,6 +16,7 @@ struct JsxSrc {
|
||||
dev: bool,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for JsxSrc {
|
||||
noop_fold_type!();
|
||||
|
||||
|
@ -565,7 +565,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// We let user do /* @refresh reset */ to reset state in the whole file.
|
||||
/// We let user do /* @refresh reset */ to reset state in the whole file.
|
||||
///
|
||||
/// TODO: VisitMut
|
||||
impl<C: Comments> Fold for Refresh<C> {
|
||||
fn fold_jsx_opening_element(&mut self, n: JSXOpeningElement) -> JSXOpeningElement {
|
||||
if let JSXElementName::Ident(ident) = &n.name {
|
||||
|
@ -5,7 +5,7 @@ edition = "2018"
|
||||
license = "Apache-2.0/MIT"
|
||||
name = "swc_visit"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
@ -17,6 +17,10 @@
|
||||
//!
|
||||
//! # `Fold`
|
||||
//!
|
||||
//! > WARNING: `Fold` is slow, and it's recommended to use VisiMut if you are
|
||||
//! experienced.
|
||||
//!
|
||||
//!
|
||||
//! `Fold` takes ownership of value, which means you have to return the new
|
||||
//! value. Returning new value means returning ownership of the value. But you
|
||||
//! don't have to care about ownership or about managing memories while using
|
||||
|
Loading…
Reference in New Issue
Block a user