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_transforms_proposal/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/swc_ecma_transforms_proposal/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.toml":"d3f12af3d5700c4399ba809d830556b860d66a9a6c62319b27424ca8b202223c","src/decorator_2022_03.rs":"f2dd91b60ce8c94d6afabc10cf301a73d5a6103930a358149360d853e73f41d5","src/decorators/legacy/metadata.rs":"fd1d0d56fb5e4904062889bfef844e06dc31c7945588711f970fef8a3bb7dea6","src/decorators/legacy/mod.rs":"e3cdf3faad988dba570ee892bc04df4d3e75f59a0bb5597d4b856135fd9b5451","src/decorators/mod.rs":"bd23c40d74fdc4d6b8ced9b43da860575b2ba2266b04f01d65a1e4cf931c86ff","src/explicit_resource_management.rs":"7ac7461b39093bb3a9ab2903314b056e87e9b5c72530c72d5ec84794705e8485","src/export_default_from.rs":"053c6d5c11c2e44583bb7ab36f5842539e2edf21cb58ac0c44da7c48baa83444","src/import_assertions.rs":"07180d134c9d8337f3929d6f5fd67e4b8e635ab7e64e76c88364a1e5a6964e1e","src/lib.rs":"49963b6612c1b391593c40f954064a3408bec80fef37a6402618dbb296628614"},"package":"122fd9a69f464694edefbf9c59106b3c15e5cc8cb8575a97836e4fb79018e98f"}
|
||||
87
third-party/vendor/swc_ecma_transforms_proposal/Cargo.toml
vendored
Normal file
87
third-party/vendor/swc_ecma_transforms_proposal/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
# 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_transforms_proposal"
|
||||
version = "0.166.3"
|
||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||
include = [
|
||||
"Cargo.toml",
|
||||
"src/**/*.rs",
|
||||
]
|
||||
description = "rust port of babel and closure compiler."
|
||||
documentation = "https://rustdoc.swc.rs/swc_ecma_transforms_proposal/"
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
|
||||
[lib]
|
||||
bench = false
|
||||
|
||||
[dependencies.either]
|
||||
version = "1.6.1"
|
||||
|
||||
[dependencies.rustc-hash]
|
||||
version = "1"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0.118"
|
||||
features = ["derive"]
|
||||
|
||||
[dependencies.smallvec]
|
||||
version = "1.8.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_loader]
|
||||
version = "0.44.2"
|
||||
optional = true
|
||||
|
||||
[dependencies.swc_ecma_transforms_base]
|
||||
version = "0.132.2"
|
||||
|
||||
[dependencies.swc_ecma_transforms_classes]
|
||||
version = "0.121.2"
|
||||
|
||||
[dependencies.swc_ecma_transforms_macros]
|
||||
version = "0.5.3"
|
||||
|
||||
[dependencies.swc_ecma_utils]
|
||||
version = "0.122.0"
|
||||
|
||||
[dependencies.swc_ecma_visit]
|
||||
version = "0.95.0"
|
||||
|
||||
[dev-dependencies.serde_json]
|
||||
version = "1.0.66"
|
||||
|
||||
[dev-dependencies.swc_ecma_parser]
|
||||
version = "0.139.0"
|
||||
|
||||
[dev-dependencies.swc_ecma_transforms_compat]
|
||||
version = "0.158.3"
|
||||
|
||||
[dev-dependencies.swc_ecma_transforms_testing]
|
||||
version = "0.135.2"
|
||||
|
||||
[dev-dependencies.testing]
|
||||
version = "0.34.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
multi-module = ["swc_ecma_loader"]
|
||||
1708
third-party/vendor/swc_ecma_transforms_proposal/src/decorator_2022_03.rs
vendored
Normal file
1708
third-party/vendor/swc_ecma_transforms_proposal/src/decorator_2022_03.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
525
third-party/vendor/swc_ecma_transforms_proposal/src/decorators/legacy/metadata.rs
vendored
Normal file
525
third-party/vendor/swc_ecma_transforms_proposal/src/decorators/legacy/metadata.rs
vendored
Normal file
|
|
@ -0,0 +1,525 @@
|
|||
use swc_atoms::{js_word, JsWord};
|
||||
use swc_common::{
|
||||
collections::AHashMap,
|
||||
util::{move_map::MoveMap, take::Take},
|
||||
Spanned, DUMMY_SP,
|
||||
};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::helper;
|
||||
use swc_ecma_utils::{quote_ident, undefined, ExprFactory};
|
||||
use swc_ecma_visit::{VisitMut, VisitMutWith};
|
||||
|
||||
use super::EnumKind;
|
||||
|
||||
/// https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata/blob/master/src/parameter/parameterVisitor.ts
|
||||
pub(super) struct ParamMetadata;
|
||||
|
||||
impl VisitMut for ParamMetadata {
|
||||
fn visit_mut_class(&mut self, cls: &mut Class) {
|
||||
cls.visit_mut_children_with(self);
|
||||
|
||||
let mut decorators = cls.decorators.take();
|
||||
|
||||
cls.body = cls.body.take().move_map(|m| match m {
|
||||
ClassMember::Constructor(mut c) => {
|
||||
for (idx, param) in c.params.iter_mut().enumerate() {
|
||||
//
|
||||
match param {
|
||||
ParamOrTsParamProp::TsParamProp(p) => {
|
||||
for decorator in p.decorators.drain(..) {
|
||||
let new_dec = self.create_param_decorator(idx, decorator.expr);
|
||||
decorators.push(new_dec);
|
||||
}
|
||||
}
|
||||
ParamOrTsParamProp::Param(param) => {
|
||||
for decorator in param.decorators.drain(..) {
|
||||
let new_dec = self.create_param_decorator(idx, decorator.expr);
|
||||
decorators.push(new_dec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ClassMember::Constructor(c)
|
||||
}
|
||||
_ => m,
|
||||
});
|
||||
cls.decorators = decorators;
|
||||
}
|
||||
|
||||
fn visit_mut_class_method(&mut self, m: &mut ClassMethod) {
|
||||
for (idx, param) in m.function.params.iter_mut().enumerate() {
|
||||
for decorator in param.decorators.drain(..) {
|
||||
let new_dec = self.create_param_decorator(idx, decorator.expr);
|
||||
m.function.decorators.push(new_dec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ParamMetadata {
|
||||
fn create_param_decorator(&self, param_index: usize, decorator_expr: Box<Expr>) -> Decorator {
|
||||
Decorator {
|
||||
span: DUMMY_SP,
|
||||
expr: Box::new(Expr::Call(CallExpr {
|
||||
span: decorator_expr.span(),
|
||||
callee: helper!(ts, ts_param),
|
||||
args: vec![param_index.as_arg(), decorator_expr.as_arg()],
|
||||
type_args: Default::default(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata/blob/master/src/metadata/metadataVisitor.ts
|
||||
pub(super) struct Metadata<'a> {
|
||||
pub(super) enums: &'a AHashMap<JsWord, EnumKind>,
|
||||
|
||||
pub(super) class_name: Option<&'a Ident>,
|
||||
}
|
||||
|
||||
impl VisitMut for Metadata<'_> {
|
||||
fn visit_mut_class(&mut self, c: &mut Class) {
|
||||
c.visit_mut_children_with(self);
|
||||
|
||||
if c.decorators.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let constructor = c.body.iter().find_map(|m| match m {
|
||||
ClassMember::Constructor(c) => Some(c),
|
||||
_ => None,
|
||||
});
|
||||
if constructor.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
let dec = self
|
||||
.create_metadata_design_decorator("design:type", quote_ident!("Function").as_arg());
|
||||
c.decorators.push(dec);
|
||||
}
|
||||
{
|
||||
let dec = self.create_metadata_design_decorator(
|
||||
"design:paramtypes",
|
||||
ArrayLit {
|
||||
span: DUMMY_SP,
|
||||
elems: constructor
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.params
|
||||
.iter()
|
||||
.map(|v| match v {
|
||||
ParamOrTsParamProp::TsParamProp(p) => {
|
||||
let ann = match &p.param {
|
||||
TsParamPropParam::Ident(i) => i.type_ann.as_deref(),
|
||||
TsParamPropParam::Assign(a) => get_type_ann_of_pat(&a.left),
|
||||
};
|
||||
Some(serialize_type(self.class_name, ann).as_arg())
|
||||
}
|
||||
ParamOrTsParamProp::Param(p) => Some(
|
||||
serialize_type(self.class_name, get_type_ann_of_pat(&p.pat))
|
||||
.as_arg(),
|
||||
),
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
.as_arg(),
|
||||
);
|
||||
c.decorators.push(dec);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_class_method(&mut self, m: &mut ClassMethod) {
|
||||
if m.function.decorators.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
let dec = self
|
||||
.create_metadata_design_decorator("design:type", quote_ident!("Function").as_arg());
|
||||
m.function.decorators.push(dec);
|
||||
}
|
||||
{
|
||||
let dec = self.create_metadata_design_decorator(
|
||||
"design:paramtypes",
|
||||
ArrayLit {
|
||||
span: DUMMY_SP,
|
||||
elems: m
|
||||
.function
|
||||
.params
|
||||
.iter()
|
||||
.map(|v| {
|
||||
Some(
|
||||
serialize_type(self.class_name, get_type_ann_of_pat(&v.pat))
|
||||
.as_arg(),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
.as_arg(),
|
||||
);
|
||||
m.function.decorators.push(dec);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_class_prop(&mut self, p: &mut ClassProp) {
|
||||
if p.decorators.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if p.type_ann.is_none() {
|
||||
return;
|
||||
}
|
||||
if let Some(name) = p
|
||||
.type_ann
|
||||
.as_ref()
|
||||
.map(|ty| &ty.type_ann)
|
||||
.and_then(|type_ann| match &**type_ann {
|
||||
TsType::TsTypeRef(r) => Some(r),
|
||||
_ => None,
|
||||
})
|
||||
.and_then(|r| match &r.type_name {
|
||||
TsEntityName::TsQualifiedName(_) => None,
|
||||
TsEntityName::Ident(i) => Some(i),
|
||||
})
|
||||
{
|
||||
if let Some(kind) = self.enums.get(&name.sym) {
|
||||
let dec = self.create_metadata_design_decorator(
|
||||
"design:type",
|
||||
match kind {
|
||||
EnumKind::Mixed => quote_ident!("Object").as_arg(),
|
||||
EnumKind::Str => quote_ident!("String").as_arg(),
|
||||
EnumKind::Num => quote_ident!("Number").as_arg(),
|
||||
},
|
||||
);
|
||||
p.decorators.push(dec);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let dec = self.create_metadata_design_decorator(
|
||||
"design:type",
|
||||
serialize_type(self.class_name, p.type_ann.as_deref()).as_arg(),
|
||||
);
|
||||
p.decorators.push(dec);
|
||||
}
|
||||
}
|
||||
|
||||
impl Metadata<'_> {
|
||||
fn create_metadata_design_decorator(&self, design: &str, type_arg: ExprOrSpread) -> Decorator {
|
||||
Decorator {
|
||||
span: DUMMY_SP,
|
||||
expr: Box::new(Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: helper!(ts, ts_metadata),
|
||||
args: vec![design.as_arg(), type_arg],
|
||||
type_args: Default::default(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_type(class_name: Option<&Ident>, param: Option<&TsTypeAnn>) -> Expr {
|
||||
fn check_object_existed(expr: Box<Expr>) -> Box<Expr> {
|
||||
match *expr {
|
||||
Expr::Member(ref member_expr) => {
|
||||
let obj_expr = member_expr.obj.clone();
|
||||
Box::new(Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: check_object_existed(obj_expr),
|
||||
op: op!("||"),
|
||||
right: Box::new(Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: Box::new(Expr::Unary(UnaryExpr {
|
||||
span: DUMMY_SP,
|
||||
op: op!("typeof"),
|
||||
arg: expr,
|
||||
})),
|
||||
op: op!("==="),
|
||||
right: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
span: DUMMY_SP,
|
||||
value: "undefined".into(),
|
||||
raw: None,
|
||||
}))),
|
||||
})),
|
||||
}))
|
||||
}
|
||||
_ => Box::new(Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: Box::new(Expr::Unary(UnaryExpr {
|
||||
span: DUMMY_SP,
|
||||
op: op!("typeof"),
|
||||
arg: expr,
|
||||
})),
|
||||
op: op!("==="),
|
||||
right: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
span: DUMMY_SP,
|
||||
value: "undefined".into(),
|
||||
raw: None,
|
||||
}))),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_type_ref(class_name: &str, ty: &TsTypeRef) -> Expr {
|
||||
match &ty.type_name {
|
||||
// We should omit references to self (class) since it will throw a ReferenceError at
|
||||
// runtime due to babel transpile output.
|
||||
TsEntityName::Ident(i) if &*i.sym == class_name => {
|
||||
return quote_ident!("Object").into()
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let member_expr = ts_entity_to_member_expr(&ty.type_name);
|
||||
|
||||
// We don't know if type is just a type (interface, etc.) or a concrete value
|
||||
// (class, etc.)
|
||||
//
|
||||
// `typeof` operator allows us to use the expression even if it is not defined,
|
||||
// fallback is just `Object`.
|
||||
|
||||
Expr::Cond(CondExpr {
|
||||
span: DUMMY_SP,
|
||||
test: check_object_existed(Box::new(member_expr.clone())),
|
||||
cons: Box::new(quote_ident!("Object").into()),
|
||||
alt: Box::new(member_expr),
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_type_list(class_name: &str, types: &[Box<TsType>]) -> Expr {
|
||||
let mut u = None;
|
||||
for ty in types {
|
||||
// Skip parens if need be
|
||||
let ty = match &**ty {
|
||||
TsType::TsParenthesizedType(ty) => &ty.type_ann,
|
||||
_ => ty,
|
||||
};
|
||||
match &**ty {
|
||||
// Always elide `never` from the union/intersection if possible
|
||||
TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsNeverKeyword,
|
||||
..
|
||||
}) => {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Elide null and undefined from unions for metadata, just like what we did prior to
|
||||
// the implementation of strict null checks
|
||||
TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsNullKeyword,
|
||||
..
|
||||
})
|
||||
| TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsUndefinedKeyword,
|
||||
..
|
||||
}) => {
|
||||
return quote_ident!("Object").into();
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let item = serialize_type_node(class_name, ty);
|
||||
|
||||
// One of the individual is global object, return immediately
|
||||
if let Expr::Ident(Ident {
|
||||
sym: js_word!("Object"),
|
||||
..
|
||||
}) = item
|
||||
{
|
||||
return item;
|
||||
}
|
||||
|
||||
// If there exists union that is not void 0 expression, check if the
|
||||
// the common type is identifier. anything more complex
|
||||
// and we will just default to Object
|
||||
|
||||
//
|
||||
match &u {
|
||||
None => {
|
||||
u = Some(item);
|
||||
}
|
||||
|
||||
Some(prev) => {
|
||||
// Check for different types
|
||||
match prev {
|
||||
Expr::Ident(prev) => match &item {
|
||||
Expr::Ident(item) if prev.sym == item.sym => {}
|
||||
_ => return quote_ident!("Object").into(),
|
||||
},
|
||||
|
||||
_ => return quote_ident!("Object").into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match u {
|
||||
Some(i) => i,
|
||||
_ => quote_ident!("Object").into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_type_node(class_name: &str, ty: &TsType) -> Expr {
|
||||
let span = ty.span();
|
||||
match ty {
|
||||
TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsVoidKeyword,
|
||||
..
|
||||
})
|
||||
| TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsUndefinedKeyword,
|
||||
..
|
||||
})
|
||||
| TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsNullKeyword,
|
||||
..
|
||||
})
|
||||
| TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsNeverKeyword,
|
||||
..
|
||||
}) => *undefined(span),
|
||||
|
||||
TsType::TsParenthesizedType(ty) => serialize_type_node(class_name, &ty.type_ann),
|
||||
|
||||
TsType::TsFnOrConstructorType(_) => quote_ident!("Function").into(),
|
||||
|
||||
TsType::TsArrayType(_) | TsType::TsTupleType(_) => quote_ident!("Array").into(),
|
||||
|
||||
TsType::TsLitType(TsLitType {
|
||||
lit: TsLit::Bool(..),
|
||||
..
|
||||
})
|
||||
| TsType::TsTypePredicate(_)
|
||||
| TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsBooleanKeyword,
|
||||
..
|
||||
}) => quote_ident!("Boolean").into(),
|
||||
|
||||
ty if is_str(ty) => quote_ident!("String").into(),
|
||||
|
||||
TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsObjectKeyword,
|
||||
..
|
||||
}) => quote_ident!("Object").into(),
|
||||
|
||||
TsType::TsLitType(TsLitType {
|
||||
lit: TsLit::Number(..),
|
||||
..
|
||||
})
|
||||
| TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsNumberKeyword,
|
||||
..
|
||||
}) => quote_ident!("Number").into(),
|
||||
|
||||
TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsBigIntKeyword,
|
||||
..
|
||||
}) => Expr::Cond(CondExpr {
|
||||
span: DUMMY_SP,
|
||||
test: check_object_existed(quote_ident!("BigInt").into()),
|
||||
cons: quote_ident!("Object").into(),
|
||||
alt: quote_ident!("BigInt").into(),
|
||||
}),
|
||||
|
||||
TsType::TsLitType(ty) => {
|
||||
// TODO: Proper error reporting
|
||||
panic!("Bad type for decoration: {:?}", ty);
|
||||
}
|
||||
|
||||
TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsSymbolKeyword,
|
||||
..
|
||||
}) => quote_ident!("Symbol").into(),
|
||||
|
||||
TsType::TsTypeQuery(_)
|
||||
| TsType::TsTypeOperator(_)
|
||||
| TsType::TsIndexedAccessType(_)
|
||||
| TsType::TsTypeLit(_)
|
||||
| TsType::TsMappedType(_)
|
||||
| TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsAnyKeyword,
|
||||
..
|
||||
})
|
||||
| TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsUnknownKeyword,
|
||||
..
|
||||
})
|
||||
| TsType::TsThisType(..) => quote_ident!("Object").into(),
|
||||
|
||||
TsType::TsUnionOrIntersectionType(ty) => match ty {
|
||||
TsUnionOrIntersectionType::TsUnionType(ty) => {
|
||||
serialize_type_list(class_name, &ty.types)
|
||||
}
|
||||
TsUnionOrIntersectionType::TsIntersectionType(ty) => {
|
||||
serialize_type_list(class_name, &ty.types)
|
||||
}
|
||||
},
|
||||
|
||||
TsType::TsConditionalType(ty) => {
|
||||
serialize_type_list(class_name, &[ty.true_type.clone(), ty.false_type.clone()])
|
||||
}
|
||||
|
||||
TsType::TsTypeRef(ty) => serialize_type_ref(class_name, ty),
|
||||
|
||||
_ => panic!("Bad type for decorator: {:?}", ty),
|
||||
}
|
||||
}
|
||||
|
||||
let param = match param {
|
||||
Some(v) => &v.type_ann,
|
||||
None => return *undefined(DUMMY_SP),
|
||||
};
|
||||
|
||||
serialize_type_node(class_name.map(|v| &*v.sym).unwrap_or(""), param)
|
||||
}
|
||||
|
||||
fn ts_entity_to_member_expr(type_name: &TsEntityName) -> Expr {
|
||||
match type_name {
|
||||
TsEntityName::TsQualifiedName(q) => {
|
||||
let obj = ts_entity_to_member_expr(&q.left);
|
||||
|
||||
Expr::Member(MemberExpr {
|
||||
span: DUMMY_SP,
|
||||
obj: obj.into(),
|
||||
prop: MemberProp::Ident(q.right.clone()),
|
||||
})
|
||||
}
|
||||
TsEntityName::Ident(i) => Expr::Ident(i.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_type_ann_of_pat(p: &Pat) -> Option<&TsTypeAnn> {
|
||||
match p {
|
||||
Pat::Ident(p) => p.type_ann.as_deref(),
|
||||
Pat::Array(p) => p.type_ann.as_deref(),
|
||||
Pat::Rest(p) => p.type_ann.as_deref(),
|
||||
Pat::Object(p) => p.type_ann.as_deref(),
|
||||
Pat::Assign(p) => {
|
||||
return get_type_ann_of_pat(&p.left);
|
||||
}
|
||||
Pat::Invalid(_) => None,
|
||||
Pat::Expr(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_str(ty: &TsType) -> bool {
|
||||
match ty {
|
||||
TsType::TsLitType(TsLitType {
|
||||
lit: TsLit::Str(..) | TsLit::Tpl(..),
|
||||
..
|
||||
})
|
||||
| TsType::TsKeywordType(TsKeywordType {
|
||||
kind: TsKeywordTypeKind::TsStringKeyword,
|
||||
..
|
||||
}) => true,
|
||||
|
||||
TsType::TsUnionOrIntersectionType(TsUnionOrIntersectionType::TsUnionType(u)) => {
|
||||
u.types.iter().all(|ty| is_str(ty))
|
||||
}
|
||||
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
544
third-party/vendor/swc_ecma_transforms_proposal/src/decorators/legacy/mod.rs
vendored
Normal file
544
third-party/vendor/swc_ecma_transforms_proposal/src/decorators/legacy/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,544 @@
|
|||
use swc_atoms::JsWord;
|
||||
use swc_common::{collections::AHashMap, util::take::Take, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::helper;
|
||||
use swc_ecma_utils::{
|
||||
constructor::inject_after_super, default_constructor, private_ident, prop_name_to_expr_value,
|
||||
quote_ident, replace_ident, undefined, ExprFactory, StmtLike,
|
||||
};
|
||||
use swc_ecma_visit::{Visit, VisitMut, VisitMutWith, VisitWith};
|
||||
|
||||
use self::metadata::{Metadata, ParamMetadata};
|
||||
use super::contains_decorator;
|
||||
|
||||
mod metadata;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum EnumKind {
|
||||
Mixed,
|
||||
Str,
|
||||
Num,
|
||||
}
|
||||
|
||||
pub(super) fn new(metadata: bool) -> TscDecorator {
|
||||
TscDecorator {
|
||||
metadata,
|
||||
enums: Default::default(),
|
||||
vars: Default::default(),
|
||||
appended_exprs: Default::default(),
|
||||
prepended_exprs: Default::default(),
|
||||
class_name: Default::default(),
|
||||
constructor_exprs: Default::default(),
|
||||
exports: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct TscDecorator {
|
||||
metadata: bool,
|
||||
|
||||
enums: AHashMap<JsWord, EnumKind>,
|
||||
|
||||
/// Used for computed keys, and this variables are not initialized.
|
||||
vars: Vec<VarDeclarator>,
|
||||
appended_exprs: Vec<Box<Expr>>,
|
||||
prepended_exprs: Vec<Box<Expr>>,
|
||||
|
||||
class_name: Option<Ident>,
|
||||
|
||||
/// Only used if `use_define_for_class_props` is false.
|
||||
constructor_exprs: Vec<Box<Expr>>,
|
||||
|
||||
exports: Vec<ExportSpecifier>,
|
||||
}
|
||||
|
||||
impl TscDecorator {
|
||||
fn visit_mut_stmt_likes<T>(&mut self, stmts: &mut Vec<T>)
|
||||
where
|
||||
T: StmtLike + VisitMutWith<Self>,
|
||||
{
|
||||
let old_vars = self.vars.take();
|
||||
let old_appended_exprs = self.appended_exprs.take();
|
||||
let old_prepended_exprs = self.prepended_exprs.take();
|
||||
|
||||
let mut new = vec![];
|
||||
|
||||
for mut s in stmts.take() {
|
||||
debug_assert!(self.appended_exprs.is_empty());
|
||||
|
||||
s.visit_mut_with(self);
|
||||
|
||||
if !self.vars.is_empty() {
|
||||
new.push(T::from_stmt(
|
||||
VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
declare: Default::default(),
|
||||
decls: self.vars.take(),
|
||||
}
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
|
||||
new.extend(
|
||||
self.prepended_exprs
|
||||
.drain(..)
|
||||
.map(|expr| {
|
||||
Stmt::Expr(ExprStmt {
|
||||
span: DUMMY_SP,
|
||||
expr,
|
||||
})
|
||||
})
|
||||
.map(T::from_stmt),
|
||||
);
|
||||
|
||||
new.push(s);
|
||||
|
||||
new.extend(
|
||||
self.appended_exprs
|
||||
.drain(..)
|
||||
.map(|expr| {
|
||||
Stmt::Expr(ExprStmt {
|
||||
span: DUMMY_SP,
|
||||
expr,
|
||||
})
|
||||
})
|
||||
.map(T::from_stmt),
|
||||
);
|
||||
}
|
||||
|
||||
*stmts = new;
|
||||
|
||||
self.prepended_exprs = old_prepended_exprs;
|
||||
self.appended_exprs = old_appended_exprs;
|
||||
self.vars = old_vars;
|
||||
}
|
||||
|
||||
fn key(&mut self, k: &mut PropName) -> Expr {
|
||||
match k {
|
||||
PropName::Computed(k) if !k.expr.is_lit() => {
|
||||
let var_name = private_ident!(k.span, "_key");
|
||||
|
||||
// Declare var
|
||||
self.vars.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(var_name.clone().into()),
|
||||
init: None,
|
||||
definite: Default::default(),
|
||||
});
|
||||
|
||||
// Initialize var
|
||||
self.prepended_exprs.push(Box::new(Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
op: op!("="),
|
||||
left: PatOrExpr::Pat(var_name.clone().into()),
|
||||
right: k.expr.take(),
|
||||
})));
|
||||
|
||||
k.expr = Box::new(Expr::Ident(var_name.clone()));
|
||||
|
||||
return Expr::Ident(var_name);
|
||||
}
|
||||
PropName::Ident(i) => {
|
||||
return Expr::Lit(Lit::Str(Str {
|
||||
span: DUMMY_SP,
|
||||
raw: None,
|
||||
value: i.sym.clone(),
|
||||
}))
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
prop_name_to_expr_value(k.clone())
|
||||
}
|
||||
|
||||
/// Creates `__decorate` calls.
|
||||
fn add_decorate_call(
|
||||
&mut self,
|
||||
decorators: impl IntoIterator<Item = Box<Expr>>,
|
||||
target: ExprOrSpread,
|
||||
key: ExprOrSpread,
|
||||
desc: ExprOrSpread,
|
||||
) {
|
||||
let decorators = ArrayLit {
|
||||
span: DUMMY_SP,
|
||||
elems: decorators
|
||||
.into_iter()
|
||||
.map(|v| v.as_arg())
|
||||
.map(Some)
|
||||
.collect(),
|
||||
}
|
||||
.as_arg();
|
||||
|
||||
self.appended_exprs.push(Box::new(Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: helper!(ts, ts_decorate),
|
||||
args: vec![decorators, target, key, desc],
|
||||
type_args: Default::default(),
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for TscDecorator {
|
||||
fn visit_ts_enum_decl(&mut self, e: &TsEnumDecl) {
|
||||
let enum_kind = e
|
||||
.members
|
||||
.iter()
|
||||
.map(|member| member.init.as_ref())
|
||||
.map(|init| match init {
|
||||
Some(e) => match &**e {
|
||||
Expr::Lit(lit) => match lit {
|
||||
Lit::Str(_) => EnumKind::Str,
|
||||
Lit::Num(_) => EnumKind::Num,
|
||||
_ => EnumKind::Mixed,
|
||||
},
|
||||
_ => EnumKind::Mixed,
|
||||
},
|
||||
None => EnumKind::Num,
|
||||
})
|
||||
.fold(None, |opt: Option<EnumKind>, item| {
|
||||
//
|
||||
let a = match item {
|
||||
EnumKind::Mixed => return Some(EnumKind::Mixed),
|
||||
_ => item,
|
||||
};
|
||||
|
||||
let b = match opt {
|
||||
Some(EnumKind::Mixed) => return Some(EnumKind::Mixed),
|
||||
Some(v) => v,
|
||||
None => return Some(item),
|
||||
};
|
||||
if a == b {
|
||||
Some(a)
|
||||
} else {
|
||||
Some(EnumKind::Mixed)
|
||||
}
|
||||
});
|
||||
if let Some(kind) = enum_kind {
|
||||
self.enums.insert(e.id.sym.clone(), kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VisitMut for TscDecorator {
|
||||
fn visit_mut_class(&mut self, n: &mut Class) {
|
||||
let old_constructor_stmts = self.constructor_exprs.take();
|
||||
|
||||
n.visit_mut_with(&mut ParamMetadata);
|
||||
|
||||
if self.metadata {
|
||||
let i = self.class_name.clone();
|
||||
|
||||
n.visit_mut_with(&mut Metadata {
|
||||
enums: &self.enums,
|
||||
class_name: i.as_ref(),
|
||||
});
|
||||
}
|
||||
|
||||
n.visit_mut_children_with(self);
|
||||
|
||||
if !self.constructor_exprs.is_empty() {
|
||||
for m in &mut n.body {
|
||||
if let ClassMember::Constructor(c @ Constructor { body: Some(..), .. }) = m {
|
||||
inject_after_super(c, self.constructor_exprs.take());
|
||||
}
|
||||
}
|
||||
|
||||
if !self.constructor_exprs.is_empty() {
|
||||
let mut c = default_constructor(n.super_class.is_some());
|
||||
inject_after_super(&mut c, self.constructor_exprs.take());
|
||||
n.body.insert(0, ClassMember::Constructor(c));
|
||||
}
|
||||
}
|
||||
|
||||
self.constructor_exprs = old_constructor_stmts;
|
||||
|
||||
if let Some(class_name) = self.class_name.clone() {
|
||||
if !n.decorators.is_empty() {
|
||||
let decorators = ArrayLit {
|
||||
span: DUMMY_SP,
|
||||
elems: n
|
||||
.decorators
|
||||
.take()
|
||||
.into_iter()
|
||||
.map(|v| v.expr.as_arg())
|
||||
.map(Some)
|
||||
.collect(),
|
||||
}
|
||||
.as_arg();
|
||||
|
||||
let decorated = Box::new(Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: helper!(ts, ts_decorate),
|
||||
args: vec![decorators, class_name.clone().as_arg()],
|
||||
type_args: Default::default(),
|
||||
}));
|
||||
self.appended_exprs.push(Box::new(Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
op: op!("="),
|
||||
left: PatOrExpr::Pat(class_name.into()),
|
||||
right: decorated,
|
||||
})));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_class_decl(&mut self, n: &mut ClassDecl) {
|
||||
let old = self.class_name.take();
|
||||
self.class_name = Some(n.ident.clone());
|
||||
|
||||
n.visit_mut_children_with(self);
|
||||
|
||||
self.class_name = old;
|
||||
}
|
||||
|
||||
fn visit_mut_class_expr(&mut self, n: &mut ClassExpr) {
|
||||
let old = self.class_name.take();
|
||||
if contains_decorator(n) && n.ident.is_none() {
|
||||
n.ident = Some(private_ident!("_class"));
|
||||
}
|
||||
|
||||
if let Some(ident) = &n.ident {
|
||||
self.class_name = Some(ident.clone());
|
||||
}
|
||||
|
||||
n.visit_mut_children_with(self);
|
||||
|
||||
self.class_name = old;
|
||||
}
|
||||
|
||||
fn visit_mut_class_method(&mut self, c: &mut ClassMethod) {
|
||||
c.visit_mut_children_with(self);
|
||||
|
||||
if let Some(class_name) = self.class_name.clone() {
|
||||
if !c.function.decorators.is_empty() {
|
||||
let key = self.key(&mut c.key);
|
||||
|
||||
let target = if c.is_static {
|
||||
class_name.as_arg()
|
||||
} else {
|
||||
class_name.make_member(quote_ident!("prototype")).as_arg()
|
||||
};
|
||||
|
||||
self.add_decorate_call(
|
||||
c.function.decorators.drain(..).map(|d| d.expr),
|
||||
target,
|
||||
key.as_arg(),
|
||||
Lit::Null(Null::dummy()).as_arg(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_class_prop(&mut self, c: &mut ClassProp) {
|
||||
c.visit_mut_children_with(self);
|
||||
|
||||
if let Some(class_name) = self.class_name.clone() {
|
||||
if !c.decorators.is_empty() {
|
||||
let key = self.key(&mut c.key);
|
||||
|
||||
let target = if c.is_static {
|
||||
class_name.as_arg()
|
||||
} else {
|
||||
class_name.make_member(quote_ident!("prototype")).as_arg()
|
||||
};
|
||||
|
||||
self.add_decorate_call(
|
||||
c.decorators.drain(..).map(|d| d.expr),
|
||||
target,
|
||||
key.as_arg(),
|
||||
undefined(DUMMY_SP).as_arg(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_decl(&mut self, n: &mut Decl) {
|
||||
match n {
|
||||
Decl::Class(decl) => {
|
||||
let convert_to_let = !decl.class.decorators.is_empty();
|
||||
decl.visit_mut_with(self);
|
||||
|
||||
if convert_to_let {
|
||||
let inner_ident = private_ident!(decl.ident.sym.clone());
|
||||
|
||||
decl.class.body.iter_mut().for_each(|m| match m {
|
||||
ClassMember::PrivateProp(PrivateProp {
|
||||
is_static: true, ..
|
||||
})
|
||||
| ClassMember::StaticBlock(..)
|
||||
| ClassMember::ClassProp(ClassProp {
|
||||
is_static: true, ..
|
||||
}) => {
|
||||
replace_ident(m, decl.ident.to_id(), &inner_ident);
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
|
||||
let d = VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: decl.ident.clone().into(),
|
||||
init: Some(Box::new(Expr::Class(ClassExpr {
|
||||
ident: Some(inner_ident),
|
||||
class: decl.class.take(),
|
||||
}))),
|
||||
definite: Default::default(),
|
||||
};
|
||||
*n = Decl::Var(Box::new(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Let,
|
||||
declare: Default::default(),
|
||||
decls: vec![d],
|
||||
}));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
n.visit_mut_children_with(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_module(&mut self, n: &mut Module) {
|
||||
n.visit_with(self);
|
||||
|
||||
n.visit_mut_children_with(self);
|
||||
}
|
||||
|
||||
fn visit_mut_module_item(&mut self, module_item: &mut ModuleItem) {
|
||||
match module_item {
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(n)) => {
|
||||
let export_decl_span = n.span;
|
||||
|
||||
match &mut n.decl {
|
||||
Decl::Class(decl) => {
|
||||
let convert_to_let = !decl.class.decorators.is_empty();
|
||||
decl.visit_mut_with(self);
|
||||
|
||||
if convert_to_let {
|
||||
let inner_ident = private_ident!(decl.ident.sym.clone());
|
||||
|
||||
decl.class.body.iter_mut().for_each(|m| match m {
|
||||
ClassMember::PrivateProp(PrivateProp {
|
||||
is_static: true, ..
|
||||
})
|
||||
| ClassMember::StaticBlock(..)
|
||||
| ClassMember::ClassProp(ClassProp {
|
||||
is_static: true, ..
|
||||
}) => {
|
||||
replace_ident(m, decl.ident.to_id(), &inner_ident);
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
|
||||
let d = VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: decl.ident.clone().into(),
|
||||
init: Some(Box::new(Expr::Class(ClassExpr {
|
||||
ident: Some(inner_ident),
|
||||
class: decl.class.take(),
|
||||
}))),
|
||||
definite: Default::default(),
|
||||
};
|
||||
|
||||
let let_decl = VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Let,
|
||||
declare: Default::default(),
|
||||
decls: vec![d],
|
||||
}
|
||||
.into();
|
||||
*module_item =
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
|
||||
span: export_decl_span,
|
||||
decl: let_decl,
|
||||
}));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
module_item.visit_mut_children_with(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(n)) => match &mut n.decl {
|
||||
DefaultDecl::Class(decl) => {
|
||||
let convert_to_let = !decl.class.decorators.is_empty();
|
||||
decl.visit_mut_with(self);
|
||||
|
||||
if convert_to_let {
|
||||
let ident = decl.ident.clone().unwrap();
|
||||
|
||||
let inner_ident = private_ident!(ident.sym.clone());
|
||||
|
||||
decl.class.body.iter_mut().for_each(|m| match m {
|
||||
ClassMember::PrivateProp(PrivateProp {
|
||||
is_static: true, ..
|
||||
})
|
||||
| ClassMember::StaticBlock(..)
|
||||
| ClassMember::ClassProp(ClassProp {
|
||||
is_static: true, ..
|
||||
}) => {
|
||||
replace_ident(m, ident.to_id(), &inner_ident);
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
|
||||
let d = VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: ident.clone().into(),
|
||||
init: Some(Box::new(Expr::Class(ClassExpr {
|
||||
ident: Some(inner_ident),
|
||||
..decl.take()
|
||||
}))),
|
||||
definite: Default::default(),
|
||||
};
|
||||
*module_item = VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Let,
|
||||
declare: Default::default(),
|
||||
decls: vec![d],
|
||||
}
|
||||
.into();
|
||||
self.exports
|
||||
.push(ExportSpecifier::Named(ExportNamedSpecifier {
|
||||
span: DUMMY_SP,
|
||||
orig: ModuleExportName::Ident(ident),
|
||||
exported: Some(ModuleExportName::Ident(quote_ident!("default"))),
|
||||
is_type_only: Default::default(),
|
||||
}));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
module_item.visit_mut_children_with(self);
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
module_item.visit_mut_children_with(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_module_items(&mut self, s: &mut Vec<ModuleItem>) {
|
||||
self.visit_mut_stmt_likes(s);
|
||||
|
||||
if !self.exports.is_empty() {
|
||||
s.push(ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(
|
||||
NamedExport {
|
||||
span: DUMMY_SP,
|
||||
specifiers: self.exports.take(),
|
||||
src: None,
|
||||
type_only: Default::default(),
|
||||
with: Default::default(),
|
||||
},
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_script(&mut self, n: &mut Script) {
|
||||
n.visit_with(self);
|
||||
|
||||
n.visit_mut_children_with(self);
|
||||
}
|
||||
|
||||
fn visit_mut_stmts(&mut self, s: &mut Vec<Stmt>) {
|
||||
self.visit_mut_stmt_likes(s)
|
||||
}
|
||||
}
|
||||
661
third-party/vendor/swc_ecma_transforms_proposal/src/decorators/mod.rs
vendored
Normal file
661
third-party/vendor/swc_ecma_transforms_proposal/src/decorators/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,661 @@
|
|||
use std::{iter, mem::take};
|
||||
|
||||
use either::Either;
|
||||
use serde::Deserialize;
|
||||
use swc_common::{Spanned, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::helper;
|
||||
use swc_ecma_transforms_classes::super_field::SuperFieldAccessFolder;
|
||||
use swc_ecma_utils::{
|
||||
alias_ident_for, constructor::inject_after_super, default_constructor, prepend_stmt,
|
||||
private_ident, prop_name_to_expr, prop_name_to_expr_value, quote_ident, quote_str, undefined,
|
||||
ExprFactory, IdentExt,
|
||||
};
|
||||
use swc_ecma_visit::{as_folder, noop_fold_type, Fold, FoldWith, Visit, VisitWith};
|
||||
|
||||
mod legacy;
|
||||
|
||||
/// ## Simple class decorator
|
||||
///
|
||||
/// ```js
|
||||
///
|
||||
/// @annotation
|
||||
/// class MyClass { }
|
||||
///
|
||||
/// function annotation(target) {
|
||||
/// target.annotated = true;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Class decorator
|
||||
///
|
||||
/// ```js
|
||||
/// @isTestable(true)
|
||||
/// class MyClass { }
|
||||
///
|
||||
/// function isTestable(value) {
|
||||
/// return function decorator(target) {
|
||||
/// target.isTestable = value;
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Class method decorator
|
||||
///
|
||||
/// ```js
|
||||
/// class C {
|
||||
/// @enumerable(false)
|
||||
/// method() { }
|
||||
/// }
|
||||
///
|
||||
/// function enumerable(value) {
|
||||
/// return function (target, key, descriptor) {
|
||||
/// descriptor.enumerable = value;
|
||||
/// return descriptor;
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn decorators(c: Config) -> impl Fold {
|
||||
if c.legacy {
|
||||
Either::Left(as_folder(self::legacy::new(c.emit_metadata)))
|
||||
} else {
|
||||
if c.emit_metadata {
|
||||
unimplemented!("emitting decorator metadata while using new proposal")
|
||||
}
|
||||
Either::Right(Decorators {
|
||||
is_in_strict: false,
|
||||
vars: Default::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Config {
|
||||
pub legacy: bool,
|
||||
#[serde(default)]
|
||||
pub emit_metadata: bool,
|
||||
|
||||
pub use_define_for_class_fields: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct Decorators {
|
||||
is_in_strict: bool,
|
||||
|
||||
vars: Vec<VarDeclarator>,
|
||||
}
|
||||
|
||||
/// TODO: VisitMut
|
||||
impl Fold for Decorators {
|
||||
noop_fold_type!();
|
||||
|
||||
fn fold_decl(&mut self, decl: Decl) -> Decl {
|
||||
let decl = decl.fold_children_with(self);
|
||||
|
||||
match decl {
|
||||
Decl::Class(ClassDecl {
|
||||
ident,
|
||||
declare: false,
|
||||
class,
|
||||
}) => {
|
||||
if !contains_decorator(&class) {
|
||||
return Decl::Class(ClassDecl {
|
||||
ident,
|
||||
declare: false,
|
||||
class,
|
||||
});
|
||||
}
|
||||
|
||||
let decorate_call = Box::new(self.fold_class_inner(ident.clone(), class));
|
||||
|
||||
VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Let,
|
||||
declare: false,
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: ident.into(),
|
||||
definite: false,
|
||||
init: Some(decorate_call),
|
||||
}],
|
||||
}
|
||||
.into()
|
||||
}
|
||||
_ => decl,
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_expr(&mut self, expr: Expr) -> Expr {
|
||||
let expr = expr.fold_children_with(self);
|
||||
|
||||
match expr {
|
||||
Expr::Class(ClassExpr { ident, class }) => {
|
||||
if !contains_decorator(&class) {
|
||||
return Expr::Class(ClassExpr { ident, class });
|
||||
}
|
||||
|
||||
self.fold_class_inner(ident.unwrap_or_else(|| quote_ident!("_class")), class)
|
||||
}
|
||||
_ => expr,
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_module_decl(&mut self, decl: ModuleDecl) -> ModuleDecl {
|
||||
let decl = decl.fold_children_with(self);
|
||||
|
||||
match decl {
|
||||
ModuleDecl::ExportDefaultDecl(ExportDefaultDecl {
|
||||
span,
|
||||
decl: DefaultDecl::Class(ClassExpr { ident, class }),
|
||||
..
|
||||
}) => {
|
||||
let decorate_call = Box::new(
|
||||
self.fold_class_inner(ident.unwrap_or_else(|| quote_ident!("_class")), class),
|
||||
);
|
||||
|
||||
ModuleDecl::ExportDefaultExpr(ExportDefaultExpr {
|
||||
span,
|
||||
expr: decorate_call,
|
||||
})
|
||||
}
|
||||
_ => decl,
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> {
|
||||
if !contains_decorator(&items) {
|
||||
return items;
|
||||
}
|
||||
|
||||
let old_strict = self.is_in_strict;
|
||||
self.is_in_strict = true;
|
||||
|
||||
let mut buf = Vec::with_capacity(items.len() + 4);
|
||||
items.into_iter().for_each(|item| {
|
||||
if !contains_decorator(&item) {
|
||||
buf.push(item);
|
||||
return;
|
||||
}
|
||||
|
||||
macro_rules! handle_class {
|
||||
($cls:expr, $ident:expr) => {{
|
||||
let class = $cls;
|
||||
let ident = $ident;
|
||||
let decorate_call = Box::new(self.fold_class_inner(ident.clone(), class));
|
||||
|
||||
buf.push(
|
||||
VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Let,
|
||||
declare: false,
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: ident.clone().into(),
|
||||
init: Some(decorate_call),
|
||||
definite: false,
|
||||
}],
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
|
||||
// export { Foo as default }
|
||||
buf.push(ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(
|
||||
NamedExport {
|
||||
span: DUMMY_SP,
|
||||
specifiers: vec![ExportNamedSpecifier {
|
||||
span: DUMMY_SP,
|
||||
orig: ModuleExportName::Ident(ident),
|
||||
exported: Some(ModuleExportName::Ident(quote_ident!("default"))),
|
||||
is_type_only: false,
|
||||
}
|
||||
.into()],
|
||||
src: None,
|
||||
type_only: false,
|
||||
with: None,
|
||||
},
|
||||
)));
|
||||
}};
|
||||
}
|
||||
//
|
||||
match item {
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(ExportDefaultDecl {
|
||||
decl:
|
||||
DefaultDecl::Class(ClassExpr {
|
||||
ident: Some(ident),
|
||||
class,
|
||||
}),
|
||||
..
|
||||
})) => handle_class!(class, ident),
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultExpr(ExportDefaultExpr {
|
||||
span,
|
||||
expr,
|
||||
..
|
||||
})) => match *expr {
|
||||
Expr::Class(ClassExpr {
|
||||
ident: Some(ident),
|
||||
class,
|
||||
}) => handle_class!(class, ident),
|
||||
|
||||
_ => {
|
||||
let item = ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultExpr(
|
||||
ExportDefaultExpr { span, expr },
|
||||
));
|
||||
buf.push(item.fold_with(self));
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
buf.push(item.fold_with(self));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
self.is_in_strict = old_strict;
|
||||
|
||||
if !self.vars.is_empty() {
|
||||
prepend_stmt(
|
||||
&mut buf,
|
||||
VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
declare: false,
|
||||
decls: take(&mut self.vars),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
impl Decorators {
|
||||
#[allow(clippy::boxed_local)]
|
||||
fn fold_class_inner(&mut self, ident: Ident, mut class: Box<Class>) -> Expr {
|
||||
let initialize = private_ident!("_initialize");
|
||||
let super_class_ident = class
|
||||
.super_class
|
||||
.as_ref()
|
||||
.map(|expr| alias_ident_for(expr, "_super"));
|
||||
let super_class_expr = class.super_class;
|
||||
class.super_class = super_class_ident.clone().map(|i| Box::new(Expr::Ident(i)));
|
||||
|
||||
let constructor = {
|
||||
let initialize_call = Box::new(Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: initialize.clone().as_callee(),
|
||||
args: vec![ThisExpr { span: DUMMY_SP }.as_arg()],
|
||||
type_args: Default::default(),
|
||||
}));
|
||||
|
||||
// Inject initialize
|
||||
let pos = class.body.iter().position(|member| {
|
||||
matches!(
|
||||
*member,
|
||||
ClassMember::Constructor(Constructor { body: Some(..), .. })
|
||||
)
|
||||
});
|
||||
|
||||
match pos {
|
||||
Some(pos) => {
|
||||
let mut c = match class.body.remove(pos) {
|
||||
ClassMember::Constructor(c) => c,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
inject_after_super(&mut c, vec![initialize_call]);
|
||||
|
||||
ClassMember::Constructor(c)
|
||||
}
|
||||
None => {
|
||||
let mut c = default_constructor(super_class_ident.is_some());
|
||||
|
||||
c.body
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.stmts
|
||||
.push(initialize_call.into_stmt());
|
||||
|
||||
ClassMember::Constructor(c)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut vars = vec![];
|
||||
|
||||
macro_rules! fold_method {
|
||||
($method:expr, $fn_name:expr, $key_prop_value:expr) => {{
|
||||
let fn_name = $fn_name;
|
||||
let method = $method;
|
||||
let mut folder = swc_ecma_visit::as_folder(SuperFieldAccessFolder {
|
||||
class_name: &ident,
|
||||
vars: &mut vars,
|
||||
constructor_this_mark: None,
|
||||
is_static: method.is_static,
|
||||
folding_constructor: false,
|
||||
in_nested_scope: false,
|
||||
in_injected_define_property_call: false,
|
||||
this_alias_mark: None,
|
||||
// TODO: loose mode
|
||||
constant_super: false,
|
||||
super_class: &None,
|
||||
in_pat: false,
|
||||
});
|
||||
|
||||
let method = method.fold_with(&mut folder);
|
||||
|
||||
// kind: "method",
|
||||
// key: getKeyJ(),
|
||||
// value: function () {
|
||||
// return 2;
|
||||
// }
|
||||
Some(
|
||||
ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: iter::once(PropOrSpread::Prop(Box::new(Prop::KeyValue(
|
||||
KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("kind")),
|
||||
value: Box::new(Expr::Lit(Lit::Str(quote_str!(
|
||||
match method.kind {
|
||||
MethodKind::Method => "method",
|
||||
MethodKind::Getter => "get",
|
||||
MethodKind::Setter => "set",
|
||||
}
|
||||
)))),
|
||||
},
|
||||
))))
|
||||
.chain(if method.is_static {
|
||||
Some(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("static")),
|
||||
value: true.into(),
|
||||
}))))
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.chain({
|
||||
//
|
||||
if method.function.decorators.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("decorators")),
|
||||
value: Box::new(Expr::Array(ArrayLit {
|
||||
span: DUMMY_SP,
|
||||
elems: method
|
||||
.function
|
||||
.decorators
|
||||
.into_iter()
|
||||
.map(|dec| dec.expr.as_arg())
|
||||
.map(Some)
|
||||
.collect(),
|
||||
})),
|
||||
}))))
|
||||
}
|
||||
})
|
||||
.chain(iter::once(PropOrSpread::Prop(Box::new(Prop::KeyValue(
|
||||
KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("key")),
|
||||
value: $key_prop_value,
|
||||
},
|
||||
)))))
|
||||
.chain(iter::once(PropOrSpread::Prop(Box::new(Prop::KeyValue(
|
||||
KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("value")),
|
||||
value: Box::new(
|
||||
FnExpr {
|
||||
ident: fn_name.map(IdentExt::private),
|
||||
function: Function {
|
||||
decorators: vec![],
|
||||
..*method.function
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
},
|
||||
)))))
|
||||
.collect(),
|
||||
}
|
||||
.as_arg(),
|
||||
)
|
||||
}};
|
||||
}
|
||||
|
||||
let descriptors = class
|
||||
.body
|
||||
.into_iter()
|
||||
.filter_map(|member| {
|
||||
//
|
||||
match member {
|
||||
ClassMember::Constructor(_) => unreachable!("multiple constructor?"),
|
||||
ClassMember::TsIndexSignature(_) => None,
|
||||
ClassMember::Method(method) => {
|
||||
let fn_name = match method.key {
|
||||
PropName::Ident(ref i) => Some(i.clone()),
|
||||
PropName::Str(ref s) => Some(Ident::new(s.value.clone(), s.span)),
|
||||
_ => None,
|
||||
};
|
||||
let key_prop_value = Box::new(prop_name_to_expr_value(method.key.clone()));
|
||||
|
||||
fold_method!(method, fn_name, key_prop_value)
|
||||
}
|
||||
ClassMember::PrivateMethod(method) => {
|
||||
let fn_name = Ident::new(
|
||||
format!("_{}", method.key.id.sym).into(),
|
||||
method.key.id.span,
|
||||
);
|
||||
let key_prop_value = Box::new(Expr::Lit(Lit::Str(Str {
|
||||
span: method.key.id.span,
|
||||
raw: None,
|
||||
value: method.key.id.sym.clone(),
|
||||
})));
|
||||
fold_method!(method, Some(fn_name), key_prop_value)
|
||||
}
|
||||
ClassMember::ClassProp(prop) => {
|
||||
let prop_span = prop.span();
|
||||
let key_prop_value = match prop.key {
|
||||
PropName::Ident(i) => Box::new(Expr::Lit(Lit::Str(Str {
|
||||
span: i.span,
|
||||
raw: None,
|
||||
value: i.sym,
|
||||
}))),
|
||||
_ => prop_name_to_expr(prop.key).into(),
|
||||
};
|
||||
//
|
||||
Some(
|
||||
ObjectLit {
|
||||
span: prop_span,
|
||||
props: iter::once(PropOrSpread::Prop(Box::new(Prop::KeyValue(
|
||||
KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("kind")),
|
||||
value: Box::new(Expr::Lit(Lit::Str(quote_str!("field")))),
|
||||
},
|
||||
))))
|
||||
.chain(if prop.is_static {
|
||||
Some(PropOrSpread::Prop(Box::new(Prop::KeyValue(
|
||||
KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("static")),
|
||||
value: true.into(),
|
||||
},
|
||||
))))
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.chain({
|
||||
//
|
||||
if prop.decorators.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(PropOrSpread::Prop(Box::new(Prop::KeyValue(
|
||||
KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("decorators")),
|
||||
value: Box::new(Expr::Array(ArrayLit {
|
||||
span: DUMMY_SP,
|
||||
elems: prop
|
||||
.decorators
|
||||
.into_iter()
|
||||
.map(|dec| dec.expr.as_arg())
|
||||
.map(Some)
|
||||
.collect(),
|
||||
})),
|
||||
},
|
||||
))))
|
||||
}
|
||||
})
|
||||
.chain(iter::once(PropOrSpread::Prop(Box::new(Prop::KeyValue(
|
||||
KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("key")),
|
||||
value: key_prop_value,
|
||||
},
|
||||
)))))
|
||||
.chain(iter::once(PropOrSpread::Prop(Box::new(match prop.value {
|
||||
Some(value) => Prop::Method(MethodProp {
|
||||
key: PropName::Ident(quote_ident!("value")),
|
||||
function: Function {
|
||||
span: DUMMY_SP,
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
decorators: vec![],
|
||||
params: vec![],
|
||||
|
||||
body: Some(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![Stmt::Return(ReturnStmt {
|
||||
span: DUMMY_SP,
|
||||
arg: Some(value),
|
||||
})],
|
||||
}),
|
||||
|
||||
type_params: Default::default(),
|
||||
return_type: Default::default(),
|
||||
}
|
||||
.into(),
|
||||
}),
|
||||
_ => Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("value")),
|
||||
value: undefined(DUMMY_SP),
|
||||
}),
|
||||
}))))
|
||||
.collect(),
|
||||
}
|
||||
.as_arg(),
|
||||
)
|
||||
}
|
||||
_ => unimplemented!("ClassMember::{:?}", member,),
|
||||
}
|
||||
})
|
||||
.map(Some)
|
||||
.collect();
|
||||
|
||||
self.vars.extend(vars);
|
||||
|
||||
Expr::Call(make_decorate_call(
|
||||
class.decorators,
|
||||
iter::once({
|
||||
// function(_initialize) {}
|
||||
Function {
|
||||
span: DUMMY_SP,
|
||||
|
||||
params: iter::once(Pat::Ident(initialize.into()))
|
||||
.chain(super_class_ident.map(Pat::from))
|
||||
.map(|pat| Param {
|
||||
span: DUMMY_SP,
|
||||
decorators: vec![],
|
||||
pat,
|
||||
})
|
||||
.collect(),
|
||||
|
||||
decorators: Default::default(),
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
|
||||
body: Some(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: if !self.is_in_strict {
|
||||
// 'use strict';
|
||||
Some(Lit::Str(quote_str!("use strict")).into_stmt())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.into_iter()
|
||||
.chain(iter::once(Stmt::Decl(Decl::Class(ClassDecl {
|
||||
ident: ident.clone(),
|
||||
class: Class {
|
||||
decorators: Default::default(),
|
||||
body: vec![constructor],
|
||||
..*class
|
||||
}
|
||||
.into(),
|
||||
declare: false,
|
||||
}))))
|
||||
.chain(iter::once(Stmt::Return(ReturnStmt {
|
||||
span: DUMMY_SP,
|
||||
arg: Some(Box::new(Expr::Object(ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: vec![
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("F")),
|
||||
value: Box::new(Expr::Ident(ident)),
|
||||
}))),
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(quote_ident!("d")),
|
||||
value: Box::new(Expr::Array(ArrayLit {
|
||||
span: DUMMY_SP,
|
||||
elems: descriptors,
|
||||
})),
|
||||
}))),
|
||||
],
|
||||
}))),
|
||||
})))
|
||||
.collect(),
|
||||
}),
|
||||
|
||||
return_type: Default::default(),
|
||||
type_params: Default::default(),
|
||||
}
|
||||
.as_arg()
|
||||
})
|
||||
.chain(super_class_expr.map(|e| e.as_arg())),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn make_decorate_call(
|
||||
decorators: Vec<Decorator>,
|
||||
args: impl Iterator<Item = ExprOrSpread>,
|
||||
) -> CallExpr {
|
||||
CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: helper!(decorate),
|
||||
args: iter::once(
|
||||
ArrayLit {
|
||||
span: DUMMY_SP,
|
||||
elems: decorators
|
||||
.into_iter()
|
||||
.map(|dec| Some(dec.expr.as_arg()))
|
||||
.collect(),
|
||||
}
|
||||
.as_arg(),
|
||||
)
|
||||
.chain(args)
|
||||
.collect(),
|
||||
type_args: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
struct DecoratorFinder {
|
||||
found: bool,
|
||||
}
|
||||
impl Visit for DecoratorFinder {
|
||||
fn visit_decorator(&mut self, _: &Decorator) {
|
||||
self.found = true
|
||||
}
|
||||
}
|
||||
|
||||
fn contains_decorator<N>(node: &N) -> bool
|
||||
where
|
||||
N: VisitWith<DecoratorFinder>,
|
||||
{
|
||||
let mut v = DecoratorFinder { found: false };
|
||||
node.visit_with(&mut v);
|
||||
v.found
|
||||
}
|
||||
332
third-party/vendor/swc_ecma_transforms_proposal/src/explicit_resource_management.rs
vendored
Normal file
332
third-party/vendor/swc_ecma_transforms_proposal/src/explicit_resource_management.rs
vendored
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
use std::iter::once;
|
||||
|
||||
use swc_common::{util::take::Take, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::helper;
|
||||
use swc_ecma_utils::{private_ident, ExprFactory, ModuleItemLike, StmtLike};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
|
||||
pub fn explicit_resource_management() -> impl Fold + VisitMut {
|
||||
as_folder(ExplicitResourceManagement::default())
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ExplicitResourceManagement {
|
||||
state: Option<State>,
|
||||
|
||||
is_not_top_level: bool,
|
||||
}
|
||||
|
||||
struct State {
|
||||
stack: Ident,
|
||||
has_error: Ident,
|
||||
error_var: Ident,
|
||||
catch_var: Ident,
|
||||
|
||||
has_await: bool,
|
||||
}
|
||||
|
||||
impl Default for State {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
stack: private_ident!("_stack"),
|
||||
has_error: private_ident!("_hasError"),
|
||||
error_var: private_ident!("_error"),
|
||||
catch_var: private_ident!("_"),
|
||||
has_await: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExplicitResourceManagement {
|
||||
fn visit_mut_stmt_likes<T>(&mut self, stmts: &mut Vec<T>)
|
||||
where
|
||||
T: StmtLike + ModuleItemLike,
|
||||
Vec<T>: VisitMutWith<Self>,
|
||||
{
|
||||
let old_state = self.state.take();
|
||||
|
||||
stmts.visit_mut_children_with(self);
|
||||
|
||||
if let Some(state) = self.state.take() {
|
||||
self.wrap_with_try(state, stmts);
|
||||
}
|
||||
|
||||
self.state = old_state;
|
||||
}
|
||||
|
||||
fn wrap_with_try<T>(&mut self, state: State, stmts: &mut Vec<T>)
|
||||
where
|
||||
T: StmtLike + ModuleItemLike,
|
||||
{
|
||||
let mut new = vec![];
|
||||
let mut try_body = vec![];
|
||||
|
||||
let stack_var_decl = VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: state.stack.clone().into(),
|
||||
init: Some(
|
||||
ArrayLit {
|
||||
span: DUMMY_SP,
|
||||
elems: vec![],
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
definite: Default::default(),
|
||||
};
|
||||
|
||||
try_body.push(Stmt::Decl(Decl::Var(Box::new(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
declare: false,
|
||||
decls: vec![stack_var_decl],
|
||||
}))));
|
||||
|
||||
for stmt in stmts.take() {
|
||||
match stmt.try_into_stmt() {
|
||||
Ok(stmt @ Stmt::Decl(Decl::Fn(..))) => {
|
||||
new.push(T::from_stmt(stmt));
|
||||
}
|
||||
Ok(stmt) => try_body.push(stmt),
|
||||
Err(stmt) => match stmt.try_into_module_decl() {
|
||||
Ok(ModuleDecl::ExportDefaultDecl(decl)) => {
|
||||
let ident = match &decl.decl {
|
||||
DefaultDecl::Class(c) => c.ident.clone(),
|
||||
DefaultDecl::Fn(f) => f.ident.clone(),
|
||||
DefaultDecl::TsInterfaceDecl(_) => unreachable!(),
|
||||
};
|
||||
|
||||
let ident = ident.unwrap_or_else(|| private_ident!("_default"));
|
||||
|
||||
// export { C as default }
|
||||
new.push(
|
||||
T::try_from_module_decl(ModuleDecl::ExportNamed(NamedExport {
|
||||
span: DUMMY_SP,
|
||||
specifiers: vec![ExportSpecifier::Named(ExportNamedSpecifier {
|
||||
span: DUMMY_SP,
|
||||
orig: ModuleExportName::Ident(ident.clone()),
|
||||
exported: Some(ModuleExportName::Ident(Ident::new(
|
||||
"default".into(),
|
||||
DUMMY_SP,
|
||||
))),
|
||||
is_type_only: Default::default(),
|
||||
})],
|
||||
src: None,
|
||||
type_only: Default::default(),
|
||||
with: None,
|
||||
}))
|
||||
.unwrap(),
|
||||
);
|
||||
try_body.push(Stmt::Decl(Decl::Var(Box::new(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
declare: Default::default(),
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: ident.into(),
|
||||
init: Some(match decl.decl {
|
||||
DefaultDecl::Class(c) => Box::new(Expr::Class(c)),
|
||||
DefaultDecl::Fn(f) => Box::new(Expr::Fn(f)),
|
||||
DefaultDecl::TsInterfaceDecl(_) => unreachable!(),
|
||||
}),
|
||||
definite: Default::default(),
|
||||
}],
|
||||
}))));
|
||||
}
|
||||
|
||||
Ok(ModuleDecl::ExportDefaultExpr(decl)) => {
|
||||
let ident = private_ident!("_default");
|
||||
|
||||
// export { _default as default }
|
||||
new.push(
|
||||
T::try_from_module_decl(ModuleDecl::ExportNamed(NamedExport {
|
||||
span: DUMMY_SP,
|
||||
specifiers: vec![ExportSpecifier::Named(ExportNamedSpecifier {
|
||||
span: DUMMY_SP,
|
||||
orig: ModuleExportName::Ident(ident.clone()),
|
||||
exported: Some(ModuleExportName::Ident(Ident::new(
|
||||
"default".into(),
|
||||
DUMMY_SP,
|
||||
))),
|
||||
is_type_only: Default::default(),
|
||||
})],
|
||||
src: None,
|
||||
type_only: Default::default(),
|
||||
with: None,
|
||||
}))
|
||||
.unwrap(),
|
||||
);
|
||||
try_body.push(Stmt::Decl(Decl::Var(Box::new(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
declare: Default::default(),
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: ident.into(),
|
||||
init: Some(decl.expr),
|
||||
definite: Default::default(),
|
||||
}],
|
||||
}))));
|
||||
}
|
||||
|
||||
Ok(stmt) => new.push(T::try_from_module_decl(stmt).unwrap()),
|
||||
Err(stmt) => new.push(stmt),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Drop `;`
|
||||
try_body.retain(|stmt| !matches!(stmt, Stmt::Empty(..)));
|
||||
|
||||
// var error = $catch_var
|
||||
let error_catch_var = Stmt::Decl(Decl::Var(Box::new(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
declare: false,
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: state.error_var.clone().into(),
|
||||
init: Some(state.catch_var.clone().into()),
|
||||
definite: false,
|
||||
}],
|
||||
})));
|
||||
|
||||
// var has_error = true
|
||||
let has_error_true = Stmt::Decl(Decl::Var(Box::new(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
declare: false,
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: state.has_error.clone().into(),
|
||||
init: Some(true.into()),
|
||||
definite: false,
|
||||
}],
|
||||
})));
|
||||
let dispose_expr = CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: helper!(dispose),
|
||||
args: vec![
|
||||
state.stack.as_arg(),
|
||||
state.error_var.as_arg(),
|
||||
state.has_error.as_arg(),
|
||||
],
|
||||
type_args: Default::default(),
|
||||
};
|
||||
let dispose_stmt = if state.has_await {
|
||||
Expr::Await(AwaitExpr {
|
||||
span: DUMMY_SP,
|
||||
arg: Box::new(dispose_expr.into()),
|
||||
})
|
||||
} else {
|
||||
dispose_expr.into()
|
||||
}
|
||||
.into_stmt();
|
||||
|
||||
let try_stmt = TryStmt {
|
||||
span: DUMMY_SP,
|
||||
block: BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: try_body,
|
||||
},
|
||||
handler: Some(CatchClause {
|
||||
span: DUMMY_SP,
|
||||
param: Some(state.catch_var.into()),
|
||||
body: BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![error_catch_var, has_error_true],
|
||||
},
|
||||
}),
|
||||
finalizer: Some(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![dispose_stmt],
|
||||
}),
|
||||
};
|
||||
|
||||
new.push(T::from_stmt(Stmt::Try(Box::new(try_stmt))));
|
||||
|
||||
*stmts = new;
|
||||
}
|
||||
}
|
||||
|
||||
impl VisitMut for ExplicitResourceManagement {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn visit_mut_for_of_stmt(&mut self, n: &mut ForOfStmt) {
|
||||
n.visit_mut_children_with(self);
|
||||
|
||||
if let ForHead::UsingDecl(decl) = &mut n.left {
|
||||
let state = State::default();
|
||||
|
||||
n.left = ForHead::VarDecl(Box::new(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Const,
|
||||
declare: false,
|
||||
decls: decl.decls.take(),
|
||||
}));
|
||||
|
||||
let mut body = vec![*n.body.take()];
|
||||
self.wrap_with_try(state, &mut body);
|
||||
n.body = Box::new(Stmt::Block(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: body,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_module_items(&mut self, stmts: &mut Vec<ModuleItem>) {
|
||||
self.visit_mut_stmt_likes(stmts)
|
||||
}
|
||||
|
||||
fn visit_mut_stmt(&mut self, s: &mut Stmt) {
|
||||
s.visit_mut_children_with(self);
|
||||
|
||||
if let Stmt::Decl(Decl::Using(decl)) = s {
|
||||
let state = self.state.get_or_insert_with(Default::default);
|
||||
|
||||
state.has_await |= decl.is_await;
|
||||
|
||||
*s = Stmt::Decl(Decl::Var(Box::new(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: if self.is_not_top_level {
|
||||
VarDeclKind::Const
|
||||
} else {
|
||||
VarDeclKind::Var
|
||||
},
|
||||
declare: Default::default(),
|
||||
decls: decl
|
||||
.decls
|
||||
.take()
|
||||
.into_iter()
|
||||
.map(|d| {
|
||||
let init = CallExpr {
|
||||
span: decl.span,
|
||||
callee: helper!(using),
|
||||
args: once(state.stack.clone().as_arg())
|
||||
.chain(once(d.init.unwrap().as_arg()))
|
||||
.chain(if decl.is_await {
|
||||
Some(true.as_arg())
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.collect(),
|
||||
type_args: Default::default(),
|
||||
};
|
||||
|
||||
VarDeclarator {
|
||||
init: Some(init.into()),
|
||||
..d
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_stmts(&mut self, stmts: &mut Vec<Stmt>) {
|
||||
let old_is_not_top_level = self.is_not_top_level;
|
||||
self.is_not_top_level = true;
|
||||
self.visit_mut_stmt_likes(stmts);
|
||||
self.is_not_top_level = old_is_not_top_level;
|
||||
}
|
||||
}
|
||||
106
third-party/vendor/swc_ecma_transforms_proposal/src/export_default_from.rs
vendored
Normal file
106
third-party/vendor/swc_ecma_transforms_proposal/src/export_default_from.rs
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
use swc_common::DUMMY_SP;
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_utils::quote_ident;
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut};
|
||||
|
||||
/// `@babel/plugin-proposal-export-default-from`
|
||||
pub fn export_default_from() -> impl Fold + VisitMut {
|
||||
as_folder(ExportDefaultFrom)
|
||||
}
|
||||
|
||||
struct ExportDefaultFrom;
|
||||
|
||||
impl VisitMut for ExportDefaultFrom {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn visit_mut_module_items(&mut self, items: &mut Vec<ModuleItem>) {
|
||||
let count = items
|
||||
.iter()
|
||||
.filter(|m| {
|
||||
matches!(m, ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(NamedExport {
|
||||
specifiers,
|
||||
src: Some(..),
|
||||
type_only: false,
|
||||
..
|
||||
})) if specifiers.iter().any(|s| s.is_default()))
|
||||
})
|
||||
.count();
|
||||
|
||||
if count == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut stmts = Vec::<ModuleItem>::with_capacity(items.len() + count);
|
||||
|
||||
for item in items.drain(..) {
|
||||
match item {
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(NamedExport {
|
||||
span,
|
||||
specifiers,
|
||||
src: Some(src),
|
||||
type_only: false,
|
||||
with,
|
||||
})) if specifiers.iter().any(|s| s.is_default()) => {
|
||||
let mut origin_specifiers = vec![];
|
||||
|
||||
let mut export_specifiers = vec![];
|
||||
|
||||
let mut has_namespace = false;
|
||||
|
||||
for s in specifiers.into_iter() {
|
||||
match s {
|
||||
ExportSpecifier::Default(ExportDefaultSpecifier { exported }) => {
|
||||
export_specifiers.push(ExportSpecifier::Named(
|
||||
ExportNamedSpecifier {
|
||||
span: DUMMY_SP,
|
||||
orig: quote_ident!(exported.span, "default").into(),
|
||||
exported: Some(exported.into()),
|
||||
is_type_only: false,
|
||||
},
|
||||
));
|
||||
}
|
||||
ExportSpecifier::Namespace(..) => {
|
||||
has_namespace = true;
|
||||
origin_specifiers.push(s);
|
||||
}
|
||||
ExportSpecifier::Named(..) => {
|
||||
if has_namespace {
|
||||
origin_specifiers.push(s);
|
||||
} else {
|
||||
export_specifiers.push(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stmts.push(ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(
|
||||
NamedExport {
|
||||
span,
|
||||
specifiers: export_specifiers,
|
||||
src: Some(src.clone()),
|
||||
type_only: false,
|
||||
with: None,
|
||||
},
|
||||
)));
|
||||
|
||||
if !origin_specifiers.is_empty() {
|
||||
stmts.push(ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(
|
||||
NamedExport {
|
||||
span,
|
||||
specifiers: origin_specifiers,
|
||||
src: Some(src),
|
||||
type_only: false,
|
||||
with,
|
||||
},
|
||||
)));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
stmts.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*items = stmts;
|
||||
}
|
||||
}
|
||||
23
third-party/vendor/swc_ecma_transforms_proposal/src/import_assertions.rs
vendored
Normal file
23
third-party/vendor/swc_ecma_transforms_proposal/src/import_assertions.rs
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
use swc_ecma_ast::{ExportAll, ImportDecl, NamedExport};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut};
|
||||
|
||||
pub fn import_assertions() -> impl VisitMut + Fold {
|
||||
as_folder(ImportAssertions)
|
||||
}
|
||||
struct ImportAssertions;
|
||||
|
||||
impl VisitMut for ImportAssertions {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn visit_mut_import_decl(&mut self, n: &mut ImportDecl) {
|
||||
n.with = None;
|
||||
}
|
||||
|
||||
fn visit_mut_export_all(&mut self, n: &mut ExportAll) {
|
||||
n.with = None;
|
||||
}
|
||||
|
||||
fn visit_mut_named_export(&mut self, n: &mut NamedExport) {
|
||||
n.with = None;
|
||||
}
|
||||
}
|
||||
13
third-party/vendor/swc_ecma_transforms_proposal/src/lib.rs
vendored
Normal file
13
third-party/vendor/swc_ecma_transforms_proposal/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#![deny(clippy::all)]
|
||||
#![allow(clippy::vec_box)]
|
||||
|
||||
pub use self::{
|
||||
decorators::decorators, export_default_from::export_default_from,
|
||||
import_assertions::import_assertions,
|
||||
};
|
||||
|
||||
pub mod decorator_2022_03;
|
||||
pub mod decorators;
|
||||
pub mod explicit_resource_management;
|
||||
mod export_default_from;
|
||||
mod import_assertions;
|
||||
Loading…
Add table
Add a link
Reference in a new issue