mirror of
https://github.com/swc-project/swc.git
synced 2024-12-28 08:04:43 +03:00
Fixes (#283)
swc_ecma_transforms: - Remove State / Clone - Fix hygiene bug of labels (#281) - Fix sequence expression in unary expression (#282)
This commit is contained in:
parent
892b4f01cd
commit
cdf4a09e65
@ -17,7 +17,6 @@ chashmap = "2.2.0"
|
||||
either = "1.5"
|
||||
fxhash = "0.2"
|
||||
lazy_static = "1"
|
||||
objekt = "0.1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
indexmap = "1"
|
||||
ordered-float = "1.0.1"
|
||||
|
@ -56,11 +56,10 @@ mod tests;
|
||||
/// };
|
||||
/// console.log(bob.printFriends());
|
||||
/// ```
|
||||
pub fn arrow() -> impl Pass + Clone + Copy {
|
||||
pub fn arrow() -> impl Pass {
|
||||
Arrow
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Arrow;
|
||||
|
||||
impl Fold<Expr> for Arrow {
|
||||
|
@ -2,11 +2,10 @@ use crate::pass::Pass;
|
||||
use ast::*;
|
||||
use swc_common::{Fold, FoldWith};
|
||||
|
||||
pub fn block_scoping() -> impl Pass + Clone + Copy {
|
||||
pub fn block_scoping() -> impl Pass {
|
||||
BlockScoping
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct BlockScoping;
|
||||
|
||||
impl Fold<VarDecl> for BlockScoping {
|
||||
|
@ -39,11 +39,10 @@ mod tests;
|
||||
///
|
||||
/// TODO(kdy1): cache reference like (_f = f, mutatorMap[_f].get = function(){})
|
||||
/// instead of (mutatorMap[f].get = function(){}
|
||||
pub fn computed_properties() -> impl Pass + Clone + Copy {
|
||||
pub fn computed_properties() -> impl Pass {
|
||||
ComputedProps
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Copy)]
|
||||
struct ComputedProps;
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -31,11 +31,10 @@ mod tests;
|
||||
/// b = _arr2[1],
|
||||
/// rest = _arr2.slice(2);
|
||||
/// ```
|
||||
pub fn destructuring() -> impl Pass + Clone + Copy {
|
||||
pub fn destructuring() -> impl Pass {
|
||||
Destructuring
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Destructuring;
|
||||
|
||||
macro_rules! impl_for_for_stmt {
|
||||
|
@ -7,11 +7,10 @@ use swc_common::{Fold, FoldWith, Spanned};
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub fn duplicate_keys() -> impl Pass + Clone + Copy {
|
||||
pub fn duplicate_keys() -> impl Pass {
|
||||
DuplicateKeys
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Copy)]
|
||||
struct DuplicateKeys;
|
||||
|
||||
impl Fold<Expr> for DuplicateKeys {
|
||||
|
@ -42,11 +42,10 @@ mod tests;
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn for_of() -> impl Pass + Clone + Copy {
|
||||
pub fn for_of() -> impl Pass {
|
||||
ForOf
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct ForOf;
|
||||
|
||||
/// Real folder.
|
||||
|
@ -27,7 +27,7 @@ mod sticky_regex;
|
||||
mod template_literal;
|
||||
mod typeof_symbol;
|
||||
|
||||
fn exprs() -> impl Pass + Clone {
|
||||
fn exprs() -> impl Pass {
|
||||
chain_at!(
|
||||
Expr,
|
||||
arrow(),
|
||||
@ -40,12 +40,12 @@ fn exprs() -> impl Pass + Clone {
|
||||
)
|
||||
}
|
||||
|
||||
fn stmts() -> impl Pass + Clone {
|
||||
fn stmts() -> impl Pass {
|
||||
chain_at!(Stmt, function_name(), exprs(),)
|
||||
}
|
||||
|
||||
/// Compiles es2015 to es5.
|
||||
pub fn es2015() -> impl Pass + Clone {
|
||||
pub fn es2015() -> impl Pass {
|
||||
chain_at!(
|
||||
Module,
|
||||
BlockScopedFns,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{scope::ScopeKind, util::State};
|
||||
use crate::scope::{IdentType, ScopeKind};
|
||||
use ast::*;
|
||||
use fxhash::FxHashSet;
|
||||
use swc_atoms::JsWord;
|
||||
@ -45,12 +45,11 @@ impl<'a> Scope<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Resolver<'a> {
|
||||
mark: State<Mark>,
|
||||
current: State<Scope<'a>>,
|
||||
cur_defining: State<Option<(JsWord, Mark)>>,
|
||||
in_var_decl: State<bool>,
|
||||
mark: Mark,
|
||||
current: Scope<'a>,
|
||||
cur_defining: Option<(JsWord, Mark)>,
|
||||
ident_type: IdentType,
|
||||
}
|
||||
|
||||
impl<'a> Resolver<'a> {
|
||||
@ -59,13 +58,13 @@ impl<'a> Resolver<'a> {
|
||||
mark: mark.into(),
|
||||
current: current.into(),
|
||||
cur_defining: cur_defining.into(),
|
||||
in_var_decl: false.into(),
|
||||
ident_type: IdentType::Ref,
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_for(&self, sym: &JsWord) -> Option<Mark> {
|
||||
let mut mark = self.mark.value;
|
||||
let mut scope = Some(&self.current.value);
|
||||
let mut mark = self.mark;
|
||||
let mut scope = Some(&self.current);
|
||||
|
||||
while let Some(cur) = scope {
|
||||
if cur.declared_symbols.contains(sym) {
|
||||
@ -90,15 +89,14 @@ impl<'a> Resolver<'a> {
|
||||
return ident;
|
||||
}
|
||||
|
||||
let (should_insert, mark) = if let Some((ref cur, override_mark)) = self.cur_defining.value
|
||||
{
|
||||
let (should_insert, mark) = if let Some((ref cur, override_mark)) = self.cur_defining {
|
||||
if *cur != ident.sym {
|
||||
(true, self.mark.value)
|
||||
(true, self.mark)
|
||||
} else {
|
||||
(false, override_mark)
|
||||
}
|
||||
} else {
|
||||
(true, self.mark.value)
|
||||
(true, self.mark)
|
||||
};
|
||||
|
||||
if should_insert {
|
||||
@ -122,7 +120,7 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
impl<'a> Fold<Function> for Resolver<'a> {
|
||||
fn fold(&mut self, mut f: Function) -> Function {
|
||||
let child_mark = Mark::fresh(self.mark.value);
|
||||
let child_mark = Mark::fresh(self.mark);
|
||||
|
||||
// Child folder
|
||||
let mut folder = Resolver::new(
|
||||
@ -131,10 +129,10 @@ impl<'a> Fold<Function> for Resolver<'a> {
|
||||
self.cur_defining.take(),
|
||||
);
|
||||
|
||||
folder.in_var_decl = true.into();
|
||||
folder.ident_type = IdentType::Binding;
|
||||
f.params = f.params.fold_with(&mut folder);
|
||||
|
||||
folder.in_var_decl = false.into();
|
||||
folder.ident_type = IdentType::Ref;
|
||||
f.body = f.body.map(|stmt| stmt.fold_children(&mut folder));
|
||||
|
||||
self.cur_defining = folder.cur_defining;
|
||||
@ -145,7 +143,7 @@ impl<'a> Fold<Function> for Resolver<'a> {
|
||||
|
||||
impl<'a> Fold<BlockStmt> for Resolver<'a> {
|
||||
fn fold(&mut self, block: BlockStmt) -> BlockStmt {
|
||||
let child_mark = Mark::fresh(*self.mark);
|
||||
let child_mark = Mark::fresh(self.mark);
|
||||
|
||||
let mut child_folder = Resolver::new(
|
||||
child_mark,
|
||||
@ -189,8 +187,8 @@ impl<'a> Fold<FnDecl> for Resolver<'a> {
|
||||
|
||||
impl<'a> Fold<Expr> for Resolver<'a> {
|
||||
fn fold(&mut self, expr: Expr) -> Expr {
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = false.into();
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Ref;
|
||||
let expr = match expr {
|
||||
// Leftmost one of a member expression shoukld be resolved.
|
||||
Expr::Member(me) => {
|
||||
@ -209,7 +207,7 @@ impl<'a> Fold<Expr> for Resolver<'a> {
|
||||
}
|
||||
_ => expr.fold_children(self),
|
||||
};
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
self.ident_type = old;
|
||||
|
||||
expr
|
||||
}
|
||||
@ -219,13 +217,13 @@ impl<'a> Fold<VarDeclarator> for Resolver<'a> {
|
||||
fn fold(&mut self, decl: VarDeclarator) -> VarDeclarator {
|
||||
// order is important
|
||||
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = true.into();
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Binding;
|
||||
let name = decl.name.fold_with(self);
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
self.ident_type = old;
|
||||
|
||||
let cur_name = match name {
|
||||
Pat::Ident(Ident { ref sym, .. }) => Some((sym.clone(), *self.mark)),
|
||||
Pat::Ident(Ident { ref sym, .. }) => Some((sym.clone(), self.mark)),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
@ -265,31 +263,36 @@ impl<'a> Fold<VarDeclarator> for Resolver<'a> {
|
||||
|
||||
impl<'a> Fold<Ident> for Resolver<'a> {
|
||||
fn fold(&mut self, i: Ident) -> Ident {
|
||||
if self.in_var_decl.value {
|
||||
self.fold_binding_ident(i)
|
||||
} else {
|
||||
let Ident { span, sym, .. } = i;
|
||||
match self.ident_type {
|
||||
IdentType::Binding => self.fold_binding_ident(i),
|
||||
IdentType::Ref => {
|
||||
let Ident { span, sym, .. } = i;
|
||||
|
||||
if cfg!(debug_assertions) && LOG {
|
||||
eprintln!("resolver: IdentRef {}{:?}", sym, i.span.ctxt());
|
||||
}
|
||||
|
||||
if span.ctxt() != SyntaxContext::empty() {
|
||||
return Ident { sym, ..i };
|
||||
}
|
||||
|
||||
if let Some(mark) = self.mark_for(&sym) {
|
||||
if cfg!(debug_assertions) && LOG {
|
||||
eprintln!("\t -> {:?}", mark);
|
||||
eprintln!("resolver: IdentRef {}{:?}", sym, i.span.ctxt());
|
||||
}
|
||||
Ident {
|
||||
sym,
|
||||
span: span.apply_mark(mark),
|
||||
..i
|
||||
|
||||
if span.ctxt() != SyntaxContext::empty() {
|
||||
return Ident { sym, ..i };
|
||||
}
|
||||
} else {
|
||||
// Cannot resolve reference. (TODO: Report error)
|
||||
Ident { sym, span, ..i }
|
||||
|
||||
if let Some(mark) = self.mark_for(&sym) {
|
||||
if cfg!(debug_assertions) && LOG {
|
||||
eprintln!("\t -> {:?}", mark);
|
||||
}
|
||||
Ident {
|
||||
sym,
|
||||
span: span.apply_mark(mark),
|
||||
..i
|
||||
}
|
||||
} else {
|
||||
// Cannot resolve reference. (TODO: Report error)
|
||||
Ident { sym, span, ..i }
|
||||
}
|
||||
}
|
||||
IdentType::Label => {
|
||||
// We currently does not touch labels
|
||||
i
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -299,10 +302,10 @@ track_ident!(Resolver);
|
||||
|
||||
impl<'a> Fold<ArrowExpr> for Resolver<'a> {
|
||||
fn fold(&mut self, e: ArrowExpr) -> ArrowExpr {
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = true.into();
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Binding;
|
||||
let params = e.params.fold_with(self);
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
self.ident_type = old;
|
||||
|
||||
let body = e.body.fold_with(self);
|
||||
|
||||
|
@ -612,3 +612,23 @@ identical!(
|
||||
scope.startOperation = startOperation;
|
||||
}"
|
||||
);
|
||||
|
||||
identical!(
|
||||
issue_281_01,
|
||||
"function foo(e) {
|
||||
e: { break e; }
|
||||
}"
|
||||
);
|
||||
|
||||
identical!(
|
||||
issue_281_02,
|
||||
"function foo(e) {
|
||||
e: {
|
||||
try {
|
||||
} catch (e1) {
|
||||
o = null;
|
||||
break e
|
||||
}
|
||||
}
|
||||
}"
|
||||
);
|
||||
|
@ -9,7 +9,7 @@ use swc_common::{util::move_map::MoveMap, Fold, FoldWith, Span, Spanned, DUMMY_S
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub fn spread() -> impl Pass + Clone {
|
||||
pub fn spread() -> impl Pass {
|
||||
Spread
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ use swc_common::{Fold, FoldWith, Span, Spanned, Visit, VisitWith, DUMMY_SP};
|
||||
///
|
||||
/// x = Math.pow(x, 3);
|
||||
/// ```
|
||||
pub fn exponentation() -> impl Pass + Clone {
|
||||
pub fn exponentation() -> impl Pass {
|
||||
Exponentation
|
||||
}
|
||||
#[derive(Clone, Copy)]
|
||||
|
@ -3,6 +3,6 @@ use crate::pass::Pass;
|
||||
|
||||
mod exponentation;
|
||||
|
||||
pub fn es2016() -> impl Pass + Clone {
|
||||
pub fn es2016() -> impl Pass {
|
||||
exponentation()
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ mod tests;
|
||||
/// yield bar();
|
||||
/// });
|
||||
/// ```
|
||||
pub fn async_to_generator() -> impl Pass + Clone {
|
||||
pub fn async_to_generator() -> impl Pass {
|
||||
AsyncToGenerator
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,6 @@ use crate::pass::Pass;
|
||||
|
||||
mod async_to_generator;
|
||||
|
||||
pub fn es2017() -> impl Pass + Clone {
|
||||
pub fn es2017() -> impl Pass {
|
||||
async_to_generator()
|
||||
}
|
||||
|
@ -4,6 +4,6 @@ use crate::pass::Pass;
|
||||
|
||||
mod object_rest_spread;
|
||||
|
||||
pub fn es2018() -> impl Pass + Clone {
|
||||
pub fn es2018() -> impl Pass {
|
||||
object_rest_spread()
|
||||
}
|
||||
|
@ -12,11 +12,10 @@ use swc_common::{
|
||||
mod tests;
|
||||
|
||||
/// `@babel/plugin-proposal-object-rest-spread`
|
||||
pub fn object_rest_spread() -> impl Pass + Clone {
|
||||
pub fn object_rest_spread() -> impl Pass {
|
||||
chain!(ObjectRest, ObjectSpread)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ObjectRest;
|
||||
|
||||
struct RestFolder {
|
||||
@ -880,7 +879,6 @@ fn simplify_pat(pat: Pat) -> Pat {
|
||||
pat.fold_with(&mut PatSimplifier)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ObjectSpread;
|
||||
|
||||
impl Fold<Expr> for ObjectSpread {
|
||||
|
@ -9,6 +9,6 @@ mod prop_lits;
|
||||
mod reserved_word;
|
||||
|
||||
/// Make output es3-compatible.
|
||||
pub fn es3() -> impl Pass + Clone {
|
||||
pub fn es3() -> impl Pass {
|
||||
chain_at!(Expr, PropertyLiteral, MemberExprLit, ReservedWord)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
pass::Pass,
|
||||
util::{drop_span, State, CM, SESSION},
|
||||
util::{drop_span, CM, SESSION},
|
||||
};
|
||||
use ast::*;
|
||||
use chashmap::CHashMap;
|
||||
@ -10,7 +10,7 @@ use swc_atoms::JsWord;
|
||||
use swc_common::{util::move_map::MoveMap, FileName, Fold, FoldWith};
|
||||
use swc_ecma_parser::{Parser, SourceFileInput, Syntax};
|
||||
|
||||
pub fn const_modules(globals: FxHashMap<JsWord, FxHashMap<JsWord, String>>) -> impl Pass + Clone {
|
||||
pub fn const_modules(globals: FxHashMap<JsWord, FxHashMap<JsWord, String>>) -> impl Pass {
|
||||
ConstModules {
|
||||
globals: globals
|
||||
.into_iter()
|
||||
@ -67,10 +67,9 @@ fn parse_option(name: &str, src: String) -> Arc<Expr> {
|
||||
expr
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ConstModules {
|
||||
globals: FxHashMap<JsWord, FxHashMap<JsWord, Arc<Expr>>>,
|
||||
scope: State<Scope>,
|
||||
scope: Scope,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@ -78,7 +77,10 @@ struct Scope {
|
||||
imported: FxHashMap<JsWord, Arc<Expr>>,
|
||||
}
|
||||
|
||||
impl Fold<Vec<ModuleItem>> for ConstModules {
|
||||
impl Fold<Vec<ModuleItem>> for ConstModules
|
||||
where
|
||||
Vec<ModuleItem>: FoldWith<Self>,
|
||||
{
|
||||
fn fold(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> {
|
||||
items.move_flat_map(|item| match item {
|
||||
ModuleItem::ModuleDecl(ModuleDecl::Import(import)) => {
|
||||
@ -101,7 +103,7 @@ impl Fold<Vec<ModuleItem>> for ConstModules {
|
||||
import.src.value, i.sym
|
||||
)
|
||||
});
|
||||
self.scope.value.imported.insert(i.sym.clone(), value);
|
||||
self.scope.imported.insert(i.sym.clone(), value);
|
||||
}
|
||||
|
||||
None
|
||||
|
@ -1,22 +1,18 @@
|
||||
use crate::{
|
||||
pass::Pass,
|
||||
util::{ExprFactory, State},
|
||||
};
|
||||
use crate::{pass::Pass, util::ExprFactory};
|
||||
use ast::*;
|
||||
use swc_common::{
|
||||
util::{map::Map, move_map::MoveMap},
|
||||
Fold, FoldWith,
|
||||
};
|
||||
|
||||
pub fn fixer() -> impl Pass + Clone {
|
||||
pub fn fixer() -> impl Pass {
|
||||
Fixer {
|
||||
ctx: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Fixer {
|
||||
ctx: State<Context>,
|
||||
ctx: Context,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@ -298,7 +294,7 @@ impl Fold<Expr> for Fixer {
|
||||
Expr::Seq(SeqExpr { span, exprs: buf })
|
||||
};
|
||||
|
||||
match self.ctx.value {
|
||||
match self.ctx {
|
||||
Context::ForcedExpr { .. } => Expr::Paren(ParenExpr {
|
||||
span,
|
||||
expr: box expr,
|
||||
@ -373,7 +369,9 @@ impl Fold<Expr> for Fixer {
|
||||
|
||||
Expr::Unary(expr) => {
|
||||
let arg = match *expr.arg {
|
||||
Expr::Assign(..) | Expr::Bin(..) => box expr.arg.wrap_with_paren(),
|
||||
Expr::Assign(..) | Expr::Bin(..) | Expr::Seq(..) => {
|
||||
box expr.arg.wrap_with_paren()
|
||||
}
|
||||
_ => expr.arg,
|
||||
};
|
||||
|
||||
@ -406,7 +404,7 @@ impl Fold<Expr> for Fixer {
|
||||
callee: ExprOrSuper::Expr(callee @ box Expr::Fn(_)),
|
||||
args,
|
||||
type_args,
|
||||
}) => match self.ctx.value {
|
||||
}) => match self.ctx {
|
||||
Context::ForcedExpr { .. } => Expr::Call(CallExpr {
|
||||
span,
|
||||
callee: callee.as_callee(),
|
||||
@ -658,4 +656,10 @@ function a() {
|
||||
"e.hasOwnProperty(a) && (t = e[a] ? this[a] = t(n) : 'target' === a ? this.target = r : \
|
||||
this[a] = n[a]);"
|
||||
);
|
||||
|
||||
identical!(
|
||||
issue_282,
|
||||
"!(A = [], B = (function () { return classNames; }).apply(exports, A), B !== undefined && \
|
||||
(module.exports = B));"
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
use self::ops::{Operator, ScopeOp};
|
||||
use crate::{pass::Pass, scope::ScopeKind, util::State};
|
||||
use crate::{
|
||||
pass::Pass,
|
||||
scope::{IdentType, ScopeKind},
|
||||
};
|
||||
use ast::*;
|
||||
use fxhash::FxHashMap;
|
||||
use std::cell::RefCell;
|
||||
@ -12,10 +15,9 @@ mod tests;
|
||||
|
||||
const LOG: bool = false;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Hygiene<'a> {
|
||||
current: State<Scope<'a>>,
|
||||
in_var_decl: State<bool>,
|
||||
current: Scope<'a>,
|
||||
ident_type: IdentType,
|
||||
}
|
||||
|
||||
impl<'a> Hygiene<'a> {
|
||||
@ -112,7 +114,7 @@ impl<'a> Hygiene<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hygiene() -> impl Pass + Clone + 'static {
|
||||
pub fn hygiene() -> impl Pass + 'static {
|
||||
#[derive(Clone, Copy)]
|
||||
struct MarkClearer;
|
||||
impl Fold<Span> for MarkClearer {
|
||||
@ -125,7 +127,7 @@ pub fn hygiene() -> impl Pass + Clone + 'static {
|
||||
Module,
|
||||
Hygiene {
|
||||
current: Default::default(),
|
||||
in_var_decl: Default::default(),
|
||||
ident_type: IdentType::Ref,
|
||||
},
|
||||
MarkClearer
|
||||
)
|
||||
@ -168,7 +170,7 @@ impl<'a> Fold<BlockStmt> for Hygiene<'a> {
|
||||
fn fold(&mut self, node: BlockStmt) -> BlockStmt {
|
||||
let mut folder = Hygiene {
|
||||
current: Scope::new(ScopeKind::Block, Some(&self.current)).into(),
|
||||
in_var_decl: false.into(),
|
||||
ident_type: IdentType::Ref,
|
||||
};
|
||||
let node = node.fold_children(&mut folder);
|
||||
|
||||
@ -187,13 +189,13 @@ impl<'a> Hygiene<'a> {
|
||||
|
||||
let mut folder = Hygiene {
|
||||
current: Scope::new(ScopeKind::Fn, Some(&self.current)).into(),
|
||||
in_var_decl: false.into(),
|
||||
ident_type: IdentType::Ref,
|
||||
};
|
||||
|
||||
folder.in_var_decl = true.into();
|
||||
folder.ident_type = IdentType::Binding;
|
||||
node.params = node.params.fold_with(&mut folder);
|
||||
|
||||
folder.in_var_decl = false.into();
|
||||
folder.ident_type = IdentType::Ref;
|
||||
node.body = node.body.map(|stmt| stmt.fold_children(&mut folder));
|
||||
|
||||
folder.apply_ops(node)
|
||||
@ -202,10 +204,10 @@ impl<'a> Hygiene<'a> {
|
||||
|
||||
impl<'a> Fold<VarDeclarator> for Hygiene<'a> {
|
||||
fn fold(&mut self, decl: VarDeclarator) -> VarDeclarator {
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = true.into();
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Binding;
|
||||
let name = decl.name.fold_with(self);
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
self.ident_type = old;
|
||||
|
||||
let init = decl.init.fold_with(self);
|
||||
VarDeclarator { name, init, ..decl }
|
||||
@ -231,10 +233,15 @@ impl<'a> Fold<FnDecl> for Hygiene<'a> {
|
||||
impl<'a> Fold<Ident> for Hygiene<'a> {
|
||||
/// Invoked for `IdetifierRefrence` / `BindingIdentifier`
|
||||
fn fold(&mut self, i: Ident) -> Ident {
|
||||
if self.in_var_decl.value {
|
||||
self.add_declared_ref(i.clone())
|
||||
} else {
|
||||
self.add_used_ref(i.clone());
|
||||
match self.ident_type {
|
||||
IdentType::Binding => self.add_declared_ref(i.clone()),
|
||||
IdentType::Ref => {
|
||||
self.add_used_ref(i.clone());
|
||||
}
|
||||
IdentType::Label => {
|
||||
// We currently does not touch labels
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
i
|
||||
@ -243,8 +250,8 @@ impl<'a> Fold<Ident> for Hygiene<'a> {
|
||||
|
||||
impl<'a> Fold<Expr> for Hygiene<'a> {
|
||||
fn fold(&mut self, node: Expr) -> Expr {
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = false.into();
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Ref;
|
||||
let node = match node {
|
||||
Expr::Ident(..) => node.fold_children(self),
|
||||
Expr::Member(e) => {
|
||||
@ -267,7 +274,7 @@ impl<'a> Fold<Expr> for Hygiene<'a> {
|
||||
_ => node.fold_children(self),
|
||||
};
|
||||
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
self.ident_type = old;
|
||||
|
||||
node
|
||||
}
|
||||
@ -411,12 +418,12 @@ macro_rules! track_ident {
|
||||
($T:tt) => {
|
||||
impl<'a> Fold<ExportSpecifier> for $T<'a> {
|
||||
fn fold(&mut self, s: ExportSpecifier) -> ExportSpecifier {
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = false.into();
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Ref;
|
||||
|
||||
let s = s.fold_children(self);
|
||||
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
self.ident_type = old;
|
||||
|
||||
s
|
||||
}
|
||||
@ -424,8 +431,8 @@ macro_rules! track_ident {
|
||||
|
||||
impl<'a> Fold<ImportSpecifier> for $T<'a> {
|
||||
fn fold(&mut self, s: ImportSpecifier) -> ImportSpecifier {
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = true.into();
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Binding;
|
||||
|
||||
let s = match s {
|
||||
ImportSpecifier::Specific(ImportSpecific { imported: None, .. })
|
||||
@ -437,7 +444,7 @@ macro_rules! track_ident {
|
||||
}),
|
||||
};
|
||||
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
self.ident_type = old;
|
||||
|
||||
s
|
||||
}
|
||||
@ -445,10 +452,10 @@ macro_rules! track_ident {
|
||||
|
||||
impl<'a> Fold<Constructor> for $T<'a> {
|
||||
fn fold(&mut self, c: Constructor) -> Constructor {
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = true.into();
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Binding;
|
||||
let params = c.params.fold_with(self);
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
self.ident_type = old;
|
||||
|
||||
let body = c.body.fold_with(self);
|
||||
let key = c.key.fold_with(self);
|
||||
@ -464,10 +471,10 @@ macro_rules! track_ident {
|
||||
|
||||
impl<'a> Fold<SetterProp> for $T<'a> {
|
||||
fn fold(&mut self, f: SetterProp) -> SetterProp {
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = true.into();
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Binding;
|
||||
let param = f.param.fold_with(self);
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
self.ident_type = old;
|
||||
|
||||
let body = f.body.fold_with(self);
|
||||
|
||||
@ -485,16 +492,51 @@ macro_rules! track_ident {
|
||||
|
||||
impl<'a> Fold<CatchClause> for $T<'a> {
|
||||
fn fold(&mut self, c: CatchClause) -> CatchClause {
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = true.into();
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Binding;
|
||||
let param = c.param.fold_with(self);
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
self.ident_type = old;
|
||||
|
||||
let body = c.body.fold_with(self);
|
||||
|
||||
CatchClause { param, body, ..c }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<LabeledStmt> for $T<'a> {
|
||||
fn fold(&mut self, s: LabeledStmt) -> LabeledStmt {
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Label;
|
||||
let label = s.label.fold_with(self);
|
||||
self.ident_type = old;
|
||||
|
||||
let body = s.body.fold_with(self);
|
||||
|
||||
LabeledStmt { label, body, ..s }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<BreakStmt> for $T<'a> {
|
||||
fn fold(&mut self, s: BreakStmt) -> BreakStmt {
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Label;
|
||||
let label = s.label.fold_with(self);
|
||||
self.ident_type = old;
|
||||
|
||||
BreakStmt { label, ..s }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<ContinueStmt> for $T<'a> {
|
||||
fn fold(&mut self, s: ContinueStmt) -> ContinueStmt {
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Label;
|
||||
let label = s.label.fold_with(self);
|
||||
self.ident_type = old;
|
||||
|
||||
ContinueStmt { label, ..s }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -504,13 +546,13 @@ impl<'a> Fold<ArrowExpr> for Hygiene<'a> {
|
||||
fn fold(&mut self, mut node: ArrowExpr) -> ArrowExpr {
|
||||
let mut folder = Hygiene {
|
||||
current: Scope::new(ScopeKind::Fn, Some(&self.current)).into(),
|
||||
in_var_decl: false.into(),
|
||||
ident_type: IdentType::Ref,
|
||||
};
|
||||
|
||||
folder.in_var_decl = true.into();
|
||||
folder.ident_type = IdentType::Binding;
|
||||
node.params = node.params.fold_with(&mut folder);
|
||||
|
||||
folder.in_var_decl = false.into();
|
||||
folder.ident_type = IdentType::Ref;
|
||||
node.body = node.body.fold_with(&mut folder);
|
||||
|
||||
folder.apply_ops(node)
|
||||
|
@ -1004,3 +1004,62 @@ fn module_03() {
|
||||
export {foo1 as foo}",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_281_01() {
|
||||
test_module(
|
||||
|tester| {
|
||||
let mark1 = Mark::fresh(Mark::root());
|
||||
|
||||
Ok(tester
|
||||
.parse_module(
|
||||
"actual1.js",
|
||||
"label: {
|
||||
break label
|
||||
}",
|
||||
)?
|
||||
.fold_with(&mut OnceMarker::new(&[("label", &[mark1, mark1])])))
|
||||
},
|
||||
"label: {
|
||||
break label
|
||||
}",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_281_02() {
|
||||
test_module(
|
||||
|tester| {
|
||||
let mark1 = Mark::fresh(Mark::root());
|
||||
let mark2 = Mark::fresh(Mark::root());
|
||||
let mark3 = Mark::fresh(Mark::root());
|
||||
|
||||
Ok(tester
|
||||
.parse_module(
|
||||
"actual1.js",
|
||||
"function foo(e) {
|
||||
e: {
|
||||
try {
|
||||
} catch (e) {
|
||||
o = null;
|
||||
break e
|
||||
}
|
||||
}
|
||||
}",
|
||||
)?
|
||||
.fold_with(&mut OnceMarker::new(&[(
|
||||
"e",
|
||||
&[mark1, mark2, mark3, mark2],
|
||||
)])))
|
||||
},
|
||||
"function foo(e) {
|
||||
e: {
|
||||
try {
|
||||
} catch (e1) {
|
||||
o = null;
|
||||
break e
|
||||
}
|
||||
}
|
||||
}",
|
||||
);
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ extern crate test;
|
||||
#[macro_use]
|
||||
extern crate testing;
|
||||
extern crate either;
|
||||
extern crate objekt;
|
||||
extern crate serde;
|
||||
extern crate unicode_xid;
|
||||
|
||||
|
@ -4,7 +4,7 @@ use super::util::{
|
||||
};
|
||||
use crate::{
|
||||
pass::Pass,
|
||||
util::{prepend_stmts, var::VarCollector, DestructuringFinder, ExprFactory, State},
|
||||
util::{prepend_stmts, var::VarCollector, DestructuringFinder, ExprFactory},
|
||||
};
|
||||
use ast::*;
|
||||
use fxhash::FxHashSet;
|
||||
@ -15,7 +15,7 @@ use swc_common::{Fold, FoldWith, Mark, VisitWith, DUMMY_SP};
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub fn amd(config: Config) -> impl Pass + Clone {
|
||||
pub fn amd(config: Config) -> impl Pass {
|
||||
Amd {
|
||||
config,
|
||||
in_top_level: Default::default(),
|
||||
@ -24,12 +24,11 @@ pub fn amd(config: Config) -> impl Pass + Clone {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Amd {
|
||||
config: Config,
|
||||
in_top_level: State<bool>,
|
||||
scope: State<Scope>,
|
||||
exports: State<Exports>,
|
||||
in_top_level: bool,
|
||||
scope: Scope,
|
||||
exports: Exports,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
@ -45,7 +44,7 @@ pub struct Config {
|
||||
impl Fold<Module> for Amd {
|
||||
fn fold(&mut self, module: Module) -> Module {
|
||||
let items = module.body;
|
||||
self.in_top_level = true.into();
|
||||
self.in_top_level = true;
|
||||
|
||||
// Inserted after initializing exported names to undefined.
|
||||
let mut extra_stmts = vec![];
|
||||
@ -59,7 +58,7 @@ impl Fold<Module> for Amd {
|
||||
let mut export_alls = vec![];
|
||||
let mut emitted_esmodule = false;
|
||||
let mut has_export = false;
|
||||
let exports_ident = self.exports.value.0.clone();
|
||||
let exports_ident = self.exports.0.clone();
|
||||
|
||||
// Process items
|
||||
for item in items {
|
||||
@ -110,7 +109,6 @@ impl Fold<Module> for Amd {
|
||||
|
||||
ModuleDecl::ExportAll(ref export) => {
|
||||
self.scope
|
||||
.value
|
||||
.import_types
|
||||
.entry(export.src.value.clone())
|
||||
.and_modify(|v| *v = true);
|
||||
@ -166,7 +164,7 @@ impl Fold<Module> for Amd {
|
||||
extra_stmts.push(Stmt::Decl(Decl::Var(var.clone().fold_with(self))));
|
||||
|
||||
var.decls.visit_with(&mut VarCollector {
|
||||
to: &mut self.scope.value.declared_vars,
|
||||
to: &mut self.scope.declared_vars,
|
||||
});
|
||||
|
||||
let mut found = vec![];
|
||||
@ -292,7 +290,7 @@ impl Fold<Module> for Amd {
|
||||
let is_import_default = orig.sym == js_word!("default");
|
||||
|
||||
let key = (orig.sym.clone(), orig.span.ctxt());
|
||||
if self.scope.value.declared_vars.contains(&key) {
|
||||
if self.scope.declared_vars.contains(&key) {
|
||||
self.scope
|
||||
.exported_vars
|
||||
.entry(key.clone())
|
||||
@ -448,7 +446,7 @@ impl Fold<Module> for Amd {
|
||||
)));
|
||||
}
|
||||
|
||||
for (src, import) in self.scope.value.imports.drain(..) {
|
||||
for (src, import) in self.scope.imports.drain(..) {
|
||||
let import = import.unwrap_or_else(|| {
|
||||
(
|
||||
local_name_for_src(&src),
|
||||
@ -464,7 +462,7 @@ impl Fold<Module> for Amd {
|
||||
|
||||
{
|
||||
// handle interop
|
||||
let ty = self.scope.value.import_types.get(&src);
|
||||
let ty = self.scope.import_types.get(&src);
|
||||
|
||||
match ty {
|
||||
Some(&wildcard) => {
|
||||
@ -541,12 +539,11 @@ impl Fold<Module> for Amd {
|
||||
|
||||
impl Fold<Expr> for Amd {
|
||||
fn fold(&mut self, expr: Expr) -> Expr {
|
||||
let exports_ident = self.exports.value.0.clone();
|
||||
let exports_ident = self.exports.0.clone();
|
||||
|
||||
macro_rules! entry {
|
||||
($i:expr) => {
|
||||
self.scope
|
||||
.value
|
||||
.exported_vars
|
||||
.entry(($i.sym.clone(), $i.span.ctxt()))
|
||||
};
|
||||
@ -573,13 +570,12 @@ impl Fold<Expr> for Amd {
|
||||
|
||||
match expr {
|
||||
Expr::Ident(i) => {
|
||||
let v = self.scope.value.idents.get(&(i.sym.clone(), i.span.ctxt()));
|
||||
let v = self.scope.idents.get(&(i.sym.clone(), i.span.ctxt()));
|
||||
match v {
|
||||
None => return Expr::Ident(i),
|
||||
Some((src, prop)) => {
|
||||
let (ident, span) = self
|
||||
.scope
|
||||
.value
|
||||
.imports
|
||||
.get(src)
|
||||
.as_ref()
|
||||
@ -739,7 +735,7 @@ impl Fold<VarDecl> for Amd {
|
||||
fn fold(&mut self, var: VarDecl) -> VarDecl {
|
||||
if var.kind != VarDeclKind::Const {
|
||||
var.decls.visit_with(&mut VarCollector {
|
||||
to: &mut self.scope.value.declared_vars,
|
||||
to: &mut self.scope.declared_vars,
|
||||
});
|
||||
}
|
||||
|
||||
@ -756,11 +752,11 @@ impl ModulePass for Amd {
|
||||
}
|
||||
|
||||
fn scope(&self) -> &Scope {
|
||||
&self.scope.value
|
||||
&self.scope
|
||||
}
|
||||
|
||||
fn scope_mut(&mut self) -> &mut Scope {
|
||||
&mut self.scope.value
|
||||
&mut self.scope
|
||||
}
|
||||
}
|
||||
mark_as_nested!(Amd);
|
||||
|
@ -5,7 +5,7 @@ use super::util::{
|
||||
};
|
||||
use crate::{
|
||||
pass::Pass,
|
||||
util::{var::VarCollector, DestructuringFinder, ExprFactory, State},
|
||||
util::{var::VarCollector, DestructuringFinder, ExprFactory},
|
||||
};
|
||||
use ast::*;
|
||||
use fxhash::FxHashSet;
|
||||
@ -14,7 +14,7 @@ use swc_common::{Fold, FoldWith, VisitWith, DUMMY_SP};
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub fn common_js(config: Config) -> impl Pass + Clone {
|
||||
pub fn common_js(config: Config) -> impl Pass {
|
||||
CommonJs {
|
||||
config,
|
||||
scope: Default::default(),
|
||||
@ -22,11 +22,10 @@ pub fn common_js(config: Config) -> impl Pass + Clone {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct CommonJs {
|
||||
config: Config,
|
||||
scope: State<Scope>,
|
||||
in_top_level: State<bool>,
|
||||
scope: Scope,
|
||||
in_top_level: bool,
|
||||
}
|
||||
|
||||
impl Fold<Vec<ModuleItem>> for CommonJs {
|
||||
@ -46,7 +45,7 @@ impl Fold<Vec<ModuleItem>> for CommonJs {
|
||||
let mut export_alls = vec![];
|
||||
|
||||
for item in items {
|
||||
self.in_top_level = true.into();
|
||||
self.in_top_level = true;
|
||||
|
||||
match item {
|
||||
ModuleItem::ModuleDecl(ModuleDecl::Import(import)) => {
|
||||
@ -91,7 +90,6 @@ impl Fold<Vec<ModuleItem>> for CommonJs {
|
||||
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportAll(ref export)) => {
|
||||
self.scope
|
||||
.value
|
||||
.import_types
|
||||
.entry(export.src.value.clone())
|
||||
.and_modify(|v| *v = true);
|
||||
@ -106,10 +104,7 @@ impl Fold<Vec<ModuleItem>> for CommonJs {
|
||||
|
||||
match item {
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportAll(export)) => {
|
||||
self.scope
|
||||
.value
|
||||
.lazy_blacklist
|
||||
.insert(export.src.value.clone());
|
||||
self.scope.lazy_blacklist.insert(export.src.value.clone());
|
||||
|
||||
export_alls.push(export);
|
||||
}
|
||||
@ -157,7 +152,7 @@ impl Fold<Vec<ModuleItem>> for CommonJs {
|
||||
))));
|
||||
|
||||
var.decls.visit_with(&mut VarCollector {
|
||||
to: &mut self.scope.value.declared_vars,
|
||||
to: &mut self.scope.declared_vars,
|
||||
});
|
||||
|
||||
let mut found = vec![];
|
||||
@ -299,7 +294,7 @@ impl Fold<Vec<ModuleItem>> for CommonJs {
|
||||
let is_import_default = orig.sym == js_word!("default");
|
||||
|
||||
let key = (orig.sym.clone(), orig.span.ctxt());
|
||||
if self.scope.value.declared_vars.contains(&key) {
|
||||
if self.scope.declared_vars.contains(&key) {
|
||||
self.scope
|
||||
.exported_vars
|
||||
.entry(key.clone())
|
||||
@ -324,7 +319,7 @@ impl Fold<Vec<ModuleItem>> for CommonJs {
|
||||
}
|
||||
|
||||
let lazy = if let Some(ref src) = export.src {
|
||||
if self.scope.value.lazy_blacklist.contains(&src.value) {
|
||||
if self.scope.lazy_blacklist.contains(&src.value) {
|
||||
false
|
||||
} else {
|
||||
self.config.lazy.is_lazy(&src.value)
|
||||
@ -332,12 +327,11 @@ impl Fold<Vec<ModuleItem>> for CommonJs {
|
||||
} else {
|
||||
match self
|
||||
.scope
|
||||
.value
|
||||
.idents
|
||||
.get(&(orig.sym.clone(), orig.span.ctxt()))
|
||||
{
|
||||
Some((ref src, _)) => {
|
||||
if self.scope.value.lazy_blacklist.contains(src) {
|
||||
if self.scope.lazy_blacklist.contains(src) {
|
||||
false
|
||||
} else {
|
||||
self.config.lazy.is_lazy(src)
|
||||
@ -350,7 +344,6 @@ impl Fold<Vec<ModuleItem>> for CommonJs {
|
||||
let is_reexport = export.src.is_some()
|
||||
|| self
|
||||
.scope
|
||||
.value
|
||||
.idents
|
||||
.contains_key(&(orig.sym.clone(), orig.span.ctxt()));
|
||||
|
||||
@ -479,8 +472,8 @@ impl Fold<Vec<ModuleItem>> for CommonJs {
|
||||
))));
|
||||
}
|
||||
|
||||
for (src, import) in self.scope.value.imports.drain(..) {
|
||||
let lazy = if self.scope.value.lazy_blacklist.contains(&src) {
|
||||
for (src, import) in self.scope.imports.drain(..) {
|
||||
let lazy = if self.scope.lazy_blacklist.contains(&src) {
|
||||
false
|
||||
} else {
|
||||
self.config.lazy.is_lazy(&src)
|
||||
@ -490,7 +483,7 @@ impl Fold<Vec<ModuleItem>> for CommonJs {
|
||||
|
||||
match import {
|
||||
Some(import) => {
|
||||
let ty = self.scope.value.import_types.get(&src);
|
||||
let ty = self.scope.import_types.get(&src);
|
||||
|
||||
let rhs = match ty {
|
||||
Some(true) if !self.config.no_interop => box Expr::Call(CallExpr {
|
||||
@ -599,7 +592,7 @@ impl Fold<Vec<ModuleItem>> for CommonJs {
|
||||
|
||||
impl Fold<Expr> for CommonJs {
|
||||
fn fold(&mut self, expr: Expr) -> Expr {
|
||||
let top_level = self.in_top_level.value;
|
||||
let top_level = self.in_top_level;
|
||||
Scope::fold_expr(self, quote_ident!("exports"), top_level, expr)
|
||||
}
|
||||
}
|
||||
@ -610,7 +603,7 @@ impl Fold<VarDecl> for CommonJs {
|
||||
fn fold(&mut self, var: VarDecl) -> VarDecl {
|
||||
if var.kind != VarDeclKind::Const {
|
||||
var.decls.visit_with(&mut VarCollector {
|
||||
to: &mut self.scope.value.declared_vars,
|
||||
to: &mut self.scope.declared_vars,
|
||||
});
|
||||
}
|
||||
|
||||
@ -627,11 +620,11 @@ impl ModulePass for CommonJs {
|
||||
}
|
||||
|
||||
fn scope(&self) -> &Scope {
|
||||
&self.scope.value
|
||||
&self.scope
|
||||
}
|
||||
|
||||
fn scope_mut(&mut self) -> &mut Scope {
|
||||
&mut self.scope.value
|
||||
&mut self.scope
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,25 +1,24 @@
|
||||
use super::util::Scope;
|
||||
use crate::{pass::Pass, util::State};
|
||||
use crate::pass::Pass;
|
||||
use ast::*;
|
||||
use swc_common::{Fold, Visit, VisitWith};
|
||||
|
||||
pub fn import_analyzer() -> impl Pass + Clone {
|
||||
pub fn import_analyzer() -> impl Pass {
|
||||
ImportAnalyzer {
|
||||
scope: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Inject required helpers methods **for** module transform passes.
|
||||
#[derive(Clone)]
|
||||
struct ImportAnalyzer {
|
||||
scope: State<Scope>,
|
||||
scope: Scope,
|
||||
}
|
||||
|
||||
impl Fold<Module> for ImportAnalyzer {
|
||||
fn fold(&mut self, module: Module) -> Module {
|
||||
module.visit_with(self);
|
||||
|
||||
for (_, ty) in self.scope.value.import_types.drain() {
|
||||
for (_, ty) in self.scope.import_types.drain() {
|
||||
match ty {
|
||||
true => {
|
||||
enable_helper!(interop_require_wildcard);
|
||||
@ -38,7 +37,6 @@ impl Visit<ExportAll> for ImportAnalyzer {
|
||||
fn visit(&mut self, export: &ExportAll) {
|
||||
*self
|
||||
.scope
|
||||
.value
|
||||
.import_types
|
||||
.entry(export.src.value.clone())
|
||||
.or_default() = true
|
||||
|
@ -6,7 +6,7 @@ use super::util::{
|
||||
};
|
||||
use crate::{
|
||||
pass::Pass,
|
||||
util::{prepend_stmts, var::VarCollector, DestructuringFinder, ExprFactory, State},
|
||||
util::{prepend_stmts, var::VarCollector, DestructuringFinder, ExprFactory},
|
||||
};
|
||||
use ast::*;
|
||||
use fxhash::FxHashSet;
|
||||
@ -17,7 +17,7 @@ mod config;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub fn umd(cm: Arc<SourceMap>, config: Config) -> impl Pass + Clone {
|
||||
pub fn umd(cm: Arc<SourceMap>, config: Config) -> impl Pass {
|
||||
Umd {
|
||||
config: config.build(cm.clone()),
|
||||
cm,
|
||||
@ -28,13 +28,12 @@ pub fn umd(cm: Arc<SourceMap>, config: Config) -> impl Pass + Clone {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Umd {
|
||||
cm: Arc<SourceMap>,
|
||||
in_top_level: State<bool>,
|
||||
in_top_level: bool,
|
||||
config: BuiltConfig,
|
||||
scope: State<Scope>,
|
||||
exports: State<Exports>,
|
||||
scope: Scope,
|
||||
exports: Exports,
|
||||
}
|
||||
|
||||
impl Fold<Module> for Umd {
|
||||
@ -57,7 +56,7 @@ impl Fold<Module> for Umd {
|
||||
let mut export_alls = vec![];
|
||||
let mut emitted_esmodule = false;
|
||||
let mut has_export = false;
|
||||
let exports_ident = self.exports.value.0.clone();
|
||||
let exports_ident = self.exports.0.clone();
|
||||
|
||||
// Process items
|
||||
for item in items {
|
||||
@ -108,7 +107,6 @@ impl Fold<Module> for Umd {
|
||||
|
||||
ModuleDecl::ExportAll(ref export) => {
|
||||
self.scope
|
||||
.value
|
||||
.import_types
|
||||
.entry(export.src.value.clone())
|
||||
.and_modify(|v| *v = true);
|
||||
@ -164,7 +162,7 @@ impl Fold<Module> for Umd {
|
||||
extra_stmts.push(Stmt::Decl(Decl::Var(var.clone().fold_with(self))));
|
||||
|
||||
var.decls.visit_with(&mut VarCollector {
|
||||
to: &mut self.scope.value.declared_vars,
|
||||
to: &mut self.scope.declared_vars,
|
||||
});
|
||||
|
||||
let mut found = vec![];
|
||||
@ -284,7 +282,7 @@ impl Fold<Module> for Umd {
|
||||
let is_import_default = orig.sym == js_word!("default");
|
||||
|
||||
let key = (orig.sym.clone(), orig.span.ctxt());
|
||||
if self.scope.value.declared_vars.contains(&key) {
|
||||
if self.scope.declared_vars.contains(&key) {
|
||||
self.scope
|
||||
.exported_vars
|
||||
.entry(key.clone())
|
||||
@ -444,7 +442,7 @@ impl Fold<Module> for Umd {
|
||||
)));
|
||||
}
|
||||
|
||||
for (src, import) in self.scope.value.imports.drain(..) {
|
||||
for (src, import) in self.scope.imports.drain(..) {
|
||||
let global_ident = Ident::new(self.config.global_name(&src), DUMMY_SP);
|
||||
let import = import.unwrap_or_else(|| {
|
||||
(
|
||||
@ -463,7 +461,7 @@ impl Fold<Module> for Umd {
|
||||
|
||||
{
|
||||
// handle interop
|
||||
let ty = self.scope.value.import_types.get(&src);
|
||||
let ty = self.scope.import_types.get(&src);
|
||||
|
||||
match ty {
|
||||
Some(&wildcard) => {
|
||||
@ -657,8 +655,8 @@ impl Fold<Module> for Umd {
|
||||
|
||||
impl Fold<Expr> for Umd {
|
||||
fn fold(&mut self, expr: Expr) -> Expr {
|
||||
let exports = self.exports.value.0.clone();
|
||||
let top_level = self.in_top_level.value;
|
||||
let exports = self.exports.0.clone();
|
||||
let top_level = self.in_top_level;
|
||||
|
||||
Scope::fold_expr(self, exports, top_level, expr)
|
||||
}
|
||||
@ -670,7 +668,7 @@ impl Fold<VarDecl> for Umd {
|
||||
fn fold(&mut self, var: VarDecl) -> VarDecl {
|
||||
if var.kind != VarDeclKind::Const {
|
||||
var.decls.visit_with(&mut VarCollector {
|
||||
to: &mut self.scope.value.declared_vars,
|
||||
to: &mut self.scope.declared_vars,
|
||||
});
|
||||
}
|
||||
|
||||
@ -687,11 +685,11 @@ impl ModulePass for Umd {
|
||||
}
|
||||
|
||||
fn scope(&self) -> &Scope {
|
||||
&self.scope.value
|
||||
&self.scope
|
||||
}
|
||||
|
||||
fn scope_mut(&mut self) -> &mut Scope {
|
||||
&mut self.scope.value
|
||||
&mut self.scope
|
||||
}
|
||||
}
|
||||
mark_as_nested!(Umd);
|
||||
|
@ -2,8 +2,7 @@ use ast::*;
|
||||
use std::marker::PhantomData;
|
||||
use swc_common::{Fold, FoldWith};
|
||||
|
||||
pub fn noop() -> impl Pass + Clone + Copy {
|
||||
#[derive(Clone, Copy)]
|
||||
pub fn noop() -> impl Pass {
|
||||
struct Noop;
|
||||
impl<T> Fold<T> for Noop
|
||||
where
|
||||
@ -58,9 +57,9 @@ macro_rules! mk_trait {
|
||||
/// Crazy trait to make traversal fast again.
|
||||
///
|
||||
/// Note that pass.clone() should create a fresh pass.
|
||||
pub trait Pass: objekt::Clone + $( ::swc_common::Fold<$T> + )* {}
|
||||
pub trait Pass: $( ::swc_common::Fold<$T> + )* {}
|
||||
impl<P> Pass for P
|
||||
where P: ?Sized + objekt::Clone + $( ::swc_common::Fold<$T> +)*{
|
||||
where P: ?Sized + $( ::swc_common::Fold<$T> +)*{
|
||||
|
||||
}
|
||||
|
||||
@ -69,8 +68,6 @@ macro_rules! mk_trait {
|
||||
)*
|
||||
};
|
||||
}
|
||||
objekt::clone_trait_object!(Pass);
|
||||
objekt::clone_trait_object!(Pass + Send + Sync);
|
||||
|
||||
mk_trait!(
|
||||
// ArrayLit,
|
||||
@ -175,23 +172,13 @@ mk_trait!(
|
||||
* VarDeclOrPat, */
|
||||
);
|
||||
|
||||
#[derive(Debug, Copy)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct JoinedPass<A, B, N> {
|
||||
pub first: A,
|
||||
pub second: B,
|
||||
pub ty: PhantomData<N>,
|
||||
}
|
||||
|
||||
impl<A: Pass, B: Pass, N> Clone for JoinedPass<A, B, N> {
|
||||
fn clone(&self) -> Self {
|
||||
JoinedPass {
|
||||
first: objekt::clone(&self.first),
|
||||
second: objekt::clone(&self.second),
|
||||
ty: self.ty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fn type_name<T>() -> String {
|
||||
// format!("{}", unsafe { std::intrinsics::type_name::<T>() })
|
||||
// }
|
||||
|
@ -28,7 +28,7 @@ mod used_name;
|
||||
/// # Impl note
|
||||
///
|
||||
/// We use custom helper to handle export defaul class
|
||||
pub fn class_properties() -> impl Pass + Clone {
|
||||
pub fn class_properties() -> impl Pass {
|
||||
ClassProperties { mark: Mark::root() }
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ mod tests;
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn decorators() -> impl Pass + Clone {
|
||||
pub fn decorators() -> impl Pass {
|
||||
Decorators {
|
||||
is_in_strict: false,
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ mod tests;
|
||||
|
||||
/// `@babel/plugin-proposal-export-default-from` and
|
||||
/// `@babel/plugin-proposal-export-namespace-from`
|
||||
pub fn export() -> impl Pass + Clone {
|
||||
pub fn export() -> impl Pass {
|
||||
ExportDefaultFrom
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,10 @@ mod tests;
|
||||
/// `@babel/plugin-transform-react-display-name`
|
||||
///
|
||||
/// Add displayName to React.createClass calls
|
||||
pub fn display_name() -> impl Pass + Clone + Copy {
|
||||
pub fn display_name() -> impl Pass {
|
||||
DisplayName
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct DisplayName;
|
||||
|
||||
impl Fold<VarDeclarator> for DisplayName {
|
||||
|
@ -92,7 +92,7 @@ fn parse_option(name: &str, src: String) -> Box<Expr> {
|
||||
/// `@babel/plugin-transform-react-jsx`
|
||||
///
|
||||
/// Turn JSX into React function calls
|
||||
pub fn jsx(options: Options) -> impl Pass + Clone {
|
||||
pub fn jsx(options: Options) -> impl Pass {
|
||||
Jsx {
|
||||
pragma: ExprOrSuper::Expr(parse_option("pragma", options.pragma)),
|
||||
pragma_frag: ExprOrSpread {
|
||||
@ -103,7 +103,6 @@ pub fn jsx(options: Options) -> impl Pass + Clone {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Jsx {
|
||||
pragma: ExprOrSuper,
|
||||
pragma_frag: ExprOrSpread,
|
||||
|
@ -8,10 +8,9 @@ mod tests;
|
||||
/// `@babel/plugin-transform-react-jsx-self`
|
||||
///
|
||||
/// Add a __self prop to all JSX Elements
|
||||
pub fn jsx_self(dev: bool) -> impl Pass + Clone + Copy {
|
||||
pub fn jsx_self(dev: bool) -> impl Pass {
|
||||
JsxSelf { dev }
|
||||
}
|
||||
#[derive(Clone, Copy)]
|
||||
struct JsxSelf {
|
||||
dev: bool,
|
||||
}
|
||||
|
@ -7,11 +7,10 @@ use swc_common::{FileName, Fold, SourceMap, DUMMY_SP};
|
||||
mod tests;
|
||||
|
||||
/// `@babel/plugin-transform-react-jsx-source`
|
||||
pub fn jsx_src(dev: bool, cm: Arc<SourceMap>) -> impl Pass + Clone {
|
||||
pub fn jsx_src(dev: bool, cm: Arc<SourceMap>) -> impl Pass {
|
||||
JsxSrc { cm, dev }
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct JsxSrc {
|
||||
cm: Arc<SourceMap>,
|
||||
dev: bool,
|
||||
|
@ -16,7 +16,7 @@ mod jsx_src;
|
||||
/// `@babel/preset-react`
|
||||
///
|
||||
/// Preset for all React plugins.
|
||||
pub fn react(cm: Arc<SourceMap>, options: Options) -> impl Pass + Clone {
|
||||
pub fn react(cm: Arc<SourceMap>, options: Options) -> impl Pass {
|
||||
let Options { development, .. } = options;
|
||||
|
||||
chain!(
|
||||
|
@ -3,3 +3,10 @@ pub enum ScopeKind {
|
||||
Block,
|
||||
Fn,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum IdentType {
|
||||
Binding,
|
||||
Ref,
|
||||
Label,
|
||||
}
|
||||
|
@ -8,11 +8,10 @@ mod expr;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub fn simplifier() -> impl Pass + Clone + Copy + 'static {
|
||||
pub fn simplifier() -> impl Pass + 'static {
|
||||
Simplifier
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Copy)]
|
||||
struct Simplifier;
|
||||
|
||||
impl<T: StmtLike> Fold<Vec<T>> for Simplifier
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
pass::Pass,
|
||||
util::{prepend_stmts, var::VarCollector, ExprFactory, State},
|
||||
util::{prepend_stmts, var::VarCollector, ExprFactory},
|
||||
};
|
||||
use ast::*;
|
||||
use fxhash::FxHashMap;
|
||||
@ -13,15 +13,15 @@ use swc_common::{
|
||||
mod tests;
|
||||
|
||||
/// Strips type annotations out.
|
||||
pub fn strip() -> impl Pass + Clone {
|
||||
pub fn strip() -> impl Pass {
|
||||
Strip::default()
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Default)]
|
||||
struct Strip {
|
||||
non_top_level: State<bool>,
|
||||
scope: State<Scope>,
|
||||
phase: State<Phase>,
|
||||
non_top_level: bool,
|
||||
scope: Scope,
|
||||
phase: Phase,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
@ -57,18 +57,13 @@ struct DeclInfo {
|
||||
impl Strip {
|
||||
fn handle_decl(&mut self, decl: &Decl) {
|
||||
// We don't care about stuffs which cannot be exported
|
||||
if self.non_top_level.value {
|
||||
if self.non_top_level {
|
||||
return;
|
||||
}
|
||||
|
||||
macro_rules! store {
|
||||
($sym:expr, $ctxt:expr, $concrete:expr) => {{
|
||||
let entry = self
|
||||
.scope
|
||||
.value
|
||||
.decls
|
||||
.entry(($sym.clone(), $ctxt))
|
||||
.or_default();
|
||||
let entry = self.scope.decls.entry(($sym.clone(), $ctxt)).or_default();
|
||||
|
||||
if $concrete {
|
||||
entry.has_concrete = true
|
||||
@ -267,11 +262,7 @@ impl Fold<Vec<ModuleItem>> for Strip {
|
||||
|
||||
export.specifiers.retain(|s| match *s {
|
||||
ExportSpecifier::Named(NamedExportSpecifier { ref orig, .. }) => {
|
||||
if let Some(e) = self
|
||||
.scope
|
||||
.value
|
||||
.decls
|
||||
.get(&(orig.sym.clone(), orig.span.ctxt()))
|
||||
if let Some(e) = self.scope.decls.get(&(orig.sym.clone(), orig.span.ctxt()))
|
||||
{
|
||||
e.has_concrete
|
||||
} else {
|
||||
@ -299,12 +290,11 @@ impl Fold<Vec<ModuleItem>> for Strip {
|
||||
|
||||
impl Fold<ImportDecl> for Strip {
|
||||
fn fold(&mut self, mut import: ImportDecl) -> ImportDecl {
|
||||
match self.phase.value {
|
||||
match self.phase {
|
||||
Phase::Analysis => {
|
||||
macro_rules! store {
|
||||
($i:expr) => {{
|
||||
self.scope
|
||||
.value
|
||||
.imported_idents
|
||||
.insert(($i.sym.clone(), $i.span.ctxt()), Default::default());
|
||||
}};
|
||||
@ -325,7 +315,6 @@ impl Fold<ImportDecl> for Strip {
|
||||
| ImportSpecifier::Specific(ImportSpecific { ref local, .. }) => {
|
||||
let entry = self
|
||||
.scope
|
||||
.value
|
||||
.imported_idents
|
||||
.get(&(local.sym.clone(), local.span.ctxt()));
|
||||
match entry {
|
||||
@ -348,7 +337,6 @@ impl Fold<ImportDecl> for Strip {
|
||||
impl Fold<Ident> for Strip {
|
||||
fn fold(&mut self, i: Ident) -> Ident {
|
||||
self.scope
|
||||
.value
|
||||
.imported_idents
|
||||
.entry((i.sym.clone(), i.span.ctxt()))
|
||||
.and_modify(|v| v.has_concrete = true);
|
||||
@ -358,7 +346,7 @@ impl Fold<Ident> for Strip {
|
||||
|
||||
impl Visit<TsEntityName> for Strip {
|
||||
fn visit(&mut self, name: &TsEntityName) {
|
||||
assert!(match self.phase.value {
|
||||
assert!(match self.phase {
|
||||
Phase::Analysis => true,
|
||||
_ => false,
|
||||
});
|
||||
@ -366,7 +354,6 @@ impl Visit<TsEntityName> for Strip {
|
||||
match *name {
|
||||
TsEntityName::Ident(ref i) => {
|
||||
self.scope
|
||||
.value
|
||||
.imported_idents
|
||||
.entry((i.sym.clone(), i.span.ctxt()))
|
||||
.and_modify(|v| v.has_type = true);
|
||||
|
@ -1,4 +1,3 @@
|
||||
pub(crate) use self::state::State;
|
||||
pub use self::{
|
||||
factory::ExprFactory,
|
||||
value::{
|
||||
@ -28,7 +27,6 @@ use unicode_xid::UnicodeXID;
|
||||
|
||||
pub(crate) mod constructor;
|
||||
mod factory;
|
||||
mod state;
|
||||
mod value;
|
||||
pub(crate) mod var;
|
||||
|
||||
|
@ -1,39 +0,0 @@
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
/// Variable which is resetted to default on clone
|
||||
#[derive(Debug, Default, Copy, PartialEq, Eq)]
|
||||
pub(crate) struct State<T: Default> {
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
impl<T: Default> From<T> for State<T> {
|
||||
fn from(value: T) -> Self {
|
||||
State { value }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Deref for State<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> DerefMut for State<T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
&mut self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Clone for State<T> {
|
||||
fn clone(&self) -> Self {
|
||||
State {
|
||||
value: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Safe iff cloned.
|
||||
unsafe impl<T: Default> Send for State<T> {}
|
||||
/// Safe iff cloned.
|
||||
unsafe impl<T: Default> Sync for State<T> {}
|
Loading…
Reference in New Issue
Block a user