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(
&self,
span: Span,

View file

@ -29,17 +29,30 @@ pub struct Decorators<'a> {
bitflags! {
#[derive(Debug, Clone, Copy)]
pub struct DecoratorFlags: u8 {
const Field = 0;
const Accessor = 1;
const Method = 2;
const Getter = 3;
const Setter = 4;
const Static = 8;
const DecoratorsHaveThis = 16;
// flag is 0
const Field = 1 << 0;
// flag is 1
const Accessor = 1 << 1;
// flag is 2
const Method = 1 << 2;
// 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 {
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 {
match kind {
MethodDefinitionKind::Method => Self::Method,
@ -48,6 +61,28 @@ impl DecoratorFlags {
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)]
@ -297,6 +332,8 @@ impl<'a> Decorators<'a> {
let mut c_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;
// insert member decorators
@ -393,9 +430,9 @@ impl<'a> Decorators<'a> {
} else {
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 {
flag += DecoratorFlags::Static.bits();
flag |= DecoratorFlags::Static;
}
def.decorators.iter().for_each(|decorator| {
@ -412,6 +449,54 @@ impl<'a> Decorators<'a> {
def.decorators.clear();
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 {
"init_computedKey".into()
} else {
@ -496,7 +581,7 @@ impl<'a> Decorators<'a> {
def.decorators.iter().for_each(|decorator| {
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();
@ -630,6 +715,15 @@ impl<'a> Decorators<'a> {
None,
)));
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);
@ -754,7 +848,7 @@ impl<'a> Decorators<'a> {
&self,
key: &PropertyKey<'a>,
value: Option<Box<'a, Function<'a>>>,
flag: u8,
flag: DecoratorFlags,
decorator: &Decorator<'a>,
) -> Expression<'a> {
let name = key.name();
@ -766,7 +860,7 @@ impl<'a> Decorators<'a> {
self.ast.literal_number_expression(NumericLiteral::new(
SPAN,
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,
)),
));

View file

@ -1,4 +1,4 @@
Passed: 344/1369
Passed: 346/1369
# All Passed:
* babel-plugin-transform-numeric-separator
@ -911,7 +911,7 @@ Passed: 344/1369
* spread-transform/transform-to-babel-extend/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/class-decorators-yield-await/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/static-private/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/public/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--to-es2015/initializers-and-static-blocks/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/private/input.js
* 2023-05-setters--to-es2015/public/input.js