Skip to content

Commit

Permalink
Metadata for typescript decorator (swc-project#939)
Browse files Browse the repository at this point in the history
swc_ecma_transforms:
 - Allow emitting decorator metadata (swc-project#666, swc-project#919)

swc:
 - change order of passes to allow decorator using type informations
  • Loading branch information
kdy1 committed Aug 6, 2020
1 parent 5fb77db commit 0989e73
Show file tree
Hide file tree
Showing 10 changed files with 1,185 additions and 78 deletions.
4 changes: 2 additions & 2 deletions ecmascript/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "swc_ecmascript"
version = "0.2.0"
version = "0.3.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
Expand All @@ -20,7 +20,7 @@ swc_ecma_ast = { version = "0.28.0", path ="./ast" }
swc_ecma_codegen = { version = "0.31.0", path ="./codegen", optional = true }
swc_ecma_parser = { version = "0.33.0", path ="./parser", optional = true }
swc_ecma_utils = { version = "0.17.0", path ="./utils", optional = true }
swc_ecma_transforms = { version = "0.18.0", path ="./transforms", optional = true }
swc_ecma_transforms = { version = "0.19.0", path ="./transforms", optional = true }
swc_ecma_visit = { version = "0.13.0", path ="./visit", optional = true }

[dev-dependencies]
2 changes: 1 addition & 1 deletion ecmascript/transforms/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "swc_ecma_transforms"
version = "0.18.1"
version = "0.19.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
Expand Down
9 changes: 7 additions & 2 deletions ecmascript/transforms/src/proposals/decorators.rs
@@ -1,4 +1,3 @@
use self::legacy::Legacy;
use crate::util::{
alias_ident_for, constructor::inject_after_super, prop_name_to_expr_value, undefined,
ExprFactory, IdentExt,
Expand Down Expand Up @@ -55,17 +54,23 @@ mod usage;
/// ```
pub fn decorators(c: Config) -> impl Fold {
if c.legacy {
Either::Left(Legacy::default())
Either::Left(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,
})
}
}

#[derive(Debug, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Config {
pub legacy: bool,
#[serde(default)]
pub emit_metadata: bool,
}

#[derive(Debug, Default)]
Expand Down
50 changes: 46 additions & 4 deletions ecmascript/transforms/src/proposals/decorators/legacy.rs
@@ -1,3 +1,4 @@
use self::metadata::{Metadata, ParamMetadata};
use super::usage::DecoratorFinder;
use crate::util::{
alias_if_required, default_constructor, prepend, prop_name_to_expr_value, undefined,
Expand All @@ -9,13 +10,25 @@ use swc_common::{util::move_map::MoveMap, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, VisitWith};

#[derive(Debug, Default)]
mod metadata;

#[derive(Debug)]
pub(super) struct Legacy {
metadata: bool,
uninitialized_vars: Vec<VarDeclarator>,
initialized_vars: Vec<VarDeclarator>,
exports: Vec<ExportSpecifier>,
}

pub(super) fn new(metadata: bool) -> Legacy {
Legacy {
metadata,
uninitialized_vars: Default::default(),
initialized_vars: Default::default(),
exports: Default::default(),
}
}

noop_fold_type!(Legacy);

impl Fold for Legacy {
Expand Down Expand Up @@ -197,6 +210,14 @@ impl Legacy {

impl Legacy {
fn handle(&mut self, mut c: ClassExpr) -> Box<Expr> {
if self.metadata {
let i = c.ident.clone();

c = c.fold_with(&mut ParamMetadata).fold_with(&mut Metadata {
class_name: i.as_ref(),
});
}

let cls_ident = private_ident!("_class");
let cls_name = c.ident.clone();

Expand Down Expand Up @@ -663,12 +684,13 @@ impl Legacy {
}));

let expr = self.apply(
&cls_ident,
if extra_exprs.is_empty() {
var_init
} else {
extra_exprs.insert(0, var_init);
// Return value.
extra_exprs.push(Box::new(Expr::Ident(cls_ident)));
extra_exprs.push(Box::new(Expr::Ident(cls_ident.clone())));

Box::new(Expr::Seq(SeqExpr {
span: DUMMY_SP,
Expand All @@ -682,7 +704,12 @@ impl Legacy {
}

/// Apply class decorators.
fn apply(&mut self, mut expr: Box<Expr>, decorators: Vec<Decorator>) -> Box<Expr> {
fn apply(
&mut self,
class_ident: &Ident,
mut expr: Box<Expr>,
decorators: Vec<Decorator>,
) -> Box<Expr> {
for dec in decorators.into_iter().rev() {
let (i, aliased) = alias_if_required(&dec.expr, "_dec");
if aliased {
Expand All @@ -694,12 +721,27 @@ impl Legacy {
});
}

expr = Box::new(Expr::Call(CallExpr {
let dec_call_expr = Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
callee: i.as_callee(),
args: vec![expr.as_arg()],
type_args: None,
}));

// _class = dec(_class = funciton() {}) || _class
let class_expr = Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
left: PatOrExpr::Pat(Box::new(Pat::Ident(class_ident.clone()))),
op: op!("="),
right: Box::new(Expr::Bin(BinExpr {
span: DUMMY_SP,
left: dec_call_expr,
op: op!("||"),
right: Box::new(Expr::Ident(class_ident.clone())),
})),
}));

expr = class_expr;
}

expr
Expand Down

0 comments on commit 0989e73

Please sign in to comment.