From 06b6eb999964c25a964b0105bd7a4f20b51300dd Mon Sep 17 00:00:00 2001 From: Austaras Date: Sat, 30 Sep 2023 05:32:48 +0800 Subject: [PATCH] fix(es/compat): Generate `OptCall` for `OptCall` for private fields (#8031) **Related issue:** - Closes #8003 --- ...privateNameFieldCallExpression.1.normal.js | 2 +- ...eNameStaticFieldCallExpression.1.normal.js | 2 +- crates/swc_ecma_transforms_base/src/fixer.rs | 16 ++++---- .../es2022/class_properties/private_field.rs | 31 +++++++++------ .../tests/es2022_class_properties.rs | 39 +++++++++++++++++++ 5 files changed, 69 insertions(+), 21 deletions(-) diff --git a/crates/swc/tests/tsc-references/privateNameFieldCallExpression.1.normal.js b/crates/swc/tests/tsc-references/privateNameFieldCallExpression.1.normal.js index c26a155eda53..7c272bb63a77 100644 --- a/crates/swc/tests/tsc-references/privateNameFieldCallExpression.1.normal.js +++ b/crates/swc/tests/tsc-references/privateNameFieldCallExpression.1.normal.js @@ -8,7 +8,7 @@ class A { var _class_private_field_get1; var _this_getInstance; _class_private_field_get(this, _fieldFunc).call(this); - ((_class_private_field_get1 = _class_private_field_get(this, _fieldFunc)) === null || _class_private_field_get1 === void 0 ? void 0 : _class_private_field_get1.call)(this); + (_class_private_field_get1 = _class_private_field_get(this, _fieldFunc)) === null || _class_private_field_get1 === void 0 ? void 0 : _class_private_field_get1.call(this); const func = _class_private_field_get(this, _fieldFunc); func(); new (_class_private_field_get(this, _fieldFunc))(); diff --git a/crates/swc/tests/tsc-references/privateNameStaticFieldCallExpression.1.normal.js b/crates/swc/tests/tsc-references/privateNameStaticFieldCallExpression.1.normal.js index 6e8d7f4acbc7..11b16b455782 100644 --- a/crates/swc/tests/tsc-references/privateNameStaticFieldCallExpression.1.normal.js +++ b/crates/swc/tests/tsc-references/privateNameStaticFieldCallExpression.1.normal.js @@ -4,7 +4,7 @@ class A { test() { var _class_static_private_field_spec_get1; _class_static_private_field_spec_get(A, A, _fieldFunc).call(A); - ((_class_static_private_field_spec_get1 = _class_static_private_field_spec_get(A, A, _fieldFunc)) === null || _class_static_private_field_spec_get1 === void 0 ? void 0 : _class_static_private_field_spec_get1.call)(A); + (_class_static_private_field_spec_get1 = _class_static_private_field_spec_get(A, A, _fieldFunc)) === null || _class_static_private_field_spec_get1 === void 0 ? void 0 : _class_static_private_field_spec_get1.call(A); const func = _class_static_private_field_spec_get(A, A, _fieldFunc); func(); new (_class_static_private_field_spec_get(A, A, _fieldFunc))(); diff --git a/crates/swc_ecma_transforms_base/src/fixer.rs b/crates/swc_ecma_transforms_base/src/fixer.rs index c585c111628a..62b296687cad 100644 --- a/crates/swc_ecma_transforms_base/src/fixer.rs +++ b/crates/swc_ecma_transforms_base/src/fixer.rs @@ -101,18 +101,16 @@ impl Fixer<'_> { } fn wrap_callee(&mut self, e: &mut Expr) { - if match e { - Expr::Lit(Lit::Num(..) | Lit::Str(..)) => false, + match e { + Expr::Lit(Lit::Num(..) | Lit::Str(..)) => (), Expr::Cond(..) | Expr::Bin(..) | Expr::Lit(..) | Expr::Unary(..) | Expr::Object(..) | Expr::Await(..) - | Expr::Yield(..) => true, - _ => false, - } { - self.wrap(e) + | Expr::Yield(..) => self.wrap(e), + _ => (), } } } @@ -400,7 +398,11 @@ impl VisitMut for Fixer<'_> { fn visit_mut_call_expr(&mut self, node: &mut CallExpr) { let old = self.visit_call(&mut node.args, &mut node.callee); if let Callee::Expr(e) = &mut node.callee { - self.wrap_callee(e) + if let Expr::OptChain(_) = &**e { + self.wrap(e) + } else { + self.wrap_callee(e) + } } self.ctx = old; diff --git a/crates/swc_ecma_transforms_compat/src/es2022/class_properties/private_field.rs b/crates/swc_ecma_transforms_compat/src/es2022/class_properties/private_field.rs index 57138f474f79..a25c2c57a883 100644 --- a/crates/swc_ecma_transforms_compat/src/es2022/class_properties/private_field.rs +++ b/crates/swc_ecma_transforms_compat/src/es2022/class_properties/private_field.rs @@ -455,21 +455,28 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> { let (expr, this) = self.visit_mut_private_get(&mut callee, None); if let Some(this) = this { let args = iter::once(this.as_arg()).chain(call.args.take()).collect(); - *e = Expr::Call(CallExpr { + let call = OptCall { span: *span, - callee: OptChainExpr { - span: *span, - optional: *optional, - base: Box::new(OptChainBase::Member(MemberExpr { - span: call.span, - obj: Box::new(expr), - prop: MemberProp::Ident(quote_ident!("call")), - })), - } - .as_callee(), + callee: Box::new( + OptChainExpr { + span: *span, + optional: *optional, + base: Box::new(OptChainBase::Member(MemberExpr { + span: call.span, + obj: Box::new(expr), + prop: MemberProp::Ident(quote_ident!("call")), + })), + } + .into(), + ), args, type_args: call.type_args.take(), - }); + }; + *e = Expr::OptChain(OptChainExpr { + span: *span, + optional: false, + base: Box::new(OptChainBase::Call(call)), + }) } else { call.callee = Box::new(expr); } diff --git a/crates/swc_ecma_transforms_compat/tests/es2022_class_properties.rs b/crates/swc_ecma_transforms_compat/tests/es2022_class_properties.rs index 34f3840443d0..0d8abadc1499 100644 --- a/crates/swc_ecma_transforms_compat/tests/es2022_class_properties.rs +++ b/crates/swc_ecma_transforms_compat/tests/es2022_class_properties.rs @@ -9,6 +9,7 @@ use swc_ecma_transforms_compat::{ es2015::{arrow, block_scoping, classes, function_name, template_literal}, es2016::exponentiation, es2017::async_to_generator, + es2020::optional_chaining, es2022::class_properties, es3::reserved_words, }; @@ -6669,3 +6670,41 @@ var _x = { }; "# ); + +test!( + syntax(), + |t| { + let unresolved = Mark::new(); + chain!( + class_properties(Some(t.comments.clone()), Default::default()), + optional_chaining(Default::default(), unresolved) + ) + }, + issue_8003, + " +class Foo { + #priv + search() { + this.#priv?.() + } +} + +console.log(new Foo().search())", + r#" +var _priv = new WeakMap(); +class Foo { + search() { + var _class_private_field_get1; + (_class_private_field_get1 = _class_private_field_get(this, _priv)) === null || _class_private_field_get1 === void 0 ? void 0 : _class_private_field_get1.call(this); + } + constructor(){ + _class_private_field_init(this, _priv, { + writable: true, + value: void 0 + }); + } +} + +console.log(new Foo().search()); +"# +);