Improve performance and reduce binary size (#973)

spack:
 - Optimize resolver

swc_bunder:
 - Parallize merging of reexports
 - Remove useless `clone`s

swc_ecma_utils:
 - Migrate DropSpan to VisitMut

swc_ecma_transforms:
 - Migrate simple transforms to VisitMut
 - Ignore types to reduce binary size
 - Hide actual types so that we can optimize it in future without breaking change

swc_visit:
 - Apply transforms for vector in-place
 - Apply transforms for box in-place
This commit is contained in:
강동윤 2020-08-19 01:29:49 +09:00 committed by GitHub
parent 7a13aabeb7
commit 3262052e33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
127 changed files with 1545 additions and 995 deletions

View File

@ -3,6 +3,7 @@
rustflags = [ rustflags = [
"--cfg", "procmacro2_semver_exempt", "--cfg", "procmacro2_semver_exempt",
"-Z", "thinlto=no", "-Z", "thinlto=no",
"-C", "target-feature=+sse2",
] ]
rustdocflags = [ rustdocflags = [

View File

@ -1,6 +1,6 @@
[package] [package]
name = "swc_bundler" name = "swc_bundler"
version = "0.2.3" version = "0.3.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"] authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT" license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git" repository = "https://github.com/swc-project/swc.git"
@ -18,11 +18,11 @@ concurrent = ["swc_common/concurrent", "dashmap", "rayon"]
swc_atoms = { version = "0.2", path = "../atoms" } swc_atoms = { version = "0.2", path = "../atoms" }
swc_common = { version = "0.9", path = "../common" } swc_common = { version = "0.9", path = "../common" }
swc_ecma_ast = { version = "0.28", path = "../ecmascript/ast" } swc_ecma_ast = { version = "0.28", path = "../ecmascript/ast" }
swc_ecma_codegen = { version = "0.31", path = "../ecmascript/codegen" } swc_ecma_codegen = { version = "0.32.0", path = "../ecmascript/codegen" }
swc_ecma_parser = { version = "0.33", path = "../ecmascript/parser" } swc_ecma_parser = { version = "0.34.0", path = "../ecmascript/parser" }
swc_ecma_transforms = { version = "0.19", path = "../ecmascript/transforms" } swc_ecma_transforms = { version = "0.20.0", path = "../ecmascript/transforms" }
swc_ecma_utils = { version = "0.17", path = "../ecmascript/utils" } swc_ecma_utils = { version = "0.18.0", path = "../ecmascript/utils" }
swc_ecma_visit = { version = "0.13", path = "../ecmascript/visit" } swc_ecma_visit = { version = "0.14.0", path = "../ecmascript/visit" }
anyhow = "1" anyhow = "1"
crc = "1.8" crc = "1.8"
radix_fmt = "1" radix_fmt = "1"

View File

@ -1,10 +1,10 @@
use super::merge::{LocalMarker, Unexporter}; use super::merge::{LocalMarker, Unexporter};
use crate::{bundler::load::TransformedModule, Bundler, Load, ModuleId, Resolve}; use crate::{bundler::load::TransformedModule, Bundler, Load, ModuleId, Resolve};
use hygiene::top_level_ident_folder; use hygiene::top_level_ident_folder;
use std::iter::once; use std::{borrow::Borrow, iter::once};
use swc_common::DUMMY_SP; use swc_common::{SyntaxContext, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_visit_type, FoldWith, Node, Visit, VisitMutWith, VisitWith};
mod hygiene; mod hygiene;
@ -112,11 +112,11 @@ where
for circular_module in circular_modules { for circular_module in circular_modules {
for (src, specifiers) in entry.imports.specifiers.iter() { for (src, specifiers) in entry.imports.specifiers.iter() {
if circular_module.id == src.module_id { if circular_module.id == src.module_id {
module = module.fold_with(&mut LocalMarker { module.visit_mut_with(&mut LocalMarker {
mark: circular_module.mark(), mark: circular_module.mark(),
top_level_ctxt: SyntaxContext::empty().apply_mark(self.top_level_mark),
specifiers: &specifiers, specifiers: &specifiers,
excluded: vec![], excluded: Default::default(),
is_export: false,
}); });
break; break;
} }
@ -165,7 +165,7 @@ fn merge_respecting_order(mut entry: Vec<ModuleItem>, mut dep: Vec<ModuleItem>)
} }
// We checked the length of `dep` // We checked the length of `dep`
if let Some(pos) = dependency_index(&dep[0], &[item.clone()]) { if let Some(pos) = dependency_index(&dep[0], &[&item]) {
log::trace!("Found reverse depndency (index[0]): {}", pos); log::trace!("Found reverse depndency (index[0]): {}", pos);
new.extend(entry.drain(..=pos)); new.extend(entry.drain(..=pos));
@ -192,25 +192,37 @@ fn merge_respecting_order(mut entry: Vec<ModuleItem>, mut dep: Vec<ModuleItem>)
new new
} }
fn dependency_index(item: &ModuleItem, deps: &[ModuleItem]) -> Option<usize> { /// Searches for top level declaration which provides requirements for `deps`.
fn dependency_index<T>(item: &ModuleItem, deps: &[T]) -> Option<usize>
where
T: Borrow<ModuleItem>,
{
let mut v = DepFinder { deps, idx: None }; let mut v = DepFinder { deps, idx: None };
item.visit_with(&Invalid { span: DUMMY_SP }, &mut v); item.visit_with(&Invalid { span: DUMMY_SP }, &mut v);
v.idx v.idx
} }
struct DepFinder<'a> { struct DepFinder<'a, T>
deps: &'a [ModuleItem], where
T: Borrow<ModuleItem>,
{
deps: &'a [T],
idx: Option<usize>, idx: Option<usize>,
} }
impl Visit for DepFinder<'_> { impl<T> Visit for DepFinder<'_, T>
where
T: Borrow<ModuleItem>,
{
noop_visit_type!();
fn visit_ident(&mut self, i: &Ident, _: &dyn Node) { fn visit_ident(&mut self, i: &Ident, _: &dyn Node) {
if self.idx.is_some() { if self.idx.is_some() {
return; return;
} }
for (idx, dep) in self.deps.iter().enumerate() { for (idx, dep) in self.deps.iter().enumerate() {
match dep { match dep.borrow() {
ModuleItem::Stmt(Stmt::Decl(Decl::Class(decl))) => { ModuleItem::Stmt(Stmt::Decl(Decl::Class(decl))) => {
log::trace!( log::trace!(
"Decl (from dep) = {}{:?}, Ident = {}{:?}", "Decl (from dep) = {}{:?}, Ident = {}{:?}",
@ -240,4 +252,11 @@ impl Visit for DepFinder<'_> {
fn visit_class_member(&mut self, _: &ClassMember, _: &dyn Node) {} fn visit_class_member(&mut self, _: &ClassMember, _: &dyn Node) {}
fn visit_function(&mut self, _: &Function, _: &dyn Node) {} fn visit_function(&mut self, _: &Function, _: &dyn Node) {}
fn visit_arrow_expr(&mut self, _: &ArrowExpr, _: &dyn Node) {} fn visit_arrow_expr(&mut self, _: &ArrowExpr, _: &dyn Node) {}
/// We only search for top-level binding
#[inline]
fn visit_stmts(&mut self, _: &[Stmt], _: &dyn Node) {}
/// We only search for top-level binding
#[inline]
fn visit_block_stmt(&mut self, _: &BlockStmt, _: &dyn Node) {}
} }

View File

@ -2,7 +2,7 @@ use crate::id::Id;
use std::collections::HashSet; use std::collections::HashSet;
use swc_common::{Mark, SyntaxContext}; use swc_common::{Mark, SyntaxContext};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub fn top_level_ident_folder(top_level_mark: Mark, module_mark: Mark) -> impl 'static + Fold { pub fn top_level_ident_folder(top_level_mark: Mark, module_mark: Mark) -> impl 'static + Fold {
MergeFolder { MergeFolder {
@ -87,6 +87,8 @@ impl<'a> MergeFolder<'a> {
} }
impl Fold for MergeFolder<'_> { impl Fold for MergeFolder<'_> {
noop_fold_type!();
fn fold_class_decl(&mut self, c: ClassDecl) -> ClassDecl { fn fold_class_decl(&mut self, c: ClassDecl) -> ClassDecl {
ClassDecl { ClassDecl {
ident: self.fold_bindine_ident(c.ident), ident: self.fold_bindine_ident(c.ident),

View File

@ -5,7 +5,7 @@ use std::{borrow::Cow, sync::atomic::Ordering};
use swc_common::{Mark, SyntaxContext, DUMMY_SP}; use swc_common::{Mark, SyntaxContext, DUMMY_SP};
use swc_ecma_ast::{ModuleItem, *}; use swc_ecma_ast::{ModuleItem, *};
use swc_ecma_utils::{prepend, undefined, ExprFactory}; use swc_ecma_utils::{prepend, undefined, ExprFactory};
use swc_ecma_visit::{Fold, FoldWith, VisitMut, VisitMutWith}; use swc_ecma_visit::{noop_visit_mut_type, FoldWith, VisitMut, VisitMutWith};
impl<L, R> Bundler<'_, L, R> impl<L, R> Bundler<'_, L, R>
where where
@ -49,10 +49,8 @@ where
{ {
info.helpers.require.store(true, Ordering::SeqCst); info.helpers.require.store(true, Ordering::SeqCst);
let dep = dep let mut dep = dep.into_owned().fold_with(&mut Unexporter);
.into_owned() dep.visit_mut_with(&mut ImportDropper);
.fold_with(&mut Unexporter)
.fold_with(&mut ImportDropper);
prepend( prepend(
&mut entry.body, &mut entry.body,
@ -150,6 +148,8 @@ struct RequireReplacer {
} }
impl VisitMut for RequireReplacer { impl VisitMut for RequireReplacer {
noop_visit_mut_type!();
fn visit_mut_module_item(&mut self, node: &mut ModuleItem) { fn visit_mut_module_item(&mut self, node: &mut ModuleItem) {
node.visit_mut_children_with(self); node.visit_mut_children_with(self);
@ -173,6 +173,7 @@ impl VisitMut for RequireReplacer {
} }
let mut props = vec![]; let mut props = vec![];
// TODO
for spec in i.specifiers.clone() { for spec in i.specifiers.clone() {
match spec { match spec {
ImportSpecifier::Named(s) => { ImportSpecifier::Named(s) => {
@ -288,15 +289,15 @@ impl VisitMut for RequireReplacer {
struct ImportDropper; struct ImportDropper;
impl Fold for ImportDropper { impl VisitMut for ImportDropper {
fn fold_module_item(&mut self, mut i: ModuleItem) -> ModuleItem { noop_visit_mut_type!();
i = i.fold_children_with(self);
fn visit_mut_module_item(&mut self, i: &mut ModuleItem) {
match i { match i {
ModuleItem::ModuleDecl(..) => { ModuleItem::ModuleDecl(..) => {
ModuleItem::Stmt(Stmt::Empty(EmptyStmt { span: DUMMY_SP })) *i = ModuleItem::Stmt(Stmt::Empty(EmptyStmt { span: DUMMY_SP }))
} }
ModuleItem::Stmt(_) => i, ModuleItem::Stmt(_) => {}
} }
} }
} }

View File

@ -1,12 +1,12 @@
use super::merge::{LocalMarker, Unexporter}; use super::merge::{LocalMarker, Unexporter};
use crate::{bundler::load::TransformedModule, Bundler, Load, ModuleId, Resolve}; use crate::{bundler::load::TransformedModule, util, Bundler, Load, ModuleId, Resolve};
use anyhow::{Context, Error}; use anyhow::{Context, Error};
use std::mem::{replace, take}; use std::mem::{replace, take};
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_common::{Spanned, SyntaxContext, DUMMY_SP}; use swc_common::{Spanned, SyntaxContext, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_utils::find_ids; use swc_ecma_utils::find_ids;
use swc_ecma_visit::{FoldWith, VisitMut, VisitMutWith}; use swc_ecma_visit::{noop_visit_mut_type, FoldWith, VisitMut, VisitMutWith};
impl<L, R> Bundler<'_, L, R> impl<L, R> Bundler<'_, L, R>
where where
@ -15,10 +15,10 @@ where
{ {
pub(super) fn merge_reexports( pub(super) fn merge_reexports(
&self, &self,
mut entry: Module, entry: &mut Module,
info: &TransformedModule, info: &TransformedModule,
targets: &mut Vec<ModuleId>, targets: &mut Vec<ModuleId>,
) -> Result<Module, Error> { ) -> Result<(), Error> {
entry.visit_mut_with(&mut DefaultRenamer); entry.visit_mut_with(&mut DefaultRenamer);
for (src, specifiers) in &info.exports.reexports { for (src, specifiers) in &info.exports.reexports {
@ -32,6 +32,32 @@ where
targets.remove(pos); targets.remove(pos);
} }
// print_hygiene("entry:init", &self.cm, &entry);
// print_hygiene("dep:init", &self.cm, &dep);
let (_, dep) = util::join(
|| {
self.run(|| {
entry.visit_mut_with(&mut LocalMarker {
mark: imported.mark(),
specifiers,
top_level_ctxt: SyntaxContext::empty().apply_mark(self.top_level_mark),
excluded: Default::default(),
});
// print_hygiene(&format!("entry:local-marker"), &self.cm, &entry);
entry.visit_mut_with(&mut NamedExportOrigMarker {
top_level_ctxt: SyntaxContext::empty().apply_mark(self.top_level_mark),
target_ctxt: SyntaxContext::empty().apply_mark(info.mark()),
});
entry.visit_mut_with(&mut ExportRenamer {
from: SyntaxContext::empty().apply_mark(imported.mark()),
to: SyntaxContext::empty().apply_mark(info.mark()),
});
})
},
|| -> Result<_, Error> {
self.run(|| {
let mut dep = self let mut dep = self
.merge_modules(src.module_id, false, targets) .merge_modules(src.module_id, false, targets)
.with_context(|| { .with_context(|| {
@ -43,23 +69,6 @@ where
dep = self.drop_unused(dep, Some(&specifiers)); dep = self.drop_unused(dep, Some(&specifiers));
// print_hygiene("entry:init", &self.cm, &entry);
// print_hygiene("dep:init", &self.cm, &dep);
entry = entry.fold_with(&mut LocalMarker {
mark: imported.mark(),
specifiers,
excluded: vec![],
is_export: false,
});
// print_hygiene(&format!("entry:local-marker"), &self.cm, &entry);
entry.visit_mut_with(&mut NamedExportOrigMarker {
top_level_ctxt: SyntaxContext::empty().apply_mark(self.top_level_mark),
target_ctxt: SyntaxContext::empty().apply_mark(info.mark()),
});
// print_hygiene(&format!("entry:named-export-orig"), &self.cm, &entry);
dep.visit_mut_with(&mut UnexportAsVar { dep.visit_mut_with(&mut UnexportAsVar {
target_ctxt: SyntaxContext::empty().apply_mark(info.mark()), target_ctxt: SyntaxContext::empty().apply_mark(info.mark()),
}); });
@ -73,17 +82,18 @@ where
dep = dep.fold_with(&mut Unexporter); dep = dep.fold_with(&mut Unexporter);
entry.visit_mut_with(&mut ExportRenamer { Ok(dep)
from: SyntaxContext::empty().apply_mark(imported.mark()), })
to: SyntaxContext::empty().apply_mark(info.mark()), },
}); );
let dep = dep?;
// print_hygiene("entry:before-injection", &self.cm, &entry); // print_hygiene("entry:before-injection", &self.cm, &entry);
// print_hygiene("dep:before-injection", &self.cm, &dep); // print_hygiene("dep:before-injection", &self.cm, &dep);
// Replace import statement / require with module body // Replace import statement / require with module body
let mut injector = ExportInjector { let mut injector = ExportInjector {
imported: dep.body.clone(), imported: dep.body,
src: src.src.clone(), src: src.src.clone(),
}; };
entry.body.visit_mut_with(&mut injector); entry.body.visit_mut_with(&mut injector);
@ -100,7 +110,7 @@ where
assert_eq!(injector.imported, vec![]); assert_eq!(injector.imported, vec![]);
} }
Ok(entry) Ok(())
} }
} }
@ -110,6 +120,8 @@ struct ExportInjector {
} }
impl VisitMut for ExportInjector { impl VisitMut for ExportInjector {
noop_visit_mut_type!();
fn visit_mut_module_items(&mut self, orig: &mut Vec<ModuleItem>) { fn visit_mut_module_items(&mut self, orig: &mut Vec<ModuleItem>) {
let items = take(orig); let items = take(orig);
let mut buf = Vec::with_capacity(self.imported.len() + items.len()); let mut buf = Vec::with_capacity(self.imported.len() + items.len());
@ -154,6 +166,8 @@ struct ExportRenamer {
} }
impl VisitMut for ExportRenamer { impl VisitMut for ExportRenamer {
noop_visit_mut_type!();
fn visit_mut_named_export(&mut self, export: &mut NamedExport) { fn visit_mut_named_export(&mut self, export: &mut NamedExport) {
// if export.src.is_none() { // if export.src.is_none() {
// return; // return;
@ -196,6 +210,8 @@ struct UnexportAsVar {
} }
impl VisitMut for UnexportAsVar { impl VisitMut for UnexportAsVar {
noop_visit_mut_type!();
fn visit_mut_module_item(&mut self, n: &mut ModuleItem) { fn visit_mut_module_item(&mut self, n: &mut ModuleItem) {
n.visit_mut_children_with(self); n.visit_mut_children_with(self);
@ -277,6 +293,8 @@ pub(super) struct NamedExportOrigMarker {
} }
impl VisitMut for NamedExportOrigMarker { impl VisitMut for NamedExportOrigMarker {
noop_visit_mut_type!();
fn visit_mut_export_named_specifier(&mut self, s: &mut ExportNamedSpecifier) { fn visit_mut_export_named_specifier(&mut self, s: &mut ExportNamedSpecifier) {
if s.orig.span.ctxt == self.top_level_ctxt { if s.orig.span.ctxt == self.top_level_ctxt {
s.orig.span = s.orig.span.with_ctxt(self.target_ctxt); s.orig.span = s.orig.span.with_ctxt(self.target_ctxt);
@ -293,6 +311,8 @@ struct AliasExports {
} }
impl VisitMut for AliasExports { impl VisitMut for AliasExports {
noop_visit_mut_type!();
fn visit_mut_module_items(&mut self, items: &mut Vec<ModuleItem>) { fn visit_mut_module_items(&mut self, items: &mut Vec<ModuleItem>) {
for item in items.iter_mut() { for item in items.iter_mut() {
item.visit_mut_with(self); item.visit_mut_with(self);
@ -355,6 +375,8 @@ impl VisitMut for AliasExports {
struct DefaultRenamer; struct DefaultRenamer;
impl VisitMut for DefaultRenamer { impl VisitMut for DefaultRenamer {
noop_visit_mut_type!();
fn visit_mut_export_named_specifier(&mut self, n: &mut ExportNamedSpecifier) { fn visit_mut_export_named_specifier(&mut self, n: &mut ExportNamedSpecifier) {
if n.orig.sym == js_word!("default") { if n.orig.sym == js_word!("default") {
n.orig.sym = "__default".into() n.orig.sym = "__default".into()

View File

@ -8,6 +8,7 @@ use crate::{
use anyhow::{Context, Error}; use anyhow::{Context, Error};
use std::{ use std::{
borrow::Cow, borrow::Cow,
collections::HashSet,
mem::take, mem::take,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
}; };
@ -15,7 +16,9 @@ use swc_atoms::{js_word, JsWord};
use swc_common::{Mark, Spanned, SyntaxContext, DUMMY_SP}; use swc_common::{Mark, Spanned, SyntaxContext, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_utils::{find_ids, DestructuringFinder, StmtLike}; use swc_ecma_utils::{find_ids, DestructuringFinder, StmtLike};
use swc_ecma_visit::{Fold, FoldWith, VisitMut, VisitMutWith, VisitWith}; use swc_ecma_visit::{
noop_fold_type, noop_visit_mut_type, Fold, FoldWith, VisitMut, VisitMutWith, VisitWith,
};
impl<L, R> Bundler<'_, L, R> impl<L, R> Bundler<'_, L, R>
where where
@ -54,8 +57,7 @@ where
log::info!("Merge: ({}){} <= {:?}", info.id, info.fm.name, targets); log::info!("Merge: ({}){} <= {:?}", info.id, info.fm.name, targets);
entry = self self.merge_reexports(&mut entry, &info, targets)
.merge_reexports(entry, &info, targets)
.context("failed to merge reepxorts")?; .context("failed to merge reepxorts")?;
for (src, specifiers) in &info.imports.specifiers { for (src, specifiers) in &info.imports.specifiers {
@ -71,11 +73,11 @@ where
if let Some(imported) = self.scope.get_module(src.module_id) { if let Some(imported) = self.scope.get_module(src.module_id) {
// Respan using imported module's syntax context. // Respan using imported module's syntax context.
entry = entry.fold_with(&mut LocalMarker { entry.visit_mut_with(&mut LocalMarker {
mark: imported.mark(), mark: imported.mark(),
top_level_ctxt: SyntaxContext::empty().apply_mark(self.top_level_mark),
specifiers: &specifiers, specifiers: &specifiers,
excluded: vec![], excluded: Default::default(),
is_export: false,
}); });
} }
@ -177,11 +179,12 @@ where
dep = dep.fold_with(&mut Unexporter); dep = dep.fold_with(&mut Unexporter);
if !specifiers.is_empty() { if !specifiers.is_empty() {
entry = entry.fold_with(&mut LocalMarker { entry.visit_mut_with(&mut LocalMarker {
mark: imported.mark(), mark: imported.mark(),
top_level_ctxt: SyntaxContext::empty()
.apply_mark(self.top_level_mark),
specifiers: &specifiers, specifiers: &specifiers,
excluded: vec![], excluded: Default::default(),
is_export: false,
}); });
// // Note: this does not handle `export default // // Note: this does not handle `export default
@ -196,7 +199,7 @@ where
// Replace import statement / require with module body // Replace import statement / require with module body
let mut injector = Es6ModuleInjector { let mut injector = Es6ModuleInjector {
imported: dep.body.clone(), imported: take(&mut dep.body),
src: src.src.clone(), src: src.src.clone(),
}; };
entry.body.visit_mut_with(&mut injector); entry.body.visit_mut_with(&mut injector);
@ -206,6 +209,7 @@ where
if injector.imported.is_empty() { if injector.imported.is_empty() {
continue; continue;
} }
dep.body = take(&mut injector.imported);
} }
if self.config.require { if self.config.require {
@ -244,6 +248,8 @@ where
pub(super) struct Unexporter; pub(super) struct Unexporter;
impl Fold for Unexporter { impl Fold for Unexporter {
noop_fold_type!();
fn fold_module_item(&mut self, item: ModuleItem) -> ModuleItem { fn fold_module_item(&mut self, item: ModuleItem) -> ModuleItem {
match item { match item {
ModuleItem::ModuleDecl(decl) => match decl { ModuleItem::ModuleDecl(decl) => match decl {
@ -342,6 +348,8 @@ impl ExportRenamer<'_> {
} }
impl Fold for ExportRenamer<'_> { impl Fold for ExportRenamer<'_> {
noop_fold_type!();
fn fold_class(&mut self, node: Class) -> Class { fn fold_class(&mut self, node: Class) -> Class {
node node
} }
@ -485,6 +493,8 @@ struct ActualMarker<'a> {
} }
impl Fold for ActualMarker<'_> { impl Fold for ActualMarker<'_> {
noop_fold_type!();
fn fold_expr(&mut self, node: Expr) -> Expr { fn fold_expr(&mut self, node: Expr) -> Expr {
node node
} }
@ -515,29 +525,13 @@ impl Fold for ActualMarker<'_> {
pub(super) struct LocalMarker<'a> { pub(super) struct LocalMarker<'a> {
/// Mark applied to imported idents. /// Mark applied to imported idents.
pub mark: Mark, pub mark: Mark,
/// Syntax context of the top level items.
pub top_level_ctxt: SyntaxContext,
pub specifiers: &'a [Specifier], pub specifiers: &'a [Specifier],
pub is_export: bool, pub excluded: HashSet<Id>,
pub excluded: Vec<Id>,
} }
impl<'a> LocalMarker<'a> { impl<'a> LocalMarker<'a> {
/// Searches for i, and fold T.
#[allow(dead_code)]
fn recurse<I, F, Ret>(&mut self, excluded_idents: I, op: F) -> Ret
where
F: FnOnce(I, &mut Self) -> Ret,
I: for<'any> VisitWith<DestructuringFinder<'any, Id>>,
{
let len = self.excluded.len();
let ids = find_ids(&excluded_idents);
self.excluded.extend(ids);
let ret = op(excluded_idents, self);
self.excluded.drain(len..);
ret
}
fn exclude<I>(&mut self, excluded_idents: &I) -> Excluder<'a, '_> fn exclude<I>(&mut self, excluded_idents: &I) -> Excluder<'a, '_>
where where
I: for<'any> VisitWith<DestructuringFinder<'any, Id>>, I: for<'any> VisitWith<DestructuringFinder<'any, Id>>,
@ -567,101 +561,77 @@ impl<'a, 'b> DerefMut for Excluder<'a, 'b> {
} }
} }
impl Fold for LocalMarker<'_> { impl VisitMut for LocalMarker<'_> {
fn fold_catch_clause(&mut self, mut node: CatchClause) -> CatchClause { noop_visit_mut_type!();
fn visit_mut_catch_clause(&mut self, node: &mut CatchClause) {
let mut f = self.exclude(&node.param); let mut f = self.exclude(&node.param);
node.body = node.body.fold_with(&mut *f); node.body.visit_mut_with(&mut *f);
node
} }
fn fold_class_decl(&mut self, mut node: ClassDecl) -> ClassDecl { fn visit_mut_class_decl(&mut self, node: &mut ClassDecl) {
self.excluded.push((&node.ident).into()); self.excluded.insert((&node.ident).into());
node.class = node.class.fold_with(self); node.class.visit_mut_with(self);
node
} }
fn fold_class_expr(&mut self, mut node: ClassExpr) -> ClassExpr { fn visit_mut_class_expr(&mut self, node: &mut ClassExpr) {
let mut f = self.exclude(&node.ident); let mut f = self.exclude(&node.ident);
node.class = node.class.fold_with(&mut *f); node.class.visit_mut_with(&mut *f);
node
} }
fn fold_constructor(&mut self, mut node: Constructor) -> Constructor { fn visit_mut_constructor(&mut self, node: &mut Constructor) {
let mut f = self.exclude(&node.params); let mut f = self.exclude(&node.params);
node.body = node.body.fold_with(&mut *f); node.body.visit_mut_with(&mut *f);
node
} }
fn fold_fn_decl(&mut self, mut node: FnDecl) -> FnDecl { fn visit_mut_fn_decl(&mut self, node: &mut FnDecl) {
self.excluded.push((&node.ident).into()); self.excluded.insert((&node.ident).into());
node.function = node.function.fold_with(self); node.function.visit_mut_with(self);
node
} }
fn fold_fn_expr(&mut self, mut node: FnExpr) -> FnExpr { fn visit_mut_fn_expr(&mut self, node: &mut FnExpr) {
let mut f = self.exclude(&node.ident); let mut f = self.exclude(&node.ident);
node.function.visit_mut_with(&mut *f);
node.function = node.function.fold_with(&mut *f);
node
} }
fn fold_function(&mut self, mut node: Function) -> Function { fn visit_mut_function(&mut self, node: &mut Function) {
let mut f = self.exclude(&node.params); let mut f = self.exclude(&node.params);
node.body = node.body.fold_with(&mut *f); node.body.visit_mut_with(&mut *f);
node
} }
fn fold_ident(&mut self, mut node: Ident) -> Ident { fn visit_mut_ident(&mut self, mut node: &mut Ident) {
if self.excluded.iter().any(|i| *i == node) { if node.span.ctxt != self.top_level_ctxt {
return node; return;
}
if self.excluded.contains(&(&*node).into()) {
return;
} }
// TODO: sym() => correct span // TODO: sym() => correct span
if self.is_export { if self.specifiers.iter().any(|id| *id.local() == *node) {
if self.specifiers.iter().any(|id| match id {
Specifier::Specific { local, alias } => match alias {
Some(v) => *v == node,
None => *local == node,
},
Specifier::Namespace { local } => *local == node,
}) {
node.span = node
.span
.with_ctxt(SyntaxContext::empty().apply_mark(self.mark));
}
} else {
if self.specifiers.iter().any(|id| *id.local() == node) {
node.span = node node.span = node
.span .span
.with_ctxt(SyntaxContext::empty().apply_mark(self.mark)); .with_ctxt(SyntaxContext::empty().apply_mark(self.mark));
// dbg!(&node);
} }
} }
node fn visit_mut_labeled_stmt(&mut self, node: &mut LabeledStmt) {
node.body.visit_mut_with(self);
} }
fn fold_labeled_stmt(&mut self, node: LabeledStmt) -> LabeledStmt { fn visit_mut_member_expr(&mut self, e: &mut MemberExpr) {
LabeledStmt { e.obj.visit_mut_with(self);
body: node.body.fold_with(self),
..node
}
}
fn fold_member_expr(&mut self, mut e: MemberExpr) -> MemberExpr {
e.obj = e.obj.fold_with(self);
if e.computed { if e.computed {
e.prop = e.prop.fold_with(self); e.prop.visit_mut_with(self);
}
} }
e fn visit_mut_setter_prop(&mut self, node: &mut SetterProp) {
}
fn fold_setter_prop(&mut self, mut node: SetterProp) -> SetterProp {
let mut f = self.exclude(&node.param); let mut f = self.exclude(&node.param);
node.body = node.body.fold_with(&mut *f); node.body.visit_mut_with(&mut *f);
node
} }
} }
@ -671,6 +641,8 @@ struct Es6ModuleInjector {
} }
impl VisitMut for Es6ModuleInjector { impl VisitMut for Es6ModuleInjector {
noop_visit_mut_type!();
fn visit_mut_module_items(&mut self, orig: &mut Vec<ModuleItem>) { fn visit_mut_module_items(&mut self, orig: &mut Vec<ModuleItem>) {
let items = take(orig); let items = take(orig);
let mut buf = Vec::with_capacity(self.imported.len() + items.len()); let mut buf = Vec::with_capacity(self.imported.len() + items.len());

View File

@ -8,7 +8,7 @@ use swc_atoms::js_word;
use swc_common::{FileName, SyntaxContext}; use swc_common::{FileName, SyntaxContext};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_utils::find_ids; use swc_ecma_utils::find_ids;
use swc_ecma_visit::{VisitMut, VisitMutWith}; use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};
impl<L, R> Bundler<'_, L, R> impl<L, R> Bundler<'_, L, R>
where where
@ -92,6 +92,8 @@ where
L: Load, L: Load,
R: Resolve, R: Resolve,
{ {
noop_visit_mut_type!();
fn visit_mut_module_item(&mut self, item: &mut ModuleItem) { fn visit_mut_module_item(&mut self, item: &mut ModuleItem) {
match item { match item {
// TODO: Optimize pure constants // TODO: Optimize pure constants

View File

@ -7,8 +7,7 @@ use std::{
}; };
use swc_common::{util::move_map::MoveMap, FileName}; use swc_common::{util::move_map::MoveMap, FileName};
use swc_ecma_ast::{ImportDecl, Str}; use swc_ecma_ast::{ImportDecl, Str};
use swc_ecma_transforms::noop_fold_type; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
use swc_ecma_visit::{Fold, FoldWith};
impl<L, R> Bundler<'_, L, R> impl<L, R> Bundler<'_, L, R>
where where
@ -121,12 +120,12 @@ where
renamed: &'a HashMap<PathBuf, String>, renamed: &'a HashMap<PathBuf, String>,
} }
noop_fold_type!(Renamer<'_, '_>);
impl<R> Fold for Renamer<'_, R> impl<R> Fold for Renamer<'_, R>
where where
R: Resolve, R: Resolve,
{ {
noop_fold_type!();
fn fold_import_decl(&mut self, import: ImportDecl) -> ImportDecl { fn fold_import_decl(&mut self, import: ImportDecl) -> ImportDecl {
let resolved = match self let resolved = match self
.resolver .resolver

View File

@ -3,8 +3,7 @@ use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
use swc_common::{FileName, FilePathMapping, SourceMap}; use swc_common::{FileName, FilePathMapping, SourceMap};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_parser::{lexer::Lexer, Parser, StringInput}; use swc_ecma_parser::{lexer::Lexer, Parser, StringInput};
use swc_ecma_utils::{prepend_stmts, DropSpan}; use swc_ecma_utils::{drop_span, prepend_stmts};
use swc_ecma_visit::FoldWith;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub(super) struct Helpers { pub(super) struct Helpers {
@ -35,9 +34,7 @@ macro_rules! define {
); );
let stmts = Parser::new_from(lexer) let stmts = Parser::new_from(lexer)
.parse_module() .parse_module()
.map(|script| script.body.fold_with(&mut DropSpan { .map(|script| drop_span(script.body))
preserve_ctxt:false,
}))
.map_err(|_| { .map_err(|_| {
() ()
}) })

View File

@ -11,7 +11,7 @@ use swc_common::{
}; };
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_utils::{find_ids, ident::IdentLike, Id}; use swc_ecma_utils::{find_ids, ident::IdentLike, Id};
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -143,6 +143,8 @@ where
L: Load, L: Load,
R: Resolve, R: Resolve,
{ {
noop_fold_type!();
fn fold_import_decl(&mut self, mut import: ImportDecl) -> ImportDecl { fn fold_import_decl(&mut self, mut import: ImportDecl) -> ImportDecl {
if !self.deglob_phase { if !self.deglob_phase {
// Ignore if it's a core module. // Ignore if it's a core module.

View File

@ -17,7 +17,7 @@ use swc_ecma_ast::{
ModuleDecl, Str, ModuleDecl, Str,
}; };
use swc_ecma_transforms::resolver_with_mark; use swc_ecma_transforms::resolver_with_mark;
use swc_ecma_visit::{FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_visit_type, FoldWith, Node, Visit, VisitWith};
/// Module after applying transformations. /// Module after applying transformations.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(super) struct TransformedModule { pub(super) struct TransformedModule {
@ -375,6 +375,8 @@ struct Es6ModuleDetector {
} }
impl Visit for Es6ModuleDetector { impl Visit for Es6ModuleDetector {
noop_visit_type!();
fn visit_call_expr(&mut self, e: &CallExpr, _: &dyn Node) { fn visit_call_expr(&mut self, e: &CallExpr, _: &dyn Node) {
e.visit_children_with(self); e.visit_children_with(self);

View File

@ -7,7 +7,7 @@ use swc_common::{sync::Lrc, FileName, SourceFile, SourceMap, GLOBALS};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_parser::{lexer::Lexer, JscTarget, Parser, StringInput}; use swc_ecma_parser::{lexer::Lexer, JscTarget, Parser, StringInput};
use swc_ecma_utils::drop_span; use swc_ecma_utils::drop_span;
use swc_ecma_visit::FoldWith; use swc_ecma_visit::VisitMutWith;
pub(super) struct Tester<'a> { pub(super) struct Tester<'a> {
pub cm: Lrc<SourceMap>, pub cm: Lrc<SourceMap>,
@ -84,7 +84,10 @@ impl<'a> Tester<'a> {
pub fn assert_eq(&self, m: &Module, expected: &str) { pub fn assert_eq(&self, m: &Module, expected: &str) {
let expected = self.parse(expected); let expected = self.parse(expected);
let m = drop_span(m.clone().fold_with(&mut HygieneRemover)); let mut m = m.clone();
m.visit_mut_with(&mut HygieneRemover);
let m = drop_span(m);
let expected = drop_span(expected); let expected = drop_span(expected);
assert_eq!(m, expected) assert_eq!(m, expected)

View File

@ -4,7 +4,7 @@ use std::io::{stdout, Write};
use swc_common::{sync::Lrc, SourceMap}; use swc_common::{sync::Lrc, SourceMap};
use swc_ecma_ast::{Ident, Module}; use swc_ecma_ast::{Ident, Module};
use swc_ecma_codegen::{text_writer::JsWriter, Emitter}; use swc_ecma_codegen::{text_writer::JsWriter, Emitter};
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub(crate) fn print_hygiene(event: &str, cm: &Lrc<SourceMap>, t: &Module) { pub(crate) fn print_hygiene(event: &str, cm: &Lrc<SourceMap>, t: &Module) {
let module = t.clone().fold_with(&mut HygieneVisualizer); let module = t.clone().fold_with(&mut HygieneVisualizer);
@ -27,6 +27,8 @@ pub(crate) fn print_hygiene(event: &str, cm: &Lrc<SourceMap>, t: &Module) {
struct HygieneVisualizer; struct HygieneVisualizer;
impl Fold for HygieneVisualizer { impl Fold for HygieneVisualizer {
noop_fold_type!();
fn fold_ident(&mut self, node: Ident) -> Ident { fn fold_ident(&mut self, node: Ident) -> Ident {
Ident { Ident {
sym: format!("{}{:?}", node.sym, node.span.ctxt()).into(), sym: format!("{}{:?}", node.sym, node.span.ctxt()).into(),

View File

@ -1,6 +1,6 @@
use std::hash::Hash; use std::hash::Hash;
use swc_common::{Span, SyntaxContext}; use swc_common::{Span, SyntaxContext};
use swc_ecma_visit::Fold; use swc_ecma_visit::{noop_visit_mut_type, VisitMut};
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct CloneMap<K, V> pub(crate) struct CloneMap<K, V>
@ -62,9 +62,11 @@ where
pub(crate) struct HygieneRemover; pub(crate) struct HygieneRemover;
impl Fold for HygieneRemover { impl VisitMut for HygieneRemover {
fn fold_span(&mut self, s: Span) -> Span { noop_visit_mut_type!();
s.with_ctxt(SyntaxContext::empty())
fn visit_mut_span(&mut self, s: &mut Span) {
*s = s.with_ctxt(SyntaxContext::empty())
} }
} }

View File

@ -1,17 +1,2 @@
/// Copied from `syntax::ptr::P` /// Moved
pub trait Map<T> { pub use swc_visit::util::map::Map;
/// Transform the inner value, consuming `self` and producing a new `P<T>`.
fn map<F>(self, f: F) -> Self
where
F: FnOnce(T) -> T;
}
impl<T> Map<T> for Box<T> {
fn map<F>(mut self, f: F) -> Self
where
F: FnOnce(T) -> T,
{
*self = f(*self);
self
}
}

View File

@ -1,93 +1 @@
use std::{iter, ptr}; pub use swc_visit::util::move_map::MoveMap;
pub trait MoveMap<T>: Sized {
fn move_map<F>(self, mut f: F) -> Self
where
F: FnMut(T) -> T,
{
self.move_flat_map(|e| iter::once(f(e)))
}
fn move_flat_map<F, I>(self, f: F) -> Self
where
F: FnMut(T) -> I,
I: IntoIterator<Item = T>;
}
impl<T> MoveMap<T> for Vec<T> {
/// This reduces binary size.
fn move_map<F>(mut self, mut f: F) -> Self
where
F: FnMut(T) -> T,
{
let mut read_i = 0;
let mut write_i = 0;
unsafe {
let old_len = self.len();
self.set_len(0); // make sure we just leak elements in case of panic
while read_i < old_len {
// move the read_i'th item out of the vector and map it
// to an iterator
let e = ptr::read(self.get_unchecked(read_i));
let e = f(e);
read_i += 1;
assert!(write_i < read_i);
ptr::write(self.get_unchecked_mut(write_i), e);
write_i += 1;
}
// write_i tracks the number of actually written new items.
self.set_len(write_i);
}
self
}
fn move_flat_map<F, I>(mut self, mut f: F) -> Self
where
F: FnMut(T) -> I,
I: IntoIterator<Item = T>,
{
let mut read_i = 0;
let mut write_i = 0;
unsafe {
let mut old_len = self.len();
self.set_len(0); // make sure we just leak elements in case of panic
while read_i < old_len {
// move the read_i'th item out of the vector and map it
// to an iterator
let e = ptr::read(self.get_unchecked(read_i));
let iter = f(e).into_iter();
read_i += 1;
for e in iter {
if write_i < read_i {
ptr::write(self.get_unchecked_mut(write_i), e);
write_i += 1;
} else {
// If this is reached we ran out of space
// in the middle of the vector.
// However, the vector is in a valid state here,
// so we just do a somewhat inefficient insert.
self.set_len(old_len);
self.insert(write_i, e);
old_len = self.len();
self.set_len(0);
read_i += 1;
write_i += 1;
}
}
}
// write_i tracks the number of actually written new items.
self.set_len(write_i);
}
self
}
}

View File

@ -1,6 +1,6 @@
[package] [package]
name = "swc_ecmascript" name = "swc_ecmascript"
version = "0.3.2" version = "0.4.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"] authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT" license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git" repository = "https://github.com/swc-project/swc.git"
@ -17,10 +17,10 @@ visit = ["swc_ecma_visit"]
[dependencies] [dependencies]
swc_ecma_ast = { version = "0.28.0", path ="./ast" } swc_ecma_ast = { version = "0.28.0", path ="./ast" }
swc_ecma_codegen = { version = "0.31.0", path ="./codegen", optional = true } swc_ecma_codegen = { version = "0.32.0", path ="./codegen", optional = true }
swc_ecma_parser = { version = "0.33.3", path ="./parser", optional = true } swc_ecma_parser = { version = "0.34.0", path ="./parser", optional = true }
swc_ecma_utils = { version = "0.17.0", path ="./utils", optional = true } swc_ecma_utils = { version = "0.18.0", path ="./utils", optional = true }
swc_ecma_transforms = { version = "0.19.5", path ="./transforms", optional = true } swc_ecma_transforms = { version = "0.20.0", path ="./transforms", optional = true }
swc_ecma_visit = { version = "0.13.0", path ="./visit", optional = true } swc_ecma_visit = { version = "0.14.0", path ="./visit", optional = true }
[dev-dependencies] [dev-dependencies]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "swc_ecma_codegen" name = "swc_ecma_codegen"
version = "0.31.0" version = "0.32.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"] authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT" license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git" repository = "https://github.com/swc-project/swc.git"
@ -20,5 +20,5 @@ num-bigint = { version = "0.2", features = ["serde"] }
[dev-dependencies] [dev-dependencies]
swc_common = { version = "0.9.0", path ="../../common", features = ["sourcemap"] } swc_common = { version = "0.9.0", path ="../../common", features = ["sourcemap"] }
swc_ecma_parser = { version = "0.33.0", path ="../parser" } swc_ecma_parser = { version = "0.34.0", path ="../parser" }
testing = { version = "0.9.0", path ="../../testing" } testing = { version = "0.9.0", path ="../../testing" }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "jsdoc" name = "jsdoc"
version = "0.1.0" version = "0.2.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"] authors = ["강동윤 <kdy1997.dev@gmail.com>"]
edition = "2018" edition = "2018"
license = "Apache-2.0/MIT" license = "Apache-2.0/MIT"
@ -17,7 +17,7 @@ serde = { version = "1", features = ["derive"] }
[dev-dependencies] [dev-dependencies]
swc_ecma_ast = { version = "0.28.0", path = "../ast" } swc_ecma_ast = { version = "0.28.0", path = "../ast" }
swc_ecma_parser = { version = "0.33.3", path = "../parser" } swc_ecma_parser = { version = "0.34.0", path = "../parser" }
testing = { version = "0.9.0", path = "../../testing" } testing = { version = "0.9.0", path = "../../testing" }
anyhow = "1" anyhow = "1"
dashmap = "3" dashmap = "3"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "swc_ecma_parser" name = "swc_ecma_parser"
version = "0.33.3" version = "0.34.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"] authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT" license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git" repository = "https://github.com/swc-project/swc.git"
@ -17,7 +17,7 @@ swc_atoms = { version = "0.2", path ="../../atoms" }
swc_common = { version = "0.9.0", path ="../../common" } swc_common = { version = "0.9.0", path ="../../common" }
swc_ecma_ast = { version = "0.28.0", path ="../ast" } swc_ecma_ast = { version = "0.28.0", path ="../ast" }
swc_ecma_parser_macros = { version = "0.4.1", path ="./macros" } swc_ecma_parser_macros = { version = "0.4.1", path ="./macros" }
swc_ecma_visit = { version = "0.13.0", path ="../visit" } swc_ecma_visit = { version = "0.14.0", path ="../visit" }
enum_kind = { version = "0.2", path ="../../macros/enum_kind" } enum_kind = { version = "0.2", path ="../../macros/enum_kind" }
unicode-xid = "0.2" unicode-xid = "0.2"
log = "0.4" log = "0.4"

View File

@ -0,0 +1,101 @@
#![feature(test)]
extern crate test;
use swc_common::{FileName, Span, SyntaxContext, DUMMY_SP};
use swc_ecma_ast::Module;
use swc_ecma_parser::{Parser, StringInput, Syntax};
use swc_ecma_visit::{Fold, FoldWith, VisitMut, VisitMutWith};
use test::Bencher;
static SOURCE: &str = include_str!("../../parser/benches/files/angular-1.2.5.js");
fn run<F>(b: &mut Bencher, mut op: F)
where
F: FnMut(Module) -> Module,
{
let _ = ::testing::run_test(false, |cm, _| {
let fm = cm.new_source_file(FileName::Anon, SOURCE.into());
let mut parser = Parser::new(Syntax::default(), StringInput::from(&*fm), None);
let module = parser.parse_module().map_err(|_| ()).unwrap();
b.iter(|| {
let module = module.clone();
let module = op(module);
test::black_box(module)
});
Ok(())
});
}
#[bench]
fn base_clone(b: &mut Bencher) {
run(b, |m| m);
}
#[bench]
fn visit_mut_span(b: &mut Bencher) {
struct RespanVisitMut;
impl VisitMut for RespanVisitMut {
fn visit_mut_span(&mut self, span: &mut Span) {
*span = DUMMY_SP;
}
}
run(b, |mut m| {
m.visit_mut_with(&mut RespanVisitMut);
m
});
}
#[bench]
fn visit_mut_span_panic(b: &mut Bencher) {
struct RespanVisitMut;
impl VisitMut for RespanVisitMut {
fn visit_mut_span(&mut self, span: &mut Span) {
if span.ctxt != SyntaxContext::empty() {
panic!()
}
*span = DUMMY_SP;
}
}
run(b, |mut m| {
m.visit_mut_with(&mut RespanVisitMut);
m
});
}
#[bench]
fn fold_span(b: &mut Bencher) {
struct RespanFold;
impl Fold for RespanFold {
fn fold_span(&mut self, _: Span) -> Span {
DUMMY_SP
}
}
run(b, |m| m.fold_with(&mut RespanFold));
}
#[bench]
fn fold_span_pnic(b: &mut Bencher) {
struct RespanFold;
impl Fold for RespanFold {
fn fold_span(&mut self, s: Span) -> Span {
if s.ctxt != SyntaxContext::empty() {
panic!()
}
DUMMY_SP
}
}
run(b, |m| m.fold_with(&mut RespanFold));
}

View File

@ -1,6 +1,6 @@
use super::*; use super::*;
use swc_common::{Span, Spanned, DUMMY_SP}; use swc_common::{Span, Spanned, DUMMY_SP};
use swc_ecma_visit::{Node, Visit, VisitWith}; use swc_ecma_visit::{noop_visit_type, Node, Visit, VisitWith};
impl<'a, I: Tokens> Parser<I> { impl<'a, I: Tokens> Parser<I> {
pub(in crate::parser) fn verify_expr(&mut self, expr: Box<Expr>) -> PResult<Box<Expr>> { pub(in crate::parser) fn verify_expr(&mut self, expr: Box<Expr>) -> PResult<Box<Expr>> {
@ -21,6 +21,8 @@ pub(super) struct Verifier {
} }
impl Visit for Verifier { impl Visit for Verifier {
noop_visit_type!();
fn visit_assign_prop(&mut self, p: &AssignProp, _: &dyn Node) { fn visit_assign_prop(&mut self, p: &AssignProp, _: &dyn Node) {
self.errors.push((p.span(), SyntaxError::AssignProperty)); self.errors.push((p.span(), SyntaxError::AssignProperty));
} }

View File

@ -8,7 +8,7 @@ use fxhash::FxHashSet;
use swc_atoms::{js_word, JsWord}; use swc_atoms::{js_word, JsWord};
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Node, Visit, VisitWith}; use swc_ecma_visit::{noop_visit_type, Node, Visit, VisitWith};
mod builtin; mod builtin;
mod data; mod data;
@ -123,6 +123,8 @@ impl UsageVisitor {
/// Detects usage of types /// Detects usage of types
impl Visit for UsageVisitor { impl Visit for UsageVisitor {
noop_visit_type!();
fn visit_ident(&mut self, node: &Ident, _: &dyn Node) { fn visit_ident(&mut self, node: &Ident, _: &dyn Node) {
node.visit_children_with(self); node.visit_children_with(self);

View File

@ -15,7 +15,7 @@ use fxhash::FxHashSet;
use swc_atoms::{js_word, JsWord}; use swc_atoms::{js_word, JsWord};
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Node, Visit, VisitWith}; use swc_ecma_visit::{noop_visit_type, Node, Visit, VisitWith};
pub(crate) struct UsageVisitor { pub(crate) struct UsageVisitor {
shipped_proposals: bool, shipped_proposals: bool,
@ -145,6 +145,8 @@ impl UsageVisitor {
} }
impl Visit for UsageVisitor { impl Visit for UsageVisitor {
noop_visit_type!();
/// `[a, b] = c` /// `[a, b] = c`
fn visit_array_pat(&mut self, p: &ArrayPat, _: &dyn Node) { fn visit_array_pat(&mut self, p: &ArrayPat, _: &dyn Node) {
p.visit_children_with(self); p.visit_children_with(self);

View File

@ -81,14 +81,9 @@ pub fn preset_env(global_mark: Mark, c: Config) -> impl Fold {
let pass = add!(pass, ExponentiationOperator, es2016::exponentation()); let pass = add!(pass, ExponentiationOperator, es2016::exponentation());
// ES2015 // ES2015
let pass = add!(pass, BlockScopedFunctions, es2015::BlockScopedFns); let pass = add!(pass, BlockScopedFunctions, es2015::block_scoped_functions());
let pass = add!( let pass = add!(pass, TemplateLiterals, es2015::template_literal(), true);
pass, let pass = add!(pass, Classes, es2015::classes());
TemplateLiterals,
es2015::TemplateLiteral::default(),
true
);
let pass = add!(pass, Classes, es2015::Classes::default());
let pass = add!( let pass = add!(
pass, pass,
Spread, Spread,
@ -98,10 +93,10 @@ pub fn preset_env(global_mark: Mark, c: Config) -> impl Fold {
let pass = add!(pass, FunctionName, es2015::function_name()); let pass = add!(pass, FunctionName, es2015::function_name());
let pass = add!(pass, ArrowFunctions, es2015::arrow()); let pass = add!(pass, ArrowFunctions, es2015::arrow());
let pass = add!(pass, DuplicateKeys, es2015::duplicate_keys()); let pass = add!(pass, DuplicateKeys, es2015::duplicate_keys());
let pass = add!(pass, StickyRegex, es2015::StickyRegex); let pass = add!(pass, StickyRegex, es2015::sticky_regex());
// TODO: InstanceOf, // TODO: InstanceOf,
let pass = add!(pass, TypeOfSymbol, es2015::TypeOfSymbol); let pass = add!(pass, TypeOfSymbol, es2015::typeof_symbol());
let pass = add!(pass, ShorthandProperties, es2015::Shorthand); let pass = add!(pass, ShorthandProperties, es2015::shorthand());
let pass = add!(pass, Parameters, es2015::parameters()); let pass = add!(pass, Parameters, es2015::parameters());
let pass = add!( let pass = add!(
pass, pass,
@ -138,15 +133,13 @@ pub fn preset_env(global_mark: Mark, c: Config) -> impl Fold {
// NamedCapturingGroupsRegex, // NamedCapturingGroupsRegex,
// ES 3 // ES 3
let pass = add!(pass, PropertyLiterals, es3::PropertyLiteral); let pass = add!(pass, PropertyLiterals, es3::property_literals());
let pass = add!(pass, MemberExpressionLiterals, es3::MemberExprLit);
let pass = add!( let pass = add!(
pass, pass,
ReservedWords, MemberExpressionLiterals,
es3::ReservedWord { es3::member_expression_literals()
preserve_import: c.dynamic_import
}
); );
let pass = add!(pass, ReservedWords, es3::reserved_words(c.dynamic_import));
if c.debug { if c.debug {
println!("Targets: {:?}", targets); println!("Targets: {:?}", targets);

View File

@ -1,6 +1,6 @@
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_ecma_ast::Invalid; use swc_ecma_ast::Invalid;
use swc_ecma_visit::{Visit, VisitWith}; use swc_ecma_visit::{noop_visit_type, Visit, VisitWith};
pub(super) fn is_required<T: VisitWith<RegeneratorVisitor>>(node: &T) -> bool { pub(super) fn is_required<T: VisitWith<RegeneratorVisitor>>(node: &T) -> bool {
let mut v = RegeneratorVisitor { found: false }; let mut v = RegeneratorVisitor { found: false };
@ -13,4 +13,6 @@ pub(super) struct RegeneratorVisitor {
} }
/// TODO /// TODO
impl Visit for RegeneratorVisitor {} impl Visit for RegeneratorVisitor {
noop_visit_type!();
}

View File

@ -19,7 +19,7 @@ use swc_ecma_ast::*;
use swc_ecma_codegen::Emitter; use swc_ecma_codegen::Emitter;
use swc_ecma_parser::{EsConfig, Parser, Syntax}; use swc_ecma_parser::{EsConfig, Parser, Syntax};
use swc_ecma_preset_env::{preset_env, Config, FeatureOrModule, Mode, Targets, Version}; use swc_ecma_preset_env::{preset_env, Config, FeatureOrModule, Mode, Targets, Version};
use swc_ecma_transforms::util::DropSpan; use swc_ecma_transforms::util::drop_span;
use swc_ecma_visit::FoldWith; use swc_ecma_visit::FoldWith;
use test::{test_main, ShouldPanic, TestDesc, TestDescAndFn, TestFn, TestName, TestType}; use test::{test_main, ShouldPanic, TestDesc, TestDescAndFn, TestFn, TestName, TestType};
use testing::Tester; use testing::Tester;
@ -304,11 +304,7 @@ fn exec(c: PresetConfig, dir: PathBuf) -> Result<(), Error> {
let actual_src = print(&actual); let actual_src = print(&actual);
let expected_src = print(&expected); let expected_src = print(&expected);
if actual.fold_with(&mut DropSpan { if drop_span(actual) == drop_span(expected) {
preserve_ctxt: false,
}) == expected.fold_with(&mut DropSpan {
preserve_ctxt: false,
}) {
return Ok(()); return Ok(());
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "swc_ecma_transforms" name = "swc_ecma_transforms"
version = "0.19.8" version = "0.20.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"] authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT" license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git" repository = "https://github.com/swc-project/swc.git"
@ -14,13 +14,13 @@ react = ["dashmap"]
default = [] default = []
[dependencies] [dependencies]
jsdoc = { version = "0.1.0", path ="../jsdoc" } jsdoc = { version = "0.2.0", path ="../jsdoc" }
swc_atoms = { version = "0.2.0", path ="../../atoms" } swc_atoms = { version = "0.2.0", path ="../../atoms" }
swc_common = { version = "0.9.0", path ="../../common" } swc_common = { version = "0.9.0", path ="../../common" }
swc_ecma_ast = { version = "0.28.0", path ="../ast" } swc_ecma_ast = { version = "0.28.0", path ="../ast" }
swc_ecma_utils = { version = "0.17.0", path ="../utils" } swc_ecma_utils = { version = "0.18.0", path ="../utils" }
swc_ecma_parser = { version = "0.33.0", path ="../parser" } swc_ecma_parser = { version = "0.34.0", path ="../parser" }
swc_ecma_visit = { version = "0.13.0", path ="../visit" } swc_ecma_visit = { version = "0.14.0", path ="../visit" }
dashmap = { version = "3", optional = true } dashmap = { version = "3", optional = true }
either = "1.5" either = "1.5"
fxhash = "0.2" fxhash = "0.2"
@ -40,7 +40,7 @@ log = "0.4.8"
[dev-dependencies] [dev-dependencies]
testing = { version = "0.9.0", path ="../../testing" } testing = { version = "0.9.0", path ="../../testing" }
swc_ecma_codegen = { version = "0.31.0", path ="../codegen" } swc_ecma_codegen = { version = "0.32.0", path ="../codegen" }
tempfile = "3" tempfile = "3"
pretty_assertions = "0.6" pretty_assertions = "0.6"
sourcemap = "6" sourcemap = "6"

View File

@ -166,7 +166,7 @@ fn es2015_arrow(b: &mut Bencher) {
#[bench] #[bench]
fn es2015_block_scoped_fn(b: &mut Bencher) { fn es2015_block_scoped_fn(b: &mut Bencher) {
tr!(b, || compat::es2015::BlockScopedFns); tr!(b, || compat::es2015::block_scoped_functions());
} }
#[bench] #[bench]
@ -176,7 +176,7 @@ fn es2015_block_scoping(b: &mut Bencher) {
#[bench] #[bench]
fn es2015_classes(b: &mut Bencher) { fn es2015_classes(b: &mut Bencher) {
tr!(b, || compat::es2015::Classes::default()); tr!(b, || compat::es2015::classes());
} }
#[bench] #[bench]
@ -211,12 +211,12 @@ fn es2015_for_of(b: &mut Bencher) {
#[bench] #[bench]
fn es2015_instanceof(b: &mut Bencher) { fn es2015_instanceof(b: &mut Bencher) {
tr!(b, || compat::es2015::InstanceOf); tr!(b, || compat::es2015::instance_of());
} }
#[bench] #[bench]
fn es2015_shorthand_property(b: &mut Bencher) { fn es2015_shorthand_property(b: &mut Bencher) {
tr!(b, || compat::es2015::Shorthand); tr!(b, || compat::es2015::shorthand());
} }
#[bench] #[bench]
@ -230,12 +230,12 @@ fn es2015_spread(b: &mut Bencher) {
#[bench] #[bench]
fn es2015_sticky_regex(b: &mut Bencher) { fn es2015_sticky_regex(b: &mut Bencher) {
tr!(b, || compat::es2015::StickyRegex); tr!(b, || compat::es2015::sticky_regex());
} }
#[bench] #[bench]
fn es2015_typeof_symbol(b: &mut Bencher) { fn es2015_typeof_symbol(b: &mut Bencher) {
tr!(b, || compat::es2015::TypeOfSymbol); tr!(b, || compat::es2015::typeof_symbol());
} }
#[bench] #[bench]

View File

@ -1,10 +1,10 @@
pub use self::{ pub use self::{
arrow::arrow, block_scoped_fn::BlockScopedFns, block_scoping::block_scoping, classes::Classes, arrow::arrow, block_scoped_fn::block_scoped_functions, block_scoping::block_scoping,
computed_props::computed_properties, destructuring::destructuring, classes::classes, computed_props::computed_properties, destructuring::destructuring,
duplicate_keys::duplicate_keys, for_of::for_of, function_name::function_name, duplicate_keys::duplicate_keys, for_of::for_of, function_name::function_name,
instanceof::InstanceOf, parameters::parameters, regenerator::regenerator, instanceof::instance_of, parameters::parameters, regenerator::regenerator,
shorthand_property::Shorthand, spread::spread, sticky_regex::StickyRegex, shorthand_property::shorthand, spread::spread, sticky_regex::sticky_regex,
template_literal::TemplateLiteral, typeof_symbol::TypeOfSymbol, template_literal::template_literal, typeof_symbol::typeof_symbol,
}; };
use serde::Deserialize; use serde::Deserialize;
use swc_common::{chain, Mark}; use swc_common::{chain, Mark};
@ -32,19 +32,19 @@ fn exprs() -> impl Fold {
chain!( chain!(
arrow(), arrow(),
duplicate_keys(), duplicate_keys(),
StickyRegex, sticky_regex(),
InstanceOf, instance_of(),
TypeOfSymbol, typeof_symbol(),
Shorthand, shorthand(),
) )
} }
/// Compiles es2015 to es5. /// Compiles es2015 to es5.
pub fn es2015(global_mark: Mark, c: Config) -> impl Fold { pub fn es2015(global_mark: Mark, c: Config) -> impl Fold {
chain!( chain!(
BlockScopedFns, block_scoped_functions(),
TemplateLiteral::default(), template_literal(),
Classes::default(), classes(),
spread(c.spread), spread(c.spread),
function_name(), function_name(),
exprs(), exprs(),
@ -145,7 +145,7 @@ export default function fn1() {
test!( test!(
::swc_ecma_parser::Syntax::default(), ::swc_ecma_parser::Syntax::default(),
|_| chain!(BlockScopedFns, resolver(),), |_| chain!(block_scoped_functions(), resolver(),),
issue_271, issue_271,
" "
function foo(scope) { function foo(scope) {

View File

@ -2,7 +2,7 @@ use crate::util::{contains_this_expr, ExprFactory};
use swc_common::{Spanned, DUMMY_SP}; use swc_common::{Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_utils::quote_ident; use swc_ecma_utils::quote_ident;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
/// Compile ES2015 arrow functions to ES5 /// Compile ES2015 arrow functions to ES5
/// ///
@ -58,9 +58,9 @@ pub fn arrow() -> impl Fold {
struct Arrow; struct Arrow;
noop_fold_type!(Arrow);
impl Fold for Arrow { impl Fold for Arrow {
noop_fold_type!();
fn fold_expr(&mut self, e: Expr) -> Expr { fn fold_expr(&mut self, e: Expr) -> Expr {
// fast path // fast path
if !contains_arrow_expr(&e) { if !contains_arrow_expr(&e) {
@ -141,6 +141,8 @@ struct ArrowVisitor {
found: bool, found: bool,
} }
impl Visit for ArrowVisitor { impl Visit for ArrowVisitor {
noop_visit_type!();
fn visit_arrow_expr(&mut self, _: &ArrowExpr, _: &dyn Node) { fn visit_arrow_expr(&mut self, _: &ArrowExpr, _: &dyn Node) {
self.found = true; self.found = true;
} }

View File

@ -1,14 +1,18 @@
use crate::util::UsageFinder; use crate::util::UsageFinder;
use swc_common::{Spanned, DUMMY_SP}; use swc_common::{Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub fn block_scoped_functions() -> impl Fold {
BlockScopedFns
}
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct BlockScopedFns; struct BlockScopedFns;
noop_fold_type!(BlockScopedFns);
impl Fold for BlockScopedFns { impl Fold for BlockScopedFns {
noop_fold_type!();
fn fold_stmts(&mut self, items: Vec<Stmt>) -> Vec<Stmt> { fn fold_stmts(&mut self, items: Vec<Stmt>) -> Vec<Stmt> {
let mut stmts = Vec::with_capacity(items.len()); let mut stmts = Vec::with_capacity(items.len());
let mut extra_stmts = Vec::with_capacity(items.len()); let mut extra_stmts = Vec::with_capacity(items.len());

View File

@ -6,7 +6,7 @@ use swc_ecma_ast::*;
use swc_ecma_utils::{ use swc_ecma_utils::{
find_ids, ident::IdentLike, prepend, var::VarCollector, ExprFactory, Id, StmtLike, find_ids, ident::IdentLike, prepend, var::VarCollector, ExprFactory, Id, StmtLike,
}; };
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
/// ///
/// ///
@ -50,8 +50,6 @@ struct BlockScoping {
var_decl_kind: VarDeclKind, var_decl_kind: VarDeclKind,
} }
noop_fold_type!(BlockScoping);
impl BlockScoping { impl BlockScoping {
/// This methods remove [ScopeKind::Loop] and [ScopeKind::Fn], but not /// This methods remove [ScopeKind::Loop] and [ScopeKind::Fn], but not
/// [ScopeKind::ForLetLoop] /// [ScopeKind::ForLetLoop]
@ -341,6 +339,8 @@ impl BlockScoping {
} }
impl Fold for BlockScoping { impl Fold for BlockScoping {
noop_fold_type!();
fn fold_arrow_expr(&mut self, f: ArrowExpr) -> ArrowExpr { fn fold_arrow_expr(&mut self, f: ArrowExpr) -> ArrowExpr {
ArrowExpr { ArrowExpr {
params: f.params.fold_with(self), params: f.params.fold_with(self),
@ -592,9 +592,9 @@ struct InfectionFinder<'a> {
found: bool, found: bool,
} }
noop_visit_type!(InfectionFinder<'_>);
impl Visit for InfectionFinder<'_> { impl Visit for InfectionFinder<'_> {
noop_visit_type!();
fn visit_assign_expr(&mut self, node: &AssignExpr, _: &dyn Node) { fn visit_assign_expr(&mut self, node: &AssignExpr, _: &dyn Node) {
let old = self.found; let old = self.found;
self.found = false; self.found = false;
@ -656,10 +656,10 @@ struct FlowHelper {
has_return: bool, has_return: bool,
} }
noop_fold_type!(FlowHelper);
/// noop /// noop
impl Fold for FlowHelper { impl Fold for FlowHelper {
noop_fold_type!();
fn fold_arrow_expr(&mut self, f: ArrowExpr) -> ArrowExpr { fn fold_arrow_expr(&mut self, f: ArrowExpr) -> ArrowExpr {
f f
} }
@ -728,9 +728,9 @@ struct FunctionFinder {
found: bool, found: bool,
} }
noop_visit_type!(FunctionFinder);
impl Visit for FunctionFinder { impl Visit for FunctionFinder {
noop_visit_type!();
fn visit_function(&mut self, _: &Function, _: &dyn Node) { fn visit_function(&mut self, _: &Function, _: &dyn Node) {
self.found = true self.found = true
} }

View File

@ -15,7 +15,7 @@ use fxhash::FxBuildHasher;
use std::iter; use std::iter;
use swc_common::{Mark, Spanned, DUMMY_SP}; use swc_common::{Mark, Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
#[macro_use] #[macro_use]
mod macros; mod macros;
@ -24,6 +24,10 @@ pub(crate) mod native;
mod prop_name; mod prop_name;
mod super_field; mod super_field;
pub fn classes() -> impl Fold {
Classes::default()
}
type IndexMap<K, V> = indexmap::IndexMap<K, V, FxBuildHasher>; type IndexMap<K, V> = indexmap::IndexMap<K, V, FxBuildHasher>;
/// `@babel/plugin-transform-classes` /// `@babel/plugin-transform-classes`
@ -58,12 +62,10 @@ type IndexMap<K, V> = indexmap::IndexMap<K, V, FxBuildHasher>;
/// }(); /// }();
/// ``` /// ```
#[derive(Default, Clone, Copy)] #[derive(Default, Clone, Copy)]
pub struct Classes { struct Classes {
in_strict: bool, in_strict: bool,
} }
noop_fold_type!(Classes);
struct Data { struct Data {
key_prop: Box<Prop>, key_prop: Box<Prop>,
method: Option<Box<Expr>>, method: Option<Box<Expr>>,
@ -167,6 +169,8 @@ impl Classes {
} }
impl Fold for Classes { impl Fold for Classes {
noop_fold_type!();
fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> { fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> {
self.fold_stmt_like(items) self.fold_stmt_like(items)
} }
@ -181,6 +185,8 @@ impl Fold for Classes {
found: bool, found: bool,
}; };
impl Visit for Visitor { impl Visit for Visitor {
noop_visit_type!();
fn visit_class(&mut self, _: &Class, _: &dyn Node) { fn visit_class(&mut self, _: &Class, _: &dyn Node) {
self.found = true self.found = true
} }
@ -875,6 +881,8 @@ fn is_always_initialized(body: &[Stmt]) -> bool {
} }
impl Visit for SuperFinder { impl Visit for SuperFinder {
noop_visit_type!();
fn visit_expr_or_super(&mut self, node: &ExprOrSuper, _: &dyn Node) { fn visit_expr_or_super(&mut self, node: &ExprOrSuper, _: &dyn Node) {
match *node { match *node {
ExprOrSuper::Super(..) => self.found = true, ExprOrSuper::Super(..) => self.found = true,

View File

@ -5,7 +5,7 @@ use swc_atoms::JsWord;
use swc_common::{Mark, DUMMY_SP}; use swc_common::{Mark, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_utils::quote_ident; use swc_ecma_utils::quote_ident;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
pub(super) struct SuperCallFinder { pub(super) struct SuperCallFinder {
mode: Option<SuperFoldingMode>, mode: Option<SuperFoldingMode>,
@ -13,8 +13,6 @@ pub(super) struct SuperCallFinder {
in_complex: bool, in_complex: bool,
} }
noop_visit_type!(SuperCallFinder);
impl SuperCallFinder { impl SuperCallFinder {
/// ///
/// - `None`: if no `super()` is found or super() is last call /// - `None`: if no `super()` is found or super() is last call
@ -68,6 +66,8 @@ macro_rules! mark_as_complex {
} }
impl Visit for SuperCallFinder { impl Visit for SuperCallFinder {
noop_visit_type!();
mark_as_complex!(visit_arrow_expr, ArrowExpr); mark_as_complex!(visit_arrow_expr, ArrowExpr);
mark_as_complex!(visit_if_stmt, IfStmt); mark_as_complex!(visit_if_stmt, IfStmt);
mark_as_complex!(visit_prop_name, PropName); mark_as_complex!(visit_prop_name, PropName);
@ -176,6 +176,7 @@ pub(super) enum SuperFoldingMode {
} }
impl Fold for ConstructorFolder<'_> { impl Fold for ConstructorFolder<'_> {
noop_fold_type!();
fold_only_key!(); fold_only_key!();
ignore_return!(fold_function, Function); ignore_return!(fold_function, Function);
@ -400,6 +401,8 @@ pub(super) fn replace_this_in_constructor(mark: Mark, c: Constructor) -> (Constr
} }
impl Fold for Replacer { impl Fold for Replacer {
noop_fold_type!();
fn fold_class(&mut self, n: Class) -> Class { fn fold_class(&mut self, n: Class) -> Class {
n n
} }
@ -485,6 +488,8 @@ pub(super) struct VarRenamer<'a> {
} }
impl<'a> Fold for VarRenamer<'a> { impl<'a> Fold for VarRenamer<'a> {
noop_fold_type!();
fn fold_pat(&mut self, pat: Pat) -> Pat { fn fold_pat(&mut self, pat: Pat) -> Pat {
match pat { match pat {
Pat::Ident(ident) => { Pat::Ident(ident) => {

View File

@ -5,7 +5,7 @@ use swc_atoms::js_word;
use swc_common::{Mark, Span, DUMMY_SP}; use swc_common::{Mark, Span, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_utils::quote_ident; use swc_ecma_utils::quote_ident;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
/// Process function body. /// Process function body.
/// ///
@ -40,8 +40,6 @@ pub(crate) struct SuperFieldAccessFolder<'a> {
pub this_alias_mark: Option<Mark>, pub this_alias_mark: Option<Mark>,
} }
noop_fold_type!(SuperFieldAccessFolder<'_>);
struct SuperCalleeFolder<'a> { struct SuperCalleeFolder<'a> {
vars: &'a mut Vec<VarDeclarator>, vars: &'a mut Vec<VarDeclarator>,
class_name: &'a Ident, class_name: &'a Ident,
@ -59,8 +57,6 @@ struct SuperCalleeFolder<'a> {
this_alias_mark: Option<Mark>, this_alias_mark: Option<Mark>,
} }
noop_fold_type!(SuperCalleeFolder<'_>);
macro_rules! mark_nested { macro_rules! mark_nested {
($name:ident, $T:tt) => { ($name:ident, $T:tt) => {
fn $name(&mut self, n: $T) -> $T { fn $name(&mut self, n: $T) -> $T {
@ -79,6 +75,8 @@ macro_rules! mark_nested {
} }
impl<'a> Fold for SuperCalleeFolder<'a> { impl<'a> Fold for SuperCalleeFolder<'a> {
noop_fold_type!();
fold_only_key!(); fold_only_key!();
fn fold_expr(&mut self, n: Expr) -> Expr { fn fold_expr(&mut self, n: Expr) -> Expr {
@ -410,6 +408,8 @@ impl<'a> SuperCalleeFolder<'a> {
} }
impl<'a> Fold for SuperFieldAccessFolder<'a> { impl<'a> Fold for SuperFieldAccessFolder<'a> {
noop_fold_type!();
mark_nested!(fold_function, Function); mark_nested!(fold_function, Function);
mark_nested!(fold_class, Class); mark_nested!(fold_class, Class);

View File

@ -1,7 +1,7 @@
use crate::util::{ExprFactory, StmtLike}; use crate::util::{ExprFactory, StmtLike};
use swc_common::{Mark, Spanned, DUMMY_SP}; use swc_common::{Mark, Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
/// `@babel/plugin-transform-computed-properties` /// `@babel/plugin-transform-computed-properties`
/// ///
@ -40,8 +40,6 @@ pub fn computed_properties() -> impl Fold {
struct ComputedProps; struct ComputedProps;
noop_fold_type!(ComputedProps);
#[derive(Default)] #[derive(Default)]
struct ObjectLitFolder { struct ObjectLitFolder {
vars: Vec<VarDeclarator>, vars: Vec<VarDeclarator>,
@ -49,6 +47,8 @@ struct ObjectLitFolder {
} }
impl Fold for ObjectLitFolder { impl Fold for ObjectLitFolder {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr { fn fold_expr(&mut self, expr: Expr) -> Expr {
let expr = validate!(expr); let expr = validate!(expr);
let expr = expr.fold_children_with(self); let expr = expr.fold_children_with(self);
@ -276,6 +276,8 @@ struct ComplexVisitor {
} }
impl Visit for ComplexVisitor { impl Visit for ComplexVisitor {
noop_visit_type!();
fn visit_prop_name(&mut self, pn: &PropName, _: &dyn Node) { fn visit_prop_name(&mut self, pn: &PropName, _: &dyn Node) {
match *pn { match *pn {
PropName::Computed(..) => self.found = true, PropName::Computed(..) => self.found = true,
@ -285,6 +287,8 @@ impl Visit for ComplexVisitor {
} }
impl Fold for ComputedProps { impl Fold for ComputedProps {
noop_fold_type!();
fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> { fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> {
self.fold_stmt_like(n) self.fold_stmt_like(n)
} }
@ -362,6 +366,8 @@ struct ShouldWork {
} }
impl Visit for ShouldWork { impl Visit for ShouldWork {
noop_visit_type!();
fn visit_prop_name(&mut self, node: &PropName, _: &dyn Node) { fn visit_prop_name(&mut self, node: &PropName, _: &dyn Node) {
match *node { match *node {
PropName::Computed(_) => self.found = true, PropName::Computed(_) => self.found = true,

View File

@ -6,7 +6,7 @@ use serde::Deserialize;
use std::iter; use std::iter;
use swc_common::{Spanned, SyntaxContext, DUMMY_SP}; use swc_common::{Spanned, SyntaxContext, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
/// `@babel/plugin-transform-destructuring` /// `@babel/plugin-transform-destructuring`
/// ///
@ -37,8 +37,6 @@ struct Destructuring {
c: Config, c: Config,
} }
noop_fold_type!(Destructuring);
#[derive(Debug, Default, Clone, Copy, Deserialize)] #[derive(Debug, Default, Clone, Copy, Deserialize)]
pub struct Config { pub struct Config {
#[serde(default)] #[serde(default)]
@ -448,6 +446,8 @@ impl AssignFolder {
} }
impl Fold for Destructuring { impl Fold for Destructuring {
noop_fold_type!();
impl_for_for_stmt!(fold_for_in_stmt, ForInStmt); impl_for_for_stmt!(fold_for_in_stmt, ForInStmt);
impl_for_for_stmt!(fold_for_of_stmt, ForOfStmt); impl_for_for_stmt!(fold_for_of_stmt, ForOfStmt);
@ -519,6 +519,8 @@ struct AssignFolder {
} }
impl Fold for AssignFolder { impl Fold for AssignFolder {
noop_fold_type!();
fn fold_export_decl(&mut self, decl: ExportDecl) -> ExportDecl { fn fold_export_decl(&mut self, decl: ExportDecl) -> ExportDecl {
let old = self.exporting; let old = self.exporting;
self.exporting = true; self.exporting = true;
@ -1101,6 +1103,8 @@ struct DestructuringVisitor {
} }
impl Visit for DestructuringVisitor { impl Visit for DestructuringVisitor {
noop_visit_type!();
fn visit_pat(&mut self, node: &Pat, _: &dyn Node) { fn visit_pat(&mut self, node: &Pat, _: &dyn Node) {
node.visit_children_with(self); node.visit_children_with(self);
match *node { match *node {

View File

@ -2,7 +2,7 @@ use std::collections::HashSet;
use swc_atoms::JsWord; use swc_atoms::JsWord;
use swc_common::Spanned; use swc_common::Spanned;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub fn duplicate_keys() -> impl Fold { pub fn duplicate_keys() -> impl Fold {
DuplicateKeys DuplicateKeys
@ -10,9 +10,9 @@ pub fn duplicate_keys() -> impl Fold {
struct DuplicateKeys; struct DuplicateKeys;
noop_fold_type!(DuplicateKeys);
impl Fold for DuplicateKeys { impl Fold for DuplicateKeys {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr { fn fold_expr(&mut self, expr: Expr) -> Expr {
let expr = expr.fold_children_with(self); let expr = expr.fold_children_with(self);
@ -37,9 +37,9 @@ struct PropFolder {
setter_props: HashSet<JsWord>, setter_props: HashSet<JsWord>,
} }
noop_fold_type!(PropFolder);
impl Fold for PropFolder { impl Fold for PropFolder {
noop_fold_type!();
fn fold_expr(&mut self, node: Expr) -> Expr { fn fold_expr(&mut self, node: Expr) -> Expr {
node node
} }
@ -87,6 +87,8 @@ struct PropNameFolder<'a> {
props: &'a mut HashSet<JsWord>, props: &'a mut HashSet<JsWord>,
} }
impl<'a> Fold for PropNameFolder<'a> { impl<'a> Fold for PropNameFolder<'a> {
noop_fold_type!();
fn fold_expr(&mut self, node: Expr) -> Expr { fn fold_expr(&mut self, node: Expr) -> Expr {
node node
} }

View File

@ -3,7 +3,7 @@ use serde::Deserialize;
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_common::{Mark, Spanned, DUMMY_SP}; use swc_common::{Mark, Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
/// `@babel/plugin-transform-for-of` /// `@babel/plugin-transform-for-of`
/// ///
@ -53,8 +53,6 @@ struct ForOf {
c: Config, c: Config,
} }
noop_fold_type!(ForOf);
/// Real folder. /// Real folder.
struct Actual { struct Actual {
c: Config, c: Config,
@ -395,6 +393,8 @@ impl Actual {
} }
impl Fold for Actual { impl Fold for Actual {
noop_fold_type!();
fn fold_stmt(&mut self, stmt: Stmt) -> Stmt { fn fold_stmt(&mut self, stmt: Stmt) -> Stmt {
match stmt { match stmt {
Stmt::Labeled(LabeledStmt { span, label, body }) => { Stmt::Labeled(LabeledStmt { span, label, body }) => {
@ -498,6 +498,8 @@ fn make_finally_block(
} }
impl Fold for ForOf { impl Fold for ForOf {
noop_fold_type!();
fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> { fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> {
self.fold_stmt_like(n) self.fold_stmt_like(n)
} }
@ -565,6 +567,8 @@ struct ForOfFinder {
} }
impl Visit for ForOfFinder { impl Visit for ForOfFinder {
noop_visit_type!();
fn visit_for_of_stmt(&mut self, _: &ForOfStmt, _: &dyn Node) { fn visit_for_of_stmt(&mut self, _: &ForOfStmt, _: &dyn Node) {
self.found = true; self.found = true;
} }

View File

@ -1,6 +1,6 @@
use crate::{ext::PatOrExprExt, util::UsageFinder}; use crate::{ext::PatOrExprExt, util::UsageFinder};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
/// `@babel/plugin-transform-function-name` /// `@babel/plugin-transform-function-name`
/// ///
@ -26,14 +26,10 @@ pub fn function_name() -> impl Fold {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
struct FnName; struct FnName;
noop_fold_type!(FnName);
struct Renamer { struct Renamer {
name: Option<Ident>, name: Option<Ident>,
} }
noop_fold_type!(Renamer);
/// This function makes a new private identifier if required. /// This function makes a new private identifier if required.
fn prepare(i: Ident, force: bool) -> Ident { fn prepare(i: Ident, force: bool) -> Ident {
if i.is_reserved_for_es3() || i.sym == *"await" || i.sym == *"eval" { if i.is_reserved_for_es3() || i.sym == *"await" || i.sym == *"eval" {
@ -48,6 +44,8 @@ fn prepare(i: Ident, force: bool) -> Ident {
} }
impl Fold for FnName { impl Fold for FnName {
noop_fold_type!();
fn fold_assign_expr(&mut self, expr: AssignExpr) -> AssignExpr { fn fold_assign_expr(&mut self, expr: AssignExpr) -> AssignExpr {
let mut expr = expr.fold_children_with(self); let mut expr = expr.fold_children_with(self);
@ -152,6 +150,8 @@ macro_rules! noop {
} }
impl Fold for Renamer { impl Fold for Renamer {
noop_fold_type!();
impl_for!(fold_fn_expr, FnExpr); impl_for!(fold_fn_expr, FnExpr);
impl_for!(fold_class_expr, ClassExpr); impl_for!(fold_class_expr, ClassExpr);

View File

@ -1,7 +1,7 @@
use crate::util::ExprFactory; use crate::util::ExprFactory;
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
/// `@babel/plugin-transform-instanceof` /// `@babel/plugin-transform-instanceof`
/// ///
@ -28,18 +28,22 @@ use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith};
/// ///
/// _instanceof(foo, Bar); /// _instanceof(foo, Bar);
/// ``` /// ```
#[derive(Clone)] pub fn instance_of() -> impl Fold {
pub struct InstanceOf; InstanceOf
}
noop_fold_type!(InstanceOf); struct InstanceOf;
impl Fold for InstanceOf { impl Fold for InstanceOf {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr { fn fold_expr(&mut self, expr: Expr) -> Expr {
fn should_work(node: &Expr) -> bool { fn should_work(node: &Expr) -> bool {
struct Visitor { struct Visitor {
found: bool, found: bool,
} }
impl Visit for Visitor { impl Visit for Visitor {
noop_visit_type!();
fn visit_bin_expr(&mut self, e: &BinExpr, _: &dyn Node) { fn visit_bin_expr(&mut self, e: &BinExpr, _: &dyn Node) {
if e.op == op!("instanceof") { if e.op == op!("instanceof") {
self.found = true self.found = true

View File

@ -2,18 +2,16 @@ use crate::util::{prepend_stmts, ExprFactory};
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use swc_common::{Mark, Spanned, DUMMY_SP}; use swc_common::{Mark, Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub fn parameters() -> Params { pub fn parameters() -> impl 'static + Fold {
Params Params
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Params; struct Params;
// prevent_recurse!(Params, Pat); // prevent_recurse!(Params, Pat);
noop_fold_type!(Params);
impl Params { impl Params {
fn fold_fn_like(&mut self, ps: Vec<Param>, body: BlockStmt) -> (Vec<Param>, BlockStmt) { fn fold_fn_like(&mut self, ps: Vec<Param>, body: BlockStmt) -> (Vec<Param>, BlockStmt) {
let body = validate!(body); let body = validate!(body);
@ -249,5 +247,7 @@ impl Params {
} }
impl Fold for Params { impl Fold for Params {
noop_fold_type!();
impl_fold_fn!(); impl_fold_fn!();
} }

View File

@ -11,7 +11,7 @@ use swc_common::{
BytePos, Span, Spanned, SyntaxContext, DUMMY_SP, BytePos, Span, Spanned, SyntaxContext, DUMMY_SP,
}; };
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(super) struct Loc { pub(super) struct Loc {
@ -1416,6 +1416,8 @@ macro_rules! leap {
} }
impl Visit for LeapFinder { impl Visit for LeapFinder {
noop_visit_type!();
leap!(visit_yield_expr, YieldExpr); leap!(visit_yield_expr, YieldExpr);
leap!(visit_break_stmt, BreakStmt); leap!(visit_break_stmt, BreakStmt);
leap!(visit_continue_stmt, ContinueStmt); leap!(visit_continue_stmt, ContinueStmt);
@ -1438,6 +1440,8 @@ struct UnmarkedInvalidHandler {
} }
impl Fold for UnmarkedInvalidHandler { impl Fold for UnmarkedInvalidHandler {
noop_fold_type!();
fn fold_expr(&mut self, e: Expr) -> Expr { fn fold_expr(&mut self, e: Expr) -> Expr {
let e = e.fold_children_with(self); let e = e.fold_children_with(self);
@ -1457,6 +1461,8 @@ struct InvalidToLit<'a> {
map: &'a [Loc], map: &'a [Loc],
} }
impl Fold for InvalidToLit<'_> { impl Fold for InvalidToLit<'_> {
noop_fold_type!();
fn fold_expr(&mut self, e: Expr) -> Expr { fn fold_expr(&mut self, e: Expr) -> Expr {
let e = e.fold_children_with(self); let e = e.fold_children_with(self);
@ -1486,9 +1492,9 @@ struct CatchParamHandler<'a> {
param: Option<&'a Pat>, param: Option<&'a Pat>,
} }
noop_fold_type!(CatchParamHandler<'_>);
impl Fold for CatchParamHandler<'_> { impl Fold for CatchParamHandler<'_> {
noop_fold_type!();
fn fold_expr(&mut self, node: Expr) -> Expr { fn fold_expr(&mut self, node: Expr) -> Expr {
match self.param { match self.param {
None => return node, None => return node,

View File

@ -3,7 +3,7 @@ use smallvec::SmallVec;
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub(super) type Vars = SmallVec<[Ident; 32]>; pub(super) type Vars = SmallVec<[Ident; 32]>;
@ -26,8 +26,6 @@ pub(super) struct Hoister {
pub arguments: Option<Ident>, pub arguments: Option<Ident>,
} }
noop_fold_type!(Hoister);
impl Hoister { impl Hoister {
fn var_decl_to_expr(&mut self, var: VarDecl) -> Expr { fn var_decl_to_expr(&mut self, var: VarDecl) -> Expr {
let var = var.fold_children_with(self); let var = var.fold_children_with(self);
@ -59,6 +57,8 @@ impl Hoister {
} }
impl Fold for Hoister { impl Fold for Hoister {
noop_fold_type!();
fn fold_expr(&mut self, e: Expr) -> Expr { fn fold_expr(&mut self, e: Expr) -> Expr {
let e = e.fold_children_with(self); let e = e.fold_children_with(self);

View File

@ -4,7 +4,7 @@ use std::mem::replace;
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_common::{Mark, Spanned, DUMMY_SP}; use swc_common::{Mark, Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
mod case; mod case;
mod hoist; mod hoist;
@ -30,8 +30,6 @@ struct Regenerator {
top_level_vars: Vec<VarDeclarator>, top_level_vars: Vec<VarDeclarator>,
} }
noop_fold_type!(Regenerator);
fn rt(global_mark: Mark, rt: Ident) -> Stmt { fn rt(global_mark: Mark, rt: Ident) -> Stmt {
Stmt::Decl(Decl::Var(VarDecl { Stmt::Decl(Decl::Var(VarDecl {
span: DUMMY_SP, span: DUMMY_SP,
@ -86,6 +84,8 @@ impl Regenerator {
} }
impl Fold for Regenerator { impl Fold for Regenerator {
noop_fold_type!();
fn fold_expr(&mut self, e: Expr) -> Expr { fn fold_expr(&mut self, e: Expr) -> Expr {
if !Finder::find(&e) { if !Finder::find(&e) {
return e; return e;
@ -485,6 +485,8 @@ struct FnSentVisitor {
} }
impl Fold for FnSentVisitor { impl Fold for FnSentVisitor {
noop_fold_type!();
fn fold_expr(&mut self, e: Expr) -> Expr { fn fold_expr(&mut self, e: Expr) -> Expr {
let e: Expr = e.fold_children_with(self); let e: Expr = e.fold_children_with(self);
@ -516,6 +518,8 @@ impl Finder {
} }
impl Visit for Finder { impl Visit for Finder {
noop_visit_type!();
fn visit_function(&mut self, node: &Function, _: &dyn Node) { fn visit_function(&mut self, node: &Function, _: &dyn Node) {
if node.is_generator { if node.is_generator {
self.found = true; self.found = true;

View File

@ -1,5 +1,5 @@
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
/// Compile ES2015 shorthand properties to ES5 /// Compile ES2015 shorthand properties to ES5
/// ///
@ -35,12 +35,16 @@ use swc_ecma_visit::{Fold, FoldWith};
/// } /// }
/// }; /// };
/// ``` /// ```
#[derive(Default, Clone, Copy)] pub fn shorthand() -> impl 'static + Fold {
pub struct Shorthand; Shorthand
}
noop_fold_type!(Shorthand); #[derive(Clone, Copy)]
struct Shorthand;
impl Fold for Shorthand { impl Fold for Shorthand {
noop_fold_type!();
fn fold_prop(&mut self, prop: Prop) -> Prop { fn fold_prop(&mut self, prop: Prop) -> Prop {
let prop = prop.fold_children_with(self); let prop = prop.fold_children_with(self);

View File

@ -7,7 +7,7 @@ use std::mem;
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_common::{util::move_map::MoveMap, Span, Spanned, DUMMY_SP}; use swc_common::{util::move_map::MoveMap, Span, Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub fn spread(c: Config) -> impl Fold { pub fn spread(c: Config) -> impl Fold {
Spread { c } Spread { c }
@ -25,17 +25,15 @@ struct Spread {
c: Config, c: Config,
} }
noop_fold_type!(Spread);
#[derive(Default)] #[derive(Default)]
struct ActualFolder { struct ActualFolder {
c: Config, c: Config,
vars: Vec<VarDeclarator>, vars: Vec<VarDeclarator>,
} }
noop_fold_type!(ActualFolder);
impl Fold for Spread { impl Fold for Spread {
noop_fold_type!();
fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> { fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> {
self.fold_stmt_like(n) self.fold_stmt_like(n)
} }
@ -72,6 +70,8 @@ impl Spread {
} }
impl Fold for ActualFolder { impl Fold for ActualFolder {
noop_fold_type!();
fn fold_expr(&mut self, e: Expr) -> Expr { fn fold_expr(&mut self, e: Expr) -> Expr {
let e = validate!(e.fold_children_with(self)); let e = validate!(e.fold_children_with(self));

View File

@ -2,7 +2,7 @@ use crate::util::ExprFactory;
use swc_atoms::JsWord; use swc_atoms::JsWord;
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
/// Compile ES2015 sticky regex to an ES5 RegExp constructor /// Compile ES2015 sticky regex to an ES5 RegExp constructor
/// ///
@ -18,12 +18,16 @@ use swc_ecma_visit::{Fold, FoldWith};
/// ```js /// ```js
/// new RegExp("o+", "y") /// new RegExp("o+", "y")
/// ``` /// ```
#[derive(Clone, Copy)] pub fn sticky_regex() -> impl 'static + Fold {
pub struct StickyRegex; StickyRegex
}
noop_fold_type!(StickyRegex); #[derive(Clone, Copy)]
struct StickyRegex;
impl Fold for StickyRegex { impl Fold for StickyRegex {
noop_fold_type!();
fn fold_expr(&mut self, e: Expr) -> Expr { fn fold_expr(&mut self, e: Expr) -> Expr {
let e = e.fold_children_with(self); let e = e.fold_children_with(self);

View File

@ -3,16 +3,20 @@ use std::{iter, mem};
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_common::{BytePos, Spanned, DUMMY_SP}; use swc_common::{BytePos, Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
#[derive(Default, Clone)] pub fn template_literal() -> impl Fold {
pub struct TemplateLiteral { TemplateLiteral::default()
}
#[derive(Default)]
struct TemplateLiteral {
added: Vec<Stmt>, added: Vec<Stmt>,
} }
noop_fold_type!(TemplateLiteral);
impl Fold for TemplateLiteral { impl Fold for TemplateLiteral {
noop_fold_type!();
fn fold_expr(&mut self, e: Expr) -> Expr { fn fold_expr(&mut self, e: Expr) -> Expr {
let e = validate!(e); let e = validate!(e);

View File

@ -2,31 +2,18 @@ use crate::util::ExprFactory;
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
pub fn typeof_symbol() -> impl Fold {
TypeOfSymbol
}
/// `@babel/plugin-transform-typeof-symbol`
///
/// # Example
/// ## In
///
/// ```js
/// typeof Symbol() === "symbol";
/// ```
///
/// ## Out
/// ```js
/// var _typeof = function (obj) {
/// return obj && obj.constructor === Symbol ? "symbol" : typeof obj;
/// };
///
/// _typeof(Symbol()) === "symbol";
/// ```
#[derive(Clone)] #[derive(Clone)]
pub struct TypeOfSymbol; struct TypeOfSymbol;
noop_fold_type!(TypeOfSymbol);
impl Fold for TypeOfSymbol { impl Fold for TypeOfSymbol {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr { fn fold_expr(&mut self, expr: Expr) -> Expr {
// fast path // fast path
if !should_work(&expr) { if !should_work(&expr) {
@ -87,6 +74,8 @@ fn should_work(node: &Expr) -> bool {
found: bool, found: bool,
} }
impl Visit for Visitor { impl Visit for Visitor {
noop_visit_type!();
fn visit_unary_expr(&mut self, e: &UnaryExpr, _: &dyn Node) { fn visit_unary_expr(&mut self, e: &UnaryExpr, _: &dyn Node) {
if e.op == op!("typeof") { if e.op == op!("typeof") {
self.found = true self.found = true

View File

@ -4,7 +4,7 @@ use crate::{
}; };
use swc_common::{Span, Spanned, DUMMY_SP}; use swc_common::{Span, Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
/// `@babel/plugin-transform-exponentiation-operator` /// `@babel/plugin-transform-exponentiation-operator`
/// ///
@ -28,19 +28,18 @@ use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith};
pub fn exponentation() -> impl Fold { pub fn exponentation() -> impl Fold {
Exponentation Exponentation
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
struct Exponentation; struct Exponentation;
noop_fold_type!(Exponentation);
#[derive(Default)] #[derive(Default)]
struct AssignFolder { struct AssignFolder {
vars: Vec<VarDeclarator>, vars: Vec<VarDeclarator>,
} }
noop_fold_type!(AssignFolder);
impl Fold for AssignFolder { impl Fold for AssignFolder {
noop_fold_type!();
fn fold_expr(&mut self, e: Expr) -> Expr { fn fold_expr(&mut self, e: Expr) -> Expr {
let e = e.fold_children_with(self); let e = e.fold_children_with(self);
@ -95,6 +94,8 @@ impl Fold for AssignFolder {
} }
impl Fold for Exponentation { impl Fold for Exponentation {
noop_fold_type!();
fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> { fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> {
self.fold_stmt_like(n) self.fold_stmt_like(n)
} }
@ -167,6 +168,8 @@ struct ShouldFold {
found: bool, found: bool,
} }
impl Visit for ShouldFold { impl Visit for ShouldFold {
noop_visit_type!();
fn visit_bin_expr(&mut self, e: &BinExpr, _: &dyn Node) { fn visit_bin_expr(&mut self, e: &BinExpr, _: &dyn Node) {
if e.op == op!("**") { if e.op == op!("**") {
self.found = true; self.found = true;

View File

@ -5,7 +5,7 @@ use crate::{
use std::iter; use std::iter;
use swc_common::{Mark, Span, Spanned, DUMMY_SP}; use swc_common::{Mark, Span, Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
/// `@babel/plugin-transform-async-to-generator` /// `@babel/plugin-transform-async-to-generator`
/// ///
@ -34,15 +34,13 @@ pub fn async_to_generator() -> impl Fold {
#[derive(Default, Clone)] #[derive(Default, Clone)]
struct AsyncToGenerator; struct AsyncToGenerator;
noop_fold_type!(AsyncToGenerator);
struct Actual { struct Actual {
extra_stmts: Vec<Stmt>, extra_stmts: Vec<Stmt>,
} }
noop_fold_type!(Actual);
impl Fold for AsyncToGenerator { impl Fold for AsyncToGenerator {
noop_fold_type!();
fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> { fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> {
self.fold_stmt_like(n) self.fold_stmt_like(n)
} }
@ -86,6 +84,8 @@ impl AsyncToGenerator {
} }
impl Fold for Actual { impl Fold for Actual {
noop_fold_type!();
fn fold_class_method(&mut self, m: ClassMethod) -> ClassMethod { fn fold_class_method(&mut self, m: ClassMethod) -> ClassMethod {
if m.function.body.is_none() { if m.function.body.is_none() {
return m; return m;
@ -401,6 +401,8 @@ impl MethodFolder {
} }
impl Fold for MethodFolder { impl Fold for MethodFolder {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr { fn fold_expr(&mut self, expr: Expr) -> Expr {
let expr = validate!(expr); let expr = validate!(expr);
// TODO(kdy): Cache (Reuse declaration for same property) // TODO(kdy): Cache (Reuse declaration for same property)
@ -758,6 +760,8 @@ fn make_fn_ref(mut expr: FnExpr) -> Expr {
} }
impl Fold for AwaitToYield { impl Fold for AwaitToYield {
noop_fold_type!();
noop!(fold_fn_decl, FnDecl); noop!(fold_fn_decl, FnDecl);
noop!(fold_fn_expr, FnExpr); noop!(fold_fn_expr, FnExpr);
noop!(fold_constructor, Constructor); noop!(fold_constructor, Constructor);
@ -819,6 +823,8 @@ struct AsyncVisitor {
} }
impl Visit for AsyncVisitor { impl Visit for AsyncVisitor {
noop_visit_type!();
fn visit_function(&mut self, f: &Function, _: &dyn Node) { fn visit_function(&mut self, f: &Function, _: &dyn Node) {
if f.is_async { if f.is_async {
self.found = true; self.found = true;

View File

@ -4,7 +4,7 @@ use crate::util::{
use std::{iter, mem}; use std::{iter, mem};
use swc_common::{chain, util::move_map::MoveMap, Mark, Spanned, DUMMY_SP}; use swc_common::{chain, util::move_map::MoveMap, Mark, Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
/// `@babel/plugin-proposal-object-rest-spread` /// `@babel/plugin-proposal-object-rest-spread`
pub fn object_rest_spread() -> impl Fold { pub fn object_rest_spread() -> impl Fold {
@ -13,8 +13,6 @@ pub fn object_rest_spread() -> impl Fold {
struct ObjectRest; struct ObjectRest;
noop_fold_type!(ObjectRest);
#[allow(clippy::vec_box)] #[allow(clippy::vec_box)]
struct RestFolder { struct RestFolder {
/// Injected before the original statement. /// Injected before the original statement.
@ -25,8 +23,6 @@ struct RestFolder {
exprs: Vec<Box<Expr>>, exprs: Vec<Box<Expr>>,
} }
noop_fold_type!(RestFolder);
macro_rules! impl_for_for_stmt { macro_rules! impl_for_for_stmt {
($name:ident, $T:tt) => { ($name:ident, $T:tt) => {
fn $name(&mut self, mut for_stmt: $T) -> $T { fn $name(&mut self, mut for_stmt: $T) -> $T {
@ -143,6 +139,8 @@ macro_rules! impl_for_for_stmt {
} }
impl Fold for RestFolder { impl Fold for RestFolder {
noop_fold_type!();
impl_for_for_stmt!(fold_for_in_stmt, ForInStmt); impl_for_for_stmt!(fold_for_in_stmt, ForInStmt);
impl_for_for_stmt!(fold_for_of_stmt, ForOfStmt); impl_for_for_stmt!(fold_for_of_stmt, ForOfStmt);
impl_fold_fn!(); impl_fold_fn!();
@ -381,6 +379,8 @@ struct RestVisitor {
} }
impl Visit for RestVisitor { impl Visit for RestVisitor {
noop_visit_type!();
fn visit_object_pat_prop(&mut self, prop: &ObjectPatProp, _: &dyn Node) { fn visit_object_pat_prop(&mut self, prop: &ObjectPatProp, _: &dyn Node) {
match *prop { match *prop {
ObjectPatProp::Rest(..) => self.found = true, ObjectPatProp::Rest(..) => self.found = true,
@ -399,6 +399,7 @@ where
} }
impl Fold for ObjectRest { impl Fold for ObjectRest {
noop_fold_type!();
fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> { fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> {
self.fold_stmt_like(n) self.fold_stmt_like(n)
} }
@ -1016,6 +1017,8 @@ fn excluded_props(props: &[ObjectPatProp]) -> Vec<Option<ExprOrSpread>> {
fn simplify_pat(pat: Pat) -> Pat { fn simplify_pat(pat: Pat) -> Pat {
struct PatSimplifier; struct PatSimplifier;
impl Fold for PatSimplifier { impl Fold for PatSimplifier {
noop_fold_type!();
fn fold_pat(&mut self, pat: Pat) -> Pat { fn fold_pat(&mut self, pat: Pat) -> Pat {
let pat = pat.fold_children_with(self); let pat = pat.fold_children_with(self);
@ -1055,9 +1058,9 @@ fn simplify_pat(pat: Pat) -> Pat {
struct ObjectSpread; struct ObjectSpread;
noop_fold_type!(ObjectSpread);
impl Fold for ObjectSpread { impl Fold for ObjectSpread {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr { fn fold_expr(&mut self, expr: Expr) -> Expr {
// fast-path // fast-path
if !contains_spread(&expr) { if !contains_spread(&expr) {
@ -1132,6 +1135,8 @@ fn contains_spread(expr: &Expr) -> bool {
} }
impl Visit for Visitor { impl Visit for Visitor {
noop_visit_type!();
fn visit_spread_element(&mut self, _: &SpreadElement, _: &dyn Node) { fn visit_spread_element(&mut self, _: &SpreadElement, _: &dyn Node) {
self.found = true; self.found = true;
} }

View File

@ -1,15 +1,15 @@
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
struct OptionalCatchBinding; struct OptionalCatchBinding;
noop_fold_type!(OptionalCatchBinding);
pub fn optional_catch_binding() -> impl Fold { pub fn optional_catch_binding() -> impl Fold {
OptionalCatchBinding OptionalCatchBinding
} }
impl Fold for OptionalCatchBinding { impl Fold for OptionalCatchBinding {
noop_fold_type!();
fn fold_catch_clause(&mut self, mut cc: CatchClause) -> CatchClause { fn fold_catch_clause(&mut self, mut cc: CatchClause) -> CatchClause {
cc = cc.fold_children_with(self); cc = cc.fold_children_with(self);

View File

@ -15,7 +15,7 @@ use std::{collections::HashSet, mem::take};
use swc_atoms::JsWord; use swc_atoms::JsWord;
use swc_common::{util::move_map::MoveMap, Mark, Spanned, DUMMY_SP}; use swc_common::{util::move_map::MoveMap, Mark, Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, VisitWith};
mod class_name_tdz; mod class_name_tdz;
mod private_field; mod private_field;
@ -51,6 +51,8 @@ struct ClassProperties {
} }
impl Fold for ClassProperties { impl Fold for ClassProperties {
noop_fold_type!();
fn fold_ident(&mut self, i: Ident) -> Ident { fn fold_ident(&mut self, i: Ident) -> Ident {
Ident { Ident {
optional: false, optional: false,

View File

@ -1,15 +1,15 @@
use crate::util::ExprFactory; use crate::util::ExprFactory;
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub(super) struct ClassNameTdzFolder<'a> { pub(super) struct ClassNameTdzFolder<'a> {
pub class_name: &'a Ident, pub class_name: &'a Ident,
} }
noop_fold_type!(ClassNameTdzFolder<'_>);
impl<'a> Fold for ClassNameTdzFolder<'a> { impl<'a> Fold for ClassNameTdzFolder<'a> {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr { fn fold_expr(&mut self, expr: Expr) -> Expr {
match expr { match expr {
Expr::Ident(i) => { Expr::Ident(i) => {

View File

@ -6,7 +6,7 @@ use std::{collections::HashSet, iter, mem};
use swc_atoms::JsWord; use swc_atoms::JsWord;
use swc_common::{Mark, Spanned, DUMMY_SP}; use swc_common::{Mark, Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub(super) struct FieldAccessFolder<'a> { pub(super) struct FieldAccessFolder<'a> {
pub mark: Mark, pub mark: Mark,
@ -16,8 +16,6 @@ pub(super) struct FieldAccessFolder<'a> {
pub in_assign_pat: bool, pub in_assign_pat: bool,
} }
noop_fold_type!(FieldAccessFolder<'_>);
macro_rules! take_vars { macro_rules! take_vars {
($name:ident, $T:tt) => { ($name:ident, $T:tt) => {
fn $name(&mut self, f: $T) -> $T { fn $name(&mut self, f: $T) -> $T {
@ -47,6 +45,8 @@ macro_rules! take_vars {
} }
impl<'a> Fold for FieldAccessFolder<'a> { impl<'a> Fold for FieldAccessFolder<'a> {
noop_fold_type!();
take_vars!(fold_function, Function); take_vars!(fold_function, Function);
take_vars!(fold_constructor, Constructor); take_vars!(fold_constructor, Constructor);

View File

@ -1,13 +1,13 @@
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub(super) struct ThisInStaticFolder { pub(super) struct ThisInStaticFolder {
pub ident: Ident, pub ident: Ident,
} }
noop_fold_type!(ThisInStaticFolder);
impl Fold for ThisInStaticFolder { impl Fold for ThisInStaticFolder {
noop_fold_type!();
fn fold_class(&mut self, n: Class) -> Class { fn fold_class(&mut self, n: Class) -> Class {
n n
} }

View File

@ -1,7 +1,7 @@
use swc_atoms::JsWord; use swc_atoms::JsWord;
use swc_common::Mark; use swc_common::Mark;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
/// Used to rename **binding** identifiers in constructor. /// Used to rename **binding** identifiers in constructor.
pub(super) struct UsedNameRenamer<'a> { pub(super) struct UsedNameRenamer<'a> {
@ -9,9 +9,9 @@ pub(super) struct UsedNameRenamer<'a> {
pub used_names: &'a [JsWord], pub used_names: &'a [JsWord],
} }
noop_fold_type!(UsedNameRenamer<'_>);
impl<'a> Fold for UsedNameRenamer<'a> { impl<'a> Fold for UsedNameRenamer<'a> {
noop_fold_type!();
fn fold_expr(&mut self, e: Expr) -> Expr { fn fold_expr(&mut self, e: Expr) -> Expr {
match e { match e {
Expr::Ident(..) => e, Expr::Ident(..) => e,
@ -49,8 +49,6 @@ pub(super) struct UsedNameCollector<'a> {
pub used_names: &'a mut Vec<JsWord>, pub used_names: &'a mut Vec<JsWord>,
} }
noop_visit_type!(UsedNameCollector<'_>);
macro_rules! noop { macro_rules! noop {
($name:ident, $T:path) => { ($name:ident, $T:path) => {
/// no-op /// no-op
@ -59,6 +57,8 @@ macro_rules! noop {
} }
impl<'a> Visit for UsedNameCollector<'a> { impl<'a> Visit for UsedNameCollector<'a> {
noop_visit_type!();
noop!(visit_arrow_expr, ArrowExpr); noop!(visit_arrow_expr, ArrowExpr);
noop!(visit_function, Function); noop!(visit_function, Function);
noop!(visit_setter_prop, SetterProp); noop!(visit_setter_prop, SetterProp);

View File

@ -2,7 +2,7 @@ use crate::util::{alias_if_required, undefined, StmtLike};
use std::mem::replace; use std::mem::replace;
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -43,6 +43,8 @@ impl NullishCoalescing {
} }
impl Fold for NullishCoalescing { impl Fold for NullishCoalescing {
noop_fold_type!();
fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> { fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> {
self.fold_stmt_like(n) self.fold_stmt_like(n)
} }

View File

@ -2,7 +2,7 @@ use crate::util::{prepend, undefined, ExprFactory, StmtLike};
use std::{fmt::Debug, iter::once, mem}; use std::{fmt::Debug, iter::once, mem};
use swc_common::{Spanned, DUMMY_SP}; use swc_common::{Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub fn optional_chaining() -> impl Fold { pub fn optional_chaining() -> impl Fold {
OptChaining::default() OptChaining::default()
@ -13,9 +13,9 @@ struct OptChaining {
vars: Vec<VarDeclarator>, vars: Vec<VarDeclarator>,
} }
noop_fold_type!(OptChaining);
impl Fold for OptChaining { impl Fold for OptChaining {
noop_fold_type!();
fn fold_expr(&mut self, e: Expr) -> Expr { fn fold_expr(&mut self, e: Expr) -> Expr {
let e = match e { let e = match e {
Expr::OptChain(e) => Expr::Cond(validate!(self.unwrap(e))), Expr::OptChain(e) => Expr::Cond(validate!(self.unwrap(e))),

View File

@ -1,5 +1,6 @@
pub use self::{ pub use self::{
member_expr_lits::MemberExprLit, prop_lits::PropertyLiteral, reserved_word::ReservedWord, member_expr_lits::member_expression_literals, prop_lits::property_literals,
reserved_word::reserved_words,
}; };
use swc_common::chain; use swc_common::chain;
use swc_ecma_visit::Fold; use swc_ecma_visit::Fold;
@ -11,8 +12,8 @@ mod reserved_word;
/// Make output es3-compatible. /// Make output es3-compatible.
pub fn es3(preserve_import: bool) -> impl Fold { pub fn es3(preserve_import: bool) -> impl Fold {
chain!( chain!(
PropertyLiteral, property_literals(),
MemberExprLit, member_expression_literals(),
ReservedWord { preserve_import } reserved_words(preserve_import)
) )
} }

View File

@ -1,6 +1,6 @@
use crate::util::is_valid_ident; use crate::util::is_valid_ident;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
/// babel: `transform-member-expression-literals` /// babel: `transform-member-expression-literals`
/// ///
@ -19,12 +19,15 @@ use swc_ecma_visit::{Fold, FoldWith};
/// obj["const"] = "isKeyword"; /// obj["const"] = "isKeyword";
/// obj["var"] = "isKeyword"; /// obj["var"] = "isKeyword";
/// ``` /// ```
pub fn member_expression_literals() -> impl Fold {
MemberExprLit
}
#[derive(Default, Clone, Copy)] #[derive(Default, Clone, Copy)]
pub struct MemberExprLit; struct MemberExprLit;
noop_fold_type!(MemberExprLit);
impl Fold for MemberExprLit { impl Fold for MemberExprLit {
noop_fold_type!();
fn fold_member_expr(&mut self, e: MemberExpr) -> MemberExpr { fn fold_member_expr(&mut self, e: MemberExpr) -> MemberExpr {
let mut e = validate!(e.fold_children_with(self)); let mut e = validate!(e.fold_children_with(self));

View File

@ -1,6 +1,6 @@
use crate::util::is_valid_ident; use crate::util::is_valid_ident;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
/// babel: `transform-property-literals` /// babel: `transform-property-literals`
/// ///
@ -29,12 +29,15 @@ use swc_ecma_visit::{Fold, FoldWith};
/// foo: 1 /// foo: 1
/// }; /// };
/// ``` /// ```
#[derive(Default, Clone, Copy)] pub fn property_literals() -> impl Fold {
pub struct PropertyLiteral; PropertyLiteral
}
noop_fold_type!(PropertyLiteral); struct PropertyLiteral;
impl Fold for PropertyLiteral { impl Fold for PropertyLiteral {
noop_fold_type!();
fn fold_prop_name(&mut self, n: PropName) -> PropName { fn fold_prop_name(&mut self, n: PropName) -> PropName {
let n = validate!(n.fold_children_with(self)); let n = validate!(n.fold_children_with(self));

View File

@ -1,5 +1,5 @@
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
/// babel: `@babel/plugin-transform-reserved-words` /// babel: `@babel/plugin-transform-reserved-words`
/// ///
@ -18,14 +18,16 @@ use swc_ecma_visit::{Fold, FoldWith};
/// var _abstract = 1; /// var _abstract = 1;
/// var x = _abstract + 1; /// var x = _abstract + 1;
/// ``` /// ```
#[derive(Default, Clone, Copy)] pub fn reserved_words(preserve_import: bool) -> impl Fold {
pub struct ReservedWord { ReservedWord { preserve_import }
}
struct ReservedWord {
pub preserve_import: bool, pub preserve_import: bool,
} }
noop_fold_type!(ReservedWord);
impl Fold for ReservedWord { impl Fold for ReservedWord {
noop_fold_type!();
fn fold_export_specifier(&mut self, n: ExportSpecifier) -> ExportSpecifier { fn fold_export_specifier(&mut self, n: ExportSpecifier) -> ExportSpecifier {
n n
} }

View File

@ -1,6 +1,6 @@
use swc_atoms::JsWord; use swc_atoms::JsWord;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub fn reserved_words() -> impl 'static + Fold { pub fn reserved_words() -> impl 'static + Fold {
EsReservedWord {} EsReservedWord {}
@ -8,9 +8,9 @@ pub fn reserved_words() -> impl 'static + Fold {
struct EsReservedWord {} struct EsReservedWord {}
noop_fold_type!(EsReservedWord);
impl Fold for EsReservedWord { impl Fold for EsReservedWord {
noop_fold_type!();
fn fold_export_specifier(&mut self, n: ExportSpecifier) -> ExportSpecifier { fn fold_export_specifier(&mut self, n: ExportSpecifier) -> ExportSpecifier {
n n
} }

View File

@ -9,7 +9,7 @@ use swc_common::{sync::Lrc, util::move_map::MoveMap, FileName, SourceMap};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_parser::{lexer::Lexer, Parser, StringInput}; use swc_ecma_parser::{lexer::Lexer, Parser, StringInput};
use swc_ecma_utils::HANDLER; use swc_ecma_utils::HANDLER;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub fn const_modules( pub fn const_modules(
cm: Lrc<SourceMap>, cm: Lrc<SourceMap>,
@ -76,14 +76,14 @@ struct ConstModules {
scope: Scope, scope: Scope,
} }
noop_fold_type!(ConstModules);
#[derive(Default)] #[derive(Default)]
struct Scope { struct Scope {
imported: HashMap<JsWord, Arc<Expr>>, imported: HashMap<JsWord, Arc<Expr>>,
} }
impl Fold for ConstModules { impl Fold for ConstModules {
noop_fold_type!();
fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> { fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> {
items.move_flat_map(|item| match item { items.move_flat_map(|item| match item {
ModuleItem::ModuleDecl(ModuleDecl::Import(import)) => { ModuleItem::ModuleDecl(ModuleDecl::Import(import)) => {

View File

@ -9,7 +9,7 @@ use swc_common::{
Span, Spanned, Span, Spanned,
}; };
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub fn fixer<'a>(comments: Option<&'a dyn Comments>) -> impl 'a + Fold { pub fn fixer<'a>(comments: Option<&'a dyn Comments>) -> impl 'a + Fold {
Fixer { Fixer {
@ -29,8 +29,6 @@ struct Fixer<'a> {
span_map: FxHashMap<Span, Span>, span_map: FxHashMap<Span, Span>,
} }
noop_fold_type!(Fixer);
#[repr(u8)] #[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Context { enum Context {
@ -70,6 +68,8 @@ macro_rules! array {
} }
impl Fold for Fixer<'_> { impl Fold for Fixer<'_> {
noop_fold_type!();
array!(fold_array_lit, ArrayLit); array!(fold_array_lit, ArrayLit);
// array!(ArrayPat); // array!(ArrayPat);

View File

@ -1,11 +1,11 @@
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use scoped_tls::scoped_thread_local; use scoped_tls::scoped_thread_local;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use swc_common::{FileName, FilePathMapping, Mark, SourceMap, Span, DUMMY_SP}; use swc_common::{FileName, FilePathMapping, Mark, SourceMap, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_parser::{lexer::Lexer, Parser, StringInput}; use swc_ecma_parser::{lexer::Lexer, Parser, StringInput};
use swc_ecma_utils::{prepend_stmts, quote_ident, quote_str, DropSpan}; use swc_ecma_utils::{prepend_stmts, quote_ident, quote_str, DropSpan};
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
#[macro_export] #[macro_export]
macro_rules! enable_helper { macro_rules! enable_helper {
@ -31,10 +31,11 @@ macro_rules! add_to {
); );
let stmts = Parser::new_from(lexer) let stmts = Parser::new_from(lexer)
.parse_script() .parse_script()
.map(|script| { .map(|mut script| {
script.body.fold_with(&mut DropSpan { script.body.visit_mut_with(&mut DropSpan {
preserve_ctxt: false, preserve_ctxt: false,
}) });
script.body
}) })
.map_err(|e| { .map_err(|e| {
unreachable!("Error occurred while parsing error: {:?}", e); unreachable!("Error occurred while parsing error: {:?}", e);
@ -49,7 +50,10 @@ macro_rules! add_to {
STMTS STMTS
.iter() .iter()
.cloned() .cloned()
.map(|stmt| stmt.fold_with(&mut Marker($mark))) .map(|mut stmt| {
stmt.visit_mut_with(&mut Marker($mark));
stmt
})
.map(ModuleItem::Stmt), .map(ModuleItem::Stmt),
) )
} }
@ -223,10 +227,11 @@ define_helpers!(Helpers {
class_private_field_destructure: (), class_private_field_destructure: (),
}); });
#[derive(Clone)] pub fn inject_helpers() -> impl Fold {
pub struct InjectHelpers; as_folder(InjectHelpers)
}
noop_fold_type!(InjectHelpers); struct InjectHelpers;
impl InjectHelpers { impl InjectHelpers {
fn mk_helpers(&self) -> Vec<ModuleItem> { fn mk_helpers(&self) -> Vec<ModuleItem> {
@ -251,23 +256,23 @@ impl InjectHelpers {
} }
} }
impl Fold for InjectHelpers { impl VisitMut for InjectHelpers {
fn fold_module(&mut self, module: Module) -> Module { noop_visit_mut_type!();
let mut module = validate!(module);
fn visit_mut_module(&mut self, module: &mut Module) {
let helpers = self.mk_helpers(); let helpers = self.mk_helpers();
prepend_stmts(&mut module.body, helpers.into_iter()); prepend_stmts(&mut module.body, helpers.into_iter());
module
} }
} }
struct Marker(Mark); struct Marker(Mark);
noop_fold_type!(Marker); impl VisitMut for Marker {
noop_visit_mut_type!();
impl Fold for Marker { fn visit_mut_ident(&mut self, i: &mut Ident) {
fn fold_span(&mut self, sp: Span) -> Span { i.span = i.span.apply_mark(self.0);
sp.apply_mark(self.0)
} }
} }
@ -275,6 +280,7 @@ impl Fold for Marker {
mod tests { mod tests {
use super::*; use super::*;
use crate::pass::noop; use crate::pass::noop;
use swc_ecma_visit::{as_folder, FoldWith};
#[test] #[test]
fn external_helper() { fn external_helper() {
@ -283,9 +289,9 @@ swcHelpers._throw()";
crate::tests::Tester::run(|tester| { crate::tests::Tester::run(|tester| {
HELPERS.set(&Helpers::new(true), || { HELPERS.set(&Helpers::new(true), || {
let expected = tester.apply_transform( let expected = tester.apply_transform(
DropSpan { as_folder(DropSpan {
preserve_ctxt: false, preserve_ctxt: false,
}, }),
"output.js", "output.js",
Default::default(), Default::default(),
"import * as swcHelpers1 from '@swc/helpers'; "import * as swcHelpers1 from '@swc/helpers';
@ -296,7 +302,7 @@ swcHelpers._throw();",
eprintln!("----- Actual -----"); eprintln!("----- Actual -----");
let tr = InjectHelpers; let tr = as_folder(InjectHelpers);
let actual = tester let actual = tester
.apply_transform(tr, "input.js", Default::default(), input)? .apply_transform(tr, "input.js", Default::default(), input)?
.fold_with(&mut crate::hygiene::hygiene()) .fold_with(&mut crate::hygiene::hygiene())
@ -329,7 +335,7 @@ swcHelpers._throw();",
Default::default(), Default::default(),
|_| { |_| {
enable_helper!(throw); enable_helper!(throw);
InjectHelpers as_folder(InjectHelpers)
}, },
"'use strict'", "'use strict'",
"'use strict' "'use strict'
@ -347,7 +353,7 @@ function _throw(e) {
Default::default(), Default::default(),
|_| { |_| {
enable_helper!(throw); enable_helper!(throw);
InjectHelpers as_folder(InjectHelpers)
}, },
"let _throw = null", "let _throw = null",
"function _throw(e) { "function _throw(e) {

View File

@ -8,7 +8,7 @@ use std::{cell::RefCell, collections::HashMap};
use swc_atoms::JsWord; use swc_atoms::JsWord;
use swc_common::{chain, Span, SyntaxContext}; use swc_common::{chain, Span, SyntaxContext};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{as_folder, noop_fold_type, noop_visit_mut_type, Fold, FoldWith, VisitMut};
mod ops; mod ops;
#[cfg(test)] #[cfg(test)]
@ -21,8 +21,6 @@ struct Hygiene<'a> {
ident_type: IdentType, ident_type: IdentType,
} }
noop_fold_type!(Hygiene<'_>);
type Contexts = SmallVec<[SyntaxContext; 32]>; type Contexts = SmallVec<[SyntaxContext; 32]>;
impl<'a> Hygiene<'a> { impl<'a> Hygiene<'a> {
@ -141,23 +139,25 @@ impl<'a> Hygiene<'a> {
} }
pub fn hygiene() -> impl Fold + 'static { pub fn hygiene() -> impl Fold + 'static {
#[derive(Clone, Copy)]
struct MarkClearer;
impl Fold for MarkClearer {
fn fold_span(&mut self, span: Span) -> Span {
span.with_ctxt(SyntaxContext::empty())
}
}
chain!( chain!(
Hygiene { Hygiene {
current: Default::default(), current: Default::default(),
ident_type: IdentType::Ref, ident_type: IdentType::Ref,
}, },
MarkClearer as_folder(MarkClearer)
) )
} }
#[derive(Clone, Copy)]
struct MarkClearer;
impl VisitMut for MarkClearer {
noop_visit_mut_type!();
fn visit_mut_span(&mut self, span: &mut Span) {
*span = span.with_ctxt(SyntaxContext::empty());
}
}
impl<'a> Hygiene<'a> { impl<'a> Hygiene<'a> {
fn apply_ops<N>(&mut self, node: N) -> N fn apply_ops<N>(&mut self, node: N) -> N
where where
@ -485,6 +485,8 @@ macro_rules! track_ident {
} }
impl<'a> Fold for Hygiene<'a> { impl<'a> Fold for Hygiene<'a> {
noop_fold_type!();
track_ident!(); track_ident!();
fn fold_arrow_expr(&mut self, mut node: ArrowExpr) -> ArrowExpr { fn fold_arrow_expr(&mut self, mut node: ArrowExpr) -> ArrowExpr {

View File

@ -1,7 +1,7 @@
use swc_atoms::JsWord; use swc_atoms::JsWord;
use swc_common::{util::move_map::MoveMap, Spanned, SyntaxContext, DUMMY_SP}; use swc_common::{util::move_map::MoveMap, Spanned, SyntaxContext, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
#[derive(Debug)] #[derive(Debug)]
pub(super) enum ScopeOp { pub(super) enum ScopeOp {
@ -13,9 +13,9 @@ pub(super) enum ScopeOp {
pub(super) struct Operator<'a>(pub &'a [ScopeOp]); pub(super) struct Operator<'a>(pub &'a [ScopeOp]);
noop_fold_type!(Operator<'_>);
impl<'a> Fold for Operator<'a> { impl<'a> Fold for Operator<'a> {
noop_fold_type!();
fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> { fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> {
let mut stmts = Vec::with_capacity(items.len()); let mut stmts = Vec::with_capacity(items.len());
@ -287,6 +287,8 @@ struct VarFolder<'a, 'b> {
} }
impl Fold for VarFolder<'_, '_> { impl Fold for VarFolder<'_, '_> {
noop_fold_type!();
fn fold_expr(&mut self, n: Expr) -> Expr { fn fold_expr(&mut self, n: Expr) -> Expr {
n n
} }

View File

@ -201,155 +201,3 @@ macro_rules! validate {
} }
}}; }};
} }
#[macro_export]
macro_rules! noop_fold_type {
($F:ty, $N:tt) => {
// impl Fold<swc_ecma_ast::$N> for $F {
// #[inline]
// fn fold(&mut self, node: swc_ecma_ast::$N) -> swc_ecma_ast::$N {
// node
// }
// }
};
($F:ty) => {
noop_fold_type!($F, Accessibility);
noop_fold_type!($F, TruePlusMinus);
noop_fold_type!($F, TsArrayType);
noop_fold_type!($F, TsCallSignatureDecl);
noop_fold_type!($F, TsConditionalType);
noop_fold_type!($F, TsConstructSignatureDecl);
noop_fold_type!($F, TsConstructorType);
noop_fold_type!($F, TsEntityName);
noop_fold_type!($F, TsEnumDecl);
noop_fold_type!($F, TsEnumMember);
noop_fold_type!($F, TsEnumMemberId);
noop_fold_type!($F, TsExternalModuleRef);
noop_fold_type!($F, TsFnOrConstructorType);
noop_fold_type!($F, TsFnParam);
noop_fold_type!($F, TsFnType);
noop_fold_type!($F, TsImportEqualsDecl);
noop_fold_type!($F, TsImportType);
noop_fold_type!($F, TsIndexSignature);
noop_fold_type!($F, TsIndexedAccessType);
noop_fold_type!($F, TsInferType);
noop_fold_type!($F, TsInterfaceBody);
noop_fold_type!($F, TsInterfaceDecl);
noop_fold_type!($F, TsIntersectionType);
noop_fold_type!($F, TsKeywordType);
noop_fold_type!($F, TsKeywordTypeKind);
noop_fold_type!($F, TsMappedType);
noop_fold_type!($F, TsMethodSignature);
noop_fold_type!($F, TsModuleBlock);
noop_fold_type!($F, TsModuleDecl);
noop_fold_type!($F, TsModuleName);
noop_fold_type!($F, TsModuleRef);
noop_fold_type!($F, TsNamespaceBody);
noop_fold_type!($F, TsNamespaceDecl);
noop_fold_type!($F, TsNamespaceExportDecl);
noop_fold_type!($F, TsOptionalType);
noop_fold_type!($F, TsParamProp);
noop_fold_type!($F, TsParamPropParam);
noop_fold_type!($F, TsParenthesizedType);
noop_fold_type!($F, TsPropertySignature);
noop_fold_type!($F, TsQualifiedName);
noop_fold_type!($F, TsRestType);
noop_fold_type!($F, TsSignatureDecl);
noop_fold_type!($F, TsThisType);
noop_fold_type!($F, TsThisTypeOrIdent);
noop_fold_type!($F, TsTupleType);
noop_fold_type!($F, TsType);
noop_fold_type!($F, TsTypeAliasDecl);
noop_fold_type!($F, TsTypeAnn);
noop_fold_type!($F, TsTypeAssertion);
noop_fold_type!($F, TsTypeCastExpr);
noop_fold_type!($F, TsTypeElement);
noop_fold_type!($F, TsTypeLit);
noop_fold_type!($F, TsTypeOperator);
noop_fold_type!($F, TsTypeOperatorOp);
noop_fold_type!($F, TsTypeParam);
noop_fold_type!($F, TsTypeParamDecl);
noop_fold_type!($F, TsTypeParamInstantiation);
noop_fold_type!($F, TsTypePredicate);
noop_fold_type!($F, TsTypeQuery);
noop_fold_type!($F, TsTypeQueryExpr);
noop_fold_type!($F, TsTypeRef);
noop_fold_type!($F, TsUnionOrIntersectionType);
noop_fold_type!($F, TsUnionType);
};
}
#[macro_export]
macro_rules! noop_visit_type {
($F:ty, $N:tt) => {
// impl Visit<swc_ecma_ast::$N> for $F {
// #[inline]
// fn visit(&mut self, _: &swc_ecma_ast::$N) {}
// }
};
($F:ty) => {
noop_visit_type!($F, Accessibility);
noop_visit_type!($F, TruePlusMinus);
noop_visit_type!($F, TsArrayType);
noop_visit_type!($F, TsCallSignatureDecl);
noop_visit_type!($F, TsConditionalType);
noop_visit_type!($F, TsConstructSignatureDecl);
noop_visit_type!($F, TsConstructorType);
noop_visit_type!($F, TsEntityName);
noop_visit_type!($F, TsEnumDecl);
noop_visit_type!($F, TsEnumMember);
noop_visit_type!($F, TsEnumMemberId);
noop_visit_type!($F, TsExternalModuleRef);
noop_visit_type!($F, TsFnOrConstructorType);
noop_visit_type!($F, TsFnParam);
noop_visit_type!($F, TsFnType);
noop_visit_type!($F, TsImportEqualsDecl);
noop_visit_type!($F, TsImportType);
noop_visit_type!($F, TsIndexSignature);
noop_visit_type!($F, TsIndexedAccessType);
noop_visit_type!($F, TsInferType);
noop_visit_type!($F, TsInterfaceBody);
noop_visit_type!($F, TsInterfaceDecl);
noop_visit_type!($F, TsIntersectionType);
noop_visit_type!($F, TsKeywordType);
noop_visit_type!($F, TsKeywordTypeKind);
noop_visit_type!($F, TsMappedType);
noop_visit_type!($F, TsMethodSignature);
noop_visit_type!($F, TsModuleBlock);
noop_visit_type!($F, TsModuleDecl);
noop_visit_type!($F, TsModuleName);
noop_visit_type!($F, TsModuleRef);
noop_visit_type!($F, TsNamespaceBody);
noop_visit_type!($F, TsNamespaceDecl);
noop_visit_type!($F, TsNamespaceExportDecl);
noop_visit_type!($F, TsOptionalType);
noop_visit_type!($F, TsParamProp);
noop_visit_type!($F, TsParamPropParam);
noop_visit_type!($F, TsParenthesizedType);
noop_visit_type!($F, TsPropertySignature);
noop_visit_type!($F, TsQualifiedName);
noop_visit_type!($F, TsRestType);
noop_visit_type!($F, TsSignatureDecl);
noop_visit_type!($F, TsThisType);
noop_visit_type!($F, TsThisTypeOrIdent);
noop_visit_type!($F, TsTupleType);
noop_visit_type!($F, TsType);
noop_visit_type!($F, TsTypeAliasDecl);
noop_visit_type!($F, TsTypeAnn);
noop_visit_type!($F, TsTypeAssertion);
noop_visit_type!($F, TsTypeCastExpr);
noop_visit_type!($F, TsTypeElement);
noop_visit_type!($F, TsTypeLit);
noop_visit_type!($F, TsTypeOperator);
noop_visit_type!($F, TsTypeOperatorOp);
noop_visit_type!($F, TsTypeParam);
noop_visit_type!($F, TsTypeParamDecl);
noop_visit_type!($F, TsTypeParamInstantiation);
noop_visit_type!($F, TsTypePredicate);
noop_visit_type!($F, TsTypeQuery);
noop_visit_type!($F, TsTypeQueryExpr);
noop_visit_type!($F, TsTypeRef);
noop_visit_type!($F, TsUnionOrIntersectionType);
noop_visit_type!($F, TsUnionType);
};
}

View File

@ -9,7 +9,7 @@ use std::iter;
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_common::{Mark, DUMMY_SP}; use swc_common::{Mark, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, VisitWith};
pub fn amd(config: Config) -> impl Fold { pub fn amd(config: Config) -> impl Fold {
Amd { Amd {
@ -27,8 +27,6 @@ struct Amd {
exports: Exports, exports: Exports,
} }
noop_fold_type!(Amd);
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "camelCase")] #[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct Config { pub struct Config {
@ -40,6 +38,8 @@ pub struct Config {
} }
impl Fold for Amd { impl Fold for Amd {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr { fn fold_expr(&mut self, expr: Expr) -> Expr {
let top_level = self.in_top_level; let top_level = self.in_top_level;

View File

@ -8,7 +8,7 @@ use fxhash::FxHashSet;
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_common::{Mark, DUMMY_SP}; use swc_common::{Mark, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, VisitWith};
pub fn common_js(root_mark: Mark, config: Config) -> impl Fold { pub fn common_js(root_mark: Mark, config: Config) -> impl Fold {
CommonJs { CommonJs {
@ -26,9 +26,9 @@ struct CommonJs {
in_top_level: bool, in_top_level: bool,
} }
noop_fold_type!(CommonJs);
impl Fold for CommonJs { impl Fold for CommonJs {
noop_fold_type!();
fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> { fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> {
let mut emitted_esmodule = false; let mut emitted_esmodule = false;
let mut stmts = Vec::with_capacity(items.len() + 4); let mut stmts = Vec::with_capacity(items.len() + 4);

View File

@ -2,7 +2,7 @@ use super::util::Scope;
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, Node, Visit}; use swc_ecma_visit::{noop_fold_type, Fold, Node, Visit};
pub fn import_analyzer() -> impl Fold { pub fn import_analyzer() -> impl Fold {
ImportAnalyzer { ImportAnalyzer {
@ -15,10 +15,9 @@ struct ImportAnalyzer {
scope: Scope, scope: Scope,
} }
noop_fold_type!(ImportAnalyzer);
noop_visit_type!(ImportAnalyzer);
impl Fold for ImportAnalyzer { impl Fold for ImportAnalyzer {
noop_fold_type!();
fn fold_module(&mut self, module: Module) -> Module { fn fold_module(&mut self, module: Module) -> Module {
self.visit_module(&module, &Invalid { span: DUMMY_SP } as _); self.visit_module(&module, &Invalid { span: DUMMY_SP } as _);
@ -35,6 +34,8 @@ impl Fold for ImportAnalyzer {
} }
impl Visit for ImportAnalyzer { impl Visit for ImportAnalyzer {
noop_visit_type!();
fn visit_export_all(&mut self, export: &ExportAll, _parent: &dyn Node) { fn visit_export_all(&mut self, export: &ExportAll, _parent: &dyn Node) {
*self *self
.scope .scope

View File

@ -9,7 +9,7 @@ use fxhash::FxHashSet;
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_common::{sync::Lrc, Mark, SourceMap, DUMMY_SP}; use swc_common::{sync::Lrc, Mark, SourceMap, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, VisitWith};
mod config; mod config;
@ -34,9 +34,9 @@ struct Umd {
exports: Exports, exports: Exports,
} }
noop_fold_type!(Umd);
impl Fold for Umd { impl Fold for Umd {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr { fn fold_expr(&mut self, expr: Expr) -> Expr {
let exports = self.exports.0.clone(); let exports = self.exports.0.clone();
let top_level = self.in_top_level; let top_level = self.in_top_level;

View File

@ -1,4 +1,4 @@
pub use self::{inline_globals::InlineGlobals, json_parse::JsonParse, simplify::simplifier}; pub use self::{inline_globals::inline_globals, json_parse::json_parse, simplify::simplifier};
mod inline_globals; mod inline_globals;
mod json_parse; mod json_parse;

View File

@ -1,17 +1,20 @@
use std::collections::HashMap; use std::collections::HashMap;
use swc_atoms::{js_word, JsWord}; use swc_atoms::{js_word, JsWord};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
#[derive(Clone)] pub fn inline_globals(envs: HashMap<JsWord, Expr>, globals: HashMap<JsWord, Expr>) -> impl Fold {
pub struct InlineGlobals { InlineGlobals { envs, globals }
pub envs: HashMap<JsWord, Expr>,
pub globals: HashMap<JsWord, Expr>,
} }
noop_fold_type!(InlineGlobals); struct InlineGlobals {
envs: HashMap<JsWord, Expr>,
globals: HashMap<JsWord, Expr>,
}
impl Fold for InlineGlobals { impl Fold for InlineGlobals {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr { fn fold_expr(&mut self, expr: Expr) -> Expr {
let expr = match expr { let expr = match expr {
Expr::Member(expr) => { Expr::Member(expr) => {
@ -83,6 +86,7 @@ impl Fold for InlineGlobals {
mod tests { mod tests {
use super::*; use super::*;
use swc_ecma_utils::DropSpan; use swc_ecma_utils::DropSpan;
use swc_ecma_visit::as_folder;
fn mk_map( fn mk_map(
tester: &mut crate::tests::Tester<'_>, tester: &mut crate::tests::Tester<'_>,
@ -100,9 +104,9 @@ mod tests {
let mut v = tester let mut v = tester
.apply_transform( .apply_transform(
DropSpan { as_folder(DropSpan {
preserve_ctxt: false, preserve_ctxt: false,
}, }),
"global.js", "global.js",
::swc_ecma_parser::Syntax::default(), ::swc_ecma_parser::Syntax::default(),
&v, &v,

View File

@ -3,7 +3,7 @@ use serde_json::Value;
use std::usize; use std::usize;
use swc_common::{Spanned, DUMMY_SP}; use swc_common::{Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
/// Trnasform to optimize performance of literals. /// Trnasform to optimize performance of literals.
/// ///
@ -27,12 +27,13 @@ use swc_ecma_visit::{Fold, FoldWith};
/// - Object literal is deeply nested (threshold: ) /// - Object literal is deeply nested (threshold: )
/// ///
/// See https://github.com/swc-project/swc/issues/409 /// See https://github.com/swc-project/swc/issues/409
#[derive(Debug)] pub fn json_parse(min_cost: usize) -> impl Fold {
pub struct JsonParse { JsonParse { min_cost }
pub min_cost: usize,
} }
noop_fold_type!(JsonParse); struct JsonParse {
pub min_cost: usize,
}
impl Default for JsonParse { impl Default for JsonParse {
fn default() -> Self { fn default() -> Self {
@ -41,6 +42,8 @@ impl Default for JsonParse {
} }
impl Fold for JsonParse { impl Fold for JsonParse {
noop_fold_type!();
/// Handles parent expressions before child expressions. /// Handles parent expressions before child expressions.
fn fold_expr(&mut self, e: Expr) -> Expr { fn fold_expr(&mut self, e: Expr) -> Expr {
if self.min_cost == usize::MAX { if self.min_cost == usize::MAX {

View File

@ -10,7 +10,7 @@ use swc_common::{
Spanned, DUMMY_SP, Spanned, DUMMY_SP,
}; };
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -44,9 +44,9 @@ struct Remover {
normal_block: bool, normal_block: bool,
} }
noop_fold_type!(Remover);
impl Fold for Remover { impl Fold for Remover {
noop_fold_type!();
fn fold_array_pat(&mut self, p: ArrayPat) -> ArrayPat { fn fold_array_pat(&mut self, p: ArrayPat) -> ArrayPat {
let mut p: ArrayPat = p.fold_children_with(self); let mut p: ArrayPat = p.fold_children_with(self);
@ -1465,6 +1465,8 @@ fn check_for_stopper(s: &[Stmt], only_conditional: bool) -> bool {
} }
impl Visit for Visitor { impl Visit for Visitor {
noop_visit_type!();
fn visit_switch_case(&mut self, node: &SwitchCase, _: &dyn Node) { fn visit_switch_case(&mut self, node: &SwitchCase, _: &dyn Node) {
let old = self.in_cond; let old = self.in_cond;
self.in_cond = true; self.in_cond = true;

View File

@ -11,7 +11,9 @@ use swc_common::{
}; };
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_utils::{find_ids, ident::IdentLike, Id, StmtLike}; use swc_ecma_utils::{find_ids, ident::IdentLike, Id, StmtLike};
use swc_ecma_visit::{Fold, FoldWith, VisitWith}; use swc_ecma_visit::{
as_folder, noop_fold_type, noop_visit_mut_type, Fold, FoldWith, VisitMut, VisitWith,
};
macro_rules! preserve { macro_rules! preserve {
($name:ident, $T:ty) => { ($name:ident, $T:ty) => {
@ -62,7 +64,7 @@ pub fn dce<'a>(config: Config<'a>) -> impl RepeatedJsPass + 'a {
marking_phase: false, marking_phase: false,
decl_dropping_phase: false, decl_dropping_phase: false,
}, },
UsedMarkRemover { used_mark } as_folder(UsedMarkRemover { used_mark })
) )
} }
@ -70,8 +72,6 @@ struct UsedMarkRemover {
used_mark: Mark, used_mark: Mark,
} }
noop_fold_type!(UsedMarkRemover);
impl CompilerPass for UsedMarkRemover { impl CompilerPass for UsedMarkRemover {
fn name() -> Cow<'static, str> { fn name() -> Cow<'static, str> {
Cow::Borrowed("dce-cleanup") Cow::Borrowed("dce-cleanup")
@ -86,14 +86,14 @@ impl Repeated for UsedMarkRemover {
fn reset(&mut self) {} fn reset(&mut self) {}
} }
impl Fold for UsedMarkRemover { impl VisitMut for UsedMarkRemover {
fn fold_span(&mut self, s: Span) -> Span { noop_visit_mut_type!();
let mut ctxt = s.ctxt().clone();
if ctxt.remove_mark() == self.used_mark {
return s.with_ctxt(ctxt);
}
s fn visit_mut_span(&mut self, s: &mut Span) {
let mut ctxt = s.ctxt.clone(); // explicit clone
if ctxt.remove_mark() == self.used_mark {
s.ctxt = ctxt;
}
} }
} }
@ -134,19 +134,14 @@ impl Repeated for Dce<'_> {
} }
impl Fold for Dce<'_> { impl Fold for Dce<'_> {
preserve!(fold_ts_interface_decl, TsInterfaceDecl); noop_fold_type!();
preserve!(fold_ts_type_alias_decl, TsTypeAliasDecl);
preserve!(fold_ts_enum_decl, TsEnumDecl);
preserve!(fold_ts_module_decl, TsModuleDecl);
preserve!(fold_debugger_stmt, DebuggerStmt); preserve!(fold_debugger_stmt, DebuggerStmt);
preserve!(fold_with_stmt, WithStmt); preserve!(fold_with_stmt, WithStmt);
preserve!(fold_break_stmt, BreakStmt); preserve!(fold_break_stmt, BreakStmt);
preserve!(fold_continue_stmt, ContinueStmt); preserve!(fold_continue_stmt, ContinueStmt);
preserve!(fold_ts_import_equals_decl, TsImportEqualsDecl);
preserve!(fold_ts_export_assignment, TsExportAssignment); preserve!(fold_ts_export_assignment, TsExportAssignment);
preserve!(fold_ts_namespace_export_decl, TsNamespaceExportDecl);
fn fold_block_stmt(&mut self, node: BlockStmt) -> BlockStmt { fn fold_block_stmt(&mut self, node: BlockStmt) -> BlockStmt {
if self.is_marked(node.span) { if self.is_marked(node.span) {
@ -677,7 +672,7 @@ impl Dce<'_> {
T: for<'any> VisitWith<SideEffectVisitor<'any>> + VisitWith<ImportDetector>, T: for<'any> VisitWith<SideEffectVisitor<'any>> + VisitWith<ImportDetector>,
{ {
if self.marking_phase { if self.marking_phase {
return items.move_map(|item| self.fold_in_marking_phase(item)); return items.move_map(|item| item.fold_with(self));
} }
let old = self.changed; let old = self.changed;

View File

@ -10,9 +10,9 @@ pub(super) struct ImportDetector {
found: bool, found: bool,
} }
noop_visit_type!(ImportDetector);
impl Visit for ImportDetector { impl Visit for ImportDetector {
noop_visit_type!();
fn visit_import_decl(&mut self, _: &ImportDecl, _: &dyn Node) { fn visit_import_decl(&mut self, _: &ImportDecl, _: &dyn Node) {
self.found = true; self.found = true;
} }
@ -58,8 +58,6 @@ impl SideEffectVisitor<'_> {
} }
} }
noop_visit_type!(SideEffectVisitor<'_>);
pub(super) struct SideEffectVisitor<'a> { pub(super) struct SideEffectVisitor<'a> {
included: &'a mut FxHashSet<Id>, included: &'a mut FxHashSet<Id>,
exports: Option<&'a [Id]>, exports: Option<&'a [Id]>,
@ -84,6 +82,8 @@ impl SideEffectVisitor<'_> {
} }
impl Visit for SideEffectVisitor<'_> { impl Visit for SideEffectVisitor<'_> {
noop_visit_type!();
fn visit_expr(&mut self, node: &Expr, _: &dyn Node) { fn visit_expr(&mut self, node: &Expr, _: &dyn Node) {
log::debug!("Visit<Expr>"); log::debug!("Visit<Expr>");

View File

@ -7,7 +7,7 @@ use swc_common::{
}; };
use swc_ecma_ast::{Ident, Lit, *}; use swc_ecma_ast::{Ident, Lit, *};
use swc_ecma_utils::ident::IdentLike; use swc_ecma_utils::ident::IdentLike;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -33,8 +33,6 @@ struct SimplifyExpr {
changed: bool, changed: bool,
} }
noop_fold_type!(SimplifyExpr);
impl CompilerPass for SimplifyExpr { impl CompilerPass for SimplifyExpr {
fn name() -> Cow<'static, str> { fn name() -> Cow<'static, str> {
Cow::Borrowed("simplify-expr") Cow::Borrowed("simplify-expr")
@ -996,6 +994,8 @@ impl SimplifyExpr {
} }
impl Fold for SimplifyExpr { impl Fold for SimplifyExpr {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr { fn fold_expr(&mut self, expr: Expr) -> Expr {
// fold children before doing something more. // fold children before doing something more.
let expr = expr.fold_children_with(self); let expr = expr.fold_children_with(self);

View File

@ -7,7 +7,7 @@ use swc_common::{
}; };
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_utils::{contains_this_expr, find_ids, ident::IdentLike, undefined, Id}; use swc_ecma_utils::{contains_this_expr, find_ids, ident::IdentLike, undefined, Id};
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
mod scope; mod scope;
@ -72,8 +72,6 @@ struct Inlining<'a> {
pat_mode: PatFoldingMode, pat_mode: PatFoldingMode,
} }
noop_fold_type!(Inlining<'_>);
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum PatFoldingMode { enum PatFoldingMode {
Assign, Assign,
@ -92,6 +90,8 @@ impl Inlining<'_> {
} }
impl Fold for Inlining<'_> { impl Fold for Inlining<'_> {
noop_fold_type!();
fn fold_arrow_expr(&mut self, node: ArrowExpr) -> ArrowExpr { fn fold_arrow_expr(&mut self, node: ArrowExpr) -> ArrowExpr {
self.fold_with_child(ScopeKind::Fn { named: false }, node) self.fold_with_child(ScopeKind::Fn { named: false }, node)
} }
@ -814,6 +814,8 @@ struct IdentListVisitor<'a, 'b> {
} }
impl Visit for IdentListVisitor<'_, '_> { impl Visit for IdentListVisitor<'_, '_> {
noop_visit_type!();
fn visit_ident(&mut self, node: &Ident, _: &dyn Node) { fn visit_ident(&mut self, node: &Ident, _: &dyn Node) {
self.scope.add_write(&node.to_id(), true); self.scope.add_write(&node.to_id(), true);
} }

View File

@ -7,7 +7,7 @@ use serde::Deserialize;
use std::iter; use std::iter;
use swc_common::{Spanned, DUMMY_SP}; use swc_common::{Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, Node, Visit, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
mod legacy; mod legacy;
mod usage; mod usage;
@ -78,9 +78,9 @@ struct Decorators {
is_in_strict: bool, is_in_strict: bool,
} }
noop_fold_type!(Decorators);
impl Fold for Decorators { impl Fold for Decorators {
noop_fold_type!();
fn fold_decl(&mut self, decl: Decl) -> Decl { fn fold_decl(&mut self, decl: Decl) -> Decl {
let decl = decl.fold_children_with(self); let decl = decl.fold_children_with(self);
@ -633,6 +633,8 @@ struct DecoratorFinder {
found: bool, found: bool,
} }
impl Visit for DecoratorFinder { impl Visit for DecoratorFinder {
noop_visit_type!();
fn visit_decorator(&mut self, _: &Decorator, _: &dyn Node) { fn visit_decorator(&mut self, _: &Decorator, _: &dyn Node) {
self.found = true self.found = true
} }

View File

@ -8,7 +8,7 @@ use smallvec::SmallVec;
use std::mem::replace; use std::mem::replace;
use swc_common::{util::move_map::MoveMap, DUMMY_SP}; use swc_common::{util::move_map::MoveMap, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, VisitWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, VisitWith};
mod metadata; mod metadata;
@ -29,9 +29,9 @@ pub(super) fn new(metadata: bool) -> Legacy {
} }
} }
noop_fold_type!(Legacy);
impl Fold for Legacy { impl Fold for Legacy {
noop_fold_type!();
fn fold_decl(&mut self, decl: Decl) -> Decl { fn fold_decl(&mut self, decl: Decl) -> Decl {
let decl: Decl = decl.fold_children_with(self); let decl: Decl = decl.fold_children_with(self);
@ -760,9 +760,9 @@ struct ClassFieldAccessConverter {
alias: Ident, alias: Ident,
} }
noop_fold_type!(ClassFieldAccessConverter);
impl Fold for ClassFieldAccessConverter { impl Fold for ClassFieldAccessConverter {
noop_fold_type!();
fn fold_ident(&mut self, node: Ident) -> Ident { fn fold_ident(&mut self, node: Ident) -> Ident {
if node.sym == self.cls_name.sym && node.span.ctxt() == self.cls_name.span.ctxt() { if node.sym == self.cls_name.sym && node.span.ctxt() == self.cls_name.span.ctxt() {
return self.alias.clone(); return self.alias.clone();

View File

@ -1,12 +1,14 @@
use swc_common::{util::move_map::MoveMap, Spanned, DUMMY_SP}; use swc_common::{util::move_map::MoveMap, Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_utils::{undefined, ExprFactory}; use swc_ecma_utils::{undefined, ExprFactory};
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
/// https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata/blob/master/src/parameter/parameterVisitor.ts /// https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata/blob/master/src/parameter/parameterVisitor.ts
pub(super) struct ParamMetadata; pub(super) struct ParamMetadata;
impl Fold for ParamMetadata { impl Fold for ParamMetadata {
noop_fold_type!();
fn fold_class(&mut self, mut cls: Class) -> Class { fn fold_class(&mut self, mut cls: Class) -> Class {
cls = cls.fold_children_with(self); cls = cls.fold_children_with(self);
let mut decorators = cls.decorators; let mut decorators = cls.decorators;
@ -120,6 +122,8 @@ pub(super) struct Metadata<'a> {
} }
impl Fold for Metadata<'_> { impl Fold for Metadata<'_> {
noop_fold_type!();
fn fold_class(&mut self, mut c: Class) -> Class { fn fold_class(&mut self, mut c: Class) -> Class {
c = c.fold_children_with(self); c = c.fold_children_with(self);

View File

@ -14,6 +14,8 @@ pub(super) struct DecoratorFinder {
} }
impl Visit for DecoratorFinder { impl Visit for DecoratorFinder {
noop_visit_type!();
fn visit_decorator(&mut self, _: &Decorator, _parent: &dyn Node) { fn visit_decorator(&mut self, _: &Decorator, _parent: &dyn Node) {
self.found = true; self.found = true;
} }

View File

@ -1,7 +1,7 @@
use crate::util::IdentExt; use crate::util::IdentExt;
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::Fold; use swc_ecma_visit::{noop_fold_type, Fold};
/// `@babel/plugin-proposal-export-default-from` and /// `@babel/plugin-proposal-export-default-from` and
/// `@babel/plugin-proposal-export-namespace-from` /// `@babel/plugin-proposal-export-namespace-from`
@ -12,9 +12,9 @@ pub fn export() -> impl Fold {
#[derive(Clone)] #[derive(Clone)]
struct ExportDefaultFrom; struct ExportDefaultFrom;
noop_fold_type!(ExportDefaultFrom);
impl Fold for ExportDefaultFrom { impl Fold for ExportDefaultFrom {
noop_fold_type!();
fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> { fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> {
// Imports // Imports
let mut stmts = Vec::with_capacity(items.len() + 4); let mut stmts = Vec::with_capacity(items.len() + 4);

View File

@ -3,7 +3,7 @@ use std::ops::DerefMut;
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -17,9 +17,9 @@ pub fn display_name() -> impl Fold {
struct DisplayName; struct DisplayName;
noop_fold_type!(DisplayName);
impl Fold for DisplayName { impl Fold for DisplayName {
noop_fold_type!();
fn fold_assign_expr(&mut self, expr: AssignExpr) -> AssignExpr { fn fold_assign_expr(&mut self, expr: AssignExpr) -> AssignExpr {
let expr = expr.fold_children_with(self); let expr = expr.fold_children_with(self);
@ -123,6 +123,8 @@ struct Folder {
} }
impl Fold for Folder { impl Fold for Folder {
noop_fold_type!();
/// Don't recurse into array. /// Don't recurse into array.
fn fold_array_lit(&mut self, node: ArrayLit) -> ArrayLit { fn fold_array_lit(&mut self, node: ArrayLit) -> ArrayLit {
node node

View File

@ -8,7 +8,7 @@ use swc_atoms::{js_word, JsWord};
use swc_common::{iter::IdentifyLast, sync::Lrc, FileName, SourceMap, Spanned, DUMMY_SP}; use swc_common::{iter::IdentifyLast, sync::Lrc, FileName, SourceMap, Spanned, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_parser::{Parser, StringInput, Syntax}; use swc_ecma_parser::{Parser, StringInput, Syntax};
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -105,8 +105,6 @@ struct Jsx {
throw_if_namespace: bool, throw_if_namespace: bool,
} }
noop_fold_type!(Jsx);
impl Jsx { impl Jsx {
fn jsx_frag_to_expr(&mut self, el: JSXFragment) -> Expr { fn jsx_frag_to_expr(&mut self, el: JSXFragment) -> Expr {
let span = el.span(); let span = el.span();
@ -255,6 +253,8 @@ impl Jsx {
} }
impl Fold for Jsx { impl Fold for Jsx {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr { fn fold_expr(&mut self, expr: Expr) -> Expr {
let mut expr = expr.fold_children_with(self); let mut expr = expr.fold_children_with(self);

View File

@ -1,8 +1,8 @@
use super::*; use super::*;
use crate::{ use crate::{
compat::{ compat::{
es2015::{arrow, Classes}, es2015::{arrow, classes},
es3::PropertyLiteral, es3::property_literals,
}, },
modules::common_js::common_js, modules::common_js::common_js,
react::display_name, react::display_name,
@ -14,7 +14,7 @@ fn tr(t: &mut Tester, options: Options) -> impl Fold {
chain!( chain!(
jsx(t.cm.clone(), options), jsx(t.cm.clone(), options),
display_name(), display_name(),
Classes::default(), classes(),
arrow(), arrow(),
) )
} }
@ -462,7 +462,7 @@ test!(
jsx: true, jsx: true,
..Default::default() ..Default::default()
}), }),
|t| chain!(tr(t, Default::default()), PropertyLiteral), |t| chain!(tr(t, Default::default()), property_literals()),
react_should_add_quotes_es3, react_should_add_quotes_es3,
r#"var es3 = <F aaa new const var default foo-bar/>;"#, r#"var es3 = <F aaa new const var default foo-bar/>;"#,
r#" r#"

View File

@ -1,6 +1,6 @@
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::Fold; use swc_ecma_visit::{noop_fold_type, Fold};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -15,9 +15,9 @@ struct JsxSelf {
dev: bool, dev: bool,
} }
noop_fold_type!(JsxSelf);
impl Fold for JsxSelf { impl Fold for JsxSelf {
noop_fold_type!();
fn fold_jsx_opening_element(&mut self, mut n: JSXOpeningElement) -> JSXOpeningElement { fn fold_jsx_opening_element(&mut self, mut n: JSXOpeningElement) -> JSXOpeningElement {
if !self.dev { if !self.dev {
return n; return n;

View File

@ -1,6 +1,6 @@
use swc_common::{sync::Lrc, FileName, SourceMap, DUMMY_SP}; use swc_common::{sync::Lrc, FileName, SourceMap, DUMMY_SP};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::Fold; use swc_ecma_visit::{noop_fold_type, Fold};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -15,9 +15,9 @@ struct JsxSrc {
dev: bool, dev: bool,
} }
noop_fold_type!(JsxSrc);
impl Fold for JsxSrc { impl Fold for JsxSrc {
noop_fold_type!();
fn fold_jsx_opening_element(&mut self, mut e: JSXOpeningElement) -> JSXOpeningElement { fn fold_jsx_opening_element(&mut self, mut e: JSXOpeningElement) -> JSXOpeningElement {
if !self.dev || e.span == DUMMY_SP { if !self.dev || e.span == DUMMY_SP {
return e; return e;

View File

@ -3,19 +3,19 @@ use std::{cell::RefCell, collections::HashSet};
use swc_atoms::JsWord; use swc_atoms::JsWord;
use swc_common::{Mark, SyntaxContext}; use swc_common::{Mark, SyntaxContext};
use swc_ecma_ast::*; use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
const LOG: bool = false; const LOG: bool = false;
pub fn resolver() -> Resolver<'static> { pub fn resolver() -> impl 'static + Fold {
resolver_with_mark(Mark::fresh(Mark::root())) resolver_with_mark(Mark::fresh(Mark::root()))
} }
/// `mark` should not be root. /// `mark` should not be root.
pub fn resolver_with_mark(top_level_mark: Mark) -> Resolver<'static> { pub fn resolver_with_mark(top_level_mark: Mark) -> impl 'static + Fold {
assert_ne!( assert_ne!(
top_level_mark, top_level_mark,
Mark::root(), Mark::root(),
@ -59,7 +59,7 @@ impl<'a> Scope<'a> {
/// ## Hoisting phase /// ## Hoisting phase
/// ///
/// ## Resolving phase /// ## Resolving phase
pub struct Resolver<'a> { struct Resolver<'a> {
hoist: bool, hoist: bool,
mark: Mark, mark: Mark,
current: Scope<'a>, current: Scope<'a>,
@ -67,8 +67,6 @@ pub struct Resolver<'a> {
ident_type: IdentType, ident_type: IdentType,
} }
noop_fold_type!(Resolver<'_>);
impl<'a> Resolver<'a> { impl<'a> Resolver<'a> {
fn new(mark: Mark, current: Scope<'a>, cur_defining: Option<(JsWord, Mark)>) -> Self { fn new(mark: Mark, current: Scope<'a>, cur_defining: Option<(JsWord, Mark)>) -> Self {
Resolver { Resolver {
@ -200,6 +198,8 @@ impl<'a> Resolver<'a> {
} }
impl<'a> Fold for Resolver<'a> { impl<'a> Fold for Resolver<'a> {
noop_fold_type!();
track_ident!(); track_ident!();
fn fold_arrow_expr(&mut self, e: ArrowExpr) -> ArrowExpr { fn fold_arrow_expr(&mut self, e: ArrowExpr) -> ArrowExpr {
@ -592,6 +592,8 @@ struct Hoister<'a, 'b> {
} }
impl Fold for Hoister<'_, '_> { impl Fold for Hoister<'_, '_> {
noop_fold_type!();
fn fold_fn_decl(&mut self, node: FnDecl) -> FnDecl { fn fold_fn_decl(&mut self, node: FnDecl) -> FnDecl {
let ident = self.resolver.fold_binding_ident(node.ident); let ident = self.resolver.fold_binding_ident(node.ident);

View File

@ -1,7 +1,7 @@
use super::*; use super::*;
use crate::{ use crate::{
compat::{ compat::{
es2015::{block_scoping, destructuring, Classes}, es2015::{block_scoping, classes, destructuring},
es2020::class_properties, es2020::class_properties,
}, },
modules::common_js::common_js, modules::common_js::common_js,
@ -985,7 +985,7 @@ test!(
syntax(), syntax(),
|_| chain!( |_| chain!(
tr(), tr(),
Classes::default(), classes(),
destructuring(Default::default()), destructuring(Default::default()),
common_js(Mark::fresh(Mark::root()), Default::default()) common_js(Mark::fresh(Mark::root()), Default::default())
), ),

View File

@ -1,4 +1,4 @@
use crate::helpers::{InjectHelpers, HELPERS}; use crate::helpers::{inject_helpers, HELPERS};
use std::{ use std::{
fmt, fmt,
fs::{create_dir_all, remove_dir_all, OpenOptions}, fs::{create_dir_all, remove_dir_all, OpenOptions},
@ -14,7 +14,7 @@ use swc_ecma_ast::{Pat, *};
use swc_ecma_codegen::Emitter; use swc_ecma_codegen::Emitter;
use swc_ecma_parser::{error::Error, lexer::Lexer, Parser, StringInput, Syntax}; use swc_ecma_parser::{error::Error, lexer::Lexer, Parser, StringInput, Syntax};
use swc_ecma_utils::DropSpan; use swc_ecma_utils::DropSpan;
use swc_ecma_visit::{Fold, FoldWith}; use swc_ecma_visit::{as_folder, Fold, FoldWith};
use tempfile::tempdir_in; use tempfile::tempdir_in;
pub(crate) struct Tester<'a> { pub(crate) struct Tester<'a> {
@ -115,9 +115,9 @@ impl<'a> Tester<'a> {
let module = validate!(module) let module = validate!(module)
.fold_with(&mut tr) .fold_with(&mut tr)
.fold_with(&mut DropSpan { .fold_with(&mut as_folder(DropSpan {
preserve_ctxt: true, preserve_ctxt: true,
}) }))
.fold_with(&mut Normalizer); .fold_with(&mut Normalizer);
Ok(module) Ok(module)
@ -179,9 +179,9 @@ pub(crate) fn test_transform<F, P>(
{ {
crate::tests::Tester::run(|tester| { crate::tests::Tester::run(|tester| {
let expected = tester.apply_transform( let expected = tester.apply_transform(
::swc_ecma_utils::DropSpan { as_folder(::swc_ecma_utils::DropSpan {
preserve_ctxt: true, preserve_ctxt: true,
}, }),
"output.js", "output.js",
syntax, syntax,
expected, expected,
@ -304,7 +304,7 @@ where
_ => {} _ => {}
} }
let module = module let mut module = module
.fold_with(&mut crate::debug::validator::Validator { name: "actual-1" }) .fold_with(&mut crate::debug::validator::Validator { name: "actual-1" })
.fold_with(&mut crate::hygiene::hygiene()) .fold_with(&mut crate::hygiene::hygiene())
.fold_with(&mut crate::debug::validator::Validator { name: "actual-2" }) .fold_with(&mut crate::debug::validator::Validator { name: "actual-2" })
@ -312,7 +312,7 @@ where
.fold_with(&mut crate::debug::validator::Validator { name: "actual-3" }); .fold_with(&mut crate::debug::validator::Validator { name: "actual-3" });
let src_without_helpers = tester.print(&module); let src_without_helpers = tester.print(&module);
let module = module.fold_with(&mut InjectHelpers {}); module = module.fold_with(&mut inject_helpers());
let src = tester.print(&module); let src = tester.print(&module);
let root = Path::new(env!("CARGO_MANIFEST_DIR")) let root = Path::new(env!("CARGO_MANIFEST_DIR"))

View File

@ -609,7 +609,18 @@ impl Fold for Strip {
}) => Expr::Member(MemberExpr { }) => Expr::Member(MemberExpr {
span, span,
obj: obj.fold_with(self), obj: obj.fold_with(self),
prop: if computed { prop.fold_with(self) } else { prop }, prop: if computed {
prop.fold_with(self)
} else {
match *prop {
Expr::Ident(i) => Box::new(Expr::Ident(Ident {
optional: false,
type_ann: None,
..i
})),
_ => prop,
}
},
computed, computed,
}), }),
_ => expr.fold_children_with(self), _ => expr.fold_children_with(self),

Some files were not shown because too many files have changed in this diff Show More