Skip to content

Commit 528d15a

Browse files
committed
port one more time
1 parent a876257 commit 528d15a

File tree

17 files changed

+471
-151
lines changed

17 files changed

+471
-151
lines changed

crates/swc_ecma_compiler/src/compat/es2022/class_properties/class.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl<'ctx> ClassProperties<'ctx> {
5555
is_abstract: bool,
5656
class_name: Option<&Ident>,
5757
_has_super_class: bool,
58-
body: &mut Vec<ClassMember>,
58+
body: &mut [ClassMember],
5959
ctx: &TransformCtx,
6060
) {
6161
// Ignore TS class declarations
@@ -251,7 +251,7 @@ impl<'ctx> ClassProperties<'ctx> {
251251
let name = class_name_binding
252252
.as_ref()
253253
.map_or("Class", |binding| binding.name.as_ref());
254-
let name = format!("_{}_brand", name);
254+
let name = format!("_{name}_brand");
255255
Some(self.generate_uid_in_current_scope(&name, ctx))
256256
} else {
257257
None
@@ -334,13 +334,11 @@ impl<'ctx> ClassProperties<'ctx> {
334334
// `self.remove_class_fields_without_initializer` are both true,
335335
// we don't need to convert properties without initializers, that means
336336
// `instance_prop_count != 0` but `instance_inits` may be empty.
337-
if instance_inits.is_empty() {
338-
return;
337+
if !instance_inits.is_empty() {
338+
// TODO: Insert instance initializers into constructor
339+
// This requires constructor transformation logic which is not yet
340+
// ported
339341
}
340-
341-
// TODO: Insert instance initializers into constructor
342-
// This requires constructor transformation logic which is not yet
343-
// ported
344342
}
345343

346344
/// Transform class declaration on exit.
@@ -629,7 +627,7 @@ impl<'ctx> ClassProperties<'ctx> {
629627
}
630628

631629
// Insert computed key initializers
632-
exprs.extend(self.insert_after_exprs.drain(..));
630+
exprs.append(&mut self.insert_after_exprs);
633631

634632
// Insert class + static property assignments + static blocks
635633
if let Some(binding) = &class_details.bindings.temp {
@@ -801,7 +799,7 @@ impl<'ctx> ClassProperties<'ctx> {
801799
// For now, use a simple implementation
802800
// TODO: Implement proper UID generation with scope tracking
803801
use swc_common::SyntaxContext;
804-
BoundIdentifier::new(format!("_{}", name).into(), SyntaxContext::empty())
802+
BoundIdentifier::new(format!("_{name}").into(), SyntaxContext::empty())
805803
}
806804

807805
/// Create temp binding for class.

crates/swc_ecma_compiler/src/compat/es2022/class_properties/class_bindings.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,9 @@ impl ClassBindings {
186186

187187
*uid_counter += 1;
188188
let name = if *uid_counter > 1 {
189-
Atom::from(format!("_{}{}", base_name, uid_counter))
189+
Atom::from(format!("_{base_name}{uid_counter}"))
190190
} else {
191-
Atom::from(format!("_{}", base_name))
191+
Atom::from(format!("_{base_name}"))
192192
};
193193

194194
BoundIdentifier::new(name, SyntaxContext::empty())
@@ -205,7 +205,7 @@ impl ClassBindings {
205205
pub fn create_brand_binding(uid_counter: &mut usize, _ctx: &TransformCtx) -> BoundIdentifier {
206206
*uid_counter += 1;
207207
let name = if *uid_counter > 1 {
208-
Atom::from(format!("_brand{}", uid_counter))
208+
Atom::from(format!("_brand{uid_counter}"))
209209
} else {
210210
"_brand".into()
211211
};

crates/swc_ecma_compiler/src/compat/es2022/class_properties/computed_key.rs

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,26 +42,24 @@ impl<'ctx> ClassProperties<'ctx> {
4242

4343
// Exit if evaluating key cannot have side effects.
4444
// This check also results in exit for non-computed keys.
45-
if !key_needs_temp_var(key_expr) {
46-
return;
47-
}
45+
if key_needs_temp_var(key_expr) {
46+
// TODO(improve-on-babel): It's unnecessary to create temp vars for
47+
// method keys unless:
48+
// 1. Properties also have computed keys.
49+
// 2. Some of those properties' computed keys have side effects and
50+
// require temp vars.
51+
// 3. At least one property satisfying the above is after this
52+
// method, or class contains a static block which is being
53+
// transformed (static blocks are always evaluated after computed
54+
// keys, regardless of order)
4855

49-
// TODO(improve-on-babel): It's unnecessary to create temp vars for
50-
// method keys unless:
51-
// 1. Properties also have computed keys.
52-
// 2. Some of those properties' computed keys have side effects and
53-
// require temp vars.
54-
// 3. At least one property satisfying the above is after this method,
55-
// or class contains a static block which is being transformed
56-
// (static blocks are always evaluated after computed keys,
57-
// regardless of order)
58-
59-
// TODO: Full implementation requires:
60-
// - Taking ownership of key expression
61-
// - Generating a unique temp var name
62-
// - Creating assignment expression
63-
// - Storing assignment in insert_before vector
64-
// - Replacing key with temp var identifier
56+
// TODO: Full implementation requires:
57+
// - Taking ownership of key expression
58+
// - Generating a unique temp var name
59+
// - Creating assignment expression
60+
// - Storing assignment in insert_before vector
61+
// - Replacing key with temp var identifier
62+
}
6563
}
6664

6765
/// Convert computed property/method key to a temp var, if a temp var is

crates/swc_ecma_compiler/src/compat/es2022/class_properties/constructor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ impl<'ctx> ClassProperties<'ctx> {
339339
) {
340340
// Add `"use strict"` directive
341341
// TODO: Check if outer scope is already strict mode
342-
let _directives = vec![Str {
342+
let _directives = [Str {
343343
span: DUMMY_SP,
344344
value: "use strict".into(),
345345
raw: None,

crates/swc_ecma_compiler/src/compat/es2022/class_properties/mod.rs

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -139,16 +139,70 @@ impl<'ctx> ClassProperties<'ctx> {
139139
}
140140

141141
impl VisitMutHook for ClassProperties<'_> {
142-
// This is a stub implementation.
143-
// The full implementation would include methods for:
144-
// - enter_program / exit_program
145-
// - enter_class / exit_class
146-
// - enter_class_members
147-
// - enter_property_definition / exit_property_definition
148-
// - enter_private_property / exit_private_property
149-
// - enter_private_method / exit_private_method
150-
// - enter_static_block / exit_static_block
151-
// - enter_expression / exit_expression
152-
// - enter_assign_expr
153-
// And many more...
142+
fn enter_class_decl(&mut self, node: &mut ClassDecl) {
143+
let class_name = &node.ident;
144+
let has_super_class = node.class.super_class.is_some();
145+
let is_abstract = node.class.is_abstract;
146+
147+
self.transform_class_body_on_entry(
148+
is_abstract,
149+
Some(class_name),
150+
has_super_class,
151+
&mut node.class.body,
152+
self.ctx,
153+
);
154+
}
155+
156+
fn exit_class_decl(&mut self, node: &mut ClassDecl) {
157+
let is_abstract = node.class.is_abstract;
158+
159+
self.transform_class_declaration_on_exit(
160+
is_abstract,
161+
&mut Some(node.ident.clone()),
162+
&mut node.class.body,
163+
self.ctx,
164+
);
165+
}
166+
167+
fn enter_class_expr(&mut self, node: &mut ClassExpr) {
168+
let class_name = node.ident.as_ref();
169+
let has_super_class = node.class.super_class.is_some();
170+
let is_abstract = node.class.is_abstract;
171+
172+
self.transform_class_body_on_entry(
173+
is_abstract,
174+
class_name,
175+
has_super_class,
176+
&mut node.class.body,
177+
self.ctx,
178+
);
179+
}
180+
181+
fn exit_class_expr(&mut self, node: &mut ClassExpr) {
182+
let is_abstract = node.class.is_abstract;
183+
184+
// Create a mutable Expr from the ClassExpr to pass to the transform
185+
let mut expr = Expr::Class(ClassExpr {
186+
class: Box::new(Class {
187+
span: node.class.span,
188+
ctxt: node.class.ctxt,
189+
decorators: std::mem::take(&mut node.class.decorators),
190+
body: std::mem::take(&mut node.class.body),
191+
super_class: node.class.super_class.take(),
192+
is_abstract: node.class.is_abstract,
193+
type_params: node.class.type_params.take(),
194+
super_type_params: node.class.super_type_params.take(),
195+
implements: std::mem::take(&mut node.class.implements),
196+
}),
197+
ident: node.ident.clone(),
198+
});
199+
200+
self.transform_class_expression_on_exit(&mut expr, is_abstract, self.ctx);
201+
202+
// Extract the transformed class back to the node
203+
if let Expr::Class(class_expr) = expr {
204+
node.ident = class_expr.ident;
205+
node.class = class_expr.class;
206+
}
207+
}
154208
}

crates/swc_ecma_compiler/src/compat/es2022/class_properties/private_field.rs

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ impl<'ctx> ClassProperties<'ctx> {
5656
#[allow(dead_code)]
5757
fn transform_private_field_expression_impl(
5858
&mut self,
59-
_object: Box<Expr>,
59+
_object: Expr,
6060
_field_name: &Atom,
6161
_is_assignment: bool,
6262
) -> Box<Expr> {
@@ -263,16 +263,16 @@ impl<'ctx> ClassProperties<'ctx> {
263263
///
264264
/// Returns 2 `Expr`s. The first must be inserted into output first.
265265
#[allow(dead_code)]
266-
pub(super) fn duplicate_object(&self, object: Box<Expr>) -> (Box<Expr>, Box<Expr>) {
266+
pub(super) fn duplicate_object(&self, object: Expr) -> (Box<Expr>, Box<Expr>) {
267267
// STUB: In SWC, we need different logic for duplicating expressions
268268
// For now, just clone the expression
269-
(object.clone(), object)
269+
(Box::new(object.clone()), Box::new(object))
270270
}
271271

272272
/// `_classPrivateFieldLooseBase(object, _prop)[_prop]`.
273273
#[allow(dead_code)]
274274
fn create_private_field_member_expr_loose(
275-
_object: Box<Expr>,
275+
_object: Expr,
276276
_prop_binding: &BoundIdentifier,
277277
) -> Box<Expr> {
278278
// STUB: Create loose mode member expression
@@ -281,7 +281,7 @@ impl<'ctx> ClassProperties<'ctx> {
281281

282282
/// `_classPrivateFieldGet2(_prop, object)`
283283
#[allow(dead_code)]
284-
fn create_private_field_get(&self, _prop_ident: Box<Expr>, _object: Box<Expr>) -> Box<Expr> {
284+
fn create_private_field_get(&self, _prop_ident: Expr, _object: Expr) -> Box<Expr> {
285285
// STUB: Create helper call for private field getter
286286
todo!("create_private_field_get not yet implemented")
287287
}
@@ -290,9 +290,9 @@ impl<'ctx> ClassProperties<'ctx> {
290290
#[allow(dead_code)]
291291
fn create_private_field_set(
292292
&self,
293-
_prop_ident: Box<Expr>,
294-
_object: Box<Expr>,
295-
_value: Box<Expr>,
293+
_prop_ident: Expr,
294+
_object: Expr,
295+
_value: Expr,
296296
) -> Box<Expr> {
297297
// STUB: Create helper call for private field setter
298298
todo!("create_private_field_set not yet implemented")
@@ -302,20 +302,16 @@ impl<'ctx> ClassProperties<'ctx> {
302302
#[allow(dead_code)]
303303
fn create_to_setter_for_private_field_set(
304304
&self,
305-
_prop_ident: Box<Expr>,
306-
_object: Box<Expr>,
305+
_prop_ident: Expr,
306+
_object: Expr,
307307
) -> Box<Expr> {
308308
// STUB: Create toSetter helper call
309309
todo!("create_to_setter_for_private_field_set not yet implemented")
310310
}
311311

312312
/// `_toSetter(_prop.bind(object))._`
313313
#[allow(dead_code)]
314-
fn create_to_setter_for_bind_call(
315-
&self,
316-
_prop_ident: Box<Expr>,
317-
_object: Box<Expr>,
318-
) -> Box<Expr> {
314+
fn create_to_setter_for_bind_call(&self, _prop_ident: Expr, _object: Expr) -> Box<Expr> {
319315
// STUB: Create toSetter with bind call
320316
todo!("create_to_setter_for_bind_call not yet implemented")
321317
}
@@ -325,9 +321,9 @@ impl<'ctx> ClassProperties<'ctx> {
325321
#[allow(dead_code)]
326322
fn create_assert_class_brand(
327323
&self,
328-
_class_ident: Box<Expr>,
329-
_object: Box<Expr>,
330-
_value_or_prop_ident: Box<Expr>,
324+
_class_ident: Expr,
325+
_object: Expr,
326+
_value_or_prop_ident: Expr,
331327
) -> Box<Expr> {
332328
// STUB: Create assertClassBrand helper call
333329
todo!("create_assert_class_brand not yet implemented")
@@ -337,8 +333,8 @@ impl<'ctx> ClassProperties<'ctx> {
337333
#[allow(dead_code)]
338334
fn create_assert_class_brand_without_value(
339335
&self,
340-
_class_ident: Box<Expr>,
341-
_object: Box<Expr>,
336+
_class_ident: Expr,
337+
_object: Expr,
342338
) -> Box<Expr> {
343339
// STUB: Create assertClassBrand without value
344340
todo!("create_assert_class_brand_without_value not yet implemented")
@@ -348,9 +344,9 @@ impl<'ctx> ClassProperties<'ctx> {
348344
#[allow(dead_code)]
349345
fn create_assert_class_brand_underscore(
350346
&self,
351-
_class_ident: Box<Expr>,
352-
_object: Box<Expr>,
353-
_prop_ident: Box<Expr>,
347+
_class_ident: Expr,
348+
_object: Expr,
349+
_prop_ident: Expr,
354350
) -> Box<Expr> {
355351
// STUB: Create assertClassBrand with underscore member
356352
todo!("create_assert_class_brand_underscore not yet implemented")
@@ -378,7 +374,7 @@ impl<'ctx> ClassProperties<'ctx> {
378374
_private_name: &str,
379375
_class_binding: Option<&BoundIdentifier>,
380376
_prop_binding: Option<&BoundIdentifier>,
381-
_object: Box<Expr>,
377+
_object: Expr,
382378
) -> Box<Expr> {
383379
// STUB: Create private getter
384380
todo!("create_private_getter not yet implemented")
@@ -393,8 +389,8 @@ impl<'ctx> ClassProperties<'ctx> {
393389
_private_name: &str,
394390
_class_binding: Option<&BoundIdentifier>,
395391
_prop_binding: Option<&BoundIdentifier>,
396-
_object: Box<Expr>,
397-
_value: Box<Expr>,
392+
_object: Expr,
393+
_value: Expr,
398394
) -> Box<Expr> {
399395
// STUB: Create private setter
400396
todo!("create_private_setter not yet implemented")
@@ -413,8 +409,8 @@ impl<'ctx> ClassProperties<'ctx> {
413409
fn create_sequence_with_read_only_error(
414410
&self,
415411
_private_name: &str,
416-
_object: Box<Expr>,
417-
_value: Option<Box<Expr>>,
412+
_object: Expr,
413+
_value: Option<Expr>,
418414
) -> Box<Expr> {
419415
// STUB: Create sequence expression with read-only error
420416
todo!("create_sequence_with_read_only_error not yet implemented")
@@ -425,15 +421,15 @@ impl<'ctx> ClassProperties<'ctx> {
425421
fn create_sequence_with_write_only_error(
426422
&self,
427423
_private_name: &str,
428-
_object: Box<Expr>,
424+
_object: Expr,
429425
) -> Box<Expr> {
430426
// STUB: Create sequence expression with write-only error
431427
todo!("create_sequence_with_write_only_error not yet implemented")
432428
}
433429

434430
/// _checkInRHS(object)
435431
#[allow(dead_code)]
436-
fn create_check_in_rhs(&self, _object: Box<Expr>) -> Box<Expr> {
432+
fn create_check_in_rhs(&self, _object: Expr) -> Box<Expr> {
437433
// STUB: Create checkInRHS helper call
438434
todo!("create_check_in_rhs not yet implemented")
439435
}

crates/swc_ecma_compiler/src/compat/es2022/class_properties/prop_decl.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ impl ClassProperties<'_> {
8383
) -> Expr {
8484
let private_props = self.current_class().private_props.as_ref().unwrap();
8585
let prop = &private_props[&ident.name];
86-
let _args = vec![
86+
let _args = [
8787
ExprOrSpread::from(Box::new(create_this_expr())),
8888
ExprOrSpread::from(Box::new(prop.binding.create_ident().into())),
8989
ExprOrSpread::from(Box::new(value)),
@@ -285,7 +285,7 @@ impl ClassProperties<'_> {
285285
prop: MemberProp::Ident(ident.clone()),
286286
}
287287
}
288-
PropName::Str(str_lit) if str_lit.value.as_str().map_or(false, |s| needs_define(s)) => {
288+
PropName::Str(str_lit) if str_lit.value.as_str().is_some_and(needs_define) => {
289289
return self
290290
.create_init_assignment_not_loose(prop, value, assignee, is_static, ctx);
291291
}
@@ -315,7 +315,7 @@ impl ClassProperties<'_> {
315315
Expr::Assign(AssignExpr {
316316
span: DUMMY_SP,
317317
op: AssignOp::Assign,
318-
left: AssignTarget::Simple(SimpleAssignTarget::Member(left.into())),
318+
left: AssignTarget::Simple(SimpleAssignTarget::Member(left)),
319319
right: Box::new(value),
320320
})
321321
}

0 commit comments

Comments
 (0)