swc_ecma_transforms:
 - Remove State / Clone
 - Fix hygiene bug of labels (#281)
 - Fix sequence expression in unary expression (#282)
This commit is contained in:
강동윤 2019-02-27 22:40:19 +09:00 committed by GitHub
parent 892b4f01cd
commit cdf4a09e65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 332 additions and 292 deletions

View File

@ -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"

View File

@ -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 {

View File

@ -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 {

View File

@ -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)]

View File

@ -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 {

View File

@ -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 {

View File

@ -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.

View File

@ -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,

View File

@ -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);

View File

@ -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
}
}
}"
);

View File

@ -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
}

View File

@ -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)]

View File

@ -3,6 +3,6 @@ use crate::pass::Pass;
mod exponentation;
pub fn es2016() -> impl Pass + Clone {
pub fn es2016() -> impl Pass {
exponentation()
}

View File

@ -29,7 +29,7 @@ mod tests;
/// yield bar();
/// });
/// ```
pub fn async_to_generator() -> impl Pass + Clone {
pub fn async_to_generator() -> impl Pass {
AsyncToGenerator
}

View File

@ -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()
}

View File

@ -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()
}

View File

@ -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 {

View File

@ -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)
}

View File

@ -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

View File

@ -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));"
);
}

View File

@ -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)

View File

@ -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
}
}
}",
);
}

View File

@ -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;

View File

@ -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);

View File

@ -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
}
}

View File

@ -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

View File

@ -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);

View File

@ -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>() })
// }

View File

@ -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() }
}

View File

@ -52,7 +52,7 @@ mod tests;
/// }
/// }
/// ```
pub fn decorators() -> impl Pass + Clone {
pub fn decorators() -> impl Pass {
Decorators {
is_in_strict: false,
}

View File

@ -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
}

View File

@ -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 {

View File

@ -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,

View File

@ -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,
}

View File

@ -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,

View File

@ -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!(

View File

@ -3,3 +3,10 @@ pub enum ScopeKind {
Block,
Fn,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IdentType {
Binding,
Ref,
Label,
}

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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> {}