feat(transformer/decorators): insert instanceBrand function (#2480)

This commit is contained in:
Dunqing 2024-02-23 23:04:27 +08:00 committed by GitHub
parent 7f867221ca
commit 3d008abacb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 122 additions and 16 deletions

View file

@ -611,6 +611,20 @@ impl<'a> AstBuilder<'a> {
}) })
} }
pub fn private_in_expression(
&self,
span: Span,
left: PrivateIdentifier,
right: Expression<'a>,
) -> Expression<'a> {
Expression::PrivateInExpression(self.alloc(PrivateInExpression {
span,
left,
operator: BinaryOperator::In,
right,
}))
}
pub fn private_field_expression( pub fn private_field_expression(
&self, &self,
span: Span, span: Span,

View file

@ -29,17 +29,30 @@ pub struct Decorators<'a> {
bitflags! { bitflags! {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct DecoratorFlags: u8 { pub struct DecoratorFlags: u8 {
const Field = 0; // flag is 0
const Accessor = 1; const Field = 1 << 0;
const Method = 2; // flag is 1
const Getter = 3; const Accessor = 1 << 1;
const Setter = 4; // flag is 2
const Static = 8; const Method = 1 << 2;
const DecoratorsHaveThis = 16; // flag is 3
const Getter = 1 << 3;
// flag is 4
const Setter = 1 << 4;
// flag is 8
const Static = 1 << 5;
// flag is 16
const DecoratorsHaveThis = 1 << 6;
} }
} }
impl DecoratorFlags { impl DecoratorFlags {
pub fn is_setter(self) -> bool {
self.contains(Self::Setter)
}
pub fn is_static(self) -> bool {
self.contains(Self::Static)
}
pub fn get_flag_by_kind(kind: MethodDefinitionKind) -> Self { pub fn get_flag_by_kind(kind: MethodDefinitionKind) -> Self {
match kind { match kind {
MethodDefinitionKind::Method => Self::Method, MethodDefinitionKind::Method => Self::Method,
@ -48,6 +61,28 @@ impl DecoratorFlags {
MethodDefinitionKind::Constructor => unreachable!(), MethodDefinitionKind::Constructor => unreachable!(),
} }
} }
pub fn to_value(self) -> u8 {
if self.contains(DecoratorFlags::DecoratorsHaveThis) {
return 16;
}
let mut value: u8 = 0;
if self.contains(DecoratorFlags::Accessor) {
value += 1;
}
if self.contains(DecoratorFlags::Method) {
value += 2;
}
if self.contains(DecoratorFlags::Getter) {
value += 3;
}
if self.contains(DecoratorFlags::Setter) {
value += 4;
}
if self.contains(DecoratorFlags::Static) {
value += 8;
}
value
}
} }
#[derive(Debug, Clone, Copy, Default, Deserialize)] #[derive(Debug, Clone, Copy, Default, Deserialize)]
@ -297,6 +332,8 @@ impl<'a> Decorators<'a> {
let mut c_elements = self.ast.new_vec(); let mut c_elements = self.ast.new_vec();
let mut e_elements = self.ast.new_vec(); let mut e_elements = self.ast.new_vec();
let mut private_in_expressions = self.ast.new_vec();
let mut init_static_name = None; let mut init_static_name = None;
// insert member decorators // insert member decorators
@ -393,9 +430,9 @@ impl<'a> Decorators<'a> {
} else { } else {
is_proto = true; is_proto = true;
} }
let mut flag = DecoratorFlags::get_flag_by_kind(def.kind).bits(); let mut flag = DecoratorFlags::get_flag_by_kind(def.kind);
if def.r#static { if def.r#static {
flag += DecoratorFlags::Static.bits(); flag |= DecoratorFlags::Static;
} }
def.decorators.iter().for_each(|decorator| { def.decorators.iter().for_each(|decorator| {
@ -412,6 +449,54 @@ impl<'a> Decorators<'a> {
def.decorators.clear(); def.decorators.clear();
if def.key.is_private_identifier() { if def.key.is_private_identifier() {
{
if flag.is_setter() && !flag.is_static() {
// _ => #a in _;
private_in_expressions.push(self.ast.arrow_expression(
SPAN,
true,
false,
self.ast.formal_parameters(
SPAN,
FormalParameterKind::ArrowFormalParameters,
self.ast.new_vec_single(self.ast.formal_parameter(
SPAN,
self.ast.binding_pattern(
self.ast.binding_pattern_identifier(
BindingIdentifier::new(SPAN, "_".into()),
),
None,
false,
),
None,
false,
self.ast.new_vec(),
)),
None,
),
self.ast.function_body(
SPAN,
self.ast.new_vec(),
self.ast.new_vec_single(self.ast.expression_statement(
SPAN,
self.ast.private_in_expression(
SPAN,
PrivateIdentifier::new(
SPAN,
def.key.private_name().unwrap(),
),
self.ast.identifier_reference_expression(
IdentifierReference::new(SPAN, "_".into()),
),
),
)),
),
None,
None,
));
}
}
name = self.get_unique_name(&if def.computed { name = self.get_unique_name(&if def.computed {
"init_computedKey".into() "init_computedKey".into()
} else { } else {
@ -496,7 +581,7 @@ impl<'a> Decorators<'a> {
def.decorators.iter().for_each(|decorator| { def.decorators.iter().for_each(|decorator| {
member_decorators_vec.push(ArrayExpressionElement::Expression( member_decorators_vec.push(ArrayExpressionElement::Expression(
self.get_decorator_info(&def.key, None, flag.bits(), decorator), self.get_decorator_info(&def.key, None, flag, decorator),
)); ));
}); });
def.decorators.clear(); def.decorators.clear();
@ -630,6 +715,15 @@ impl<'a> Decorators<'a> {
None, None,
))); )));
arguments.push(class_decorators_argument); arguments.push(class_decorators_argument);
if !private_in_expressions.is_empty() {
// classDecsHaveThis
arguments.push(Argument::Expression(self.ast.literal_number_expression(
// TODO: use correct number instead of `0`
self.ast.number_literal(SPAN, 0f64, "0", oxc_syntax::NumberBase::Decimal),
)));
// instanceBrand
arguments.extend(private_in_expressions.into_iter().map(Argument::Expression));
}
let mut call_expr = self.ast.call_expression(SPAN, callee, arguments, false, None); let mut call_expr = self.ast.call_expression(SPAN, callee, arguments, false, None);
@ -754,7 +848,7 @@ impl<'a> Decorators<'a> {
&self, &self,
key: &PropertyKey<'a>, key: &PropertyKey<'a>,
value: Option<Box<'a, Function<'a>>>, value: Option<Box<'a, Function<'a>>>,
flag: u8, flag: DecoratorFlags,
decorator: &Decorator<'a>, decorator: &Decorator<'a>,
) -> Expression<'a> { ) -> Expression<'a> {
let name = key.name(); let name = key.name();
@ -766,7 +860,7 @@ impl<'a> Decorators<'a> {
self.ast.literal_number_expression(NumericLiteral::new( self.ast.literal_number_expression(NumericLiteral::new(
SPAN, SPAN,
0f64, 0f64,
self.ast.new_str(flag.to_string().as_str()), self.ast.new_str(flag.to_value().to_string().as_str()),
oxc_syntax::NumberBase::Decimal, oxc_syntax::NumberBase::Decimal,
)), )),
)); ));

View file

@ -1,4 +1,4 @@
Passed: 344/1369 Passed: 346/1369
# All Passed: # All Passed:
* babel-plugin-transform-numeric-separator * babel-plugin-transform-numeric-separator
@ -911,7 +911,7 @@ Passed: 344/1369
* spread-transform/transform-to-babel-extend/input.js * spread-transform/transform-to-babel-extend/input.js
* spread-transform/transform-to-object-assign/input.js * spread-transform/transform-to-object-assign/input.js
# babel-plugin-proposal-decorators (20/190) # babel-plugin-proposal-decorators (22/190)
* 2018-09-transformation/async-generator-method/input.js * 2018-09-transformation/async-generator-method/input.js
* 2018-09-transformation/class-decorators-yield-await/input.js * 2018-09-transformation/class-decorators-yield-await/input.js
* 2021-12-accessors/context-name/input.js * 2021-12-accessors/context-name/input.js
@ -1033,7 +1033,6 @@ Passed: 344/1369
* 2023-05-getters--to-es2015/public/input.js * 2023-05-getters--to-es2015/public/input.js
* 2023-05-getters--to-es2015/static-private/input.js * 2023-05-getters--to-es2015/static-private/input.js
* 2023-05-getters--to-es2015/static-public/input.js * 2023-05-getters--to-es2015/static-public/input.js
* 2023-05-getters-and-setters/private/input.js
* 2023-05-getters-and-setters--to-es2015/private/input.js * 2023-05-getters-and-setters--to-es2015/private/input.js
* 2023-05-getters-and-setters--to-es2015/public/input.js * 2023-05-getters-and-setters--to-es2015/public/input.js
* 2023-05-getters-and-setters--to-es2015/static-private/input.js * 2023-05-getters-and-setters--to-es2015/static-private/input.js
@ -1071,7 +1070,6 @@ Passed: 344/1369
* 2023-05-ordering/initializers-and-static-blocks/input.js * 2023-05-ordering/initializers-and-static-blocks/input.js
* 2023-05-ordering--to-es2015/initializers-and-static-blocks/input.js * 2023-05-ordering--to-es2015/initializers-and-static-blocks/input.js
* 2023-05-setters/context-name/input.js * 2023-05-setters/context-name/input.js
* 2023-05-setters/private/input.js
* 2023-05-setters--to-es2015/context-name/input.js * 2023-05-setters--to-es2015/context-name/input.js
* 2023-05-setters--to-es2015/private/input.js * 2023-05-setters--to-es2015/private/input.js
* 2023-05-setters--to-es2015/public/input.js * 2023-05-setters--to-es2015/public/input.js