diff --git a/src/lib.rs b/src/lib.rs index 36aea59..508c041 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -217,13 +217,27 @@ test!( t19, r#"
{ + array.map((item) => item) + } + { + array.map((item) => item * x) + } + { array.map((item) => { - return {item * 2} + return item * x; }) } + { + array.map((item) => { + return {item * x} + }) + } + { + array.map((item) =>
{item * x}
) + } { array.filter((item) => { - return {item * 2} + return {item * x} }) } { @@ -234,3 +248,106 @@ test!(
"# ); + +test!( + Syntax::Es(EsSyntax { + jsx: true, + ..Default::default() + },), + |_| TransformVisitor, + t20, + r#""# +); + +test!( + Syntax::Es(EsSyntax { + jsx: true, + ..Default::default() + },), + |_| TransformVisitor, + t21, + r#""# +); + +test!( + Syntax::Es(EsSyntax { + jsx: true, + ..Default::default() + },), + |_| TransformVisitor, + t22, + r#"const x = arr.map(a => a*2)"# +); + +test!( + Syntax::Es(EsSyntax { + jsx: true, + ..Default::default() + },), + |_| TransformVisitor, + t23, + r#"const x = $(arr.map(a => a*2))"# +); + +test!( + Syntax::Es(EsSyntax { + jsx: true, + ..Default::default() + },), + |_| TransformVisitor, + t24, + r#"const x = $(() => x + 1)"# +); + + +test!( + Syntax::Es(EsSyntax { + jsx: true, + ..Default::default() + },), + |_| TransformVisitor, + t25, + r#"const x = $(x.$.y)"# +); + +test!( + Syntax::Es(EsSyntax { + jsx: true, + ..Default::default() + },), + |_| TransformVisitor, + t26, + r#" + const x =
{x+1}
; + const x = $(
{x+1}
); + "# +); + + +test!( + Syntax::Es(EsSyntax { + jsx: true, + ..Default::default() + },), + |_| TransformVisitor, + t27, + r#" + const x = $([ + 1,2,y+1 + ]) + "# +); + +test!( + Syntax::Es(EsSyntax { + jsx: true, + ..Default::default() + },), + |_| TransformVisitor, + t28, + r#" + const x = $([ + 1,2,3 + ]) + "# +); \ No newline at end of file diff --git a/src/visitor.rs b/src/visitor.rs index 4e26ac3..26781ee 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,5 +1,5 @@ -use swc_core::ecma::ast::{IdentName, JSXAttr, JSXAttrName, JSXAttrValue, JSXElement, JSXElementChild, JSXSpreadChild, MemberExpr, MemberProp}; -use swc_core::ecma::visit::VisitWith; +use swc_core::ecma::ast::{FnExpr, IdentName, JSXAttr, JSXAttrName, JSXAttrValue, JSXElement, JSXElementChild, JSXSpreadChild, MemberExpr, MemberProp}; +use swc_core::ecma::visit::{FoldWith, VisitWith}; use swc_core::{ atoms::Atom, common::{util::take::Take, SyntaxContext, DUMMY_SP}, @@ -91,7 +91,10 @@ impl TransformVisitor { Default::default(), )))), args: vec![ - m.obj.clone().into(), + ExprOrSpread { + expr: self.transform_expr_reactive(m.obj.clone()), + spread: None + }, // convert prop to string match &m.prop { MemberProp::Ident(_) => Expr::Lit(Lit::Str(Str { @@ -131,7 +134,31 @@ impl TransformVisitor { format!("$.{}", prop.as_ident().unwrap().sym).to_string() )), }))), - args: c.args.clone(), + // transform first arg if it's a function, keep others + args: c.args.clone().into_iter().map(|a| { + match a { + ExprOrSpread { + expr: e, + spread: None, + } => match e.unwrap_parens() { + Expr::Arrow(a1) => ExprOrSpread { + expr: { + let mut a2 = a1.clone(); + a2.body = Box::new( + *a2.body.fold_with(self) + ); + Box::new(Expr::Arrow(a2)) + }, + spread: None, + }, + _ => ExprOrSpread { + expr: e, + spread: None, + } + }, + _ => a + } + }).collect(), type_args: Take::dummy(), ctxt: Default::default(), })) @@ -141,7 +168,7 @@ impl TransformVisitor { // already has an always() or $$() wrapper Expr::Call(c) if c.callee.is_expr() - && (c.callee.as_expr().unwrap().is_ident_ref_to("always") + && (c.callee.as_expr().unwrap().is_ident_ref_to("_$") || c.callee.as_expr().unwrap().is_ident_ref_to("$$")) => { e @@ -158,7 +185,7 @@ impl TransformVisitor { _ => Box::new(Expr::Call(CallExpr { span: DUMMY_SP, callee: Callee::Expr(Box::new(Expr::Ident(Ident::new( - "always".into(), + "_$".into(), DUMMY_SP, Default::default(), )))), @@ -299,33 +326,45 @@ impl Fold for TransformVisitor { DUMMY_SP, call.ctxt, )))), - args: vec![arg.into()], + args: vec![arg.fold_with(self).into()], type_args: Take::dummy(), ctxt: call.ctxt, }, // default: wrap in always - _ => CallExpr { - span: DUMMY_SP, - callee: Callee::Expr(Box::new(Expr::Ident(Ident::new( - "always".into(), - DUMMY_SP, - call.ctxt, - )))), - args: vec![Expr::Arrow(ArrowExpr { - span: DUMMY_SP, - params: Take::dummy(), - body: Box::new(BlockStmtOrExpr::Expr(arg)), - is_async: false, - is_generator: false, - type_params: Take::dummy(), - return_type: Take::dummy(), - ctxt: call.ctxt, - }) - .into()], - type_args: Take::dummy(), - ctxt: call.ctxt, - }, + _ => { + let reactive = self.transform_expr_reactive(arg.clone()); + match reactive.unwrap_parens() { + Expr::Call(c) => c.clone(), + // transform_expr_reactive returns a CallExpr in all cases except for Expr::Arrow(_) | Expr::Fn + _ => CallExpr { + span: DUMMY_SP, + callee: Callee::Expr(Box::new(Expr::Ident(Ident::new( + "_$".into(), + DUMMY_SP, + call.ctxt, + )))), + args: vec![ + match arg.unwrap_parens() { + Expr::Arrow(_) | Expr::Fn(_) => arg.into(), + _ => Expr::Arrow(ArrowExpr { + span: DUMMY_SP, + params: Take::dummy(), + body: Box::new(BlockStmtOrExpr::Expr(arg)), + is_async: false, + is_generator: false, + type_params: Take::dummy(), + return_type: Take::dummy(), + ctxt: call.ctxt, + }) + .into(), + } + ], + type_args: Take::dummy(), + ctxt: call.ctxt, + } + } + } }; } @@ -343,7 +382,7 @@ impl Fold for TransformVisitor { // if n.callee.is_expr() && n.callee.expect_expr().expect_ident().sym.eq_ignore_ascii_case("$") { // return CallExpr { // span: DUMMY_SP, - // callee: Callee::Expr(Box::new(Expr::Ident(Ident::new("always".into(), DUMMY_SP)))), + // callee: Callee::Expr(Box::new(Expr::Ident(Ident::new("_$".into(), DUMMY_SP)))), // args: vec![Expr::Arrow(ArrowExpr { // span: DUMMY_SP, // params: Take::dummy(), diff --git a/tests/__swc_snapshots__/src/lib.rs/t11.js b/tests/__swc_snapshots__/src/lib.rs/t11.js index 0ced79a..4785e07 100644 --- a/tests/__swc_snapshots__/src/lib.rs/t11.js +++ b/tests/__swc_snapshots__/src/lib.rs/t11.js @@ -1 +1 @@ -
{always(()=>x + 1)}
; +
{_$(()=>x + 1)}
; diff --git a/tests/__swc_snapshots__/src/lib.rs/t12.js b/tests/__swc_snapshots__/src/lib.rs/t12.js index 408e302..778de2e 100644 --- a/tests/__swc_snapshots__/src/lib.rs/t12.js +++ b/tests/__swc_snapshots__/src/lib.rs/t12.js @@ -1,5 +1,5 @@
- {always(()=>x + 1)} - {always(()=>y + 1)} - X + Y = {always(()=>x + y)} + {_$(()=>x + 1)} + {_$(()=>y + 1)} + X + Y = {_$(()=>x + y)}
; diff --git a/tests/__swc_snapshots__/src/lib.rs/t13.js b/tests/__swc_snapshots__/src/lib.rs/t13.js index 239da97..bbcc2d3 100644 --- a/tests/__swc_snapshots__/src/lib.rs/t13.js +++ b/tests/__swc_snapshots__/src/lib.rs/t13.js @@ -1,3 +1,3 @@
- {always(()=>x ? {x + 1} : False)} + {_$(()=>x ? {x + 1} : False)}
; diff --git a/tests/__swc_snapshots__/src/lib.rs/t19.js b/tests/__swc_snapshots__/src/lib.rs/t19.js index 0f0a283..d511639 100644 --- a/tests/__swc_snapshots__/src/lib.rs/t19.js +++ b/tests/__swc_snapshots__/src/lib.rs/t19.js @@ -1,11 +1,17 @@
+ {array.$.map((item)=>item)} + {array.$.map((item)=>item * x)} + {array.$.map((item)=>{ + return item * x; +})} {array.$.map((item)=>{ - return {item * 2}; + return {_$(()=>item * x)}; })} + {array.$.map((item)=>
{_$(()=>item * x)}
)} {array.$.filter((item)=>{ - return {item * 2}; + return {_$(()=>item * x)}; })} - {always(()=>array.normalMethod((item)=>{ + {_$(()=>array.normalMethod((item)=>{ return {item * 2}; }))}
; diff --git a/tests/__swc_snapshots__/src/lib.rs/t2.js b/tests/__swc_snapshots__/src/lib.rs/t2.js index 28e6fd0..5d5444f 100644 --- a/tests/__swc_snapshots__/src/lib.rs/t2.js +++ b/tests/__swc_snapshots__/src/lib.rs/t2.js @@ -1 +1 @@ -const y = always(()=>y * 2); +const y = _$(()=>y * 2); diff --git a/tests/__swc_snapshots__/src/lib.rs/t20.js b/tests/__swc_snapshots__/src/lib.rs/t20.js new file mode 100644 index 0000000..787cfce --- /dev/null +++ b/tests/__swc_snapshots__/src/lib.rs/t20.js @@ -0,0 +1 @@ +; diff --git a/tests/__swc_snapshots__/src/lib.rs/t21.js b/tests/__swc_snapshots__/src/lib.rs/t21.js new file mode 100644 index 0000000..275afcc --- /dev/null +++ b/tests/__swc_snapshots__/src/lib.rs/t21.js @@ -0,0 +1 @@ +; diff --git a/tests/__swc_snapshots__/src/lib.rs/t22.js b/tests/__swc_snapshots__/src/lib.rs/t22.js new file mode 100644 index 0000000..a831390 --- /dev/null +++ b/tests/__swc_snapshots__/src/lib.rs/t22.js @@ -0,0 +1 @@ +const x = arr.map((a)=>a * 2); diff --git a/tests/__swc_snapshots__/src/lib.rs/t23.js b/tests/__swc_snapshots__/src/lib.rs/t23.js new file mode 100644 index 0000000..98eb294 --- /dev/null +++ b/tests/__swc_snapshots__/src/lib.rs/t23.js @@ -0,0 +1 @@ +const x = arr.$.map((a)=>a * 2); diff --git a/tests/__swc_snapshots__/src/lib.rs/t24.js b/tests/__swc_snapshots__/src/lib.rs/t24.js new file mode 100644 index 0000000..c2d6d10 --- /dev/null +++ b/tests/__swc_snapshots__/src/lib.rs/t24.js @@ -0,0 +1 @@ +const x = _$(()=>x + 1); diff --git a/tests/__swc_snapshots__/src/lib.rs/t25.js b/tests/__swc_snapshots__/src/lib.rs/t25.js new file mode 100644 index 0000000..f9bbd71 --- /dev/null +++ b/tests/__swc_snapshots__/src/lib.rs/t25.js @@ -0,0 +1 @@ +const x = _$(()=>x.$.y); diff --git a/tests/__swc_snapshots__/src/lib.rs/t26.js b/tests/__swc_snapshots__/src/lib.rs/t26.js new file mode 100644 index 0000000..8b27ad9 --- /dev/null +++ b/tests/__swc_snapshots__/src/lib.rs/t26.js @@ -0,0 +1,2 @@ +const x =
{_$(()=>x + 1)}
; +const x = $$(
{_$(()=>x + 1)}
); diff --git a/tests/__swc_snapshots__/src/lib.rs/t27.js b/tests/__swc_snapshots__/src/lib.rs/t27.js new file mode 100644 index 0000000..aa6ea3a --- /dev/null +++ b/tests/__swc_snapshots__/src/lib.rs/t27.js @@ -0,0 +1,5 @@ +const x = _$(()=>[ + 1, + 2, + y + 1 + ]); diff --git a/tests/__swc_snapshots__/src/lib.rs/t28.js b/tests/__swc_snapshots__/src/lib.rs/t28.js new file mode 100644 index 0000000..1cc1ee0 --- /dev/null +++ b/tests/__swc_snapshots__/src/lib.rs/t28.js @@ -0,0 +1,5 @@ +const x = _$(()=>[ + 1, + 2, + 3 + ]); diff --git a/tests/__swc_snapshots__/src/lib.rs/t7.js b/tests/__swc_snapshots__/src/lib.rs/t7.js index accb4b6..d5913e5 100644 --- a/tests/__swc_snapshots__/src/lib.rs/t7.js +++ b/tests/__swc_snapshots__/src/lib.rs/t7.js @@ -1 +1 @@ -