Skip to content

Commit

Permalink
refactor: Simplified processing logic
Browse files Browse the repository at this point in the history
  • Loading branch information
magic-akari committed Aug 12, 2023
1 parent eace3f4 commit 8118f32
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 194 deletions.
188 changes: 54 additions & 134 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@ use swc_core::{
common::{Span, Spanned, DUMMY_SP},
ecma::{
ast::*,
atoms::{js_word, JsWord},
utils::{
is_valid_prop_ident, member_expr, private_ident, quote_ident, quote_str, ExprFactory,
FunctionFactory, IdentExt,
},
atoms::JsWord,
utils::{member_expr, private_ident, quote_ident, quote_str, ExprFactory, IdentExt},
},
};

Expand Down Expand Up @@ -38,58 +35,59 @@ impl ObjPropKeyIdent {
&self.0
}

pub fn into_expr(self) -> Expr {
self.2.into()
pub fn ident(&self) -> &Ident {
&self.2
}
}

/// ```javascript
/// {
/// key: () => expr,
/// get() { return ident; }
/// }
/// ```
pub(crate) fn prop_arrow(prop: ObjPropKeyIdent) -> Prop {
let key = prop_name(prop.key(), prop.span()).into();
pub(crate) fn prop_method_getter(ident: Ident) -> Prop {
let key = quote_ident!("get").into();

KeyValueProp {
MethodProp {
key,
value: Box::new(prop.into_expr().into_lazy_arrow(Default::default()).into()),
function: ident.into_lazy_fn(Default::default()).into(),
}
.into()
}

pub(crate) fn prop_name(key: &str, span: Span) -> IdentOrStr {
if is_valid_prop_ident(key) {
IdentOrStr::Ident(quote_ident!(span, key))
} else {
IdentOrStr::Str(quote_str!(span, key))
}
}
/// ```javascript
/// {
/// set(v) { ident = v; }
/// }
/// ```
pub(crate) fn prop_method_setter(ident: Ident) -> Prop {
let key = quote_ident!("set").into();

pub(crate) enum IdentOrStr {
Ident(Ident),
Str(Str),
}
let setter_param = private_ident!("v");
let params = vec![setter_param.clone().into()];

impl From<IdentOrStr> for PropName {
fn from(val: IdentOrStr) -> Self {
match val {
IdentOrStr::Ident(i) => Self::Ident(i),
IdentOrStr::Str(s) => Self::Str(s),
}
}
}
let body = BlockStmt {
span: DUMMY_SP,
stmts: vec![setter_param
.make_assign_to(op!("="), Pat::Ident(ident.clone().into()).into())
.into_stmt()],
};

impl From<IdentOrStr> for MemberProp {
fn from(val: IdentOrStr) -> Self {
match val {
IdentOrStr::Ident(i) => Self::Ident(i),
IdentOrStr::Str(s) => Self::Computed(ComputedPropName {
span: DUMMY_SP,
expr: s.into(),
}),
MethodProp {
key,
function: Function {
params,
decorators: Default::default(),
span: DUMMY_SP,
body: Some(body),
is_generator: false,
is_async: false,
type_params: None,
return_type: None,
}
.into(),
}
.into()
}

/// Creates
Expand All @@ -112,7 +110,8 @@ pub(super) fn object_define_property(
pub(crate) fn object_define_enumerable_configurable(
target: ExprOrSpread,
prop_name: ExprOrSpread,
prop: PropOrSpread,
getter: PropOrSpread,
setter: PropOrSpread,
) -> Expr {
object_define_property(
target,
Expand All @@ -127,7 +126,8 @@ pub(crate) fn object_define_enumerable_configurable(
}
.into(),
)),
prop,
getter,
setter,
PropOrSpread::Prop(Box::new(
KeyValueProp {
key: quote_ident!("configurable").into(),
Expand All @@ -141,99 +141,19 @@ pub(crate) fn object_define_enumerable_configurable(
)
}

pub(crate) fn emit_export_stmts(exports: Ident, mut prop_list: Vec<ObjPropKeyIdent>) -> Vec<Stmt> {
match prop_list.len() {
0 | 1 => prop_list
.pop()
.map(|obj_prop| {
object_define_enumerable_configurable(
exports.as_arg(),
quote_str!(obj_prop.span(), obj_prop.key()).as_arg(),
prop_arrow((js_word!("get"), DUMMY_SP, obj_prop.2.clone()).into()).into(),
)
.into_stmt()
})
.into_iter()
.collect(),
_ => {
let props = prop_list
.into_iter()
.map(prop_arrow)
.map(Into::into)
.collect();
let obj_lit = ObjectLit {
span: DUMMY_SP,
props,
};

let esm_export_ident = private_ident!("_export");

vec![
Stmt::Decl(Decl::Fn(
esm_export().into_fn_decl(esm_export_ident.clone()),
)),
esm_export_ident
.as_call(DUMMY_SP, vec![exports.as_arg(), obj_lit.as_arg()])
.into_stmt(),
]
}
}
}

/// ```javascript
/// function _esmExport(target, all) {
/// for (var name in all)Object.defineProperty(target, name, { get: all[name], enumerable: true, configurable: true });
/// }
/// ```
pub(crate) fn esm_export() -> Function {
let target = private_ident!("target");
let all = private_ident!("all");
let name = private_ident!("name");

let getter = KeyValueProp {
key: quote_ident!("get").into(),
value: Box::new(all.clone().computed_member(Expr::from(name.clone()))),
};

let body = object_define_enumerable_configurable(
target.clone().as_arg(),
name.clone().as_arg(),
PropOrSpread::Prop(Box::new(Prop::KeyValue(getter))),
)
.into_stmt();

let for_in_stmt: Stmt = ForInStmt {
span: DUMMY_SP,
left: VarDecl {
span: DUMMY_SP,
kind: VarDeclKind::Var,
declare: false,
decls: vec![VarDeclarator {
span: DUMMY_SP,
name: name.into(),
init: None,
definite: false,
}],
}
.into(),
right: Box::new(all.clone().into()),
body: Box::new(body),
}
.into();

Function {
params: vec![target.into(), all.into()],
decorators: Default::default(),
span: DUMMY_SP,
body: Some(BlockStmt {
span: DUMMY_SP,
stmts: vec![for_in_stmt],
}),
is_generator: false,
is_async: false,
type_params: None,
return_type: None,
}
pub(crate) fn emit_export_stmts(exports: Ident, prop_list: Vec<ObjPropKeyIdent>) -> Vec<Stmt> {
prop_list
.into_iter()
.map(|obj_prop| {
object_define_enumerable_configurable(
exports.clone().as_arg(),
quote_str!(obj_prop.span(), obj_prop.key()).as_arg(),
prop_method_getter(obj_prop.ident().clone()).into(),
prop_method_setter(obj_prop.ident().clone()).into(),
)
.into_stmt()
})
.collect()
}

pub(crate) fn key_from_export_name(n: &ModuleExportName) -> (JsWord, Span) {
Expand Down
29 changes: 19 additions & 10 deletions tests/fixture/case_1/output.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
export { };
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name],
configurable: true
});
}
_export(exports, {
child: ()=>child,
callChild: ()=>callChild
Object.defineProperty(exports, "child", {
enumerable: true,
get () {
return child;
},
set (v) {
child = v;
},
configurable: true
});
Object.defineProperty(exports, "callChild", {
enumerable: true,
get () {
return callChild;
},
set (v) {
callChild = v;
},
configurable: true
});
const child = ()=>{
console.log("Hello World!");
Expand Down
62 changes: 49 additions & 13 deletions tests/fixture/case_11/output.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,53 @@
export { };
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name],
configurable: true
});
}
_export(exports, {
foo: ()=>foo1,
foofoo: ()=>foofoo,
bar: ()=>bar1,
"y-1": ()=>x1,
ns: ()=>ns
Object.defineProperty(exports, "foo", {
enumerable: true,
get () {
return foo1;
},
set (v) {
foo1 = v;
},
configurable: true
});
Object.defineProperty(exports, "foofoo", {
enumerable: true,
get () {
return foofoo;
},
set (v) {
foofoo = v;
},
configurable: true
});
Object.defineProperty(exports, "bar", {
enumerable: true,
get () {
return bar1;
},
set (v) {
bar1 = v;
},
configurable: true
});
Object.defineProperty(exports, "y-1", {
enumerable: true,
get () {
return x1;
},
set (v) {
x1 = v;
},
configurable: true
});
Object.defineProperty(exports, "ns", {
enumerable: true,
get () {
return ns;
},
set (v) {
ns = v;
},
configurable: true
});
import { foo } from "foo";
import { foo as foo1, foofoo as foofoo } from "foo";
Expand Down
7 changes: 6 additions & 1 deletion tests/fixture/case_2/output.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
export { };
Object.defineProperty(exports, "getRedis", {
enumerable: true,
get: ()=>getRedis,
get () {
return getRedis;
},
set (v) {
getRedis = v;
},
configurable: true
});
import memoize from "p-memoize";
Expand Down
7 changes: 6 additions & 1 deletion tests/fixture/case_3/output.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
export { };
Object.defineProperty(exports, "App", {
enumerable: true,
get: ()=>App,
get () {
return App;
},
set (v) {
App = v;
},
configurable: true
});
import React from "react";
Expand Down
Loading

0 comments on commit 8118f32

Please sign in to comment.