Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/swc_ecma_utils/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/swc_ecma_utils/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.toml":"646c16d73c72c84d696e4646853588a3494e00624fb5bf99e77cd324b2643321","src/constructor.rs":"ada7b0091d58c664f1c4b6539472f4ba1e5e1231a5614b036bb066bd5a6a268d","src/factory.rs":"c4e220799b4b44b2e36babc95cfe69317fbac5316e47558a2d8001e7c255419f","src/function/fn_env_hoister.rs":"ee797f3158dfd1edbefdb01cca8891f3b492f2cabc05e7a5b23d21ee3c94a41e","src/function/function_wrapper.rs":"512682ecc72fc7fd7df4ade4a491390b78200ee849c43056cb8846c77c24a426","src/function/mod.rs":"d7d3cefed8e3110563b3fc3b553c7cc91daf0795dc0ae03961ae572cdaac2f50","src/ident.rs":"5f00f829b4c146689c5e4b38b9e5d676fd2ad26a64c9a28a685b5ae095c629ee","src/lib.rs":"e5c1327013ba9a45720ae397038c865efecd07da8ad16fb6736b4075959b5226","src/macros.rs":"e4ad8693585f7b722d7e5c7d9524de4b1f3c8dbe80ba283a7db30c8fb7edc156","src/node_ignore_span.rs":"522909a4fc4e838e6f5490dd131e39c3b4cab9640c981f5a665858d8ddfb7c1f","src/parallel.rs":"428b59eec4833fdb563a78333eeb627f64413bc12fc302915a664d1fa606dfed","src/value.rs":"b48ec3c30da1f200042a79d86ffb973a837a58e9ff1f8317571860907e1a5590","src/var.rs":"5d8d90409a17696270fa6d4a3c1b44133eb4546417ebdf4b4520b4dfd28126bd"},"package":"11006a3398ffd4693c4d3b0a1b1a5030edbdc04228159f5301120a6178144708"}
|
||||
76
third-party/vendor/swc_ecma_utils/Cargo.toml
vendored
Normal file
76
third-party/vendor/swc_ecma_utils/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2021"
|
||||
name = "swc_ecma_utils"
|
||||
version = "0.122.0"
|
||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||
description = "Utilities for swc ecmascript ast nodes"
|
||||
documentation = "https://rustdoc.swc.rs/swc_ecma_utils/"
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = [
|
||||
"--cfg",
|
||||
"docsrs",
|
||||
]
|
||||
|
||||
[lib]
|
||||
bench = false
|
||||
|
||||
[dependencies.indexmap]
|
||||
version = "1.9.3"
|
||||
|
||||
[dependencies.num_cpus]
|
||||
version = "1.13.1"
|
||||
|
||||
[dependencies.once_cell]
|
||||
version = "1.18.0"
|
||||
|
||||
[dependencies.rayon]
|
||||
version = "1.7.0"
|
||||
optional = true
|
||||
|
||||
[dependencies.rustc-hash]
|
||||
version = "1.1.0"
|
||||
|
||||
[dependencies.swc_atoms]
|
||||
version = "0.5.9"
|
||||
|
||||
[dependencies.swc_common]
|
||||
version = "0.32.0"
|
||||
|
||||
[dependencies.swc_ecma_ast]
|
||||
version = "0.109.0"
|
||||
|
||||
[dependencies.swc_ecma_visit]
|
||||
version = "0.95.0"
|
||||
|
||||
[dependencies.tracing]
|
||||
version = "0.1.37"
|
||||
|
||||
[dependencies.unicode-id]
|
||||
version = "0.3"
|
||||
|
||||
[dev-dependencies.swc_ecma_parser]
|
||||
version = "0.139.0"
|
||||
|
||||
[dev-dependencies.testing]
|
||||
version = "0.34.0"
|
||||
|
||||
[features]
|
||||
concurrent = [
|
||||
"swc_common/concurrent",
|
||||
"rayon",
|
||||
]
|
||||
164
third-party/vendor/swc_ecma_utils/src/constructor.rs
vendored
Normal file
164
third-party/vendor/swc_ecma_utils/src/constructor.rs
vendored
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
use std::iter;
|
||||
|
||||
use swc_common::{util::take::Take, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_visit::{noop_fold_type, noop_visit_mut_type, Fold, FoldWith, VisitMut, VisitMutWith};
|
||||
|
||||
use crate::{prepend_stmts, ExprFactory};
|
||||
|
||||
pub fn inject_after_super(c: &mut Constructor, mut exprs: Vec<Box<Expr>>) {
|
||||
// Allow using super multiple time
|
||||
let mut folder = Injector {
|
||||
exprs: &mut exprs,
|
||||
injected: false,
|
||||
};
|
||||
|
||||
c.body = std::mem::take(&mut c.body).fold_with(&mut folder);
|
||||
if !folder.injected {
|
||||
if c.body.is_none() {
|
||||
c.body = Some(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![],
|
||||
});
|
||||
}
|
||||
// there was no super() call
|
||||
prepend_stmts(
|
||||
&mut c.body.as_mut().unwrap().stmts,
|
||||
exprs.into_iter().map(|v| v.into_stmt()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
struct Injector<'a> {
|
||||
injected: bool,
|
||||
exprs: &'a mut Vec<Box<Expr>>,
|
||||
}
|
||||
|
||||
impl<'a> Fold for Injector<'a> {
|
||||
noop_fold_type!();
|
||||
|
||||
fn fold_class(&mut self, c: Class) -> Class {
|
||||
c
|
||||
}
|
||||
|
||||
fn fold_constructor(&mut self, n: Constructor) -> Constructor {
|
||||
n
|
||||
}
|
||||
|
||||
fn fold_function(&mut self, n: Function) -> Function {
|
||||
n
|
||||
}
|
||||
|
||||
fn fold_stmts(&mut self, stmts: Vec<Stmt>) -> Vec<Stmt> {
|
||||
if self.exprs.is_empty() {
|
||||
return stmts;
|
||||
}
|
||||
|
||||
let mut buf = Vec::with_capacity(stmts.len() + 8);
|
||||
|
||||
stmts.into_iter().for_each(|stmt| {
|
||||
if let Stmt::Expr(ExprStmt { ref expr, .. }) = stmt {
|
||||
if let Expr::Call(CallExpr {
|
||||
callee: Callee::Super(..),
|
||||
..
|
||||
}) = &**expr
|
||||
{
|
||||
self.injected = true;
|
||||
buf.push(stmt);
|
||||
buf.extend(self.exprs.clone().into_iter().map(|v| v.into_stmt()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let mut folder = Injector {
|
||||
injected: false,
|
||||
exprs: self.exprs,
|
||||
};
|
||||
let mut stmt = stmt.fold_children_with(&mut folder);
|
||||
self.injected |= folder.injected;
|
||||
if folder.injected {
|
||||
buf.push(stmt);
|
||||
} else {
|
||||
let mut folder = ExprInjector {
|
||||
injected: false,
|
||||
exprs: self.exprs,
|
||||
injected_tmp: None,
|
||||
};
|
||||
stmt.visit_mut_with(&mut folder);
|
||||
|
||||
self.injected |= folder.injected;
|
||||
|
||||
buf.extend(folder.injected_tmp.map(|ident| {
|
||||
Stmt::Decl(Decl::Var(Box::new(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(ident.into()),
|
||||
init: None,
|
||||
definite: false,
|
||||
}],
|
||||
declare: false,
|
||||
})))
|
||||
}));
|
||||
buf.push(stmt);
|
||||
}
|
||||
});
|
||||
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles code like `foo(super())`
|
||||
struct ExprInjector<'a> {
|
||||
injected: bool,
|
||||
exprs: &'a mut Vec<Box<Expr>>,
|
||||
injected_tmp: Option<Ident>,
|
||||
}
|
||||
|
||||
impl VisitMut for ExprInjector<'_> {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn visit_mut_class(&mut self, c: &mut Class) {
|
||||
c.super_class.visit_mut_with(self);
|
||||
}
|
||||
|
||||
fn visit_mut_constructor(&mut self, _: &mut Constructor) {}
|
||||
|
||||
fn visit_mut_expr(&mut self, expr: &mut Expr) {
|
||||
expr.visit_mut_children_with(self);
|
||||
|
||||
if let Expr::Call(CallExpr {
|
||||
callee: Callee::Super(..),
|
||||
..
|
||||
}) = expr
|
||||
{
|
||||
self.injected_tmp = Some(
|
||||
self.injected_tmp
|
||||
.take()
|
||||
.unwrap_or_else(|| private_ident!("_temp")),
|
||||
);
|
||||
self.injected = true;
|
||||
let e = expr.take();
|
||||
|
||||
*expr = Expr::Seq(SeqExpr {
|
||||
span: DUMMY_SP,
|
||||
exprs: iter::once(Box::new(Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(Box::new(Pat::Ident(
|
||||
self.injected_tmp.as_ref().cloned().unwrap().into(),
|
||||
))),
|
||||
op: op!("="),
|
||||
right: Box::new(e),
|
||||
})))
|
||||
.chain(self.exprs.clone())
|
||||
.chain(iter::once(Box::new(Expr::Ident(
|
||||
self.injected_tmp.as_ref().cloned().unwrap(),
|
||||
))))
|
||||
.collect(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_function(&mut self, _: &mut Function) {}
|
||||
}
|
||||
374
third-party/vendor/swc_ecma_utils/src/factory.rs
vendored
Normal file
374
third-party/vendor/swc_ecma_utils/src/factory.rs
vendored
Normal file
|
|
@ -0,0 +1,374 @@
|
|||
use std::iter;
|
||||
|
||||
use swc_atoms::js_word;
|
||||
use swc_common::{util::take::Take, Span, Spanned, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
|
||||
/// Extension methods for [Expr].
|
||||
///
|
||||
/// Note that many types implements `Into<Expr>` and you can do like
|
||||
///
|
||||
/// ```rust
|
||||
/// use swc_ecma_utils::ExprFactory;
|
||||
///
|
||||
/// let _args = vec![0f64.as_arg()];
|
||||
/// ```
|
||||
///
|
||||
/// to create literals. Almost all rust core types implements `Into<Expr>`.
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub trait ExprFactory: Into<Expr> {
|
||||
/// Creates an [ExprOrSpread] using the given [Expr].
|
||||
///
|
||||
/// This is recommended way to create [ExprOrSpread].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use swc_common::DUMMY_SP;
|
||||
/// use swc_ecma_ast::*;
|
||||
/// use swc_ecma_utils::ExprFactory;
|
||||
///
|
||||
/// let first = Lit::Num(Number {
|
||||
/// span: DUMMY_SP,
|
||||
/// value: 0.0,
|
||||
/// raw: None,
|
||||
/// });
|
||||
/// let _args = vec![first.as_arg()];
|
||||
/// ```
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn as_arg(self) -> ExprOrSpread {
|
||||
ExprOrSpread {
|
||||
expr: Box::new(self.into()),
|
||||
spread: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn as_pat_or_expr(self) -> PatOrExpr {
|
||||
PatOrExpr::Expr(Box::new(self.into()))
|
||||
}
|
||||
|
||||
/// Creates an expression statement with `self`.
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn into_stmt(self) -> Stmt {
|
||||
Stmt::Expr(ExprStmt {
|
||||
span: DUMMY_SP,
|
||||
expr: Box::new(self.into()),
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a statement whcih return `self`.
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn into_return_stmt(self) -> ReturnStmt {
|
||||
ReturnStmt {
|
||||
span: DUMMY_SP,
|
||||
arg: Some(Box::new(self.into())),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn as_callee(self) -> Callee {
|
||||
Callee::Expr(Box::new(self.into()))
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn as_iife(self) -> CallExpr {
|
||||
CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: self.as_callee(),
|
||||
args: Default::default(),
|
||||
type_args: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// create a ArrowExpr which return self
|
||||
/// - `(params) => $self`
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn into_lazy_arrow(self, params: Vec<Pat>) -> ArrowExpr {
|
||||
ArrowExpr {
|
||||
span: DUMMY_SP,
|
||||
params,
|
||||
body: Box::new(BlockStmtOrExpr::from(self)),
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
type_params: None,
|
||||
return_type: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// create a Function which return self
|
||||
/// - `function(params) { return $self; }`
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn into_lazy_fn(self, params: Vec<Param>) -> Function {
|
||||
Function {
|
||||
params,
|
||||
decorators: Default::default(),
|
||||
span: DUMMY_SP,
|
||||
body: Some(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![self.into_return_stmt().into()],
|
||||
}),
|
||||
is_generator: false,
|
||||
is_async: false,
|
||||
type_params: None,
|
||||
return_type: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn into_lazy_auto(self, params: Vec<Pat>, support_arrow: bool) -> Expr {
|
||||
if support_arrow {
|
||||
self.into_lazy_arrow(params).into()
|
||||
} else {
|
||||
self.into_lazy_fn(params.into_iter().map(From::from).collect())
|
||||
.into_fn_expr(None)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// create a var declartor using self as init
|
||||
/// - `var name = expr`
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn into_var_decl(self, kind: VarDeclKind, name: Pat) -> VarDecl {
|
||||
let var_declarator = VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name,
|
||||
init: Some(Box::new(self.into())),
|
||||
definite: false,
|
||||
};
|
||||
|
||||
VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind,
|
||||
declare: false,
|
||||
decls: vec![var_declarator],
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn into_new_expr(self, span: Span, args: Option<Vec<ExprOrSpread>>) -> NewExpr {
|
||||
NewExpr {
|
||||
span,
|
||||
callee: Box::new(self.into()),
|
||||
args,
|
||||
type_args: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn apply(self, span: Span, this: Box<Expr>, args: Vec<ExprOrSpread>) -> Expr {
|
||||
let apply = self.make_member(Ident::new(js_word!("apply"), span));
|
||||
|
||||
Expr::Call(CallExpr {
|
||||
span,
|
||||
callee: apply.as_callee(),
|
||||
args: iter::once(this.as_arg()).chain(args).collect(),
|
||||
type_args: None,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn call_fn(self, span: Span, args: Vec<ExprOrSpread>) -> Expr {
|
||||
Expr::Call(CallExpr {
|
||||
span,
|
||||
args,
|
||||
callee: self
|
||||
.make_member(Ident::new(js_word!("call"), span))
|
||||
.as_callee(),
|
||||
type_args: None,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn as_call(self, span: Span, args: Vec<ExprOrSpread>) -> Expr {
|
||||
Expr::Call(CallExpr {
|
||||
span,
|
||||
args,
|
||||
callee: self.as_callee(),
|
||||
type_args: None,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn as_fn_decl(self) -> Option<FnDecl> {
|
||||
match self.into() {
|
||||
Expr::Fn(FnExpr {
|
||||
ident: Some(ident),
|
||||
function,
|
||||
}) => Some(FnDecl {
|
||||
ident,
|
||||
declare: false,
|
||||
function,
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn as_class_decl(self) -> Option<ClassDecl> {
|
||||
match self.into() {
|
||||
Expr::Class(ClassExpr {
|
||||
ident: Some(ident),
|
||||
class,
|
||||
}) => Some(ClassDecl {
|
||||
ident,
|
||||
declare: false,
|
||||
class,
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn wrap_with_paren(self) -> Expr {
|
||||
let expr = Box::new(self.into());
|
||||
let span = expr.span();
|
||||
Expr::Paren(ParenExpr { expr, span })
|
||||
}
|
||||
|
||||
/// Creates a binary expr `$self === `
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn make_eq<T>(self, right: T) -> Expr
|
||||
where
|
||||
T: Into<Expr>,
|
||||
{
|
||||
self.make_bin(op!("==="), right)
|
||||
}
|
||||
|
||||
/// Creates a binary expr `$self $op $rhs`
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn make_bin<T>(self, op: BinaryOp, right: T) -> Expr
|
||||
where
|
||||
T: Into<Expr>,
|
||||
{
|
||||
let right = Box::new(right.into());
|
||||
|
||||
Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: Box::new(self.into()),
|
||||
op,
|
||||
right,
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a assign expr `$lhs $op $self`
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn make_assign_to(self, op: AssignOp, left: PatOrExpr) -> Expr {
|
||||
let right = Box::new(self.into());
|
||||
|
||||
Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left,
|
||||
op,
|
||||
right,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn make_member<T>(self, prop: T) -> Expr
|
||||
where
|
||||
T: Into<Ident>,
|
||||
{
|
||||
Expr::Member(MemberExpr {
|
||||
obj: Box::new(self.into()),
|
||||
span: DUMMY_SP,
|
||||
prop: MemberProp::Ident(prop.into()),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn computed_member<T>(self, prop: T) -> Expr
|
||||
where
|
||||
T: Into<Expr>,
|
||||
{
|
||||
Expr::Member(MemberExpr {
|
||||
obj: Box::new(self.into()),
|
||||
span: DUMMY_SP,
|
||||
prop: MemberProp::Computed(ComputedPropName {
|
||||
span: DUMMY_SP,
|
||||
expr: Box::new(prop.into()),
|
||||
}),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<Expr>> ExprFactory for T {}
|
||||
|
||||
pub trait IntoIndirectCall
|
||||
where
|
||||
Self: std::marker::Sized,
|
||||
{
|
||||
type Item;
|
||||
fn into_indirect(self) -> Self::Item;
|
||||
}
|
||||
|
||||
impl IntoIndirectCall for CallExpr {
|
||||
type Item = CallExpr;
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn into_indirect(self) -> CallExpr {
|
||||
let callee = self.callee.into_indirect();
|
||||
|
||||
CallExpr { callee, ..self }
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIndirectCall for Callee {
|
||||
type Item = Callee;
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn into_indirect(self) -> Callee {
|
||||
SeqExpr {
|
||||
span: DUMMY_SP,
|
||||
exprs: vec![0f64.into(), self.expect_expr()],
|
||||
}
|
||||
.as_callee()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIndirectCall for TaggedTpl {
|
||||
type Item = TaggedTpl;
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn into_indirect(mut self) -> Self {
|
||||
Self {
|
||||
tag: Box::new(
|
||||
SeqExpr {
|
||||
span: DUMMY_SP,
|
||||
exprs: vec![0f64.into(), self.tag.take()],
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
..self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FunctionFactory: Into<Function> {
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn into_fn_expr(self, ident: Option<Ident>) -> FnExpr {
|
||||
FnExpr {
|
||||
ident,
|
||||
function: Box::new(self.into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn into_fn_decl(self, ident: Ident) -> FnDecl {
|
||||
FnDecl {
|
||||
ident,
|
||||
declare: false,
|
||||
function: Box::new(self.into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn into_method_prop(self, key: PropName) -> MethodProp {
|
||||
MethodProp {
|
||||
key,
|
||||
function: Box::new(self.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<Function>> FunctionFactory for T {}
|
||||
852
third-party/vendor/swc_ecma_utils/src/function/fn_env_hoister.rs
vendored
Normal file
852
third-party/vendor/swc_ecma_utils/src/function/fn_env_hoister.rs
vendored
Normal file
|
|
@ -0,0 +1,852 @@
|
|||
use std::mem;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use swc_atoms::{js_word, JsWord};
|
||||
use swc_common::{util::take::Take, Span, Spanned, SyntaxContext, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};
|
||||
|
||||
use crate::ExprFactory;
|
||||
|
||||
#[derive(Default)]
|
||||
struct SuperField {
|
||||
computed: Option<Ident>,
|
||||
ident: IndexMap<JsWord, Ident>,
|
||||
}
|
||||
|
||||
/// Don't use it against function, it will stop if come across any function
|
||||
/// use it against function body
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct FnEnvHoister {
|
||||
unresolved_ctxt: SyntaxContext,
|
||||
this: Option<Ident>,
|
||||
args: Option<Ident>,
|
||||
new_target: Option<Ident>,
|
||||
super_get: SuperField,
|
||||
super_set: SuperField,
|
||||
super_update: SuperField,
|
||||
|
||||
arguments_disabled: bool,
|
||||
this_disabled: bool,
|
||||
super_disabled: bool,
|
||||
|
||||
in_pat: bool,
|
||||
|
||||
// extra ident for super["xx"] += 123
|
||||
extra_ident: Vec<Ident>,
|
||||
}
|
||||
|
||||
impl FnEnvHoister {
|
||||
pub fn new(unresolved_ctxt: SyntaxContext) -> Self {
|
||||
Self {
|
||||
unresolved_ctxt,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Disable hoisting of `arguments`
|
||||
pub fn disable_arguments(&mut self) {
|
||||
self.arguments_disabled = true;
|
||||
}
|
||||
|
||||
/// Disable hoisting of `this`
|
||||
pub fn disable_this(&mut self) {
|
||||
self.this_disabled = true;
|
||||
}
|
||||
|
||||
/// Disable hoisting of nodes realted to `super`
|
||||
pub fn disable_super(&mut self) {
|
||||
self.super_disabled = true;
|
||||
}
|
||||
|
||||
pub fn take(&mut self) -> Self {
|
||||
let mut new = Self {
|
||||
unresolved_ctxt: self.unresolved_ctxt,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
mem::swap(self, &mut new);
|
||||
|
||||
new
|
||||
}
|
||||
|
||||
pub fn to_decl(self) -> Vec<VarDeclarator> {
|
||||
let Self {
|
||||
this,
|
||||
args,
|
||||
new_target,
|
||||
super_get,
|
||||
super_set,
|
||||
super_update,
|
||||
..
|
||||
} = self;
|
||||
|
||||
let mut decls = Vec::with_capacity(3);
|
||||
if let Some(this_id) = this {
|
||||
decls.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: this_id.into(),
|
||||
init: Some(Box::new(Expr::This(ThisExpr { span: DUMMY_SP }))),
|
||||
definite: false,
|
||||
});
|
||||
}
|
||||
if let Some(id) = args {
|
||||
decls.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: id.into(),
|
||||
init: Some(Box::new(Expr::Ident(Ident::new(
|
||||
js_word!("arguments"),
|
||||
DUMMY_SP,
|
||||
)))),
|
||||
definite: false,
|
||||
});
|
||||
}
|
||||
if let Some(id) = new_target {
|
||||
decls.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: id.into(),
|
||||
init: Some(Box::new(Expr::MetaProp(MetaPropExpr {
|
||||
span: DUMMY_SP,
|
||||
kind: MetaPropKind::NewTarget,
|
||||
}))),
|
||||
definite: false,
|
||||
});
|
||||
}
|
||||
extend_super(&mut decls, super_get, super_set, super_update);
|
||||
decls
|
||||
}
|
||||
|
||||
pub fn to_stmt(self) -> Option<Stmt> {
|
||||
let decls = self.to_decl();
|
||||
|
||||
if decls.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(Stmt::Decl(Decl::Var(Box::new(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
declare: false,
|
||||
decls,
|
||||
}))))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_stmt_in_subclass(self) -> (Option<Stmt>, Option<Ident>) {
|
||||
let Self {
|
||||
this,
|
||||
args,
|
||||
new_target,
|
||||
super_get,
|
||||
super_set,
|
||||
super_update,
|
||||
..
|
||||
} = self;
|
||||
|
||||
let mut decls = Vec::with_capacity(3);
|
||||
if let Some(this_id) = &this {
|
||||
decls.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: this_id.clone().into(),
|
||||
init: None,
|
||||
definite: false,
|
||||
});
|
||||
}
|
||||
if let Some(id) = args {
|
||||
decls.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: id.into(),
|
||||
init: Some(Box::new(Expr::Ident(Ident::new(
|
||||
js_word!("arguments"),
|
||||
DUMMY_SP,
|
||||
)))),
|
||||
definite: false,
|
||||
});
|
||||
}
|
||||
if let Some(id) = new_target {
|
||||
decls.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: id.into(),
|
||||
init: Some(Box::new(Expr::MetaProp(MetaPropExpr {
|
||||
span: DUMMY_SP,
|
||||
kind: MetaPropKind::NewTarget,
|
||||
}))),
|
||||
definite: false,
|
||||
});
|
||||
}
|
||||
|
||||
extend_super(&mut decls, super_get, super_set, super_update);
|
||||
|
||||
if decls.is_empty() {
|
||||
(None, None)
|
||||
} else {
|
||||
(
|
||||
Some(Stmt::Decl(Decl::Var(Box::new(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
declare: false,
|
||||
decls,
|
||||
})))),
|
||||
this,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_this(&mut self) -> Ident {
|
||||
self.this
|
||||
.get_or_insert_with(|| private_ident!("_this"))
|
||||
.clone()
|
||||
}
|
||||
|
||||
fn super_get(&mut self, prop_name: &JsWord, prop_span: Span) -> Ident {
|
||||
if let Some(callee) = self.super_get.ident.get(prop_name) {
|
||||
callee.clone()
|
||||
} else {
|
||||
let ident = private_ident!(prop_span, format!("_superprop_get_{}", prop_name));
|
||||
self.super_get
|
||||
.ident
|
||||
.insert(prop_name.clone(), ident.clone());
|
||||
ident
|
||||
}
|
||||
}
|
||||
|
||||
fn super_get_computed(&mut self, span: Span) -> Ident {
|
||||
self.super_get
|
||||
.computed
|
||||
.get_or_insert_with(|| private_ident!(span, "_superprop_get"))
|
||||
.clone()
|
||||
}
|
||||
|
||||
fn super_set(&mut self, prop_name: &JsWord, prop_span: Span) -> Ident {
|
||||
if let Some(callee) = self.super_set.ident.get(prop_name) {
|
||||
callee.clone()
|
||||
} else {
|
||||
let ident = private_ident!(prop_span, format!("_superprop_set_{}", prop_name));
|
||||
self.super_set
|
||||
.ident
|
||||
.insert(prop_name.clone(), ident.clone());
|
||||
ident
|
||||
}
|
||||
}
|
||||
|
||||
fn super_set_computed(&mut self, span: Span) -> Ident {
|
||||
self.super_set
|
||||
.computed
|
||||
.get_or_insert_with(|| private_ident!(span, "_superprop_set"))
|
||||
.clone()
|
||||
}
|
||||
|
||||
fn super_update(&mut self, prop_name: &JsWord, prop_span: Span) -> Ident {
|
||||
if let Some(callee) = self.super_update.ident.get(prop_name) {
|
||||
callee.clone()
|
||||
} else {
|
||||
self.super_get
|
||||
.ident
|
||||
.entry(prop_name.clone())
|
||||
.or_insert_with(|| {
|
||||
private_ident!(prop_span, format!("_superprop_get_{}", prop_name))
|
||||
});
|
||||
|
||||
self.super_set
|
||||
.ident
|
||||
.entry(prop_name.clone())
|
||||
.or_insert_with(|| {
|
||||
private_ident!(prop_span, format!("_superprop_set_{}", prop_name))
|
||||
});
|
||||
|
||||
let ident = private_ident!(prop_span, format!("_superprop_update_{}", prop_name));
|
||||
self.super_update
|
||||
.ident
|
||||
.insert(prop_name.clone(), ident.clone());
|
||||
ident
|
||||
}
|
||||
}
|
||||
|
||||
fn super_update_computed(&mut self, span: Span) -> Ident {
|
||||
self.super_get
|
||||
.computed
|
||||
.get_or_insert_with(|| private_ident!(span, "_superprop_get"));
|
||||
self.super_set
|
||||
.computed
|
||||
.get_or_insert_with(|| private_ident!(span, "_superprop_set"));
|
||||
self.super_update
|
||||
.computed
|
||||
.get_or_insert_with(|| private_ident!(span, "_superprop_update"))
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl VisitMut for FnEnvHoister {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn visit_mut_pat(&mut self, n: &mut Pat) {
|
||||
let in_pat = self.in_pat;
|
||||
self.in_pat = true;
|
||||
n.visit_mut_children_with(self);
|
||||
self.in_pat = in_pat;
|
||||
}
|
||||
|
||||
fn visit_mut_expr(&mut self, e: &mut Expr) {
|
||||
match e {
|
||||
Expr::Ident(Ident { span, sym, .. })
|
||||
if !self.arguments_disabled
|
||||
&& *sym == js_word!("arguments")
|
||||
&& (span.ctxt == self.unresolved_ctxt
|
||||
|| span.ctxt == SyntaxContext::empty()) =>
|
||||
{
|
||||
let arguments = self
|
||||
.args
|
||||
.get_or_insert_with(|| private_ident!("_arguments"));
|
||||
*e = Expr::Ident(arguments.clone());
|
||||
}
|
||||
Expr::This(..) if !self.this_disabled => {
|
||||
let this = self.get_this();
|
||||
*e = Expr::Ident(this);
|
||||
}
|
||||
Expr::MetaProp(MetaPropExpr {
|
||||
kind: MetaPropKind::NewTarget,
|
||||
..
|
||||
}) => {
|
||||
let target = self
|
||||
.new_target
|
||||
.get_or_insert_with(|| private_ident!("_newtarget"));
|
||||
*e = Expr::Ident(target.clone());
|
||||
}
|
||||
// super.foo = 123 => super_get_foo = (value) => super.foo = value
|
||||
Expr::Assign(AssignExpr {
|
||||
left,
|
||||
right,
|
||||
span,
|
||||
op,
|
||||
}) => {
|
||||
let expr = match left {
|
||||
PatOrExpr::Expr(e) => e,
|
||||
PatOrExpr::Pat(p) => {
|
||||
if let Pat::Expr(e) = &mut **p {
|
||||
e
|
||||
} else {
|
||||
e.visit_mut_children_with(self);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
if !self.super_disabled {
|
||||
if let Expr::SuperProp(super_prop) = &mut **expr {
|
||||
let left_span = super_prop.span;
|
||||
match &mut super_prop.prop {
|
||||
SuperProp::Computed(c) => {
|
||||
let callee = self.super_set_computed(left_span);
|
||||
|
||||
let op = op.to_update();
|
||||
|
||||
let args = if let Some(op) = op {
|
||||
let tmp = private_ident!("tmp");
|
||||
self.extra_ident.push(tmp.clone());
|
||||
vec![
|
||||
Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(tmp.clone().into()),
|
||||
op: op!("="),
|
||||
right: c.expr.take(),
|
||||
})
|
||||
.as_arg(),
|
||||
Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: Box::new(Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: self
|
||||
.super_get_computed(DUMMY_SP)
|
||||
.as_callee(),
|
||||
args: vec![tmp.as_arg()],
|
||||
type_args: None,
|
||||
})),
|
||||
op,
|
||||
right: right.take(),
|
||||
})
|
||||
.as_arg(),
|
||||
]
|
||||
} else {
|
||||
vec![c.expr.take().as_arg(), right.take().as_arg()]
|
||||
};
|
||||
*e = Expr::Call(CallExpr {
|
||||
span: *span,
|
||||
args,
|
||||
callee: callee.as_callee(),
|
||||
type_args: None,
|
||||
});
|
||||
}
|
||||
SuperProp::Ident(id) => {
|
||||
let callee = self.super_set(&id.sym, left_span);
|
||||
*e = Expr::Call(CallExpr {
|
||||
span: *span,
|
||||
args: vec![(if let Some(op) = op.to_update() {
|
||||
Box::new(Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: Box::new(
|
||||
self.super_get(&id.sym, id.span)
|
||||
.as_call(id.span, Vec::new()),
|
||||
),
|
||||
op,
|
||||
right: right.take(),
|
||||
}))
|
||||
} else {
|
||||
right.take()
|
||||
})
|
||||
.as_arg()],
|
||||
callee: callee.as_callee(),
|
||||
type_args: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
e.visit_mut_children_with(self)
|
||||
}
|
||||
// super.foo() => super_get_foo = () => super.foo
|
||||
Expr::Call(CallExpr {
|
||||
span,
|
||||
callee: Callee::Expr(expr),
|
||||
args,
|
||||
..
|
||||
}) => {
|
||||
if !self.super_disabled {
|
||||
if let Expr::SuperProp(super_prop) = &mut **expr {
|
||||
match &mut super_prop.prop {
|
||||
SuperProp::Computed(c) => {
|
||||
let callee = self.super_get_computed(super_prop.span);
|
||||
let call = Expr::Call(CallExpr {
|
||||
span: *span,
|
||||
args: vec![c.expr.take().as_arg()],
|
||||
callee: callee.as_callee(),
|
||||
type_args: None,
|
||||
});
|
||||
let mut new_args = args.take();
|
||||
|
||||
new_args.insert(0, self.get_this().as_arg());
|
||||
|
||||
*e = call.call_fn(*span, new_args);
|
||||
}
|
||||
SuperProp::Ident(id) => {
|
||||
let callee = self.super_get(&id.sym, super_prop.span);
|
||||
let call = Expr::Call(CallExpr {
|
||||
span: *span,
|
||||
args: Vec::new(),
|
||||
callee: callee.as_callee(),
|
||||
type_args: None,
|
||||
});
|
||||
let mut new_args = args.take();
|
||||
|
||||
new_args.insert(0, self.get_this().as_arg());
|
||||
|
||||
*e = call.call_fn(*span, new_args);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
e.visit_mut_children_with(self)
|
||||
}
|
||||
// super.foo ++
|
||||
Expr::Update(UpdateExpr { arg, .. }) if arg.is_super_prop() => {
|
||||
let in_pat = self.in_pat;
|
||||
// NOTE: It's not in pat, but we need the `update` trick
|
||||
self.in_pat = true;
|
||||
arg.visit_mut_with(self);
|
||||
self.in_pat = in_pat;
|
||||
}
|
||||
Expr::SuperProp(SuperPropExpr { prop, span, .. }) if !self.super_disabled => match prop
|
||||
{
|
||||
SuperProp::Computed(c) => {
|
||||
c.expr.visit_mut_children_with(self);
|
||||
*e = if self.in_pat {
|
||||
Expr::Call(CallExpr {
|
||||
span: *span,
|
||||
args: vec![c.expr.take().as_arg()],
|
||||
callee: self.super_update_computed(*span).as_callee(),
|
||||
type_args: None,
|
||||
})
|
||||
.make_member(quote_ident!("_"))
|
||||
} else {
|
||||
Expr::Call(CallExpr {
|
||||
span: *span,
|
||||
args: vec![c.expr.take().as_arg()],
|
||||
callee: self.super_get_computed(*span).as_callee(),
|
||||
type_args: None,
|
||||
})
|
||||
};
|
||||
}
|
||||
SuperProp::Ident(id) => {
|
||||
*e = if self.in_pat {
|
||||
self.super_update(&id.sym, *span)
|
||||
.make_member(quote_ident!("_"))
|
||||
} else {
|
||||
Expr::Call(CallExpr {
|
||||
span: *span,
|
||||
args: Vec::new(),
|
||||
callee: self.super_get(&id.sym, *span).as_callee(),
|
||||
type_args: None,
|
||||
})
|
||||
};
|
||||
}
|
||||
},
|
||||
_ => e.visit_mut_children_with(self),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_block_stmt(&mut self, b: &mut BlockStmt) {
|
||||
b.visit_mut_children_with(self);
|
||||
|
||||
// we will not vist into fn/class so it's fine
|
||||
if !self.extra_ident.is_empty() {
|
||||
b.stmts.insert(
|
||||
0,
|
||||
Stmt::Decl(Decl::Var(Box::new(VarDecl {
|
||||
kind: VarDeclKind::Var,
|
||||
span: DUMMY_SP,
|
||||
decls: self
|
||||
.extra_ident
|
||||
.take()
|
||||
.into_iter()
|
||||
.map(|ident| VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: ident.into(),
|
||||
init: None,
|
||||
definite: false,
|
||||
})
|
||||
.collect(),
|
||||
declare: false,
|
||||
}))),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_block_stmt_or_expr(&mut self, b: &mut BlockStmtOrExpr) {
|
||||
b.visit_mut_children_with(self);
|
||||
|
||||
// we will not vist into fn/class so it's fine
|
||||
if !self.extra_ident.is_empty() {
|
||||
if let BlockStmtOrExpr::Expr(e) = b {
|
||||
*b = BlockStmtOrExpr::BlockStmt(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![
|
||||
Stmt::Decl(Decl::Var(Box::new(VarDecl {
|
||||
kind: VarDeclKind::Var,
|
||||
span: DUMMY_SP,
|
||||
decls: self
|
||||
.extra_ident
|
||||
.take()
|
||||
.into_iter()
|
||||
.map(|ident| VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: ident.into(),
|
||||
init: None,
|
||||
definite: false,
|
||||
})
|
||||
.collect(),
|
||||
declare: false,
|
||||
}))),
|
||||
Stmt::Return(ReturnStmt {
|
||||
span: e.span(),
|
||||
arg: Some(e.take()),
|
||||
}),
|
||||
],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Don't recurse into constructor
|
||||
fn visit_mut_class(&mut self, _: &mut Class) {}
|
||||
|
||||
/// Don't recurse into fn
|
||||
fn visit_mut_function(&mut self, _: &mut Function) {}
|
||||
|
||||
/// Don't recurse into getter/setter/method except computed key
|
||||
fn visit_mut_getter_prop(&mut self, p: &mut GetterProp) {
|
||||
if p.key.is_computed() {
|
||||
p.key.visit_mut_with(self);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_setter_prop(&mut self, p: &mut SetterProp) {
|
||||
if p.key.is_computed() {
|
||||
p.key.visit_mut_with(self);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_method_prop(&mut self, p: &mut MethodProp) {
|
||||
if p.key.is_computed() {
|
||||
p.key.visit_mut_with(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_this(stmts: &mut Vec<Stmt>, this_id: &Ident) {
|
||||
stmts.visit_mut_children_with(&mut InitThis { this_id })
|
||||
}
|
||||
|
||||
struct InitThis<'a> {
|
||||
this_id: &'a Ident,
|
||||
}
|
||||
|
||||
// babel is skip function and class property
|
||||
impl<'a> VisitMut for InitThis<'a> {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn visit_mut_class(&mut self, _: &mut Class) {}
|
||||
|
||||
// babel will transform super() to super(); _this = this
|
||||
// hopefully it will be meaningless
|
||||
// fn visit_mut_stmts(&mut self, stmt: &mut Vec<Stmt>) {}
|
||||
|
||||
fn visit_mut_expr(&mut self, expr: &mut Expr) {
|
||||
expr.visit_mut_children_with(self);
|
||||
|
||||
if let Expr::Call(
|
||||
call_expr @ CallExpr {
|
||||
callee: Callee::Super(..),
|
||||
..
|
||||
},
|
||||
) = expr
|
||||
{
|
||||
let span = call_expr.span;
|
||||
*expr = Expr::Paren(ParenExpr {
|
||||
span,
|
||||
expr: Box::new(Expr::Seq(SeqExpr {
|
||||
span,
|
||||
exprs: vec![
|
||||
Box::new(Expr::Call(call_expr.take())),
|
||||
Box::new(Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(self.this_id.clone().into()),
|
||||
op: AssignOp::Assign,
|
||||
right: Box::new(Expr::This(ThisExpr { span: DUMMY_SP })),
|
||||
})),
|
||||
],
|
||||
})),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn extend_super(
|
||||
decls: &mut Vec<VarDeclarator>,
|
||||
get: SuperField,
|
||||
set: SuperField,
|
||||
update: SuperField,
|
||||
) {
|
||||
decls.extend(update.ident.into_iter().map(|(key, ident)| {
|
||||
let value = private_ident!("v");
|
||||
VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: ident.into(),
|
||||
init: Some(Box::new(Expr::Object(ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: vec![
|
||||
Prop::Getter(GetterProp {
|
||||
span: DUMMY_SP,
|
||||
key: PropName::Ident(quote_ident!("_")),
|
||||
type_ann: None,
|
||||
body: Some(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![Expr::Ident(
|
||||
get.ident
|
||||
.get(&key)
|
||||
.cloned()
|
||||
.expect("getter not found")
|
||||
.without_loc(),
|
||||
)
|
||||
.as_call(DUMMY_SP, Default::default())
|
||||
.into_return_stmt()
|
||||
.into()],
|
||||
}),
|
||||
}),
|
||||
Prop::Setter(SetterProp {
|
||||
span: DUMMY_SP,
|
||||
key: PropName::Ident(quote_ident!("_")),
|
||||
param: value.clone().into(),
|
||||
body: Some(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![Expr::Ident(
|
||||
set.ident
|
||||
.get(&key)
|
||||
.cloned()
|
||||
.expect("setter not found")
|
||||
.without_loc(),
|
||||
)
|
||||
.as_call(DUMMY_SP, vec![value.as_arg()])
|
||||
.into_stmt()],
|
||||
}),
|
||||
}),
|
||||
]
|
||||
.into_iter()
|
||||
.map(Box::new)
|
||||
.map(From::from)
|
||||
.collect(),
|
||||
}))),
|
||||
definite: false,
|
||||
}
|
||||
}));
|
||||
if let Some(id) = update.computed {
|
||||
let prop = private_ident!("_prop");
|
||||
let value = private_ident!("v");
|
||||
|
||||
decls.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: id.into(),
|
||||
init: Some(Box::new(Expr::Arrow(ArrowExpr {
|
||||
span: DUMMY_SP,
|
||||
params: vec![prop.clone().into()],
|
||||
body: Box::new(BlockStmtOrExpr::Expr(Box::new(Expr::Object(ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: vec![
|
||||
Prop::Getter(GetterProp {
|
||||
span: DUMMY_SP,
|
||||
key: PropName::Ident(quote_ident!("_")),
|
||||
type_ann: None,
|
||||
body: Some(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![Expr::Ident(
|
||||
get.computed
|
||||
.clone()
|
||||
.expect("getter computed not found")
|
||||
.without_loc(),
|
||||
)
|
||||
.as_call(DUMMY_SP, vec![prop.clone().as_arg()])
|
||||
.into_return_stmt()
|
||||
.into()],
|
||||
}),
|
||||
}),
|
||||
Prop::Setter(SetterProp {
|
||||
span: DUMMY_SP,
|
||||
key: PropName::Ident(quote_ident!("_")),
|
||||
param: value.clone().into(),
|
||||
body: Some(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![Expr::Ident(
|
||||
set.computed
|
||||
.clone()
|
||||
.expect("setter computed not found")
|
||||
.without_loc(),
|
||||
)
|
||||
.as_call(DUMMY_SP, vec![prop.as_arg(), value.as_arg()])
|
||||
.into_return_stmt()
|
||||
.into()],
|
||||
}),
|
||||
}),
|
||||
]
|
||||
.into_iter()
|
||||
.map(Box::new)
|
||||
.map(From::from)
|
||||
.collect(),
|
||||
})))),
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
return_type: None,
|
||||
type_params: None,
|
||||
}))),
|
||||
definite: false,
|
||||
});
|
||||
}
|
||||
decls.extend(get.ident.into_iter().map(|(key, ident)| VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: ident.without_loc().into(),
|
||||
init: Some(Box::new(Expr::Arrow(ArrowExpr {
|
||||
span: DUMMY_SP,
|
||||
params: Vec::new(),
|
||||
body: Box::new(BlockStmtOrExpr::Expr(Box::new(Expr::SuperProp(
|
||||
SuperPropExpr {
|
||||
obj: Super { span: DUMMY_SP },
|
||||
prop: SuperProp::Ident(quote_ident!(key)),
|
||||
span: DUMMY_SP,
|
||||
},
|
||||
)))),
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
return_type: None,
|
||||
type_params: None,
|
||||
}))),
|
||||
definite: false,
|
||||
}));
|
||||
if let Some(id) = get.computed {
|
||||
let param = private_ident!("_prop");
|
||||
decls.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: id.without_loc().into(),
|
||||
init: Some(Box::new(Expr::Arrow(ArrowExpr {
|
||||
span: DUMMY_SP,
|
||||
params: vec![param.clone().into()],
|
||||
body: Box::new(BlockStmtOrExpr::Expr(Box::new(Expr::SuperProp(
|
||||
SuperPropExpr {
|
||||
obj: Super { span: DUMMY_SP },
|
||||
prop: SuperProp::Computed(ComputedPropName {
|
||||
span: DUMMY_SP,
|
||||
expr: Box::new(Expr::Ident(param)),
|
||||
}),
|
||||
span: DUMMY_SP,
|
||||
},
|
||||
)))),
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
return_type: None,
|
||||
type_params: None,
|
||||
}))),
|
||||
definite: false,
|
||||
});
|
||||
}
|
||||
decls.extend(set.ident.into_iter().map(|(key, ident)| {
|
||||
let value = private_ident!("_value");
|
||||
VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: ident.without_loc().into(),
|
||||
init: Some(Box::new(Expr::Arrow(ArrowExpr {
|
||||
span: DUMMY_SP,
|
||||
params: vec![value.clone().into()],
|
||||
body: Box::new(BlockStmtOrExpr::Expr(Box::new(Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Expr(Box::new(Expr::SuperProp(SuperPropExpr {
|
||||
obj: Super { span: DUMMY_SP },
|
||||
prop: SuperProp::Ident(quote_ident!(key)),
|
||||
span: DUMMY_SP,
|
||||
}))),
|
||||
op: op!("="),
|
||||
right: Box::new(Expr::Ident(value)),
|
||||
})))),
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
return_type: None,
|
||||
type_params: None,
|
||||
}))),
|
||||
definite: false,
|
||||
}
|
||||
}));
|
||||
if let Some(id) = set.computed {
|
||||
let prop = private_ident!("_prop");
|
||||
let value = private_ident!("_value");
|
||||
decls.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: id.without_loc().into(),
|
||||
init: Some(Box::new(Expr::Arrow(ArrowExpr {
|
||||
span: DUMMY_SP,
|
||||
params: vec![prop.clone().into(), value.clone().into()],
|
||||
body: Box::new(BlockStmtOrExpr::Expr(Box::new(Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Expr(Box::new(Expr::SuperProp(SuperPropExpr {
|
||||
obj: Super { span: DUMMY_SP },
|
||||
prop: SuperProp::Computed(ComputedPropName {
|
||||
span: DUMMY_SP,
|
||||
expr: Box::new(Expr::Ident(prop)),
|
||||
}),
|
||||
span: DUMMY_SP,
|
||||
}))),
|
||||
op: op!("="),
|
||||
right: Box::new(Expr::Ident(value)),
|
||||
})))),
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
return_type: None,
|
||||
type_params: None,
|
||||
}))),
|
||||
definite: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
434
third-party/vendor/swc_ecma_utils/src/function/function_wrapper.rs
vendored
Normal file
434
third-party/vendor/swc_ecma_utils/src/function/function_wrapper.rs
vendored
Normal file
|
|
@ -0,0 +1,434 @@
|
|||
use std::marker::PhantomData;
|
||||
|
||||
use swc_common::{util::take::Take, Spanned, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
|
||||
use crate::ExprFactory;
|
||||
|
||||
pub struct FunctionWrapper<T> {
|
||||
pub binding_ident: Option<Ident>,
|
||||
pub function: Expr,
|
||||
|
||||
pub ignore_function_name: bool,
|
||||
pub ignore_function_length: bool,
|
||||
|
||||
function_ident: Option<Ident>,
|
||||
params: Vec<Param>,
|
||||
|
||||
_type: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> FunctionWrapper<T> {
|
||||
/// `get_params` clone only the parameters that count in function length.
|
||||
fn get_params<'a, ParamsIter, Item>(params_iter: ParamsIter) -> Vec<Param>
|
||||
where
|
||||
Item: Into<&'a Param>,
|
||||
ParamsIter: IntoIterator<Item = Item>,
|
||||
{
|
||||
params_iter
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
.map_while(|param| match param.pat {
|
||||
Pat::Ident(..) => Some(param.clone()),
|
||||
Pat::Array(..) | Pat::Object(..) => Some(Param {
|
||||
span: param.span,
|
||||
decorators: param.decorators.clone(),
|
||||
pat: Pat::Ident(private_ident!("_").into()),
|
||||
}),
|
||||
_ => None,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
///
|
||||
/// ```javascript
|
||||
/// (function () {
|
||||
/// var REF = FUNCTION;
|
||||
/// return function NAME(PARAMS) {
|
||||
/// return REF.apply(this, arguments);
|
||||
/// };
|
||||
/// })()
|
||||
/// ```
|
||||
fn build_anonymous_expression_wrapper(&mut self) -> Expr {
|
||||
let name_ident = self.binding_ident.take();
|
||||
let ref_ident = private_ident!("_ref");
|
||||
|
||||
let ref_decl: Decl = Box::new(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(ref_ident.clone().into()),
|
||||
init: Some(Box::new(self.function.take())),
|
||||
definite: false,
|
||||
}],
|
||||
declare: false,
|
||||
})
|
||||
.into();
|
||||
|
||||
let return_fn_stmt = {
|
||||
let fn_expr = self.build_function_forward(ref_ident, name_ident);
|
||||
|
||||
ReturnStmt {
|
||||
span: DUMMY_SP,
|
||||
arg: Some(Box::new(fn_expr.into())),
|
||||
}
|
||||
}
|
||||
.into();
|
||||
|
||||
let block_stmt = BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![ref_decl.into(), return_fn_stmt],
|
||||
};
|
||||
|
||||
let function = Box::new(Function {
|
||||
span: DUMMY_SP,
|
||||
body: Some(block_stmt),
|
||||
params: Default::default(),
|
||||
is_generator: false,
|
||||
is_async: false,
|
||||
decorators: Default::default(),
|
||||
return_type: Default::default(),
|
||||
type_params: Default::default(),
|
||||
});
|
||||
|
||||
FnExpr {
|
||||
ident: None,
|
||||
function,
|
||||
}
|
||||
.as_iife()
|
||||
.into()
|
||||
}
|
||||
|
||||
///
|
||||
/// ```javascript
|
||||
/// (function () {
|
||||
/// var REF = FUNCTION;
|
||||
/// function NAME(PARAMS) {
|
||||
/// return REF.apply(this, arguments);
|
||||
/// }
|
||||
/// return NAME;
|
||||
/// })()
|
||||
/// ```
|
||||
fn build_named_expression_wrapper(&mut self, name_ident: Ident) -> Expr {
|
||||
let ref_ident = self.function_ident.as_ref().map_or_else(
|
||||
|| private_ident!("_ref"),
|
||||
|ident| private_ident!(ident.span, format!("_{}", ident.sym)),
|
||||
);
|
||||
|
||||
let ref_stmt: Stmt = Stmt::Decl(
|
||||
Box::new(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(ref_ident.clone().into()),
|
||||
init: Some(Box::new(self.function.take())),
|
||||
definite: false,
|
||||
}],
|
||||
declare: false,
|
||||
})
|
||||
.into(),
|
||||
);
|
||||
|
||||
let fn_decl_stmt = {
|
||||
let FnExpr { function, .. } = self.build_function_forward(ref_ident, None);
|
||||
|
||||
Stmt::Decl(
|
||||
FnDecl {
|
||||
ident: name_ident.clone(),
|
||||
declare: false,
|
||||
function,
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
};
|
||||
|
||||
let return_stmt = Stmt::Return(ReturnStmt {
|
||||
span: DUMMY_SP,
|
||||
arg: Some(Box::new(name_ident.into())),
|
||||
});
|
||||
|
||||
let block_stmt = BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![ref_stmt, fn_decl_stmt, return_stmt],
|
||||
};
|
||||
|
||||
let function = Box::new(Function {
|
||||
span: DUMMY_SP,
|
||||
body: Some(block_stmt),
|
||||
params: Default::default(),
|
||||
is_generator: false,
|
||||
is_async: false,
|
||||
decorators: Default::default(),
|
||||
return_type: Default::default(),
|
||||
type_params: Default::default(),
|
||||
});
|
||||
|
||||
FnExpr {
|
||||
ident: None,
|
||||
function,
|
||||
}
|
||||
.as_iife()
|
||||
.into()
|
||||
}
|
||||
|
||||
///
|
||||
/// ```javascript
|
||||
/// function NAME(PARAMS) {
|
||||
/// return REF.apply(this, arguments);
|
||||
/// }
|
||||
/// function REF() {
|
||||
/// REF = FUNCTION;
|
||||
/// return REF.apply(this, arguments);
|
||||
/// }
|
||||
/// ```
|
||||
fn build_declaration_wrapper(&mut self, name_ident: Option<Ident>) -> (FnExpr, FnDecl) {
|
||||
let ref_ident = self.function_ident.as_ref().map_or_else(
|
||||
|| private_ident!("_ref"),
|
||||
|ident| private_ident!(ident.span, format!("_{}", ident.sym)),
|
||||
);
|
||||
|
||||
// function NAME
|
||||
let fn_expr = self.build_function_forward(ref_ident.clone(), name_ident);
|
||||
|
||||
let assign_stmt = AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
op: op!("="),
|
||||
left: PatOrExpr::Expr(Box::new(Expr::Ident(ref_ident.clone()))),
|
||||
right: Box::new(self.function.take()),
|
||||
}
|
||||
.into_stmt();
|
||||
|
||||
// clone `return REF.apply(this, arguments);`
|
||||
let return_ref_apply_stmt = fn_expr
|
||||
.function
|
||||
.body
|
||||
.as_ref()
|
||||
.expect("The `fn_expr` we construct cannot be None")
|
||||
.stmts[0]
|
||||
.clone();
|
||||
|
||||
let ref_fn_block_stmt = BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![assign_stmt, return_ref_apply_stmt],
|
||||
};
|
||||
|
||||
// function REF
|
||||
let ref_decl = FnDecl {
|
||||
declare: false,
|
||||
ident: ref_ident,
|
||||
function: Box::new(Function {
|
||||
span: DUMMY_SP,
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
params: self.params.take(),
|
||||
body: Some(ref_fn_block_stmt),
|
||||
decorators: Default::default(),
|
||||
type_params: Default::default(),
|
||||
return_type: Default::default(),
|
||||
}),
|
||||
};
|
||||
|
||||
(fn_expr, ref_decl)
|
||||
}
|
||||
|
||||
///
|
||||
/// ```javascript
|
||||
/// function NAME(PARAMS) {
|
||||
/// return REF.apply(this, arguments);
|
||||
/// }
|
||||
/// ```
|
||||
fn build_function_forward(&mut self, ref_ident: Ident, name_ident: Option<Ident>) -> FnExpr {
|
||||
let apply = Stmt::Return(ReturnStmt {
|
||||
span: DUMMY_SP,
|
||||
arg: Some(Box::new(ref_ident.apply(
|
||||
DUMMY_SP,
|
||||
Box::new(Expr::This(ThisExpr { span: DUMMY_SP })),
|
||||
vec![quote_ident!("arguments").as_arg()],
|
||||
))),
|
||||
});
|
||||
|
||||
FnExpr {
|
||||
ident: name_ident,
|
||||
function: Box::new(Function {
|
||||
params: self.params.take(),
|
||||
decorators: Default::default(),
|
||||
span: DUMMY_SP,
|
||||
body: Some(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![apply],
|
||||
}),
|
||||
is_generator: false,
|
||||
is_async: false,
|
||||
type_params: Default::default(),
|
||||
return_type: Default::default(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FnExpr> for FunctionWrapper<Expr> {
|
||||
fn from(mut fn_expr: FnExpr) -> Self {
|
||||
let function_ident = fn_expr.ident.take();
|
||||
let params = Self::get_params(fn_expr.function.params.iter());
|
||||
Self {
|
||||
binding_ident: None,
|
||||
function_ident,
|
||||
params,
|
||||
ignore_function_name: false,
|
||||
ignore_function_length: false,
|
||||
function: fn_expr.into(),
|
||||
_type: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ArrowExpr> for FunctionWrapper<Expr> {
|
||||
fn from(
|
||||
ArrowExpr {
|
||||
span,
|
||||
params,
|
||||
body,
|
||||
is_async,
|
||||
is_generator,
|
||||
..
|
||||
}: ArrowExpr,
|
||||
) -> Self {
|
||||
let body = Some(match *body {
|
||||
BlockStmtOrExpr::BlockStmt(block) => block,
|
||||
BlockStmtOrExpr::Expr(expr) => BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![Stmt::Return(ReturnStmt {
|
||||
span: expr.span(),
|
||||
arg: Some(expr),
|
||||
})],
|
||||
},
|
||||
});
|
||||
|
||||
let function = Box::new(Function {
|
||||
span,
|
||||
params: params.into_iter().map(Into::into).collect(),
|
||||
decorators: Default::default(),
|
||||
body,
|
||||
type_params: None,
|
||||
return_type: None,
|
||||
is_generator,
|
||||
is_async,
|
||||
});
|
||||
|
||||
let fn_expr = FnExpr {
|
||||
ident: None,
|
||||
function,
|
||||
};
|
||||
|
||||
Self {
|
||||
binding_ident: None,
|
||||
function_ident: None,
|
||||
ignore_function_name: false,
|
||||
ignore_function_length: false,
|
||||
params: Self::get_params(fn_expr.function.params.iter()),
|
||||
function: fn_expr.into(),
|
||||
_type: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::from_over_into)]
|
||||
impl Into<Expr> for FunctionWrapper<Expr> {
|
||||
/// If a function has a function name, it may be called recursively.
|
||||
/// We use the named expression to hoist the function name internally
|
||||
/// Therefore, its recursive calls refer to the correct identity.
|
||||
///
|
||||
/// Else
|
||||
/// if a function has a binding name, it may be called recursively as well.
|
||||
/// But it refer the binding name which exist the outer scope.
|
||||
/// It is safe to using anonymous expression wrapper.
|
||||
///
|
||||
/// Optimization:
|
||||
/// A function without a name cannot be recursively referenced by Ident.
|
||||
/// It's safe to return the expr without wrapper if the params.len is 0.
|
||||
fn into(mut self) -> Expr {
|
||||
if let Some(name_ident) = self.function_ident.as_ref().cloned() {
|
||||
self.build_named_expression_wrapper(name_ident)
|
||||
} else if (!self.ignore_function_name && self.binding_ident.is_some())
|
||||
|| (!self.ignore_function_length && !self.params.is_empty())
|
||||
{
|
||||
self.build_anonymous_expression_wrapper()
|
||||
} else {
|
||||
self.function
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FnDecl> for FunctionWrapper<FnDecl> {
|
||||
fn from(mut fn_decl: FnDecl) -> Self {
|
||||
let function_ident = Some(fn_decl.ident.take());
|
||||
let params = Self::get_params(fn_decl.function.params.iter());
|
||||
Self {
|
||||
binding_ident: None,
|
||||
function_ident,
|
||||
params,
|
||||
ignore_function_name: false,
|
||||
ignore_function_length: false,
|
||||
function: FnExpr {
|
||||
ident: None,
|
||||
function: fn_decl.function,
|
||||
}
|
||||
.into(),
|
||||
_type: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// The result of declaration wrapper includes two parts.
|
||||
/// `name_fn` is used to replace the original function.
|
||||
/// `ref_fn` is an extra function called internally by `name_fn`.
|
||||
///
|
||||
/// ```javascript
|
||||
/// function NAME(PARAMS) {
|
||||
/// return REF.apply(this, arguments);
|
||||
/// }
|
||||
/// function REF() {
|
||||
/// REF = FUNCTION;
|
||||
/// return REF.apply(this, arguments);
|
||||
/// }
|
||||
/// ```
|
||||
pub struct FnWrapperResult<N, R> {
|
||||
pub name_fn: N,
|
||||
pub ref_fn: R,
|
||||
}
|
||||
|
||||
impl From<FunctionWrapper<FnDecl>> for FnWrapperResult<FnDecl, FnDecl> {
|
||||
fn from(mut value: FunctionWrapper<FnDecl>) -> Self {
|
||||
let name_ident = value
|
||||
.function_ident
|
||||
.clone()
|
||||
.expect("`FunctionWrapper` converted from `FnDecl` definitely has `Ident`");
|
||||
|
||||
let (FnExpr { function, .. }, ref_fn) = value.build_declaration_wrapper(None);
|
||||
|
||||
FnWrapperResult {
|
||||
name_fn: FnDecl {
|
||||
ident: name_ident,
|
||||
declare: false,
|
||||
function,
|
||||
},
|
||||
ref_fn,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FunctionWrapper<Expr>> for FnWrapperResult<FnExpr, FnDecl> {
|
||||
fn from(mut value: FunctionWrapper<Expr>) -> Self {
|
||||
let name_ident = value
|
||||
.function_ident
|
||||
.clone()
|
||||
.or_else(|| value.binding_ident.clone());
|
||||
|
||||
let (name_fn, ref_fn) = value.build_declaration_wrapper(name_ident);
|
||||
|
||||
FnWrapperResult { name_fn, ref_fn }
|
||||
}
|
||||
}
|
||||
5
third-party/vendor/swc_ecma_utils/src/function/mod.rs
vendored
Normal file
5
third-party/vendor/swc_ecma_utils/src/function/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
mod fn_env_hoister;
|
||||
mod function_wrapper;
|
||||
|
||||
pub use fn_env_hoister::*;
|
||||
pub use function_wrapper::*;
|
||||
80
third-party/vendor/swc_ecma_utils/src/ident.rs
vendored
Normal file
80
third-party/vendor/swc_ecma_utils/src/ident.rs
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
use swc_atoms::JsWord;
|
||||
use swc_common::{Span, SyntaxContext};
|
||||
use swc_ecma_ast::{BindingIdent, Id, Ident};
|
||||
|
||||
pub trait IdentLike: Sized {
|
||||
fn from_ident(i: &Ident) -> Self;
|
||||
fn to_id(&self) -> Id;
|
||||
fn into_id(self) -> Id;
|
||||
}
|
||||
|
||||
impl IdentLike for BindingIdent {
|
||||
fn from_ident(i: &Ident) -> Self {
|
||||
i.clone().into()
|
||||
}
|
||||
|
||||
fn to_id(&self) -> Id {
|
||||
(self.id.sym.clone(), self.id.span.ctxt())
|
||||
}
|
||||
|
||||
fn into_id(self) -> Id {
|
||||
self.id.into_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl IdentLike for (JsWord, Span) {
|
||||
#[inline]
|
||||
fn from_ident(i: &Ident) -> Self {
|
||||
(i.sym.clone(), i.span)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_id(&self) -> Id {
|
||||
(self.0.clone(), self.1.ctxt())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_id(self) -> Id {
|
||||
(self.0, self.1.ctxt())
|
||||
}
|
||||
}
|
||||
|
||||
impl IdentLike for (JsWord, SyntaxContext) {
|
||||
#[inline]
|
||||
fn from_ident(i: &Ident) -> Self {
|
||||
(i.sym.clone(), i.span.ctxt())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_id(&self) -> Id {
|
||||
(self.0.clone(), self.1)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_id(self) -> Id {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl IdentLike for Ident {
|
||||
#[inline]
|
||||
fn from_ident(i: &Ident) -> Self {
|
||||
Ident::new(i.sym.clone(), i.span)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_id(&self) -> Id {
|
||||
(self.sym.clone(), self.span.ctxt())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_id(self) -> Id {
|
||||
(self.sym, self.span.ctxt())
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated = "Use i.to_id() instead"]
|
||||
#[inline(always)]
|
||||
pub fn id(i: &Ident) -> Id {
|
||||
(i.sym.clone(), i.span.ctxt())
|
||||
}
|
||||
3104
third-party/vendor/swc_ecma_utils/src/lib.rs
vendored
Normal file
3104
third-party/vendor/swc_ecma_utils/src/lib.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
118
third-party/vendor/swc_ecma_utils/src/macros.rs
vendored
Normal file
118
third-party/vendor/swc_ecma_utils/src/macros.rs
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/// Shortcut for `quote_ident!(span.apply_mark(Mark::fresh(Mark::root())), s)`
|
||||
#[macro_export]
|
||||
macro_rules! private_ident {
|
||||
($s:expr) => {
|
||||
private_ident!($crate::swc_common::DUMMY_SP, $s)
|
||||
};
|
||||
($span:expr, $s:expr) => {{
|
||||
let mark = $crate::swc_common::Mark::fresh($crate::swc_common::Mark::root());
|
||||
let span = $span.apply_mark(mark);
|
||||
$crate::swc_ecma_ast::Ident::new($s.into(), span)
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! quote_ident {
|
||||
($s:expr) => {
|
||||
quote_ident!($crate::swc_common::DUMMY_SP, $s)
|
||||
};
|
||||
($span:expr, $s:expr) => {{
|
||||
$crate::swc_ecma_ast::Ident::new($s.into(), $span)
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! quote_str {
|
||||
($s:expr) => {
|
||||
quote_str!($crate::swc_common::DUMMY_SP, $s)
|
||||
};
|
||||
($span:expr, $s:expr) => {{
|
||||
$crate::swc_ecma_ast::Str {
|
||||
span: $span,
|
||||
raw: None,
|
||||
value: $s.into(),
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! quote_expr {
|
||||
($span:expr, null) => {{
|
||||
use $crate::swc_ecma_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](swc_ecma_ast::Expr)>.
|
||||
#[macro_export]
|
||||
macro_rules! member_expr {
|
||||
($span:expr, $first:ident) => {{
|
||||
use $crate::swc_ecma_ast::Expr;
|
||||
Box::new(Expr::Ident($crate::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)* ) => {{
|
||||
use $crate::swc_ecma_ast::MemberProp;
|
||||
let prop = MemberProp::Ident($crate::quote_ident!($span, stringify!($first)));
|
||||
|
||||
member_expr!(@EXT, $span, Box::new(Expr::Member(MemberExpr{
|
||||
span: $crate::swc_common::DUMMY_SP,
|
||||
obj: $obj,
|
||||
prop,
|
||||
})), $($rest)*)
|
||||
}};
|
||||
|
||||
(@EXT, $span:expr, $obj:expr, $first:ident) => {{
|
||||
use $crate::swc_ecma_ast::*;
|
||||
let prop = MemberProp::Ident($crate::quote_ident!($span, stringify!($first)));
|
||||
|
||||
Box::new(Expr::Member(MemberExpr{
|
||||
span: $crate::swc_common::DUMMY_SP,
|
||||
obj: $obj,
|
||||
prop,
|
||||
}))
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use swc_common::DUMMY_SP as span;
|
||||
use swc_ecma_ast::*;
|
||||
|
||||
use crate::drop_span;
|
||||
|
||||
#[test]
|
||||
fn quote_member_expr() {
|
||||
let expr: Box<Expr> = drop_span(member_expr!(span, Function.prototype.bind));
|
||||
|
||||
assert_eq!(
|
||||
expr,
|
||||
Box::new(Expr::Member(MemberExpr {
|
||||
span,
|
||||
obj: Box::new(Expr::Member(MemberExpr {
|
||||
span,
|
||||
obj: member_expr!(span, Function),
|
||||
prop: MemberProp::Ident(quote_ident!(span, "prototype")),
|
||||
})),
|
||||
prop: MemberProp::Ident(quote_ident!(span, "bind")),
|
||||
}))
|
||||
);
|
||||
}
|
||||
}
|
||||
136
third-party/vendor/swc_ecma_utils/src/node_ignore_span.rs
vendored
Normal file
136
third-party/vendor/swc_ecma_utils/src/node_ignore_span.rs
vendored
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
use std::{borrow::Cow, fmt::Debug, hash::Hash};
|
||||
|
||||
use swc_common::EqIgnoreSpan;
|
||||
use swc_ecma_ast::{Expr, MemberProp};
|
||||
|
||||
/// A newtype that will ignore Span while doing `eq` or `hash`.
|
||||
pub struct NodeIgnoringSpan<'a, Node: ToOwned + Debug>(Cow<'a, Node>);
|
||||
|
||||
impl<'a, Node: ToOwned + Debug> Debug for NodeIgnoringSpan<'a, Node> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("NodeIgnoringSpan").field(&*self.0).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Node: ToOwned + Debug> NodeIgnoringSpan<'a, Node> {
|
||||
#[inline]
|
||||
pub fn borrowed(expr: &'a Node) -> Self {
|
||||
Self(Cow::Borrowed(expr))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn owned(expr: <Node as ToOwned>::Owned) -> Self {
|
||||
Self(Cow::Owned(expr))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Node: EqIgnoreSpan + ToOwned + Debug> PartialEq for NodeIgnoringSpan<'a, Node> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0.eq_ignore_span(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Node: EqIgnoreSpan + ToOwned + Debug> Eq for NodeIgnoringSpan<'a, Node> {}
|
||||
|
||||
// TODO: This is only a workaround for Expr. we need something like
|
||||
// `hash_ignore_span` for each node in the end.
|
||||
impl<'a> Hash for NodeIgnoringSpan<'a, Expr> {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
// In pratice, most of cases/input we are dealing with are Expr::Member or
|
||||
// Expr::Ident.
|
||||
match &*self.0 {
|
||||
Expr::Ident(i) => {
|
||||
i.sym.hash(state);
|
||||
}
|
||||
Expr::Member(i) => {
|
||||
{
|
||||
NodeIgnoringSpan::borrowed(i.obj.as_ref()).hash(state);
|
||||
}
|
||||
if let MemberProp::Ident(prop) = &i.prop {
|
||||
prop.sym.hash(state);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Other expression kinds would fallback to the same empty hash.
|
||||
// So, they will spend linear time to do comparisons.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash_eq_ignore_span_expr_ref() {
|
||||
use rustc_hash::FxHashSet;
|
||||
use swc_common::{util::take::Take, Mark, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
|
||||
use crate::{member_expr, quote_expr};
|
||||
|
||||
fn expr_ref(expr_ref: &Expr) -> NodeIgnoringSpan<Expr> {
|
||||
NodeIgnoringSpan::borrowed(expr_ref)
|
||||
}
|
||||
|
||||
testing::run_test(false, |_cm, _handler| {
|
||||
Ident::within_ignored_ctxt(|| {
|
||||
let dummy_sp = DUMMY_SP;
|
||||
let meaningful_sp = dummy_sp.apply_mark(Mark::new());
|
||||
|
||||
let meaningful_ident_expr = Expr::Ident(Ident::new("foo".into(), meaningful_sp));
|
||||
let dummy_ident_expr = Expr::Ident(Ident::new("foo".into(), dummy_sp));
|
||||
|
||||
let meaningful_member_expr = member_expr!(meaningful_sp, foo.bar);
|
||||
let dummy_member_expr = member_expr!(dummy_sp, foo.bar);
|
||||
|
||||
let meaningful_null_expr = quote_expr!(meaningful_sp, null);
|
||||
let dummy_null_expr = quote_expr!(dummy_sp, null);
|
||||
|
||||
let meaningful_array_expr = Box::new(Expr::Array(ArrayLit {
|
||||
span: meaningful_sp,
|
||||
elems: Default::default(),
|
||||
}));
|
||||
|
||||
let dummy_array_expr = Box::new(Expr::Array(ArrayLit::dummy()));
|
||||
|
||||
// Should equal ignoring span and syntax context
|
||||
assert_eq!(
|
||||
expr_ref(&meaningful_ident_expr),
|
||||
expr_ref(&dummy_ident_expr)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
expr_ref(&meaningful_array_expr),
|
||||
expr_ref(&dummy_array_expr)
|
||||
);
|
||||
|
||||
let mut set = FxHashSet::from_iter([
|
||||
expr_ref(&meaningful_ident_expr),
|
||||
expr_ref(&meaningful_member_expr),
|
||||
expr_ref(&meaningful_null_expr),
|
||||
expr_ref(&meaningful_array_expr),
|
||||
]);
|
||||
|
||||
// Should produce the same hash value ignoring span and syntax
|
||||
assert!(set.contains(&expr_ref(&dummy_ident_expr)));
|
||||
assert!(set.contains(&expr_ref(&dummy_member_expr)));
|
||||
assert!(set.contains(&expr_ref(&dummy_null_expr)));
|
||||
assert!(set.contains(&expr_ref(&dummy_array_expr)));
|
||||
|
||||
set.insert(expr_ref(&dummy_ident_expr));
|
||||
set.insert(expr_ref(&dummy_member_expr));
|
||||
set.insert(expr_ref(&dummy_null_expr));
|
||||
set.insert(expr_ref(&dummy_array_expr));
|
||||
assert_eq!(set.len(), 4);
|
||||
|
||||
// Should not equal ignoring span and syntax context
|
||||
let dummy_ident_expr = Expr::Ident(Ident::new("baz".into(), dummy_sp));
|
||||
let dummy_member_expr = member_expr!(dummy_sp, baz.bar);
|
||||
let dummy_arrow_expr = Box::new(Expr::Arrow(ArrowExpr::dummy()));
|
||||
assert!(!set.contains(&expr_ref(&dummy_ident_expr)));
|
||||
assert!(!set.contains(&expr_ref(&dummy_member_expr)));
|
||||
assert!(!set.contains(&expr_ref(&dummy_arrow_expr)));
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
187
third-party/vendor/swc_ecma_utils/src/parallel.rs
vendored
Normal file
187
third-party/vendor/swc_ecma_utils/src/parallel.rs
vendored
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
//! Module for parallel processing
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use swc_common::GLOBALS;
|
||||
use swc_ecma_ast::*;
|
||||
|
||||
static CPU_COUNT: Lazy<usize> = Lazy::new(num_cpus::get);
|
||||
|
||||
pub fn cpu_count() -> usize {
|
||||
*CPU_COUNT
|
||||
}
|
||||
|
||||
pub trait Parallel: swc_common::sync::Send + swc_common::sync::Sync {
|
||||
/// Used to create visitor.
|
||||
fn create(&self) -> Self;
|
||||
|
||||
/// This can be called in anytime.
|
||||
fn merge(&mut self, other: Self);
|
||||
|
||||
/// Invoked after visiting all [Stmt]s, possibly in parallel.
|
||||
fn after_stmts(&mut self, _stmts: &mut Vec<Stmt>) {}
|
||||
|
||||
/// Invoked after visiting all [ModuleItem]s, possibly in parallel.
|
||||
fn after_module_items(&mut self, _stmts: &mut Vec<ModuleItem>) {}
|
||||
}
|
||||
|
||||
/// This is considered as a private type and it's NOT A PUBLIC API.
|
||||
#[cfg(feature = "concurrent")]
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
pub trait Items:
|
||||
rayon::iter::IntoParallelIterator<Iter = Self::ParIter> + IntoIterator<Item = Self::Elem>
|
||||
{
|
||||
type Elem: Send + Sync;
|
||||
|
||||
type ParIter: rayon::iter::ParallelIterator<Item = Self::Elem>
|
||||
+ rayon::iter::IndexedParallelIterator;
|
||||
|
||||
fn len(&self) -> usize;
|
||||
}
|
||||
|
||||
/// This is considered as a private type and it's NOT A PUBLIC API.
|
||||
#[cfg(not(feature = "concurrent"))]
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
pub trait Items: IntoIterator<Item = Self::Elem> {
|
||||
type Elem: Send + Sync;
|
||||
|
||||
fn len(&self) -> usize;
|
||||
}
|
||||
|
||||
impl<T> Items for Vec<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
type Elem = T;
|
||||
#[cfg(feature = "concurrent")]
|
||||
type ParIter = rayon::vec::IntoIter<T>;
|
||||
|
||||
fn len(&self) -> usize {
|
||||
Vec::len(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Items for &'a mut Vec<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
type Elem = &'a mut T;
|
||||
#[cfg(feature = "concurrent")]
|
||||
type ParIter = rayon::slice::IterMut<'a, T>;
|
||||
|
||||
fn len(&self) -> usize {
|
||||
Vec::len(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Items for &'a mut [T]
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
type Elem = &'a mut T;
|
||||
#[cfg(feature = "concurrent")]
|
||||
type ParIter = rayon::slice::IterMut<'a, T>;
|
||||
|
||||
fn len(&self) -> usize {
|
||||
<[T]>::len(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Items for &'a [T]
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
type Elem = &'a T;
|
||||
#[cfg(feature = "concurrent")]
|
||||
type ParIter = rayon::slice::Iter<'a, T>;
|
||||
|
||||
fn len(&self) -> usize {
|
||||
<[T]>::len(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ParallelExt: Parallel {
|
||||
/// Invoke `op` in parallel, if `swc_ecma_utils` is compiled with
|
||||
/// concurrent feature enabled and `nodes.len()` is bigger than threshold.
|
||||
///
|
||||
///
|
||||
/// This configures [GLOBALS], while not configuring [HANDLER] nor [HELPERS]
|
||||
fn maybe_par<I, F>(&mut self, threshold: usize, nodes: I, op: F)
|
||||
where
|
||||
I: Items,
|
||||
F: Send + Sync + Fn(&mut Self, I::Elem),
|
||||
{
|
||||
self.maybe_par_idx(threshold, nodes, |v, _, n| op(v, n))
|
||||
}
|
||||
|
||||
/// Invoke `op` in parallel, if `swc_ecma_utils` is compiled with
|
||||
/// concurrent feature enabled and `nodes.len()` is bigger than threshold.
|
||||
///
|
||||
///
|
||||
/// This configures [GLOBALS], while not configuring [HANDLER] nor [HELPERS]
|
||||
fn maybe_par_idx<I, F>(&mut self, threshold: usize, nodes: I, op: F)
|
||||
where
|
||||
I: Items,
|
||||
F: Send + Sync + Fn(&mut Self, usize, I::Elem);
|
||||
}
|
||||
|
||||
#[cfg(feature = "concurrent")]
|
||||
impl<T> ParallelExt for T
|
||||
where
|
||||
T: Parallel,
|
||||
{
|
||||
fn maybe_par_idx<I, F>(&mut self, threshold: usize, nodes: I, op: F)
|
||||
where
|
||||
I: Items,
|
||||
F: Send + Sync + Fn(&mut Self, usize, I::Elem),
|
||||
{
|
||||
if nodes.len() >= threshold || option_env!("SWC_FORCE_CONCURRENT") == Some("1") {
|
||||
GLOBALS.with(|globals| {
|
||||
use rayon::prelude::*;
|
||||
|
||||
let visitor = nodes
|
||||
.into_par_iter()
|
||||
.enumerate()
|
||||
.map(|(idx, node)| {
|
||||
GLOBALS.set(globals, || {
|
||||
let mut visitor = Parallel::create(&*self);
|
||||
op(&mut visitor, idx, node);
|
||||
|
||||
visitor
|
||||
})
|
||||
})
|
||||
.reduce(
|
||||
|| Parallel::create(&*self),
|
||||
|mut a, b| {
|
||||
Parallel::merge(&mut a, b);
|
||||
|
||||
a
|
||||
},
|
||||
);
|
||||
|
||||
Parallel::merge(self, visitor);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (idx, n) in nodes.into_iter().enumerate() {
|
||||
op(self, idx, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "concurrent"))]
|
||||
impl<T> ParallelExt for T
|
||||
where
|
||||
T: Parallel,
|
||||
{
|
||||
fn maybe_par_idx<I, F>(&mut self, _threshold: usize, nodes: I, op: F)
|
||||
where
|
||||
I: Items,
|
||||
F: Send + Sync + Fn(&mut Self, usize, I::Elem),
|
||||
{
|
||||
for (idx, n) in nodes.into_iter().enumerate() {
|
||||
op(self, idx, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
110
third-party/vendor/swc_ecma_utils/src/value.rs
vendored
Normal file
110
third-party/vendor/swc_ecma_utils/src/value.rs
vendored
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
use std::ops::Not;
|
||||
|
||||
use self::Value::{Known, Unknown};
|
||||
|
||||
/// Runtime value.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum Value<T> {
|
||||
Known(T),
|
||||
/// Not determined at compile time.`
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// Type of value.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum Type {
|
||||
Undefined,
|
||||
Null,
|
||||
Bool,
|
||||
Str,
|
||||
Symbol,
|
||||
Num,
|
||||
Obj,
|
||||
}
|
||||
|
||||
impl Value<Type> {
|
||||
pub fn casted_to_number_on_add(self) -> bool {
|
||||
match self {
|
||||
Known(Type::Bool) | Known(Type::Null) | Known(Type::Num) | Known(Type::Undefined) => {
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Value could not be determined
|
||||
pub struct UnknownError;
|
||||
|
||||
// impl<T> Try for Value<T> {
|
||||
// type Ok = T;
|
||||
// type Error = UnknownError;
|
||||
// fn from_ok(t: T) -> Self {
|
||||
// Known(t)
|
||||
// }
|
||||
// fn from_error(_: UnknownError) -> Self {
|
||||
// Unknown
|
||||
// }
|
||||
// fn into_result(self) -> Result<T, UnknownError> {
|
||||
// match self {
|
||||
// Known(t) => Ok(t),
|
||||
// Unknown => Err(UnknownError),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<T> Value<T> {
|
||||
pub fn into_result(self) -> Result<T, UnknownError> {
|
||||
match self {
|
||||
Known(v) => Ok(v),
|
||||
Unknown => Err(UnknownError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Value<T> {
|
||||
/// Returns true if the value is not known.
|
||||
pub fn is_unknown(&self) -> bool {
|
||||
matches!(*self, Unknown)
|
||||
}
|
||||
|
||||
/// Returns true if the value is known.
|
||||
pub fn is_known(&self) -> bool {
|
||||
matches!(*self, Known(..))
|
||||
}
|
||||
}
|
||||
|
||||
impl Value<bool> {
|
||||
pub fn and(self, other: Self) -> Self {
|
||||
match self {
|
||||
Known(true) => other,
|
||||
Known(false) => Known(false),
|
||||
Unknown => match other {
|
||||
Known(false) => Known(false),
|
||||
_ => Unknown,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn or(self, other: Self) -> Self {
|
||||
match self {
|
||||
Known(true) => Known(true),
|
||||
Known(false) => other,
|
||||
Unknown => match other {
|
||||
Known(true) => Known(true),
|
||||
_ => Unknown,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Not for Value<bool> {
|
||||
type Output = Self;
|
||||
|
||||
fn not(self) -> Self {
|
||||
match self {
|
||||
Value::Known(b) => Value::Known(!b),
|
||||
Value::Unknown => Value::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
34
third-party/vendor/swc_ecma_utils/src/var.rs
vendored
Normal file
34
third-party/vendor/swc_ecma_utils/src/var.rs
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
use swc_ecma_ast::*;
|
||||
use swc_ecma_visit::{noop_visit_type, Visit, VisitWith};
|
||||
|
||||
use crate::ident::IdentLike;
|
||||
|
||||
/// This collects variables bindings while ignoring if it's nested in
|
||||
/// expression.
|
||||
pub struct VarCollector<'a, I: IdentLike> {
|
||||
pub to: &'a mut Vec<I>,
|
||||
}
|
||||
|
||||
impl<'a, I: IdentLike> Visit for VarCollector<'a, I> {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_arrow_expr(&mut self, _: &ArrowExpr) {}
|
||||
|
||||
fn visit_constructor(&mut self, _: &Constructor) {}
|
||||
|
||||
fn visit_expr(&mut self, _: &Expr) {}
|
||||
|
||||
fn visit_function(&mut self, _: &Function) {}
|
||||
|
||||
fn visit_key_value_pat_prop(&mut self, node: &KeyValuePatProp) {
|
||||
node.value.visit_with(self);
|
||||
}
|
||||
|
||||
fn visit_ident(&mut self, i: &Ident) {
|
||||
self.to.push(I::from_ident(i))
|
||||
}
|
||||
|
||||
fn visit_var_declarator(&mut self, node: &VarDeclarator) {
|
||||
node.name.visit_with(self);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue