Extract utils from swc_ecma_transforms (#575)

swc_ecma_transforms:
 - extract utils
This commit is contained in:
강동윤 2020-01-08 10:55:22 +09:00 committed by GitHub
parent 6eb066166f
commit 5503cde085
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 197 additions and 162 deletions

View File

@ -13,7 +13,8 @@ edition = "2018"
ast = { package = "swc_ecma_ast", path ="./ast" }
codegen = { package = "swc_ecma_codegen", path ="./codegen" }
parser = { package = "swc_ecma_parser", path ="./parser", features = ["verify"] }
transforms = { package = "swc_ecma_transforms", path ="./transforms" }
preset_env = { package = "swc_ecma_preset_env", path ="preset_env" }
utils = { package = "swc_ecma_utils", path ="./utils" }
transforms = { package = "swc_ecma_transforms", path ="./transforms" }
[dev-dependencies]

View File

@ -1,6 +1,6 @@
[package]
name = "swc_ecma_transforms"
version = "0.4.0"
version = "0.5.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
@ -12,6 +12,7 @@ edition = "2018"
swc_atoms = { version = "0.2.0", path ="../../atoms" }
swc_common = { version = "0.4.2", path ="../../common" }
ast = { package = "swc_ecma_ast", version = "0.14.0", path ="../ast" }
utils = { package = "swc_ecma_utils", version = "0.1.0", path ="../utils" }
swc_ecma_parser = { version = "0.16", path ="../parser", features = ["verify"] }
chashmap = "2.2.0"
either = "1.5"

View File

@ -4,6 +4,7 @@ use crate::{
};
use ast::*;
use swc_common::{Fold, FoldWith, Spanned, Visit, VisitWith, DUMMY_SP};
use utils::quote_ident;
/// Compile ES2015 arrow functions to ES5
///

View File

@ -4,6 +4,7 @@ use ast::*;
use std::iter;
use swc_atoms::JsWord;
use swc_common::{Fold, FoldWith, Mark, Visit, VisitWith, DUMMY_SP};
use utils::quote_ident;
pub(super) struct SuperCallFinder {
mode: Option<SuperFoldingMode>,

View File

@ -4,6 +4,7 @@ use ast::*;
use std::iter;
use swc_atoms::js_word;
use swc_common::{Fold, FoldWith, Mark, Span, Spanned, DUMMY_SP};
use utils::quote_ident;
/// Process function body.
///

View File

@ -1,13 +1,13 @@
use crate::util::{
options::{CM, SESSION},
prepend_stmts, DropSpan,
};
use ast::*;
use lazy_static::lazy_static;
use scoped_tls::scoped_thread_local;
use std::sync::atomic::{AtomicBool, Ordering};
use swc_common::{FileName, Fold, FoldWith, Mark, Span, DUMMY_SP};
use swc_ecma_parser::{lexer::Lexer, Parser, SourceFileInput};
use utils::{
options::{CM, SESSION},
prepend_stmts, quote_ident, quote_str, DropSpan,
};
#[macro_export]
macro_rules! enable_helper {

View File

@ -8,6 +8,9 @@
#![cfg_attr(test, feature(test))]
#![recursion_limit = "1024"]
#[macro_use]
extern crate utils;
pub use self::{const_modules::const_modules, fixer::fixer, hygiene::hygiene, resolver::resolver};
#[macro_use]
@ -33,4 +36,6 @@ pub mod react;
mod resolver;
pub mod scope;
pub mod typescript;
pub mod util;
pub mod util {
pub use utils::*;
}

View File

@ -1,16 +1,3 @@
/// Shortcut for `quote_ident!(span.apply_mark(Mark::fresh(Mark::root())), s)`
macro_rules! private_ident {
($s:expr) => {
private_ident!(::swc_common::DUMMY_SP, $s)
};
($span:expr, $s:expr) => {{
use swc_common::Mark;
let mark = Mark::fresh(Mark::root());
let span = $span.apply_mark(mark);
::ast::Ident::new($s.into(), span)
}};
}
macro_rules! external_name {
("typeof") => {
"_typeof"
@ -57,109 +44,3 @@ macro_rules! helper {
helper_expr!($span, $field_name, $s).as_callee()
}};
}
#[macro_export]
macro_rules! quote_ident {
($s:expr) => {
quote_ident!(::swc_common::DUMMY_SP, $s)
};
($span:expr, $s:expr) => {{
::ast::Ident::new($s.into(), $span)
}};
}
#[macro_export]
macro_rules! quote_str {
($s:expr) => {
quote_str!(::swc_common::DUMMY_SP, $s)
};
($span:expr, $s:expr) => {{
::ast::Str {
span: $span,
value: $s.into(),
has_escape: false,
}
}};
}
#[macro_export]
macro_rules! quote_expr {
($span:expr, null) => {{
use ast::*;
Expr::Lit(Lit::Null(Null { span: $span }))
}};
($span:expr, undefined) => {{
box Expr::Ident(Ident::new(js_word!("undefined"), $span))
}};
}
/// Creates a member expression.
///
/// # Usage
/// ```rust,ignore
/// member_expr!(span, Function.bind.apply);
/// ```
///
/// Returns Box<Expr>
#[macro_export]
macro_rules! member_expr {
($span:expr, $first:ident) => {{
use ast::Expr;
box Expr::Ident(quote_ident!($span, stringify!($first)))
}};
($span:expr, $first:ident . $($rest:tt)+) => {{
let obj = member_expr!($span, $first);
member_expr!(@EXT, $span, obj, $($rest)* )
}};
(@EXT, $span:expr, $obj:expr, $first:ident . $($rest:tt)* ) => {{
let prop = member_expr!($span, $first);
member_expr!(@EXT, $span, box Expr::Member(MemberExpr{
span: ::swc_common::DUMMY_SP,
obj: ExprOrSuper::Expr($obj),
computed: false,
prop,
}), $($rest)*)
}};
(@EXT, $span:expr, $obj:expr, $first:ident) => {{
use ast::*;
let prop = member_expr!($span, $first);
box Expr::Member(MemberExpr{
span: ::swc_common::DUMMY_SP,
obj: ExprOrSuper::Expr($obj),
computed: false,
prop,
})
}};
}
#[cfg(test)]
mod tests {
use ast::*;
use swc_common::DUMMY_SP as span;
#[test]
fn quote_member_expr() {
let expr: Box<Expr> = member_expr!(span, Function.prototype.bind);
testing::assert_eq_ignore_span!(
expr,
box Expr::Member(MemberExpr {
span,
obj: ExprOrSuper::Expr(box Expr::Member(MemberExpr {
span,
obj: ExprOrSuper::Expr(member_expr!(span, Function)),
computed: false,
prop: member_expr!(span, prototype),
})),
computed: false,
prop: member_expr!(span, bind),
})
);
}
}

View File

@ -0,0 +1,19 @@
[package]
name = "swc_ecma_utils"
version = "0.1.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ast = { package = "swc_ecma_ast", version = "0.14.0", path ="../ast" }
swc_atoms = { version = "0.2.0", path ="../../atoms" }
swc_common = { version = "0.4.2", path ="../../common" }
swc_ecma_parser = { version = "0.16", path ="../parser", features = ["verify"] }
lazy_static = "1"
scoped-tls = "1"
unicode-xid = "0.2"
[dev-dependencies]
testing = { version = "0.4", path ="../../testing" }

View File

@ -1,10 +1,10 @@
use crate::util::{prepend_stmts, ExprFactory};
use crate::{prepend_stmts, ExprFactory};
use ast::*;
use std::iter;
use swc_common::{Fold, FoldWith, DUMMY_SP};
#[allow(clippy::vec_box)]
pub(crate) fn inject_after_super(mut c: Constructor, exprs: Vec<Box<Expr>>) -> Constructor {
pub fn inject_after_super(mut c: Constructor, exprs: Vec<Box<Expr>>) -> Constructor {
// Allow using super multiple time
let mut folder = Injector {
exprs: &exprs,

View File

@ -1,3 +1,8 @@
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(try_trait)]
#![feature(specialization)]
pub use self::{
factory::ExprFactory,
ident::{id, Id},
@ -10,7 +15,7 @@ pub use self::{
},
Purity::{MayBeImpure, Pure},
};
use crate::util::ident::IdentLike;
use crate::ident::IdentLike;
use ast::*;
use scoped_tls::scoped_thread_local;
use std::{
@ -26,14 +31,16 @@ use swc_common::{
};
use unicode_xid::UnicodeXID;
pub(crate) mod constructor;
#[macro_use]
mod macros;
pub mod constructor;
mod factory;
pub mod ident;
pub(crate) mod options;
pub mod options;
mod value;
pub(crate) mod var;
pub mod var;
pub(crate) struct ThisVisitor {
pub struct ThisVisitor {
found: bool,
}
@ -63,7 +70,7 @@ impl Visit<FnDecl> for ThisVisitor {
fn visit(&mut self, _: &FnDecl) {}
}
pub(crate) fn contains_this_expr<N>(body: &N) -> bool
pub fn contains_this_expr<N>(body: &N) -> bool
where
ThisVisitor: Visit<N>,
{
@ -72,7 +79,7 @@ where
visitor.found
}
pub(crate) fn contains_ident_ref<'a, N>(body: &N, ident: &'a Ident) -> bool
pub fn contains_ident_ref<'a, N>(body: &N, ident: &'a Ident) -> bool
where
N: VisitWith<IdentFinder<'a>>,
{
@ -84,7 +91,7 @@ where
visitor.found
}
pub(crate) struct IdentFinder<'a> {
pub struct IdentFinder<'a> {
ident: &'a Ident,
found: bool,
}
@ -213,7 +220,7 @@ impl<T> IsEmpty for Vec<T> {
}
/// Extracts hoisted variables
pub(crate) fn extract_var_ids<T: VisitWith<Hoister>>(node: &T) -> Vec<Ident> {
pub fn extract_var_ids<T: VisitWith<Hoister>>(node: &T) -> Vec<Ident> {
let mut v = Hoister { vars: vec![] };
node.visit_with(&mut v);
v.vars
@ -275,7 +282,7 @@ impl StmtExt for Box<Stmt> {
}
}
pub(crate) struct Hoister {
pub struct Hoister {
vars: Vec<Ident>,
}
@ -1013,7 +1020,7 @@ impl Add for Purity {
}
/// Cast to javascript's int32
pub(crate) fn to_int32(d: f64) -> i32 {
pub fn to_int32(d: f64) -> i32 {
let id = d as i32;
if id as f64 == d {
// This covers -0.0 as well
@ -1036,7 +1043,7 @@ pub(crate) fn to_int32(d: f64) -> i32 {
l as i32
}
// pub(crate) fn to_u32(_d: f64) -> u32 {
// pub fn to_u32(_d: f64) -> u32 {
// // if (Double.isNaN(d) || Double.isInfinite(d) || d == 0) {
// // return 0;
// // }
@ -1055,13 +1062,13 @@ pub(crate) fn to_int32(d: f64) -> i32 {
// unimplemented!("to_u32")
// }
pub(crate) fn has_rest_pat<T: VisitWith<RestPatVisitor>>(node: &T) -> bool {
pub fn has_rest_pat<T: VisitWith<RestPatVisitor>>(node: &T) -> bool {
let mut v = RestPatVisitor { found: false };
node.visit_with(&mut v);
v.found
}
pub(crate) struct RestPatVisitor {
pub struct RestPatVisitor {
found: bool,
}
@ -1071,7 +1078,7 @@ impl Visit<RestPat> for RestPatVisitor {
}
}
pub(crate) fn is_literal<T>(node: &T) -> bool
pub fn is_literal<T>(node: &T) -> bool
where
T: VisitWith<LiteralVisitor>,
{
@ -1080,7 +1087,7 @@ where
}
#[inline(never)]
pub(crate) fn calc_literal_cost<T>(e: &T, allow_non_json_value: bool) -> (bool, usize)
pub fn calc_literal_cost<T>(e: &T, allow_non_json_value: bool) -> (bool, usize)
where
T: VisitWith<LiteralVisitor>,
{
@ -1094,7 +1101,7 @@ where
(v.is_lit, v.cost)
}
pub(crate) struct LiteralVisitor {
pub struct LiteralVisitor {
is_lit: bool,
cost: usize,
allow_non_json_value: bool,
@ -1257,7 +1264,7 @@ pub fn alias_if_required(expr: &Expr, default: &str) -> (Ident, bool) {
(alias_ident_for(expr, default), true)
}
pub(crate) fn prop_name_to_expr(p: PropName) -> Expr {
pub fn prop_name_to_expr(p: PropName) -> Expr {
match p {
PropName::Ident(i) => Expr::Ident(i),
PropName::Str(s) => Expr::Lit(Lit::Str(s)),
@ -1268,7 +1275,7 @@ pub(crate) fn prop_name_to_expr(p: PropName) -> Expr {
/// Simillar to `prop_name_to_expr`, but used for value position.
///
/// e.g. value from `{ key: value }`
pub(crate) fn prop_name_to_expr_value(p: PropName) -> Expr {
pub fn prop_name_to_expr_value(p: PropName) -> Expr {
match p {
PropName::Ident(i) => Expr::Lit(Lit::Str(Str {
span: i.span,
@ -1320,7 +1327,7 @@ pub fn default_constructor(has_super: bool) -> Constructor {
}
/// Check if `e` is `...arguments`
pub(crate) fn is_rest_arguments(e: &ExprOrSpread) -> bool {
pub fn is_rest_arguments(e: &ExprOrSpread) -> bool {
match *e {
ExprOrSpread {
spread: Some(..),
@ -1335,7 +1342,7 @@ pub(crate) fn is_rest_arguments(e: &ExprOrSpread) -> bool {
}
#[inline]
pub(crate) fn undefined(span: Span) -> Box<Expr> {
pub fn undefined(span: Span) -> Box<Expr> {
box Expr::Unary(UnaryExpr {
span,
op: op!("void"),
@ -1429,11 +1436,11 @@ impl IdentExt for Ident {
}
/// Finds all idents of variable
pub(crate) struct DestructuringFinder<'a, I: IdentLike> {
pub struct DestructuringFinder<'a, I: IdentLike> {
pub found: &'a mut Vec<I>,
}
pub(crate) fn find_ids<T, I: IdentLike>(node: &T) -> Vec<I>
pub fn find_ids<T, I: IdentLike>(node: &T) -> Vec<I>
where
T: for<'any> VisitWith<DestructuringFinder<'any, I>>,
{
@ -1463,7 +1470,7 @@ impl<'a, I: IdentLike> Visit<Ident> for DestructuringFinder<'a, I> {
}
}
pub(crate) fn is_valid_ident(s: &JsWord) -> bool {
pub fn is_valid_ident(s: &JsWord) -> bool {
if s.len() == 0 {
return false;
}
@ -1471,14 +1478,14 @@ pub(crate) fn is_valid_ident(s: &JsWord) -> bool {
UnicodeXID::is_xid_start(first) && s.chars().skip(1).all(UnicodeXID::is_xid_continue)
}
pub(crate) fn drop_span<T>(t: T) -> T
pub fn drop_span<T>(t: T) -> T
where
T: FoldWith<DropSpan>,
{
t.fold_with(&mut DropSpan)
}
pub(crate) struct DropSpan;
pub struct DropSpan;
impl Fold<Span> for DropSpan {
fn fold(&mut self, _: Span) -> Span {
DUMMY_SP
@ -1486,7 +1493,7 @@ impl Fold<Span> for DropSpan {
}
/// Finds usage of `ident`
pub(crate) struct UsageFinder<'a> {
pub struct UsageFinder<'a> {
ident: &'a Ident,
found: bool,
}
@ -1510,7 +1517,7 @@ impl<'a> Visit<Ident> for UsageFinder<'a> {
}
impl<'a> UsageFinder<'a> {
pub(crate) fn find<N>(ident: &'a Ident, node: &N) -> bool
pub fn find<N>(ident: &'a Ident, node: &N) -> bool
where
N: VisitWith<Self>,
{
@ -1527,7 +1534,7 @@ scoped_thread_local!(pub static HANDLER: Handler);
scoped_thread_local!(pub static COMMENTS: Comments);
/// make a new expression which evaluates `val` preserving side effects, if any.
pub(crate) fn preserve_effects<I>(span: Span, val: Expr, exprs: I) -> Expr
pub fn preserve_effects<I>(span: Span, val: Expr, exprs: I) -> Expr
where
I: IntoIterator<Item = Box<Expr>>,
{

View File

@ -0,0 +1,119 @@
/// Shortcut for `quote_ident!(span.apply_mark(Mark::fresh(Mark::root())), s)`
#[macro_export]
macro_rules! private_ident {
($s:expr) => {
private_ident!(::swc_common::DUMMY_SP, $s)
};
($span:expr, $s:expr) => {{
use swc_common::Mark;
let mark = Mark::fresh(Mark::root());
let span = $span.apply_mark(mark);
::ast::Ident::new($s.into(), span)
}};
}
#[macro_export]
macro_rules! quote_ident {
($s:expr) => {
quote_ident!(::swc_common::DUMMY_SP, $s)
};
($span:expr, $s:expr) => {{
::ast::Ident::new($s.into(), $span)
}};
}
#[macro_export]
macro_rules! quote_str {
($s:expr) => {
quote_str!(::swc_common::DUMMY_SP, $s)
};
($span:expr, $s:expr) => {{
::ast::Str {
span: $span,
value: $s.into(),
has_escape: false,
}
}};
}
#[macro_export]
macro_rules! quote_expr {
($span:expr, null) => {{
use ast::*;
Expr::Lit(Lit::Null(Null { span: $span }))
}};
($span:expr, undefined) => {{
box Expr::Ident(Ident::new(js_word!("undefined"), $span))
}};
}
/// Creates a member expression.
///
/// # Usage
/// ```rust,ignore
/// member_expr!(span, Function.bind.apply);
/// ```
///
/// Returns Box<Expr>
#[macro_export]
macro_rules! member_expr {
($span:expr, $first:ident) => {{
use ast::Expr;
box Expr::Ident(quote_ident!($span, stringify!($first)))
}};
($span:expr, $first:ident . $($rest:tt)+) => {{
let obj = member_expr!($span, $first);
member_expr!(@EXT, $span, obj, $($rest)* )
}};
(@EXT, $span:expr, $obj:expr, $first:ident . $($rest:tt)* ) => {{
let prop = member_expr!($span, $first);
member_expr!(@EXT, $span, box Expr::Member(MemberExpr{
span: ::swc_common::DUMMY_SP,
obj: ExprOrSuper::Expr($obj),
computed: false,
prop,
}), $($rest)*)
}};
(@EXT, $span:expr, $obj:expr, $first:ident) => {{
use ast::*;
let prop = member_expr!($span, $first);
box Expr::Member(MemberExpr{
span: ::swc_common::DUMMY_SP,
obj: ExprOrSuper::Expr($obj),
computed: false,
prop,
})
}};
}
#[cfg(test)]
mod tests {
use ast::*;
use swc_common::DUMMY_SP as span;
#[test]
fn quote_member_expr() {
let expr: Box<Expr> = member_expr!(span, Function.prototype.bind);
testing::assert_eq_ignore_span!(
expr,
box Expr::Member(MemberExpr {
span,
obj: ExprOrSuper::Expr(box Expr::Member(MemberExpr {
span,
obj: ExprOrSuper::Expr(member_expr!(span, Function)),
computed: false,
prop: member_expr!(span, prototype),
})),
computed: false,
prop: member_expr!(span, bind),
})
);
}
}

View File

@ -7,9 +7,8 @@ use swc_common::{
use swc_ecma_parser::Session;
lazy_static! {
pub(crate) static ref CM: Arc<SourceMap> =
{ Arc::new(SourceMap::new(FilePathMapping::empty())) };
pub(crate) static ref HANDLER: Handler =
pub static ref CM: Arc<SourceMap> = { Arc::new(SourceMap::new(FilePathMapping::empty())) };
pub static ref HANDLER: Handler =
{ Handler::with_tty_emitter(ColorConfig::Always, false, true, Some(CM.clone())) };
pub(crate) static ref SESSION: Session<'static> = { Session { handler: &*HANDLER } };
pub static ref SESSION: Session<'static> = { Session { handler: &*HANDLER } };
}

View File

@ -2,7 +2,7 @@ use ast::*;
use swc_atoms::JsWord;
use swc_common::{SyntaxContext, Visit, VisitWith};
pub(crate) struct VarCollector<'a> {
pub struct VarCollector<'a> {
pub to: &'a mut Vec<(JsWord, SyntaxContext)>,
}