Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(es/compat): Implement decorator metadata proposal #8097

Merged
merged 1 commit into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 36 additions & 11 deletions crates/swc_ecma_transforms_base/src/helpers/_apply_decs_2203_r.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ function applyDecs2203RFactory() {
kind,
isStatic,
isPrivate,
metadata,
value
) {
var kindStr;
Expand All @@ -61,6 +62,7 @@ function applyDecs2203RFactory() {
name: isPrivate ? "#" + name : name,
static: isStatic,
private: isPrivate,
metadata: metadata,
};

var decoratorFinishedRef = { v: false };
Expand Down Expand Up @@ -168,7 +170,8 @@ function applyDecs2203RFactory() {
kind,
isStatic,
isPrivate,
initializers
initializers,
metadata
) {
var decs = decInfo[0];

Expand Down Expand Up @@ -221,6 +224,7 @@ function applyDecs2203RFactory() {
kind,
isStatic,
isPrivate,
metadata,
value
);

Expand Down Expand Up @@ -251,6 +255,7 @@ function applyDecs2203RFactory() {
kind,
isStatic,
isPrivate,
metadata,
value
);

Expand Down Expand Up @@ -345,7 +350,7 @@ function applyDecs2203RFactory() {
}
}

function applyMemberDecs(Class, decInfos) {
function applyMemberDecs(Class, decInfos, metadata) {
var ret = [];
var protoInitializers;
var staticInitializers;
Expand Down Expand Up @@ -415,7 +420,8 @@ function applyDecs2203RFactory() {
kind,
isStatic,
isPrivate,
initializers
initializers,
metadata
);
}

Expand All @@ -435,7 +441,7 @@ function applyDecs2203RFactory() {
}
}

function applyClassDecs(targetClass, classDecs) {
function applyClassDecs(targetClass, classDecs, metadata) {
if (classDecs.length > 0) {
var initializers = [];
var newClass = targetClass;
Expand All @@ -452,6 +458,7 @@ function applyDecs2203RFactory() {
initializers,
decoratorFinishedRef
),
metadata,
});
} finally {
decoratorFinishedRef.v = true;
Expand All @@ -464,7 +471,7 @@ function applyDecs2203RFactory() {
}

return [
newClass,
defineMetadata(newClass, metadata),
function () {
for (var i = 0; i < initializers.length; i++) {
initializers[i].call(newClass);
Expand All @@ -476,6 +483,14 @@ function applyDecs2203RFactory() {
// so we don't have to return an empty array here.
}

function defineMetadata(Class, metadata) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you write this by yourself? I want to know if there was a reference implementation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The js part is almost copied and adapted from babel implementation, while the Rust part obviously not
Tests are copied from babel

return Object.defineProperty(
Class,
Symbol.metadata || Symbol.for("Symbol.metadata"),
{ configurable: true, enumerable: true, value: metadata }
);
}

/**
Basic usage:

Expand Down Expand Up @@ -622,21 +637,31 @@ function applyDecs2203RFactory() {
initializeClass(Class);
*/

return function applyDecs2203R(targetClass, memberDecs, classDecs) {
return function applyDecs2203R(targetClass, memberDecs, classDecs, parentClass) {
if (parentClass !== void 0) {
var parentMetadata =
parentClass[Symbol.metadata || Symbol.for("Symbol.metadata")];
}
var metadata = Object.create(
parentMetadata === void 0 ? null : parentMetadata
);
var e = applyMemberDecs(targetClass, memberDecs, metadata);
if (!classDecs.length) defineMetadata(targetClass, metadata);
return {
e: applyMemberDecs(targetClass, memberDecs),
e: e,
// Lazily apply class decorations so that member init locals can be properly bound.
get c() {
return applyClassDecs(targetClass, classDecs);
return applyClassDecs(targetClass, classDecs, metadata);
},
};
};
}

function _apply_decs_2203_r(targetClass, memberDecs, classDecs) {
function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
return (_apply_decs_2203_r = applyDecs2203RFactory())(
targetClass,
memberDecs,
classDecs
classDecs,
parentClass
);
}
}
34 changes: 32 additions & 2 deletions crates/swc_ecma_transforms_proposal/src/decorator_2022_03.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ use swc_common::{util::take::Take, Spanned, SyntaxContext, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_transforms_base::{helper, helper_expr};
use swc_ecma_utils::{
constructor::inject_after_super, default_constructor, prepend_stmt, private_ident,
prop_name_to_expr_value, quote_ident, replace_ident, ExprFactory, IdentExt, IdentRenamer,
alias_ident_for, constructor::inject_after_super, default_constructor, prepend_stmt,
private_ident, prop_name_to_expr_value, quote_ident, replace_ident, ExprFactory, IdentExt,
IdentRenamer,
};
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};

Expand Down Expand Up @@ -53,6 +54,8 @@ struct ClassState {

class_lhs: Vec<Option<Pat>>,
class_decorators: Vec<Option<ExprOrSpread>>,

super_class: Option<Ident>,
}

impl Decorator202203 {
Expand Down Expand Up @@ -154,6 +157,10 @@ impl Decorator202203 {
.as_arg(),
);

if let Some(super_class) = self.state.super_class.as_ref() {
combined_args.push(super_class.clone().as_arg());
}

let e_pat = if e_lhs.is_empty() {
None
} else {
Expand Down Expand Up @@ -323,6 +330,27 @@ impl Decorator202203 {
unreachable!()
}

fn handle_super_class(&mut self, class: &mut Class) {
if let Some(super_class) = class.super_class.take() {
let id = alias_ident_for(&super_class, "_super");
self.extra_vars.push(VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(id.clone().into()),
init: None,
definite: false,
});

class.super_class = Some(Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
op: AssignOp::Assign,
left: PatOrExpr::Pat(Box::new(Pat::Ident(id.clone().into()))),
right: super_class,
})));

self.state.super_class = Some(id);
}
}

fn handle_class_expr(&mut self, class: &mut Class, ident: Option<&Ident>) -> Ident {
debug_assert!(
!class.decorators.is_empty(),
Expand Down Expand Up @@ -361,6 +389,7 @@ impl Decorator202203 {

let decorators = self.preserve_side_effect_of_decorators(class.decorators.take());
self.state.class_decorators.extend(decorators);
self.handle_super_class(class);

{
let call_stmt = CallExpr {
Expand Down Expand Up @@ -417,6 +446,7 @@ impl Decorator202203 {
self.state.class_lhs.push(Some(init_class.clone().into()));

self.state.class_decorators.extend(decorators);
self.handle_super_class(&mut c.class);

let mut body = c.class.body.take();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var _A, __, __1, __2, _C, __3, __11, __21, _class, __4, __12, __22, _class1, __5, __13, __23, _G, __6, __14, __24, _class2, __7, __15, __25, _class3, __8, __16, __26, _K, __9, __17, __27;
var _initClass, _A1, _initClass1, _C1, _initClass2, _class4, _initClass3, _class5, _initClass4, _G1, _initClass5, _class6, _initClass6, _class7, _initClass7, _K1;
var _initClass, _A1, _initClass1, _C1, _initClass2, _class4, _initClass3, _class5, _initClass4, _G1, _initClass5, _class6, _initClass6, _class7, _I, _initClass7, _K1, _L;
const dec = ()=>{};
const A = ((_A = class A {
}, __ = {
Expand Down Expand Up @@ -81,25 +81,25 @@ const F = [
value: _initClass5()
}, _class2), _class6)
];
const H = ((_class3 = class extends I {
const H = ((_class3 = class extends (_I = I) {
}, __8 = {
writable: true,
value: { c: [_class7, _initClass6] } = _apply_decs_2203_r(_class3, [], [
dec
])
], _I)
}, __16 = {
writable: true,
value: (()=>{})()
}, __26 = {
writable: true,
value: _initClass6()
}, _class3), _class7);
const J = ((_K = class K extends L {
const J = ((_K = class K extends (_L = L) {
}, __9 = {
writable: true,
value: { c: [_K1, _initClass7] } = _apply_decs_2203_r(_K, [], [
dec
])
], _L)
}, __17 = {
writable: true,
value: (()=>{})()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var _A, __, __1, _C, __2, __11, _class, __3, __12, _class1, __4, __13, _G, __5, __14, _class2, __6, __15, _class3, __7, __16, _K, __8, __17;
var _initClass, _A1, _initClass1, _C1, _initClass2, _class4, _initClass3, _class5, _initClass4, _G1, _initClass5, _class6, _initClass6, _class7, _initClass7, _K1;
var _initClass, _A1, _initClass1, _C1, _initClass2, _class4, _initClass3, _class5, _initClass4, _G1, _initClass5, _class6, _initClass6, _class7, _I, _initClass7, _K1, _L;
const dec = ()=>{};
const A = ((_A = class A {
}, __ = {
Expand Down Expand Up @@ -63,22 +63,22 @@ const F = [
value: _initClass5()
}, _class2), _class6)
];
const H = ((_class3 = class extends I {
const H = ((_class3 = class extends (_I = I) {
}, __7 = {
writable: true,
value: { c: [_class7, _initClass6] } = _apply_decs_2203_r(_class3, [], [
dec
])
], _I)
}, __16 = {
writable: true,
value: _initClass6()
}, _class3), _class7);
const J = ((_K = class K extends L {
const J = ((_K = class K extends (_L = L) {
}, __8 = {
writable: true,
value: { c: [_K1, _initClass7] } = _apply_decs_2203_r(_K, [], [
dec
])
], _L)
}, __17 = {
writable: true,
value: _initClass7()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
var _initClass, _initClass1;
var _initClass, _initClass1, _Bar;
const dec1 = ()=>{};
const dec2 = ()=>{};
let _Bar;
let _Bar1;
class Bar {
}
var __ = {
writable: true,
value: { c: [_Bar, _initClass] } = _apply_decs_2203_r(Bar, [], [
value: { c: [_Bar1, _initClass] } = _apply_decs_2203_r(Bar, [], [
dec1
])
};
Expand All @@ -15,13 +15,13 @@ var __1 = {
value: _initClass()
};
let _Foo;
class Foo extends _Bar {
class Foo extends (_Bar = _Bar1) {
}
var __2 = {
writable: true,
value: { c: [_Foo, _initClass1] } = _apply_decs_2203_r(Foo, [], [
dec2
])
], _Bar)
};
var __11 = {
writable: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
var _class, __, _class1, __1;
var _initClass, _initClass1;
var _initClass, _initClass1, _Foo;
const dec = ()=>{};
let _Foo;
let _Foo1;
new (_class = class extends _identity {
constructor(){
super(_Foo), _initClass();
super(_Foo1), _initClass();
}
}, __ = {
writable: true,
Expand All @@ -13,7 +13,7 @@ new (_class = class extends _identity {
}
var __ = {
writable: true,
value: { c: [_Foo, _initClass] } = _apply_decs_2203_r(Foo, [], [
value: { c: [_Foo1, _initClass] } = _apply_decs_2203_r(Foo, [], [
dec
])
};
Expand All @@ -28,13 +28,14 @@ new (_class1 = class extends _identity {
}, __1 = {
writable: true,
value: (()=>{
class Bar extends _Foo {
var _ref;
class Bar extends (_ref = _Foo = _Foo1) {
}
var __ = {
writable: true,
value: { c: [_Bar, _initClass1] } = _apply_decs_2203_r(Bar, [], [
dec
])
], _Foo)
};
_define_property(Bar, "field", ((()=>{
Bar.otherField = 456;
Expand Down
Loading
Loading