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 = [
"--cfg", "procmacro2_semver_exempt",
"-Z", "thinlto=no",
"-C", "target-feature=+sse2",
]
rustdocflags = [

View File

@ -1,6 +1,6 @@
[package]
name = "swc_bundler"
version = "0.2.3"
version = "0.3.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT"
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_common = { version = "0.9", path = "../common" }
swc_ecma_ast = { version = "0.28", path = "../ecmascript/ast" }
swc_ecma_codegen = { version = "0.31", path = "../ecmascript/codegen" }
swc_ecma_parser = { version = "0.33", path = "../ecmascript/parser" }
swc_ecma_transforms = { version = "0.19", path = "../ecmascript/transforms" }
swc_ecma_utils = { version = "0.17", path = "../ecmascript/utils" }
swc_ecma_visit = { version = "0.13", path = "../ecmascript/visit" }
swc_ecma_codegen = { version = "0.32.0", path = "../ecmascript/codegen" }
swc_ecma_parser = { version = "0.34.0", path = "../ecmascript/parser" }
swc_ecma_transforms = { version = "0.20.0", path = "../ecmascript/transforms" }
swc_ecma_utils = { version = "0.18.0", path = "../ecmascript/utils" }
swc_ecma_visit = { version = "0.14.0", path = "../ecmascript/visit" }
anyhow = "1"
crc = "1.8"
radix_fmt = "1"

View File

@ -1,10 +1,10 @@
use super::merge::{LocalMarker, Unexporter};
use crate::{bundler::load::TransformedModule, Bundler, Load, ModuleId, Resolve};
use hygiene::top_level_ident_folder;
use std::iter::once;
use swc_common::DUMMY_SP;
use std::{borrow::Borrow, iter::once};
use swc_common::{SyntaxContext, DUMMY_SP};
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;
@ -112,11 +112,11 @@ where
for circular_module in circular_modules {
for (src, specifiers) in entry.imports.specifiers.iter() {
if circular_module.id == src.module_id {
module = module.fold_with(&mut LocalMarker {
module.visit_mut_with(&mut LocalMarker {
mark: circular_module.mark(),
top_level_ctxt: SyntaxContext::empty().apply_mark(self.top_level_mark),
specifiers: &specifiers,
excluded: vec![],
is_export: false,
excluded: Default::default(),
});
break;
}
@ -165,7 +165,7 @@ fn merge_respecting_order(mut entry: Vec<ModuleItem>, mut dep: Vec<ModuleItem>)
}
// 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);
new.extend(entry.drain(..=pos));
@ -192,25 +192,37 @@ fn merge_respecting_order(mut entry: Vec<ModuleItem>, mut dep: Vec<ModuleItem>)
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 };
item.visit_with(&Invalid { span: DUMMY_SP }, &mut v);
v.idx
}
struct DepFinder<'a> {
deps: &'a [ModuleItem],
struct DepFinder<'a, T>
where
T: Borrow<ModuleItem>,
{
deps: &'a [T],
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) {
if self.idx.is_some() {
return;
}
for (idx, dep) in self.deps.iter().enumerate() {
match dep {
match dep.borrow() {
ModuleItem::Stmt(Stmt::Decl(Decl::Class(decl))) => {
log::trace!(
"Decl (from dep) = {}{:?}, Ident = {}{:?}",
@ -240,4 +252,11 @@ impl Visit for DepFinder<'_> {
fn visit_class_member(&mut self, _: &ClassMember, _: &dyn Node) {}
fn visit_function(&mut self, _: &Function, _: &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 swc_common::{Mark, SyntaxContext};
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 {
MergeFolder {
@ -87,6 +87,8 @@ impl<'a> MergeFolder<'a> {
}
impl Fold for MergeFolder<'_> {
noop_fold_type!();
fn fold_class_decl(&mut self, c: ClassDecl) -> ClassDecl {
ClassDecl {
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_ecma_ast::{ModuleItem, *};
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>
where
@ -49,10 +49,8 @@ where
{
info.helpers.require.store(true, Ordering::SeqCst);
let dep = dep
.into_owned()
.fold_with(&mut Unexporter)
.fold_with(&mut ImportDropper);
let mut dep = dep.into_owned().fold_with(&mut Unexporter);
dep.visit_mut_with(&mut ImportDropper);
prepend(
&mut entry.body,
@ -150,6 +148,8 @@ struct RequireReplacer {
}
impl VisitMut for RequireReplacer {
noop_visit_mut_type!();
fn visit_mut_module_item(&mut self, node: &mut ModuleItem) {
node.visit_mut_children_with(self);
@ -173,6 +173,7 @@ impl VisitMut for RequireReplacer {
}
let mut props = vec![];
// TODO
for spec in i.specifiers.clone() {
match spec {
ImportSpecifier::Named(s) => {
@ -288,15 +289,15 @@ impl VisitMut for RequireReplacer {
struct ImportDropper;
impl Fold for ImportDropper {
fn fold_module_item(&mut self, mut i: ModuleItem) -> ModuleItem {
i = i.fold_children_with(self);
impl VisitMut for ImportDropper {
noop_visit_mut_type!();
fn visit_mut_module_item(&mut self, i: &mut ModuleItem) {
match i {
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 crate::{bundler::load::TransformedModule, Bundler, Load, ModuleId, Resolve};
use crate::{bundler::load::TransformedModule, util, Bundler, Load, ModuleId, Resolve};
use anyhow::{Context, Error};
use std::mem::{replace, take};
use swc_atoms::js_word;
use swc_common::{Spanned, SyntaxContext, DUMMY_SP};
use swc_ecma_ast::*;
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>
where
@ -15,10 +15,10 @@ where
{
pub(super) fn merge_reexports(
&self,
mut entry: Module,
entry: &mut Module,
info: &TransformedModule,
targets: &mut Vec<ModuleId>,
) -> Result<Module, Error> {
) -> Result<(), Error> {
entry.visit_mut_with(&mut DefaultRenamer);
for (src, specifiers) in &info.exports.reexports {
@ -32,6 +32,32 @@ where
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
.merge_modules(src.module_id, false, targets)
.with_context(|| {
@ -43,23 +69,6 @@ where
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 {
target_ctxt: SyntaxContext::empty().apply_mark(info.mark()),
});
@ -73,17 +82,18 @@ where
dep = dep.fold_with(&mut Unexporter);
entry.visit_mut_with(&mut ExportRenamer {
from: SyntaxContext::empty().apply_mark(imported.mark()),
to: SyntaxContext::empty().apply_mark(info.mark()),
});
Ok(dep)
})
},
);
let dep = dep?;
// print_hygiene("entry:before-injection", &self.cm, &entry);
// print_hygiene("dep:before-injection", &self.cm, &dep);
// Replace import statement / require with module body
let mut injector = ExportInjector {
imported: dep.body.clone(),
imported: dep.body,
src: src.src.clone(),
};
entry.body.visit_mut_with(&mut injector);
@ -100,7 +110,7 @@ where
assert_eq!(injector.imported, vec![]);
}
Ok(entry)
Ok(())
}
}
@ -110,6 +120,8 @@ struct ExportInjector {
}
impl VisitMut for ExportInjector {
noop_visit_mut_type!();
fn visit_mut_module_items(&mut self, orig: &mut Vec<ModuleItem>) {
let items = take(orig);
let mut buf = Vec::with_capacity(self.imported.len() + items.len());
@ -154,6 +166,8 @@ struct ExportRenamer {
}
impl VisitMut for ExportRenamer {
noop_visit_mut_type!();
fn visit_mut_named_export(&mut self, export: &mut NamedExport) {
// if export.src.is_none() {
// return;
@ -196,6 +210,8 @@ struct UnexportAsVar {
}
impl VisitMut for UnexportAsVar {
noop_visit_mut_type!();
fn visit_mut_module_item(&mut self, n: &mut ModuleItem) {
n.visit_mut_children_with(self);
@ -277,6 +293,8 @@ pub(super) struct NamedExportOrigMarker {
}
impl VisitMut for NamedExportOrigMarker {
noop_visit_mut_type!();
fn visit_mut_export_named_specifier(&mut self, s: &mut ExportNamedSpecifier) {
if s.orig.span.ctxt == self.top_level_ctxt {
s.orig.span = s.orig.span.with_ctxt(self.target_ctxt);
@ -293,6 +311,8 @@ struct AliasExports {
}
impl VisitMut for AliasExports {
noop_visit_mut_type!();
fn visit_mut_module_items(&mut self, items: &mut Vec<ModuleItem>) {
for item in items.iter_mut() {
item.visit_mut_with(self);
@ -355,6 +375,8 @@ impl VisitMut for AliasExports {
struct DefaultRenamer;
impl VisitMut for DefaultRenamer {
noop_visit_mut_type!();
fn visit_mut_export_named_specifier(&mut self, n: &mut ExportNamedSpecifier) {
if n.orig.sym == js_word!("default") {
n.orig.sym = "__default".into()

View File

@ -8,6 +8,7 @@ use crate::{
use anyhow::{Context, Error};
use std::{
borrow::Cow,
collections::HashSet,
mem::take,
ops::{Deref, DerefMut},
};
@ -15,7 +16,9 @@ use swc_atoms::{js_word, JsWord};
use swc_common::{Mark, Spanned, SyntaxContext, DUMMY_SP};
use swc_ecma_ast::*;
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>
where
@ -54,8 +57,7 @@ where
log::info!("Merge: ({}){} <= {:?}", info.id, info.fm.name, targets);
entry = self
.merge_reexports(entry, &info, targets)
self.merge_reexports(&mut entry, &info, targets)
.context("failed to merge reepxorts")?;
for (src, specifiers) in &info.imports.specifiers {
@ -71,11 +73,11 @@ where
if let Some(imported) = self.scope.get_module(src.module_id) {
// Respan using imported module's syntax context.
entry = entry.fold_with(&mut LocalMarker {
entry.visit_mut_with(&mut LocalMarker {
mark: imported.mark(),
top_level_ctxt: SyntaxContext::empty().apply_mark(self.top_level_mark),
specifiers: &specifiers,
excluded: vec![],
is_export: false,
excluded: Default::default(),
});
}
@ -177,11 +179,12 @@ where
dep = dep.fold_with(&mut Unexporter);
if !specifiers.is_empty() {
entry = entry.fold_with(&mut LocalMarker {
entry.visit_mut_with(&mut LocalMarker {
mark: imported.mark(),
top_level_ctxt: SyntaxContext::empty()
.apply_mark(self.top_level_mark),
specifiers: &specifiers,
excluded: vec![],
is_export: false,
excluded: Default::default(),
});
// // Note: this does not handle `export default
@ -196,7 +199,7 @@ where
// Replace import statement / require with module body
let mut injector = Es6ModuleInjector {
imported: dep.body.clone(),
imported: take(&mut dep.body),
src: src.src.clone(),
};
entry.body.visit_mut_with(&mut injector);
@ -206,6 +209,7 @@ where
if injector.imported.is_empty() {
continue;
}
dep.body = take(&mut injector.imported);
}
if self.config.require {
@ -244,6 +248,8 @@ where
pub(super) struct Unexporter;
impl Fold for Unexporter {
noop_fold_type!();
fn fold_module_item(&mut self, item: ModuleItem) -> ModuleItem {
match item {
ModuleItem::ModuleDecl(decl) => match decl {
@ -342,6 +348,8 @@ impl ExportRenamer<'_> {
}
impl Fold for ExportRenamer<'_> {
noop_fold_type!();
fn fold_class(&mut self, node: Class) -> Class {
node
}
@ -485,6 +493,8 @@ struct ActualMarker<'a> {
}
impl Fold for ActualMarker<'_> {
noop_fold_type!();
fn fold_expr(&mut self, node: Expr) -> Expr {
node
}
@ -515,29 +525,13 @@ impl Fold for ActualMarker<'_> {
pub(super) struct LocalMarker<'a> {
/// Mark applied to imported idents.
pub mark: Mark,
/// Syntax context of the top level items.
pub top_level_ctxt: SyntaxContext,
pub specifiers: &'a [Specifier],
pub is_export: bool,
pub excluded: Vec<Id>,
pub excluded: HashSet<Id>,
}
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, '_>
where
I: for<'any> VisitWith<DestructuringFinder<'any, Id>>,
@ -567,101 +561,77 @@ impl<'a, 'b> DerefMut for Excluder<'a, 'b> {
}
}
impl Fold for LocalMarker<'_> {
fn fold_catch_clause(&mut self, mut node: CatchClause) -> CatchClause {
impl VisitMut for LocalMarker<'_> {
noop_visit_mut_type!();
fn visit_mut_catch_clause(&mut self, node: &mut CatchClause) {
let mut f = self.exclude(&node.param);
node.body = node.body.fold_with(&mut *f);
node
node.body.visit_mut_with(&mut *f);
}
fn fold_class_decl(&mut self, mut node: ClassDecl) -> ClassDecl {
self.excluded.push((&node.ident).into());
node.class = node.class.fold_with(self);
node
fn visit_mut_class_decl(&mut self, node: &mut ClassDecl) {
self.excluded.insert((&node.ident).into());
node.class.visit_mut_with(self);
}
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);
node.class = node.class.fold_with(&mut *f);
node
node.class.visit_mut_with(&mut *f);
}
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);
node.body = node.body.fold_with(&mut *f);
node
node.body.visit_mut_with(&mut *f);
}
fn fold_fn_decl(&mut self, mut node: FnDecl) -> FnDecl {
self.excluded.push((&node.ident).into());
node.function = node.function.fold_with(self);
node
fn visit_mut_fn_decl(&mut self, node: &mut FnDecl) {
self.excluded.insert((&node.ident).into());
node.function.visit_mut_with(self);
}
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);
node.function = node.function.fold_with(&mut *f);
node
node.function.visit_mut_with(&mut *f);
}
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);
node.body = node.body.fold_with(&mut *f);
node
node.body.visit_mut_with(&mut *f);
}
fn fold_ident(&mut self, mut node: Ident) -> Ident {
if self.excluded.iter().any(|i| *i == node) {
return node;
fn visit_mut_ident(&mut self, mut node: &mut Ident) {
if node.span.ctxt != self.top_level_ctxt {
return;
}
if self.excluded.contains(&(&*node).into()) {
return;
}
// TODO: sym() => correct span
if self.is_export {
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) {
if self.specifiers.iter().any(|id| *id.local() == *node) {
node.span = node
.span
.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 {
LabeledStmt {
body: node.body.fold_with(self),
..node
}
}
fn fold_member_expr(&mut self, mut e: MemberExpr) -> MemberExpr {
e.obj = e.obj.fold_with(self);
fn visit_mut_member_expr(&mut self, e: &mut MemberExpr) {
e.obj.visit_mut_with(self);
if e.computed {
e.prop = e.prop.fold_with(self);
e.prop.visit_mut_with(self);
}
}
e
}
fn fold_setter_prop(&mut self, mut node: SetterProp) -> SetterProp {
fn visit_mut_setter_prop(&mut self, node: &mut SetterProp) {
let mut f = self.exclude(&node.param);
node.body = node.body.fold_with(&mut *f);
node
node.body.visit_mut_with(&mut *f);
}
}
@ -671,6 +641,8 @@ struct Es6ModuleInjector {
}
impl VisitMut for Es6ModuleInjector {
noop_visit_mut_type!();
fn visit_mut_module_items(&mut self, orig: &mut Vec<ModuleItem>) {
let items = take(orig);
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_ecma_ast::*;
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>
where
@ -92,6 +92,8 @@ where
L: Load,
R: Resolve,
{
noop_visit_mut_type!();
fn visit_mut_module_item(&mut self, item: &mut ModuleItem) {
match item {
// TODO: Optimize pure constants

View File

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

View File

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

View File

@ -11,7 +11,7 @@ use swc_common::{
};
use swc_ecma_ast::*;
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)]
mod tests;
@ -143,6 +143,8 @@ where
L: Load,
R: Resolve,
{
noop_fold_type!();
fn fold_import_decl(&mut self, mut import: ImportDecl) -> ImportDecl {
if !self.deglob_phase {
// Ignore if it's a core module.

View File

@ -17,7 +17,7 @@ use swc_ecma_ast::{
ModuleDecl, Str,
};
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.
#[derive(Debug, Clone)]
pub(super) struct TransformedModule {
@ -375,6 +375,8 @@ struct Es6ModuleDetector {
}
impl Visit for Es6ModuleDetector {
noop_visit_type!();
fn visit_call_expr(&mut self, e: &CallExpr, _: &dyn Node) {
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_parser::{lexer::Lexer, JscTarget, Parser, StringInput};
use swc_ecma_utils::drop_span;
use swc_ecma_visit::FoldWith;
use swc_ecma_visit::VisitMutWith;
pub(super) struct Tester<'a> {
pub cm: Lrc<SourceMap>,
@ -84,7 +84,10 @@ impl<'a> Tester<'a> {
pub fn assert_eq(&self, m: &Module, expected: &str) {
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);
assert_eq!(m, expected)

View File

@ -4,7 +4,7 @@ use std::io::{stdout, Write};
use swc_common::{sync::Lrc, SourceMap};
use swc_ecma_ast::{Ident, Module};
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) {
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;
impl Fold for HygieneVisualizer {
noop_fold_type!();
fn fold_ident(&mut self, node: Ident) -> Ident {
Ident {
sym: format!("{}{:?}", node.sym, node.span.ctxt()).into(),

View File

@ -1,6 +1,6 @@
use std::hash::Hash;
use swc_common::{Span, SyntaxContext};
use swc_ecma_visit::Fold;
use swc_ecma_visit::{noop_visit_mut_type, VisitMut};
#[derive(Debug)]
pub(crate) struct CloneMap<K, V>
@ -62,9 +62,11 @@ where
pub(crate) struct HygieneRemover;
impl Fold for HygieneRemover {
fn fold_span(&mut self, s: Span) -> Span {
s.with_ctxt(SyntaxContext::empty())
impl VisitMut for HygieneRemover {
noop_visit_mut_type!();
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`
pub trait Map<T> {
/// 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
}
}
/// Moved
pub use swc_visit::util::map::Map;

View File

@ -1,93 +1 @@
use std::{iter, ptr};
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
}
}
pub use swc_visit::util::move_map::MoveMap;

View File

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

View File

@ -1,6 +1,6 @@
[package]
name = "swc_ecma_codegen"
version = "0.31.0"
version = "0.32.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
@ -20,5 +20,5 @@ num-bigint = { version = "0.2", features = ["serde"] }
[dev-dependencies]
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" }

View File

@ -1,6 +1,6 @@
[package]
name = "jsdoc"
version = "0.1.0"
version = "0.2.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
edition = "2018"
license = "Apache-2.0/MIT"
@ -17,7 +17,7 @@ serde = { version = "1", features = ["derive"] }
[dev-dependencies]
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" }
anyhow = "1"
dashmap = "3"

View File

@ -1,6 +1,6 @@
[package]
name = "swc_ecma_parser"
version = "0.33.3"
version = "0.34.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT"
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_ecma_ast = { version = "0.28.0", path ="../ast" }
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" }
unicode-xid = "0.2"
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 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> {
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 {
noop_visit_type!();
fn visit_assign_prop(&mut self, p: &AssignProp, _: &dyn Node) {
self.errors.push((p.span(), SyntaxError::AssignProperty));
}

View File

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

View File

@ -15,7 +15,7 @@ use fxhash::FxHashSet;
use swc_atoms::{js_word, JsWord};
use swc_common::DUMMY_SP;
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 {
shipped_proposals: bool,
@ -145,6 +145,8 @@ impl UsageVisitor {
}
impl Visit for UsageVisitor {
noop_visit_type!();
/// `[a, b] = c`
fn visit_array_pat(&mut self, p: &ArrayPat, _: &dyn Node) {
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());
// ES2015
let pass = add!(pass, BlockScopedFunctions, es2015::BlockScopedFns);
let pass = add!(
pass,
TemplateLiterals,
es2015::TemplateLiteral::default(),
true
);
let pass = add!(pass, Classes, es2015::Classes::default());
let pass = add!(pass, BlockScopedFunctions, es2015::block_scoped_functions());
let pass = add!(pass, TemplateLiterals, es2015::template_literal(), true);
let pass = add!(pass, Classes, es2015::classes());
let pass = add!(
pass,
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, ArrowFunctions, es2015::arrow());
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,
let pass = add!(pass, TypeOfSymbol, es2015::TypeOfSymbol);
let pass = add!(pass, ShorthandProperties, es2015::Shorthand);
let pass = add!(pass, TypeOfSymbol, es2015::typeof_symbol());
let pass = add!(pass, ShorthandProperties, es2015::shorthand());
let pass = add!(pass, Parameters, es2015::parameters());
let pass = add!(
pass,
@ -138,15 +133,13 @@ pub fn preset_env(global_mark: Mark, c: Config) -> impl Fold {
// NamedCapturingGroupsRegex,
// ES 3
let pass = add!(pass, PropertyLiterals, es3::PropertyLiteral);
let pass = add!(pass, MemberExpressionLiterals, es3::MemberExprLit);
let pass = add!(pass, PropertyLiterals, es3::property_literals());
let pass = add!(
pass,
ReservedWords,
es3::ReservedWord {
preserve_import: c.dynamic_import
}
MemberExpressionLiterals,
es3::member_expression_literals()
);
let pass = add!(pass, ReservedWords, es3::reserved_words(c.dynamic_import));
if c.debug {
println!("Targets: {:?}", targets);

View File

@ -1,6 +1,6 @@
use swc_common::DUMMY_SP;
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 {
let mut v = RegeneratorVisitor { found: false };
@ -13,4 +13,6 @@ pub(super) struct RegeneratorVisitor {
}
/// 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_parser::{EsConfig, Parser, Syntax};
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 test::{test_main, ShouldPanic, TestDesc, TestDescAndFn, TestFn, TestName, TestType};
use testing::Tester;
@ -304,11 +304,7 @@ fn exec(c: PresetConfig, dir: PathBuf) -> Result<(), Error> {
let actual_src = print(&actual);
let expected_src = print(&expected);
if actual.fold_with(&mut DropSpan {
preserve_ctxt: false,
}) == expected.fold_with(&mut DropSpan {
preserve_ctxt: false,
}) {
if drop_span(actual) == drop_span(expected) {
return Ok(());
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,14 +1,18 @@
use crate::util::UsageFinder;
use swc_common::{Spanned, DUMMY_SP};
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)]
pub struct BlockScopedFns;
noop_fold_type!(BlockScopedFns);
struct BlockScopedFns;
impl Fold for BlockScopedFns {
noop_fold_type!();
fn fold_stmts(&mut self, items: Vec<Stmt>) -> Vec<Stmt> {
let mut 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::{
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,
}
noop_fold_type!(BlockScoping);
impl BlockScoping {
/// This methods remove [ScopeKind::Loop] and [ScopeKind::Fn], but not
/// [ScopeKind::ForLetLoop]
@ -341,6 +339,8 @@ impl BlockScoping {
}
impl Fold for BlockScoping {
noop_fold_type!();
fn fold_arrow_expr(&mut self, f: ArrowExpr) -> ArrowExpr {
ArrowExpr {
params: f.params.fold_with(self),
@ -592,9 +592,9 @@ struct InfectionFinder<'a> {
found: bool,
}
noop_visit_type!(InfectionFinder<'_>);
impl Visit for InfectionFinder<'_> {
noop_visit_type!();
fn visit_assign_expr(&mut self, node: &AssignExpr, _: &dyn Node) {
let old = self.found;
self.found = false;
@ -656,10 +656,10 @@ struct FlowHelper {
has_return: bool,
}
noop_fold_type!(FlowHelper);
/// noop
impl Fold for FlowHelper {
noop_fold_type!();
fn fold_arrow_expr(&mut self, f: ArrowExpr) -> ArrowExpr {
f
}
@ -728,9 +728,9 @@ struct FunctionFinder {
found: bool,
}
noop_visit_type!(FunctionFinder);
impl Visit for FunctionFinder {
noop_visit_type!();
fn visit_function(&mut self, _: &Function, _: &dyn Node) {
self.found = true
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
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
///
@ -35,12 +35,16 @@ use swc_ecma_visit::{Fold, FoldWith};
/// }
/// };
/// ```
#[derive(Default, Clone, Copy)]
pub struct Shorthand;
pub fn shorthand() -> impl 'static + Fold {
Shorthand
}
noop_fold_type!(Shorthand);
#[derive(Clone, Copy)]
struct Shorthand;
impl Fold for Shorthand {
noop_fold_type!();
fn fold_prop(&mut self, prop: Prop) -> Prop {
let prop = prop.fold_children_with(self);

View File

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

View File

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

View File

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

View File

@ -2,31 +2,18 @@ use crate::util::ExprFactory;
use swc_atoms::js_word;
use swc_common::DUMMY_SP;
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)]
pub struct TypeOfSymbol;
noop_fold_type!(TypeOfSymbol);
struct TypeOfSymbol;
impl Fold for TypeOfSymbol {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr {
// fast path
if !should_work(&expr) {
@ -87,6 +74,8 @@ fn should_work(node: &Expr) -> bool {
found: bool,
}
impl Visit for Visitor {
noop_visit_type!();
fn visit_unary_expr(&mut self, e: &UnaryExpr, _: &dyn Node) {
if e.op == op!("typeof") {
self.found = true

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,15 +1,15 @@
use crate::util::ExprFactory;
use swc_common::DUMMY_SP;
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 class_name: &'a Ident,
}
noop_fold_type!(ClassNameTdzFolder<'_>);
impl<'a> Fold for ClassNameTdzFolder<'a> {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr {
match expr {
Expr::Ident(i) => {

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@ use crate::util::{alias_if_required, undefined, StmtLike};
use std::mem::replace;
use swc_common::DUMMY_SP;
use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith};
use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
#[cfg(test)]
mod tests;
@ -43,6 +43,8 @@ impl NullishCoalescing {
}
impl Fold for NullishCoalescing {
noop_fold_type!();
fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> {
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 swc_common::{Spanned, DUMMY_SP};
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 {
OptChaining::default()
@ -13,9 +13,9 @@ struct OptChaining {
vars: Vec<VarDeclarator>,
}
noop_fold_type!(OptChaining);
impl Fold for OptChaining {
noop_fold_type!();
fn fold_expr(&mut self, e: Expr) -> Expr {
let e = match e {
Expr::OptChain(e) => Expr::Cond(validate!(self.unwrap(e))),

View File

@ -1,5 +1,6 @@
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_ecma_visit::Fold;
@ -11,8 +12,8 @@ mod reserved_word;
/// Make output es3-compatible.
pub fn es3(preserve_import: bool) -> impl Fold {
chain!(
PropertyLiteral,
MemberExprLit,
ReservedWord { preserve_import }
property_literals(),
member_expression_literals(),
reserved_words(preserve_import)
)
}

View File

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

View File

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

View File

@ -1,5 +1,5 @@
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`
///
@ -18,14 +18,16 @@ use swc_ecma_visit::{Fold, FoldWith};
/// var _abstract = 1;
/// var x = _abstract + 1;
/// ```
#[derive(Default, Clone, Copy)]
pub struct ReservedWord {
pub fn reserved_words(preserve_import: bool) -> impl Fold {
ReservedWord { preserve_import }
}
struct ReservedWord {
pub preserve_import: bool,
}
noop_fold_type!(ReservedWord);
impl Fold for ReservedWord {
noop_fold_type!();
fn fold_export_specifier(&mut self, n: ExportSpecifier) -> ExportSpecifier {
n
}

View File

@ -1,6 +1,6 @@
use swc_atoms::JsWord;
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 {
EsReservedWord {}
@ -8,9 +8,9 @@ pub fn reserved_words() -> impl 'static + Fold {
struct EsReservedWord {}
noop_fold_type!(EsReservedWord);
impl Fold for EsReservedWord {
noop_fold_type!();
fn fold_export_specifier(&mut self, n: ExportSpecifier) -> ExportSpecifier {
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_parser::{lexer::Lexer, Parser, StringInput};
use swc_ecma_utils::HANDLER;
use swc_ecma_visit::{Fold, FoldWith};
use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
pub fn const_modules(
cm: Lrc<SourceMap>,
@ -76,14 +76,14 @@ struct ConstModules {
scope: Scope,
}
noop_fold_type!(ConstModules);
#[derive(Default)]
struct Scope {
imported: HashMap<JsWord, Arc<Expr>>,
}
impl Fold for ConstModules {
noop_fold_type!();
fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> {
items.move_flat_map(|item| match item {
ModuleItem::ModuleDecl(ModuleDecl::Import(import)) => {

View File

@ -9,7 +9,7 @@ use swc_common::{
Span, Spanned,
};
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 {
Fixer {
@ -29,8 +29,6 @@ struct Fixer<'a> {
span_map: FxHashMap<Span, Span>,
}
noop_fold_type!(Fixer);
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Context {
@ -70,6 +68,8 @@ macro_rules! array {
}
impl Fold for Fixer<'_> {
noop_fold_type!();
array!(fold_array_lit, ArrayLit);
// array!(ArrayPat);

View File

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

View File

@ -8,7 +8,7 @@ use std::{cell::RefCell, collections::HashMap};
use swc_atoms::JsWord;
use swc_common::{chain, Span, SyntaxContext};
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;
#[cfg(test)]
@ -21,8 +21,6 @@ struct Hygiene<'a> {
ident_type: IdentType,
}
noop_fold_type!(Hygiene<'_>);
type Contexts = SmallVec<[SyntaxContext; 32]>;
impl<'a> Hygiene<'a> {
@ -141,23 +139,25 @@ impl<'a> Hygiene<'a> {
}
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!(
Hygiene {
current: Default::default(),
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> {
fn apply_ops<N>(&mut self, node: N) -> N
where
@ -485,6 +485,8 @@ macro_rules! track_ident {
}
impl<'a> Fold for Hygiene<'a> {
noop_fold_type!();
track_ident!();
fn fold_arrow_expr(&mut self, mut node: ArrowExpr) -> ArrowExpr {

View File

@ -1,7 +1,7 @@
use swc_atoms::JsWord;
use swc_common::{util::move_map::MoveMap, Spanned, SyntaxContext, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith};
use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
#[derive(Debug)]
pub(super) enum ScopeOp {
@ -13,9 +13,9 @@ pub(super) enum ScopeOp {
pub(super) struct Operator<'a>(pub &'a [ScopeOp]);
noop_fold_type!(Operator<'_>);
impl<'a> Fold for Operator<'a> {
noop_fold_type!();
fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> {
let mut stmts = Vec::with_capacity(items.len());
@ -287,6 +287,8 @@ struct VarFolder<'a, 'b> {
}
impl Fold for VarFolder<'_, '_> {
noop_fold_type!();
fn fold_expr(&mut self, n: Expr) -> Expr {
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_common::{Mark, DUMMY_SP};
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 {
Amd {
@ -27,8 +27,6 @@ struct Amd {
exports: Exports,
}
noop_fold_type!(Amd);
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct Config {
@ -40,6 +38,8 @@ pub struct Config {
}
impl Fold for Amd {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr {
let top_level = self.in_top_level;

View File

@ -8,7 +8,7 @@ use fxhash::FxHashSet;
use swc_atoms::js_word;
use swc_common::{Mark, DUMMY_SP};
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 {
CommonJs {
@ -26,9 +26,9 @@ struct CommonJs {
in_top_level: bool,
}
noop_fold_type!(CommonJs);
impl Fold for CommonJs {
noop_fold_type!();
fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> {
let mut emitted_esmodule = false;
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_common::DUMMY_SP;
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 {
ImportAnalyzer {
@ -15,10 +15,9 @@ struct ImportAnalyzer {
scope: Scope,
}
noop_fold_type!(ImportAnalyzer);
noop_visit_type!(ImportAnalyzer);
impl Fold for ImportAnalyzer {
noop_fold_type!();
fn fold_module(&mut self, module: Module) -> Module {
self.visit_module(&module, &Invalid { span: DUMMY_SP } as _);
@ -35,6 +34,8 @@ impl Fold for ImportAnalyzer {
}
impl Visit for ImportAnalyzer {
noop_visit_type!();
fn visit_export_all(&mut self, export: &ExportAll, _parent: &dyn Node) {
*self
.scope

View File

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

View File

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

View File

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

View File

@ -10,7 +10,7 @@ use swc_common::{
Spanned, DUMMY_SP,
};
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)]
mod tests;
@ -44,9 +44,9 @@ struct Remover {
normal_block: bool,
}
noop_fold_type!(Remover);
impl Fold for Remover {
noop_fold_type!();
fn fold_array_pat(&mut self, p: ArrayPat) -> ArrayPat {
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 {
noop_visit_type!();
fn visit_switch_case(&mut self, node: &SwitchCase, _: &dyn Node) {
let old = self.in_cond;
self.in_cond = true;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,12 +1,14 @@
use swc_common::{util::move_map::MoveMap, Spanned, DUMMY_SP};
use swc_ecma_ast::*;
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
pub(super) struct ParamMetadata;
impl Fold for ParamMetadata {
noop_fold_type!();
fn fold_class(&mut self, mut cls: Class) -> Class {
cls = cls.fold_children_with(self);
let mut decorators = cls.decorators;
@ -120,6 +122,8 @@ pub(super) struct Metadata<'a> {
}
impl Fold for Metadata<'_> {
noop_fold_type!();
fn fold_class(&mut self, mut c: Class) -> Class {
c = c.fold_children_with(self);

View File

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

View File

@ -1,7 +1,7 @@
use crate::util::IdentExt;
use swc_common::DUMMY_SP;
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-namespace-from`
@ -12,9 +12,9 @@ pub fn export() -> impl Fold {
#[derive(Clone)]
struct ExportDefaultFrom;
noop_fold_type!(ExportDefaultFrom);
impl Fold for ExportDefaultFrom {
noop_fold_type!();
fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> {
// Imports
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_common::DUMMY_SP;
use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith};
use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
#[cfg(test)]
mod tests;
@ -17,9 +17,9 @@ pub fn display_name() -> impl Fold {
struct DisplayName;
noop_fold_type!(DisplayName);
impl Fold for DisplayName {
noop_fold_type!();
fn fold_assign_expr(&mut self, expr: AssignExpr) -> AssignExpr {
let expr = expr.fold_children_with(self);
@ -123,6 +123,8 @@ struct Folder {
}
impl Fold for Folder {
noop_fold_type!();
/// Don't recurse into array.
fn fold_array_lit(&mut self, node: ArrayLit) -> ArrayLit {
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_ecma_ast::*;
use swc_ecma_parser::{Parser, StringInput, Syntax};
use swc_ecma_visit::{Fold, FoldWith};
use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
#[cfg(test)]
mod tests;
@ -105,8 +105,6 @@ struct Jsx {
throw_if_namespace: bool,
}
noop_fold_type!(Jsx);
impl Jsx {
fn jsx_frag_to_expr(&mut self, el: JSXFragment) -> Expr {
let span = el.span();
@ -255,6 +253,8 @@ impl Jsx {
}
impl Fold for Jsx {
noop_fold_type!();
fn fold_expr(&mut self, expr: Expr) -> Expr {
let mut expr = expr.fold_children_with(self);

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
use super::*;
use crate::{
compat::{
es2015::{block_scoping, destructuring, Classes},
es2015::{block_scoping, classes, destructuring},
es2020::class_properties,
},
modules::common_js::common_js,
@ -985,7 +985,7 @@ test!(
syntax(),
|_| chain!(
tr(),
Classes::default(),
classes(),
destructuring(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::{
fmt,
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_parser::{error::Error, lexer::Lexer, Parser, StringInput, Syntax};
use swc_ecma_utils::DropSpan;
use swc_ecma_visit::{Fold, FoldWith};
use swc_ecma_visit::{as_folder, Fold, FoldWith};
use tempfile::tempdir_in;
pub(crate) struct Tester<'a> {
@ -115,9 +115,9 @@ impl<'a> Tester<'a> {
let module = validate!(module)
.fold_with(&mut tr)
.fold_with(&mut DropSpan {
.fold_with(&mut as_folder(DropSpan {
preserve_ctxt: true,
})
}))
.fold_with(&mut Normalizer);
Ok(module)
@ -179,9 +179,9 @@ pub(crate) fn test_transform<F, P>(
{
crate::tests::Tester::run(|tester| {
let expected = tester.apply_transform(
::swc_ecma_utils::DropSpan {
as_folder(::swc_ecma_utils::DropSpan {
preserve_ctxt: true,
},
}),
"output.js",
syntax,
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::hygiene::hygiene())
.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" });
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 root = Path::new(env!("CARGO_MANIFEST_DIR"))

View File

@ -609,7 +609,18 @@ impl Fold for Strip {
}) => Expr::Member(MemberExpr {
span,
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,
}),
_ => expr.fold_children_with(self),

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